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...