Nytro Posted July 5, 2010 Report Posted July 5, 2010 // InjHookTHM.c pour The Hackademy Manuel #10 (auteur: Carib)#include <stdio.h>#include <windows.h>#include <tlhelp32.h>#define SIZE_HOOKFUNCTION 4096#define SIZE_RPLFUNCTION 4096typedef HMODULE (WINAPI *pfGetModuleHandle)(LPCTSTR);typedef FARPROC (WINAPI *pfGetProcAddress)(HMODULE, LPCSTR);typedef BOOL (WINAPI *pfVirtualProtect)(LPVOID, DWORD, DWORD, PDWORD);typedef INT (WINAPI *pfMessageBox)(HWND, LPCSTR, LPCTSTR, UINT);typedef LONG (WINAPI *pfDispatchMessage)(CONST MSG *lpmsg);// La structure de données que nous allons injectertypedef struct{ CHAR szRplFunctionModule[20]; CHAR szRplFunction[20]; PVOID pMyRplFunction; PVOID pOrigRplFunction; pfLoadLibrary _LoadLibraryA; pfGetModuleHandle _GetModuleHandleA; pfGetProcAddress _GetProcAddress; pfVirtualProtect _VirtualProtect; CHAR szUser32[20]; CHAR szMessageBoxW[20]; pfMessageBox _MessageBoxW;}INJECTEDDATA;// Obtenir un handle en accès complet d'un processusHANDLE GetProcessByName(CHAR *szProcessName){ HANDLE hProcessSnap; DWORD th32ProcessID; PROCESSENTRY32 pe32; HANDLE hProcess = NULL; BOOL bFound = FALSE; // Snapshot de tous les processus hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // Initialisation de la structure qui contiendra les infos pe32.dwSize = sizeof(PROCESSENTRY32); // Parcours de tous les processus th32ProcessID = Process32First(hProcessSnap, &pe32); while(th32ProcessID) { // Essai d'obtenir un handle en écriture sur le processus hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); if(hProcess != NULL && strcmp(pe32.szExeFile, szProcessName) == 0) { bFound = TRUE; break; } pe32.dwSize = sizeof(PROCESSENTRY32); th32ProcessID = Process32Next(hProcessSnap, &pe32); } CloseHandle(hProcessSnap); return (bFound ? hProcess: NULL);}int main(void){ HANDLE hProcess; HMODULE hKernel32; INJECTEDDATA Data, *pData; PVOID pHookFunction; DWORD dwNbBytesWritten, dwThreadID, dwExitCode; HANDLE hThread; if((hProcess = GetProcessByName("notepad.exe")) == NULL) { printf("Le processus ne peut etre ouvert\n"); return 0; } hKernel32 = LoadLibrary("kernel32.dll"); Data._GetModuleHandleA = (pfGetModuleHandle)GetProcAddress(hKernel32, "GetModuleHandleA"); Data._GetProcAddress = (pfGetProcAddress)GetProcAddress(hKernel32, "GetProcAddress"); Data._VirtualProtect = (pfVirtualProtect)GetProcAddress(hKernel32, "VirtualProtect"); // APIs utiles au hook => APIs de user32, etc. lstrcpy(Data.szUser32, "user32.dll"); lstrcpy(Data.szMessageBoxA, "MessageBoxW"); // API hookée : DispatchMessage afin d'intercepter les messages WM_CHAR lstrcpy(Data.szRplFunctionModule, "user32.dll"); lstrcpy(Data.szRplFunction, "DispatchMessageW"); // Injection de la fonction de remplacement. L'adresse de cette fonction est stockée dans la structure de données injectée. Data.pMyRplFunction = VirtualAllocEx(hProcess, NULL, SIZE_RPLFUNCTION, MEM_COMMIT, PAGE_EXECUTE_READWRITE); WriteProcessMemory(hProcess, Data.pMyRplFunction, MyDispatchMessage, SIZE_RPLFUNCTION, &dwNbBytesWritten); // Injection de la fonction qui va coordonner le hook. pHookFunction = VirtualAllocEx(hProcess, NULL, SIZE_HOOKFUNCTION, MEM_COMMIT, PAGE_EXECUTE_READWRITE); WriteProcessMemory(hProcess, pHookFunction, HookFunction, SIZE_HOOKFUNCTION, &dwNbBytesWritten); // Injection de la structure de données. pData = VirtualAllocEx(hProcess, NULL, sizeof(INJECTEDDATA), MEM_COMMIT, PAGE_EXECUTE_READWRITE); WriteProcessMemory(hProcess, pData, &Data, sizeof(INJECTEDDATA), &dwNbBytesWritten); // Création de thread dans le processus cible. if((hThread = CreateRemoteThread(hProcess, NULL, 0, pHookFunction, pData, 0, &dwThreadID)) == NULL) { printf("Erreur lors de CreateRemoteThread\n"); return 0; } WaitForSingleObject(hThread, INFINITE); GetExitCodeThread(hThread, &dwExitCode); if(dwExitCode == 0) { printf("Erreur lors du hook\n"); return 0; } return 1;}// Fonction de hook exécutée lors de la création du threadstatic DWORD WINAPI HookFunction(INJECTEDDATA *pData){ // Variables automatiques placées sur la pile => pas de problème HMODULE hModule, hRplFunctionModule, hUser32; PVOID address; DWORD dwOldProtection; // Modification de pData dans la fonction de remplacement => voir plus loin *((DWORD *)((DWORD)(pData->pMyRplFunction) + 9)) = (DWORD)pData; // Récupération des adresses des APIs annexes nécessaires à la fonction de remplacement. On va pouvoir accéder à l'API MessageBoxA hUser32 = pData->_GetModuleHandleA(pData->szUser32); pData->_MessageBoxW = (pfMessageBox)pData->_GetProcAddress(hUser32, pData->szMessageBoxW); // Adresse du module exécutable cible hModule = pData->_GetModuleHandleA(NULL); // Récupération de l'adresse originale de l'API que l'on va hooker hRplFunctionModule = pData->_GetModuleHandleA(pData->szRplFunctionModule); pData->pOrigRplFunction = pData->_GetProcAddress(hRplFunctionModule, pData->szRplFunction); address = pData->pOrigRplFunction; // Recherche de l'adresse à patcher dans l'IAT du module exe __asm { mov esi, address mov eax, hModule // BaseAddress du module exe mov ebx, [eax + 3Ch] // offset e_lfanew add ebx, eax // ptr vers la struct IMAGE_NT_HEADERS32 mov ecx, [ebx + 0D8h] // RVA de l'Import Address Table add ecx, eax // adresse de l'Import Address Table mov edx, [ebx + 0DCh] // taille de l'IAT shr edx, 2 // nb d'adresses dans l'IATNextAPI: cmp [ecx], esi je APIFound // adresse trouvée => sortie add ecx, 4 // sinon, adresse suivante dec edx // on continue tant qu'il reste des adresses jz APINotFound jmp NextAPIAPINotFound: mov ecx, 0APIFound: mov address, ecx } if(address == 0) return 0; // Modification de l'adresse dans l'IAT pData->_VirtualProtect(address, 4, PAGE_READWRITE, &dwOldProtection); *((PDWORD)address) = (DWORD)(pData->pMyRplFunction); pData->_VirtualProtect(address, 4, dwOldProtection, &dwOldProtection); return 1;}static LONG MyDispatchMessage(CONST MSG *lpmsg){ INJECTEDDATA *pData = (INJECTEDDATA *)0x12345678; WCHAR s[2]; if(lpmsg->message == WM_CHAR) { s[0] = (WCHAR)(lpmsg->wParam); s[1] = 0; pData->_MessageBoxW(NULL, s, s, MB_OK); } return ((pfDispatchMessage)pData->pOrigRplFunction)(lpmsg);} Quote