覆蓋SEH的溢位利用檢測思路

2021-04-13 07:19:19 字數 3683 閱讀 8841

kruglinski (kruglinski_at_sohu.com)

看到安焦上的一篇《基於棧指紋檢測緩衝區溢位的一點思路》,這是在shellcode已經執行時在它的呼叫堆疊(被hook的下級呼叫函式 loadlibrary)裡進行檢測,有些利用溢位覆蓋seh handler,然後任程式執行,因為溢位破壞了堆或棧,肯定會出現異常,這時指向shellcode的handler被執行,我在想這一類的溢位利用,既然它想執行,那首先要過作業系統的異常派遣這一關,如果在分派異常時我們就對seh handler進行一下檢測,或許能在shellcode執行前就發現它。

我簡單看了一下seh處理流程,一直跟到這兩個函式,因為wrk**不全,所以我選取reactos的**,但並不影響理解。

以下**來自reactos,版權歸原作者

void

ntapi

kiuserexceptiondispatcher(pexception_record exceptionrecord,

pcontext context)

else

else

}/* setup the exception record */

nestedexceptionrecord.exceptioncode = status;

nestedexceptionrecord.exceptionflags = exception_noncontinuable;

nestedexceptionrecord.exceptionrecord = exceptionrecord;

nestedexceptionrecord.numberparameters = status;

/* raise the exception */

rtlraiseexception(&nestedexceptionrecord);

}boolean

ntapi

rtldispatchexception(in pexception_record exceptionrecord,

in pcontext context)

/* set invalid stack and return false */

exceptionrecord->exceptionflags |= exception_stack_invalid;

return false;

}/* check if logging is enabled */

rtlpchecklogexception(exceptionrecord,

context,

registrationframe,

sizeof(*registrationframe));

/* call the handler */

disposition = rtlpexecutehandlerforexception(exceptionrecord,

registrationframe,

context,

&dispatchercontext,

registrationframe->

handler);

/* check if this is a nested frame */

if (registrationframe == nestedframe)

/* handle the dispositions */

switch (disposition)

else

/* continue searching */

case exceptioncontinuesearch:

break;

/* nested exception */

case exceptionnestedexception:

/* turn the nested flag on */

exceptionrecord->exceptionflags |= exception_nested_call;

/* update the current nested frame */

if (dispatchercontext.registrationpointer > nestedframe)

break;

/* anything else */

default:

/* set up the exception record */

exceptionrecord2.exceptionrecord = exceptionrecord;

exceptionrecord2.exceptioncode = status_invalid_disposition;

exceptionrecord2.exceptionflags = exception_noncontinuable;

exceptionrecord2.numberparameters = 0;

/* raise the exception */

rtlraiseexception(&exceptionrecord2);

break;

}/* go to the next frame */

registrationframe = registrationframe->next;

}/* unhandled, return false */

return false;

}然後我們可以為需要保護的程序hook kiuserexceptiondispatcher,在這裡面檢測handler是否安全,我能想到的可能不太安全的handler有四種情況,也許有更多,我只簡單的實現了第乙個策略(就是遍歷一下seh鏈),下面是相關的**片段。

//sehchecker.cpp

inline dword __fastcall getfsdword(dword dwoffset)

//策略:

//1. handler在棧區域

//2. handler在堆區域

//3. handler在全域性資料區

//4. handler在正常的**頁中,但第一條指令是jmp ***,或者handler前一段是不影響shellcode的指令,後面帶有乙個jmp ***,跳到handler中,怎麼檢測?

bool anyunsafehandler(void)

;sehchain* pchain=(sehchain*)getfsdword(0);

dword dwstackbase=getfsdword(4);

dword dwstacklimit=getfsdword(8);

bool bret=false;

dowhile(!bret&&(pchain!=(sehchain*)-1));

return bret;

}void

winapi

hookeduserexceptiondispatcher(pexception_record exceptionrecord,

pcontext context)

trampolineuserexceptiondispatcher(exceptionrecord,context);

}在檢測到非安全的handler時我為什麼要用exitthread呢,因為基於tib的seh chain是執行緒相關的,它不是final型的seh handler(不懂的參考一下hume大俠的經典文章<>),所以直接用exitthread把可能出現危險的執行緒給退掉,如果是主線程則程序會退出,需要的話同時記錄一下日誌,以供管理員分析受攻擊情況。

1 棧溢位的利用

1.程序使用的記憶體都可以按功能大致分為以下4個部分 1 區 這個區域儲存著被裝入執行的二進位制機器 處理器會到這個區域取指並執行。2 資料區 用於儲存全域性變數等。3 堆區 程序可以在堆區動態地請求一定大小的記憶體,並在用完之後還給堆區。動態分配和 是堆區的特點。4 棧區 用於動態地儲存函式之間的...

人臉遮擋檢測的幾種思路

遮擋是一直以來困擾研究人員及技術人員的問題,原因是存在遮擋後,不管是對人臉進行檢測,還是其它屬性識別 如關鍵點 角度 姿態 年齡等 的效果都會有很大影響。為了消除這些影響,一種思路是先判斷是否被遮擋,再進行屬性識別,另一種思路是在對人臉進行屬性識別時加入對遮擋的處理,提高演算法的魯棒性。目前,暫時還...

利用O(nlogn)的LIS的思路題

題意 t組資料,每組資料是長度為n的陣列,其中0可以換為任意的整數 可以使複數 問這個陣列的最長上公升子串行 嚴格上公升 思路 我們發現在選擇的子串行左側和右側的每個0都能使得整個陣列的長度增加1,但如果零實在選擇的序列的中間時則取決於兩個數字的value差與零的個數如1 2 0 0 3,1 2 0...