對雙機調試的探索

最近學習遊戲保護,發現VM+WINDBG雙機調試不能使用,以遊戲保護*P爲例,經過論壇搜索,發現有以下幾點動了手腳:
1.   kdDebuggerEnabled變量不停的清零,清零的代碼還做了檢測,所以意味着不能輕易修改*P的代碼, 
kdDebuggerEnabled是windows全局變量,用來標識內核調試是否被啓用
開啓調試狀態:*(PBYTE)KdDebuggerEnabled=0x01;
禁止調試狀態:*(PBYTE)KdDebuggerEnabled=0x00;

2.   KiDebugRoutine變量不停設置爲KdpStub函數, 其寫入的代碼同上做了檢測,不能隨便修改
KiDebugRoutine是函數指針,內核調試引擎的異常處理回調函數指針。當內核調試引擎活動時,它指向KdpTrap函數,否則指向KdpStub函數

3.   KdSendPacket和KdReceivePacket函數的IAT HOOK,且在HOOK的地方也做了檢測,所以同樣不能簡單修改來達到目的
KdSendPacket KDCOM函數,發送數據包
KdReceivePacket KDCOM函數,接收數據包

以上就是*p的3塊防護及其含義,下面一塊一塊來探索一番

第一塊:
正常情況下ctrl+break中斷到windbg,
1
2
1: kd>  dd  kdDebuggerEnabled
83f9d96c  00000001 00000000 00000000 db1dbbbb
發現此時kdDebuggerEnabled爲1,
1
2
3
1: kd> ed kdDebuggerEnabled 0
1: kd>  dd  kdDebuggerEnabled
83f9d96c  00000000 00000000 00000000 db1dbbbb
修改後F5虛擬機跑起來,但是ctrl+break不能斷下了
首先想到觀察下ctrl+break的函數流程, 看看這個變量對流程中的哪個地方造成了阻礙,
雙機調試正常情況下ctrl+break中斷到windbg棧回溯如下:
1
2
3
4
5
00 807eaae0 83eb40cb nt!RtlpBreakWithStatusInstruction
01 807eaae8 83eb409d nt!KdCheckForDebugBreak+0x22
02 807eab98 83eb937f nt!KeUpdateRunTime+0x164
03 807eac20 83eb0e0d nt!PoIdle+0x524
04 807eac24 00000000 nt!KiIdleLoop+0xd
或者
1
2
3
4
5
00 807eaae0 83e950cb nt!RtlpBreakWithStatusInstruction
01 807eaae8 83e9509d nt!KdCheckForDebugBreak+0x22
02 807eab18 8422f430 nt!KeUpdateRunTime+0x164
03 807eab18 937d05d6 hal!HalpClockInterruptPn+0x158
...
無論從哪裏發起最後的幾個函數流程都是一樣KeUpdateRunTime-> KdCheckForDebugBreak-> RtlpBreakWithStatusInstruction
自然想看看這幾個函數中的代碼,看看是否和kdDebuggerEnabled有關,

1
2
3
4
5
6
7
8
9
1: kd> uf KeUpdateRunTime
後ctrl+F搜索kdDebuggerEnabled發現一處代碼
83eb4082 803d6cd9f98300   cmp      byte ptr [nt!KdDebuggerEnabled (83f9d96c)],0
83eb4089 7412            je      nt!KeUpdateRunTime+0x164 (83eb409d)
83eb408b a1740ff783      mov     eax,dword ptr [nt!KiPollSlot (83f70f74)]
83eb4090 3b86cc030000     cmp      eax,dword ptr [esi+3CCh]
83eb4096 7505            jne     nt!KeUpdateRunTime+0x164 (83eb409d)
83eb4098 e80c000000      call    nt!KdCheckForDebugBreak (83eb40a9)
83eb409d 5f              pop     edi
如果kdDebuggerEnabled爲0則跳到83eb409d,這樣就不會執行KdCheckForDebugBreak函數了,但是流程中KdCheckForDebugBreak函數必須要執行此函數後,ctrl+break才能斷下,所以證明了kdDebuggerEnabled設置爲0直接導致ctrl+break的失效,以此類推對餘下的兩個函數進行反彙編,發現如下代碼:

1
2
3
4
5
6
7
8
9
10
11
1: kd> uf KdCheckForDebugBreak
83eb40a9 803d271df68300   cmp      byte ptr [nt!KdPitchDebugger (83f61d27)],0
83eb40b0 7519            jne     nt!KdCheckForDebugBreak+0x22 (83eb40cb)
83eb40b2 803d6cd9f98300   cmp      byte ptr [nt!KdDebuggerEnabled (83f9d96c)],0
83eb40b9 7410            je      nt!KdCheckForDebugBreak+0x22 (83eb40cb)
83eb40bb e81f000000      call    nt!KdPollBreakIn (83eb40df)
83eb40c0 84c0             test     al,al
83eb40c2 7407            je      nt!KdCheckForDebugBreak+0x22 (83eb40cb)
83eb40c4 6a01            push    1
83eb40c6 e801000000      call    nt!DbgBreakPointWithStatus (83eb40cc)
83eb40cb c3              ret
可見此函數也用到了kdDebuggerEnabled變量,除此之外還可以發現2個問題:

1.   除了kdDebuggerEnabled變量,貌似KdPitchDebugger變量也比較重要,百度以下發現: 如果KdPitchDebugger爲TRUE,即在bcd中指定了nodebug,這樣也就不支持調試了,所以也算一個內核調試是否啓用的標誌,

2.   流程中KdCheckForDebugBreak調用的是RtlpBreakWithStatusInstruction,但是代碼中卻沒有發現他的調用,唯一調用的兩個函數是KdPollBreakIn和DbgBreakPointWithStatus,抱着試一試的心態反彙編這兩個函數發現:
1
2
3
4
5
6
1: kd> u DbgBreakPointWithStatus
nt!DbgBreakPointWithStatus:
83eb40cc 8b442404        mov     eax,dword ptr [esp+4]
nt!RtlpBreakWithStatusInstruction:
83eb40d0 cc              int     3
83eb40d1 c20400          ret     4
發現RtlpBreakWithStatusInstruction其實是DbgBreakPointWithStatus的一個標籤,所以流程中KdCheckForDebugBreak實際上是調用的DbgBreakPointWithStatus
由於KdCheckForDebugBreak中有對KdPollBreakIn的調用,所以順道反彙編以下KdPollBreakIn函數,偶然也發現一處和kdDebuggerEnabled相關的代碼:
1
83eb40fa 381d6cd9f983     cmp      byte ptr [nt!KdDebuggerEnabled (83f9d96c)],bl


總結一下上面的發現: 當把kdDebuggerEnabled設置爲0後,ctrl+break失效,跟蹤流程發現kdDebuggerEnabled和KdPitchDebugger標誌直接影響中斷到windbg,反彙編流程中的函數發現:
包含KdDebuggerEnabled的函數有:
KeUpdateRunTime
KdCheckForDebugBreak
KdPollBreakIn


包含KdPitchDebugger的函數有:
KdCheckForDebugBreak
KdPollBreakIn


接下來就是編程解決問題,思路是轉移變量,把這些函數中的KdDebuggerEnabled和KdPitchDebugger變量設置爲自己驅動模塊中的全局變量,部分代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//KdDebuggerEnabled 變量存儲
BOOLEAN gKdDebuggerEnabled=TRUE;
 
//KdPitchDebugger 變量存儲
BOOLEAN gKdPitchDebugger=FALSE;
 
// 轉移win7中的KdDebuggerEnabled和KdPitchDebugger變量
void MoveVariable_Win7(IN BOOL b***)
{
     ULONG ulAddr, ulAddr2;
 
     //---------------------------- 改寫KeUpdateRunTime中的KdDebuggerEnabled 
 
     // 得到原內核的KeUpdateRunTime地址
     ulAddr=GetOriginalProcAddr(L "KeUpdateRunTime" );
 
     // 定位KdDebuggerEnabled
     // 特徵碼
     //83ec9082  803d6c29fb8300   cmp      byte ptr [nt!KdDebuggerEnabled (83fb296c)],0
     //83ec9089  7412            je      nt!KeUpdateRunTime+0x164 (83ec909d)
     //83ec908b  a1745ff883      mov     eax,dword ptr [nt!KiPollSlot (83f85f74)]
     UCHAR szSig1[10] = {0x80, 0x3d,  '?' '?' '?' '?' '?' , 0x74, 0x12, 0xa1};
 
     // 特徵碼定位KdDebuggerEnabled
     ulAddr=SearchCode((PUCHAR)ulAddr, szSig1, 10, 0x200);
     ulAddr+=2;
 
     // 改寫KdDebuggerEnabled變量
     PageProtect(FALSE);
     *(PULONG)ulAddr=(ULONG)&gKdDebuggerEnabled;
     PageProtect(TRUE);
 
 
     //---------------------------- 改寫KdCheckForDebugBreak中的KdDebuggerEnabled
 
     // 得到KdCheckForDebugBreak地址
     // 特徵碼
     //83ec9098  e80c000000      call    nt!KdCheckForDebugBreak (83ec90a9)
     //83ec909d  5f              pop     edi
     UCHAR szSig2[6] = {0xe8,  '?' '?' '?' '?' , 0x5f};
     ulAddr=SearchCode((PUCHAR)ulAddr, szSig2, 6, 0x100);
     ulAddr=ulAddr+*(PULONG)((PUCHAR)ulAddr+1)+5;
 
     // 記錄KdCheckForDebugBreak函數地址 用於KdPitchDebugger變量的處理
     ulAddr2=ulAddr;
 
     // 特徵碼定位KdDebuggerEnabled
     //83ec90b2  803d6c29fb8300   cmp      byte ptr [nt!KdDebuggerEnabled (83fb296c)],0
     //83ec90b9  7410            je      nt!KdCheckForDebugBreak+0x22 (83ec90cb)
     //83ec90bb  e81f000000      call    nt!KdPollBreakIn (83ec90df)
     UCHAR szSig3[10] = {0x80, 0x3d,  '?' '?' '?' '?' '?' , 0x74, 0x10, 0xe8};
     ulAddr=SearchCode((PUCHAR)ulAddr, szSig3, 10, 0x100);
     ulAddr+=2;
 
     // 改寫KdDebuggerEnabled變量
     PageProtect(FALSE);
     *(PULONG)ulAddr=(ULONG)&gKdDebuggerEnabled;
     PageProtect(TRUE);
 
 
     //---------------------------- 改寫KdCheckForDebugBreak中的KdPitchDebugger
 
     // 定位KdPitchDebugger變量
     // 由於KdPitchDebugger變量在函數開頭偏移2處 所以直接偏移定位KdPitchDebugger
     //83eb30a9  803d270df68300   cmp      byte ptr [nt!KdPitchDebugger (83f60d27)],0
     //83eb30b0  7519            jne     nt!KdCheckForDebugBreak+0x22 (83eb30cb)
     ulAddr2+=2;
 
     // 改寫KdPitchDebugger變量
     PageProtect(FALSE);
     *(PULONG)ulAddr2=(ULONG)&gKdPitchDebugger;
     PageProtect(TRUE);
 
 
     //---------------------------- 改寫KdPollBreakIn中的KdDebuggerEnabled
 
     // 得到KdPollBreakIn地址
     // 特徵碼
     //83ebe0bb  e81f000000      call    nt!KdPollBreakIn (83ebe0df)
     //83ebe0c0  84c0             test     al,al
     UCHAR szSig4[7] = {0xe8,  '?' '?' '?' '?' , 0x84, 0xc0};
     ulAddr=SearchCode((PUCHAR)ulAddr, szSig4, 7, 0x100);
     ulAddr=ulAddr+*(PULONG)((PUCHAR)ulAddr+1)+5;
 
     // 記錄KdPollBreakIn函數地址 用於KdPitchDebugger變量的處理
     ulAddr2=ulAddr;
 
     // 特徵碼定位KdDebuggerEnabled
     //83ebe0f7  885dff          mov     byte ptr [ebp-1],bl
     //83ebe0fa  381d6c79fa83     cmp      byte ptr [nt!KdDebuggerEnabled (83fa796c)],bl
     //83ebe100  0f84c0000000    je      nt!KdPollBreakIn+0xe7 (83ebe1c6)
     UCHAR szSig5[11] = {0x88, 0x5d, 0xff, 0x38, 0x1d,  '?' '?' '?' '?' , 0x0f, 0x84};
     ulAddr=SearchCode((PUCHAR)ulAddr, szSig5, 11, 0x100);
     ulAddr+=5;
 
     // 改寫KdDebuggerEnabled變量
     PageProtect(FALSE);
     *(PULONG)ulAddr=(ULONG)&gKdDebuggerEnabled;
     PageProtect(TRUE);
 
 
     //---------------------------- 改寫KdPollBreakIn中的KdPitchDebugger
 
     // 特徵碼定位KdPitchDebugger
     //83eb30e6  33db            xor     ebx,ebx
     //83eb30e8  381d270df683     cmp      byte ptr [nt!KdPitchDebugger (83f60d27)],bl
     //83eb30ee  7407            je      nt!KdPollBreakIn+0x18 (83eb30f7)
     UCHAR szSig6[10] = {0x33, 0xdb, 0x38, 0x1d,  '?' '?' '?' '?' , 0x74, 0x07};
     ulAddr2=SearchCode((PUCHAR)ulAddr2, szSig6, 10, 0x100);
     ulAddr2+=4;
 
     // 改寫KdPitchDebugger變量
     PageProtect(FALSE);
     *(PULONG)ulAddr2=(ULONG)&gKdPitchDebugger;
     PageProtect(TRUE);
 
}
經過以上轉移以後 再次清零KdDebuggerEnabled變量後,也可以ctrl+break斷點到windbg中,第一塊問題就基本解決了

