天天看點

<Oday安全 11.6利用加載子產品之外的位址繞過SafeSEH>一節注記---jmp [ebp+N] (下)

    接上回,還剩幾條跳轉的指令還沒分析到,這些指令将在本篇中完成。

    先來看看call/jmp [ebp-0x4]這條指令。這是在目前函數_except_handler4棧的局部變量,是以需要檢視反彙編代碼:

0:000> uf ntdll!ExecuteHandler2
ntdll!ExecuteHandler2:
7c923282 55              push    ebp
7c923283 8bec            mov     ebp,esp
7c923285 ff750c          push    dword ptr [ebp+0Ch]
7c923288 52              push    edx
7c923289 64ff3500000000  push    dword ptr fs:[0]
7c923290 64892500000000  mov     dword ptr fs:[0],esp
7c923297 ff7514          push    dword ptr [ebp+14h]
7c92329a ff7510          push    dword ptr [ebp+10h]
7c92329d ff750c          push    dword ptr [ebp+0Ch]
7c9232a0 ff7508          push    dword ptr [ebp+8]
7c9232a3 8b4d18          mov     ecx,dword ptr [ebp+18h]
7c9232a6 ffd1            call    ecx ;調用異常處理程式_except_handler      

     先前提到,由于棧溢出,異常處理結構已經被覆寫,是以執行call ecx時并不會去執行_except_handler而是執行call/jmp [ebp+N]指令。由于這條指令并沒有操作ebp,是以ebp的值依然是ntdll!ExecuteHandler2的函數棧桢。[ebp-4]就順理成章的變成了ntdll!ExecuteHandler2中的第一個入棧局部變量。而第一個入棧的局部變量正是[ebp+0xc]。這個值是什麼?正好和另一個call/jmp [ebp+N]相同----call/jmp [ebp+0x0c]。

    上面提到了[ebp+0xc],現在我們來看下call/jmp [ebp+0x0c]這個指令。這個指令分析起來比較簡單ebp+0x0c傳入函數的第二個參數的位址(廣義Esp定理:[ebp+0]:orig ebp;[ebp+4]:retAddr;[ebp+8]:arg1;[ebp+0xc]:arg2).被調用的函數不用說就是異常處理函數_except_handler4了,那麼,是誰調用并傳參數給它的?

0:000> kb
ChildEBP RetAddr  Args to Child              
0012f9b4 7c9232a8 0012faa0 0012fe80(<-參數2) 0012fab4 offset!_except_handler4
0012f9d8 7c92327a 0012faa0 0012fe80 0012fab4 ntdll!ExecuteHandler2+0x26
0012fa88 7c92e46a 00000000 0012fab4 0012faa0 ntdll!ExecuteHandler+0x24

0:000> dd 0012fe80 L2 ;第二個參數的位址值為0x12fe80
0012fe80  0012ffa8 00411078 ;12fe80包含了一個異常處理節點
0:000> ln 00411078
(00411078)   offset!ILT+115(__except_handler4)   |  (0041107d)   offset!ILT+120(__lock)
Exact matches:      

    從堆棧回溯結果來看Arg2是ntdll!ExecuteHandler2調用_except_handler4時傳入的;而_except_handler4接口的第二個參數正是PEXCEPTION_REGISTRATION結構。這樣異常處理時還是會跳轉到被溢出後的棧中,進而執行shellcode。

    再看第4條指令call [ebp-0x18]又指向哪?同樣,目前ebp指向的是ntdll!ExecuteHandler2的棧桢,[ebp-0x18]還是ntdll!ExecuteHandler2中的局部變量。

0:000> ?? @ebp-0x18
unsigned int 0x12f9c0
0:000> dd 0x12f9c0 L1 
0012f9c0  0012fe80 ;同樣是目前異常處理節點在棧中的位址

ntdll!ExecuteHandler2:
7c92329d ff750c          push    dword ptr [ebp+0Ch] <----這條指令執行後,正好形成局部變量[ebp-0x18]。而這條指令壓入的正是前面分析過的[ebp+0xc]
7c9232a0 ff7508          push    dword ptr [ebp+8]
7c9232a3 8b4d18          mov     ecx,dword ptr [ebp+18h]
7c9232a6 ffd1            call    ecx      

    最後兩條指令,偏移實在是太遠了:[ebp+0x24]/[ebp+0x30]一種沖出地球的感覺...

    [ebp+0x0c]是函數ntdll!ExecuteHandler2的第二個參數,[ebp+0x24]比[ebp+0x0c]更早入棧,這十有八九和ntdll!ExecuteHandler2的調用者有關了,檢視函數調用棧:

0:000> kb
ChildEBP RetAddr  Args to Child              
0012f9b4 7c9232a8 0012faa0 0012fe80 0012fab4 offset!_except_handler4
0012f9d8 7c92327a 0012faa0 0012fe80 0012fab4 ntdll!ExecuteHandler2+0x26
0012fa88 7c92e46a 00000000 0012fab4 0012faa0 ntdll!ExecuteHandler+0x24      

    ntdll!ExecuteHandler2的調用者是ntdll!ExecuteHandler,反彙編代碼,可以看到[ebp+0x24]的由來:

0:000> uf ExecuteHandler
ntdll!ExecuteHandler:
7c923256 53              push    ebx  <----------------壓棧後形成[ebp+0x24]
7c923257 56              push    esi
7c923258 57              push    edi
7c923259 33c0            xor     eax,eax
7c92325b 33db            xor     ebx,ebx
7c92325d 33f6            xor     esi,esi
7c92325f 33ff            xor     edi,edi
7c923261 ff742420        push    dword ptr [esp+20h]
7c923265 ff742420        push    dword ptr [esp+20h]
7c923269 ff742420        push    dword ptr [esp+20h]
7c92326d ff742420        push    dword ptr [esp+20h] <---------這條指令形成[ebp+0x0c],從這倒着數上去就能找到[ebp+0x24]的由來,那就是函數的第一條指令
7c923271 ff742420        push    dword ptr [esp+20h]
7c923275 e808000000      call    ntdll!ExecuteHandler2 (7c923282)      
ntdll!RtlpExecuteHandlerForException:
7c923247 babc32927c      mov     edx,offset ntdll!ExecuteHandler2+0x3a (7c9232bc)
7c92324c eb08            jmp     ntdll!ExecuteHandler (7c923256)

0:000> ?? @ebp+0x24
unsigned int 0x12f9fc
0:000> dd 0x12f9fc L2
0012f9fc  0012fe80 7c94a9ef      
ntdll!RtlDispatchException+0xa0:
7c94a9de ff7304          push    dword ptr [ebx+4]
7c94a9e1 8d45ec          lea     eax,[ebp-14h]
7c94a9e4 50              push    eax
7c94a9e5 ff750c          push    dword ptr [ebp+0Ch]
7c94a9e8 53              push    ebx
7c94a9e9 56              push    esi
7c94a9ea e85888fdff      call    ntdll!RtlpExecuteHandlerForException
RtlpExecuteHandlerForException(pExcptRec,pRegistration,pContext,&DispatcherContext,pRegistration->Handler);

ntdll!RtlDispatchException+0xa0:
7c94a9e8 53              push    ebx ;第一次壓棧 [ebp+0x30]
7c94a9e9 56              push    esi ;第二次壓棧 [ebp+0x2c]
7c94a9ea e85888fdff      call    ntdll!RtlpExecuteHandlerForException ;函數調用 又一次壓棧 [ebp+0x28]--->進入RtlpExecuteHandlerForException,執行push ebx;      

繼續閱讀