├── README.md ├── RegHook.cpp ├── RegHook.h ├── RegHookEx.sln ├── RegHookEx.vcxproj └── fde ├── fde64.asm ├── fde64.h └── fde64.obj /README.md: -------------------------------------------------------------------------------- 1 | # RegHook/RegHookEx 2 | 3 | RegHook is a way of creating your own pointers, copied from registers in a function. 4 | RegHook is for **internal** usage, RegHookEx is for **externals**. 5 | 6 | More specificly, it's a midfunction hooking library, who's purpose is 7 | to retrieve register data at any particular point in a process. 8 | 9 | ### Sample: 10 | 11 | ```c++ 12 | RegHook AngleFuncHook(OFFSET_VIEWANGLEFUNC); 13 | ((ViewAngle*)AngleFuncHook.GetRegDump().RBX)->Pitch = 0; 14 | ``` 15 | 16 | `regHook.GetRegDump()` returns a `RegDump` class. 17 | ```c++ 18 | class RegDump 19 | { 20 | public: 21 | char pad_0000[160]; //0x0000 22 | DWORD_PTR R15; //0x00A0 23 | DWORD_PTR R14; //0x00A8 24 | DWORD_PTR R13; //0x00B0 25 | DWORD_PTR R12; //0x00B8 26 | DWORD_PTR R11; //0x00C0 27 | DWORD_PTR R10; //0x00C8 28 | DWORD_PTR R9; //0x00D0 29 | DWORD_PTR R8; //0x00D8 30 | DWORD_PTR RDI; //0x00E0 31 | DWORD_PTR RSI; //0x00E8 32 | DWORD_PTR RSP; //0x00F0 33 | DWORD_PTR RBP; //0x00F8 34 | DWORD_PTR RDX; //0x0100 35 | DWORD_PTR RCX; //0x0108 36 | DWORD_PTR RBX; //0x0110 37 | DWORD_PTR RAX; //0x0118 38 | }; 39 | ``` 40 | 41 | ## Usage 42 | 43 | ###### Internal 44 | ```c++ 45 | RegHook AngleFuncHook(OFFSET_VIEWANGLEFUNC); 46 | if (IsValidPtr((LPVOID)AngleFuncHook.GetRegDump().RBX)) { 47 | ((ViewAngle*)AngleFuncHook.GetRegDump().RBX)->Pitch = 0; 48 | ((ViewAngle*)AngleFuncHook.GetRegDump().RBX)->Yaw = 0; 49 | } 50 | 51 | ``` 52 | 53 | ##### External 54 | ```c++ 55 | RegHookEx AngleFuncHook(rpm.hProcess, OFFSET_VIEWANGLEFUNC); 56 | if (rpm.read(AngleFuncHook.GetAddressOfHook()).RBX != 0) { 57 | //Read 58 | ViewAngle pViewAngle = rpm.read(AngleFuncHook.GetRegDump().RBX); 59 | //pViewAngle.Yaw, pViewAngle.Pitch 60 | //Write 61 | RegDump pRegDump = rpm.read(AngleFuncHook.GetAddressOfHook()); 62 | rpm.write(pRegDump.RBX + offsetof(ViewAngle, ViewAngle::Yaw), 0); 63 | rpm.write(pRegDump.RBX + offsetof(ViewAngle, ViewAngle::Pitch), 0); 64 | } 65 | ``` 66 | 67 | #### fde64 68 | 69 | The hook takes 16 bytes to write, and requires RAX to be used for the call. 70 | I'm using [fde64](https://github.com/GiveMeZeny/fde64/) for length dissasembly, 71 | so the nearest instruction end after 16 is located automaticlly. 72 | 73 | #### Original Function 74 | Here is the function with RegHookEx installed. 75 | 76 | ![](https://s31.postimg.cc/nw0ffmqkr/image.png) 77 | 78 | The first thing that happens, is some memory is allocated for the hooked function. 79 | This is where program flow will be redirected to temporarily. 80 | 81 | ```nasm 82 | push rax 83 | movabs rax, jump location 84 | xchg [rsp], rax 85 | ret 86 | ``` 87 | 88 | This takes up 16 bytes. Any unused bytes must be NOP'd, in this example none need 89 | to be since the function we're overwriting already is 16 bytes. 90 | 91 | #### Hooked Function 92 | Now at the hooked function: 93 | 94 | ![](https://s31.postimg.cc/l377vg5m3/image.png) 95 | 96 | 97 | The next 17 bytes have been copied from the original function, 98 | and placed here. The target process doesn't know this ever happened. 99 | 100 | 101 | This is followed by a shitload of NOPs. This allows for all 102 | instructions to get hooked (up to 15 bytes, aka max). 103 | 104 | #### RIP Relative Addressing 105 | 106 | ![](https://s31.postimg.cc/h6tvzoxjv/image.png) 107 | 108 | Writing all of these manually would be a pain, so I'm using relative 109 | addressing. I'm writing it by: 110 | 111 | ```nasm 112 | mov[rip + 0xf3], rax 113 | mov[rip + 0xe4], rbx 114 | mov[rip + 0xd5], rcx 115 | mov[rip + 0xc6], rdx 116 | mov[rip + 0xb7], rbp 117 | mov[rip + 0xa8], rsp 118 | mov[rip + 0x99], rsi 119 | mov[rip + 0x8a], rdi 120 | mov[rip + 0x7b], r8 121 | mov[rip + 0x6c], r9 122 | mov[rip + 0x5d], r10 123 | mov[rip + 0x4e], r11 124 | mov[rip + 0x3f], r12 125 | mov[rip + 0x30], r13 126 | mov[rip + 0x21], r14 127 | mov[rip + 0x12], r15 128 | ``` 129 | 130 | This accounts for the `RET`, as well as the misalignment of 131 | the class, thus re-aligning it to the 8'th byte. 132 | 133 | #### Optimization 134 | 135 | Due to the wonders of the RIP register, I only need to write one 136 | address into the hooked function for it to work. The hook itself 137 | requires two in order to preserve RAX. You no longer need to specify 138 | a length for RegHookEx to work, that is done for you too. 139 | 140 | 141 | #### Full Shellcode 142 | 143 | The Hooked Function allocated in memory: 144 | 145 | ```c++ 146 | // shellcode for the hkedfunc 147 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nop ; * min_size*instruction_max 148 | 0x48, 0x89, 0x05, 0xF3, 0x00, 0x00, 0x00, // mov[rip + 0xf3], rax 149 | 0x48, 0x89, 0x1D, 0xE4, 0x00, 0x00, 0x00, // mov[rip + 0xe4], rbx 150 | 0x48, 0x89, 0x0D, 0xD5, 0x00, 0x00, 0x00, // mov[rip + 0xd5], rcx 151 | 0x48, 0x89, 0x15, 0xC6, 0x00, 0x00, 0x00, // mov[rip + 0xc6], rdx 152 | 0x48, 0x89, 0x2D, 0xB7, 0x00, 0x00, 0x00, // mov[rip + 0xb7], rbp 153 | 0x48, 0x89, 0x25, 0xA8, 0x00, 0x00, 0x00, // mov[rip + 0xa8], rsp 154 | 0x48, 0x89, 0x35, 0x99, 0x00, 0x00, 0x00, // mov[rip + 0x99], rsi 155 | 0x48, 0x89, 0x3D, 0x8A, 0x00, 0x00, 0x00, // mov[rip + 0x8a], rdi 156 | 0x4C, 0x89, 0x05, 0x7B, 0x00, 0x00, 0x00, // mov[rip + 0x7b], r8 157 | 0x4C, 0x89, 0x0D, 0x6C, 0x00, 0x00, 0x00, // mov[rip + 0x6c], r9 158 | 0x4C, 0x89, 0x15, 0x5D, 0x00, 0x00, 0x00, // mov[rip + 0x5d], r10 159 | 0x4C, 0x89, 0x1D, 0x4E, 0x00, 0x00, 0x00, // mov[rip + 0x4e], r11 160 | 0x4C, 0x89, 0x25, 0x3F, 0x00, 0x00, 0x00, // mov[rip + 0x3f], r12 161 | 0x4C, 0x89, 0x2D, 0x30, 0x00, 0x00, 0x00, // mov[rip + 0x30], r13 162 | 0x4C, 0x89, 0x35, 0x21, 0x00, 0x00, 0x00, // mov[rip + 0x21], r14 163 | 0x4C, 0x89, 0x3D, 0x12, 0x00, 0x00, 0x00, // mov[rip + 0x12], r15 164 | 0x50, // push rax 165 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, FuncAddress + lengthOfInstructions 166 | 0x48, 0x87, 0x04, 0x24, // xchg [rsp], rax 167 | 0xC3 // ret 168 | ``` 169 | 170 | The hook: 171 | 172 | ```c++ 173 | 0x50, // push rax 174 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // movabs rax, jump location 175 | 0x48, 0x87, 0x04, 0x24, // xchg [rsp], rax 176 | 0xC3, // ret 177 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 178 | ``` 179 | 180 | ## Unhooking 181 | 182 | Unhooking can be done in two different ways. 183 | 1. Per-class 184 | 2. With the static method 185 | 3. Using the static method on exit 186 | 187 | ##### Per-class unhooking: 188 | 189 | Unhooks and repairs the original function. 190 | 191 | ```c++ 192 | AngleFuncHook.DestroyHook(); 193 | ``` 194 | 195 | ##### Static Method: 196 | 197 | Unhooks and repairs original functions of all active instances of RegHookEx. 198 | 199 | ```c++ 200 | RegHookEx::DestroyAllHooks(); 201 | ``` 202 | 203 | ##### Automated Unhooking: 204 | 205 | Use this for externals to Unhook whenever you exit the console. 206 | 207 | ```c++ 208 | bool ctrlh(DWORD event) 209 | { 210 | if (event == CTRL_CLOSE_EVENT) { 211 | std::cout << "Deleting All Hooks" << std::endl; 212 | RegHookEx::DestroyAllHooks(); 213 | return TRUE; 214 | } 215 | return FALSE; 216 | } 217 | 218 | void main() { 219 | SetConsoleCtrlHandler((PHANDLER_ROUTINE)(ctrlh), TRUE); 220 | // your stuff 221 | } 222 | ``` 223 | 224 | For internals, you can call the static function in your DllMain. 225 | ```c++ 226 | BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwAttached, LPVOID lpvReserved) 227 | { 228 | if (dwAttached == DLL_PROCESS_ATTACH) { 229 | //... 230 | } 231 | if (dwAttached == DLL_PROCESS_DETACH) { 232 | RegHook::DestroyAllHooks(); 233 | FreeConsole(); 234 | } 235 | return 1; 236 | } 237 | ``` 238 | -------------------------------------------------------------------------------- /RegHook.cpp: -------------------------------------------------------------------------------- 1 | #include "RegHook.h" 2 | #include "fde\fde64.h" 3 | 4 | class RegHookShared { 5 | public: 6 | static size_t min_size; 7 | static byte* hkpatch; 8 | static byte* funcpatch; 9 | const static SIZE_T hkpatch_size; 10 | const static SIZE_T funcpatch_size; 11 | static size_t GetInstructionLength(void*); 12 | const static size_t instruction_max; 13 | }; 14 | 15 | size_t RegHookShared::GetInstructionLength(void* buff) { 16 | void *ptr = (void*)buff; 17 | fde64s cmd; 18 | decode(ptr, &cmd); 19 | ptr = (void *)((uintptr_t)ptr + cmd.len); 20 | return cmd.len; 21 | } 22 | 23 | size_t RegHookShared::min_size = 16; 24 | const size_t RegHookShared::instruction_max = 15; 25 | 26 | const size_t RegHookShared::hkpatch_size = 158; 27 | byte* RegHookShared::hkpatch = new byte[RegHookShared::hkpatch_size]{ 28 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nop ; * min_size*instruction_max 29 | 0x48, 0x89, 0x05, 0xF3, 0x00, 0x00, 0x00, // mov[rip + 0xf3], rax 30 | 0x48, 0x89, 0x1D, 0xE4, 0x00, 0x00, 0x00, // mov[rip + 0xe4], rbx 31 | 0x48, 0x89, 0x0D, 0xD5, 0x00, 0x00, 0x00, // mov[rip + 0xd5], rcx 32 | 0x48, 0x89, 0x15, 0xC6, 0x00, 0x00, 0x00, // mov[rip + 0xc6], rdx 33 | 0x48, 0x89, 0x2D, 0xB7, 0x00, 0x00, 0x00, // mov[rip + 0xb7], rbp 34 | 0x48, 0x89, 0x25, 0xA8, 0x00, 0x00, 0x00, // mov[rip + 0xa8], rsp 35 | 0x48, 0x89, 0x35, 0x99, 0x00, 0x00, 0x00, // mov[rip + 0x99], rsi 36 | 0x48, 0x89, 0x3D, 0x8A, 0x00, 0x00, 0x00, // mov[rip + 0x8a], rdi 37 | 0x4C, 0x89, 0x05, 0x7B, 0x00, 0x00, 0x00, // mov[rip + 0x7b], r8 38 | 0x4C, 0x89, 0x0D, 0x6C, 0x00, 0x00, 0x00, // mov[rip + 0x6c], r9 39 | 0x4C, 0x89, 0x15, 0x5D, 0x00, 0x00, 0x00, // mov[rip + 0x5d], r10 40 | 0x4C, 0x89, 0x1D, 0x4E, 0x00, 0x00, 0x00, // mov[rip + 0x4e], r11 41 | 0x4C, 0x89, 0x25, 0x3F, 0x00, 0x00, 0x00, // mov[rip + 0x3f], r12 42 | 0x4C, 0x89, 0x2D, 0x30, 0x00, 0x00, 0x00, // mov[rip + 0x30], r13 43 | 0x4C, 0x89, 0x35, 0x21, 0x00, 0x00, 0x00, // mov[rip + 0x21], r14 44 | 0x4C, 0x89, 0x3D, 0x12, 0x00, 0x00, 0x00, // mov[rip + 0x12], r15 45 | 0x50, // push rax 46 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, FuncAddress + lengthOfInstructions 47 | 0x48, 0x87, 0x04, 0x24, // xchg [rsp], rax 48 | 0xC3 // ret 49 | }; 50 | 51 | const size_t RegHookShared::funcpatch_size = 31; 52 | byte* RegHookShared::funcpatch = new byte[RegHookShared::funcpatch_size]{ 53 | 0x50, // push rax 54 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // movabs rax, jump location 55 | 0x48, 0x87, 0x04, 0x24, // xchg [rsp], rax 56 | 0xC3, // ret 57 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; // extra nops 58 | 59 | bool RegHook::CreateHookV6() { 60 | if (this->lengthOfInstructions > RegHookShared::min_size + RegHookShared::instruction_max || this->lengthOfInstructions < RegHookShared::min_size) return false; 61 | this->HookedAddress = (DWORD_PTR)VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 62 | RegHook::ReadMem((LPVOID)this->FuncAddress, &this->toFixPatch, this->lengthOfInstructions); 63 | byte* hkpatch = RegHookShared::hkpatch; 64 | memcpy(hkpatch, &this->toFixPatch, this->lengthOfInstructions); 65 | DWORD_PTR returnAddress = this->lengthOfInstructions + this->FuncAddress; // get the address to return to 66 | memcpy(hkpatch + 145, &returnAddress, 8); // write it into the hkpatch 67 | RegHook::WriteMem((LPVOID)this->HookedAddress, hkpatch, RegHookShared::hkpatch_size); 68 | byte* funcpatch = RegHookShared::funcpatch; 69 | memcpy(funcpatch + 3, &this->HookedAddress, 8); 70 | RegHook::WriteMem((LPVOID)this->FuncAddress, funcpatch, this->lengthOfInstructions); 71 | this->HookInstances.push_back(this); 72 | return true; 73 | } 74 | void RegHook::ReadMem(void* dst, void* src, const size_t size) { 75 | DWORD protect; 76 | VirtualProtect(dst, size, PAGE_EXECUTE_READWRITE, &protect); 77 | memcpy(src, dst, size); 78 | VirtualProtect(dst, size, protect, nullptr); 79 | } 80 | 81 | void RegHook::WriteMem(void* dst, void* src, const size_t size) { 82 | DWORD protect; 83 | VirtualProtect(dst, size, PAGE_EXECUTE_READWRITE, &protect); 84 | memcpy(dst, src, size); 85 | VirtualProtect(dst, size, protect, nullptr); 86 | } 87 | 88 | size_t RegHook::GetFuncLen() { 89 | DWORD_PTR addr = this->FuncAddress; 90 | while (this->lengthOfInstructions < RegHookShared::min_size) { 91 | byte buff[RegHookShared::instruction_max]; 92 | RegHook::ReadMem((LPVOID)addr, &buff, RegHookShared::instruction_max); 93 | size_t tmpsize = RegHookShared::GetInstructionLength(&buff); 94 | this->lengthOfInstructions += tmpsize; 95 | addr += tmpsize; 96 | } 97 | return this->lengthOfInstructions; 98 | } 99 | 100 | DWORD_PTR RegHook::GetAddressOfHook() { 101 | if (this->HookedAddress == 0) { 102 | CreateHookV6(); 103 | } 104 | return this->HookedAddress; 105 | } 106 | 107 | void RegHook::DestroyHook() { 108 | if (this->toFixPatch[0] != 0) 109 | RegHook::WriteMem((LPVOID)this->FuncAddress, &this->toFixPatch, this->lengthOfInstructions); 110 | } 111 | 112 | void RegHook::DestroyAllHooks() { 113 | for (int i = 0; i < HookInstances.size(); i++) { 114 | HookInstances[i]->DestroyHook(); 115 | } 116 | } 117 | 118 | RegDump RegHook::GetRegDump() { 119 | RegDump pDump; 120 | RegHook::ReadMem((LPVOID)this->GetAddressOfHook(), &pDump, sizeof(RegDump)); 121 | return pDump; 122 | } 123 | 124 | RegHook::RegHook(DWORD_PTR _FuncAddress) { 125 | this->FuncAddress = _FuncAddress; 126 | this->lengthOfInstructions = this->GetFuncLen(); 127 | } 128 | 129 | std::vector RegHook::HookInstances; 130 | 131 | // ------------------------------------------------------------ 132 | 133 | bool RegHookEx::CreateHookV6() { 134 | if (this->lengthOfInstructions > RegHookShared::min_size + RegHookShared::instruction_max || this->lengthOfInstructions < RegHookShared::min_size) return false; 135 | this->HookedAddress = (DWORD_PTR)VirtualAllocEx(this->hProcess, NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 136 | ReadProcessMemory(this->hProcess, (LPCVOID)this->FuncAddress, &this->toFixPatch, this->lengthOfInstructions, NULL); 137 | byte* hkpatch = RegHookShared::hkpatch; 138 | memcpy(hkpatch, &this->toFixPatch, this->lengthOfInstructions); 139 | DWORD_PTR returnAddress = this->lengthOfInstructions + this->FuncAddress; // get the address to return to 140 | memcpy(hkpatch + 145, &returnAddress, 8); // write it into the hkpatch 141 | WriteProcessMemory(this->hProcess, (LPVOID)this->HookedAddress, hkpatch, RegHookShared::hkpatch_size, NULL); 142 | byte* funcpatch = RegHookShared::funcpatch; 143 | memcpy(funcpatch + 3, &this->HookedAddress, 8); // write the address to jump to 144 | WriteProcessMemory(this->hProcess, (LPVOID)this->FuncAddress, funcpatch, this->lengthOfInstructions, NULL); 145 | this->HookInstances.push_back(this); 146 | return true; 147 | } 148 | 149 | size_t RegHookEx::GetFuncLen() { 150 | DWORD_PTR addr = this->FuncAddress; 151 | while (this->lengthOfInstructions < RegHookShared::min_size) { 152 | byte buff[RegHookShared::instruction_max]; 153 | ReadProcessMemory(this->hProcess, (LPCVOID)addr, &buff, RegHookShared::instruction_max, NULL); 154 | size_t tmpsize = RegHookShared::GetInstructionLength(&buff); 155 | this->lengthOfInstructions += tmpsize; 156 | addr += tmpsize; 157 | } 158 | return this->lengthOfInstructions; 159 | } 160 | 161 | DWORD_PTR RegHookEx::GetAddressOfHook() { 162 | if (this->HookedAddress == 0) { 163 | CreateHookV6(); 164 | } 165 | return this->HookedAddress; 166 | } 167 | 168 | void RegHookEx::DestroyHook() { 169 | if (this->toFixPatch[0] != 0) 170 | WriteProcessMemory(this->hProcess, (LPVOID)this->FuncAddress, &this->toFixPatch, this->lengthOfInstructions, NULL); 171 | } 172 | 173 | void RegHookEx::DestroyAllHooks() { 174 | for (int i = 0; i < HookInstances.size(); i++) { 175 | HookInstances[i]->DestroyHook(); 176 | } 177 | } 178 | 179 | RegDump RegHookEx::GetRegDump() { 180 | RegDump pDump; 181 | ReadProcessMemory(this->hProcess, (LPVOID)this->GetAddressOfHook(), &pDump, sizeof(RegDump), nullptr); 182 | return pDump; 183 | } 184 | 185 | RegHookEx::RegHookEx(HANDLE _hProcess, DWORD_PTR _FuncAddress) { 186 | this->hProcess = _hProcess; 187 | this->FuncAddress = _FuncAddress; 188 | this->lengthOfInstructions = this->GetFuncLen(); 189 | } 190 | 191 | std::vector RegHookEx::HookInstances; -------------------------------------------------------------------------------- /RegHook.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // output class 5 | class RegDump 6 | { 7 | public: 8 | char pad_0000[160]; //0x0000 9 | DWORD_PTR R15; //0x00A0 10 | DWORD_PTR R14; //0x00A8 11 | DWORD_PTR R13; //0x00B0 12 | DWORD_PTR R12; //0x00B8 13 | DWORD_PTR R11; //0x00C0 14 | DWORD_PTR R10; //0x00C8 15 | DWORD_PTR R9; //0x00D0 16 | DWORD_PTR R8; //0x00D8 17 | DWORD_PTR RDI; //0x00E0 18 | DWORD_PTR RSI; //0x00E8 19 | DWORD_PTR RSP; //0x00F0 20 | DWORD_PTR RBP; //0x00F8 21 | DWORD_PTR RDX; //0x0100 22 | DWORD_PTR RCX; //0x0108 23 | DWORD_PTR RBX; //0x0110 24 | DWORD_PTR RAX; //0x0118 25 | }; 26 | 27 | class RegHook { 28 | private: 29 | static std::vector HookInstances; 30 | DWORD_PTR FuncAddress; 31 | size_t lengthOfInstructions; 32 | DWORD_PTR HookedAddress = 0; 33 | byte toFixPatch[60]; 34 | bool CreateHookV6(); 35 | size_t GetFuncLen(); 36 | static void ReadMem(void*, void*, const size_t); 37 | static void WriteMem(void*, void*, const size_t); 38 | public: 39 | RegHook(DWORD_PTR _FuncAddress); 40 | DWORD_PTR GetAddressOfHook(); 41 | void DestroyHook(); 42 | static void DestroyAllHooks(); 43 | RegDump GetRegDump(); 44 | }; 45 | 46 | class RegHookEx{ 47 | private: 48 | static std::vector HookInstances; 49 | HANDLE hProcess; 50 | DWORD_PTR FuncAddress; 51 | DWORD_PTR HookedAddress = 0; 52 | byte toFixPatch[60]; 53 | bool CreateHookV6(); 54 | size_t GetFuncLen(); 55 | size_t lengthOfInstructions; 56 | public: 57 | RegHookEx(HANDLE _hProcess, DWORD_PTR _FuncAddress); 58 | DWORD_PTR GetAddressOfHook(); 59 | void DestroyHook(); 60 | static void DestroyAllHooks(); 61 | RegDump GetRegDump(); 62 | }; 63 | 64 | -------------------------------------------------------------------------------- /RegHookEx.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RegHookEx", "RegHookEx.vcxproj", "{189BBF63-1D4D-4A01-A341-13B096269C98}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {189BBF63-1D4D-4A01-A341-13B096269C98}.Debug|x64.ActiveCfg = Debug|x64 17 | {189BBF63-1D4D-4A01-A341-13B096269C98}.Debug|x64.Build.0 = Debug|x64 18 | {189BBF63-1D4D-4A01-A341-13B096269C98}.Debug|x86.ActiveCfg = Debug|Win32 19 | {189BBF63-1D4D-4A01-A341-13B096269C98}.Debug|x86.Build.0 = Debug|Win32 20 | {189BBF63-1D4D-4A01-A341-13B096269C98}.Release|x64.ActiveCfg = Release|x64 21 | {189BBF63-1D4D-4A01-A341-13B096269C98}.Release|x64.Build.0 = Release|x64 22 | {189BBF63-1D4D-4A01-A341-13B096269C98}.Release|x86.ActiveCfg = Release|Win32 23 | {189BBF63-1D4D-4A01-A341-13B096269C98}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /RegHookEx.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {189BBF63-1D4D-4A01-A341-13B096269C98} 23 | Win32Proj 24 | RegHookEx 25 | 10.0.16299.0 26 | RegHook 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | StaticLibrary 44 | true 45 | v141 46 | MultiByte 47 | 48 | 49 | StaticLibrary 50 | false 51 | v141 52 | true 53 | MultiByte 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(DXDIR);C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include\ 79 | 80 | 81 | false 82 | 83 | 84 | false 85 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(DXDIR);C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include\ 86 | 87 | 88 | 89 | 90 | 91 | Level3 92 | Disabled 93 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | true 95 | 96 | 97 | Console 98 | true 99 | 100 | 101 | 102 | 103 | 104 | 105 | Level3 106 | Disabled 107 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | true 109 | 110 | 111 | Console 112 | true 113 | $(DXDIR) 114 | 115 | 116 | 117 | 118 | Level3 119 | 120 | 121 | MaxSpeed 122 | true 123 | true 124 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 125 | true 126 | 127 | 128 | Console 129 | true 130 | true 131 | true 132 | 133 | 134 | 135 | 136 | Level3 137 | 138 | 139 | MaxSpeed 140 | true 141 | true 142 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 143 | true 144 | 145 | 146 | Console 147 | true 148 | true 149 | true 150 | $(DXDIR) 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /fde/fde64.asm: -------------------------------------------------------------------------------- 1 | 2 | format ms64 coff 3 | 4 | include 'win64a.inc' 5 | 6 | public encode 7 | public encode as '_encode' 8 | 9 | encode: 10 | file '..\bin\encode.bin' 11 | 12 | public decode 13 | public decode as '_decode' 14 | 15 | decode: 16 | file '..\bin\decode.bin' 17 | -------------------------------------------------------------------------------- /fde/fde64.h: -------------------------------------------------------------------------------- 1 | 2 | // Nov 2012 3 | // un[f]ancy [d]isassembler [e]ngine (fde64) v0.04 4 | // 5 | 6 | #ifndef _FDE64_H_ 7 | #define _FDE64_H_ 8 | 9 | // flags 10 | 11 | #define F_NONE 0x00000000 12 | #define F_MODRM 0x00000001 13 | #define F_SIB 0x00000002 14 | #define F_DISP8 0x00000004 15 | #define F_DISP32 0x00000008 16 | #define F_DISP64 0x00000010 17 | #define F_DISP F_DISP8+F_DISP32+F_DISP64 18 | #define F_IMM8 0x00000020 19 | #define F_IMM16 0x00000040 20 | #define F_IMM32 0x00000080 21 | #define F_IMM64 0x00000100 22 | #define F_IMM F_IMM8+F_IMM16+F_IMM32+F_IMM64 23 | #define F_RELATIVE 0x00000200 24 | #define F_RIPDISP32 0x00000400 25 | #define F_GROUP 0x00000800 // index specified in modrm.reg 26 | #define F_REX_IGNORED 0x00001000 27 | #define F_VEX_BAD_PREFIX 0x00002000 28 | #define F_ERROR_LOCK 0x00004000 // lock-prefix not possible 29 | #define F_ERROR_X86_64 0x00008000 // invalid under x64 30 | #define F_ERROR_LENGTH 0x00010000 31 | #define F_ERROR_OPCODE 0x00020000 // undefined opcode 32 | 33 | // prefix flags 34 | 35 | #define PRE_NONE 0x00h 36 | #define PRE_LOCK 0x01h 37 | #define PRE_REP 0x02h 38 | #define PRE_SEG 0x04h 39 | #define PRE_66 0x08h // ignored if rex.w=1 40 | #define PRE_67 0x10h 41 | #define PRE_REX 0x20h 42 | #define PRE_VEX 0x40h // partly encoded in complements to distinguish from les/lds 43 | #define PRE_ALL PRE_LOCK+PRE_REP+PRE_SEG+PRE_66+PRE_67 44 | #define PRE_ALL64 PRE_ALL+PRE_REX+PRE_VEX 45 | 46 | // vex-prefix m-mmmm 47 | 48 | #define M_MMMM_0F 1 49 | #define M_MMMM_0F_38 2 50 | #define M_MMMM_0F_3A 3 51 | 52 | // vex-prefix l 53 | 54 | #define L_SCALAR 0 55 | #define L_128_VECTOR 0 56 | #define L_256_VECTOR 1 57 | 58 | // vex-prefix pp 59 | 60 | #define PP_NONE 0 61 | #define PP_66 1 62 | #define PP_F3 2 63 | #define PP_F2 3 64 | 65 | // modr/m mod 66 | 67 | #define MOD_NODISP 0 68 | #define MOD_DISP8 1 69 | #define MOD_DISP32 2 70 | #define MOD_REG 3 71 | 72 | // modr/m reg 73 | 74 | /* GPRs */ 75 | #define REG_RAX 0 // x64 gprs are being used if rex.w=1 76 | #define REG_RCX 1 77 | #define REG_RDX 2 78 | #define REG_RBX 3 79 | #define REG_RSP 4 80 | #define REG_RBP 5 81 | #define REG_RSI 6 82 | #define REG_RDI 7 83 | #define REG_R8 REG_RAX // r8-r15 are being used if rex.rxb=1 84 | #define REG_R9 REG_RCX 85 | #define REG_R10 REG_RDX 86 | #define REG_R11 REG_RBX 87 | #define REG_R12 REG_RSP 88 | #define REG_R13 REG_RBP 89 | #define REG_R14 REG_RSI 90 | #define REG_R15 REG_RDI 91 | #define REG_AL REG_RAX 92 | #define REG_AH REG_RSP 93 | #define REG_CL REG_RCX 94 | #define REG_CH REG_RBP 95 | #define REG_DL REG_RDX 96 | #define REG_DH REG_RSI 97 | #define REG_BL REG_RBX 98 | #define REG_BH REG_RDI 99 | #define REG_SPL REG_AH // spl-dil are being used if rex (rex.rb=1 is for r8l-r15l) 100 | #define REG_SBL REG_CH 101 | #define REG_SIL REG_DH 102 | #define REG_DIL REG_BH 103 | /* special */ 104 | #define REG_DR0 REG_RAX 105 | #define REG_DR1 REG_RCX 106 | #define REG_DR2 REG_RDX 107 | #define REG_DR3 REG_RBX 108 | #define REG_DR4 REG_RSP // refers to DR6 if CR4.DE is cleared 109 | #define REG_DR5 REG_RBP // refers to DR7 ^ 110 | #define REG_DR6 REG_RSI 111 | #define REG_DR7 REG_RDI 112 | #define REG_CR0 REG_RAX 113 | #define REG_CR2 REG_RDX 114 | #define REG_CR3 REG_RBX 115 | #define REG_CR4 REG_RSP 116 | #define REG_CR8 REG_RAX // cr8 is being used if rex.r=1 117 | /* MMX/XMM/YMM */ 118 | #define REG_SIMD0 REG_RAX 119 | #define REG_SIMD1 REG_RCX 120 | #define REG_SIMD2 REG_RDX 121 | #define REG_SIMD3 REG_RBX 122 | #define REG_SIMD4 REG_RSP 123 | #define REG_SIMD5 REG_RBP 124 | #define REG_SIMD6 REG_RSI 125 | #define REG_SIMD7 REG_RDI 126 | #define REG_SIMD8 REG_RAX // simd8-simd15 are being used if rex.rb=1 or vex.vvvv=8-15 127 | #define REG_SIMD9 REG_RCX 128 | #define REG_SIMD10 REG_RDX 129 | #define REG_SIMD11 REG_RBX 130 | #define REG_SIMD12 REG_RSP 131 | #define REG_SIMD13 REG_RBP 132 | #define REG_SIMD14 REG_RSI 133 | #define REG_SIMD15 REG_RDI 134 | /* FPU */ 135 | #define REG_ST0 REG_RAX 136 | #define REG_ST1 REG_RCX 137 | #define REG_ST2 REG_RDX 138 | #define REG_ST3 REG_RBX 139 | #define REG_ST4 REG_RSP 140 | #define REG_ST5 REG_RBP 141 | #define REG_ST6 REG_RSI 142 | #define REG_ST7 REG_RDI 143 | /* Sregs */ 144 | #define SEG_ES REG_RAX 145 | #define SEG_CS REG_RCX 146 | #define SEG_SS REG_RDX 147 | #define SEG_DS REG_RBX 148 | #define SEG_FS REG_RSP 149 | #define SEG_GS REG_RBP 150 | 151 | // modr/m r/m 152 | 153 | #define RM_SIB REG_RSP 154 | #define RM_DISP32 REG_RBP 155 | 156 | // sib scale 157 | 158 | #define SCALE_1 0 159 | #define SCALE_2 1 160 | #define SCALE_4 2 161 | #define SCALE_8 3 162 | 163 | // prefixes 164 | 165 | #define PREFIX_SEGMENT_CS 0x2E 166 | #define PREFIX_SEGMENT_SS 0x36 167 | #define PREFIX_SEGMENT_DS 0x3E 168 | #define PREFIX_SEGMENT_ES 0x26 169 | #define PREFIX_SEGMENT_FS 0x64 170 | #define PREFIX_SEGMENT_GS 0x65 171 | #define PREFIX_LOCK 0xF0 172 | #define PREFIX_REPNZ 0xF2 173 | #define PREFIX_REP 0xF3 174 | #define PREFIX_OPERAND_SIZE 0x66 175 | #define PREFIX_ADDRESS_SIZE 0x67 176 | #define PREFIX_REX_START 0x40 177 | #define PREFIX_REX_END 0x4F 178 | #define PREFIX_VEX_2_BYTE 0xC5 179 | #define PREFIX_VEX_3_BYTE 0xC4 180 | 181 | #pragma pack(push, 1) 182 | 183 | // structure representing any instruction 184 | 185 | typedef struct 186 | { 187 | unsigned char len; 188 | unsigned char prefix; 189 | unsigned char prefix_lock; 190 | unsigned char prefix_rep; 191 | unsigned char prefix_seg; 192 | unsigned char prefix_66; 193 | unsigned char prefix_67; 194 | unsigned char rex; 195 | unsigned char rex_w; 196 | unsigned char rex_r; 197 | unsigned char rex_x; 198 | unsigned char rex_b; 199 | unsigned char vex; 200 | unsigned char vex2; 201 | unsigned char vex3; 202 | unsigned char vex_r; 203 | unsigned char vex_x; 204 | unsigned char vex_b; 205 | unsigned char vex_m_mmmm; 206 | unsigned char vex_w; 207 | unsigned char vex_vvvv; 208 | unsigned char vex_l; 209 | unsigned char vex_pp; 210 | unsigned char opcode_len; 211 | unsigned char opcode; 212 | unsigned char opcode2; 213 | unsigned char opcode3; 214 | unsigned char modrm; 215 | unsigned char modrm_mod; 216 | unsigned char modrm_reg; 217 | unsigned char modrm_rm; 218 | unsigned char sib; 219 | unsigned char sib_scale; 220 | unsigned char sib_index; 221 | unsigned char sib_base; 222 | union 223 | { 224 | char disp8; 225 | int disp32; 226 | long long disp64; 227 | }; 228 | union 229 | { 230 | char imm8; 231 | short imm16; 232 | int imm32; 233 | long long imm64; 234 | }; 235 | union 236 | { 237 | char imm8_2; 238 | short imm16_2; 239 | }; 240 | unsigned int flags; 241 | } fde64s; 242 | 243 | #pragma pack(pop) 244 | 245 | #ifdef __cplusplus 246 | extern "C" 247 | { 248 | #endif 249 | 250 | int encode(void *dest, fde64s *cmd); 251 | int decode(void *src, fde64s *cmd); 252 | 253 | #ifdef __cplusplus 254 | } 255 | #endif 256 | 257 | #endif /* _FDE64_H_ */ 258 | -------------------------------------------------------------------------------- /fde/fde64.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coltonon/RegHookEx/929048300322a0e3d32e047e8bd6480b227f140c/fde/fde64.obj --------------------------------------------------------------------------------