Тъй като офанзивните набори от инструменти продължават да се движат към използването на C# като предпочитан език за последваща експлоатация, реших, че би било полезно да помисля за някои от оперативните предизвикателства, свързани с използването на C# обидно, особено като в сравнение с PowerShell. PowerShell има много оперативни и удобни предимства за офанзивните оператори, които губим, когато преминаваме към C#. Въпреки това, стелтът почти винаги трябва да има предимство пред удобството по време на операции на червения екип. Като се има предвид това, ние винаги искаме нашият набор от инструменти да бъде възможно най-гъвкав и удобен, като същевременно остава под летвата за откриване.

В тази публикация ще се опитам да документирам някои оперативни предизвикателства при използването на C# и ще предложа решения за справяне с тези предизвикателства. Примерите в тази публикация ще използват SharpSploit, .NET библиотека след експлоатация, която наскоро разработих (и представих в моята последна публикация). Моята цел обаче е да документирам по начин, който е приложим за всяка C# библиотека или проект.

Освен това ще представя SharpGen, нов проект, който създадох за борба с някои от тези оперативни предизвикателства.

Оперативно предизвикателство — Изпълнение

Когато пуснах SharpSploit, взех решение да публикувам като библиотека, за разлика от самостоятелен изпълним файл. Направих това с известно колебание, тъй като знаех, че може да причини някои оперативни проблеми, но докато продължавам да се развивам върху набори от инструменти на C#, съм убеден, че това е правилното решение. Форматирането на набори от инструменти като библиотеки им позволява да се използват заедно и помага да се възвърне част от гъвкавостта, загубена при прехода от PowerShell.

Публикуването като библиотека обаче добавя и оперативно предизвикателство, с което няма да се налага да се справяте за повечето други набори от инструменти на C#, как всъщност да използвам този DLL? Вариантите са няколко! И както обещах в предишния ми пост, ще документирам няколко опции тук.

Конзолно приложение

Най-лесният и очевиден метод за извикване на методи на SharpSploit е да се създаде ново конзолно приложение, да се добави препратка към компилираното SharpSploit.dll, да се напише персонализиран код, който използва SharpSploit, и да се компилира. Това ще доведе до компилиран .exe файл, който трябва да можете да изпълните от командния ред. Въпреки това, важно предупреждение с този подход е, че полученото .exe очаква SharpSploit.dll да присъства в целевата система.

Препратките към DLL се използват по време на компилация за вграждане на метаданни за .dll в .exe, така че .exe да може да търси DLL в системата по време на изпълнение. Този подход ще бъде успешен, ако планирате да копирате .exe и SharpSploit.dll на диска на целевата система, но няма да бъде успешен чрез метод като командата execute-assembly на Cobalt Strike, която не записва .exe или неговите препратки към диск на целева система.

И така, как можем да се борим с тази главоблъсканица с липсващата DLL? Документирам четири метода по-долу: ILMerge, Costura, Reflection и DotNetToJScript.

ILMerge

ILMerge е статичен линкер с отворен код за .NET сборки. Както подсказва името, той обединява множество .NET сглобки в една изходна сглобка. За да направи това, ILMerge всъщност модифицира обединените сглобки, като премахва метаданните на обединените сглобки и създава изцяло нова сглобка със свои собствени метаданни и идентичност. Ако първият сбор в списъка, предоставен на ILMerge, съдържа EntryPoint, EntryPoint се приема като EntryPoint на обединения сбор. „EntryPoint“ е това, което прави конзолното приложение конзолно приложение, а не просто библиотека. EntryPoint често е „главната“ функция, с която може да сте запознати.

Ще разгледам бърз пример за това как да използвате ILMerge. Първо, ще създадете ново конзолно приложение, което препраща към SharpSploit, и ще напишете вашия персонализиран код, който го използва:

Ще създадете това приложение, което води до .exe, SharpSploitDriver.exe в този случай и SharpSploit.dll. Сега можем да използваме ILMerge, за да обединим тези две сглобки в SharpSploit.exe. В този случай ILMerge.exe вече е на моя Път. Също така ще трябва да се уверите, че сте изтрили всички генерирани .pdb файлове преди сливането.

Този генериран SharpSploit.exe е самостоятелен изпълним файл, който няма да очаква SharpSploit.dll в целевата система. ILMerge може също да бъде автоматизиран като част от процеса на изграждане с известна конфигурация. Ако изберете да следвате този път, ILMerge документира как да направите това в README.

Има и някои интересни криминалистични последици от това сливане. Ако отворим SharpSploit.exe в DNSpy:

Виждаме, че SharpSploit всъщност не е включено като препратка, но пространствата от имена на SharpSploit са вградени като модули в сборката SharpSploit.exe. Можем да сравним това с SharpSploitDriver.exe в DNSpy:

В този случай SharpSploit е включен като справка, но не и като модул. Не съм сигурен, че едното или другото е криминалистично „по-скрито“, въпреки че препратките могат да доведат до събития „ImageLoad“ (да използваме номенклатурата на Sysmon), които могат да бъдат открити. Така или иначе, мисля, че е важно да сме наясно с потенциалните криминалистични артефакти.

За да бъде ясно, този процес е повече от просто обединяване на файлове заедно, но всъщност обединяване на сглобки. Този процес е частично разрушителен и може да окаже влияние върху начина, по който се изпълнява приложението. Например, ако функционалността зависи от името на сборката:

Костура

Costura е друг проект с отворен код с цел, подобна на ILMerge. Използваният метод обаче е малко по-различен. Costura добавя препратки към DLL като „вградени ресурси“ към конзолното приложение. Вградените ресурси обикновено се използват за различни файлове, необходими на дадено приложение, като изображения, видеоклипове или други файлове.

Costura вгражда референтни DLL файлове като вградени ресурси и добавя обратно извикване към събитието AssemblyResolve на AppDomain, което се опитва да зареди асембли от вградените ресурси на приложението! Това се отразява на начина, по който системата ще разреши натоварванията на сглобки за приложението и ни позволява да зареждаме сглобки от произволни местоположения, като например вградените ресурси на приложението.

Този трик произлиза от публикация в блог от 2010 г. на Джефри Рихтер, в която той демонстрира процеса за регистриране на обратно извикване за събитието AssemblyResolve.

Ще разгледам бърз пример за това как да използвате Costura. Ще започнете точно както миналия път, като създадете конзолно приложение, добавите препратка към SharpSploit.dll и напишете всеки персонализиран C# код, който използва SharpSploit. Ще трябва също да добавите препратка към Costura.Fody. Това може да се инсталира като пакет Nuget, като щракнете с десния бутон върху References и изберете Manage Nuget Packages:

Нещо, което трябва да имате предвид при Costura, е, че най-новите версии са отхвърлили поддръжката за .NET Framework v3.5. За офанзивни операции обикновено искате да работите с .NET Framework v3.5. Не забравяйте да инсталирате Costura v1.6.2, за да работите с модули на .NET Framework v3.5. След като инсталирате ILMerge, ще видите, че е създаден файл FodyWeavers.xml. Това е конфигурацията на Costura, която по подразбиране ще вгради всички референтни сборки като ресурси. Сега, когато прекомпилираме, това води до самостоятелен изпълним файл SharpSploitDriver.exe:

Има и някои интересни криминалистични последици от генерираните от Костура двоични файлове. Когато отваряте SharpSploitDriver.exe в DNSpy:

Ще видите, че не само SharpSploitDriver.exe ще запази своята препратка към SharpSploit, но също така включва: препратка към Costura, няколко вградени препратки: costura.sharpsploit.dll.compressed, costura.sharpsploit.pdb и costura.system.management.automation.dll, както и Costura модул.

И така, как се сравняват ILMerge и Costura? Е, ще намерите интересен коментар върху споменатата по-горе публикация в блога от автора на ILMerge:

Въпреки този коментар, мисля, че има случаи на употреба и за двете решения. Всъщност, поради скрити и криминалистични причини, вероятно бих препоръчал ILMerge вместо Costura, освен ако ILMerge не повлияе на това как се изпълнява конкретното ви приложение. Конкретно за SharpSploit не съм забелязал никакви проблеми при използването на ILMerge.

Отражение

Отражението може да се използва за изпълнение на .NET сборки, които не съдържат EntryPoint (т.е. DLL). Пространството от имена System.Reflection може да се използва за зареждане на .NET сборки, извикване на методи и много други. Така че можем да използваме .NET отражение, за да заредим асемблирането на SharpSploit и да извикаме методи.

Един метод за използване на отражение е използването на PowerShell. Например, можем да извикаме методи на SharpSploit като този:

Или бихме могли да го заредим от хоствано местоположение и след това да заредим асемблирането и да извикаме методите, като използваме отражение:

И разбира се, всичко, което можем да направим от PowerShell, можем да направим от C#:

За този пример ще искате да запомните да компилирате като конзолно приложение. Въпреки това, няма да е необходимо да се притеснявате за добавяне на препратки, тъй като SharpSploit се зарежда чрез отражение, а не чрез типичния процес на разрешаване на асемблиране. Въпреки че си струва да се отбележи, че техниката „AssemblyResolve“ на Костура самата използва отражение, като използва метода System.Reflection.Assembly.Load().

Reflection е интересен вектор за изпълнение и може да служи като полезна „поставка за изтегляне“, за да спестите размер на изпълнимия файл и да избегнете усложненията с референтните файлове. За повече информация относно размисъла бих препоръчал да разгледате документацията на Microsoft.

DotNetToJScript

DotNetToJScript е инструмент с отворен код, написан от James Forshaw, който създава JScript или VBScript файлове, които зареждат дадена .NET сборка. Има обаче няколко ограничаващи фактора, които правят тази опция по-малко практична за използване с SharpSploit. Все още е възможно, но ще изисква известна персонализация!

Първото нещо, което ще забележите е, че DotNetToJScript не работи добре с големи сборки и по подразбиране SharpSploit е голяма сборка:

Вградените двоични файлове на Mimikatz причиняват големи размери на SharpSploit. За щастие е лесно да изберете да не вграждате двоичните файлове по време на компилиране, ако не ви трябват. Просто коментирайте няколко реда във файла SharpSploit.csproj, така:

След като направите тази промяна, просто ще трябва да прекомпилирате SharpSploit и да копирате новия SharpSploit.dll в папката DotNetToJScript.

Следващото нещо, което ще откриете е, че DotNetToJScript не работи добре с static класове или методи:

Повечето от полезните методи на SharpSploit са статични, включително ShellExecute. За да използвате този метод с DotNetToJScript, ще трябва да редактирате метода в SharpSploit, като премахнете класификатора static на метода ShellExecute, прекомпилирате и копирате новия SharpSploit.dll в папката DotNetToJScript. И накрая трябва да успее:

Този метод е интересен за еднократни изпълнения или стартиране на агент, но изисква да пуснем JScript или VBScript файл на диска на целевата система, което е ненужно, ако вече имате агент в системата.

Сравнение

Досега съм документирал четири потенциални опции за създаване на самостоятелен изпълним файл и/или скрипт, който може да извиква методи на SharpSploit: Costura, ILMerge, Reflection и JScript/VBScript чрез DotNetToJScript. Нека бързо да сравним и противопоставим тези методи и кога могат да бъдат полезни:

  • DotNetToJScript — Методът JScript/VBScript е най-полезен при сценарии за стартиране на агент, което със сигурност не е целта на SharpSploit. Представям си, че SharpSploit се използва почти изцяло в ситуации, в които вече имаме агент в система. В този случай не искаме да изпускаме JScript или VBScript файлове на диска, така че засега ще игнорираме този метод. Исках обаче да документирам този вектор за тези, които се интересуват от сценарии за стартиране на агенти.
  • Отражение — Методът на отражение е интересен и е най-полезен при стартиране на агент или сценарии „Разрешаване на събрание“ (т.е. Costura). Използването на базирана на отражение .NET поставка за изтегляне е добър вектор за стартиране на стартирането на агент. Със сигурност бихме могли да продължим да използваме тези поставки за изтегляне, за да изпълним всеки модул след експлоатация, който желаем, но това също така създава допълнителен, нежелан мрежов трафик, който бихме могли да избегнем.
  • Costura/ILMerge — Последните два метода и според мен най-полезните от гледна точка на работа са Costura и ILMerge. Тези методи създават самостоятелни изпълними файлове, които могат да се използват с командата execute-assembly на Cobalt Strike и подобни методи. Вече сравних и противопоставих тези методи по-рано и заключението беше, че ILMerge е обикновено, но не винаги, правилната опция.

