├── 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 |
--------------------------------------------------------------------------------