日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

反汇编算法介绍和应用——线性扫描算法分析

發布時間:2023/11/27 生活经验 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 反汇编算法介绍和应用——线性扫描算法分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ? ??做過逆向的朋友應該會很熟悉IDA和Windbg這類的軟件。IDA的強項在于靜態反匯編,Windbg的強項在于動態調試。往往將這兩款軟件結合使用會達到事半功倍的效果。可能經常玩這個的朋友會發現IDA反匯編的代碼準確度要高于Windbg,深究其原因,是因為IDA采用的反匯編算法和Windbg是不同的。下面我來說說我所知道的兩種反匯編算法。(轉載請指明來自breaksoftware的csdn博客)

? ? ? ? 1 線性掃描(Linear sweep)

? ? ? ??線性掃描是一種非常基礎的反匯編算法。看到“線性”二字,我們腦海里可能會立馬浮現出一個指針對一段內存中數據從開始到最后進行一次遍歷的場景。而實際上這種算法的確是如此執行的。像windbg就是使用這種反匯編算法的。反匯編步驟是:

? ? ? ??A 位置指針lpStart指向代碼段開始處

? ? ? ??B 從lpStart位置開始嘗試匹配指令,并得到指令長度n

? ? ? ??C 如果B成功,則反匯編(Intel風格或者AT&T風格)從lpStart之后n個數據;如果失敗,則退出

? ? ? ??D?位置指針lpStart賦值為lpStart+n,即上條指令的結尾

? ? ? ??E 判斷lpStart是否超過了代碼段結尾處,如果超出則結束。如果不超出則進入B流程。

? ? ? ??在A、E這兩個過程中,我們需要提前確定代碼開始處和結束處。一般來說,在windows平臺上,我們可以根據PE文件的可選頭標準域中BaseOfCode結合DataDirectory中相關信息可以算出來代碼開始位置,從PE文件可選頭標準域中SizeOfCode得到代碼段總大小,從而確定結尾位置。

? ? ? ??在B這個過程,對于不同指令集存在細微的差別。現在簡要說下主要兩種指令集:

RISC全稱是Reduced Instruction Set Computing,即精簡指令集。該指令集有個非常重要的特定——指令長度相同,這樣反匯編匹配不會出現回溯現象。

CISC全稱是Complex Instruction Set Computer,即復雜指令集。該指令集一個重要的特點是和RISC正好相反的——指令長度可變,這樣反匯編匹配會出現回溯現象。

? ? ? ??可以發現線性掃描的一大特點就是簡單方便,但是它存在一個問題:它無法知道整個程序的執行流。使用過IDA的朋友會發現,在我們使用IDA打開一個PE文件時,IDA會給我們顯示一個UML類型的執行流程圖。而Windbg就沒有這樣的功能。為什么?就是因為線性掃描有不知執行流這個缺陷。

? ? ? ??既然知道了缺陷,那么在充滿極客的安全領域,自然有人會去研究和利用。我們可以利用這個缺陷,讓Windbg這類使用線性反匯編算法的工具分析出錯誤的結果。

? ? ? ??我們開始一個思考個過程:看如上ABCDE流程,我們可以發現特別“懸”的一個操作就是確定lpStart。因為只要lpStart確定錯誤,那么分析出來的結果肯定是不對的。的確,線性掃描算法就是存在這樣一個致命的問題。那如何利用呢?

? ? ? ??a 在一條可以改變執行流的有效指令后插入無效信息

? ? ? ??這兒所說的指令包括jmp,ja等跳轉,以及ret等改變EIP的指令。

? ? ? ??我們先看個跳轉指令例子

int _tmain(int argc, _TCHAR* argv[])
{int i = argc;if ( argc > 1 ) {i++;}__asm{jz positionjnz position_emit 0xE8position:}i++;return 0;
}

? ? ? ??我們使用jz position、jnz position使程序的執行流肯定走到position處,從而我們在jnz position這條有效指令后插入的0xE8是個無效數據。這樣我們將觸發線性掃描出錯

? ? ? ??我們可以看到插入的0xE8(call指令)影響了分析結果,因為線性掃描在掃描004017fb~004017fc時發現是有效的jne指令,于是它傻乎乎的認為004017fd開始的就是下一條指令開始處。正確的結果我們看IDA的反匯編結果

? ? ? ??我們再看一個ret的例子

int _tmain(int argc, _TCHAR* argv[])
{__asm{push xxxret_emit 0xE8xxx:}printf("1");return 0;
}

? ? ? ??因為push xxx使得棧頂為xxx,而ret將pop出xxx,并將EIP改成xxx,讓程序從xxx初開始執行。這樣我們又構造了一個無效數據0xE8。我們看看Windbg和IDA的反匯編結果

Windbg

? ? ? ??IDA(此處IDA有點智能,它判斷了下ret之后的EIP是否為一個固定地址)

? ? ? ??b 正常的流程識別錯誤

? ? ? ??編譯器在將處理我們代碼時是有策略的,比如當我們switch中case比較多的時候(我在我的環境測試時發現好像要超過2個case),switch case邏輯會使用跳轉表來表達。舉個例子

int switchfun(int nvalue){switch(nvalue) {case 0:case 1: {nvalue++;}break;case 2: {nvalue += 2;}break;case 3: {nvalue += 3;}break;default: {nvalue = 0;};}return nvalue;
}


? ? ? ??可以見到這就是使用了跳轉表。我們可以看到0040177C位置是一組數據。如果我們將這個跳轉表放在0040174A處,將原來0040174A的邏輯后移,并修正相關偏移,是不是我們就讓Windbg分析出錯呢?是的,可是為了構造這樣的結構,我得對我的代碼做改動,且要修改生成的二進制文件。

int switchfun(int nvalue){{__asm nop;...__asm nop;}switch(nvalue) {case 0:case 1: {nvalue++;}break;case 2: {nvalue += 2;}break;case 3: {nvalue += 3;}break;default: {nvalue = 0;};}return nvalue;
}

? ? ? ??我們人為插入多個nop,為我們之后方便修改二進制文件提供空間,同時可以減少計算偏移的量。對二進制文件修改如下


我將從B7C到B92的數據拷貝到以前是一串90(nop)開始處的B34。并緊跟這串數據,將BC4開始的跳轉表數據拷貝過來,同時修正跳轉表的偏移(C4->4A)。程序可以正確執行,我們看windbg的反匯編結果。

? ? ? ??錯了吧!

? ? ? ??我們再看看IDA的反匯編結果

? ? ? ??可以見到IDA分析是正確的。

? ? ? ??經過如上分析,是不是你覺得IDA比Windbg好呢?其實也不一定。線性掃描的一個大優點就是它可以把所有代碼都反匯編掉,而IDA使用的遞歸下降(recursive descent)算法并不一定會將所有代碼都反匯編掉,我會在下一篇博文說明如何利用IDA這個缺陷,來隱藏我們不想被反匯編的邏輯。

總結

以上是生活随笔為你收集整理的反汇编算法介绍和应用——线性扫描算法分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。