|
| 1 | +#include "stdafx.h" |
| 2 | +#include "Hook.h" |
| 3 | + |
| 4 | +PROCESS_BASIC_INFORMATION BasicProcessInfo; |
| 5 | + |
| 6 | +void InitializeHooking() |
| 7 | +{ |
| 8 | + // Get our Process Handle |
| 9 | + const HANDLE Process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, GetCurrentProcessId()); |
| 10 | + |
| 11 | + // Find out our base address, where the Executable image is loaded in memory |
| 12 | + NtQueryInformationProcess(Process, ProcessBasicInformation, &BasicProcessInfo, sizeof(BasicProcessInfo), nullptr); |
| 13 | +} |
| 14 | + |
| 15 | +void* HookFunction_Internal(const char* DLLName, const char* FunctionName, void* NewAddress) |
| 16 | +{ |
| 17 | + // In the PEB structure provided by Microsoft the ImageBaseAddress is part of a "Reserved" array, |
| 18 | + // for better clarity we use a custom struct here |
| 19 | + CUSTOM_PEB* PEBExtendedInfo = (CUSTOM_PEB*)BasicProcessInfo.PebBaseAddress; |
| 20 | + PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER)PEBExtendedInfo->ImageBaseAddress; |
| 21 | + // This is the start of the executable file in memory |
| 22 | + BYTE* BaseAddress = (BYTE*)PEBExtendedInfo->ImageBaseAddress; |
| 23 | + |
| 24 | + // Get the Address of our NT Image headers |
| 25 | + PIMAGE_NT_HEADERS64 FileHeader = (PIMAGE_NT_HEADERS64)(BaseAddress + pDOSHeader->e_lfanew); |
| 26 | + |
| 27 | + // Retrieve the import directory in which all imported dlls and functions are listed |
| 28 | + IMAGE_DATA_DIRECTORY ImportDirectory = FileHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; |
| 29 | + const int NumImportDesciptors = ImportDirectory.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR); |
| 30 | + PIMAGE_IMPORT_DESCRIPTOR Descriptors = (PIMAGE_IMPORT_DESCRIPTOR)(BaseAddress + ImportDirectory.VirtualAddress); |
| 31 | + |
| 32 | + // Go through all imported DLLs and find the one we are insteresed in |
| 33 | + for (int ImportDLLIndex = 0; ImportDLLIndex < NumImportDesciptors; ++ImportDLLIndex) |
| 34 | + { |
| 35 | + PIMAGE_IMPORT_DESCRIPTOR Descriptor = Descriptors + ImportDLLIndex; |
| 36 | + const char* ImportDLLName = (const char*)BaseAddress + Descriptor->Name; |
| 37 | + |
| 38 | + // Check if we found our DLL in the import table |
| 39 | + if (!strcmp(ImportDLLName, DLLName)) |
| 40 | + { |
| 41 | + |
| 42 | + PIMAGE_THUNK_DATA64 ImportNameTable = (PIMAGE_THUNK_DATA64)(BaseAddress + Descriptor->OriginalFirstThunk); |
| 43 | + int Offset = 0; |
| 44 | + // The import name table is a null terminated array, so iterate until we either found it or reach the null termination |
| 45 | + while (ImportNameTable->u1.AddressOfData != 0) |
| 46 | + { |
| 47 | + PIMAGE_IMPORT_BY_NAME NameImport = (PIMAGE_IMPORT_BY_NAME)(BaseAddress + ImportNameTable->u1.AddressOfData); |
| 48 | + // Null terminated function name start pointer is stored in here |
| 49 | + const char* ImportFunctionName = NameImport->Name; |
| 50 | + |
| 51 | + if (!strcmp(FunctionName, ImportFunctionName)) |
| 52 | + { |
| 53 | + PIMAGE_THUNK_DATA64 ImportAddressTable = (PIMAGE_THUNK_DATA64)(BaseAddress + Descriptor->FirstThunk); |
| 54 | + // The import address table is in the same order as the import name table |
| 55 | + ImportAddressTable += Offset; |
| 56 | + |
| 57 | + void* OriginalAddress = (void*)ImportAddressTable->u1.AddressOfData; |
| 58 | + DWORD OldProtection; |
| 59 | + // Make the page writable to patch the pointer |
| 60 | + VirtualProtect(ImportAddressTable, sizeof(IMAGE_THUNK_DATA64), PAGE_READWRITE, &OldProtection); |
| 61 | + ImportAddressTable->u1.AddressOfData = (ULONGLONG)NewAddress; |
| 62 | + // Restore page protection to the previous state |
| 63 | + VirtualProtect(ImportAddressTable, sizeof(IMAGE_THUNK_DATA64), OldProtection, &OldProtection); |
| 64 | + return OriginalAddress; |
| 65 | + } |
| 66 | + |
| 67 | + |
| 68 | + ++ImportNameTable; |
| 69 | + ++Offset; |
| 70 | + } |
| 71 | + |
| 72 | + // We've found the DLL but not the function, break here. No need to go through the rest of the DLLs |
| 73 | + break; |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + // DLL and function import not found return nullptr to signal this |
| 78 | + return nullptr; |
| 79 | +} |
| 80 | + |
0 commit comments