├── BasicHook.sln ├── BasicHook ├── BasicHook.vcxproj ├── disassembler │ ├── hde32.c │ ├── hde32.h │ └── table32.h ├── hook.cpp └── hook.h └── README.md /BasicHook.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicHook", "BasicHook\BasicHook.vcxproj", "{0CF00F05-CE60-422B-A2F0-5630E3BF32C0}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {0CF00F05-CE60-422B-A2F0-5630E3BF32C0}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {0CF00F05-CE60-422B-A2F0-5630E3BF32C0}.Debug|Win32.Build.0 = Debug|Win32 14 | {0CF00F05-CE60-422B-A2F0-5630E3BF32C0}.Release|Win32.ActiveCfg = Release|Win32 15 | {0CF00F05-CE60-422B-A2F0-5630E3BF32C0}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /BasicHook/BasicHook.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {0CF00F05-CE60-422B-A2F0-5630E3BF32C0} 15 | Win32Proj 16 | BasicHook 17 | 18 | 19 | 20 | Application 21 | true 22 | v110 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v110 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 55 | 56 | 57 | Console 58 | true 59 | 60 | 61 | 62 | 63 | Level3 64 | 65 | 66 | MaxSpeed 67 | true 68 | true 69 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 70 | 71 | 72 | Console 73 | true 74 | true 75 | true 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /BasicHook/disassembler/hde32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 C 3 | * Copyright (c) 2008, Veacheslav Patkov 4 | * aLL rights reserved. 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "hde32.h" 12 | #include "table32.h" 13 | 14 | unsigned int hde32_disasm(const void *code, hde32s *hs) 15 | { 16 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; 17 | uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0; 18 | 19 | memset(hs,0,sizeof(hde32s)); 20 | 21 | for (x = 16; x; x--) 22 | switch (c = *p++) { 23 | case 0xf3: 24 | hs->p_rep = c; 25 | pref |= PRE_F3; 26 | break; 27 | case 0xf2: 28 | hs->p_rep = c; 29 | pref |= PRE_F2; 30 | break; 31 | case 0xf0: 32 | hs->p_lock = c; 33 | pref |= PRE_LOCK; 34 | break; 35 | case 0x26: case 0x2e: case 0x36: 36 | case 0x3e: case 0x64: case 0x65: 37 | hs->p_seg = c; 38 | pref |= PRE_SEG; 39 | break; 40 | case 0x66: 41 | hs->p_66 = c; 42 | pref |= PRE_66; 43 | break; 44 | case 0x67: 45 | hs->p_67 = c; 46 | pref |= PRE_67; 47 | break; 48 | default: 49 | goto pref_done; 50 | } 51 | pref_done: 52 | if (!pref) 53 | pref |= PRE_NONE; 54 | 55 | hs->flags = (uint32_t)pref << 23; 56 | 57 | if ((hs->opcode = c) == 0x0f) { 58 | hs->opcode2 = c = *p++; 59 | ht += DELTA_OPCODES; 60 | } else if (c >= 0xa0 && c <= 0xa3) { 61 | if (pref & PRE_67) 62 | pref |= PRE_66; 63 | else 64 | pref &= ~PRE_66; 65 | } 66 | 67 | opcode = c; 68 | cflags = ht[ht[opcode / 4] + (opcode % 4)]; 69 | 70 | if (cflags == C_ERROR) { 71 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 72 | cflags = 0; 73 | if ((opcode & -3) == 0x24) 74 | cflags++; 75 | } 76 | 77 | x = 0; 78 | if (cflags & C_GROUP) { 79 | uint16_t t; 80 | t = *(uint16_t *)(ht + (cflags & 0x7f)); 81 | cflags = (uint8_t)t; 82 | x = (uint8_t)(t >> 8); 83 | } 84 | 85 | if (hs->opcode2) { 86 | ht = hde32_table + DELTA_PREFIXES; 87 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref) 88 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 89 | } 90 | 91 | if (cflags & C_MODRM) { 92 | hs->flags |= F_MODRM; 93 | hs->modrm = c = *p++; 94 | hs->modrm_mod = m_mod = c >> 6; 95 | hs->modrm_rm = m_rm = c & 7; 96 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3; 97 | 98 | if (x && ((x << m_reg) & 0x80)) 99 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 100 | 101 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { 102 | uint8_t t = opcode - 0xd9; 103 | if (m_mod == 3) { 104 | ht = hde32_table + DELTA_FPU_MODRM + t*8; 105 | t = ht[m_reg] << m_rm; 106 | } else { 107 | ht = hde32_table + DELTA_FPU_REG; 108 | t = ht[t] << m_reg; 109 | } 110 | if (t & 0x80) 111 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 112 | } 113 | 114 | if (pref & PRE_LOCK) { 115 | if (m_mod == 3) { 116 | hs->flags |= F_ERROR | F_ERROR_LOCK; 117 | } else { 118 | uint8_t *table_end, op = opcode; 119 | if (hs->opcode2) { 120 | ht = hde32_table + DELTA_OP2_LOCK_OK; 121 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; 122 | } else { 123 | ht = hde32_table + DELTA_OP_LOCK_OK; 124 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; 125 | op &= -2; 126 | } 127 | for (; ht != table_end; ht++) 128 | if (*ht++ == op) 129 | if (!((*ht << m_reg) & 0x80)) 130 | goto no_lock_error; 131 | else 132 | break; 133 | hs->flags |= F_ERROR | F_ERROR_LOCK; 134 | no_lock_error: 135 | ; 136 | } 137 | } 138 | 139 | if (hs->opcode2) { 140 | switch (opcode) { 141 | case 0x20: case 0x22: 142 | m_mod = 3; 143 | if (m_reg > 4 || m_reg == 1) 144 | goto error_operand; 145 | else 146 | goto no_error_operand; 147 | case 0x21: case 0x23: 148 | m_mod = 3; 149 | if (m_reg == 4 || m_reg == 5) 150 | goto error_operand; 151 | else 152 | goto no_error_operand; 153 | } 154 | } else { 155 | switch (opcode) { 156 | case 0x8c: 157 | if (m_reg > 5) 158 | goto error_operand; 159 | else 160 | goto no_error_operand; 161 | case 0x8e: 162 | if (m_reg == 1 || m_reg > 5) 163 | goto error_operand; 164 | else 165 | goto no_error_operand; 166 | } 167 | } 168 | 169 | if (m_mod == 3) { 170 | uint8_t *table_end; 171 | if (hs->opcode2) { 172 | ht = hde32_table + DELTA_OP2_ONLY_MEM; 173 | table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM; 174 | } else { 175 | ht = hde32_table + DELTA_OP_ONLY_MEM; 176 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; 177 | } 178 | for (; ht != table_end; ht += 2) 179 | if (*ht++ == opcode) 180 | if (*ht++ & pref && !((*ht << m_reg) & 0x80)) 181 | goto error_operand; 182 | else 183 | break; 184 | goto no_error_operand; 185 | } else if (hs->opcode2) { 186 | switch (opcode) { 187 | case 0x50: case 0xd7: case 0xf7: 188 | if (pref & (PRE_NONE | PRE_66)) 189 | goto error_operand; 190 | break; 191 | case 0xd6: 192 | if (pref & (PRE_F2 | PRE_F3)) 193 | goto error_operand; 194 | break; 195 | case 0xc5: 196 | goto error_operand; 197 | } 198 | goto no_error_operand; 199 | } else 200 | goto no_error_operand; 201 | 202 | error_operand: 203 | hs->flags |= F_ERROR | F_ERROR_OPERAND; 204 | no_error_operand: 205 | 206 | c = *p++; 207 | if (m_reg <= 1) { 208 | if (opcode == 0xf6) 209 | cflags |= C_IMM8; 210 | else if (opcode == 0xf7) 211 | cflags |= C_IMM_P66; 212 | } 213 | 214 | switch (m_mod) { 215 | case 0: 216 | if (pref & PRE_67) { 217 | if (m_rm == 6) 218 | disp_size = 2; 219 | } else 220 | if (m_rm == 5) 221 | disp_size = 4; 222 | break; 223 | case 1: 224 | disp_size = 1; 225 | break; 226 | case 2: 227 | disp_size = 2; 228 | if (!(pref & PRE_67)) 229 | disp_size <<= 1; 230 | } 231 | 232 | if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) { 233 | hs->flags |= F_SIB; 234 | p++; 235 | hs->sib = c; 236 | hs->sib_scale = c >> 6; 237 | hs->sib_index = (c & 0x3f) >> 3; 238 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) 239 | disp_size = 4; 240 | } 241 | 242 | p--; 243 | switch (disp_size) { 244 | case 1: 245 | hs->flags |= F_DISP8; 246 | hs->disp8 = *p; 247 | break; 248 | case 2: 249 | hs->flags |= F_DISP16; 250 | hs->disp16 = *(uint16_t *)p; 251 | break; 252 | case 4: 253 | hs->flags |= F_DISP32; 254 | hs->disp32 = *(uint32_t *)p; 255 | } 256 | p += disp_size; 257 | } else if (pref & PRE_LOCK) 258 | hs->flags |= F_ERROR | F_ERROR_LOCK; 259 | 260 | if (cflags & C_IMM_P66) { 261 | if (cflags & C_REL32) { 262 | if (pref & PRE_66) { 263 | hs->flags |= F_REL16; 264 | hs->rel16 = *(uint16_t *)p; 265 | p += 2; 266 | goto disasm_done; 267 | } 268 | goto rel32_ok; 269 | } 270 | if (pref & PRE_66) { 271 | hs->flags |= F_IMM16; 272 | hs->imm16 = *(uint16_t *)p; 273 | p += 2; 274 | } else { 275 | hs->flags |= F_IMM32; 276 | hs->imm32 = *(uint32_t *)p; 277 | p += 4; 278 | } 279 | } 280 | 281 | if (cflags & C_IMM16) { 282 | if (hs->flags & F_IMM16) { 283 | hs->flags |= F_2IMM16; 284 | hs->imm32 = *(uint16_t *)p; 285 | } else { 286 | hs->flags |= F_IMM16; 287 | hs->imm16 = *(uint16_t *)p; 288 | } 289 | p += 2; 290 | } 291 | if (cflags & C_IMM8) { 292 | hs->flags |= F_IMM8; 293 | hs->imm8 = *p++; 294 | } 295 | 296 | if (cflags & C_REL32) { 297 | rel32_ok: 298 | hs->flags |= F_REL32; 299 | hs->rel32 = *(uint32_t *)p; 300 | p += 4; 301 | } else if (cflags & C_REL8) { 302 | hs->flags |= F_REL8; 303 | hs->rel8 = *p++; 304 | } 305 | 306 | disasm_done: 307 | 308 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { 309 | hs->flags |= F_ERROR | F_ERROR_LENGTH; 310 | hs->len = 15; 311 | } 312 | 313 | return (unsigned int)hs->len; 314 | } 315 | -------------------------------------------------------------------------------- /BasicHook/disassembler/hde32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 3 | * Copyright (c) 2006-2008, Veacheslav Patkov 4 | * aLL rights reserved. 5 | * 6 | * hde32.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE32_H_ 11 | #define _HDE32_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_DISP8 0x00000020 30 | #define F_DISP16 0x00000040 31 | #define F_DISP32 0x00000080 32 | #define F_REL8 0x00000100 33 | #define F_REL16 0x00000200 34 | #define F_REL32 0x00000400 35 | #define F_2IMM16 0x00000800 36 | #define F_ERROR 0x00001000 37 | #define F_ERROR_OPCODE 0x00002000 38 | #define F_ERROR_LENGTH 0x00004000 39 | #define F_ERROR_LOCK 0x00008000 40 | #define F_ERROR_OPERAND 0x00010000 41 | #define F_PREFIX_REPNZ 0x01000000 42 | #define F_PREFIX_REPX 0x02000000 43 | #define F_PREFIX_REP 0x03000000 44 | #define F_PREFIX_66 0x04000000 45 | #define F_PREFIX_67 0x08000000 46 | #define F_PREFIX_LOCK 0x10000000 47 | #define F_PREFIX_SEG 0x20000000 48 | #define F_PREFIX_ANY 0x3f000000 49 | 50 | #define PREFIX_SEGMENT_CS 0x2e 51 | #define PREFIX_SEGMENT_SS 0x36 52 | #define PREFIX_SEGMENT_DS 0x3e 53 | #define PREFIX_SEGMENT_ES 0x26 54 | #define PREFIX_SEGMENT_FS 0x64 55 | #define PREFIX_SEGMENT_GS 0x65 56 | #define PREFIX_LOCK 0xf0 57 | #define PREFIX_REPNZ 0xf2 58 | #define PREFIX_REPX 0xf3 59 | #define PREFIX_OPERAND_SIZE 0x66 60 | #define PREFIX_ADDRESS_SIZE 0x67 61 | 62 | #pragma pack(push,1) 63 | 64 | typedef struct { 65 | uint8_t len; 66 | uint8_t p_rep; 67 | uint8_t p_lock; 68 | uint8_t p_seg; 69 | uint8_t p_66; 70 | uint8_t p_67; 71 | uint8_t opcode; 72 | uint8_t opcode2; 73 | uint8_t modrm; 74 | uint8_t modrm_mod; 75 | uint8_t modrm_reg; 76 | uint8_t modrm_rm; 77 | uint8_t sib; 78 | uint8_t sib_scale; 79 | uint8_t sib_index; 80 | uint8_t sib_base; 81 | uint8_t imm8; 82 | uint16_t imm16; 83 | uint32_t imm32; 84 | uint8_t disp8; 85 | uint16_t disp16; 86 | uint32_t disp32; 87 | uint8_t rel8; 88 | uint16_t rel16; 89 | uint32_t rel32; 90 | uint32_t flags; 91 | } hde32s; 92 | 93 | #pragma pack(pop) 94 | 95 | #ifdef __cplusplus 96 | extern "C" { 97 | #endif 98 | 99 | /* __cdecl */ 100 | unsigned int hde32_disasm(const void *code, hde32s *hs); 101 | 102 | #ifdef __cplusplus 103 | } 104 | #endif 105 | 106 | #endif /* _HDE32_H_ */ 107 | -------------------------------------------------------------------------------- /BasicHook/disassembler/table32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 C 3 | * Copyright (c) 2008, Veacheslav Patkov 4 | * aLL rights reserved. 5 | * 6 | */ 7 | 8 | #define C_NONE 0x00 9 | #define C_MODRM 0x01 10 | #define C_IMM8 0x02 11 | #define C_IMM16 0x04 12 | #define C_IMM_P66 0x10 13 | #define C_REL8 0x20 14 | #define C_REL32 0x40 15 | #define C_GROUP 0x80 16 | #define C_ERROR 0xff 17 | 18 | #define PRE_ANY 0x00 19 | #define PRE_NONE 0x01 20 | #define PRE_F2 0x02 21 | #define PRE_F3 0x04 22 | #define PRE_66 0x08 23 | #define PRE_67 0x10 24 | #define PRE_LOCK 0x20 25 | #define PRE_SEG 0x40 26 | #define PRE_ALL 0xff 27 | 28 | #define DELTA_OPCODES 0x4a 29 | #define DELTA_PREFIXES 0x14d 30 | #define DELTA_FPU_MODRM 0x115 31 | #define DELTA_FPU_REG 0x10e 32 | #define DELTA_OP_LOCK_OK 0x1bf 33 | #define DELTA_OP2_LOCK_OK 0x1d7 34 | #define DELTA_OP_ONLY_MEM 0x1e9 35 | #define DELTA_OP2_ONLY_MEM 0x1f8 36 | 37 | unsigned char hde32_table[] = { 38 | 0xa1,0x9b,0xa1,0x9b,0xa1,0x9b,0xa1,0x9b,0xa1,0x9b,0xa1,0x9b,0xa1,0x9b,0xa1, 39 | 0x9b,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9f,0x9d,0xd1,0x9d,0xb2,0xb2, 40 | 0xb2,0xb2,0xc6,0xa1,0xa1,0xf6,0x9d,0x9d,0xc0,0x9d,0xa9,0x9d,0x9b,0x9d,0x98, 41 | 0x98,0xa9,0xa9,0xd4,0xf2,0xd8,0xb9,0xa1,0xb6,0xa1,0xa1,0xb2,0x98,0xaf,0x9d, 42 | 0x9d,0x9f,0x9d,0xfa,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xb4, 43 | 0x95,0x97,0xa0,0x57,0x57,0x57,0x57,0x57,0x9d,0x57,0x57,0x53,0x97,0x9d,0x9d, 44 | 0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0xb8,0x58,0x97, 45 | 0x57,0x63,0x63,0x63,0x63,0x57,0x57,0x57,0x57,0x54,0x9b,0x54,0x81,0x57,0x57, 46 | 0xc0,0x57,0x83,0xbc,0x53,0x53,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57, 47 | 0x57,0x57,0x92,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, 48 | 0x03,0xf0,0x02,0x02,0x02,0x02,0x10,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01, 49 | 0x00,0x01,0x00,0x03,0x10,0x10,0x10,0x10,0x50,0x50,0x50,0x50,0x14,0x20,0x20, 50 | 0x20,0x20,0x02,0x02,0x00,0x00,0x02,0x00,0x00,0x03,0x01,0x00,0x00,0x00,0x14, 51 | 0x00,0x01,0x01,0x03,0x11,0x03,0x03,0x03,0x03,0x01,0x01,0x01,0x03,0x01,0x10, 52 | 0x11,0x02,0x03,0x03,0x04,0x00,0x06,0x00,0x04,0x00,0x01,0x01,0x01,0xff,0x00, 53 | 0x00,0x00,0xff,0xff,0x03,0x01,0xff,0xff,0xff,0xff,0x01,0x00,0x03,0x00,0x00, 54 | 0xc0,0xc8,0x01,0x01,0xc0,0xc2,0x01,0x01,0x01,0xc4,0x00,0x00,0xc6,0xc8,0xc0, 55 | 0xc2,0x01,0x01,0x03,0xc4,0xc6,0xc8,0x03,0x03,0x03,0xca,0x00,0xff,0xcc,0x01, 56 | 0x40,0x00,0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00, 57 | 0x00,0x00,0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00, 58 | 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 59 | 0xff,0xff,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f, 60 | 0x00,0x00,0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42, 61 | 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44, 62 | 0x57,0x43,0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 63 | 0x40,0x40,0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44, 64 | 0x46,0x40,0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06, 65 | 0x01,0x06,0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02, 66 | 0x07,0x07,0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00, 67 | 0x04,0x04,0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08, 68 | 0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01, 69 | 0x86,0x00,0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba, 70 | 0xf8,0xbb,0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00, 71 | 0xc4,0xff,0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00, 72 | 0x13,0x09,0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07, 73 | 0xb2,0xff,0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf, 74 | 0xe7,0x08,0x00,0xf0,0x02,0x00 75 | }; 76 | -------------------------------------------------------------------------------- /BasicHook/hook.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "hook.h" 6 | #include "Disassembler\hde32.h" 7 | 8 | //use _InterlockedCompareExchange64 instead of inline ASM (depends on compiler) 9 | #define NO_INLINE_ASM 10 | 11 | TdefOldMessageBoxA OldMessageBoxA; 12 | TdefOldMessageBoxW OldMessageBoxW; 13 | 14 | LPVOID OriginalMemArea; 15 | 16 | HOOK_ARRAY HookArray[] = 17 | { 18 | {"user32.dll", "MessageBoxA", (LPVOID)&NewMessageBoxA, &OldMessageBoxA, 0}, 19 | {"user32.dll", "MessageBoxW", (LPVOID)&NewMessageBoxW, &OldMessageBoxW, 0}, 20 | }; 21 | 22 | void HookAll() 23 | { 24 | int i, NumEntries = sizeof(HookArray) / sizeof(HOOK_ARRAY); 25 | 26 | //Needs 25 bytes for each hooked function to hold original byte + return jump 27 | OriginalMemArea = VirtualAlloc(NULL, 25 * NumEntries, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 28 | if(!OriginalMemArea) 29 | return; 30 | 31 | for(i = 0; i < NumEntries; i++) 32 | { 33 | //Split the allocated memory into a block of 25 bytes for each hooked function 34 | *(LPVOID *)HookArray[i].original = (LPVOID)((DWORD)OriginalMemArea + (i * 25)); 35 | HookFunction(HookArray[i].dll, HookArray[i].name, HookArray[i].proxy, *(LPVOID *)HookArray[i].original, &HookArray[i].length); 36 | } 37 | } 38 | 39 | void UnhookAll() 40 | { 41 | int i, NumEntries = sizeof(HookArray) / sizeof(HOOK_ARRAY); 42 | 43 | for(i = 0; i < NumEntries; i++) 44 | UnhookFunction(HookArray[i].dll, HookArray[i].name, *(LPVOID *)HookArray[i].original, HookArray[i].length); 45 | 46 | VirtualFree(OriginalMemArea, 0, MEM_RELEASE); 47 | } 48 | 49 | int WINAPI NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCTSTR lpCaption, UINT uType) 50 | { 51 | printf("MessageBoxA called!\ntitle: %s\ntext: %s\n\n", lpCaption, lpText); 52 | return OldMessageBoxA(hWnd, lpText, lpCaption, uType); 53 | } 54 | 55 | int WINAPI NewMessageBoxW(HWND hWnd, LPWSTR lpText, LPCTSTR lpCaption, UINT uType) 56 | { 57 | printf("MessageBoxW called!\ntitle: %ws\ntext: %ws\n\n", lpCaption, lpText); 58 | return OldMessageBoxW(hWnd, lpText, lpCaption, uType); 59 | } 60 | 61 | //We need to copy 5 bytes, but we can only do 2, 4, 8 atomically 62 | //Pad buffer to 8 bytes then use lock cmpxchg8b instruction 63 | void SafeMemcpyPadded(LPVOID destination, LPVOID source, DWORD size) 64 | { 65 | BYTE SourceBuffer[8]; 66 | 67 | if(size > 8) 68 | return; 69 | 70 | //Pad the source buffer with bytes from destination 71 | memcpy(SourceBuffer, destination, 8); 72 | memcpy(SourceBuffer, source, size); 73 | 74 | #ifndef NO_INLINE_ASM 75 | __asm 76 | { 77 | lea esi, SourceBuffer; 78 | mov edi, destination; 79 | 80 | mov eax, [edi]; 81 | mov edx, [edi+4]; 82 | mov ebx, [esi]; 83 | mov ecx, [esi+4]; 84 | 85 | lock cmpxchg8b[edi]; 86 | } 87 | #else 88 | _InterlockedCompareExchange64((LONGLONG *)destination, *(LONGLONG *)SourceBuffer, *(LONGLONG *)destination); 89 | #endif 90 | } 91 | 92 | BOOL HookFunction(CHAR *dll, CHAR *name, LPVOID proxy, LPVOID original, PDWORD length) 93 | { 94 | LPVOID FunctionAddress; 95 | DWORD TrampolineLength = 0, OriginalProtection; 96 | hde32s disam; 97 | BYTE Jump[5] = {0xE9, 0x00, 0x00, 0x00, 0x00}; 98 | 99 | FunctionAddress = GetProcAddress(GetModuleHandleA(dll), name); 100 | if(!FunctionAddress) 101 | return FALSE; 102 | 103 | //disassemble length of each instruction, until we have 5 or more bytes worth 104 | while(TrampolineLength < 5) 105 | { 106 | LPVOID InstPointer = (LPVOID)((DWORD)FunctionAddress + TrampolineLength); 107 | TrampolineLength += hde32_disasm(InstPointer, &disam); 108 | } 109 | 110 | //Build the trampoline buffer 111 | memcpy(original, FunctionAddress, TrampolineLength); 112 | *(DWORD *)(Jump+1) = ((DWORD)FunctionAddress + TrampolineLength) - ((DWORD)original + TrampolineLength + 5); 113 | memcpy((LPVOID)((DWORD)original+TrampolineLength), Jump, 5); 114 | 115 | //Make sure the function is writable 116 | if(!VirtualProtect(FunctionAddress, TrampolineLength, PAGE_EXECUTE_READWRITE, &OriginalProtection)) 117 | return FALSE; 118 | 119 | //Build and atomically write the hook 120 | *(DWORD *)(Jump+1) = (DWORD)proxy - (DWORD)FunctionAddress - 5; 121 | SafeMemcpyPadded(FunctionAddress, Jump, 5); 122 | 123 | //Restore the original page protection 124 | VirtualProtect(FunctionAddress, TrampolineLength, OriginalProtection, &OriginalProtection); 125 | 126 | //Clear CPU instruction cache 127 | FlushInstructionCache(GetCurrentProcess(), FunctionAddress, TrampolineLength); 128 | 129 | *length = TrampolineLength; 130 | return TRUE; 131 | } 132 | 133 | BOOL UnhookFunction(CHAR *dll, CHAR *name, LPVOID original, DWORD length) 134 | { 135 | LPVOID FunctionAddress; 136 | DWORD OriginalProtection; 137 | 138 | FunctionAddress = GetProcAddress(GetModuleHandleA(dll), name); 139 | if(!FunctionAddress) 140 | return FALSE; 141 | 142 | if(!VirtualProtect(FunctionAddress, length, PAGE_EXECUTE_READWRITE, &OriginalProtection)) 143 | return FALSE; 144 | 145 | SafeMemcpyPadded(FunctionAddress, original, length); 146 | 147 | VirtualProtect(FunctionAddress, length, PAGE_EXECUTE_READWRITE, &OriginalProtection); 148 | 149 | FlushInstructionCache(GetCurrentProcess(), FunctionAddress, length); 150 | 151 | return TRUE; 152 | } 153 | 154 | int main() 155 | { 156 | HookAll(); 157 | 158 | MessageBoxA(NULL, "Hello", "MsgBoxA Test", MB_OK); 159 | MessageBoxA(NULL, "World", "MsgBoxA Test", MB_OK); 160 | 161 | MessageBoxW(NULL, L"Hello", L"MsgBoxW Test", MB_OK); 162 | MessageBoxW(NULL, L"World", L"MsgBoxW Test", MB_OK); 163 | 164 | UnhookAll(); 165 | getchar(); 166 | } 167 | 168 | -------------------------------------------------------------------------------- /BasicHook/hook.h: -------------------------------------------------------------------------------- 1 | typedef struct 2 | { 3 | CHAR *dll; 4 | CHAR *name; 5 | LPVOID proxy; 6 | LPVOID original; 7 | DWORD length; 8 | } HOOK_ARRAY; 9 | 10 | typedef int (WINAPI *TdefOldMessageBoxA)(HWND hWnd, LPCSTR lpText, LPCTSTR lpCaption, UINT uType); 11 | typedef int (WINAPI *TdefOldMessageBoxW)(HWND hWnd, LPWSTR lpText, LPCTSTR lpCaption, UINT uType); 12 | 13 | int WINAPI NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCTSTR lpCaption, UINT uType); 14 | int WINAPI NewMessageBoxW(HWND hWnd, LPWSTR lpText, LPCTSTR lpCaption, UINT uType); 15 | 16 | BOOL HookFunction(CHAR *dll, CHAR *name, LPVOID proxy, LPVOID original, PDWORD length); 17 | BOOL UnhookFunction(CHAR *dll, CHAR *name, LPVOID original, DWORD length); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BasicHook 2 | Hooks functions using 32-bit relative jump, writing is done atomically to avoid race conditions. 3 | Uses hde32 from instruction length disassembly. 4 | --------------------------------------------------------------------------------