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为例,其反汇编如下:
nt!NtOpenFile:
8057b1a0 8bff mov edi, edi
8057b1a2 55 push ebp
8057b1a3 8bec mov ebp, esp
8057b1a5 33c0 xor eax, eax
8057b1a7 50 push eax
8057b1a8 50 push eax
8057b1a9 50 push eax
8057b1aa 50 push eax
8057b1ab 50 push eax
8057b1ac ff751c push dword ptr [ebp+1Ch]
8057b1af 6a01 push 1
8057b1b1 ff7518 push dword ptr [ebp+18h]
8057b1b4 50 push eax
8057b1b5 50 push eax
8057b1b6 ff7514 push dword ptr [ebp+14h]
8057b1b9 ff7510 push dword ptr [ebp+10h]
8057b1bc ff750c push dword ptr [ebp+0Ch]
8057b1bf ff7508 push dword ptr [ebp+8]
8057b1c2 e873c7ffff call nt!IoCreateFile (8057793a)
8057b1c7 5d pop ebp
8057b1c8 c21800 ret 18h
8057b1cb cc int 3
8057b1cc cc int 3
8057b1cd cc int 3
8057b1ce cc int 3
8057b1cf cc int 3
在这种情况下进行Near Jmp的Inline Hook正好,三条指令,5个字节长度。但也有例外情况。
如Windows XP SP3中的 NtOpenEvent:
nt!NtOpenEvent:
806101e0 6a18 push 18h
806101e2 68a0df4d80 push offset nt!ExTraceAllTables+0x1b (804ddfa0)
806101e7 e854cbf2ff call nt!_SEH_prolog (8053cd40)
806101ec 64a124010000 mov eax, dword ptr fs:[00000124h]
806101f2 8a9840010000 mov bl, byte ptr [eax+140h]
806101f8 885ddc mov byte ptr [ebp-24h], bl
806101fb 84db test bl, bl
806101fd 743c je nt!NtOpenEvent+0x5b (8061023b)
806101ff 8365fc00 and dword ptr [ebp-4], 0
80610203 8b7508 mov esi, dword ptr [ebp+8]
80610206 a134315680 mov eax, dword ptr [nt!MmUserProbeAddress (80563134)]
8061020b 3bf0 cmp esi, eax
8061020d 7206 jb nt!NtOpenEvent+0x35 (80610215)
8061020f c70000000000 mov dword ptr [eax], 0
80610215 8b06 mov eax, dword ptr [esi]
80610217 8906 mov dword ptr [esi], eax
80610219 834dfcff or dword ptr [ebp-4], 0FFFFFFFFh
8061021d eb1f jmp nt!NtOpenEvent+0x5e (8061023e)
8061021f 8b45ec mov eax, dword ptr [ebp-14h]
80610222 8b00 mov eax, dword ptr [eax]
80610224 8b00 mov eax, dword ptr [eax]
80610226 8945e0 mov dword ptr [ebp-20h], eax
80610229 e8c0400000 call nt!ExSystemExceptionFilter (806142ee)
8061022e c3 ret
......
发现第一条指令2字节,第二条指令5字节,对于使用Near Jmp的5字节来说,正好落在第2条指令中间,也就是说把一整条指令打断了,这样运行肯定会出问题。
所以需要一个计算每条指令长度的功能,来获取大于等于我们需要hook长度的最少完整指令长度,而 Hook Api lib 0.4 for C 这篇文章就提供了这个方法。
二、代码实现
直接上代码:
头文件
//
//deroko 的LDEX86的头文件定义
/*
C_MODRM for instructions that require MODRM
C_PREFIX for PREFIXES (SEG/REP)
C_2BYTE for instructions which opcode is 2 byte
*/
#define C_SIZE1 0x01
#define C_MODRM 0x02
#define C_DATA8 0x04
#define C_DATA16 0x08
#define C_DATA32 0x10
#define C_PREFIX 0x20
#define C_2BYTE 0x40
#define C_REL 0x80 //used to don't fuck up relative jmps with 67 prefix
#define C_66 0x66 //operand size prefix
#define C_67 0x67 //address size prefix
#define C_UNKNOWN 0x00
static BYTE table_1[256]={
/* 00 */ C_MODRM
/* 01 */, C_MODRM
/* 02 */, C_MODRM
/* 03 */, C_MODRM
/* 04 */, C_DATA8 // add al, ax, eax + 32imm w not set imm size = 8
/* 05 */, C_DATA32 // add al, ax, eax + 32imm w set imm size = 32
/* 06 */, C_SIZE1 //push es
/* 07 */, C_SIZE1 //pop es
/* 08 */, C_MODRM //or w set
/* 09 */, C_MODRM //or w not set :)
/* 0A */, C_MODRM
/* 0B */, C_MODRM
/* 0C */, C_DATA8 // or al/ax/eax shortcut
/* 0D */, C_DATA32 // or al/ax/eax shortcut
/* 0E */, C_SIZE1 // push cs
/* 0F */, C_2BYTE
/* 10 */, C_MODRM //adc w/d set mod rm, next 4
/* 11 */, C_MODRM
/* 12 */, C_MODRM
/* 13 */, C_MODRM
/* 14 */, C_DATA8 //adc al, imm8
/* 15 */, C_DATA32 //adc al, imm32
/* 16 */, C_SIZE1 //push ss
/* 17 */, C_SIZE1 //pop ss
/* 18 */, C_MODRM //sbb w set/not set
/* 19 */, C_MODRM
/* 1A */, C_MODRM //sbb d/w combinations
/* 1B */, C_MODRM //sbb d/w combinations
/* 1C */, C_DATA8 //sbb al, imm8
/* 1D */, C_DATA32 //sbb eax, imm32
/* 1E */, C_SIZE1 //push ds
/* 1F */, C_SIZE1 //pop ds
/* 20 */, C_MODRM //and mod/rm d/w bit combinations = 4
/* 21 */, C_MODRM
/* 22 */, C_MODRM
/* 23 */, C_MODRM //end and mod/rm d/w bit combinations
/* 24 */, C_DATA8 //and al, imm8
/* 25 */, C_DATA32 //and al, imm32
/* 26 */, C_PREFIX
/* 27 */, C_SIZE1 //daa
/* 28 */, C_MODRM //sub w/d mixup
/* 29 */, C_MODRM
/* 2A */, C_MODRM
/* 2B */, C_MODRM //sub w/d mixup end
/* 2C */, C_DATA8 //sub al, ax ,eax imm8
/* 2D */, C_DATA32 //sub al, ax, eax imm8
/* 2E */, C_PREFIX
/* 2F */, C_SIZE1 //das
/* 30 */, C_MODRM //xor next 4
/* 31 */, C_MODRM
/* 32 */, C_MODRM
/* 33 */, C_MODRM
/* 34 */, C_DATA8 //xor al, ax, eax imm 8 w not set (al)
/* 35 */, C_DATA32 //xor al, ax, eax imm 32 w set (eax)
/* 36 */, C_PREFIX
/* 37 */, C_SIZE1 //AAA
/* 38 */, C_MODRM //cmp d/w set 4 combinations
/* 39 */, C_MODRM //cmp
/* 3A */, C_MODRM //cmp
/* 3B */, C_MODRM //cmp
/* 3C */, C_DATA8 //cmp al, ax, eax imm 8
/* 3D */, C_DATA32 //cmp al, ax, eax imm 32
/* 3E */, C_PREFIX
/* 3F */, C_SIZE1 //AAS
/* 40 */, C_SIZE1 //inc reg (alternate encoding)
/* 41 */, C_SIZE1
/* 42 */, C_SIZE1
/* 43 */, C_SIZE1
/* 44 */, C_SIZE1
/* 45 */, C_SIZE1
/* 46 */, C_SIZE1
/* 47 */, C_SIZE1
/* 48 */, C_SIZE1 //dec reg (alternate encoding)
/* 49 */, C_SIZE1
/* 4A */, C_SIZE1
/* 4B */, C_SIZE1
/* 4C */, C_SIZE1
/* 4D */, C_SIZE1
/* 4E */, C_SIZE1
/* 4F */, C_SIZE1
/* 50 */, C_SIZE1
/* 51 */, C_SIZE1
/* 52 */, C_SIZE1
/* 53 */, C_SIZE1
/* 54 */, C_SIZE1
/* 55 */, C_SIZE1
/* 56 */, C_SIZE1
/* 57 */, C_SIZE1
/* 58 */, C_SIZE1 //pop reg
/* 59 */, C_SIZE1
/* 5A */, C_SIZE1
/* 5B */, C_SIZE1
/* 5C */, C_SIZE1
/* 5D */, C_SIZE1
/* 5E */, C_SIZE1
/* 5F */, C_SIZE1 //pop reg ends
/* 60 */, C_SIZE1 //pushad
/* 61 */, C_SIZE1 //popad
/* 62 */, C_MODRM //bound
/* 63 */, C_MODRM //arpl
/* 64 */, C_PREFIX
/* 65 */, C_PREFIX
/* 66 */, C_PREFIX
/* 67 */, C_PREFIX
/* 68 */, C_DATA32 //push immidiate 32
/* 69 */, C_MODRM + C_DATA32 //imul reg/reg imm32
/* 6A */, C_DATA8 //push imm 8
/* 6B */, C_MODRM + C_DATA8 //imul reg/reg imm8
/* 6C */, C_SIZE1 //ins w not set
/* 6D */, C_SIZE1 //ins w set
/* 6E */, C_SIZE1 //outs w not set
/* 6F */, C_SIZE1 //outs w set
/* 70 */, C_DATA8 + C_REL //jcc 8 bit displacement start
/* 71 */, C_DATA8 + C_REL
/* 72 */, C_DATA8 + C_REL
/* 73 */, C_DATA8 + C_REL
/* 74 */, C_DATA8 + C_REL
/* 75 */, C_DATA8 + C_REL
/* 76 */, C_DATA8 + C_REL
/* 77 */, C_DATA8 + C_REL
/* 78 */, C_DATA8 + C_REL
/* 79 */, C_DATA8 + C_REL
/* 7A */, C_DATA8 + C_REL
/* 7B */, C_DATA8 + C_REL
/* 7C */, C_DATA8 + C_REL
/* 7D */, C_DATA8 + C_REL
/* 7E */, C_DATA8 + C_REL
/* 7F */, C_DATA8 + C_REL //jcc 8 bit displacement ends
/* 80 */, C_MODRM + C_DATA8 //sub immidira/reg 32bit imm, also cmp modrm/imm32, also cmp
/* 81 */, C_MODRM + C_DATA32 //sub imidiate/reg 32bit imm, also cmp modrm/imm32, also cmp
/* 82 */, C_MODRM + C_DATA8 //sub or mod rm 8imm w not set, --||-- /imm8, also cmp
/* 83 */, C_MODRM + C_DATA8 //sub or mod rm 8imm w set set, --||-- /imm8, also cmp
/* 84 */, C_MODRM //test w not set
/* 85 */, C_MODRM //test w set
/* 86 */, C_MODRM //xchg w not set
/* 87 */, C_MODRM //xchg w set
/* 88 */, C_MODRM //mov not set w
/* 89 */, C_MODRM //mov set w
/* 8A */, C_MODRM //mov d set/not
/* 8B */, C_MODRM
/* 8C */, C_MODRM //mov reg/seg
/* 8D */, C_MODRM //lea
/* 8E */, C_MODRM //mov reg/seg I guess
/* 8F */, C_MODRM //pop reg/memory
/* 90 */, C_SIZE1 //nop
/* 91 */, C_SIZE1 //xchg al, ax, eax reg
/* 92 */, C_SIZE1
/* 93 */, C_SIZE1
/* 94 */, C_SIZE1
/* 95 */, C_SIZE1
/* 96 */, C_SIZE1
/* 97 */, C_SIZE1 //xchg al, ax, eax, ret ends
/* 98 */, C_SIZE1 //cbw, cwde
/* 99 */, C_SIZE1 //cdq, cwd
/* 9A */, C_DATA32 + C_DATA16 //far call (call unsinged full offset,selector)
/* 9B */, C_SIZE1 //wait//fwait
/* 9C */, C_SIZE1 //pushfd
/* 9D */, C_SIZE1 //popfd
/* 9E */, C_SIZE1 //sahf
/* 9F */, C_SIZE1 //LAHF
/* A0 */, C_DATA32 //mov al, ax, eax,mem full_offset
/* A1 */, C_DATA32 //mov al, ax, eax, mem full_offset
/* A2 */, C_DATA32 //mov mem, al, ax, eax full_offset
/* A3 */, C_DATA32 //mov mem, al, ax, eax full_offset
/* A4 */, C_SIZE1 //movsb
/* A5 */, C_SIZE1 //movsd
/* A6 */, C_SIZE1 //cmpsb... 2 of them w bit set
/* A7 */, C_SIZE1
/* A8 */, C_DATA8 //test al/ax/eax shortcut
/* A9 */, C_DATA32 //test al/ax/eax shortcut
/* AA */, C_SIZE1 //stosb
/* AB */, C_SIZE1 //stosd, or stosw + PREFIX 66
/* AC */, C_SIZE1 //lodsb
/* AD */, C_SIZE1 //lodsw + PREFIX 66 or lodsd
/* AE */, C_SIZE1 //scasb
/* AF */, C_SIZE1 //scasd
/* B0 */, C_DATA8 //mov reg, imm 8 alterante encoding
/* B1 */, C_DATA8
/* B2 */, C_DATA8
/* B3 */, C_DATA8
/* B4 */, C_DATA8
/* B5 */, C_DATA8
/* B6 */, C_DATA8
/* B7 */, C_DATA8
/* B8 */, C_DATA32 //mov immidiate to reg (alternate encoding)
/* B9 */, C_DATA32
/* BA */, C_DATA32
/* BB */, C_DATA32
/* BC */, C_DATA32
/* BD */, C_DATA32
/* BE */, C_DATA32
/* BF */, C_DATA32
/* C0 */, C_MODRM+C_DATA8 //rcl reg/mem by imm8 also rcr depends on opcode in modr/m field, also rol/ror
/* C1 */, C_MODRM+C_DATA8 //-----------||-----------
/* C2 */, C_DATA16
/* C3 */, C_SIZE1 //ret no args
/* C4 */, C_MODRM //les
/* C5 */, C_MODRM //lds
/* C6 */, C_MODRM+C_DATA8 // mov mem/imm
/* C7 */, C_MODRM+C_DATA32 //litle change (mov mem/imm)
/* C8 */, C_DATA8 + C_DATA16 //enter 16disp, 8bit level =4 size
/* C9 */, C_SIZE1
/* CA */, C_DATA16 //retf param
/* CB */, C_SIZE1 //retf no param
/* CC */, C_SIZE1
/* CD */, C_DATA8 //int, 8bit interupt number
/* CE */, C_SIZE1 //into
/* CF */, C_SIZE1 //iret
/* D0 */, C_MODRM //rcl reg/memory by 1 , also rcr, also ror/rol
/* D1 */, C_MODRM //same with w bit set , -||-
/* D2 */, C_MODRM //rcl register by cl , -||-
/* D3 */, C_MODRM //same with w bit set , -||- , also rol,ror
/* D4 */, C_DATA8 //aam 2 byte long but C_DATA8 is processed as 2 in my algo so this is ok
/* D5 */, C_DATA8 //aad 2 bytes long C_DATA8 is processed as 2 byte long
/* D6 */, C_SIZE1 //salc
/* D7 */, C_SIZE1 //xlat
/* D8 */, C_MODRM //all FPU are C_MODRM
/* D9 */, C_MODRM
/* DA */, C_MODRM
/* DB */, C_MODRM
/* DC */, C_MODRM
/* DD */, C_MODRM
/* DE */, C_MODRM
/* DF */, C_MODRM //end FPU instructions
/* E0 */, C_DATA8 + C_REL //loonz 8bit
/* E1 */, C_DATA8 + C_REL //loopz 8bit
/* E2 */, C_DATA8 + C_REL //loop 8bit
/* E3 */, C_DATA8 + C_REL //jecxz 8bit Address-size prefix indicates jcxz or jecxz
/* E4 */, C_DATA8 //in al, port
/* E5 */, C_DATA8 //in eax, port
/* E6 */, C_DATA8 //out port w not set (out 0, al)
/* E7 */, C_DATA8 //out port w set (out 0, eax)
/* E8 */, C_DATA32 + C_REL
/* E9 */, C_DATA32 + C_REL //jmp full displacement
/* EA */, C_DATA32 + C_DATA16 //jmp far full offset, selector
/* EB */, C_DATA8 //jmp 8 bit displacement
/* EC */, C_SIZE1 //in
/* ED */, C_SIZE1 //in
/* EE */, C_SIZE1 //out
/* EF */, C_SIZE1 //out
/* F0 */, C_PREFIX
/* F1 */, C_SIZE1 //int1
/* F2 */, C_PREFIX
/* F3 */, C_PREFIX
/* F4 */, C_SIZE1 //hlt
/* F5 */, C_SIZE1 //cmc
/* F6 */, C_MODRM + C_DATA8 //not (w not set), neg depends on opcode field in modrm, it can be test imm
/* F7 */, C_MODRM + C_DATA32 //not (w set) , neg depends on opcode field in modrm, it can be test imm
/* F8 */, C_SIZE1 //clc
/* F9 */, C_SIZE1 //stc
/* FA */, C_SIZE1 //cli
/* FB */, C_SIZE1 //sti
/* FC */, C_SIZE1 //cld
/* FD */, C_SIZE1 //std
/* FE */, C_MODRM //inc/dec w not set (modrm)
/* FF */, C_MODRM //inc/dec w set (modrm) //call also depends on reg/opcode field
}; //also jmp (depends on reg/opcode) fild
static BYTE table_2[256]={
/* 00 */ C_MODRM //lldt
/* 01 */, C_MODRM //invlpg
/* 02 */, C_MODRM //lar
/* 03 */, C_MODRM //LSL
/* 04 */, 0
/* 05 */, 0
/* 06 */, C_SIZE1 //clts
/* 07 */, 0
/* 08 */, C_SIZE1 //invd
/* 09 */, C_SIZE1
/* 0A */, 0
/* 0B */, 0
/* 0C */, 0
/* 0D */, 0
/* 0E */, 0
/* 0F */, 0
/* 10 */, 0
/* 11 */, 0
/* 12 */, 0
/* 13 */, 0
/* 14 */, 0
/* 15 */, 0
/* 16 */, 0
/* 17 */, 0
/* 18 */, 0
/* 19 */, 0
/* 1A */, 0
/* 1B */, 0
/* 1C */, 0
/* 1D */, 0
/* 1E */, 0
/* 1F */, 0
/* 20 */, C_MODRM //mov reg/crX
/* 21 */, C_MODRM //mov drX/reg
/* 22 */, C_MODRM //mov crX/reg and it foes all the way down
/* 23 */, C_MODRM //mov reg/drX
/* 24 */, 0
/* 25 */, 0
/* 26 */, 0
/* 27 */, 0
/* 28 */, 0
/* 29 */, 0
/* 2A */, 0
/* 2B */, 0
/* 2C */, 0
/* 2D */, 0
/* 2E */, 0
/* 2F */, 0
/* 30 */, C_SIZE1
/* 31 */, C_SIZE1
/* 32 */, C_SIZE1
/* 33 */, C_SIZE1
/* 34 */, C_SIZE1
/* 35 */, 0
/* 36 */, 0
/* 37 */, 0
/* 38 */, 0
/* 39 */, 0
/* 3A */, 0
/* 3B */, 0
/* 3C */, 0
/* 3D */, 0
/* 3E */, 0
/* 3F */, 0
/* 40 */, C_MODRM //conditional move
/* 41 */, C_MODRM
/* 42 */, C_MODRM
/* 43 */, C_MODRM
/* 44 */, C_MODRM
/* 45 */, C_MODRM
/* 46 */, C_MODRM
/* 47 */, C_MODRM
/* 48 */, C_MODRM
/* 49 */, C_MODRM
/* 4A */, C_MODRM
/* 4B */, C_MODRM
/* 4C */, C_MODRM
/* 4D */, C_MODRM
/* 4E */, C_MODRM
/* 4F */, C_MODRM //end conditional move
/* 50 */, 0
/* 51 */, 0
/* 52 */, 0
/* 53 */, 0
/* 54 */, 0
/* 55 */, 0
/* 56 */, 0
/* 57 */, 0
/* 58 */, 0
/* 59 */, 0
/* 5A */, 0
/* 5B */, 0
/* 5C */, 0
/* 5D */, 0
/* 5E */, 0
/* 5F */, 0
/* 60 */, 0
/* 61 */, 0
/* 62 */, 0
/* 63 */, 0
/* 64 */, 0
/* 65 */, 0
/* 66 */, 0
/* 67 */, 0
/* 68 */, 0
/* 69 */, 0
/* 6A */, 0
/* 6B */, 0
/* 6C */, 0
/* 6D */, 0
/* 6E */, 0
/* 6F */, 0
/* 70 */, 0
/* 71 */, 0
/* 72 */, 0
/* 73 */, 0
/* 74 */, 0
/* 75 */, 0
/* 76 */, 0
/* 77 */, 0
/* 78 */, 0
/* 79 */, 0
/* 7A */, 0
/* 7B */, 0
/* 7C */, 0
/* 7D */, 0
/* 7E */, 0
/* 7F */, 0
/* 80 */, C_DATA32 //jccs 2 byte long imm32
/* 81 */, C_DATA32
/* 82 */, C_DATA32
/* 83 */, C_DATA32
/* 84 */, C_DATA32
/* 85 */, C_DATA32
/* 86 */, C_DATA32
/* 87 */, C_DATA32
/* 88 */, C_DATA32
/* 89 */, C_DATA32
/* 8A */, C_DATA32
/* 8B */, C_DATA32
/* 8C */, C_DATA32
/* 8D */, C_DATA32
/* 8E */, C_DATA32
/* 8F */, C_DATA32 //jccs 2byte long ends imm32
/* 90 */, C_MODRM
/* 91 */, C_MODRM
/* 92 */, C_MODRM
/* 93 */, C_MODRM
/* 94 */, C_MODRM
/* 95 */, C_MODRM
/* 96 */, C_MODRM
/* 97 */, C_MODRM
/* 98 */, C_MODRM
/* 99 */, C_MODRM
/* 9A */, C_MODRM
/* 9B */, C_MODRM
/* 9C */, C_MODRM
/* 9D */, C_MODRM
/* 9E */, C_MODRM
/* 9F */, C_MODRM
/* A0 */, C_SIZE1 //push fs
/* A1 */, C_SIZE1 //pop fs
/* A2 */, C_SIZE1 //cpuid
/* A3 */, C_MODRM //bt reg/mem
/* A4 */, C_MODRM + C_DATA8
/* A5 */, C_MODRM
/* A6 */, 0
/* A7 */, 0
/* A8 */, C_SIZE1 //push gs
/* A9 */, C_SIZE1 //pop gs
/* AA */, C_SIZE1
/* AB */, C_MODRM //bts
/* AC */, C_MODRM + C_DATA8
/* AD */, C_MODRM
/* AE */, 0
/* AF */, C_MODRM //imul reg/reg or reg/mem
/* B0 */, C_MODRM //cmpxchg
/* B1 */, C_MODRM //cmpxchg
/* B2 */, C_MODRM //lss
/* B3 */, C_MODRM //btr
/* B4 */, C_MODRM //lfs
/* B5 */, C_MODRM //lgs
/* B6 */, C_MODRM //movzx
/* B7 */, C_MODRM //movzx
/* B8 */, 0
/* B9 */, 0
/* BA */, C_MODRM + C_DATA8 //bt imm8
/* BB */, C_MODRM //btc mod/rm
/* BC */, C_MODRM //BSF
/* BD */, C_MODRM //BSR
/* BE */, C_MODRM //movsx
/* BF */, C_MODRM //movsx
/* C0 */, C_MODRM //xadd
/* C1 */, C_MODRM //xadd
/* C2 */, 0
/* C3 */, 0
/* C4 */, 0
/* C5 */, 0
/* C6 */, 0
/* C7 */, 0
/* C8 */, C_SIZE1 //bswap eax
/* C9 */, C_SIZE1
/* CA */, C_SIZE1
/* CB */, C_SIZE1
/* CC */, C_SIZE1
/* CD */, C_SIZE1
/* CE */, C_SIZE1
/* CF */, C_SIZE1 //bswap reg ends
/* D0 */, 0
/* D1 */, 0
/* D2 */, 0
/* D3 */, 0
/* D4 */, 0
/* D5 */, 0
/* D6 */, 0
/* D7 */, 0
/* D8 */, 0
/* D9 */, 0
/* DA */, 0
/* DB */, 0
/* DC */, 0
/* DD */, 0
/* DE */, 0
/* DF */, 0
/* E0 */, 0
/* E1 */, 0
/* E2 */, 0
/* E3 */, 0
/* E4 */, 0
/* E5 */, 0
/* E6 */, 0
/* E7 */, 0
/* E8 */, 0
/* E9 */, 0
/* EA */, 0
/* EB */, 0
/* EC */, 0
/* ED */, 0
/* EE */, 0
/* EF */, 0
/* F0 */, 0
/* F1 */, 0
/* F2 */, 0
/* F3 */, 0
/* F4 */, 0
/* F5 */, 0
/* F6 */, 0
/* F7 */, 0
/* F8 */, 0
/* F9 */, 0
/* FA */, 0
/* FB */, 0
/* FC */, 0
/* FD */, 0
/* FE */, 0
/* FF */, 0
};
CPP文件
int GetOpCodeSize(PVOID Start)
{
BYTE opcode, * p, /*tempopcode,*/ instruction;
int size;
int opsizeprefix = 0, addressprefix = 0;
size = 0;
p = (PBYTE)Start;
opcode = *p;
//Proces PREFIXES!!! if any...
prefix_loop:
if (table_1[opcode] == C_PREFIX) {
if (opcode == C_66)
opsizeprefix = 1;
if (opcode == C_67)
addressprefix = 1;
size++;
p++;
opcode = *p;
goto prefix_loop;
}
//check for test, stupid and fucking test
instruction = table_1[opcode];
if ((opcode == 0xF6) || (opcode == 0xF7)) {
opcode = p[1];
if ((opcode & 0x38) != 0) //test or neg/not...
instruction = C_MODRM;
}
if (opsizeprefix)
//where was 8 still is 8 //where was 32 now is 16
if (instruction & C_DATA32) {
instruction &= ~(C_DATA32);
instruction |= C_DATA16;
}
//if not relative change
if (addressprefix && !(instruction & C_REL)) {
instruction &= ~(C_DATA32);
instruction &= ~(C_DATA8);
instruction |= C_DATA16;
}
//clear relative flag
if (instruction & C_REL)
instruction &= ~(C_REL);
//fill instruction with flags from table_2 and decode it in right way
if (instruction == C_2BYTE) {
size += 1;
p++;
instruction = table_2[*p];
//if (instruction == C_DATA32)
// size += 5;
//goto check_modrm;
}
size += 1; //opcode len;
//check_modrm:
if (instruction & C_MODRM) {
unsigned char modrm, sib;
size += 1;
p++;
modrm = *p;
if ((modrm >> 6) == 0 && (modrm & 0x07) == 0x05) //modrm is folowed by 32disp
size += 4;
if ((modrm >> 6) != 3 && (modrm & 0x07) == 0x04) { //sib
size++;
p++;
sib = *p;
if ((modrm >> 6) == 1 && (modrm & 0x07) == 0x04) //8bit disp after SIB(added to index)
size++;
if ((modrm >> 6) == 2 && (modrm & 0x07) == 0x04) //32bit displacement after sib(added to index)
size += 4;
if ((modrm >> 6) == 0 && (sib & 0x07) == 0x05)
size += 4;
} //SIB processing
TEST CODE//
if (modrm >= 0x40 && modrm <= 0x7f && (modrm & 0x07) != 0x04)
size += 1;
if (modrm >= 0x80 && modrm <= 0xbf && (modrm & 0x07) != 0x04)
size += 4;
///TEST CODE///
}
if (instruction & C_DATA32) //is this opcode opcode modrm immdata ???
size += 4;
if (instruction & C_DATA8)
size++;
if (instruction & C_DATA16)
size += 2;
if (instruction == C_UNKNOWN)
size += 1;
return size;
}
三、测试
测试循环打印出 NtOpenProcess 前50行指令,环境为WinXP x86 SP3.。
1.代码
#if DBG
#define KDPRINT(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, ##__VA_ARGS__ )
#else
#define KDPRINT(format, ...)
#endif
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pRegistryPath)
{
UNREFERENCED_PARAMETER(pDriverObject);
NTSTATUS ntStatus = STATUS_SUCCESS;
do
{
KDPRINT("【GetOpCodeX86】::【DriverEntry】DriverEntry! \n");
KDPRINT("【GetOpCodeX86】::【DriverEntry】Hello Kernel World! CurrentProcessId:0x%p CurrentIRQL:0x%u\n",
PsGetCurrentProcessId(),
KeGetCurrentIrql());
if (pRegistryPath != NULL)
{
KDPRINT("【GetOpCodeX86】::【DriverEntry】RegistryPath:%wZ \n", pRegistryPath);
}
pDriverObject->DriverUnload = DriverUnload;
PrintFunctionOpCode((PBYTE)NtOpenProcess);
} while (false);
return ntStatus;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
UNREFERENCED_PARAMETER(pDriverObject);
KDPRINT("【GetOpCodeX86】::【DriverUnload】DriverUnload CurrentProcessId:0x%p CurrentIRQL:0x%u\n",
PsGetCurrentProcessId(),
KeGetCurrentIrql());
}
VOID PrintFunctionOpCode(PBYTE pAddress)
{
ULONG ulGetOpCodeSingleSize = 0;
ULONG ulGetOpCodeTotalSize = 0;
ULONG nLines = 1;
while (nLines <= 50)
{
ulGetOpCodeSingleSize = GetOpCodeSize(pAddress + ulGetOpCodeTotalSize);
KDPRINT("【GetOpCodeX86】::【PrintFunctionOpCode】Line %03d, GetOpCodeSize:%d\r\n",
nLines, ulGetOpCodeSingleSize);
ulGetOpCodeTotalSize += ulGetOpCodeSingleSize;
nLines++;
}
}
2.输出结果:
3.Windbg反汇编结果
4.结论
通过对比可以看出前50条指令中每条指令长度都是正确计算出来的。
PS 附上库代码的CSDN下载链接
HookAPILib 0.4.rarhttps://download.csdn.net/download/zhuting__xf/36512669