
Meine Experimente zur Bewaffnung von Nim (https://nim-lang.org/)
Meine Experimente zur Bewaffnung von Nim für die Entwicklung von Implantaten und allgemeine offensive Operationen.
DllMain
mingw-Toolchains und die Übergabe eines einzelnen Flags an den Nim-Compiler.| Datei | Beschreibung |
|---|---|
| amsi_patch_2_bin.nim | Patcht AMSI aus dem aktuellen Prozess mit einer anderen Methode (WIP, Hilfe erwünscht) |
| excel_4_com_bin.nim |
Dieses Repository stellt keine Binärdateien bereit, Sie müssen sie selbst kompilieren. Dieses Repository wurde eingerichtet, um die Beispiel-Nim-Quelldateien von Linux oder MacOS nach Windows zu cross-kompilieren.
Verwenden Sie VSCode Devcontainers, um automatisch eine Entwicklungsumgebung für Sie einzurichten (siehe Abschnitt Einrichten einer Dev-Umgebung). Sobald das erledigt ist, führen Sie einfach make aus.
Installieren Sie Nim mit Ihrem Systempaketmanager (für Windows verwenden Sie den Installer auf der offiziellen Website)
brew install nimapt install nimchoco install nim(Nim bietet auch ein Docker-Image auf Dockerhub)
Sie sollten nun die Befehle nim und nimble zur Verfügung haben, ersterer ist der Nim-Compiler und letzterer ist Nims Paketmanager.
Installieren Sie das Mingw-Toolchain, das für die Cross-Compilierung nach Windows benötigt wird (nicht erforderlich, wenn Sie unter Windows kompilieren):
apt-get install mingw-w64brew install mingw-w64Installieren Sie schließlich die großartige Winim-Bibliothek zusammen mit zippy und nimcrypto:
nimble install winim zippy nimcryptoWechseln Sie dann in das Root-Verzeichnis dieses Repositorys und führen Sie make aus.
Sie sollten die Binärdateien und DLLs im Verzeichnis bin/ finden.
Siehe den Cross-Compilierungsabschnitt im Nim-Compiler-Benutzerhandbuch für viele weitere Details.
Cross-Compilierung nach Windows von MacOS/*nix erfordert das mingw-Toolchain, normalerweise nur eine Frage von brew install mingw-w64 oder apt install mingw-w64.
Sie müssen dann nur das Flag -d=mingw an den Nim-Compiler übergeben.
Z.B. nim c -d=mingw --app=console --cpu=amd64 source.nim
Siehe den verrückten FFI-Abschnitt im Nim-Handbuch.
Wenn Sie mit csharps P/Invoke vertraut sind, ist es im Grunde das gleiche Konzept, wenn auch ein bisschen hässlicher:
Beispiel für den Aufruf von `MessageBox````nim type HANDLE* = int HWND* = HANDLE UINT* = int32 LPCSTR* = cstring
proc MessageBox*(hWnd: HWND, lpText: LPCSTR, lpCaption: LPCSTR, uType: UINT): int32 {.discardable, stdcall, dynlib: "user32", importc: "MessageBoxA".}
MessageBox(0, "Hello, world !", "Nim is Powerful", 0)
Für komplexe Windows-API-Aufrufe verwenden Sie die [Winim-Bibliothek](https://github.com/khchen/winim), das spart eine wahnsinnige Menge Zeit und vergrößert die ausführbare Datei nicht zu sehr (siehe unten), je nachdem, wie Sie sie importieren.
Hat sogar COM-Unterstützung!!!
## Erstellen von Windows-DLLs mit einem exportierten `DllMain`
Ein großer Dank an die Person, die [dies](https://forum.nim-lang.org/t/1973) im Nim-Forum gepostet hat.
Der Nim-Compiler versucht, für Sie automatisch eine `DllMain`-Funktion zur Kompilierzeit zu erstellen, wenn Sie ihn anweisen, eine Windows-DLL zu erstellen, aber aus irgendeinem Grund exportiert er sie nicht. Um eine exportierte `DllMain` zu haben, müssen Sie `--nomain` übergeben und selbst eine `DllMain`-Funktion mit den entsprechenden Pragma-Direktiven definieren (`stdcall, exportc, dynlib`).
Sie müssen auch `NimMain` von Ihrer `DllMain` aus aufrufen, um Nims Garbage Collector zu initialisieren. (Sehr wichtig, sonst explodiert Ihr Computer buchstäblich).
Beispiel:
```nim
import winim
proc DllMain(hinstDLL: HINSTANCE, fdwReason: DWORD, lpvReserved: LPVOID): BOOL {.stdcall, exportc, dynlib.} =
if fdwReason == DLL_PROCESS_ATTACH:
nimMain()
return TRUE
``````nim
import winim/lean
proc NimMain() {.cdecl, importc.}
proc DllMain(hinstDLL: HINSTANCE, fdwReason: DWORD, lpvReserved: LPVOID) : BOOL {.stdcall, exportc, dynlib.} =
NimMain()
if fdwReason == DLL_PROCESS_ATTACH:
MessageBox(0, "Hello, world !", "Nim is Powerful", 0)
return true
Zum Kompilieren:``` nim c -d=mingw --app=lib --nomain --cpu=amd64 mynim.dll
### Erstellen von XLLs
Sie können eine XLL (eine Excel-DLL, stellen Sie sich das vor) mit einer Auto-Open-Funktion erstellen, die für die Bereitstellung von Payloads verwendet werden kann. Der folgende Code erstellt eine einfache XLL mit einer Auto-Open-Funktion und dem gesamten weiteren Boilerplate-Code, der zum Kompilieren als Link-Bibliothek erforderlich ist. Der POC wird als DLL kompiliert. Sie können dann die Erweiterung in .xll ändern, und die Datei wird in Excel geöffnet und führt den Payload aus, wenn Sie darauf doppelklicken:```nim
#[
Compile:
nim c -d=mingw --app=lib --nomain --cpu=amd64 nim_xll.nim
Will compile as a DLL, you can then just change the extension to .xll
]#
import winim/lean
proc xlAutoOpen() {.stdcall, exportc, dynlib.} =
MessageBox(0, "Hello, world !", "Nim is Powerful", 0)
proc NimMain() {.cdecl, importc.}
proc DllMain(hinstDLL: HINSTANCE, fdwReason: DWORD, lpvReserved: LPVOID) : BOOL {.stdcall, exportc, dynlib.} =
NimMain()
return true
Es gibt viele andere hinterhältige Dinge, die mit XLLs gemacht werden können. Siehe weitere Beispiele für XLL-Tradecraft hier.
Entnommen aus der Nim-FAQ-Seite
Für die größte Größenreduzierung verwenden Sie die folgenden Flags -d:danger -d:strip --opt:size
Zusätzlich habe ich festgestellt, dass man noch ein paar Bytes herausholen kann, indem man --passc=-flto --passl=-flto an den Compiler übergibt. Schauen Sie sich auch die Makefile in diesem Repository an.
Diese Flags verringern die Größen dramatisch: das Shellcode-Injection-Beispiel geht von 484.3 KB auf 46.5 KB zurück, wenn es von MacOSX aus cross-kompiliert wird!
Großer Dank an @Shitsecure, der das herausgefunden hat!
Standardmäßig generiert Nim keine PEs mit einer Relokationstabelle, die von den meisten Tools benötigt wird, die EXEs reflektiv laden.
Um ein Nim-Executable mit einem Relokationsabschnitt zu erzeugen, müssen Sie dem Linker ein paar zusätzliche Flags übergeben.
Specifically: --passL:-Wl,--dynamicbase
Vollständiges Beispielkommando:``` nim c --passL:-Wl,--dynamicbase my_awesome_malwarez.nim
## Unterschiede in der ausführbaren Dateigröße bei Verwendung der Winim-Bibliothek im Vergleich zu ohne
Erstaunlicherweise ist der Größenunterschied ziemlich vernachlässigbar. Besonders wenn man die oben beschriebenen Größenoptimierungen anwendet.
Die beiden Beispiele `pop_bin.nim` und `pop_winim_bin.nim` wurden zu diesem Zweck erstellt.
Ersteres definiert den WinAPI-Aufruf `MessageBox` manuell und letzteres verwendet die Winim-Bibliothek (genauer `winim/lean`, das nur das Kern-SDK enthält, siehe [hier](https://github.com/khchen/winim#usage)), Ergebnisse:```
byt3bl33d3r@ecl1ps3 OffensiveNim % ls -lah bin
-rwxr-xr-x 1 byt3bl33d3r 25K Nov 20 18:32 pop_bin_32.exe
-rwxr-xr-x 1 byt3bl33d3r 32K Nov 20 18:32 pop_bin_64.exe
-rwxr-xr-x 1 byt3bl33d3r 26K Nov 20 18:33 pop_winim_bin_32.exe
-rwxr-xr-x 1 byt3bl33d3r 34K Nov 20 18:32 pop_winim_bin_64.exe
Wenn Sie die gesamte Winim-Bibliothek mit import winim/com importieren, fügt sie nur etwa ~20 KB hinzu, was angesichts der Menge an Funktionalität, die sie abstrahiert, die zusätzliche Größe zu 100 % wert ist:```
byt3bl33d3r@ecl1ps3 OffensiveNim % ls -lah bin
-rwxr-xr-x 1 byt3bl33d3r 42K Nov 20 19:20 pop_winim_bin_32.exe
-rwxr-xr-x 1 byt3bl33d3r 53K Nov 20 19:20 pop_winim_bin_64.exe
## Opsec-Überlegungen
Aufgrund der Art und Weise, wie Nim DLLs dynamisch mit `LoadLibrary` mittels seines FFI auflöst, werden keine Ihrer extern importierten Funktionen in den statischen Importen der ausführbaren Datei angezeigt (siehe [diesen Blogbeitrag](https://web.archive.org/web/20210117002945/https://secbytes.net/implant-roulette-part-1:-nimplant/) für weitere Informationen):

Wenn Sie Nim-Quellcode in eine DLL kompilieren, scheint es, dass Sie immer ein exportiertes `NimMain` haben, unabhängig davon, ob Sie Ihr eigenes `DllMain` angeben oder nicht (??). Dies könnte potenziell als Signatur verwendet werden, ich weiß nicht, wie viele Unternehmen tatsächlich Nim in ihrem Entwicklungsstack verwenden. Fällt definitiv auf.

## Schreiben von Nim ohne die Nim-Laufzeit
Da Nim von Antivirenlösungen stark markiert wird, besteht eine Möglichkeit darin, Nim-Programme ohne die Nim-Laufzeit zu schreiben. [Writing Nim-less Nim](https://www.youtube.com/watch?v=EXX3HmCG3pw) ist ein Vortrag, der die Schritte beschreibt, wie man Nim-Code ohne die Nim- und C-Laufzeit schreibt. Der Quellcode zu diesem Vortrag ist [hier](https://github.com/m4ul3r/writing_nimless) verfügbar. Der Vortrag folgt und erweitert die Arbeit von [zimawhit3](https://github.com/zimawhit3) mit [Bitmancer](https://github.com/zimawhit3/Bitmancer/tree/main).
Das Prinzip besteht darin, sich auf die Typdefinitionen von `winim` zu verlassen und Code zu schreiben, der nicht zur Nutzung der Nim-Laufzeit führt.
## Konvertieren von C-Code in Nim
https://github.com/nim-lang/c2nim
Habe es verwendet, um eine Reihe kleiner C-Snippets zu übersetzen, habe noch nichts Großes versucht.
## Sprachbrücken
- Python integration https://github.com/yglukhov/nimpy
* Das ist tatsächlich super interessant, [insbesondere dieser Teil](https://github.com/yglukhov/nimpy/blob/master/nimpy/py_lib.nim#L330). Könnte dies mit einigen Modifikationen die PythonxXX.dll aus dem Speicher laden?
- Jave VM integration: https://github.com/yglukhov/jnim
## Debugging
Verwenden Sie die Funktion `repr()` in Kombination mit `echo`, sie unterstützt fast alle (??) Datentypen, sogar Strukturen!
Siehe [diesen Blogbeitrag für mehr](https://nim-lang.org/blog/2017/10/02/documenting-profiling-and-debugging-nim-code.html)
## Einrichten einer Entwicklungsumgebung
Dieses Repository unterstützt [VSCode Devcontainers](https://code.visualstudio.com/docs/remote/create-dev-container), die es Ihnen ermöglichen, in einem Docker-Container zu entwickeln. Dies automatisiert die Einrichtung einer Entwicklungsumgebung für Sie.
1. Installieren Sie VSCode und Docker Desktop
2. Klonen Sie dieses Repository und öffnen Sie es in VSCode
3. Installieren Sie die Erweiterung `Visual Studio Code Remote - Containers`
4. Öffnen Sie die Befehlspalette und wählen Sie den Befehl `Remote-Containers: Reopen in Container`
VSCode wird nun das Docker-Image erstellen (wird etwas dauern) und Sie direkt in Ihre vorgefertigte Nim-Entwicklungsumgebung versetzen!
## Fallstricke, in die ich selbst getappt bin
- Wenn Sie Winapi-Aufrufe mit Winim tätigen und versuchen, einen Nullwert zu übergeben, stellen Sie sicher, dass Sie den Wert `NULL` (innerhalb der Winim-Bibliothek definiert) anstelle von Nims eingebautem `nil`-Wert übergeben. (Ugh)
- Um das Betriebssystem-Handle für die erstellte Datei nach dem Aufruf von `open()` unter Windows zu erhalten, müssen Sie `f.getOsFileHandle()` **nicht** `f.getFileHandle()` aufrufen, aus Gründen.
- Der Nim-Compiler akzeptiert Argumente in der Form `-a=value` oder `--arg=value`, obwohl in der Verwendung nur Argumente als `-a:value` oder `--arg:value` angegeben werden. (Wichtig für Makefiles)
- Wenn Sie ein Byte-Array definieren, müssen Sie zumindest beim ersten Wert angeben, dass es sich um ein Byte-Array handelt, etwas seltsam, aber ok (https://forum.nim-lang.org/t/4322)
Byte-Array in C#:```csharp
byte[] buf = new byte[5] {0xfc,0x48,0x81,0xe4,0xf0,0xff}
Byte-Array in Nim:```nim var buf: array[5, byte] = [byte 0xfc,0x48,0x81,0xe4,0xf0,0xff]
## Interessante Nim-Bibliotheken
- https://github.com/dom96/jester
- https://github.com/pragmagic/karax
- https://github.com/Niminem/Neel
- https://github.com/status-im/nim-libp2p
- https://github.com/PMunch/libkeepass
- https://github.com/def-/nim-syscall
- https://github.com/tulayang/asyncdocker
- https://github.com/treeform/ws
- https://github.com/guzba/zippy
- https://github.com/rockcavera/nim-iputils
- https://github.com/FedericoCeratto/nim-socks5
- https://github.com/CORDEA/backoff
- https://github.com/treeform/steganography
- https://github.com/miere43/nim-registry
- https://github.com/status-im/nim-daemon
## Nim für Implant-Entwicklung Links
- https://web.archive.org/web/20210117002945/https://secbytes.net/implant-roulette-part-1:-nimplant/
- https://securelist.com/zebrocys-multilanguage-malware-salad/90680/
- https://github.com/MythicAgents/Nimplant
- https://github.com/elddy/Nim-SMBExec
- https://github.com/elddy/NimScan
## Mitwirkende
Virtuelle Umarmung an alle, die mitgewirkt haben ❤️
<a href="https://github.com/byt3bl33d3r/OffensiveNim/graphs/contributors">
<img src="https://contrib.rocks/image?repo=byt3bl33d3r/OffensiveNim" />
</a>
| Datei | Beschreibung |
|---|
| pop_bin.nim | Aufruf von MessageBox WinApi ohne Verwendung der Winim-Bibliothek |
| pop_winim_bin.nim | Aufruf von MessageBox mit der Winim-Bibliothek |
| pop_winim_lib.nim | Beispiel für die Erstellung einer Windows-DLL mit exportiertem DllMain |
| execute_assembly_bin.nim | Hostet die CLR, führt reflektiv .NET-Assemblies aus dem Speicher aus |
| clr_host_cpp_embed_bin.nim | Hostet die CLR durch direktes Einbetten von C++-Code, führt ein .NET-Assembly von der Festplatte aus |
| scshell_c_embed_bin.nim | Zeigt, wie man vorhandenen C-Code schnell bewaffnet, indem man SCShell (C) direkt in Nim einbettet |
| fltmc_bin.nim | Listet alle Minifilter-Treiber auf |
| blockdlls_acg_ppid_spoof_bin.nim | Erstellt einen angehaltenen Prozess, der seine PPID auf explorer.exe fälscht, aktiviert auch BlockDLLs und ACG |
| named_pipe_client_bin.nim | Named-Pipe-Client |
| named_pipe_server_bin.nim | Named-Pipe-Server |
| embed_rsrc_bin.nim | Bettet eine Ressource (ZIP-Datei) zur Kompilierzeit ein und extrahiert den Inhalt zur Laufzeit |
| self_delete_bin.nim | Eine Möglichkeit, eine gesperrte oder aktuell laufende ausführbare Datei auf der Festplatte zu löschen. Methode entdeckt von @jonasLyk |
| encrypt_decrypt_bin.nim | Ver-/Entschlüsselung mit AES256 (CTR-Modus) unter Verwendung der Nimcrypto-Bibliothek |
| amsi_patch_bin.nim | Patcht AMSI aus dem aktuellen Prozess |
| amsi_providerpatch_bin.nim | Patcht die AMSI-Provider-DLL (in diesem Fall MpOav.dll), um AMSI zu umgehen. Veröffentlicht hier |
| etw_patch_bin.nim | Patcht ETW aus dem aktuellen Prozess (Beigetragen von ) |
| wmiquery_bin.nim | Fragt laufende Prozesse und installierte Antivirenprogramme mit WMI ab |
| out_compressed_dll_bin.nim | Komprimiert, Base-64-kodiert und gibt PowerShell-Code aus, um eine verwaltete DLL im Speicher zu laden. Portierung des ursprünglichen PowerSploit-Skripts nach Nim. |
| dynamic_shellcode_local_inject_bin.nim | POC zum lokalen Injizieren von dynamisch abgerufenen Shellcode anstatt ihn fest in einem Array zu kodieren. |
| shellcode_callback_bin.nim | Führt Shellcode mit Callback-Funktionen aus |
| shellcode_bin.nim | Erstellt einen angehaltenen Prozess und injiziert Shellcode mit VirtualAllocEx/CreateRemoteThread. Demonstriert auch die Verwendung von Kompilierzeit-Definitionen zur Erkennung von Architektur, Betriebssystem usw. |
| shellcode_fiber.nim | Shellcode-Ausführung über Fasern |
| shellcode_inline_asm_bin.nim | Führt Shellcode mit Inline-Assembly aus |
| ssdt_dump.nim | Einfaches SSDT-Abrufen mit Laufzeitfunktionstabelle aus dem Ausnahmeverzeichnis. Technik inspiriert vom MDSEC-Artikel |
| syscalls_bin.nim | Zeigt, wie man direkte Systemaufrufe tätigt |
| execute_powershell_bin.nim | Hostet die CLR und führt PowerShell über einen nicht verwalteten Runspace aus |
| passfilter_lib.nim | Protokolliert Passwortänderungen in eine Datei durch (Miss-)Brauch eines Passwortkomplexitätsfilters |
| minidump_bin.nim | Erstellt einen Speicherauszug von lsass mit MiniDumpWriteDump |
| http_request_bin.nim | Demonstriert einige Möglichkeiten, HTTP-Anfragen zu stellen |
| execute_sct_bin.nim | .sct-Dateiausführung über GetObject() |
| scriptcontrol_bin.nim | Dynamische Ausführung von VBScript und JScript mit dem MSScriptControl COM-Objekt |
| excel_com_bin.nim | Injiziert Shellcode mit dem Excel-COM-Objekt und Makros |
| keylogger_bin.nim | Keylogger mit SetWindowsHookEx |
| memfd_python_interpreter_bin.nim | Verwendet den memfd_create-Syscall, um eine Binärdatei in eine anonyme Datei zu laden und mit execve auszuführen. |
| uuid_exec_bin.nim | Platziert Shellcode aus einem UUID-Array im Heap-Speicher und verwendet den EnumSystemLocalesA-Callback, um den Shellcode auszuführen. |
| unhookc.nim | Entfernt Hooks aus ntdll.dll, um EDR/AV-Hooks zu umgehen (bettet die C-Codevorlage von ired.team ein) |
| unhook.nim | Entfernt Hooks aus ntdll.dll, um EDR/AV-Hooks zu umgehen (reine Nim-Implementierung) |
| taskbar_ewmi_bin.nim | Verwendet Extra Window Memory Injection über die Running Application-Eigenschaft der Taskleiste, um den Shellcode auszuführen. |
| fork_dump_bin.nim | (Miss-)Braucht Windows' Implementierung von fork() und erlangt ein Handle zu einem entfernten Prozess mit dem Zugriffsrecht PROCESS_CREATE_PROCESS. Versucht dann, den Speicher des geforkten Prozesses mit MiniDumpWriteDump() auszugeben. |
| ldap_query_bin.nim | Führt LDAP-Abfragen über COM mit ADO's ADSI-Provider durch |
| sandbox_process_bin.nim | Sandboxt einen Prozess, indem es seine Integritätsstufe auf "Nicht vertrauenswürdig" setzt und wichtige Tokens entfernt. Dies kann verwendet werden, um einen PPL-Prozess (z.B. AV/EDR) "stumm zu deaktivieren". |
| list_remote_shares.nim | Verwendet NetShareEnum, um die für den aktuellen Benutzer zugänglichen Freigaben aufzulisten |
| chrome_dump_bin.nim | Liest und entschlüsselt Cookies aus Chromes sqlite-Datenbank |
| suspended_thread_injection.nim | Shellcode-Ausführung durch Injektion in angehaltene Threads |
| dns_exfiltrate.nim | Einfache DNS-Exfiltration über TXT-Eintragsanfragen |
| rsrc_section_shellcode.nim | Führt Shellcode aus, der im .rsrc-Abschnitt der Binärdatei eingebettet ist |
| token_steal_cmd.nim | Stehle ein Token/Impersoniere und führe dann einen Befehl aus |
| anti_analysis_isdebuggerpresent.nim | Einfache Anti-Analyse, die auf einen Debugger prüft |
| sandbox_domain_check.nim | Einfache Sandbox-Umgehungstechnik, die prüft, ob der Computer mit einer Domäne verbunden ist oder nicht |
| Hook.nim | Beispiel für offensives Hooking von MessageBoxA |
| anti_debug.nim | Vorstellung von zwei Anti-Debugging-Techniken |
| anti_debug_via_tls.nim | Anti-Debugging über TLS |
| local_pe_execution.nim | Ausführung von exe- und dll-Dateien im Speicher |
| stack_string_allocation.nim | Allokieren von C- und Wide-Strings auf dem Stack mit Arrays |
| hardware_breakpoints.nim | Hooking von Funktionen mit Hardware-Breakpoints |
| Injiziert Shellcode mit dem Excel-COM-Objekt und Excel 4 Makros (WIP) |