OD附加功能分析

OD版本:OllyICE v1.10ide

 

在從文件菜單選擇附加後,OD會在註冊一個窗口類後,先建立一個0x138大小的進程表; 再是CreateWindowExA 建立窗口;函數

 

00478013 loc_478013:                            線程

00478013                 push    0               ; int調試

00478015                 push    offset sub_477C10 ; intorm

0047801A                 push    100h            ; int排序

0047801F                 push    310h            ; int索引

00478024                 push    offset asc_4C20E8 ; "?進程

00478029                 push    offset byte_4ED3FC ; dest事件

0047802E                 call    _Createsorteddata     //此處爲建立進程表內存

 

表的結構體以下:

table           struc ; (sizeof=0x138)

name            db 260 dup(?)   //表的名字

count       dd ?                //表中保存的數據個數

maxcount        dd ?           //表能保存的最大數量

currentobj      dd ?            //當前選中的表中數據的ID,未選中時爲爲-1

addrcurobj       dd ?             //當前選中數據的地址,未選中時爲0

size            dd ?            //表中每一個數據的大小

field_118       dd ?

baseaddrobj           dd ?      //表中保存的數據的基地址

fncmp              dd ?        //函數首地址

field_124       dd ?

field_128      dd ?    

sign            dd ?   //標誌位,表示是否有索引數據(也就是baseaddroffset是否有效)

baseaddroffset        dd ?       //索引數據,標示每一個數據在表中的順序

field_134       dd ?

table           ends

 

 

而後OD會獲取本身的進程ID號,並獲取EnumProcesses ,EnumProcessModules,GetModuleFileNameExA 三個函數的地址;

 

 

00475138 loc_475138:                            

00475138                 xor     ebx, ebx

0047513A                 call    GetCurrentProcessId  //獲取OD自己的進程ID

0047513F                 mov     [ebp+var_10], eax

00475142                 mov     eax, dword_4D5A0C

00475147                 test    eax, eax

00475149                 jz      loc_4752AF

0047514F                 push    offset aEnumprocesses ; "EnumProcesses"

00475154                 push    eax             ; hModule

00475155                 call    GetProcAddress//獲取EnumProcesses地址

0047515A                 mov     edi, eax

0047515C                 push    offset aEnumprocessm_0 ; "EnumProcessModules"

00475161                 mov     eax, dword_4D5A0C

00475166                 push    eax             ; hModule

00475167                 call    GetProcAddress//獲取EnumProcessModules的地址

0047516C                 mov     [ebp+var_20], eax

0047516F                 push    offset aGetmodulefil_0 ; "GetModuleFileNameExA"

00475174                 mov     edx, dword_4D5A0C

0047517A                 push    edx             ; hModule

0047517B                 call    GetProcAddress//獲取GetModuleFileNameExA地址

00475180                 mov     [ebp+var_24], eax

 

 

以後OD枚舉系統中的全部進程並保存枚舉到的進程;

 

004751A3                 push    eax

004751A4                 push    400h

004751A9                 push    edx

004751AA                 call    edi   // EnumProcesses  枚舉進程

004751AC                 test    eax, eax

004751AE                 jnz     short loc_4751B3

 

 

接着再一個循環中OD會嘗試利用OpenProcess打開枚舉到的全部進程,若是進程ID不等於OD自己ID 而且OpenProcess函數返回成功的話,OD會利用EnumProcessModules枚舉模塊並獲取第一個模塊句柄,若是EnumProcessModules返回成功,OD會利用GetModuleFileNameExA獲取模塊全路徑,最後把進程ID和 模塊全路徑 按順序保存到上面創建的 進程表 中; 

 

004751DB loc_4751DB:                             

004751DB                 mov     eax, [edi]

004751DD                 cmp     eax, [ebp+var_10]// 判斷是否等於OD自己ID

004751E0                 jz      loc_47529B

004751E6                 push    eax             ; dwProcessId

004751E7                 push    0               ; bInheritHandle

004751E9                 push    410h            ; dwDesiredAccess

004751EE                 call    OpenProcess

004751F3                 mov     [ebp+hObject], eax

004751F6                 cmp     [ebp+hObject], 0//判斷進程是否打開成功

004751FA                 jz      loc_47529B

00475200                 lea     edx, [ebp+var_C]

00475203                 lea     ecx, [ebp+var_1C]

00475206                 push    edx

00475207                 push    4

00475209                 push    ecx

0047520A                 mov     eax, [ebp+hObject]

0047520D                 push    eax

0047520E                 call    [ebp+var_20] //EnumProcessModules枚舉進程模塊

00475211                 test    eax, eax

00475213                 jnz     short loc_475220

00475215                 mov     edx, [ebp+hObject]

00475218                 push    edx             ; hObject

00475219                 call    CloseHandle//若是EnumProcessModules不成功則關閉句柄

0047521E                 jmp     short loc_47529B

 

 

若是EnumProcessModules成功則走以下分支

 

00475220 loc_475220:                          

00475220                 mov     ecx, [edi]      ; int

00475222                 xor     eax, eax        ; int

00475224                 mov     dword ptr [ebp+arglist], ecx//把進程ID保存到一臨時結構體中

0047522A                 lea     edx, [ebp+var_528]

00475230                 mov     [ebp+var_730], 1

0047523A                 mov     [ebp+var_72C], eax

00475240                 mov     [ebp+var_528], 0

00475247                 push    104h

0047524C                 push    edx

0047524D                 mov     ecx, [ebp+var_1C]

00475250                 push    ecx

00475251                 mov     eax, [ebp+hObject]

00475254                 push    eax

00475255                 call    [ebp+var_24]//GetModuleFileNameExA得到模塊路徑

00475258                 mov     [ebp+var_425], 0

0047525F                 mov     edx, [ebp+hObject]

00475262                 push    edx             ; hObject

00475263                 call    CloseHandle//關閉打開的進程句柄

00475268                 push    0

0047526A                 lea     ecx, [ebp+var_728]

00475270                 push    ecx

00475271                 push    0

00475273                 push    0

00475275                 lea     eax, [ebp+var_528]

0047527B                 push    eax

0047527C                 call    004A51BC   //把模塊路徑複製到臨時變量結構體中

00475281                 add     esp, 14h

00475284                 lea     edx, [ebp+arglist] ; int

0047528A                 mov     [ebp+var_628], 0

00475291                 push    edx             ; arglist

00475292                 push    esi             ; src

00475293                 call    _Addsorteddata //把包含了進程ID與模塊路徑的臨時結構體添加到進程表中

00475298                 add     esp, 8

 

0047529B loc_47529B:                                                               

0047529B                 inc     [ebp+var_4]

0047529E                 add     edi, 4

004752A1                 mov     ecx, [ebp+var_4]

004752A4                 cmp     ecx, [ebp+var_8] //檢查比較次數是否小於枚舉到的進程個數

004752A7                 jl      loc_4751DB //小於則繼續循環

 

           

 

枚舉完進程後接着檢查進程表中保存的數據是否小於等於0;若是小於等於則直接返回;

反之則EnumWindows,並利用GetWindowText函數獲取桌面窗口的標題

保存到 進程表中 對應的進程數據中

004753E9              cmp     dword ptr [esi+104h], 0//比較進程表中數據是否小於0

004753F0              jle     short loc_4753FD

004753F2              push    esi       //此處的參數是 進程表的首地址

004753F3              push    offset sub_477A90 ; lpEnumFunc

004753F8              call    EnumWindows

 

 

 

如下是EnumWindowsProc的功能

00477AA8                 lea     edx, [ebp+dwProcessId]

00477AAB                 push    edx             ; lpdwProcessId

00477AAC                 mov     ecx, [ebp+hWnd]

00477AAF                 push    ecx        //枚舉的窗口進程的句柄

00477AB0                 call    GetWindowThreadProcessId //得到窗口的進程ID

 

 

下面是個循環 利用上面獲得的進程ID與進程表中保存的進程ID作比較,若是相等 則GetWindowTextA得到窗口標題,並把獲得的數據保存在進程表中對應的位置

00477ABB loc_477ABB:                             ; CODE XREF: sub_477A90+75j

00477ABB                 mov     edx, [ebx]

00477ABD                 cmp     edx, [ebp+dwProcessId]

00477AC0                 jnz     short loc_477AF8

00477AC2                 cmp     byte ptr [ebx+10Ch], 0

00477AC9                 jnz     short loc_477AF8

00477ACB                 push    100h            ; nMaxCount

00477AD0                 mov     ecx, eax

00477AD2                 lea     eax, [ecx+eax*2]

00477AD5                 shl     eax, 4

00477AD8                 add     eax, ecx

00477ADA                 shl     eax, 4

00477ADD                 add     esi, eax

00477ADF                 add     esi, 10Ch

00477AE5                 push    esi  //此buffer既爲進程表中不一樣進程對應的數據地址

00477AE6                 mov     eax, [ebp+hWnd]

00477AE9                 push    eax             ; hWnd

00477AEA                 call    GetWindowTextA  //得到枚舉的窗口的標題並保存到進程表中對應的進程數據中

 

00477AEF                 mov     byte ptr [ebx+20Bh], 0

00477AF6                 jmp     short loc_477B07得到後跳出循環 利用枚舉到的下一個窗口再次執行此函數

 

 

若是進程ID不相等則繼續循環

00477AF8                 inc     eax

00477AF9                 add     ebx, 310h  0x310爲結構體大小

00477AFF loc_477AFF:                           

00477AFF                 cmp     eax, [edi+104h] //檢查比較的次數 是否大於進程表中 的進程數

00477B05                 jl      short loc_477ABB

 

在EnumWindows函數執行完成返回後,OD會調用InvalidateRect函數,使顯示進程的窗口重繪;

004782F8                 push    0               ; bErase

004782FA                 push    0               ; lpRect

004782FC                 mov     edx, dword_4ED3F8

00478302                 push    edx             ; hWnd

00478303                 call    InvalidateRect

 

 

OD會對進程表中的 ID號,把相對應的索引數據進行從小到大的排序..

004AC501                 jz      short loc_4AC51C

004AC503                 mov     edx, [ebp+fcmp]

004AC506                 mov     ecx, [ebp+nelem]

004AC509                 push    ecx //第一個參數爲進程表中的數據個數

004AC50A                 mov     dword_50A5F8, edx

004AC510                 mov     eax, [ebp+base] //第二個參數爲進程表中索引數據的首地址

004AC513                 push    eax

004AC514                 call    sub_4AC310

最終函數會調用到進程表結構體中偏移0x120位置保存的函數地址;

 

 

當從進程窗口列表框中選擇要附加的進程並點擊附加按鈕後,OD會記錄其序號,並經過序號計算出此進程在 進程表中的 偏移位置,經過偏移位置獲得進程ID

 

004784A5                 mov     eax, dword_4ED508//獲得要附加進程在列表框中的位置

004784AA                 test    eax, eax

004784AC                 jl      loc_47867B//若是進程號小於0則直接返回;

004784B2                 cmp     eax, dword_4ED500/比較序號是否大於進程總數

004784B8                 jge     loc_47867B  //大於也直接返回

004784BE                 mov     edx, dword_4ED52C

004784C4                 mov     esi, [edx+eax*4]

004784C7                 imul    esi, dword_4ED510

004784CE                 add     esi, dword_4ED518 //上面幾步是計算得出附加的進程在進程表中存儲的首地址

004784D4                 mov     eax, [esi]  //獲得進程ID

004784D6                 cmp     eax, dword_4D5A70 //判斷OD是否正在調試此程序

004784DC                 jnz     short loc_4784F4

 

 

若是此時OD正在調試此程序則會彈出一錯誤框提示 進程「xxxx」是你正在調試的程序……

並直接返回。

 

004784DE                 add     esi, 0Ch

004784E1                 push    esi             ; arglist

004784E2                 push    offset asc_4C2122 ; "?

004784E7                 call    _Error

004784EC                 add     esp, 8

004784EF                 jmp     loc_47867B//直接返回..

 

 

接着OD會申請必定的空間並初始化一些表,如:dll句柄表,線程表,統計表,等等…

 

004784F4 loc_4784F4:                           

004784F4                 push    1

004784F6                 call    sub_4758A4

004784FB                 pop     ecx

004784FC                 test    eax, eax

004784FE                 jnz     loc_47867B

00478504                 call    sub_47540C //此函數用於申請空間並初始化表

00478509                 test    eax, eax //判斷是否初始化成功。

0047850B                 jz      short loc_47851D

0047850D                 push    offset aIFUC    ; "沒法分配足夠內存"

00478512                 call    _Error//若是不成功則會報告內存內存不足…並直接返回

00478517                 pop     ecx

00478518                 jmp     loc_47867B

 

 

在0046b258這個函數中OD會根據用戶設置的導入庫保存在ollydbg.ini文件中的[Import libraries]項解析調試程序中的庫函數;

下面就是處理的一個循環過程

 

0046B268 loc_46B268:                          

0046B268                 push    ebx

0046B269                 lea     eax, [edi+4F8h]

0046B26F                 push    eax             ; format

0046B270                 lea     edx, [esp+318h+buffer]

0046B277                 push    edx             ; buffer

0046B278                 call    _sprintf

0046B27D                 add     esp, 0Ch

0046B280                 push    offset FileName ; lpFileName

0046B285                 push    104h            ; nSize

0046B28A                 lea     ecx, [esp+318h+path]

0046B28E                 push    ecx             ; lpReturnedString

0046B28F                 lea     eax, [edi+4]

0046B292                 push    eax             ; lpDefault

0046B293                 lea     edx, [esp+320h+buffer]

0046B29A                 push    edx             ; lpKeyName

0046B29B                 lea     ecx, [edi+503h]

0046B2A1                 push    ecx             ; lpAppName

0046B2A2                 call    GetPrivateProfileStringA  //獲得ollydbg.ini 文件中[Import libraries]項中的路徑

0046B2A7                 cmp     [esp+310h+path], 0

0046B2AB                 jz      short loc_46B2E6

0046B2AD                 mov     eax, hCursor

0046B2B2                 push    eax             ; hCursor

0046B2B3                 call    SetCursor

0046B2B8                 mov     esi, eax

0046B2BA                 xor     eax, eax

0046B2BC                 mov     dword_4EAE50, eax

0046B2C1                 push    0               ; int

0046B2C3                 lea     edx, [esp+314h+arglist]

0046B2CA                 push    edx             ; arglist

0046B2CB                 lea     ecx, [esp+318h+path]

0046B2CF                 push    ecx             ; path

0046B2D0                 call    sub_469818//此函數裏面主要是負責解析的函數

0046B2D5                 add     esp, 0Ch

0046B2D8                 call    sub_46718C

0046B2DD                 cmp     dword_4EAE50, 0

0046B2E4                 jnz     short loc_46B2F3

0046B2E6

0046B2E6 loc_46B2E6:     

0046B2E6                 inc     ebx

0046B2E7                 cmp     ebx, 0C8h

0046B2ED                 jl      loc_46B268

 

 

 

等作完上面的工做後,OD纔開始真正的附加 主要是經過DebugActiveProcess對程序附加

00478522                 mov     eax, [esi]

00478524                 push    eax             /要附加的進程ID

00478525                 call    DebugActiveProcess

0047852A                 test    eax, eax

 

以後OD按必定格式設置窗口標題;

004785A5                 push    edx

004785A6                 push    offset byte_4D5A7C

004785AB                 push    offset aOllyice ; "OllyICE"

004785B0                 push    offset aSSS_0   ; "%s - %s%s"

004785B5                 lea     ecx, [ebp+buffer]

004785BB                 push    ecx             ; buffer

004785BC                 call    _sprintf

004785C1                 add     esp, 14h

004785C4                 lea     eax, [ebp+buffer] ; int

004785CA                 push    eax             ; lpString

004785CB                 mov     edx, hWnd

004785D1                 push    edx             ; hWnd

004785D2                 call    SetWindowTextA

而後OD會對ollydbg.ini文件中的[History],[Arguments]兩項進行設置……下面只貼出部分代碼

 

00476F08                 lea     edx, [ebx+1]

00476F0B                 push    edx

00476F0C                 lea     ecx, [edi+6DAh]

00476F12                 push    ecx             ; format

00476F13                 lea     eax, [ebp+buffer]

00476F19                 push    eax             ; buffer

00476F1A                 call    _sprintf

00476F1F                 mov     edx, ebx

00476F21                 add     esp, 0Ch

00476F24                 shl     edx, 6

00476F27                 lea     ecx, [ebp+var_518]

00476F2D                 add     edx, ebx

00476F2F                 push    offset FileName ; lpFileName

00476F34                 shl     edx, 2

00476F37                 lea     eax, [ebp+buffer]

00476F3D                 add     edx, ecx

00476F3F                 push    edx             ; lpString

00476F40                 lea     edx, [edi+6E9h]

00476F46                 push    eax             ; lpKeyName

00476F47                 push    edx             ; lpAppName

00476F48                 call    WritePrivateProfileStringA

 

 

接着OD設置程序狀態,並退出Dialog對話框…

 

0047860E                 push    0               ; name

00478610                 push    offset byte_4D5A7C ; int

00478615                 call    sub_409370

0047861A                 add     esp, 8

0047861D                 push    3  //設置狀態爲運行

0047861F                 call    sub_431978

00478624                 pop     ecx

00478625                 push    0               ; nResult

00478627                 push    ebx             ; hDlg

00478628                 call    EndDialog //結束附加窗口

0047862D                 jmp     short loc_47867B

 

 

DebugActiveProcess附加程序後,系統會爲進程中的每個建立線程,向調試器發送CREATE_THREAD_DEBUG_EVENT調試事件,會爲進程中的每一個動態加載DLL向調試器發送LOAD_DLL_DEBUG_EVENT調試事件..  OD經過WaitForDebugEvent函數得到這些事件,作相應處理,並調用ContinueDebugEvent使程序繼續執行…..當這些都作完後,系統恢復進程中的全部線程,而且在第一個線程恢復的時候會執行 一個 斷點指令,最後會調用Ntdll.dll中的DbgBreakPoint函數 而根據跟蹤得知DbgBreakPoint中的實現 就是一個int3指令;

 

dwDebugEventCode事件處理表:

0042EBF7                 mov     edx, DebugEvent.dwDebugEventCode

0042EBFD                 cmp     edx, 9          ; switch 10 cases

0042EC00                 ja      loc_4313F4      ; default

0042EC00                                         ; jumptable 0042EC06 case 0

0042EC06                 jmp     ds:off_42EC0D[edx*4] ; switch jump

0042EC06 ; ---------------------------------------------------------------------------

0042EC0D off_42EC0D      dd offset loc_4313F4    ; DATA XREF: sub_42EBD0+36r

0042EC0D                 dd offset loc_42EC35    ; jump table for switch 

0042EC0D                 dd offset loc_430CFF

0042EC0D                 dd offset loc_430DD7

0042EC0D                 dd offset loc_430F3F

0042EC0D                 dd offset loc_431037

0042EC0D                 dd offset loc_43112D

0042EC0D                 dd offset loc_4311B7

0042EC0D                 dd offset loc_431276

0042EC0D                 dd offset loc_4313C7

 

DbgBreakPoint的實現

 

7C92120E >  CC              int3     

7C92120F    C3              retn

 

所以當程序執行到此時,會引發一個EXCEPTION_DEBUG_EVENT事件,OD經過WaitForDebugEvent函數會得到此調試事件…OD在得到EXCEPTION_DEBUG_EVENT事件後,以後並無調用ContinueDebugEvent使程序執行。所以OD會停到DbgBreakPoint處,也就是EIP會指在retn處。

相關文章
相關標籤/搜索