第二塊:
正常情況下觀察KiDebugRoutine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1: kd>  dd  KiDebugRoutine
83fa2b20  841664f2 83f16683 00000000 0311870a
83fa2b30  00000bb8 00000011 5385d2ba d717548f
83fa2b40  83eb7d5c 00000000 00000191 83eb83a4
83fa2b50  986fa000 00000000 00000339 986fb02c
83fa2b60  00000100 00000000 00000000 83fa2b68
83fa2b70  00000340 00000340 00000007 00000000
83fa2b80  86cdb6b8 86cdb5f0 86ce3838 86ce39c8
83fa2b90  86ce3900 00000000 86d37040 00000000
1: kd> u 841664f2 
nt!KdpTrap:
841664f2 8bff            mov     edi,edi
841664f4 55              push    ebp
841664f5 8bec            mov     ebp,esp
841664f7 51              push    ecx
841664f8 51              push    ecx
841664f9 8b4510          mov     eax,dword ptr [ebp+10h]
841664fc 33d2            xor     edx,edx
841664fe 813803000080     cmp      dword ptr [eax],80000003h

將其設置爲KdpStub函數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1: kd> ed KiDebugRoutine KdpStub
1: kd>  dd  KiDebugRoutine
83fa2b20  83f16983 83f16683 00000000 0311870a
83fa2b30  00000bb8 00000011 5385d2ba d717548f
83fa2b40  83eb7d5c 00000000 00000191 83eb83a4
83fa2b50  986fa000 00000000 00000339 986fb02c
83fa2b60  00000100 00000000 00000000 83fa2b68
83fa2b70  00000340 00000340 00000007 00000000
83fa2b80  86cdb6b8 86cdb5f0 86ce3838 86ce39c8
83fa2b90  86ce3900 00000000 86d37040 00000000
1: kd> u 83f16983 
nt!KdpStub:
83f16983 8bff            mov     edi,edi
83f16985 55              push    ebp
83f16986 8bec            mov     ebp,esp
83f16988 53              push    ebx
83f16989 56              push    esi
83f1698a 8b7510          mov     esi,dword ptr [ebp+10h]
83f1698d 33db            xor     ebx,ebx
83f1698f 813e03000080     cmp      dword ptr [esi],80000003h

Windbg F5運行起來,接着ctrl+break發現VM死機了,看來這個影響還蠻大的,重啓後IDA打開內核搜索全部KiDebugRoutine,發現調用它的代碼全部都在KiDispatchException中,反彙編KiDispatchException搜索KiDebugRoutine相關代碼,過程和第一塊一樣,發現以下三個結果:
1
2
3
83f04027 ff15208bfb83    call    dword ptr [nt!KiDebugRoutine (83fb8b20)]
83f0404f ff15208bfb83    call    dword ptr [nt!KiDebugRoutine (83fb8b20)]
83f040c8 ff15208bfb83    call    dword ptr [nt!KiDebugRoutine (83fb8b20)]
看來先前修改了KiDebugRoutine,造成的死機就是在KiDispatchException中出現的問題,現在編程解決問題,思路和上一塊一樣,轉移KiDebugRoutine變量,部分代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//KiDebugRoutine 變量存儲
ULONG gKiDebugRoutine=0;
 
// 轉移win7中的KiDebugRoutine變量
void MoveKiDebugRoutine_Win7(IN BOOL b***)
{
     // 得到KdpTrap地址
     ULONG ulAddr=GetOriginalProcAddr(L "KdpTrap" );
 
     // 設置自定義的KiDebugRoutine變量
     gKiDebugRoutine=ulAddr;
 
     // 得到原內核KiDispatchException地址
     ulAddr=GetOriginalProcAddr(L "KiDispatchException" );
 
     //--------------------------------------- 第一處KiDebugRoutine
     // 特徵碼定位KiDebugRoutine
     //83eb5027  ff15209bf683    call    dword ptr [nt!KiDebugRoutine (83f69b20)]
     //83eb502d  84c0             test     al,al
     UCHAR szSig[8] = {0xff, 0x15,  '?' '?' '?' '?' , 0x84, 0xc0};
     ulAddr=SearchCode((PUCHAR)ulAddr, szSig, 8, 0x200);
     if (!ulAddr)
     {
       KdPrint(( "\n[MoveKiDebugRoutine_Win7]: The signature is not found in KiDispatchException" ));
       return ;
     }
     ulAddr+=2; 
 
     // 改寫KiDebugRoutine變量
     PageProtect(FALSE);
     *(PULONG)ulAddr=(ULONG)&gKiDebugRoutine;
     PageProtect(TRUE);
 
 
     //--------------------------------------- 第二處KiDebugRoutine
     // 特徵碼與前邊一樣
     ulAddr=SearchCode((PUCHAR)ulAddr, szSig, 8, 0x200);
     ulAddr+=2; 
     // 改寫KiDebugRoutine變量
     PageProtect(FALSE);
     *(PULONG)ulAddr=(ULONG)&gKiDebugRoutine;
     PageProtect(TRUE);
 
 
     //--------------------------------------- 第三處KiDebugRoutine
     // 特徵碼與前邊一樣
     ulAddr=SearchCode((PUCHAR)ulAddr, szSig, 8, 0x200);
     ulAddr+=2; 
 
     // 改寫KiDebugRoutine變量
     PageProtect(FALSE);
     *(PULONG)ulAddr=(ULONG)&gKiDebugRoutine;
     PageProtect(TRUE);
}
這樣一來第二塊問題也基本解決了,這個和第一塊原理一樣,接下來就是第三塊了

第三塊:
反彙編KdSendPacket 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1: kd> u KdSendPacket
nt!KdSendPacket:
83e60200 ff25cc01e583    jmp     dword ptr [nt!_imp__KdSendPacket (83e501cc)]
83e60206 90              nop
83e60207 90              nop
83e60208 90              nop
83e60209 90              nop
83e6020a 90              nop
1: kd>  dd  83e501cc
83e501cc  80bc757c 80bc7170 80bc7160 80bc709c
83e501dc  80bc7150 00000000 8c8e3a04 8c8b5cb8
83e501ec  8c8b35bc 8c8e485c 8c8b5db0 8c8e37e0
83e501fc  8c8e7db2 8c8e4b4a 8c8e7df2 8c8e7538
83e5020c  8c8e4fd2 8c8c19d0 8c8b3586 8c8e2b44
83e5021c  8c8e4468 8c8e4a40 8c8e3c96 8c8e2f5e
83e5022c  8c8e2894 8c8c19d8 8c8e6e3e 8c8bde0c
83e5023c  8c8e810a 8c8e416a 8c8b5cee 8c8e7fc0
1: kd>  dd  83e501c8
83e501c8  80bc7300 80bc757c 80bc7170 80bc7160
1: kd> u 80bc757c 
80bc757c 8bff            mov     edi,edi
80bc757e 55              push    ebp
80bc757f 8bec            mov     ebp,esp
80bc7581 8b4510          mov     eax,dword ptr [ebp+10h]
80bc7584 83ec10          sub     esp,10h
80bc7587 53              push    ebx
80bc7588 33db            xor     ebx,ebx
80bc758a 56              push    esi
可以發現其他call KdSendPacket其實是通過jmp訪問了83e501cc地址裏邊的80bc757c,這裏的83e501cc也就是iat導入表中的地址,KdSendPacket函數屬於kdcom.dll,內核文件是引入的這個dll,IAT HOOK也就是把83e501cc地址裏邊的80bc757c修改成了自己的函數地址,80bc757c本來是真正的KdSendPacket函數地址,KdReceivePacket函數原理也是一樣,解決的思路是把call KdSendPacket的代碼修改爲call 80bc757c這樣就不經過iat表了,當然此方法牽涉的函數量比較大,部分代碼實現如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// 轉移KdSendPacket和KdReceivePacket相關的信息記錄
typedef struct _CODE_SIGN_KD
{
   UCHAR szFunSig[30];       // 函數特徵碼
   ULONG ulSigLen;         // 特徵碼長度
   ULONG ulOffset;         // 關鍵指令相對特徵碼的偏移
   PCHAR pFunName;         // 函數名稱
} CODE_SIGN_KD;
 
 
// 需要轉移的KdSendPacket相關的函數信息
CODE_SIGN_KD gKdSendPacketInfo_win7[]={
   {{0x6A, 0x02, 0xC7, 0x45, 0xC0, 0x46, 0x31, 0, 0, 0xE8,  '?' '?' '?' '?' , 0xE9,  '?' '?' '?' '?' , 0x6A, 0x38}, 21, 9,  "1.KdpSendWaitContinue" },
   {{0x50, 0x56, 0xE8,  '?' '?' '?' '?' , 0xE9,  '?' '?' '?' '?' , 0x53}, 13, 2,  "2.KdpSendWaitContinue" },
   {{0xFF, 0x75, 0x98, 0x6A, 0x07, 0xE8,  '?' '?' '?' '?' , 0x80, 0x3D,  '?' '?' '?' '?' , 0x00, 0x0F, 0x84, 0x66, 0xF9, 0xFF, 0xFF}, 23, 5,  "3.KdpSendWaitContinue" },
   {{0x66, 0x89, 0x74, 0x24, 0x20, 0x89, 0x7C, 0x24, 0x24, 0xE8,  '?' '?' '?' '?' , 0xE8,  '?' '?' '?' '?' , 0x5F}, 20, 9,  "4.KdpPrintString" },
   {{0x51, 0x8D, 0x45, 0xF8, 0x50, 0x6A, 0x02, 0xE8,  '?' '?' '?' '?' , 0x5F, 0x5E}, 14, 7,  "5.KdGetInternalBreakpoint" },
   {{0x53, 0x8D, 0x45, 0xF4, 0x50, 0x6A, 0x02, 0xE8,  '?' '?' '?' '?' , 0x5F, 0x5E}, 14, 7,  "6.KdpGetContext" },
   {{0x50, 0x6A, 0x02, 0xE8,  '?' '?' '?' '?' , 0x5B, 0xC9}, 10, 3,  "7.KdpSetContext" },
   {{0x50, 0x6A, 0x02, 0xE8,  '?' '?' '?' '?' , 0xC9, 0xC3}, 10, 3,  "8.KdpReadPhysicalMemory" },
   {{0x50, 0x6A, 0x02, 0xE8,  '?' '?' '?' '?' , 0x8B, 0x46, 0x14, 0xEB, 0x1B}, 13, 3,  "9.KdpWriteBreakPointEx" },
   {{0x6A, 0x02, 0xC7, 0x46, 0x08, 0x01, 0x00, 0x00, 0xC0, 0xE8,  '?' '?' '?' '?' , 0x8B, 0x46, 0x08, 0x5F}, 18, 9,  "10.KdpWriteBreakPointEx" },
   {{0x50, 0x6A, 0x02, 0xE8,  '?' '?' '?' '?' , 0x5F, 0x5B}, 10, 3,  "11.KdpRestoreBreakPointEx" },
   {{0x6A, 0x02, 0x89, 0x7D, 0xD0, 0xE8,  '?' '?' '?' '?' , 0x5E, 0x5B}, 12, 5,  "12.KdpSearchMemory" },
   {{0x89, 0x4E, 0x08, 0x89, 0x75, 0xDC, 0xE8,  '?' '?' '?' '?' , 0x5F, 0x5B}, 13, 6,  "13.KdpFillMemory" },
   {{0x89, 0x4C, 0x24, 0x24, 0x89, 0x74, 0x24, 0x1C, 0xE8,  '?' '?' '?' '?' , 0x5E, 0x8B, 0xE5}, 16, 8,  "14.KdpSendTraceData" },
   {{0x89, 0x4C, 0x24, 0x2C, 0x89, 0x74, 0x24, 0x24, 0xE8,  '?' '?' '?' '?' , 0x6A, 0x10, 0x58}, 16, 8,  "15.KdpPromptString" },
   {{0x50, 0x6A, 0x0B, 0xE8,  '?' '?' '?' '?' , 0x80, 0x3D,  '?' '?' '?' '?' , 0x00, 0x0F, 0x84, 0x79, 0xFF, 0xFF, 0xFF}, 21, 3,  "16.KdpCreateRemoteFile" },
   {{0x50, 0x6A, 0x0B, 0xE8,  '?'
相關文章
相關標籤/搜索