
D/Invoke implementation in Nim
Implementação de D/Invoke em Nim
Todos os binários Nim normalmente expõem as mesmas 58-60 funções da API do Windows:
Todas as outras funções da API do Windows normalmente são resolvidas em tempo de execução via GetProcAddress e LoadLibraryA, como mencionado em OffensiveNim ou neste post de blog.
Portanto, não é possível ocultar importações de API (completamente) via DInvoke em Nim, a menos que alguém, por exemplo, use esta implementação de DInvoke para modificar o compilador Nim para uso de DInvoke em vez de Dynlib.
Analisar manualmente as funções do PEB em vez de usar GetProcAddress e LoadLibraryA ainda é mais furtivo do que o comportamento padrão do Nim. Para também evitar inline hooking, por exemplo, seria necessário o mapeamento manual de uma cópia nova da DLL, como mencionado no post de blog sobre DInvoke do TheWover:
Isso, no entanto, ainda não está implementado aqui yet. Atualmente estou apenas usando LdrLoadDll para carregar novas DLLs na memória.
Este projeto foi fortemente inspirado no código D/Invoke do NanoDump.
A função pode então ser usada assim:
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)
)
Nos meus testes, enfrentei comportamentos estranhos em algumas funções da API, que precisam de casos especiais para encontrar o endereço relativo correto. Minha confusão pode ser encontrada nos comentários. Talvez isso também seja apenas meu estilo de código ruim — quem sabe.
O exemplo, quando bem-sucedido, se parece com o seguinte: