日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

【原創(chuàng)】OllyDBG分析報(bào)告系列(1)

 herowuking 2015-05-31
標(biāo) 題: 【原創(chuàng)】OllyDBG分析報(bào)告系列(1)---Int3斷點(diǎn)
作 者: driverox
時(shí) 間: 2008-05-19,16:45:43
鏈 接: http://bbs./showthread.php?t=65094

最近學(xué)習(xí)逆向,對(duì)OD本身做了個(gè)逆向,也算是一個(gè)小小的鍛煉吧。呵呵,在這里以分析報(bào)告的形式貼出來(lái),請(qǐng)大家批評(píng)指正。謝謝。

Ollydbg(以下均簡(jiǎn)稱為OD)中的Int3斷點(diǎn)的主要功能是:在需要下斷點(diǎn)的執(zhí)行代碼處將原來(lái)的代碼改成0xCC,程序執(zhí)行到此處后會(huì)報(bào)一個(gè)Int3異常,由OD捕獲并處理。當(dāng)要執(zhí)行該行代碼時(shí),將原來(lái)的代碼改回來(lái)并執(zhí)行,然后再恢復(fù)斷點(diǎn),這樣就不會(huì)影響程序的正常運(yùn)行了。
這里僅描述最常見(jiàn)的功能,其它的有興趣的話可以分析一把。

先說(shuō)明一下OD中的兩個(gè)結(jié)構(gòu)體,在IDA中,聲明為如下格式:
t_bpoint用來(lái)保存Int斷點(diǎn)的相關(guān)信息
00000000 t_bpoint        struc ; (sizeof=0x11)
00000000 addr         dd ?                    ; // Address of breakpoint
00000004 dummy      dd ?                    ; // Always 1
00000008 type         dd ?                    ; // Type of breakpoint, TY_xxx
0000000C cmd         db ?                    ; // Old value of command
0000000D passcount    dd ?                    ; // Actual pass count
00000011 t_bpoint        ends
其中:addr為斷點(diǎn)的地址,dummy始終為1,type為斷點(diǎn)的類(lèi)型,cmd為要用0xCC替換的指令碼,passcount為需要斷下的次數(shù),0表示每次都斷下。

t_sorted結(jié)構(gòu)體保存了一種有序的數(shù)據(jù):
00000000 ; Descriptor of sorted table
00000000 t_sorted        struc ; (sizeof=0x138)
00000000 name[MAXPATH]   db 260 dup(?)     ; char  Name of table, as appears in error messages
00000104 n               dd ?                    ; int  Actual number of entries
00000108 nmax            dd ?                    ; int  Maximal number of entries
0000010C selected        dd ?                    ; int  Index of selected entry or -1
00000110 seladdr         dd ?                    ; ulong  Base address of selected entry
00000114 itemsize        dd ?                    ; int  Size of single entry
00000118 version         dd ?                    ; ulong  Unique version of table
0000011C data            dd ?                    ; void*  Elements, sorted by address
00000120 sortfunc        dd ?                  ; SORTFUNC  Function which sorts data or NULL
00000124 destfunc        dd ?                    ; DESTFUNC  Destructor function or NULL
00000128 sort            dd ?                    ; int  Sorting criterium (column)
0000012C sorted          dd ?                    ; int  Whether indexes are sorted
00000130 index           dd ?                    ; int  Indexes, sorted by criterium
00000134 suppresserr     dd ?                    ; int  Suppress multiple overflow errors
00000138 t_sorted        ends
name是結(jié)構(gòu)體的名稱,用來(lái)區(qū)別不同類(lèi)型的結(jié)構(gòu)體
n是數(shù)組元素的個(gè)數(shù)
itemsize是數(shù)組元素的大小
data 是指向各種數(shù)據(jù)結(jié)構(gòu)數(shù)組的指針,這里使用的是int3斷點(diǎn),所以現(xiàn)在保存的是int3斷點(diǎn)數(shù)據(jù)結(jié)構(gòu)體數(shù)組的指針
---------------------------------------------------------------------------------------------------------------------------------

1)Int3斷點(diǎn)的設(shè)置
int3斷點(diǎn)的設(shè)置是通過(guò)消息來(lái)處理的,對(duì)應(yīng)右鍵點(diǎn)擊菜單中的切換,其對(duì)應(yīng)的消息為1E;此外還有熱鍵F2、雙擊反匯編窗口等也能切換int3斷點(diǎn),轉(zhuǎn)入的函數(shù)雖然不同,但是調(diào)用設(shè)置int3斷點(diǎn)的函數(shù)都是同一個(gè),就不再舉例了。傳入相應(yīng)參數(shù)調(diào)用函數(shù)00419974,改變int3斷點(diǎn),該函數(shù)的調(diào)用處如下:
004237C8   .  51                    push    ecx    ; |Arg6
004237C9   .  50                    push    eax    ; |Arg5 => 00000002
004237CA   .  6A 00                 push    0      ; |Arg4 = 00000000
004237CC   .  6A 00                 push    0      ; |Arg3 = 00000000
004237CE   .  6A 71                 push    71     ; |Arg2 = 00000071
004237D0   .  52                    push    edx    ; |Arg1 => 0040100C
004237D1   .  E8 9E61FFFF           call    00419974   ; \OLLYDBG.00419974

