
D/Invoke implementation in Nim
D/Invoke-Implementierung in Nim
Alle Nim-Binaries legen typischerweise dieselben 58–60 Windows-API-Funktionen offen:
Alle anderen Windows-API-Funktionen werden zur Laufzeit typischerweise über GetProcAddress und LoadLibraryA aufgelöst, wie in OffensiveNim oder diesem Blogbeitrag erwähnt.
Daher ist es nicht möglich, API-Importe (vollständig) über DInvoke in Nim zu verstecken, es sei denn, jemand nutzt beispielsweise diese DInvoke-Implementierung, um den Nim-Compiler für die DInvoke-Nutzung anstelle von Dynlib zu modifizieren.
Das manuelle Parsen der Funktionen aus dem PEB anstelle von GetProcAddress und LoadLibraryA ist immer noch unauffälliger als das Standardverhalten von Nim. Um Inline-Hooking zu vermeiden, wäre beispielsweise das manuelle Mapping einer frischen DLL-Kopie erforderlich, wie in TheWovers DInvoke-Blogbeitrag erwähnt:
Dies ist hier allerdings yet nicht implementiert. Ich verwende derzeit nur LdrLoadDll, um neue DLLs in den Speicher zu laden.
Dieses Projekt wurde stark vom NanoDump-D/Invoke-Code inspiriert.
Die Funktion kann dann wie folgt verwendet werden:
const
KERNEL32_DLL* = "kernel32.dll"
const
OpenProcess_FuncName * = "OpenProcess"
type
OpenProcess_t* = proc (dwDesiredAccess: DWORD, bInheritHandle: WINBOOL, dwProcessId: DWORD): HANDLE {.stdcall.}
MyOpenProcess = cast[OpenProcess_t](cast[LPVOID](get_function_address(cast[HMODULE](get_library_address(KERNEL32_DLL, FALSE)), OpenProcess_FuncName, 0)))
echo "[*] Calling OpenProcess via D/Invoke"
let pHandle = MyOpenProcess(
PROCESS_ALL_ACCESS,
false,
cast[DWORD](https://github.com/s3cur3th1ssh1t/nim_dinvoke/blob/HEAD/processID)
)
In meinen Tests bin ich bei einigen API-Funktionen auf seltsames Verhalten gestoßen, die Sonderfälle benötigen, um die korrekte relative Adresse zu finden. Meine Verwirrung findet sich in den Kommentaren. Vielleicht ist das auch nur mein schlechter Codierstil – wer weiß.
Bei erfolgreicher Ausführung sieht das Beispiel wie folgt aus: