Comment créer une fonction de crochet et de trampoline dans WinAPI

Je me suis donc familiarisé avec le concept de raccordement et d’utilisation de trampolines afin de contourner / exécuter des données dans une fonction de raccordement WinAPI (dans un fichier exécutable différent, à l’aide de l’injection de DLL). Jusqu’ici, je sais comment le faire (trampoline et crochet) en utilisant un mélange d’assemblage et de C, mais je n’arrive pas à le faire en utilisant simplement C, car il me semble manquer quelque chose. J’apprécierais que quelqu’un me dise ce que je fais de mal et comment y remédier.

En ce moment mon code:

#include  unsigned char* address = 0; __declspec(naked) int __stdcall MessageBoxAHookTrampoline(HWND Window, char* Message, char* Title, int Type) { __asm { push ebp mov ebp, esp mov eax, address add eax, 5 jmp eax } } int __stdcall MessageBoxAHook(HWND Window, char* Message, char* Title, int Type) { wchar_t* WMessage = L"Hooked!"; wchar_t* WTitle = L"Success!"; MessageBoxW(0, WMessage, WTitle, 0); return MessageBoxAHookTrampoline(Window, Message, Title, Type); } unsigned long __stdcall Thread(void* Context) { address = (unsigned char*)GetProcAddress(LoadLibraryA("user32"), "MessageBoxA"); ULONG OP = 0; if (VirtualProtect(address, 1, PAGE_EXECUTE_READWRITE, &OP)) { memset(address, 0x90, 5); *address = 0xE9; *(unsigned long*)(address + 1) = (unsigned long)MessageBoxAHook - (unsigned long)address - 5; } else { MessageBoxA(0, "Failed to change protection", "RIP", 0); } return 1; } // Entry point. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { if (fdwReason == DLL_PROCESS_ATTACH) { CreateThread(0, 0, Thread, 0, 0, 0); } else if (fdwReason == DLL_PROCESS_DETACH) { } return true; } 

La question est donc de savoir comment faire en sorte qu’une fonction dise InstallHook qui installe le crochet et renvoie un trampoline afin que je puisse l’utiliser facilement. Le prototype de fonction serait probablement: void* InstallHook(void* originalFunc, void* targetFunc, int jumpsize) , ou alors j’ai compris lire en ligne, mais jumpsize ne jumpsize pas à quoi jumpsize .

Jusqu’à présent, je sais que les 5 premiers octets doivent être conservés et restaurés, puis il y a un saut à l’adresse de la fonction accrochée d’origine. Donc, je devrais utiliser malloc pour allouer de la mémoire, mémoire pour copier des octets, 0xE9 est la valeur d’une instruction de saut, 0xE9 , mais je ne sais tout simplement pas comment l’implémenter en utilisant uniquement du C pur. être quelque chose de similaire au code dans cette question. Alors, comment puis-je écrire une fonction hook qui retourne un trampoline en utilisant des fonctions C pur pour WinAPI?

Si j’ai bien compris la question, vous voulez éviter de “coder en dur” la fonction de trampoline dans l’assemblage, probablement pour pouvoir utiliser plusieurs trampolines en même temps sans dupliquer le code. Vous pouvez y parvenir en utilisant VirtualAlloc ( malloc ne fonctionnera pas car la mémoire renvoyée ne sera pas exécutable).

J’ai écrit cela de mémoire sans avoir access à un compilateur, ce qui peut avoir quelques bugs mineurs, mais l’idée générale est là. Normalement, vous utiliseriez également VirtualProtect pour changer les permissions de page en rx au lieu de rwx une fois que vous avez fini de le modifier, mais je ne l’ai pas laissé par souci de simplicité:

 void *CreateTrampoline(void *originalFunc) { /* Allocate the trampoline function */ uint8_t *trampoline = VirtualAlloc( NULL, 5 + 5, /* 5 for the prolog, 5 for the JMP */ MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); /* Make trampoline executable */ /* Copy the original function's prolog */ memcpy(trampoline, originalFunc, 5); /* JMP rel/32 opcode */ trampoline[5] = 0xE9; /* JMP rel/32 operand */ uint32_t jmpDest = (uint32_t)originalFunc + 5; /* Skip original prolog */ uint32_t jmpSrc = (uint32_t)trampoline + 10; /* Starting after the JMP */ uint32_t delta = jmpDest - jmpSrc; memcpy(trampoline + 6, &delta, 4); return trampoline; } 

Votre fonction InstallHook alors que CreateTrampoline pour créer un trampoline, puis patcherait les 5 premiers octets de la fonction originale avec un JMP rel/32 .

Soyez averti, cela ne fonctionne que sur les fonctions WinAPI, car Microsoft requirejs un prolog de 5 octets pour activer le correctif à chaud (ce que vous faites ici). Les fonctions normales ne sont pas push ebp; mov ebp, esp cette exigence – elles ne commencent généralement que par push ebp; mov ebp, esp push ebp; mov ebp, esp qui n’est que de 3 octets (et parfois même pas si le compilateur décide de l’optimiser).

Edit: voici comment fonctionne le calcul:

  _______________delta______________ | | trampoline | originalFunc | | | | | v | vv [prolog][jmp delta] [prolog][rest of func] |________||_________| |________| 5 + 5 5