Истинският недостатък на методите Costura/ILMerge, поне както е описано досега, е удобството. Не само трябва да компилирате библиотеката SharpSploit, но също така трябва да създадете допълнително конзолно приложение, което препраща към библиотеката, да внедрите ILMerge или Costura конфигурации и да компилирате.

Първоначално това не изглежда като твърде много допълнителна работа, която да поискате. Въпреки това ще трябва да правите всичко това всеки път, когато искате да извикате който и да е метод на SharpSploit. Като оператор вие наистина искате да можете бързо да извиквате последователни методи на SharpSploit и това е истинска пречка за оперативната ефективност на проекта.

И така, как можем да разрешим оперативното предизвикателство на удобството?

Оперативно предизвикателство — Удобство

След пускането на SharpSploit преди малко повече от месец, два проекта с отворен код вече се опитаха да се преборят с оперативното предизвикателство на удобството. „SharpSploitConsole“ и „SharpAttack“ се стремят да решат този проблем по сходни, но различни начини. И двете служат като единствено конзолно приложение, което може да взаимодейства с много различни методи, включени в SharpSploit. SharpSploitConsole използва Costura, докато SharpAttack използва ILMerge.

И двете приложения приемат аргументи като параметри на командния ред, които указват методите и параметрите на SharpSploit, които да бъдат изпълнени. Тези проекти ни позволяват да компилираме конзолно приложение само веднъж и да имаме достъп до по-голямата част от функционалността на SharpSploit, без да се налага постоянно да прекомпилираме нови конзолни приложения. Това е огромна печалба за удобство, но мисля, че има недостатък в гъвкавостта с тези подходи.

Например, да приемем, че искате да използвате SharpSploit, за да изброите всички компютри в домейна и да намерите локалните администратори за тези компютри. В персонализирано конзолно приложение с SharpSploit бихте направили нещо подобно:

С SharpSploitConsole или SharpAttack вероятно ще трябва да изпълните GetDomainComputers(), да анализирате резултатите като текст и да изпълните GetNetLocalGroupMembers() на всяко от имената на компютъра.

Или да кажем, че искаме да изпълним някакъв персонализиран C# код като алтернативен потребител в стил runas.exe. В персонализирано конзолно приложение с SharpSploit бихте направили нещо подобно:

С SharpSploitConsole или SharpAttack не съм сигурен, че това би било възможно, тъй като персонализираният C# код трябва да бъде компилиран и зареден като сборка.

Допълнително предупреждение с тези подходи, което всъщност е грешка на самия SharpSploit, е, че те не работят извън кутията с execute-assembly на Cobalt Strike. Трябва да премахнете вградените бинарни файлове на Mimikatz PE, преди да използвате с execute-assembly, тъй като Cobalt Strike има горна граница на размера от 1 MB за сборки. Истински неприятно е да не можете да използвате Mimikatz от SharpSploit над Cobalt Strike. За щастие направих някои промени в SharpSploit v1.1, които ще позволят това да се случи, което ще обсъдим по-късно в публикацията.

С тези подходи ние печелим удобство с цената на загубата на мощност от използването на SharpSploit като библиотека по персонализирани начини. Ние представяме оперативното предизвикателство на гъвкавостта.

Оперативно предизвикателство — Гъвкавост

Има ключови оперативни разлики при използването на компилиран език като C# за разлика от интерпретиран език като PowerShell. Губим доста гъвкавост при тази промяна. Със скриптовия език можем бързо да редактираме скриптове в движение, без да се притесняваме за допълнителната стъпка на компилиране. Без PowerShell губим мощността на тръбопровода и способността да комбинираме набори от инструменти или бързо да филтрираме или форматираме изход с вградени командлети, като Select-Object или Format-List.

С C# няма собствен начин за изпращане на изхода на един инструмент през тръбопровода като вход към друг инструмент. Няма естествен начин да направите малка редакция на компилиран изпълним файл. За да помогна да върна малко от тази гъвкавост, написах инструмент, наречен SharpGen, който е описан в останалата част от публикацията.

SharpGen

За да се опитам да се справя с оперативното предизвикателство на гъвкавостта, създадох конзолно приложение .NET Core, наречено SharpGen. SharpGen използва C# компилатора Roslyn за бързо кръстосано компилиране на конзолни приложения или библиотеки на .NET Framework. .NET Core позволява на SharpGen да бъде междуплатформен, позволявайки на операторите да използват SharpGen от каквато операционна система предпочитат.

Не забравяйте, че предизвикателството на удобството беше причинено от необходимостта постоянно да създавате нови конзолни приложения във Visual Studio, да добавяте препратки, да вграждате препратките с помощта на Costura или ILMerge и т.н. SharpGen решава това предизвикателство, като създава толкова бързо, колкото една единствена команда конзолно приложение и идва с някои допълнителни предимства.

Основна употреба

Най-основното използване на SharpGen би било да предоставите на SharpGen име на изходен файл и едноредов C#, който искате да изпълните. SharpGen ще генерира конзолно приложение .NET Framework, което ще изпълни едноредовия. Например:

Този пример генерира example.exe, конзолно приложение на .NET Framework, което изпълнява модула Mimikatz sekurlsa::logonpasswords и записва изхода на екрана.

Едноредовият C# винаги трябва да се посочва като последен, неназован аргумент на командния ред, когато се използва SharpGen. Въпреки това можете алтернативно да посочите изходен файл, от който да четете. Може да ви е необходима някаква логика, която не се вписва добре в един ред, или може би имате проблеми с избягването на кавички в командния ред. SharpGen поддържа четене от файл с аргумента на командния ред --source-file.

Или можете да посочите изходен файл с предварително дефиниран клас, допълнен с основна функция:

Това са самите основи на инструмента. Пълната информация за използването на командния ред е включена по-долу:

Ще се потопим в някои подробности за това как SharpGen работи под капака и допълнителни употреби в следващите раздели.

Междинно използване

За да разберете как работи SharpGen, нека хвърлим бърз поглед върху структурата на директорията на проекта:

Ще искате да обърнете особено внимание на директориите Source, References и Resources, тъй като те управляват основната функционалност на SharpGen. Целият изходен код, поставен в папката Source, ще бъде компилиран като изходен код в един сборник. Тъй като е компилиран като източник, няма нужда да се притеснявате за комбинирането на сборки или вграждането им като ресурси. По подразбиране изходният код на SharpSploit е включен в директорията Source за лесно компилиране срещу SharpSploit. Въпреки това, SharpGen е изграден по такъв начин, че всички изходни библиотеки да могат да бъдат пуснати в тази папка и включени.

Например, можем да пуснем изходния код на GhostPack SharpWMI в папката Source (с няколко незначителни модификации) и да компилираме спрямо него:

Това ни позволява да извикаме SharpWMI и SharpSploit методи от една сглобка! Възможността за добавяне на други библиотеки и бързо компилиране срещу комбинация от библиотеки може да е любимата ми функция на SharpGen. Трябваше да направя няколко малки модификации на SharpWMI, за да позволя това да работи. Бих искал да видя нови обидни набори от инструменти за C#, форматирани като библиотеки, за да позволят този вид комбинация от инструменти по подразбиране, без персонализации.

Препратките към сглобяване могат да бъдат конфигурирани в директорията References. Препратките могат да се прилагат към модули net35 или net40, като се поставят в съответната директория и се конфигурират в конфигурационния файл references.yml. Тази references.yml конфигурация идва със здрави настройки по подразбиране, но може да искате някои персонализации. Например, ако добавите допълнителен изходен код, който очаква допълнителна препратка, ще трябва да добавите тази препратка в конфигурацията.

Или да речем, че знаете, че няма да имате нужда от конкретна препратка. Например, знаете, че няма да е необходимо да изпълнявате PowerShell и крайната точка, на която се намирате, ще открие събитие System.Management.Automation.dll ImageLoad. SharpSploit включва препратка към System.Management.Automation.dll по подразбиране, но може да бъде премахната, ако не планирате да използвате метода SharpSploit.Execution.Shell.PowerShellExecute(). В този сценарий можете просто да деактивирате препратката System.Management.Automation.dll в конфигурацията references.yml, като зададете Enabled: false:

Не забравяйте също така да деактивирате препратката Net40, ако планирате да се насочите към .NET framework v4.0!

Ако планирате да използвате SharpGen за създаване на сборки за използване с командата execute-assembly на Cobalt Strike (за която е специално проектирана), трябва да обърнете внимание на директорията Resources. Основният ограничаващ фактор на командата execute-assembly е горната граница на размера от 1 MB. SharpSploit вгражда както x86, така и x64 Mimikatz двоични файлове по подразбиране, което го избутва над ограничението от 1MB. Имате няколко възможности за борба с този ограничаващ фактор:

  1. Ако не планирате да използвате никакви методи на Mimikatz, можете безопасно да деактивирате вградените ресурси на Mimikatz в конфигурационния файл resources.yml, което драстично ще намали вашия двоичен размер. За да направите това, просто превключете конфигурацията на ресурса на Enabled: false:

2. Ако планирате да използвате методите use Mimikatz, наистина ли имате нужда от x86 и x64 копие на Mimikatz? Ако не, можем да вградим само ресурса на платформата, от която се нуждаем. Има два начина да направите това:

2а. Можете да филтрирате ресурси въз основа на платформа чрез аргументи на командния ред. Това трябва да ви сведе малко под ограничението от 1MB:

2б. Можете също така просто да деактивирате ненужния ресурс в конфигурационния файл resources.yml, както направихме по-рано:

3. За допълнително намаляване на двоичния размер можете да вградите компресирани ресурси на Mimikatz вместо ресурсите по подразбиране, които се поддържат и управляват от SharpSploit. Те се компресират с помощта на вградената библиотека System.IO.Compression. Това компресиране не е достатъчно ефективно, за да ви позволи да вградите както x64, така и x86 ресурсите и да останете под ограничението от 1MB, но все пак значително намалява двоичния размер. Това може да се направи с помощта на конфигурационния файл resources.yml чрез активиране на компресирани ресурси и деактивиране на некомпресирани ресурси:

4. По-надеждният начин да използвате Mimikatz и да вградите както x64, така и x86 ресурсите, като същевременно останете под лимита от 1 MB, е чрез използване на защита на ресурсите ConfuserEx, която използва много по-ефективен алгоритъм за компресия. Ще обсъдим това в раздела за разширено използване.

Разширено използване

SharpGen поддържа използването на ConfuserEx, защита с отворен код за .NET приложения. Оригиналният ConfuserEx, с който бях запознат, е достъпен тук. Бях доста развълнуван да открия, че ConfuserEx е раздвоен и се поддържа на ново място, тъй като първоначалният проект е изоставен. Бях още по-развълнуван, когато разбрах, че новият ConfuserEx поддържа .NET Core! Това ни позволява да автоматизираме защитата и обфускацията на нашите двоични файлове от SharpGen, кръстосано компилирани за .NET Framework!

SharpGen включва проектен файл ConfuserEx по подразбиране, confuse.cr, който може да се използва и/или персонализира с допълнителни правила на ConfuserEx и може да се използва чрез аргументи на командния ред:

Файлът confuse.cr по подразбиране включва само едно правило, което позволява защита на ресурсите. Защитата на ресурсите ConfuserEx извършва криптиране и LZMA компресиране на вградените ресурси. LZMA компресията е много по-ефективен алгоритъм за компресия от System.IO.Compression компресията, извършена върху powerkatz*.dll.comp файловете, включени в SharpGen. Това по-ефективно компресиране ни позволява да вградим и двата двоични файла на Mimikatz в компилиран двоичен файл и все още да попадаме под 1MB Cobalt Strike execute-assembly лимит! Важно предупреждение е, че трябва да вградите некомпресираната версия на ресурсите, когато използвате тази техника, тъй като компресирането на предварително компресирани файлове не работи почти толкова добре.

В допълнение към защитата на ресурсите, файлът на проекта confuse.cr може да бъде модифициран с допълнителни правила на ConfuserEx. За по-лесна употреба, настройката по подразбиране съдържа много допълнителни правила, които могат да бъдат декоментирани, за да се активира:

За допълнителна информация относно наличните защити на ConfuserEx ще ви насоча към документацията на ConfuserEx Wiki.

Друга характеристика на SharpGen, която трябва да имате предвид, е, че SharpGen се опитва да оптимизира вашия изходен код, като премахва неизползваните типове. Прави това, за да намали крайния двоичен размер, но също и за стелт. Няма причина вашето събрание да съдържа Mimikatz и PE зареждащ изходен код, ако не се нуждае от него! Това става много по-полезно, ако добавяте много библиотеки под папката Source, тъй като може да не е необходимо да препращате към всички тях за всяка компилация.

SharpGen е доста прозрачен относно оптимизациите, направени по време на компилация, и винаги ще отпечатва оригиналния източник и оптимизирания изходен код, докато компилира.

Тази оптимизация изглежда работи добре, но, разбира се, винаги има риск от счупване на нещата при автоматизиране на модификациите на изходния код. Така че, ако срещнете проблеми с тази оптимизация, винаги можете да я деактивирате с аргумента на командния ред --no-optimization (имайте предвид, че това може да увеличи двоичния ви размер!):

Бъдещи допълнения

По стечение на обстоятелствата подобен инструмент с някои ключови разлики беше пуснат миналата седмица, наречен „SharpCompile“, който бих насърчил всички също да разгледат. Мисля, че най-готиният аспект на SharpCompile е, че включва агресорен скрипт, който обработва цялата компилация във фонов режим, така че никога да не се налага да напускате интерфейса на Cobalt Strike!

Бих искал да добавя подобна функция към SharpGen, която да обработва цялата компилация във фонов режим и да не позволява на потребителите да напускат интерфейса на Cobalt Strike, за да генерират нови сборки. Така че очаквайте това да бъде добавено към SharpGen тук в близко бъдеще.

Заключение

Използването на обиден C# е вълнуващо, но също така идва с набор от оперативни предизвикателства, особено при форматиране на набори от инструменти като библиотеки. Лично аз бих се радвал да видя допълнителни набори от инструменти с отворен код, публикувани като библиотеки с опционален интерфейс за конзолно приложение отпред, което ще ни даде най-доброто от двата свята.

Решенията на тези оперативни предизвикателства трябва да изберат метод на изпълнение, като балансират нуждите от удобство и гъвкавост. SharpGen е моето решение за този балансиращ акт и се надявам, че други го намират за полезен. Но други жизнеспособни решения като SharpSploitConsole, SharpAttack и SharpCompile съществуват и съм сигурен, че ще се появят и други. Насърчавам другите да помислят върху тези предизвикателства, за да изберат правилния инструмент за правилния случай на употреба.

Кредити

SharpGen използва няколко библиотеки с отворен код, които бих искал да призная:

  • Roslyn — SharpGen използва компилатора Roslyn C# или Microsoft.CodeAnalysis.CSharp, написан от Microsoft.
  • CommandLineUtils — SharpGen анализира аргументите на командния ред с помощта на библиотеката McMaster.Extensions.CommandLineUtils, написана от Nate McMaster.
  • ConfuserEx — SharpGen по избор използва ConfuserEx за защита и обфускация на сглобяване, първоначално написан от yck1509 и сега поддържан от mkaring.
  • dnlib — самият ConfuserEx използва dnlib, библиотека за четене/записване на .NET асемблиране с отворен код, написана от 0xd4d.
  • YamlDotNet — SharpGen анализира конфигурационните файлове на YAML с помощта на YamlDotNet, .NET библиотека с отворен код за анализиране на YAML, написана от aaubry.

Бих искал също така да поздравя някои от другите проекти с отворен код, споменати в тази публикация:

  • SharpAttack — SharpAttack е преден край на конзолно приложение с отворен код за SharpSploit, който използва ILMerge и е написан от Jared Haight.
  • SharpSploitConsole — SharpSploitConsole е преден край на конзолно приложение с отворен код за SharpSploit, което използва Costura и е написано от anthemtotheego и g0ldengunsec.
  • SharpCompile — автоматизирано, обидно решение за компилиране на .NET, което използва агресорен скрипт и HTTP сървър, който използва csc.exe.
  • Costura — Costura вгражда референтни сборки като ресурси.
  • ILMerge — ILMerge е статичен линкер за .NET сборки, написан от Mike Barnett и поддържан от Microsoft.

И накрая, някои допълнителни ресурси, които бих препоръчал да разгледате: