├── CMakeLists.txt ├── test ├── CMakeLists.txt └── sleep.cpp └── src ├── uimports.cpp └── xhook.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | ################################################################################### 4 | project(xhook) 5 | 6 | set(TARGET "xhook") 7 | add_library("${TARGET}" STATIC "../src/xhook.cpp") 8 | add_subdirectory(test) 9 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | ################################################################################### 4 | project(test) 5 | 6 | include_directories("${PROJECT_SOURCE_DIR}/../src") 7 | aux_source_directory(${PROJECT_SOURCE_DIR} SRC_LIST) 8 | 9 | foreach(var ${SRC_LIST}) 10 | string(REGEX REPLACE ".*/" "" var ${var}) 11 | string(REGEX REPLACE ".cpp" "" tgt ${var}) 12 | add_executable(${tgt}.t ${var}) 13 | target_link_libraries(${tgt}.t xhook) 14 | endforeach(var) 15 | 16 | -------------------------------------------------------------------------------- /test/sleep.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "xhook.h" 3 | 4 | #include 5 | using namespace std; 6 | 7 | typedef void(WINAPI *SleepF)(DWORD dwMilliseconds); 8 | SleepF sleep_fn = &::Sleep; 9 | 10 | void WINAPI MySleep(DWORD ms) 11 | { 12 | cout << "MySleep(" << ms << ")" << endl; 13 | } 14 | 15 | int main() 16 | { 17 | XHookRestoreAfterWith(); 18 | XHookTransactionBegin(); 19 | XHookUpdateThread(GetCurrentThread()); 20 | XHookAttach(&(PVOID&)sleep_fn, MySleep); 21 | XHookTransactionCommit(); 22 | ::Sleep(1); 23 | cout << 1 << endl; 24 | system("pause"); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /src/uimports.cpp: -------------------------------------------------------------------------------- 1 | // UpdateImports32 aka UpdateImports64 2 | static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, 3 | HMODULE hModule, 4 | LPCSTR *plpDlls, 5 | DWORD nDlls) 6 | { 7 | BOOL fSucceeded = FALSE; 8 | BYTE * pbNew = NULL; 9 | DWORD i; 10 | 11 | PBYTE pbModule = (PBYTE)hModule; 12 | 13 | IMAGE_DOS_HEADER idh; 14 | ZeroMemory(&idh, sizeof(idh)); 15 | if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { 16 | XHOOK_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n", 17 | pbModule, pbModule + sizeof(idh), GetLastError())); 18 | 19 | finish: 20 | if (pbNew != NULL) { 21 | delete[] pbNew; 22 | pbNew = NULL; 23 | } 24 | return fSucceeded; 25 | } 26 | 27 | IMAGE_NT_HEADERS_XX inh; 28 | ZeroMemory(&inh, sizeof(inh)); 29 | 30 | if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) { 31 | XHOOK_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n", 32 | pbModule + idh.e_lfanew, 33 | pbModule + idh.e_lfanew + sizeof(inh), 34 | GetLastError())); 35 | goto finish; 36 | } 37 | 38 | if (inh.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC_XX) { 39 | XHOOK_TRACE(("Wrong size image (%04x != %04x).\n", 40 | inh.OptionalHeader.Magic, IMAGE_NT_OPTIONAL_HDR_MAGIC_XX)); 41 | SetLastError(ERROR_INVALID_BLOCK); 42 | goto finish; 43 | } 44 | 45 | // Zero out the bound table so loader doesn't use it instead of our new table. 46 | inh.BOUND_DIRECTORY.VirtualAddress = 0; 47 | inh.BOUND_DIRECTORY.Size = 0; 48 | 49 | // Find the size of the mapped file. 50 | DWORD dwFileSize = 0; 51 | DWORD dwSec = idh.e_lfanew + 52 | FIELD_OFFSET(IMAGE_NT_HEADERS_XX, OptionalHeader) + 53 | inh.FileHeader.SizeOfOptionalHeader; 54 | 55 | for (i = 0; i < inh.FileHeader.NumberOfSections; i++) { 56 | IMAGE_SECTION_HEADER ish; 57 | ZeroMemory(&ish, sizeof(ish)); 58 | 59 | if (!ReadProcessMemory(hProcess, pbModule + dwSec + sizeof(ish) * i, &ish, 60 | sizeof(ish), NULL)) { 61 | XHOOK_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %d\n", 62 | pbModule + dwSec + sizeof(ish) * i, 63 | pbModule + dwSec + sizeof(ish) * (i + 1), 64 | GetLastError())); 65 | goto finish; 66 | } 67 | 68 | XHOOK_TRACE(("ish[%d] : va=%08x sr=%d\n", i, ish.VirtualAddress, ish.SizeOfRawData)); 69 | 70 | // If the file didn't have an IAT_DIRECTORY, we assign it... 71 | if (inh.IAT_DIRECTORY.VirtualAddress == 0 && 72 | inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress && 73 | inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) { 74 | 75 | inh.IAT_DIRECTORY.VirtualAddress = ish.VirtualAddress; 76 | inh.IAT_DIRECTORY.Size = ish.SizeOfRawData; 77 | } 78 | 79 | // Find the end of the file... 80 | if (dwFileSize < ish.PointerToRawData + ish.SizeOfRawData) { 81 | dwFileSize = ish.PointerToRawData + ish.SizeOfRawData; 82 | } 83 | } 84 | XHOOK_TRACE(("dwFileSize = %08x\n", dwFileSize)); 85 | 86 | #if IGNORE_CHECKSUMS 87 | // Find the current checksum. 88 | WORD wBefore = ComputeChkSum(hProcess, pbModule, &inh); 89 | XHOOK_TRACE(("ChkSum: %04x + %08x => %08x\n", wBefore, dwFileSize, wBefore + dwFileSize)); 90 | #endif 91 | 92 | XHOOK_TRACE((" Imports: %p..%p\n", 93 | (DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, 94 | (DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress + 95 | inh.IMPORT_DIRECTORY.Size)); 96 | 97 | DWORD obRem = sizeof(IMAGE_IMPORT_DESCRIPTOR) * nDlls; 98 | DWORD obTab = PadToDwordPtr(obRem + 99 | inh.IMPORT_DIRECTORY.Size + 100 | sizeof(IMAGE_IMPORT_DESCRIPTOR)); 101 | DWORD obDll = obTab + sizeof(DWORD_XX) * 4 * nDlls; 102 | DWORD obStr = obDll; 103 | DWORD cbNew = obStr; 104 | DWORD n; 105 | for (n = 0; n < nDlls; n++) { 106 | cbNew += PadToDword((DWORD)strlen(plpDlls[n]) + 1); 107 | } 108 | 109 | pbNew = new BYTE [cbNew]; 110 | if (pbNew == NULL) { 111 | XHOOK_TRACE(("new BYTE [cbNew] failed.\n")); 112 | goto finish; 113 | } 114 | ZeroMemory(pbNew, cbNew); 115 | 116 | PBYTE pbBase = pbModule; 117 | PBYTE pbNext = pbBase 118 | + inh.OptionalHeader.BaseOfCode 119 | + inh.OptionalHeader.SizeOfCode 120 | + inh.OptionalHeader.SizeOfInitializedData 121 | + inh.OptionalHeader.SizeOfUninitializedData; 122 | if (pbBase < pbNext) { 123 | pbBase = pbNext; 124 | } 125 | XHOOK_TRACE(("pbBase = %p\n", pbBase)); 126 | 127 | PBYTE pbNewIid = FindAndAllocateNearBase(hProcess, pbBase, cbNew); 128 | if (pbNewIid == NULL) { 129 | XHOOK_TRACE(("FindAndAllocateNearBase failed.\n")); 130 | goto finish; 131 | } 132 | 133 | DWORD obBase = (DWORD)(pbNewIid - pbModule); 134 | DWORD dwProtect = 0; 135 | if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) { 136 | // Read the old import directory if it exists. 137 | #if 0 138 | if (!VirtualProtectEx(hProcess, 139 | pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, 140 | inh.IMPORT_DIRECTORY.Size, PAGE_EXECUTE_READWRITE, &dwProtect)) { 141 | XHOOK_TRACE(("VirtualProtectEx(import) write failed: %d\n", GetLastError())); 142 | goto finish; 143 | } 144 | #endif 145 | XHOOK_TRACE(("IMPORT_DIRECTORY perms=%x\n", dwProtect)); 146 | 147 | if (!ReadProcessMemory(hProcess, 148 | pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, 149 | pbNew + obRem, 150 | inh.IMPORT_DIRECTORY.Size, NULL)) { 151 | XHOOK_TRACE(("ReadProcessMemory(imports) failed: %d\n", GetLastError())); 152 | goto finish; 153 | } 154 | } 155 | 156 | PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew; 157 | DWORD_XX *pt; 158 | 159 | for (n = 0; n < nDlls; n++) { 160 | HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]); 161 | if (FAILED(hrRet)) { 162 | XHOOK_TRACE(("StringCchCopyA failed: %d\n", GetLastError())); 163 | goto finish; 164 | } 165 | 166 | // After copying the string, we patch up the size "??" bits if any. 167 | hrRet = ReplaceOptionalSizeA((char*)pbNew + obStr, 168 | cbNew - obStr, 169 | XHOOKS_STRINGIFY(XHOOKS_BITS_XX)); 170 | if (FAILED(hrRet)) { 171 | XHOOK_TRACE(("ReplaceOptionalSizeA failed: %d\n", GetLastError())); 172 | goto finish; 173 | } 174 | 175 | DWORD nOffset = obTab + (sizeof(DWORD_XX) * (4 * n)); 176 | piid[n].OriginalFirstThunk = obBase + nOffset; 177 | pt = ((DWORD_XX*)(pbNew + nOffset)); 178 | pt[0] = IMAGE_ORDINAL_FLAG_XX + 1; 179 | pt[1] = 0; 180 | 181 | nOffset = obTab + (sizeof(DWORD_XX) * ((4 * n) + 2)); 182 | piid[n].FirstThunk = obBase + nOffset; 183 | pt = ((DWORD_XX*)(pbNew + nOffset)); 184 | pt[0] = IMAGE_ORDINAL_FLAG_XX + 1; 185 | pt[1] = 0; 186 | piid[n].TimeDateStamp = 0; 187 | piid[n].ForwarderChain = 0; 188 | piid[n].Name = obBase + obStr; 189 | 190 | obStr += PadToDword((DWORD)strlen(plpDlls[n]) + 1); 191 | } 192 | 193 | for (i = 0; i < nDlls + (inh.IMPORT_DIRECTORY.Size / sizeof(*piid)); i++) { 194 | XHOOK_TRACE(("%8d. Look=%08x Time=%08x Fore=%08x Name=%08x Addr=%08x\n", 195 | i, 196 | piid[i].OriginalFirstThunk, 197 | piid[i].TimeDateStamp, 198 | piid[i].ForwarderChain, 199 | piid[i].Name, 200 | piid[i].FirstThunk)); 201 | if (piid[i].OriginalFirstThunk == 0 && piid[i].FirstThunk == 0) { 202 | break; 203 | } 204 | } 205 | 206 | if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) { 207 | XHOOK_TRACE(("WriteProcessMemory(iid) failed: %d\n", GetLastError())); 208 | goto finish; 209 | } 210 | 211 | XHOOK_TRACE(("obBaseBef = %08x..%08x\n", 212 | inh.IMPORT_DIRECTORY.VirtualAddress, 213 | inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size)); 214 | XHOOK_TRACE(("obBaseAft = %08x..%08x\n", obBase, obBase + obStr)); 215 | 216 | // If the file doesn't have an IAT_DIRECTORY, we create it... 217 | if (inh.IAT_DIRECTORY.VirtualAddress == 0) { 218 | inh.IAT_DIRECTORY.VirtualAddress = obBase; 219 | inh.IAT_DIRECTORY.Size = cbNew; 220 | } 221 | 222 | inh.IMPORT_DIRECTORY.VirtualAddress = obBase; 223 | inh.IMPORT_DIRECTORY.Size = cbNew; 224 | 225 | /////////////////////// Update the NT header for the new import directory. 226 | /////////////////////////////// Update the DOS header to fix the checksum. 227 | // 228 | if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders, 229 | PAGE_EXECUTE_READWRITE, &dwProtect)) { 230 | XHOOK_TRACE(("VirtualProtectEx(inh) write failed: %d\n", GetLastError())); 231 | goto finish; 232 | } 233 | 234 | #if IGNORE_CHECKSUMS 235 | idh.e_res[0] = 0; 236 | #else 237 | inh.OptionalHeader.CheckSum = 0; 238 | #endif // IGNORE_CHECKSUMS 239 | 240 | if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { 241 | XHOOK_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError())); 242 | goto finish; 243 | } 244 | XHOOK_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh))); 245 | 246 | if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) { 247 | XHOOK_TRACE(("WriteProcessMemory(inh) failed: %d\n", GetLastError())); 248 | goto finish; 249 | } 250 | XHOOK_TRACE(("WriteProcessMemory(inh:%p..%p)\n", 251 | pbModule + idh.e_lfanew, 252 | pbModule + idh.e_lfanew + sizeof(inh))); 253 | 254 | #if IGNORE_CHECKSUMS 255 | WORD wDuring = ComputeChkSum(hProcess, pbModule, &inh); 256 | XHOOK_TRACE(("ChkSum: %04x + %08x => %08x\n", wDuring, dwFileSize, wDuring + dwFileSize)); 257 | 258 | idh.e_res[0] = xhook_sum_minus(idh.e_res[0], xhook_sum_minus(wDuring, wBefore)); 259 | 260 | if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { 261 | XHOOK_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError())); 262 | goto finish; 263 | } 264 | #endif // IGNORE_CHECKSUMS 265 | 266 | if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders, 267 | dwProtect, &dwProtect)) { 268 | XHOOK_TRACE(("VirtualProtectEx(idh) restore failed: %d\n", GetLastError())); 269 | goto finish; 270 | } 271 | 272 | #if IGNORE_CHECKSUMS 273 | WORD wAfter = ComputeChkSum(hProcess, pbModule, &inh); 274 | XHOOK_TRACE(("ChkSum: %04x + %08x => %08x\n", wAfter, dwFileSize, wAfter + dwFileSize)); 275 | XHOOK_TRACE(("Before: %08x, After: %08x\n", wBefore + dwFileSize, wAfter + dwFileSize)); 276 | 277 | if (wBefore != wAfter) { 278 | XHOOK_TRACE(("Restore of checksum failed %04x != %04x.\n", wBefore, wAfter)); 279 | goto finish; 280 | } 281 | #endif // IGNORE_CHECKSUMS 282 | 283 | fSucceeded = TRUE; 284 | goto finish; 285 | } 286 | 287 | -------------------------------------------------------------------------------- /src/xhook.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN64 4 | #define XHOOKS_64BIT 1 5 | #define XHOOKS_X64 1 6 | #else 7 | #define XHOOKS_32BIT 1 8 | #define XHOOKS_X86 1 9 | #endif 10 | 11 | #define XHOOKS_VERSION 10000 // 1.00.00 12 | 13 | ////////////////////////////////////////////////////////////////////////////// 14 | // 15 | 16 | #if (_MSC_VER < 1299) 17 | typedef LONG LONG_PTR; 18 | typedef ULONG ULONG_PTR; 19 | #endif 20 | 21 | #ifndef __in_z 22 | #define __in_z 23 | #endif 24 | 25 | ////////////////////////////////////////////////////////////////////////////// 26 | // 27 | #ifndef GUID_DEFINED 28 | #define GUID_DEFINED 29 | typedef struct _GUID 30 | { 31 | DWORD Data1; 32 | WORD Data2; 33 | WORD Data3; 34 | BYTE Data4[8]; 35 | } GUID; 36 | 37 | #ifdef INITGUID 38 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 39 | const GUID name \ 40 | = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } 41 | #else 42 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 43 | const GUID name 44 | #endif // INITGUID 45 | #endif // !GUID_DEFINED 46 | 47 | #if defined(__cplusplus) 48 | #ifndef _REFGUID_DEFINED 49 | #define _REFGUID_DEFINED 50 | #define REFGUID const GUID & 51 | #endif // !_REFGUID_DEFINED 52 | #else // !__cplusplus 53 | #ifndef _REFGUID_DEFINED 54 | #define _REFGUID_DEFINED 55 | #define REFGUID const GUID * const 56 | #endif // !_REFGUID_DEFINED 57 | #endif // !__cplusplus 58 | 59 | // 60 | ////////////////////////////////////////////////////////////////////////////// 61 | 62 | #ifdef __cplusplus 63 | extern "C" { 64 | #endif // __cplusplus 65 | 66 | /////////////////////////////////////////////////// Instruction Target Macros. 67 | // 68 | #define XHOOK_INSTRUCTION_TARGET_NONE ((PVOID)0) 69 | #define XHOOK_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1) 70 | #define XHOOK_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0" 71 | 72 | extern const GUID XHOOK_EXE_RESTORE_GUID; 73 | extern const GUID XHOOK_EXE_HELPER_GUID; 74 | 75 | #define XHOOK_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! 76 | typedef struct _XHOOK_TRAMPOLINE XHOOK_TRAMPOLINE, *PXHOOK_TRAMPOLINE; 77 | 78 | /////////////////////////////////////////////////////////// Binary Structures. 79 | // 80 | #pragma pack(push, 8) 81 | typedef struct _XHOOK_SECTION_HEADER 82 | { 83 | DWORD cbHeaderSize; 84 | DWORD nSignature; 85 | DWORD nDataOffset; 86 | DWORD cbDataSize; 87 | 88 | DWORD nOriginalImportVirtualAddress; 89 | DWORD nOriginalImportSize; 90 | DWORD nOriginalBoundImportVirtualAddress; 91 | DWORD nOriginalBoundImportSize; 92 | 93 | DWORD nOriginalIatVirtualAddress; 94 | DWORD nOriginalIatSize; 95 | DWORD nOriginalSizeOfImage; 96 | DWORD cbPrePE; 97 | 98 | DWORD nOriginalClrFlags; 99 | DWORD reserved1; 100 | DWORD reserved2; 101 | DWORD reserved3; 102 | 103 | // Followed by cbPrePE bytes of data. 104 | } XHOOK_SECTION_HEADER, *PXHOOK_SECTION_HEADER; 105 | 106 | typedef struct _XHOOK_SECTION_RECORD 107 | { 108 | DWORD cbBytes; 109 | DWORD nReserved; 110 | GUID guid; 111 | } XHOOK_SECTION_RECORD, *PXHOOK_SECTION_RECORD; 112 | 113 | typedef struct _XHOOK_CLR_HEADER 114 | { 115 | // Header versioning 116 | ULONG cb; 117 | USHORT MajorRuntimeVersion; 118 | USHORT MinorRuntimeVersion; 119 | 120 | // Symbol table and startup information 121 | IMAGE_DATA_DIRECTORY MetaData; 122 | ULONG Flags; 123 | 124 | // Followed by the rest of the IMAGE_COR20_HEADER 125 | } XHOOK_CLR_HEADER, *PXHOOK_CLR_HEADER; 126 | 127 | typedef struct _XHOOK_EXE_RESTORE 128 | { 129 | DWORD cb; 130 | DWORD cbidh; 131 | DWORD cbinh; 132 | DWORD cbclr; 133 | 134 | PBYTE pidh; 135 | PBYTE pinh; 136 | PBYTE pclr; 137 | 138 | IMAGE_DOS_HEADER idh; 139 | union { 140 | IMAGE_NT_HEADERS inh; 141 | IMAGE_NT_HEADERS32 inh32; 142 | IMAGE_NT_HEADERS64 inh64; 143 | BYTE raw[sizeof(IMAGE_NT_HEADERS64) + 144 | sizeof(IMAGE_SECTION_HEADER) * 32]; 145 | }; 146 | XHOOK_CLR_HEADER clr; 147 | 148 | } XHOOK_EXE_RESTORE, *PXHOOK_EXE_RESTORE; 149 | 150 | typedef struct _XHOOK_EXE_HELPER 151 | { 152 | DWORD cb; 153 | DWORD pid; 154 | CHAR DllName[MAX_PATH]; 155 | 156 | } XHOOK_EXE_HELPER, *PXHOOK_EXE_HELPER; 157 | 158 | #pragma pack(pop) 159 | 160 | #define XHOOK_SECTION_HEADER_DECLARE(cbSectionSize) \ 161 | { \ 162 | sizeof(XHOOK_SECTION_HEADER),\ 163 | XHOOK_SECTION_HEADER_SIGNATURE,\ 164 | sizeof(XHOOK_SECTION_HEADER),\ 165 | (cbSectionSize),\ 166 | \ 167 | 0,\ 168 | 0,\ 169 | 0,\ 170 | 0,\ 171 | \ 172 | 0,\ 173 | 0,\ 174 | 0,\ 175 | 0,\ 176 | } 177 | 178 | /////////////////////////////////////////////////////////////// Helper Macros. 179 | // 180 | #define XHOOKS_STRINGIFY(x) XHOOKS_STRINGIFY_(x) 181 | #define XHOOKS_STRINGIFY_(x) #x 182 | 183 | ///////////////////////////////////////////////////////////// Binary Typedefs. 184 | // 185 | typedef BOOL(CALLBACK *PF_XHOOK_BINARY_BYWAY_CALLBACK)(PVOID pContext, 186 | PCHAR pszFile, 187 | PCHAR *ppszOutFile); 188 | 189 | typedef BOOL(CALLBACK *PF_XHOOK_BINARY_FILE_CALLBACK)(PVOID pContext, 190 | PCHAR pszOrigFile, 191 | PCHAR pszFile, 192 | PCHAR *ppszOutFile); 193 | 194 | typedef BOOL(CALLBACK *PF_XHOOK_BINARY_SYMBOL_CALLBACK)(PVOID pContext, 195 | ULONG nOrigOrdinal, 196 | ULONG nOrdinal, 197 | ULONG *pnOutOrdinal, 198 | PCHAR pszOrigSymbol, 199 | PCHAR pszSymbol, 200 | PCHAR *ppszOutSymbol); 201 | 202 | typedef BOOL(CALLBACK *PF_XHOOK_BINARY_COMMIT_CALLBACK)(PVOID pContext); 203 | 204 | typedef BOOL(CALLBACK *PF_XHOOK_ENUMERATE_EXPORT_CALLBACK)(PVOID pContext, 205 | ULONG nOrdinal, 206 | PCHAR pszName, 207 | PVOID pCode); 208 | 209 | typedef BOOL(CALLBACK *PF_XHOOK_IMPORT_FILE_CALLBACK)(PVOID pContext, 210 | HMODULE hModule, 211 | PCSTR pszFile); 212 | 213 | typedef BOOL(CALLBACK *PF_XHOOK_IMPORT_FUNC_CALLBACK)(PVOID pContext, 214 | DWORD nOrdinal, 215 | PCSTR pszFunc, 216 | PVOID pvFunc); 217 | 218 | typedef VOID * PXHOOK_BINARY; 219 | typedef VOID * PXHOOK_LOADED_BINARY; 220 | 221 | //////////////////////////////////////////////////////////// Transaction APIs. 222 | // 223 | LONG WINAPI XHookTransactionBegin(VOID); 224 | LONG WINAPI XHookTransactionAbort(VOID); 225 | LONG WINAPI XHookTransactionCommit(VOID); 226 | LONG WINAPI XHookTransactionCommitEx(PVOID **pppFailedPointer); 227 | 228 | LONG WINAPI XHookUpdateThread(HANDLE hThread); 229 | 230 | LONG WINAPI XHookAttach(PVOID *ppPointer, 231 | PVOID pXHook); 232 | 233 | LONG WINAPI XHookAttachEx(PVOID *ppPointer, 234 | PVOID pXHook, 235 | PXHOOK_TRAMPOLINE *ppRealTrampoline, 236 | PVOID *ppRealTarget, 237 | PVOID *ppRealXHook); 238 | 239 | LONG WINAPI XHookDetach(PVOID *ppPointer, 240 | PVOID pXHook); 241 | 242 | BOOL WINAPI XHookSetIgnoreTooSmall(BOOL fIgnore); 243 | BOOL WINAPI XHookSetRetainRegions(BOOL fRetain); 244 | 245 | ////////////////////////////////////////////////////////////// Code Functions. 246 | // 247 | PVOID WINAPI XHookFindFunction(PCSTR pszModule, PCSTR pszFunction); 248 | PVOID WINAPI XHookCodeFromPointer(PVOID pPointer, PVOID *ppGlobals); 249 | PVOID WINAPI XHookCopyInstruction(PVOID pDst, 250 | PVOID *pDstPool, 251 | PVOID pSrc, 252 | PVOID *ppTarget, 253 | LONG *plExtra); 254 | 255 | ///////////////////////////////////////////////////// Loaded Binary Functions. 256 | // 257 | HMODULE WINAPI XHookGetContainingModule(PVOID pvAddr); 258 | HMODULE WINAPI XHookEnumerateModules(HMODULE hModuleLast); 259 | PVOID WINAPI XHookGetEntryPoint(HMODULE hModule); 260 | ULONG WINAPI XHookGetModuleSize(HMODULE hModule); 261 | BOOL WINAPI XHookEnumerateExports(HMODULE hModule, 262 | PVOID pContext, 263 | PF_XHOOK_ENUMERATE_EXPORT_CALLBACK pfExport); 264 | BOOL WINAPI XHookEnumerateImports(HMODULE hModule, 265 | PVOID pContext, 266 | PF_XHOOK_IMPORT_FILE_CALLBACK pfImportFile, 267 | PF_XHOOK_IMPORT_FUNC_CALLBACK pfImportFunc); 268 | 269 | PVOID WINAPI XHookFindPayload(HMODULE hModule, REFGUID rguid, DWORD *pcbData); 270 | PVOID WINAPI XHookFindPayloadEx(REFGUID rguid, DWORD * pcbData); 271 | DWORD WINAPI XHookGetSizeOfPayloads(HMODULE hModule); 272 | 273 | ///////////////////////////////////////////////// Persistent Binary Functions. 274 | // 275 | 276 | PXHOOK_BINARY WINAPI XHookBinaryOpen(HANDLE hFile); 277 | PVOID WINAPI XHookBinaryEnumeratePayloads(PXHOOK_BINARY pBinary, 278 | GUID *pGuid, 279 | DWORD *pcbData, 280 | DWORD *pnIterator); 281 | PVOID WINAPI XHookBinaryFindPayload(PXHOOK_BINARY pBinary, 282 | REFGUID rguid, 283 | DWORD *pcbData); 284 | PVOID WINAPI XHookBinarySetPayload(PXHOOK_BINARY pBinary, 285 | REFGUID rguid, 286 | PVOID pData, 287 | DWORD cbData); 288 | BOOL WINAPI XHookBinaryDeletePayload(PXHOOK_BINARY pBinary, REFGUID rguid); 289 | BOOL WINAPI XHookBinaryPurgePayloads(PXHOOK_BINARY pBinary); 290 | BOOL WINAPI XHookBinaryResetImports(PXHOOK_BINARY pBinary); 291 | BOOL WINAPI XHookBinaryEditImports(PXHOOK_BINARY pBinary, 292 | PVOID pContext, 293 | PF_XHOOK_BINARY_BYWAY_CALLBACK pfByway, 294 | PF_XHOOK_BINARY_FILE_CALLBACK pfFile, 295 | PF_XHOOK_BINARY_SYMBOL_CALLBACK pfSymbol, 296 | PF_XHOOK_BINARY_COMMIT_CALLBACK pfCommit); 297 | BOOL WINAPI XHookBinaryWrite(PXHOOK_BINARY pBinary, HANDLE hFile); 298 | BOOL WINAPI XHookBinaryClose(PXHOOK_BINARY pBinary); 299 | 300 | /////////////////////////////////////////////////// Create Process & Load Dll. 301 | // 302 | typedef BOOL(WINAPI *PXHOOK_CREATE_PROCESS_ROUTINEA) 303 | (LPCSTR lpApplicationName, 304 | LPSTR lpCommandLine, 305 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 306 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 307 | BOOL bInheritHandles, 308 | DWORD dwCreationFlags, 309 | LPVOID lpEnvironment, 310 | LPCSTR lpCurrentDirectory, 311 | LPSTARTUPINFOA lpStartupInfo, 312 | LPPROCESS_INFORMATION lpProcessInformation); 313 | 314 | typedef BOOL(WINAPI *PXHOOK_CREATE_PROCESS_ROUTINEW) 315 | (LPCWSTR lpApplicationName, 316 | LPWSTR lpCommandLine, 317 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 318 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 319 | BOOL bInheritHandles, 320 | DWORD dwCreationFlags, 321 | LPVOID lpEnvironment, 322 | LPCWSTR lpCurrentDirectory, 323 | LPSTARTUPINFOW lpStartupInfo, 324 | LPPROCESS_INFORMATION lpProcessInformation); 325 | 326 | BOOL WINAPI XHookCreateProcessWithDllA(LPCSTR lpApplicationName, 327 | __in_z LPSTR lpCommandLine, 328 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 329 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 330 | BOOL bInheritHandles, 331 | DWORD dwCreationFlags, 332 | LPVOID lpEnvironment, 333 | LPCSTR lpCurrentDirectory, 334 | LPSTARTUPINFOA lpStartupInfo, 335 | LPPROCESS_INFORMATION lpProcessInformation, 336 | LPCSTR lpDllName, 337 | PXHOOK_CREATE_PROCESS_ROUTINEA 338 | pfCreateProcessA); 339 | 340 | BOOL WINAPI XHookCreateProcessWithDllW(LPCWSTR lpApplicationName, 341 | __in_z LPWSTR lpCommandLine, 342 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 343 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 344 | BOOL bInheritHandles, 345 | DWORD dwCreationFlags, 346 | LPVOID lpEnvironment, 347 | LPCWSTR lpCurrentDirectory, 348 | LPSTARTUPINFOW lpStartupInfo, 349 | LPPROCESS_INFORMATION lpProcessInformation, 350 | LPCSTR lpDllName, 351 | PXHOOK_CREATE_PROCESS_ROUTINEW 352 | pfCreateProcessW); 353 | 354 | #ifdef UNICODE 355 | #define XHookCreateProcessWithDll XHookCreateProcessWithDllW 356 | #define PXHOOK_CREATE_PROCESS_ROUTINE PXHOOK_CREATE_PROCESS_ROUTINEW 357 | #else 358 | #define XHookCreateProcessWithDll XHookCreateProcessWithDllA 359 | #define PXHOOK_CREATE_PROCESS_ROUTINE PXHOOK_CREATE_PROCESS_ROUTINEA 360 | #endif // !UNICODE 361 | 362 | BOOL WINAPI XHookCreateProcessWithDllExA(LPCSTR lpApplicationName, 363 | __in_z LPSTR lpCommandLine, 364 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 365 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 366 | BOOL bInheritHandles, 367 | DWORD dwCreationFlags, 368 | LPVOID lpEnvironment, 369 | LPCSTR lpCurrentDirectory, 370 | LPSTARTUPINFOA lpStartupInfo, 371 | LPPROCESS_INFORMATION lpProcessInformation, 372 | LPCSTR lpDllName, 373 | PXHOOK_CREATE_PROCESS_ROUTINEA 374 | pfCreateProcessA); 375 | 376 | BOOL WINAPI XHookCreateProcessWithDllExW(LPCWSTR lpApplicationName, 377 | __in_z LPWSTR lpCommandLine, 378 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 379 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 380 | BOOL bInheritHandles, 381 | DWORD dwCreationFlags, 382 | LPVOID lpEnvironment, 383 | LPCWSTR lpCurrentDirectory, 384 | LPSTARTUPINFOW lpStartupInfo, 385 | LPPROCESS_INFORMATION lpProcessInformation, 386 | LPCSTR lpDllName, 387 | PXHOOK_CREATE_PROCESS_ROUTINEW 388 | pfCreateProcessW); 389 | 390 | #ifdef UNICODE 391 | #define XHookCreateProcessWithDllEx XHookCreateProcessWithDllExW 392 | #define PXHOOK_CREATE_PROCESS_ROUTINE PXHOOK_CREATE_PROCESS_ROUTINEW 393 | #else 394 | #define XHookCreateProcessWithDllEx XHookCreateProcessWithDllExA 395 | #define PXHOOK_CREATE_PROCESS_ROUTINE PXHOOK_CREATE_PROCESS_ROUTINEA 396 | #endif // !UNICODE 397 | 398 | BOOL WINAPI XHookProcessViaHelperA(DWORD dwTargetPid, 399 | LPCSTR lpDllName, 400 | PXHOOK_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 401 | 402 | BOOL WINAPI XHookProcessViaHelperW(DWORD dwTargetPid, 403 | LPCSTR lpDllName, 404 | PXHOOK_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 405 | 406 | #ifdef UNICODE 407 | #define XHookProcessViaHelper XHookProcessViaHelperW 408 | #else 409 | #define XHookProcessViaHelper XHookProcessViaHelperA 410 | #endif // !UNICODE 411 | 412 | BOOL WINAPI XHookUpdateProcessWithDll(HANDLE hProcess, 413 | LPCSTR *plpDlls, 414 | DWORD nDlls); 415 | 416 | BOOL WINAPI XHookCopyPayloadToProcess(HANDLE hProcess, 417 | REFGUID rguid, 418 | PVOID pvData, 419 | DWORD cbData); 420 | BOOL WINAPI XHookRestoreAfterWith(VOID); 421 | BOOL WINAPI XHookRestoreAfterWithEx(PVOID pvData, DWORD cbData); 422 | BOOL WINAPI XHookIsHelperProcess(VOID); 423 | VOID CALLBACK XHookFinishHelperProcess(HWND, HINSTANCE, LPSTR, INT); 424 | 425 | // 426 | ////////////////////////////////////////////////////////////////////////////// 427 | #ifdef __cplusplus 428 | } 429 | #endif // __cplusplus 430 | 431 | //////////////////////////////////////////////// XHooks Internal Definitions. 432 | // 433 | #ifdef __cplusplus 434 | #ifdef XHOOKS_INTERNAL 435 | 436 | #ifndef __deref_out 437 | #define __deref_out 438 | #endif 439 | 440 | #ifndef __deref 441 | #define __deref 442 | #endif 443 | 444 | ////////////////////////////////////////////////////////////////////////////// 445 | // 446 | #if (_MSC_VER < 1299) 447 | #include 448 | typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; 449 | typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; 450 | typedef IMAGEHLP_SYMBOL SYMBOL_INFO; 451 | typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO; 452 | 453 | static inline 454 | LONG InterlockedCompareExchange(LONG *ptr, LONG nval, LONG oval) 455 | { 456 | return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval); 457 | } 458 | #else 459 | #include 460 | #endif 461 | 462 | #ifdef IMAGEAPI // defined by DBGHELP.H 463 | typedef LPAPI_VERSION(NTAPI *PF_ImagehlpApiVersionEx)(LPAPI_VERSION AppVersion); 464 | 465 | typedef BOOL(NTAPI *PF_SymInitialize)(IN HANDLE hProcess, 466 | IN LPCSTR UserSearchPath, 467 | IN BOOL fInvadeProcess); 468 | typedef DWORD(NTAPI *PF_SymSetOptions)(IN DWORD SymOptions); 469 | typedef DWORD(NTAPI *PF_SymGetOptions)(VOID); 470 | typedef DWORD64(NTAPI *PF_SymLoadModule64)(IN HANDLE hProcess, 471 | IN HANDLE hFile, 472 | IN PSTR ImageName, 473 | IN PSTR ModuleName, 474 | IN DWORD64 BaseOfDll, 475 | IN DWORD SizeOfDll); 476 | typedef BOOL(NTAPI *PF_SymGetModuleInfo64)(IN HANDLE hProcess, 477 | IN DWORD64 qwAddr, 478 | OUT PIMAGEHLP_MODULE64 ModuleInfo); 479 | typedef BOOL(NTAPI *PF_SymFromName)(IN HANDLE hProcess, 480 | IN LPSTR Name, 481 | OUT PSYMBOL_INFO Symbol); 482 | 483 | typedef struct _XHOOK_SYM_INFO 484 | { 485 | HANDLE hProcess; 486 | HMODULE hDbgHelp; 487 | PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx; 488 | PF_SymInitialize pfSymInitialize; 489 | PF_SymSetOptions pfSymSetOptions; 490 | PF_SymGetOptions pfSymGetOptions; 491 | PF_SymLoadModule64 pfSymLoadModule64; 492 | PF_SymGetModuleInfo64 pfSymGetModuleInfo64; 493 | PF_SymFromName pfSymFromName; 494 | } XHOOK_SYM_INFO, *PXHOOK_SYM_INFO; 495 | 496 | PXHOOK_SYM_INFO XHookLoadDbgHelp(VOID); 497 | 498 | #endif // IMAGEAPI 499 | 500 | #ifndef XHOOK_TRACE 501 | #if XHOOK_DEBUG 502 | #define XHOOK_TRACE(x) printf x 503 | #define XHOOK_BREAK() __debugbreak() 504 | #include 505 | #include 506 | #else 507 | #define XHOOK_TRACE(x) 508 | #define XHOOK_BREAK() 509 | #endif 510 | #endif 511 | 512 | #ifdef XHOOKS_IA64 513 | __declspec(align(16)) struct XHOOK_IA64_BUNDLE 514 | { 515 | public: 516 | union 517 | { 518 | BYTE data[16]; 519 | UINT64 wide[2]; 520 | }; 521 | 522 | public: 523 | struct XHOOK_IA64_METADATA; 524 | 525 | typedef BOOL(XHOOK_IA64_BUNDLE::* XHOOK_IA64_METACOPY) 526 | (const XHOOK_IA64_METADATA *pMeta, XHOOK_IA64_BUNDLE *pDst) const; 527 | 528 | enum { 529 | A_UNIT = 1u, 530 | I_UNIT = 2u, 531 | M_UNIT = 3u, 532 | B_UNIT = 4u, 533 | F_UNIT = 5u, 534 | L_UNIT = 6u, 535 | X_UNIT = 7u, 536 | UNIT_MASK = 7u, 537 | STOP = 8u 538 | }; 539 | struct XHOOK_IA64_METADATA 540 | { 541 | ULONG nTemplate : 8; // Instruction template. 542 | ULONG nUnit0 : 4; // Unit for slot 0 543 | ULONG nUnit1 : 4; // Unit for slot 1 544 | ULONG nUnit2 : 4; // Unit for slot 2 545 | XHOOK_IA64_METACOPY pfCopy; // Function pointer. 546 | }; 547 | 548 | protected: 549 | BOOL CopyBytes(const XHOOK_IA64_METADATA *pMeta, XHOOK_IA64_BUNDLE *pDst) const; 550 | BOOL CopyBytesMMB(const XHOOK_IA64_METADATA *pMeta, XHOOK_IA64_BUNDLE *pDst) const; 551 | BOOL CopyBytesMBB(const XHOOK_IA64_METADATA *pMeta, XHOOK_IA64_BUNDLE *pDst) const; 552 | BOOL CopyBytesBBB(const XHOOK_IA64_METADATA *pMeta, XHOOK_IA64_BUNDLE *pDst) const; 553 | BOOL CopyBytesMLX(const XHOOK_IA64_METADATA *pMeta, XHOOK_IA64_BUNDLE *pDst) const; 554 | 555 | static const XHOOK_IA64_METADATA s_rceCopyTable[33]; 556 | 557 | public: 558 | // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0 559 | // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0. 560 | 561 | // 00 562 | // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0. 563 | // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0] 564 | // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5] 565 | // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42] 566 | // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46] 567 | // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83] 568 | // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87] 569 | // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124] 570 | BYTE GetTemplate() const; 571 | BYTE GetInst0() const; 572 | BYTE GetInst1() const; 573 | BYTE GetInst2() const; 574 | BYTE GetUnit0() const; 575 | BYTE GetUnit1() const; 576 | BYTE GetUnit2() const; 577 | UINT64 GetData0() const; 578 | UINT64 GetData1() const; 579 | UINT64 GetData2() const; 580 | 581 | public: 582 | BOOL IsBrl() const; 583 | VOID SetBrl(); 584 | VOID SetBrl(UINT64 target); 585 | UINT64 GetBrlTarget() const; 586 | VOID SetBrlTarget(UINT64 target); 587 | VOID SetBrlImm(UINT64 imm); 588 | UINT64 GetBrlImm() const; 589 | 590 | BOOL IsMovlGp() const; 591 | UINT64 GetMovlGp() const; 592 | VOID SetMovlGp(UINT64 gp); 593 | 594 | VOID SetInst0(BYTE nInst); 595 | VOID SetInst1(BYTE nInst); 596 | VOID SetInst2(BYTE nInst); 597 | VOID SetData0(UINT64 nData); 598 | VOID SetData1(UINT64 nData); 599 | VOID SetData2(UINT64 nData); 600 | BOOL SetNop0(); 601 | BOOL SetNop1(); 602 | BOOL SetNop2(); 603 | BOOL SetStop(); 604 | 605 | BOOL Copy(XHOOK_IA64_BUNDLE *pDst) const; 606 | }; 607 | #endif // XHOOKS_IA64 608 | 609 | //#ifdef XHOOKS_ARM 610 | //#error Feature not supported in this release. 611 | 612 | 613 | 614 | //#endif // XHOOKS_ARM 615 | 616 | ////////////////////////////////////////////////////////////////////////////// 617 | 618 | #endif // XHOOKS_INTERNAL 619 | #endif // __cplusplus 620 | 621 | 622 | #ifndef XHOOKS_STRINGIFY 623 | #define XHOOKS_STRINGIFY(x) XHOOKS_STRINGIFY_(x) 624 | #define XHOOKS_STRINGIFY_(x) #x 625 | #endif 626 | 627 | #define VER_FILEFLAGSMASK 0x3fL 628 | #define VER_FILEFLAGS 0x0L 629 | #define VER_FILEOS 0x00040004L 630 | #define VER_FILETYPE 0x00000002L 631 | #define VER_FILESUBTYPE 0x00000000L 632 | 633 | #define VER_XHOOKS_BITS XHOOK_STRINGIFY(XHOOKS_BITS) 634 | 635 | --------------------------------------------------------------------------------