下面主要來(lái)分析上述的00419974這個(gè)函數(shù),經(jīng)過(guò)分析可知大致主要流程為:

1.    判斷是否配置了“Warn when break not in code”為1,若為1的話,程序會(huì)先判斷所下斷點(diǎn)是否在代碼區(qū),不在的話,會(huì)顯示警告消息,若用戶選擇繼續(xù),則會(huì)斷下,否則退出;
2.    若沒(méi)有配置上面的項(xiàng)目,則首先獲得斷點(diǎn)的類(lèi)型(即斷點(diǎn)類(lèi)型的高位是否為2,若為2則刪除斷點(diǎn),不為2則設(shè)置斷點(diǎn)),檢查該地址的斷點(diǎn)是否已經(jīng)存在,若存在,則刪除斷點(diǎn),并退出;
3.    若該地址處無(wú)Int3斷點(diǎn),則設(shè)置斷點(diǎn),使用的是Setbreakpointext函數(shù),其流程如下:
a)  獲得斷點(diǎn)在調(diào)試進(jìn)程中實(shí)際地址;
b)  判斷指令碼是否有效(判斷規(guī)則是:指令碼與1F做與運(yùn)算之后為3或13的時(shí)候,說(shuō)明是斷在指令碼中間;1D、1E、1F是正常指令碼,除此之外,其它的都是無(wú)法執(zhí)行的指令碼),無(wú)效的話,重新設(shè)置CPU窗口,顯示錯(cuò)誤提示并退出;
c)  在t_sorted結(jié)構(gòu)中查找斷點(diǎn)數(shù)據(jù);
d)  若t_sorted中不存在該斷點(diǎn),則添加;
e)  判斷被調(diào)試進(jìn)程是否在運(yùn)行狀態(tài),若在運(yùn)行,則把所有的線程都掛起;
f)  讀取斷點(diǎn)所在地址的內(nèi)存,若讀取成功的話,調(diào)用WriteMemory寫(xiě)入0xCC斷點(diǎn)(跟入WriteMemory后,發(fā)現(xiàn)是調(diào)用WriteProcessMemory這個(gè)API函數(shù)來(lái)下Int3斷點(diǎn)的);
g)  恢復(fù)線程運(yùn)行;
h)  顯示信息在窗口中;
4.  若設(shè)置斷點(diǎn)成功,則插入name并做其它的一些判斷與顯示操作,進(jìn)而退出;

保存現(xiàn)場(chǎng),提升棧幀空間,用于存放局部變量:
00419974  /$  55         push    ebp
00419975  |.  8BEC       mov     ebp, esp
00419977  |.  81C4 F8FBF>add     esp, -408
0041997D  |.  53         push    ebx
0041997E  |.  56         push    esi
0041997F  |.  57         push    edi
檢查OD配置文件中的   “Warn when break not in code”是否為1,1為真,0為假,若上面的配置為0,則跳到下面的處理代碼中:
00419980  |.  8B7D 14    mov     edi, dword ptr [ebp+14]
00419983  |.  8B5D 08    mov     ebx, dword ptr [ebp+8]
00419986  |.  833D C4574>cmp     dword ptr [4D57C4], 0  ; 4D57C4--Warn when break not in code
0041998D  |.  74 5E      je      short 004199ED  ;為0則跳轉(zhuǎn)到下面的處理代碼
檢查傳入的參數(shù)是否正確:
0041998F  |.  837D 0C 71 cmp     dword ptr [ebp+C], 71
00419993  |.  75 12      jnz     short 004199A7
00419995  |.  837D 10 00 cmp     dword ptr [ebp+10], 0
00419999  |.  75 0C      jnz     short 004199A7
先在t_sorted列表中查找int3斷點(diǎn),找不到返回8,并跳過(guò)取得模塊信息部分:
0041999B  |.  53         push    ebx
0041999C  |.  E8 D703000>call    _Getbreakpointtype
004199A1  |.  F6C4 02    test    ah, 2    ;檢查返回值是否為20h
004199A4  |.  59         pop     ecx
004199A5  |.  75 46      jnz     short 004199ED  ;不是則跳過(guò)取得模塊信息部分
取得模塊信息,并檢查是否取得,若取得失敗則跳轉(zhuǎn)到顯示斷點(diǎn)錯(cuò)誤消息分支:
004199A7  |>  53         push    ebx                       ; /Arg1
004199A8  |.  E8 6B44040>call    _Findmodule               ; \_Findmodule
004199AD  |.  59         pop     ecx
004199AE  |.  8BF0       mov     esi, eax
004199B0  |.  85C0       test    eax, eax  ;檢查是否得到模塊信息
004199B2  |.  74 0F      je      short 004199C3  ;沒(méi)有得到則跳轉(zhuǎn)到下面錯(cuò)誤顯示分支
004199B4  |.  3B5E 0C    cmp     ebx, dword ptr [esi+C]
004199B7  |.  72 0A      jb      short 004199C3
004199B9  |.  8B56 0C    mov     edx, dword ptr [esi+C]
004199BC  |.  0356 10    add     edx, dword ptr [esi+10]
004199BF  |.  3BDA       cmp     ebx, edx
004199C1  |.  72 2A      jb      short 004199ED
顯示斷點(diǎn)錯(cuò)誤消息,若用戶選擇Yes則繼續(xù),否則退出:
004199C3  |>  68 2421000>push    2124                              ; /Style = MB_YESNO
004199C8  |.  68 40274B0>push    004B2740                           ; |Title
004199CD  |.  68 C3284B0>push    004B28C3                          ; |Text
004199D2  |.  8B0D 7C3B4>mov     ecx, dword ptr [4D3B7C]              ; |
004199D8  |.  51         push    ecx                               ; |hOwner
004199D9  |.  E8 385B090>call    <jmp.&USER32.MessageBoxA>           ; \MessageBoxA
004199DE  |.  8BF0       mov     esi, eax
004199E0  |.  83FE 06    cmp     esi, 6
004199E3  |.  74 08      je      short 004199ED
004199E5  |.  83C8 FF    or      eax, FFFFFFFF  ;返回-1
004199E8  |.  E9 8403000>jmp     00419D71  ;跳轉(zhuǎn)到結(jié)束處
得到該地址int3斷點(diǎn)的屬性,如果已經(jīng)設(shè)置了int3斷點(diǎn),則將其刪除并跳轉(zhuǎn)到結(jié)束處;若沒(méi)有設(shè)置,則跳過(guò)刪除部分代碼:
004199ED  |>  837D 0C 71 cmp     dword ptr [ebp+C], 71
004199F1  |.  0F85 24020>jnz     00419C1B
004199F7  |.  837D 10 00 cmp     dword ptr [ebp+10], 0
004199FB  |.  75 20      jnz     short 00419A1D
004199FD  |.  53         push    ebx
004199FE  |.  E8 7503000>call    _Getbreakpointtype  ;得到該地址的int3斷點(diǎn)的屬性
00419A03  |.  F6C4 02    test    ah, 2    ;比較是否已經(jīng)設(shè)置了int3斷點(diǎn)
00419A06  |.  59         pop     ecx
00419A07  |.  74 14      je      short 00419A1D  ;若沒(méi)有設(shè)置則跳過(guò)刪除斷點(diǎn)的代碼
00419A09  |.  6A 00      push    0                         ; /Arg3 = 00000000
00419A0B  |.  8D53 01    lea     edx, dword ptr [ebx+1]    ; |
00419A0E  |.  52         push    edx                       ; |Arg2
00419A0F  |.  53         push    ebx                       ; |Arg1
00419A10  |.  E8 03FBFFF>call    _Deletebreakpoints        ; \_Deletebreakpoints
00419A15  |.  83C4 0C    add     esp, 0C
00419A18  |.  E9 4103000>jmp     00419D5E
在這里有對(duì)傳入?yún)?shù)的一個(gè)比較,但是測(cè)試時(shí)無(wú)法得到0以外的值,所以無(wú)法確定該參數(shù)的作用,這樣也無(wú)法測(cè)試00419A6D后面的代碼所表示的意義:
00419A1D  |>  837D 10 00 cmp     dword ptr [ebp+10], 0
00419A21  |.  75 4A      jnz     short 00419A6D
這里就是設(shè)置int3斷點(diǎn)的函數(shù),將地址傳入即可:
00419A23  |.  6A 00      push    0                         ; /Arg4 = 00000000
00419A25  |.  6A 00      push    0                         ; |Arg3 = 00000000
00419A27  |.  68 0002020>push    20200                     ; |Arg2 = 00020200
00419A2C  |.  53         push    ebx                       ; |Arg1
00419A2D  |.  E8 2EFBFFF>call    _Setbreakpointext         ; \_Setbreakpointext
00419A32  |.  83C4 10    add     esp, 10
設(shè)置完int3斷點(diǎn)后,刪除int3斷點(diǎn)處的name屬性為38h、3Ch、3Bh以及30h的name,然后跳轉(zhuǎn)到結(jié)束廣播處:
00419A35  |.  8D73 01    lea     esi, dword ptr [ebx+1]
00419A38  |.  6A 38      push    38                        ; /Arg3 = 00000038
00419A3A  |.  56         push    esi                       ; |Arg2
00419A3B  |.  53         push    ebx                       ; |Arg1
00419A3C  |.  E8 87B5040>call    _Deletenamerange          ; \_Deletenamerange
00419A41  |.  83C4 0C    add     esp, 0C
00419A44  |.  6A 3C      push    3C                        ; /Arg3 = 0000003C
00419A46  |.  56         push    esi                       ; |Arg2
00419A47  |.  53         push    ebx                       ; |Arg1
00419A48  |.  E8 7BB5040>call    _Deletenamerange          ; \_Deletenamerange
00419A4D  |.  83C4 0C    add     esp, 0C
00419A50  |.  6A 3B      push    3B                        ; /Arg3 = 0000003B
00419A52  |.  56         push    esi                       ; |Arg2
00419A53  |.  53         push    ebx                       ; |Arg1
00419A54  |.  E8 6FB5040>call    _Deletenamerange          ; \_Deletenamerange
00419A59  |.  83C4 0C    add     esp, 0C
00419A5C  |.  6A 30      push    30                        ; /Arg3 = 00000030
00419A5E  |.  56         push    esi                       ; |Arg2
00419A5F  |.  53         push    ebx                       ; |Arg1
00419A60  |.  E8 63B5040>call    _Deletenamerange          ; \_Deletenamerange
00419A65  |.  83C4 0C    add     esp, 0C
00419A68  |.  E9 F102000>jmp     00419D5E      ;跳轉(zhuǎn)到結(jié)束廣播處
這部分省略的代碼無(wú)法得知其調(diào)用的必要條件,不過(guò)里面的內(nèi)容跟上面相似,都是通過(guò)判斷來(lái)設(shè)置int3斷點(diǎn),這里就不再詳細(xì)說(shuō)明了:
……
……
向子窗體發(fā)送廣播,要求更新所有子窗口:
00419D5E  |>  6A 00      push    0                         ; /Arg3 = 00000000
00419D60  |.  6A 00      push    0                         ; |Arg2 = 00000000
00419D62  |.  68 7404000>push    474                       ; |Arg1 = 00000474
00419D67  |.  E8 0807040>call    _Broadcast                ; \_Broadcast
00419D6C  |.  83C4 0C    add     esp, 0C
最后返回0,并且恢復(fù)現(xiàn)場(chǎng):
00419D6F  |.  33C0       xor     eax, eax
00419D71  |>  5F         pop     edi
00419D72  |.  5E         pop     esi
00419D73  |.  5B         pop     ebx
00419D74  |.  8BE5       mov     esp, ebp
00419D76  |.  5D         pop     ebp
00419D77  \.  C3         retn

