小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

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

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

最近學習逆向,對OD本身做了個逆向,也算是一個小小的鍛煉吧。呵呵,在這里以分析報告的形式貼出來,請大家批評指正。謝謝。

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

先說明一下OD中的兩個結(jié)構(gòu)體,在IDA中,聲明為如下格式:
t_bpoint用來保存Int斷點的相關(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為斷點的地址,dummy始終為1,type為斷點的類型,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)體的名稱,用來區(qū)別不同類型的結(jié)構(gòu)體
n是數(shù)組元素的個數(shù)
itemsize是數(shù)組元素的大小
data 是指向各種數(shù)據(jù)結(jié)構(gòu)數(shù)組的指針,這里使用的是int3斷點,所以現(xiàn)在保存的是int3斷點數(shù)據(jù)結(jié)構(gòu)體數(shù)組的指針
---------------------------------------------------------------------------------------------------------------------------------

1)Int3斷點的設置
int3斷點的設置是通過消息來處理的,對應右鍵點擊菜單中的切換,其對應的消息為1E;此外還有熱鍵F2、雙擊反匯編窗口等也能切換int3斷點,轉(zhuǎn)入的函數(shù)雖然不同,但是調(diào)用設置int3斷點的函數(shù)都是同一個,就不再舉例了。傳入相應參數(shù)調(diào)用函數(shù)00419974,改變int3斷點,該函數(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

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

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

保存現(xiàn)場,提升棧幀空間,用于存放局部變量:
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斷點,找不到返回8,并跳過取得模塊信息部分:
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  ;不是則跳過取得模塊信息部分
取得模塊信息,并檢查是否取得,若取得失敗則跳轉(zhuǎn)到顯示斷點錯誤消息分支:
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  ;沒有得到則跳轉(zhuǎn)到下面錯誤顯示分支
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
顯示斷點錯誤消息,若用戶選擇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斷點的屬性,如果已經(jīng)設置了int3斷點,則將其刪除并跳轉(zhuǎn)到結(jié)束處;若沒有設置,則跳過刪除部分代碼:
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斷點的屬性
00419A03  |.  F6C4 02    test    ah, 2    ;比較是否已經(jīng)設置了int3斷點
00419A06  |.  59         pop     ecx
00419A07  |.  74 14      je      short 00419A1D  ;若沒有設置則跳過刪除斷點的代碼
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
在這里有對傳入?yún)?shù)的一個比較,但是測試時無法得到0以外的值,所以無法確定該參數(shù)的作用,這樣也無法測試00419A6D后面的代碼所表示的意義:
00419A1D  |>  837D 10 00 cmp     dword ptr [ebp+10], 0
00419A21  |.  75 4A      jnz     short 00419A6D
這里就是設置int3斷點的函數(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
設置完int3斷點后,刪除int3斷點處的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é)束廣播處
這部分省略的代碼無法得知其調(diào)用的必要條件,不過里面的內(nèi)容跟上面相似,都是通過判斷來設置int3斷點,這里就不再詳細說明了:
……
……
向子窗體發(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,并且恢復現(xiàn)場:
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斷點的處理
Int3斷點處理的大致流程是:
1、  獲取當前寄存器的信息,重點是Eip的值
2、  根據(jù)Int3斷點的類型(0xCC或0xCD03)回溯指針地址
3、  觸發(fā)Int3異常,被調(diào)試程序斷下;
4、  若繼續(xù)跑的話,則恢復原有的指令,讓被調(diào)試程序正確執(zhí)行指令;
5、  走完正確指令之后,再重新設置指令為Int3斷點;

在OD中有一個處理所有異常的函數(shù)42EBD0,從該函數(shù)入手分析Int3斷點的處理。
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  ;以上是開棧幀代碼

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

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

這里說到了兩個結(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)  ;保存線程信息,同時有新舊兩份reg值,可以用來在OD的寄存器窗口為改變的值設置顏色等功能。
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)
用來判斷是何種異常:
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  ;檢查主線程中是否有當前寄存器的信息;
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(因為Eip指向下一條指令,回溯后才是正確的斷點地址),若是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在斷點地址讀的指令碼是CC的話,ebp-24設為1---ebp-24保存的是要回溯的指令長度
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      ;  回溯指令碼,才是正確的斷點地址
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       ;  把當前斷點地址保存到全局變量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]

以上找到了回溯后的斷點地址。然后下面是做一些別的操作,這里暫不予考慮。
這時因為觸發(fā)了Int3異常,被調(diào)試程序斷了下來,且已經(jīng)回溯了地址,這時按下F9的話,OD就會重新跑起來,這時OD對用戶設置的Int3斷點又做了兩件事:
1、恢復原有的指令,讓被調(diào)試程序正確執(zhí)行指令;
2、走完正確指令之后,再重新設置指令為0xCC;
在OD的函數(shù)Go中:
先通過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
然后通過線程結(jié)構(gòu)體獲得當前要執(zhí)行的指令的地址(這個地址在前面已經(jīng)用回溯法修正過了)
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斷點結(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斷點結(jié)構(gòu)體數(shù)組首地址
OD的Int3斷點結(jié)構(gòu)體中有斷點處的原始指令碼,用來恢復被調(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ù)恢復指令碼的:
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

在運行完該指令之后,OD又把該指令碼設為Int3斷點,即0xCC
關(guān)鍵Call是函數(shù)41B5A4,在這個函數(shù)里,調(diào)用WriteMemory設置0xCC斷點,而WriteMemory最終調(diào)用的還是上面所說的WriteProcessMemory(這里就不再詳細描述了)
0041B6A4  |.  C60424 CC     |mov     byte ptr [esp], 0CC      ;直接設置0xCC斷點
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

通過以上方法,OD實現(xiàn)了在運行時動態(tài)處理Int3斷點的功能。


                              武漢科銳學員: driverox
                                2008-5-19                                 

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多