/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------- Hooking Library coded in C ------------------------- lowHertz aka b1nc0der --------------------------------------------------------------------------------------------------------------------------------*/#include <windows.h>#include <stdio.h>#include <stdlib.h>#define JMP 0xE9#define NOP 0x90#define JMP_SIZE 5#define STUB_SIZE 0x10 + JMP_SIZE//extern int __cdecl disasm_main(BYTE* opcodeptr);//extern "C" void pascal disasm_main(BYTE* opcodeptr);int IAT_HOOK(LPSTR szModuleName, LPSTR szProcName, DWORD dwNewFunc);int JMP_HOOK(DWORD dwAddress, DWORD dwJmpAddress);void Create_JMP(CHAR* pcJmpBuf,DWORD dwJmpAddr);typedef BOOL (WINAPI *_VirtualProtect)( LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);struct _IAT_FUNC_INFO { LPDWORD func_addr; LPDWORD func;}IAT_FUNC_INFO, *PIAT_FUNC_INFO;void Create_JMP(CHAR* pcJmpBuf, DWORD dwJmpAddr){ pcJmpBuf[0]=(BYTE)JMP; pcJmpBuf[1]=(BYTE)(dwJmpAddr & 0xFF); pcJmpBuf[2]=(BYTE)((dwJmpAddr >> 8) & 0xFF); pcJmpBuf[3]=(BYTE)((dwJmpAddr >> 16) & 0xFF); pcJmpBuf[4]=(BYTE)((dwJmpAddr >> 24) & 0xFF);}int IAT_HOOK(LPSTR szModuleName, LPSTR szProcName, DWORD dwNewFunc){ DWORD dwOldProtect; // Declare a VirtualProtect function pointer _VirtualProtect __VirtualProtect = NULL; __VirtualProtect = (_VirtualProtect)GetProcAddress(GetModuleHandle("kernel32.dll"), "VirtualProtect"); // Get the original function addr by name DWORD dwOrgFunc = (DWORD)GetProcAddress(GetModuleHandle(szModuleName), szProcName); // Module Handle HMODULE hModule = GetModuleHandle(NULL); PIMAGE_DOS_HEADER pimage_dos_header = (PIMAGE_DOS_HEADER)hModule; // Valid DOS sig ? if(pimage_dos_header->e_magic != IMAGE_DOS_SIGNATURE) return 0; PIMAGE_NT_HEADERS pimage_nt_headers = (PIMAGE_NT_HEADERS)((LPBYTE)hModule + pimage_dos_header->e_lfanew); // Valid NT sig ? if(pimage_nt_headers->Signature != IMAGE_NT_SIGNATURE) return 0; // Import directory is an array of IMAGE_IMPORT_DESCRIPTORs, one for each used DLL PIMAGE_IMPORT_DESCRIPTOR pimage_import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)hModule + pimage_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); while(pimage_import_desc->Name) { if(!stricmp((LPSTR)((PBYTE)hModule + pimage_import_desc->Name), szModuleName)) break; pimage_import_desc++; } // Array of RVAs to IMAGE_THUNK_DATAs, each describing one imported function. // FirstThunk array can change but OriginalFirstThunk can't. PIMAGE_THUNK_DATA pimage_thunk_data = (PIMAGE_THUNK_DATA)((LPBYTE)hModule + pimage_import_desc->FirstThunk); while(pimage_thunk_data->u1.Function) { if(pimage_thunk_data->u1.Function == (LPDWORD)dwOrgFunc) // pimage_thunk_data->u1.Function is the current function address { __VirtualProtect(&pimage_thunk_data->u1.Function, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect); IAT_FUNC_INFO.func_addr = (LPDWORD)&pimage_thunk_data->u1.Function; // this is the address (in the IAT) where it is written the function address IAT_FUNC_INFO.func = (LPDWORD)pimage_thunk_data->u1.Function; // function address pimage_thunk_data->u1.Function = (LPDWORD)dwNewFunc; __VirtualProtect(&pimage_thunk_data->u1.Function, sizeof(DWORD), dwOldProtect, NULL); return 1; // Success :-) } pimage_thunk_data++; } return 0; // Epic Fail :-(}void IAT_UNHOOK(){ *IAT_FUNC_INFO.func_addr = (DWORD)IAT_FUNC_INFO.func;}////////////////////////////////////////////// NOT COMPLETE -> PROBLEM WITH LDE32.OBJ////////////////////////////////////////////int JMP_HOOK(DWORD dwAddress, DWORD dwJmpAddress){ LPVOID lpStub = NULL; DWORD dwOldProtect, dwBytesWritten, dwBytesRead, dwLength = 0; MEMORY_BASIC_INFORMATION mbi; CHAR cStub[STUB_SIZE]; CHAR* cJmp; BYTE* pByte; INT s; HANDLE hProcess = GetCurrentProcess(); BOOL bWrite,bRead; // Get info about the function address VirtualQuery((VOID *)dwAddress, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); // Change the protection for the region VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect); // Fill stub buffer with nops FillMemory(cStub, STUB_SIZE, NOP); // Begin reading at the baseaddress of the function pByte = (BYTE *)dwAddress; // Get the length of the first instruction(s) // This part is done by Z0MBiE's LDE32 v1.05 /* s = disasm_main(pByte); // get first instruction length while (s != -1 && dwLength < JMP_SIZE) { dwLength += s; pByte += s; s = disasm_main(pByte); // next instruction length } */ // API code is too short too hook this way if (dwLength < JMP_SIZE){ VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwOldProtect); return 0; } // Read the first instruction(s) from the function into our stub buffer bRead = ReadProcessMemory(hProcess, (VOID *)dwAddress, cStub, dwLength, &dwBytesRead); // If reading failed or we didn't read enough bytes return NULL if (!bRead || dwBytesRead != dwLength){ VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwOldProtect); return 0; } // Allocate space with read/write access for our "stub" lpStub = VirtualAlloc(NULL, STUB_SIZE, MEM_COMMIT|MEM_TOP_DOWN, PAGE_READWRITE); if (!lpStub){ VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwOldProtect); return 0; } // Build jmp buffer for jumping to original function Create_JMP(cStub + (STUB_SIZE - JMP_SIZE), (dwAddress + dwLength) - ((DWORD)lpStub + (STUB_SIZE))); // Copy the "stub" buffer to process memory bWrite = WriteProcessMemory(hProcess, lpStub, cStub, STUB_SIZE, &dwBytesWritten); // Check that we really wrote our stub completely if ((!bWrite) || (dwBytesWritten != STUB_SIZE)){ // Release the stub buffer VirtualFree(lpStub, dwBytesWritten, MEM_RELEASE); // Make sure that it is NULL lpStub = NULL; } // Give our stub same access as the original function VirtualProtect(lpStub, STUB_SIZE, mbi.Protect, &dwOldProtect); // Allocate buffer for code replacement cJmp = (CHAR *) malloc(dwLength); // Fill it with NULL FillMemory(cJmp, dwLength, '\0'); // Prepare jmpcode Create_JMP(cJmp, dwJmpAddress - (DWORD)dwAddress - JMP_SIZE); // Write jumpcode into the function. bWrite = WriteProcessMemory(hProcess, (VOID *)dwAddress, cJmp, dwLength, &dwBytesWritten); // Free allocated buffer free(cJmp); // Check that we really wrote our jmpcode completely if (!bWrite || dwBytesWritten != dwLength) { // Try to fix things, only if we wrote stuff if (dwBytesWritten) WriteProcessMemory(hProcess, (VOID *)dwAddress, lpStub, dwBytesWritten, &dwBytesWritten); // Release the stub buffer VirtualFree(lpStub, dwBytesWritten, MEM_RELEASE); // Make sure that it is NULL lpStub = NULL; } // Flush instruction cache FlushInstructionCache(hProcess, mbi.BaseAddress, mbi.RegionSize); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwOldProtect); return 1;}