2)Int3斷點(diǎn)的處理
Int3斷點(diǎn)處理的大致流程是:
1、  獲取當(dāng)前寄存器的信息,重點(diǎn)是Eip的值
2、  根據(jù)Int3斷點(diǎn)的類(lèi)型(0xCC或0xCD03)回溯指針地址
3、  觸發(fā)Int3異常,被調(diào)試程序斷下;
4、  若繼續(xù)跑的話,則恢復(fù)原有的指令,讓被調(diào)試程序正確執(zhí)行指令;
5、  走完正確指令之后,再重新設(shè)置指令為Int3斷點(diǎn);

在OD中有一個(gè)處理所有異常的函數(shù)42EBD0,從該函數(shù)入手分析Int3斷點(diǎn)的處理。
0042EBD0  /$  55            push    ebp
0042EBD1  |.  8BEC          mov     ebp, esp
0042EBD3  |.  81C4 04F0FFFF add     esp, -0FFC
0042EBD9  |.  50            push    eax
0042EBDA  |.  81C4 00F5FFFF add     esp, -0B00
0042EBE0  |.  53            push    ebx
0042EBE1  |.  56            push    esi
0042EBE2  |.  57            push    edi  ;以上是開(kāi)棧幀代碼

0042EBE3  |.  8B35 1C574D00 mov     esi, dword ptr [4D571C] ;4D571C為全局變量,保存的是DebugEvent.dwThreadId
0042EBE9  |.  56            push    esi
0042EBEA  |.  E8 5DF8FFFF   call    0042E44C
函數(shù)42E44C的主要功能描述如下:

函數(shù)功能:通過(guò)GetThreadContext的方法獲得線程的上下文環(huán)境,把該環(huán)境保存
          至OD線程信息結(jié)構(gòu)中的reg字段中,若oldreg已經(jīng)失效,則復(fù)制reg的
          值到oldreg中。
          若被調(diào)試進(jìn)程有多個(gè)線程,則循環(huán)取值,保存至OD線程信息結(jié)構(gòu)數(shù)組中。
傳入?yún)?shù):DebugEvent.dwThreadId 
返回值  :成功時(shí)為保存在OD線程信息結(jié)構(gòu)中的當(dāng)前寄存器信息結(jié)構(gòu)的指針(主線程)
          失敗返回0

這里說(shuō)到了兩個(gè)結(jié)構(gòu)體,在IDA中描述如下:
00000000 t_reg           struc ; (sizeof=0x196)    ;保存寄存器信息
00000000 r_modified      dd ?                    ; // Some regs modified, update context
00000004 r_modifiedbyuser dd ?                   ; // Among modified, some modified by user
00000008 r_singlestep    dd ?                    ; // Type of single step, SS_xxx
0000000C r_EAX           dd ?
00000010 r_ECX           dd ?
00000014 r_EDX           dd ?
00000018 r_EBX           dd ?
0000001C r_ESP           dd ?
00000020 r_EBP           dd ?
00000024 r_ESI           dd ?
00000028 r_EDI           dd ?
0000002C r_EIP           dd ?                    ; // Instruction pointer (EIP)
00000030 r_EFlags        dd ?                    ; // Flags
00000034 r_top           dd ?                    ; // Index of top-of-stack
00000038 r_long_double   db 80 dup(?)            ; // Float registers, f[top] - top of stack
00000088 r_tag           db 8 dup(?)             ; // Float tags (0x3 - empty register)
00000090 r_fst           dd ?                    ; // FPU status word
00000094 r_fcw           dd ?                    ; // FPU control word
00000098 r_ES            dd ?
0000009C r_CS            dd ?
000000A0 r_SS            dd ?
000000A4 r_DS            dd ?
000000A8 r_FS            dd ?
000000AC r_GS            dd ?
000000B0 r_base          dd 6 dup(?)             ; // Segment bases
000000C8 r_limit         dd 6 dup(?)             ; // Segment limits
000000E0 r_big           db 6 dup(?)             ; // Default size (0-16, 1-32 bit)
000000E6 r_dr6           dd ?                    ; // Debug register DR6
000000EA r_threadid      dd ?                    ; // ID of thread that owns registers
000000EE r_lasterror     dd ?                    ; // Last thread error or 0xFFFFFFFF
000000F2 r_ssevalid      dd ?                    ; // Whether SSE registers valid
000000F6 r_ssemodified   dd ?                    ; // Whether SSE registers modified
000000FA r_ssereg        db 128 dup(?)           ; // SSE registers
0000017A r_mxcsr         dd ?                    ; // SSE control and status register
0000017E r_selected      dd ?                    ; // Reports selected register to plugin
00000182 r_dr0           dd ?                    ; // Debug registers DR0..DR3
00000186 r_dr1           dd ?
0000018A r_dr2           dd ?
0000018E r_dr3           dd ?
00000192 r_dr7           dd ?                    ; // Debug register DR7
00000196 t_reg           ends
00000196
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 t_thread        struc ; (sizeof=0x66C)  ;保存線程信息,同時(shí)有新舊兩份reg值,可以用來(lái)在OD的寄存器窗口為改變的值設(shè)置顏色等功能。
00000000 th_threadid     dd ?                    ; // Thread identifier
00000004 th_dummy        dd ?                    ; // Always 1
00000008 th_type         dd ?                    ; // Service information, TY_xxx
0000000C th_thread       dd ?                    ; // Thread handle
00000010 th_datablock    dd ?                    ; // Per-thread data block
00000014 th_entry        dd ?                    ; // Thread entry point
00000018 th_stacktop     dd ?                    ; // Working variable of Listmemory()
0000001C th_stackbottom  dd ?                    ; // Working variable of Listmemory()
00000020 th_context      CONTEXT ?               ; // Actual context of the thread
000002EC th_reg          t_reg ?                 ; // Actual contents of registers
00000482 th_regvalid     dd ?                    ; // Whether reg is valid
00000486 th_oldreg       t_reg ?                 ; // Previous contents of registers
0000061C th_oldregvalid  dd ?                    ; // Whether oldreg is valid
00000620 th_suspendcount dd ?                    ; // Suspension count (may be negative)
00000624 th_usertime     dd ?                    ; // Time in user mode, 1/10th ms, or -1
00000628 th_systime      dd ?                    ; // Time in system mode, 1/10th ms, or -1
0000062C th_reserved     dd 16 dup(?)            ; // Reserved for future compatibility
0000066C t_thread        ends


下面的代碼是:
0042EBEF  |.  8BF8               mov     edi, eax
0042EBF1  |.  8B45 08            mov     eax, dword ptr [ebp+8]
0042EBF4  |.  59                 pop     ecx
0042EBF5  |.  8938               mov     dword ptr [eax], edi
0042EBF7  |.  8B15 14574D00      mov     edx, dword ptr [4D5714]   ; 4D5714中保存的是調(diào)試事件的代碼DebugEvent.dwDebugEventCode
0042EBFD  |.  83FA 09            cmp     edx, 9                 ;  Switch (cases 1..9)
0042EC00  |.  0F87 EE270000      ja      004313F4
0042EC06  |.  FF2495 0DEC4200    jmp     dword ptr [edx*4+42EC0D]  ; 這里是switch跳轉(zhuǎn)
用來(lái)判斷是何種異常:
0042EC0D  |.  F4134300           dd      OLLYDBG.004313F4  ; EXCEPTION_DEBUG_EVENT
0042EC11  |. |35EC4200           dd      OLLYDBG.0042EC35
0042EC15  |. |FF0C4300           dd      OLLYDBG.00430CFF
0042EC19  |. |D70D4300           dd      OLLYDBG.00430DD7
0042EC1D  |. |3F0F4300           dd      OLLYDBG.00430F3F
0042EC21  |. |37104300           dd      OLLYDBG.00431037
0042EC25  |. |2D114300           dd      OLLYDBG.0043112D
0042EC29  |. |B7114300           dd      OLLYDBG.004311B7
0042EC2D  |. |76124300           dd      OLLYDBG.00431276
0042EC31  |. |C7134300           dd      OLLYDBG.004313C7

0042EC35  |> \8B0D 0C364E00      mov     ecx, dword ptr [4E360C]              ;  Case 1 of switch 0042EBFD
0042EC3B  |.  33C0               xor     eax, eax
0042EC3D  |.  894D EC            mov     dword ptr [ebp-14], ecx
0042EC40  |.  A3 0C364E00        mov     dword ptr [4E360C], eax
0042EC45  |.  C745 A4 20574D00   mov     dword ptr [ebp-5C], 004D5720
0042EC4C  |.  85FF               test    edi, edi  ;檢查主線程中是否有當(dāng)前寄存器的信息;
0042EC4E  |.  75 0D              jnz     short 0042EC5D
0042EC50  |.  8B55 A4            mov     edx, dword ptr [ebp-5C]
0042EC53  |.  33DB               xor     ebx, ebx
0042EC55  |.  8B4A 0C            mov     ecx, dword ptr [edx+C]
0042EC58  |.  894D D8            mov     dword ptr [ebp-28], ecx
0042EC5B  |.  EB 22              jmp     short 0042EC7F
0042EC5D  |>  8B47 2C            mov     eax, dword ptr [edi+2C]              ;  ntdll.7C921231
0042EC60  |.  8945 D8            mov     dword ptr [ebp-28], eax  ;這一段是把異常地址賦給局部變量ebp-28
0042EC63  |.  837D EC 00         cmp     dword ptr [ebp-14], 0
0042EC67  |.  8B5F 10            mov     ebx, dword ptr [edi+10]
0042EC6A  |.  74 13              je      short 0042EC7F

以下代碼是判斷產(chǎn)生中斷的指令碼是0xCC還是0xCD03,若是0xCC,則指令碼要回溯1(因?yàn)镋ip指向下一條指令,回溯后才是正確的斷點(diǎn)地址),若是0xCD03,則指令碼要回溯2,其它的不回溯。
0042EC6C  |.  F647 31 01         test    byte ptr [edi+31], 1
0042EC70  |.  74 0D              je      short 0042EC7F
0042EC72  |.  8167 30 FFFEFFFF   and     dword ptr [edi+30], FFFFFEFF
0042EC79  |.  C707 01000000      mov     dword ptr [edi], 1
0042EC7F  |>  8B45 A4            mov     eax, dword ptr [ebp-5C]
0042EC82  |.  8138 03000080      cmp     dword ptr [eax], 80000003          ;  Int3中斷
0042EC88  |.  74 07              je      short 0042EC91
0042EC8A  |.  33D2               xor     edx, edx
0042EC8C  |.  8955 DC            mov     dword ptr [ebp-24], edx
0042EC8F  |.  EB 79              jmp     short 0042ED0A
0042EC91  |>  6A 02              push    2                         ; /Arg4 = 00000002
0042EC93  |.  6A 01              push    1                         ; |Arg3 = 00000001
0042EC95  |.  8B4D D8            mov     ecx, dword ptr [ebp-28]             ; |
0042EC98  |.  49                 dec     ecx                   ; |減一是讓指令碼回溯
0042EC99  |.  51                 push    ecx                              ; |Arg2
0042EC9A  |.  8D45 BB            lea     eax, dword ptr [ebp-45]              ; |
0042EC9D  |.  50                 push    eax                              ; |Arg1
0042EC9E  |.  E8 69260300        call    _Readmemory                 ; \_Readmemory
0042ECA3  |.  83C4 10            add     esp, 10
0042ECA6  |.  83F8 01            cmp     eax, 1
0042ECA9  |.  74 07              je      short 0042ECB2
0042ECAB  |.  33D2               xor     edx, edx
0042ECAD  |.  8955 DC            mov     dword ptr [ebp-24], edx
0042ECB0  |.  EB 58              jmp     short 0042ED0A
0042ECB2  |>  33C0               xor     eax, eax
0042ECB4  |.  8A45 BB            mov     al, byte ptr [ebp-45]
0042ECB7  |.  3D CC000000        cmp     eax, 0CC
0042ECBC  |.  75 09              jnz     short 0042ECC7
0042ECBE  |.  C745 DC 01000000   mov     dword ptr [ebp-24], 1        ;  若Readmemory在斷點(diǎn)地址讀的指令碼是CC的話,ebp-24設(shè)為1---ebp-24保存的是要回溯的指令長(zhǎng)度
0042ECC5  |.  EB 43              jmp     short 0042ED0A
0042ECC7  |>  83F8 03            cmp     eax, 3
0042ECCA  |.  74 07              je      short 0042ECD3
0042ECCC  |.  33D2               xor     edx, edx
0042ECCE  |.  8955 DC            mov     dword ptr [ebp-24], edx
0042ECD1  |.  EB 37              jmp     short 0042ED0A
0042ECD3  |>  6A 02              push    2                         ; /Arg4 = 00000002
0042ECD5  |.  6A 01              push    1                         ; |Arg3 = 00000001
0042ECD7  |.  8B4D D8            mov     ecx, dword ptr [ebp-28]      ; |
0042ECDA  |.  83E9 02            sub     ecx, 2                     ; |指令碼回溯2
0042ECDD  |.  51                 push    ecx                       ; |Arg2
0042ECDE  |.  8D45 BB            lea     eax, dword ptr [ebp-45]        ; |
0042ECE1  |.  50                 push    eax                        ; |Arg1
0042ECE2  |.  E8 25260300        call    _Readmemory              ; \_Readmemory
0042ECE7  |.  83C4 10            add     esp, 10
0042ECEA  |.  83F8 01            cmp     eax, 1
0042ECED  |.  75 0D              jnz     short 0042ECFC
0042ECEF  |.  33D2               xor     edx, edx
0042ECF1  |.  8A55 BB            mov     dl, byte ptr [ebp-45]
0042ECF4  |.  81FA CD000000      cmp     edx, 0CD
0042ECFA  |.  74 07              je      short 0042ED03
0042ECFC  |>  33C9               xor     ecx, ecx
0042ECFE  |.  894D DC            mov     dword ptr [ebp-24], ecx
0042ED01  |.  EB 07              jmp     short 0042ED0A
0042ED03  |>  C745 DC 02000000   mov     dword ptr [ebp-24], 2
0042ED0A  |>  8B45 DC            mov     eax, dword ptr [ebp-24]
0042ED0D  |.  2945 D8            sub     dword ptr [ebp-28], eax      ;  回溯指令碼,才是正確的斷點(diǎn)地址
0042ED10  |.  8B15 08574D00      mov     edx, dword ptr [4D5708]
0042ED16  |.  3B55 D8            cmp     edx, dword ptr [ebp-28]   ;  ntdll.DbgBreakPoint
0042ED19  |.  75 08              jnz     short 0042ED23
0042ED1B  |.  3B1D 0C574D00      cmp     ebx, dword ptr [4D570C]
0042ED21  |.  74 16              je      short 0042ED39

0042ED23  |> \33C9          xor     ecx, ecx
0042ED25  |.  8B45 D8       mov     eax, dword ptr [ebp-28]
0042ED28  |.  890D 10574D00 mov     dword ptr [4D5710], ecx
0042ED2E  |.  A3 08574D00   mov     dword ptr [4D5708], eax       ;  把當(dāng)前斷點(diǎn)地址保存到全局變量4D5708中
0042ED33  |.  891D 0C574D00 mov     dword ptr [4D570C], ebx
0042ED39  |>  8B55 A4       mov     edx, dword ptr [ebp-5C]
0042ED3C  |.  8B0A          mov     ecx, dword ptr [edx]

以上找到了回溯后的斷點(diǎn)地址。然后下面是做一些別的操作,這里暫不予考慮。
這時(shí)因?yàn)橛|發(fā)了Int3異常,被調(diào)試程序斷了下來(lái),且已經(jīng)回溯了地址,這時(shí)按下F9的話,OD就會(huì)重新跑起來(lái),這時(shí)OD對(duì)用戶設(shè)置的Int3斷點(diǎn)又做了兩件事:
1、恢復(fù)原有的指令,讓被調(diào)試程序正確執(zhí)行指令;
2、走完正確指令之后,再重新設(shè)置指令為0xCC;
在OD的函數(shù)Go中:
先通過(guò)Findthread獲得線程結(jié)構(gòu)體:
00434A45  |> \8B4D 08       mov     ecx, dword ptr [ebp+8]
00434A48  |.  51            push    ecx            ; ecx 是Go函數(shù)傳入?yún)?shù),為被調(diào)試線程的ID
00434A49  |.  E8 2A3F0400   call    _Findthread      ; 返回OD中t_thread線程結(jié)構(gòu)體
00434A4E  |.  59            pop     ecx
00434A4F  |.  8945 DC       mov     dword ptr [ebp-24], eax ;把t_thread線程結(jié)構(gòu)體的地址賦給ebp-24
然后通過(guò)線程結(jié)構(gòu)體獲得當(dāng)前要執(zhí)行的指令的地址(這個(gè)地址在前面已經(jīng)用回溯法修正過(guò)了)
00434AB9  |.  8B99 18030000 mov     ebx, dword ptr [ecx+t_thread.th_reg.r_EIP]

00434B2A  |.  53            push    ebx       ; ebx = t_thread.th_reg.r_EIP
00434B2B  |.  E8 7C49FEFF   call    004194AC   ; 把Eip傳給函數(shù)004194AC

在函數(shù)004194AC中,先獲得Int3斷點(diǎn)結(jié)構(gòu)體數(shù)組:
004194EC  |> \56            push    esi             ;Eip
004194ED  |.  68 E17E4D00   push    004D7EE1       ; |Arg1 = 004D7EE1 ASCII "Table of breakpoints"
004194F2  |.  E8 19C00300   call    _Findsorteddata    ; 返回Int3斷點(diǎn)結(jié)構(gòu)體數(shù)組首地址
OD的Int3斷點(diǎn)結(jié)構(gòu)體中有斷點(diǎn)處的原始指令碼,用來(lái)恢復(fù)被調(diào)試程序原先的指令碼。把該地址作為參數(shù)傳給函數(shù)00418C4C
00419505  |.  50            push    eax
00419506  |.  8915 20D64C00 mov     dword ptr [4CD620], edx
0041950C  |.  E8 3BF7FFFF   call    00418C4C
在函數(shù)00418C4C中層層調(diào)用,最終是調(diào)用WriteProcessMemory函數(shù)恢復(fù)指令碼的:
00461814  |> \6A 00         push    0                             ; /pBytesWritten = NULL
00461816  |.  A1 685A4D00   mov     eax, dword ptr [4D5A68]       ; |
0046181B  |.  8B55 10       mov     edx, dword ptr [ebp+10]       ; |
0046181E  |.  52            push    edx                           ; |BytesToWrite
0046181F  |.  8B4D 08       mov     ecx, dword ptr [ebp+8]        ; |
00461822  |.  51            push    ecx                           ; |Buffer
00461823  |.  56            push    esi                           ; |Address
00461824  |.  50            push    eax                           ; |hProcess => 0000026C (window)
00461825  |.  E8 F8D90400   call    <jmp.&KERNEL32.WriteProcessMe>; \WriteProcessMemory

在運(yùn)行完該指令之后,OD又把該指令碼設(shè)為Int3斷點(diǎn),即0xCC
關(guān)鍵Call是函數(shù)41B5A4,在這個(gè)函數(shù)里,調(diào)用WriteMemory設(shè)置0xCC斷點(diǎn),而WriteMemory最終調(diào)用的還是上面所說(shuō)的WriteProcessMemory(這里就不再詳細(xì)描述了)
0041B6A4  |.  C60424 CC     |mov     byte ptr [esp], 0CC      ;直接設(shè)置0xCC斷點(diǎn)
0041B6A8  |.  6A 02         |push    2                              ; /Arg4 = 00000002
0041B6AA  |.  6A 01         |push    1                              ; |Arg3 = 00000001
0041B6AC  |.  55            |push    ebp                            ; BreakPointAddress
0041B6AD  |.  8D5424 0C     |lea     edx, dword ptr [esp+C]             ; [esp+C] = 0xCC
0041B6B1  |.  52            |push    edx                            ; [edx] = 0xCC
0041B6B2  |.  E8 71600400   |call    _Writememory                    ; \_Writememory

通過(guò)以上方法,OD實(shí)現(xiàn)了在運(yùn)行時(shí)動(dòng)態(tài)處理Int3斷點(diǎn)的功能。


                              武漢科銳學(xué)員: driverox
                                2008-5-19                                 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多