Hook Api lib 0.4 for C原文及源代码地址链接《 [原创]Hook Api lib 0.4 for C 》
一、使用背景
最新在学习SSDT Inline Hook,一般在Hook开头进行一个JMP,例如Near Jmp,或者一个Far Jmp。
Near Jmp机器码为 E9 xx xx xx xx,一共五个字节;Far Jmp机器码为 EA xx xx xx xx 08 00,其中驱动中段址为08。
在Hook时保存原调用函数对应的字节数,然后修改其为跳转到自定义函数。
以Windows XP SP3中的 NtOpenFile为例,其反汇编如下:
1 0: kd> u nt!NtOpenFile nt!NtQueryEaFile-1
2 nt!NtOpenFile:
3 8057b1a0 8bff mov edi,edi
4 8057b1a2 55 push ebp
5 8057b1a3 8bec mov ebp,esp
6 8057b1a5 33c0 xor eax,eax
7 8057b1a7 50 push eax
8 8057b1a8 50 push eax
9 8057b1a9 50 push eax
10 8057b1aa 50 push eax
11 8057b1ab 50 push eax
12 8057b1ac ff751c push dword ptr [ebp+1Ch]
13 8057b1af 6a01 push 1
14 8057b1b1 ff7518 push dword ptr [ebp+18h]
15 8057b1b4 50 push eax
16 8057b1b5 50 push eax
17 8057b1b6 ff7514 push dword ptr [ebp+14h]
18 8057b1b9 ff7510 push dword ptr [ebp+10h]
19 8057b1bc ff750c push dword ptr [ebp+0Ch]
20 8057b1bf ff7508 push dword ptr [ebp+8]
21 8057b1c2 e873c7ffff call nt!IoCreateFile (8057793a)
22 8057b1c7 5d pop ebp
23 8057b1c8 c21800 ret 18h
24 8057b1cb cc int 3
25 8057b1cc cc int 3
26 8057b1cd cc int 3
27 8057b1ce cc int 3
28 8057b1cf cc int 3
在这种情况下进行Near Jmp的Inline Hook正好,三条指令,5个字节长度。但也有例外情况。
如Windows XP SP3中的 NtOpenEvent:
1 0: kd> u nt!NtOpenEvent L25
2 nt!NtOpenEvent:
3 806101e0 6a18 push 18h
4 806101e2 68a0df4d80 push offset nt!ExTraceAllTables+0x1b (804ddfa0)
5 806101e7 e854cbf2ff call nt!_SEH_prolog (8053cd40)
6 806101ec 64a124010000 mov eax,dword ptr fs:[00000124h]
7 806101f2 8a9840010000 mov bl,byte ptr [eax+140h]
8 806101f8 885ddc mov byte ptr [ebp-24h],bl
9 806101fb 84db test bl,bl
10 806101fd 743c je nt!NtOpenEvent+0x5b (8061023b)
11 806101ff 8365fc00 and dword ptr [ebp-4],0
12 80610203 8b7508 mov esi,dword ptr [ebp+8]
13 80610206 a134315680 mov eax,dword ptr [nt!MmUserProbeAddress (80563134)]
14 8061020b 3bf0 cmp esi,eax
15 8061020d 7206 jb nt!NtOpenEvent+0x35 (80610215)
16 8061020f c70000000000 mov dword ptr [eax],0
17 80610215 8b06 mov eax,dword ptr [esi]
18 80610217 8906 mov dword ptr [esi],eax
19 80610219 834dfcff or dword ptr [ebp-4],0FFFFFFFFh
20 8061021d eb1f jmp nt!NtOpenEvent+0x5e (8061023e)
21 8061021f 8b45ec mov eax,dword ptr [ebp-14h]
22 80610222 8b00 mov eax,dword ptr [eax]
23 80610224 8b00 mov eax,dword ptr [eax]
24 80610226 8945e0 mov dword ptr [ebp-20h],eax
25 80610229 e8c0400000 call nt!ExSystemExceptionFilter (806142ee)
26 8061022e c3 ret
27 ......
发现第一条指令2字节,第二条指令5字节,对于使用Near Jmp的5字节来说,正好落在第2条指令中间,也就是说把一整条指令打断了,这样运行肯定会出问题。
所以需要一个计算每条指令长度的功能,来获取大于等于我们需要hook长度的最少完整指令长度,而 Hook Api lib 0.4 for C 这篇文章就提供了这个方法。
二、代码实现
直接上代码:
头文件
1 //
2 //deroko 的LDEX86的头文件定义
3 /*
4 C_MODRM for instructions that require MODRM
5 C_PREFIX for PREFIXES (SEG/REP)
6 C_2BYTE for instructions which opcode is 2 byte
7 */
8 #define C_SIZE1 0x01
9 #define C_MODRM 0x02
10 #define C_DATA8 0x04
11 #define C_DATA16 0x08
12 #define C_DATA32 0x10
13 #define C_PREFIX 0x20
14 #define C_2BYTE 0x40
15 #define C_REL 0x80 //used to don't fuck up relative jmps with 67 prefix
16 #define C_66 0x66 //operand size prefix
17 #define C_67 0x67 //address size prefix
18
19 #define C_UNKNOWN 0x00
20
21 static BYTE table_1[256]={
22 /* 00 */ C_MODRM
23 /* 01 */, C_MODRM
24 /* 02 */, C_MODRM
25 /* 03 */, C_MODRM
26 /* 04 */, C_DATA8 // add al, ax, eax + 32imm w not set imm size = 8
27 /* 05 */, C_DATA32 // add al, ax, eax + 32imm w set imm size = 32
28 /* 06 */, C_SIZE1 //push es
29 /* 07 */, C_SIZE1 //pop es
30 /* 08 */, C_MODRM //or w set
31 /* 09 */, C_MODRM //or w not set :)
32 /* 0A */, C_MODRM
33 /* 0B */, C_MODRM
34 /* 0C */, C_DATA8 // or al/ax/eax shortcut
35 /* 0D */, C_DATA32 // or al/ax/eax shortcut
36 /* 0E */, C_SIZE1 // push cs
37 /* 0F */, C_2BYTE
38 /* 10 */, C_MODRM //adc w/d set mod rm, next 4
39 /* 11 */, C_MODRM
40 /* 12 */, C_MODRM
41 /* 13 */, C_MODRM
42 /* 14 */, C_DATA8 //adc al, imm8
43 /* 15 */, C_DATA32 //adc al, imm32
44 /* 16 */, C_SIZE1 //push ss
45 /* 17 */, C_SIZE1 //pop ss
46 /* 18 */, C_MODRM //sbb w set/not set
47 /* 19 */, C_MODRM
48 /* 1A */, C_MODRM //sbb d/w combinations
49 /* 1B */, C_MODRM //sbb d/w combinations
50 /* 1C */, C_DATA8 //sbb al, imm8
51 /* 1D */, C_DATA32 //sbb eax, imm32
52 /* 1E */, C_SIZE1 //push ds
53 /* 1F */, C_SIZE1 //pop ds
54 /* 20 */, C_MODRM //and mod/rm d/w bit combinations = 4
55 /* 21 */, C_MODRM
56 /* 22 */, C_MODRM
57 /* 23 */, C_MODRM //end and mod/rm d/w bit combinations
58 /* 24 */, C_DATA8 //and al, imm8
59 /* 25 */, C_DATA32 //and al, imm32
60 /* 26 */, C_PREFIX
61 /* 27 */, C_SIZE1 //daa
62 /* 28 */, C_MODRM //sub w/d mixup
63 /* 29 */, C_MODRM
64 /* 2A */, C_MODRM
65 /* 2B */, C_MODRM //sub w/d mixup end
66 /* 2C */, C_DATA8 //sub al, ax ,eax imm8
67 /* 2D */, C_DATA32 //sub al, ax, eax imm8
68 /* 2E */, C_PREFIX
69 /* 2F */, C_SIZE1 //das
70 /* 30 */, C_MODRM //xor next 4
71 /* 31 */, C_MODRM
72 /* 32 */, C_MODRM
73 /* 33 */, C_MODRM
74 /* 34 */, C_DATA8 //xor al, ax, eax imm 8 w not set (al)
75 /* 35 */, C_DATA32 //xor al, ax, eax imm 32 w set (eax)
76 /* 36 */, C_PREFIX
77 /* 37 */, C_SIZE1 //AAA
78 /* 38 */, C_MODRM //cmp d/w set 4 combinations
79 /* 39 */, C_MODRM //cmp
80 /* 3A */, C_MODRM //cmp
81 /* 3B */, C_MODRM //cmp
82 /* 3C */, C_DATA8 //cmp al, ax, eax imm 8
83 /* 3D */, C_DATA32 //cmp al, ax, eax imm 32
84 /* 3E */, C_PREFIX
85 /* 3F */, C_SIZE1 //AAS
86 /* 40 */, C_SIZE1 //inc reg (alternate encoding)
87 /* 41 */, C_SIZE1
88 /* 42 */, C_SIZE1
89 /* 43 */, C_SIZE1
90 /* 44 */, C_SIZE1
91 /* 45 */, C_SIZE1
92 /* 46 */, C_SIZE1
93 /* 47 */, C_SIZE1
94 /* 48 */, C_SIZE1 //dec reg (alternate encoding)
95 /* 49 */, C_SIZE1
96 /* 4A */, C_SIZE1
97 /* 4B */, C_SIZE1
98 /* 4C */, C_SIZE1
99 /* 4D */, C_SIZE1
100 /* 4E */, C_SIZE1
101 /* 4F */, C_SIZE1
102 /* 50 */, C_SIZE1
103 /* 51 */, C_SIZE1
104 /* 52 */, C_SIZE1
105 /* 53 */, C_SIZE1
106 /* 54 */, C_SIZE1
107 /* 55 */, C_SIZE1
108 /* 56 */, C_SIZE1
109 /* 57 */, C_SIZE1
110 /* 58 */, C_SIZE1 //pop reg
111 /* 59 */, C_SIZE1
112 /* 5A */, C_SIZE1
113 /* 5B */, C_SIZE1
114 /* 5C */, C_SIZE1
115 /* 5D */, C_SIZE1
116 /* 5E */, C_SIZE1
117 /* 5F */, C_SIZE1 //pop reg ends
118 /* 60 */, C_SIZE1 //pushad
119 /* 61 */, C_SIZE1 //popad
120 /* 62 */, C_MODRM //bound
121 /* 63 */, C_MODRM //arpl
122 /* 64 */, C_PREFIX
123 /* 65 */, C_PREFIX
124 /* 66 */, C_PREFIX
125 /* 67 */, C_PREFIX
126 /* 68 */, C_DATA32 //push immidiate 32
127 /* 69 */, C_MODRM + C_DATA32 //imul reg/reg imm32
128 /* 6A */, C_DATA8 //push imm 8
129 /* 6B */, C_MODRM + C_DATA8 //imul reg/reg imm8
130 /* 6C */, C_SIZE1 //ins w not set
131 /* 6D */, C_SIZE1 //ins w set
132 /* 6E */, C_SIZE1 //outs w not set
133 /* 6F */, C_SIZE1 //outs w set
134 /* 70 */, C_DATA8 + C_REL //jcc 8 bit displacement start
135 /* 71 */, C_DATA8 + C_REL
136 /* 72 */, C_DATA8 + C_REL
137 /* 73 */, C_DATA8 + C_REL
138 /* 74 */, C_DATA8 + C_REL
139 /* 75 */, C_DATA8 + C_REL
140 /* 76 */, C_DATA8 + C_REL
141 /* 77 */, C_DATA8 + C_REL
142 /* 78 */, C_DATA8 + C_REL
143 /* 79 */, C_DATA8 + C_REL
144 /* 7A */, C_DATA8 + C_REL
145 /* 7B */, C_DATA8 + C_REL
146 /* 7C */, C_DATA8 + C_REL
147 /* 7D */, C_DATA8 + C_REL
148 /* 7E */, C_DATA8 + C_REL
149 /* 7F */, C_DATA8 + C_REL //jcc 8 bit displacement ends
150 /* 80 */, C_MODRM + C_DATA8 //sub immidira/reg 32bit imm, also cmp modrm/imm32, also cmp
151 /* 81 */, C_MODRM + C_DATA32 //sub imidiate/reg 32bit imm, also cmp modrm/imm32, also cmp
152 /* 82 */, C_MODRM + C_DATA8 //sub or mod rm 8imm w not set, --||-- /imm8, also cmp
153 /* 83 */, C_MODRM + C_DATA8 //sub or mod rm 8imm w set set, --||-- /imm8, also cmp
154 /* 84 */, C_MODRM //test w not set
155 /* 85 */, C_MODRM //test w set
156 /* 86 */, C_MODRM //xchg w not set
157 /* 87 */, C_MODRM //xchg w set
158 /* 88 */, C_MODRM //mov not set w
159 /* 89 */, C_MODRM //mov set w
160 /* 8A */, C_MODRM //mov d set/not
161 /* 8B */, C_MODRM
162 /* 8C */, C_MODRM //mov reg/seg
163 /* 8D */, C_MODRM //lea
164 /* 8E */, C_MODRM //mov reg/seg I guess
165 /* 8F */, C_MODRM //pop reg/memory
166 /* 90 */, C_SIZE1 //nop
167 /* 91 */, C_SIZE1 //xchg al, ax, eax reg
168 /* 92 */, C_SIZE1
169 /* 93 */, C_SIZE1
170 /* 94 */, C_SIZE1
171 /* 95 */, C_SIZE1
172 /* 96 */, C_SIZE1
173 /* 97 */, C_SIZE1 //xchg al, ax, eax, ret ends
174 /* 98 */, C_SIZE1 //cbw, cwde
175 /* 99 */, C_SIZE1 //cdq, cwd
176 /* 9A */, C_DATA32 + C_DATA16 //far call (call unsinged full offset,selector)
177 /* 9B */, C_SIZE1 //wait//fwait
178 /* 9C */, C_SIZE1 //pushfd
179 /* 9D */, C_SIZE1 //popfd
180 /* 9E */, C_SIZE1 //sahf
181 /* 9F */, C_SIZE1 //LAHF
182 /* A0 */, C_DATA32 //mov al, ax, eax,mem full_offset
183 /* A1 */, C_DATA32 //mov al, ax, eax, mem full_offset
184 /* A2 */, C_DATA32 //mov mem, al, ax, eax full_offset
185 /* A3 */, C_DATA32 //mov mem, al, ax, eax full_offset
186 /* A4 */, C_SIZE1 //movsb
187 /* A5 */, C_SIZE1 //movsd
188 /* A6 */, C_SIZE1 //cmpsb... 2 of them w bit set
189 /* A7 */, C_SIZE1
190 /* A8 */, C_DATA8 //test al/ax/eax shortcut
191 /* A9 */, C_DATA32 //test al/ax/eax shortcut
192 /* AA */, C_SIZE1 //stosb
193 /* AB */, C_SIZE1 //stosd, or stosw + PREFIX 66
194 /* AC */, C_SIZE1 //lodsb
195 /* AD */, C_SIZE1 //lodsw + PREFIX 66 or lodsd
196 /* AE */, C_SIZE1 //scasb
197 /* AF */, C_SIZE1 //scasd
198 /* B0 */, C_DATA8 //mov reg, imm 8 alterante encoding
199 /* B1 */, C_DATA8
200 /* B2 */, C_DATA8
201 /* B3 */, C_DATA8
202 /* B4 */, C_DATA8
203 /* B5 */, C_DATA8
204 /* B6 */, C_DATA8
205 /* B7 */, C_DATA8
206 /* B8 */, C_DATA32 //mov immidiate to reg (alternate encoding)
207 /* B9 */, C_DATA32
208 /* BA */, C_DATA32
209 /* BB */, C_DATA32
210 /* BC */, C_DATA32
211 /* BD */, C_DATA32
212 /* BE */, C_DATA32
213 /* BF */, C_DATA32
214 /* C0 */, C_MODRM+C_DATA8 //rcl reg/mem by imm8 also rcr depends on opcode in modr/m field, also rol/ror
215 /* C1 */, C_MODRM+C_DATA8 //-----------||-----------
216 /* C2 */, C_DATA16
217 /* C3 */, C_SIZE1 //ret no args
218 /* C4 */, C_MODRM //les
219 /* C5 */, C_MODRM //lds
220 /* C6 */, C_MODRM+C_DATA8 // mov mem/imm
221 /* C7 */, C_MODRM+C_DATA32 //litle change (mov mem/imm)
222 /* C8 */, C_DATA8 + C_DATA16 //enter 16disp, 8bit level =4 size
223 /* C9 */, C_SIZE1
224 /* CA */, C_DATA16 //retf param
225 /* CB */, C_SIZE1 //retf no param
226 /* CC */, C_SIZE1
227 /* CD */, C_DATA8 //int, 8bit interupt number
228 /* CE */, C_SIZE1 //into
229 /* CF */, C_SIZE1 //iret
230 /* D0 */, C_MODRM //rcl reg/memory by 1 , also rcr, also ror/rol
231 /* D1 */, C_MODRM //same with w bit set , -||-
232 /* D2 */, C_MODRM //rcl register by cl , -||-
233 /* D3 */, C_MODRM //same with w bit set , -||- , also rol,ror
234 /* D4 */, C_DATA8 //aam 2 byte long but C_DATA8 is processed as 2 in my algo so this is ok
235 /* D5 */, C_DATA8 //aad 2 bytes long C_DATA8 is processed as 2 byte long
236 /* D6 */, C_SIZE1 //salc
237 /* D7 */, C_SIZE1 //xlat
238 /* D8 */, C_MODRM //all FPU are C_MODRM
239 /* D9 */, C_MODRM
240 /* DA */, C_MODRM
241 /* DB */, C_MODRM
242 /* DC */, C_MODRM
243 /* DD */, C_MODRM
244 /* DE */, C_MODRM
245 /* DF */, C_MODRM //end FPU instructions
246 /* E0 */, C_DATA8 + C_REL //loonz 8bit
247 /* E1 */, C_DATA8 + C_REL //loopz 8bit
248 /* E2 */, C_DATA8 + C_REL //loop 8bit
249 /* E3 */, C_DATA8 + C_REL //jecxz 8bit Address-size prefix indicates jcxz or jecxz
250 /* E4 */, C_DATA8 //in al, port
251 /* E5 */, C_DATA8 //in eax, port
252 /* E6 */, C_DATA8 //out port w not set (out 0, al)
253 /* E7 */, C_DATA8 //out port w set (out 0, eax)
254 /* E8 */, C_DATA32 + C_REL
255 /* E9 */, C_DATA32 + C_REL //jmp full displacement
256 /* EA */, C_DATA32 + C_DATA16 //jmp far full offset, selector
257 /* EB */, C_DATA8 //jmp 8 bit displacement
258 /* EC */, C_SIZE1 //in
259 /* ED */, C_SIZE1 //in
260 /* EE */, C_SIZE1 //out
261 /* EF */, C_SIZE1 //out
262 /* F0 */, C_PREFIX
263 /* F1 */, C_SIZE1 //int1
264 /* F2 */, C_PREFIX
265 /* F3 */, C_PREFIX
266 /* F4 */, C_SIZE1 //hlt
267 /* F5 */, C_SIZE1 //cmc
268 /* F6 */, C_MODRM + C_DATA8 //not (w not set), neg depends on opcode field in modrm, it can be test imm
269 /* F7 */, C_MODRM + C_DATA32 //not (w set) , neg depends on opcode field in modrm, it can be test imm
270 /* F8 */, C_SIZE1 //clc
271 /* F9 */, C_SIZE1 //stc
272 /* FA */, C_SIZE1 //cli
273 /* FB */, C_SIZE1 //sti
274 /* FC */, C_SIZE1 //cld
275 /* FD */, C_SIZE1 //std
276 /* FE */, C_MODRM //inc/dec w not set (modrm)
277 /* FF */, C_MODRM //inc/dec w set (modrm) //call also depends on reg/opcode field
278 }; //also jmp (depends on reg/opcode) fild
279
280 static BYTE table_2[256]={
281 /* 00 */ C_MODRM //lldt
282 /* 01 */, C_MODRM //invlpg
283 /* 02 */, C_MODRM //lar
284 /* 03 */, C_MODRM //LSL
285 /* 04 */, 0
286 /* 05 */, 0
287 /* 06 */, C_SIZE1 //clts
288 /* 07 */, 0
289 /* 08 */, C_SIZE1 //invd
290 /* 09 */, C_SIZE1
291 /* 0A */, 0
292 /* 0B */, 0
293 /* 0C */, 0
294 /* 0D */, 0
295 /* 0E */, 0
296 /* 0F */, 0
297 /* 10 */, 0
298 /* 11 */, 0
299 /* 12 */, 0
300 /* 13 */, 0
301 /* 14 */, 0
302 /* 15 */, 0
303 /* 16 */, 0
304 /* 17 */, 0
305 /* 18 */, 0
306 /* 19 */, 0
307 /* 1A */, 0
308 /* 1B */, 0
309 /* 1C */, 0
310 /* 1D */, 0
311 /* 1E */, 0
312 /* 1F */, 0
313 /* 20 */, C_MODRM //mov reg/crX
314 /* 21 */, C_MODRM //mov drX/reg
315 /* 22 */, C_MODRM //mov crX/reg and it foes all the way down
316 /* 23 */, C_MODRM //mov reg/drX
317 /* 24 */, 0
318 /* 25 */, 0
319 /* 26 */, 0
320 /* 27 */, 0
321 /* 28 */, 0
322 /* 29 */, 0
323 /* 2A */, 0
324 /* 2B */, 0
325 /* 2C */, 0
326 /* 2D */, 0
327 /* 2E */, 0
328 /* 2F */, 0
329 /* 30 */, C_SIZE1
330 /* 31 */, C_SIZE1
331 /* 32 */, C_SIZE1
332 /* 33 */, C_SIZE1
333 /* 34 */, C_SIZE1
334 /* 35 */, 0
335 /* 36 */, 0
336 /* 37 */, 0
337 /* 38 */, 0
338 /* 39 */, 0
339 /* 3A */, 0
340 /* 3B */, 0
341 /* 3C */, 0
342 /* 3D */, 0
343 /* 3E */, 0
344 /* 3F */, 0
345 /* 40 */, C_MODRM //conditional move
346 /* 41 */, C_MODRM
347 /* 42 */, C_MODRM
348 /* 43 */, C_MODRM
349 /* 44 */, C_MODRM
350 /* 45 */, C_MODRM
351 /* 46 */, C_MODRM
352 /* 47 */, C_MODRM
353 /* 48 */, C_MODRM
354 /* 49 */, C_MODRM
355 /* 4A */, C_MODRM
356 /* 4B */, C_MODRM
357 /* 4C */, C_MODRM
358 /* 4D */, C_MODRM
359 /* 4E */, C_MODRM
360 /* 4F */, C_MODRM //end conditional move
361 /* 50 */, 0
362 /* 51 */, 0
363 /* 52 */, 0
364 /* 53 */, 0
365 /* 54 */, 0
366 /* 55 */, 0
367 /* 56 */, 0
368 /* 57 */, 0
369 /* 58 */, 0
370 /* 59 */, 0
371 /* 5A */, 0
372 /* 5B */, 0
373 /* 5C */, 0
374 /* 5D */, 0
375 /* 5E */, 0
376 /* 5F */, 0
377 /* 60 */, 0
378 /* 61 */, 0
379 /* 62 */, 0
380 /* 63 */, 0
381 /* 64 */, 0
382 /* 65 */, 0
383 /* 66 */, 0
384 /* 67 */, 0
385 /* 68 */, 0
386 /* 69 */, 0
387 /* 6A */, 0
388 /* 6B */, 0
389 /* 6C */, 0
390 /* 6D */, 0
391 /* 6E */, 0
392 /* 6F */, 0
393 /* 70 */, 0
394 /* 71 */, 0
395 /* 72 */, 0
396 /* 73 */, 0
397 /* 74 */, 0
398 /* 75 */, 0
399 /* 76 */, 0
400 /* 77 */, 0
401 /* 78 */, 0
402 /* 79 */, 0
403 /* 7A */, 0
404 /* 7B */, 0
405 /* 7C */, 0
406 /* 7D */, 0
407 /* 7E */, 0
408 /* 7F */, 0
409 /* 80 */, C_DATA32 //jccs 2 byte long imm32
410 /* 81 */, C_DATA32
411 /* 82 */, C_DATA32
412 /* 83 */, C_DATA32
413 /* 84 */, C_DATA32
414 /* 85 */, C_DATA32
415 /* 86 */, C_DATA32
416 /* 87 */, C_DATA32
417 /* 88 */, C_DATA32
418 /* 89 */, C_DATA32
419 /* 8A */, C_DATA32
420 /* 8B */, C_DATA32
421 /* 8C */, C_DATA32
422 /* 8D */, C_DATA32
423 /* 8E */, C_DATA32
424 /* 8F */, C_DATA32 //jccs 2byte long ends imm32
425 /* 90 */, C_MODRM
426 /* 91 */, C_MODRM
427 /* 92 */, C_MODRM
428 /* 93 */, C_MODRM
429 /* 94 */, C_MODRM
430 /* 95 */, C_MODRM
431 /* 96 */, C_MODRM
432 /* 97 */, C_MODRM
433 /* 98 */, C_MODRM
434 /* 99 */, C_MODRM
435 /* 9A */, C_MODRM
436 /* 9B */, C_MODRM
437 /* 9C */, C_MODRM
438 /* 9D */, C_MODRM
439 /* 9E */, C_MODRM
440 /* 9F */, C_MODRM
441 /* A0 */, C_SIZE1 //push fs
442 /* A1 */, C_SIZE1 //pop fs
443 /* A2 */, C_SIZE1 //cpuid
444 /* A3 */, C_MODRM //bt reg/mem
445 /* A4 */, C_MODRM + C_DATA8
446 /* A5 */, C_MODRM
447 /* A6 */, 0
448 /* A7 */, 0
449 /* A8 */, C_SIZE1 //push gs
450 /* A9 */, C_SIZE1 //pop gs
451 /* AA */, C_SIZE1
452 /* AB */, C_MODRM //bts
453 /* AC */, C_MODRM + C_DATA8
454 /* AD */, C_MODRM
455 /* AE */, 0
456 /* AF */, C_MODRM //imul reg/reg or reg/mem
457 /* B0 */, C_MODRM //cmpxchg
458 /* B1 */, C_MODRM //cmpxchg
459 /* B2 */, C_MODRM //lss
460 /* B3 */, C_MODRM //btr
461 /* B4 */, C_MODRM //lfs
462 /* B5 */, C_MODRM //lgs
463 /* B6 */, C_MODRM //movzx
464 /* B7 */, C_MODRM //movzx
465 /* B8 */, 0
466 /* B9 */, 0
467 /* BA */, C_MODRM + C_DATA8 //bt imm8
468 /* BB */, C_MODRM //btc mod/rm
469 /* BC */, C_MODRM //BSF
470 /* BD */, C_MODRM //BSR
471 /* BE */, C_MODRM //movsx
472 /* BF */, C_MODRM //movsx
473 /* C0 */, C_MODRM //xadd
474 /* C1 */, C_MODRM //xadd
475 /* C2 */, 0
476 /* C3 */, 0
477 /* C4 */, 0
478 /* C5 */, 0
479 /* C6 */, 0
480 /* C7 */, 0
481 /* C8 */, C_SIZE1 //bswap eax
482 /* C9 */, C_SIZE1
483 /* CA */, C_SIZE1
484 /* CB */, C_SIZE1
485 /* CC */, C_SIZE1
486 /* CD */, C_SIZE1
487 /* CE */, C_SIZE1
488 /* CF */, C_SIZE1 //bswap reg ends
489 /* D0 */, 0
490 /* D1 */, 0
491 /* D2 */, 0
492 /* D3 */, 0
493 /* D4 */, 0
494 /* D5 */, 0
495 /* D6 */, 0
496 /* D7 */, 0
497 /* D8 */, 0
498 /* D9 */, 0
499 /* DA */, 0
500 /* DB */, 0
501 /* DC */, 0
502 /* DD */, 0
503 /* DE */, 0
504 /* DF */, 0
505 /* E0 */, 0
506 /* E1 */, 0
507 /* E2 */, 0
508 /* E3 */, 0
509 /* E4 */, 0
510 /* E5 */, 0
511 /* E6 */, 0
512 /* E7 */, 0
513 /* E8 */, 0
514 /* E9 */, 0
515 /* EA */, 0
516 /* EB */, 0
517 /* EC */, 0
518 /* ED */, 0
519 /* EE */, 0
520 /* EF */, 0
521 /* F0 */, 0
522 /* F1 */, 0
523 /* F2 */, 0
524 /* F3 */, 0
525 /* F4 */, 0
526 /* F5 */, 0
527 /* F6 */, 0
528 /* F7 */, 0
529 /* F8 */, 0
530 /* F9 */, 0
531 /* FA */, 0
532 /* FB */, 0
533 /* FC */, 0
534 /* FD */, 0
535 /* FE */, 0
536 /* FF */, 0
537 };
CPP文件
1 int GetOpCodeSize(PVOID Start)
2 {
3 BYTE opcode, * p, /*tempopcode,*/ instruction;
4 int size;
5 int opsizeprefix = 0, addressprefix = 0;
6 size = 0;
7 p = (PBYTE)Start;
8 opcode = *p;
9 //Proces PREFIXES!!! if any...
10 prefix_loop:
11 if (table_1[opcode] == C_PREFIX) {
12 if (opcode == C_66)
13 opsizeprefix = 1;
14 if (opcode == C_67)
15 addressprefix = 1;
16 size++;
17 p++;
18 opcode = *p;
19 goto prefix_loop;
20 }
21 //check for test, stupid and fucking test
22 instruction = table_1[opcode];
23 if ((opcode == 0xF6) || (opcode == 0xF7)) {
24 opcode = p[1];
25 if ((opcode & 0x38) != 0) //test or neg/not...
26 instruction = C_MODRM;
27
28 }
29 if (opsizeprefix)
30 //where was 8 still is 8 //where was 32 now is 16
31 if (instruction & C_DATA32) {
32 instruction &= ~(C_DATA32);
33 instruction |= C_DATA16;
34 }
35 //if not relative change
36 if (addressprefix && !(instruction & C_REL)) {
37 instruction &= ~(C_DATA32);
38 instruction &= ~(C_DATA8);
39 instruction |= C_DATA16;
40 }
41 //clear relative flag
42 if (instruction & C_REL)
43 instruction &= ~(C_REL);
44 //fill instruction with flags from table_2 and decode it in right way
45 if (instruction == C_2BYTE) {
46 size += 1;
47 p++;
48 instruction = table_2[*p];
49 //if (instruction == C_DATA32)
50 // size += 5;
51 //goto check_modrm;
52 }
53 size += 1; //opcode len;
54 //check_modrm:
55 if (instruction & C_MODRM) {
56 unsigned char modrm, sib;
57 size += 1;
58 p++;
59 modrm = *p;
60 if ((modrm >> 6) == 0 && (modrm & 0x07) == 0x05) //modrm is folowed by 32disp
61 size += 4;
62
63 if ((modrm >> 6) != 3 && (modrm & 0x07) == 0x04) { //sib
64 size++;
65 p++;
66 sib = *p;
67 if ((modrm >> 6) == 1 && (modrm & 0x07) == 0x04) //8bit disp after SIB(added to index)
68 size++;
69 if ((modrm >> 6) == 2 && (modrm & 0x07) == 0x04) //32bit displacement after sib(added to index)
70 size += 4;
71 if ((modrm >> 6) == 0 && (sib & 0x07) == 0x05)
72 size += 4;
73 } //SIB processing
74 TEST CODE//
75 if (modrm >= 0x40 && modrm <= 0x7f && (modrm & 0x07) != 0x04)
76 size += 1;
77 if (modrm >= 0x80 && modrm <= 0xbf && (modrm & 0x07) != 0x04)
78 size += 4;
79 ///TEST CODE///
80 }
81 if (instruction & C_DATA32) //is this opcode opcode modrm immdata ???
82 size += 4;
83 if (instruction & C_DATA8)
84 size++;
85 if (instruction & C_DATA16)
86 size += 2;
87 if (instruction == C_UNKNOWN)
88 size += 1;
89 return size;
90 }
三、测试
测试循环打印出 NtOpenProcess 前50行指令,环境为WinXP x86 SP3.。
1.代码
1 #if DBG 2 #define KDPRINT(projectName, format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, projectName "::【" __FUNCTION__ "】" ##format, ##__VA_ARGS__ ) 3 #else 4 #define KDPRINT(format, ...) 5 #endif 6 7 8 NTSTATUS DriverEntry( 9 PDRIVER_OBJECT pDriverObject, 10 PUNICODE_STRING pRegistryPath) 11 { 12 UNREFERENCED_PARAMETER(pDriverObject); 13 NTSTATUS ntStatus = STATUS_SUCCESS; 14 do 15 { 16 KDPRINT("【GetOpCodeX86】","DriverEntry! \n"); 17 18 KDPRINT("【GetOpCodeX86】","Hello Kernel World! CurrentProcessId:0x%p CurrentIRQL:0x%u\n", 19 PsGetCurrentProcessId(), 20 KeGetCurrentIrql()); 21 22 if (pRegistryPath != NULL) 23 { 24 KDPRINT("【GetOpCodeX86】","RegistryPath:%wZ \n", pRegistryPath); 25 } 26 pDriverObject->DriverUnload = DriverUnload; 27 28 PrintFunctionOpCode((PBYTE)NtOpenProcess); 29 30 } while (false); 31 32 return ntStatus; 33 } 34 35 VOID DriverUnload( 36 PDRIVER_OBJECT pDriverObject) 37 { 38 UNREFERENCED_PARAMETER(pDriverObject); 39 KDPRINT("【GetOpCodeX86】"," CurrentProcessId:0x%p CurrentIRQL:0x%u\n", 40 PsGetCurrentProcessId(), 41 KeGetCurrentIrql()); 42 } 43 44 VOID PrintFunctionOpCode(PBYTE pAddress) 45 { 46 ULONG ulGetOpCodeSingleSize = 0; 47 ULONG ulGetOpCodeTotalSize = 0; 48 ULONG nLines = 1; 49 while (nLines <= 50) 50 { 51 ulGetOpCodeSingleSize = GetOpCodeSize(pAddress + ulGetOpCodeTotalSize); 52 KDPRINT("【GetOpCodeX86】","Line %03d, GetOpCodeSize:%d\r\n", 53 nLines, ulGetOpCodeSingleSize); 54 ulGetOpCodeTotalSize += ulGetOpCodeSingleSize; 55 nLines++; 56 } 57 }
2.输出结果(WinXP SP3):
3.Windbg反汇编结果
4.结论
通过对比可以看出前50条指令中每条指令长度都是正确计算出来的。