Поскольку наступательные наборы инструментов продолжают переходить двигаться к использованию 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

Costura - еще один проект с открытым исходным кодом, преследующий те же цели, что и ILMerge. Однако используемый метод немного отличается. Costura добавляет ссылки на DLL как «встроенные ресурсы» в консольное приложение. Встроенные ресурсы обычно используются для разных файлов, необходимых приложению, таких как изображения, видео или другие файлы.

Costura встраивает ссылочные библиотеки DLL как встроенные ресурсы и добавляет обратный вызов к событию AssemblyResolve домена приложения, которое пытается загрузить сборки из встроенных ресурсов приложения! Это влияет на способ, которым система будет разрешать сборочные нагрузки для приложения, и позволяет нам загружать сборки из произвольных мест, таких как встроенные ресурсы приложения.

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

Я расскажу на небольшом примере, как использовать Costura. Как и в прошлый раз, вы начнете с создания консольного приложения, добавления ссылки на SharpSploit.dll и написания любого пользовательского кода C #, который использует SharpSploit. Вам также необходимо добавить ссылку на Costura.Fody. Его можно установить как пакет Nuget, щелкнув правой кнопкой мыши ссылку "Ссылки" и выбрав 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 исполняемый файл:

Есть также некоторые интересные следствия для судебной экспертизы двоичных файлов, генерируемых Costura. При открытии 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 загружается через отражение, а не через обычный процесс разрешения сборки. Хотя стоит отметить, что техника Costura «AssemblyResolve» сама использует отражение, используя метод System.Reflection.Assembly.Load().

Отражение - интересный вектор для выполнения, и он может служить полезной подставкой для загрузки, чтобы сэкономить на размере исполняемого файла и избежать сложностей со ссылками. Для получения дополнительной информации о размышлениях я бы рекомендовал ознакомиться с документацией Microsoft.

DotNetToJScript

DotNetToJScript - это инструмент с открытым исходным кодом, написанный Джеймсом Форшоу, который создает файлы 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 на диск, поэтому пока мы по большей части игнорируем этот метод. Однако я хотел задокументировать этот вектор для тех, кто интересуется сценариями запуска агентов.
  • Отражение. Метод отражения интересен и наиболее полезен в сценариях запуска агента или «AssemblyResolve» (например, 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 МБ. Настоящий облом - не иметь возможности использовать 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.

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

Это самые основы инструмента. Полная информация об использовании командной строки приведена ниже:

В следующих разделах мы рассмотрим некоторые подробности того, как 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 МБ. SharpSploit по умолчанию встраивает двоичные файлы Mimikatz x86 и x64, что увеличивает его размер до 1 МБ. У вас есть несколько вариантов борьбы с этим ограничивающим фактором:

  1. Если вы не планируете использовать какие-либо методы Mimikatz, вы можете безопасно отключить встроенные ресурсы Mimikatz в resources.yml файле конфигурации, что значительно уменьшит размер вашего двоичного файла. Для этого просто переключите конфигурацию ресурса на Enabled: false:

2. Если вы все же планируете использовать методы Mimikatz, действительно ли вам нужна копия Mimikatz как x86, так и x64? В противном случае мы можем встроить только необходимый нам ресурс платформы. Есть два способа сделать это:

2а. Вы можете фильтровать ресурсы на основе платформы с помощью аргументов командной строки. Это должно привести вас чуть ниже лимита в 1 МБ:

2b. Вы также можете просто отключить ненужный ресурс в файле конфигурации resources.yml, как мы это сделали ранее:

3. Чтобы еще больше уменьшить размер двоичного файла, вы можете встроить сжатые ресурсы Mimikatz вместо ресурсов по умолчанию, которые поддерживаются и обрабатываются SharpSploit. Они сжимаются с помощью встроенной библиотеки System.IO.Compression. Это сжатие недостаточно эффективно, чтобы позволить вам встраивать ресурсы x64 и x86 и оставаться в пределах 1 МБ, но все же значительно уменьшает двоичный размер. Это можно сделать с помощью файла конфигурации resources.yml, включив сжатые ресурсы и отключив несжатые ресурсы:

4. Более надежный способ использовать Mimikatz и встраивать ресурсы x64 и x86, не превышая лимит в 1 МБ, - это использовать защиту ресурсов 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 в скомпилированный двоичный файл и по-прежнему оставаться в пределах 1 МБ 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, написанной Нейтом Макмастером.
  • ConfuserEx - SharpGen дополнительно использует ConfuserEx для защиты сборки и обфускации, изначально написанного yck1509, а теперь поддерживаемого mkaring.
  • Dnlib - сам ConfuserEx использует dnlib, библиотеку чтения / записи сборок .NET с открытым исходным кодом, написанную 0xd4d.
  • YamlDotNet - SharpGen анализирует файлы конфигурации YAML с помощью YamlDotNet, .NET-библиотеки с открытым исходным кодом для анализа YAML, написанной aaubry.

Я также хотел бы поблагодарить некоторые другие проекты с открытым исходным кодом, упомянутые в этом посте:

  • SharpAttack - SharpAttack - это консольное приложение с открытым исходным кодом для SharpSploit, которое использует ILMerge и написано Джаредом Хейтом.
  • SharpSploitConsole - SharpSploitConsole - это консольное приложение с открытым исходным кодом для SharpSploit, которое использует Costura и написано anthemtotheego и g0ldengunsec.
  • SharpCompile - автоматическое агрессивное решение для компиляции .NET, использующее скрипт-агрессор и HTTP-сервер, использующий csc.exe.
  • Costura - Costura встраивает справочные сборки как ресурсы.
  • ILMerge - ILMerge - статический компоновщик для сборок .NET, написанный Майком Барнеттом и поддерживаемый Microsoft.

И, наконец, некоторые дополнительные ресурсы, которые я бы порекомендовал изучить: