
D/Invoke implementation in Nim
Nim による D/Invoke 実装
すべての Nim バイナリは、通常同じ 58〜60 個の Windows API 関数を公開します:
その他の Windows API 関数は、OffensiveNim または こちらのブログ記事 で述べられているように、通常は実行時に GetProcAddress と LoadLibraryA を介して解決されます。
したがって、Nim で DInvoke を使って API インポートを(完全に)隠すことはできません。ただし、誰かが例えばこの DInvoke 実装を利用して、Dynlib の代わりに DInvoke を使用するように Nim コンパイラを変更する場合を除きます。
GetProcAddress と LoadLibraryA を使用する代わりに PEB から関数を手動で解析することは、デフォルトの Nim の動作よりもステルス性が高くなります。インライン フッキングを回避するには、TheWovers DInvoke ブログ記事 で述べられているように、新しい DLL コピーを手動でマッピングする必要があるでしょう:
ただし、これはここでは まだ 実装されていません。現在は LdrLoadDll を使用して新しい DLL をメモリに読み込んでいるだけです。
このプロジェクトは、NanoDump の D/Invoke コードに大きく影響を受けています。
関数は次のように使用できます:
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)
)
私のテストでは、正しい相対アドレスを見つけるために特別な処理が必要な API 関数がいくつかあり、奇妙な動作に直面しました。私の混乱はコメントに記載されています。単に私のコーディングスタイルがゴミなだけかもしれませんが、誰にもわかりません。
このサンプルが成功すると、次のようになります: