芯片IC單片機解密百科

十年專注單片機解密

程序反匯編技術詳細分析

先總結一下,在這個函數中BBIN导航學到了使用SEH來改變程序的執行流程。SHE通常用來反-反匯編和反調試技術。另外異常處理程序的地址也被XOR混淆了。本次實驗BBIN导航會分析一個特別準備好的二進製文件(非惡意文件),但是裏麵使用了各種反-反匯編技術。


首先使用IDA打開antidisasm.exe:



你可以看到這裏有一組函數調用,每一個函數使用了不同的反反匯編技術,並把返回值保存在eax寄存器。本次任務是通過靜態分析找出每個函數的返回值是什麽?


1)  分析Loc_40101A函數


首先進入到0x40101A函數



看上去IDA並沒有識別出這是一個函數,而且這個函數看上去也沒有返回值,因為在CALL EAX指令後麵有一些垃圾指令,而loc_401045標簽位置是下一個函數的開始。


注意 在loc_40101A開始的地方有一個奇怪的call( call $+5)。




這個有趣的CALL的調用地址是下一條指令(0x401022)。它這樣調用的目的是為了把返回地址(0x401022)PUSH到棧上,然後通過執行POP EAX指令把剛才的地址加載到EAX。


然後EAX+10被加10後,CALL向了這個新的EAX的值。




現在你知道EAX的值是0x401032(0x401022+0x10)。不幸的是,這個地址的位置是垃圾代碼中間的位置,並且看上去這個地址的位置並沒有指令。



很明顯這些垃圾代碼是因為反匯編引擎解析某些指令時出現了錯位導致的。因為在IDA解析CALL EAX這條指令,IDA並不知道它CALL的地址是多少,所以嚐試反匯編CALL EAX的下一條指令。


要修複這個問題,首先選中所有的垃圾代碼,然後右鍵選擇undefined(或者按U鍵):



下一步,選中0x401032位置的第一個字節,按下C鍵把這個位置的字節轉換成代碼。可以看到CALL EAX指令後麵出現了一個字符串”Fintastic!”。



現在代碼比剛才清晰多了,你可以看到loc_40101A函數的返回值是0x1337。



總結一下,在這個函數中學到了兩種反反匯編技術,第一這裏有個間接調用到動態計算的地址。IDA不知道這個被調用的地址是多少,因此它嚐試解析這個CALL後麵在行內嵌入的字符串(第二種反反匯編技術)。最終導致解析出了一些垃圾指令,而不是一個有效的匯編指令。


2)  分析loc_401045函數


本次BBIN导航將分析位於loc_401045的函數。



第一眼看上去盡管IDA並沒有識別出這裏的代碼是一個正常的函數,但是這裏有一個經典的函數開始和結束retn指令。你也可以高亮EAX寄存器來找到它在哪裏被賦值的。


看上去EAX第一次被賦值成了0x11EB,然後增加了0x1000。即使如此,BBIN导航應該把注意力放在跳轉指令(jz),jz看上去是跳轉到了另一條匯編指令的中間位置。同樣注意到這裏有個有條紅色交叉引用,看上去這裏貌似出現了什麽問題。



在分析jz將要跳轉到哪裏之前,先來看看什麽條件它才會跳轉。最後一條指令導致零標誌位ZF被置1的指令是jz跳轉指令前麵的XOR EAX EAX,它會清空EAX寄存器,並設置ZF標誌為1。這表示跳轉一定會被執行。


由於跳轉到了一條匯編指令中間,選中這條指令並把它轉換成數據(使用Undefine 或 按U鍵)。



IDA可能會轉換比你預期等多的代碼,但沒關係,因為你知道jz跳轉的目標地址是0x40104B,原始的jz指令位於0x401050。



現在選中0x40104B處的一字節,按下C轉換成代碼,同樣操作來轉換jz指令的位置,0x401050。做完這些操作後,你應該能看到類似下麵這樣的代碼:



這表示在PUSH指令中間隱藏了另一個跳轉指令jmp。



正如你所見,這條被隱藏的跳轉指令的目的地址是0x40105E(另一條匯編指令0x40105D的中間位置)。但是這次看上去是一個正常的匯編錯位解析指令。


為了繼續進行,把0x40105D轉換成數據,然後把0x40105E位置轉成代碼,轉換完成後,你看到的代碼應該是這個樣子:



現在你可以清楚的看到返回值被設置成了0x4096。注意在返回指令retn後麵的這幾個垃圾字節,是曾經被用來阻止IDA反匯編EAX被賦值這條指令的。


下麵截圖展示了在沒有做任何修改之前,這個函數的執行流程:



總結一下通過這個函數你學習到的一些反-反匯編技術。最明顯的一個就是跳轉到另一條指令中間。在這種情況下PUSH指令被用來隱藏另一個跳轉指令。你還看到把jz條件跳轉變成了無條件跳轉,以及一些垃圾字節來阻止IDA反匯編。


3)  分析sub_401065函數


下一個要分析的函數是sub_401065。但是這次IDA把它識別成一個正常的函數了。



可以看到EAX開始被清空了,然後調用了sub_40107D函數(傳入參數0x1000),最終EAX又增加了0x1000。問題是不知道sub_40107D函數的返回值EAX有沒有被修改。


來看一下sub_40107D函數:



看上去這個函數做的唯一一件事就是把參數0x1000賦值給了EAX,然後又加了0x1000,當這個函數返回時EAX應該是0x2000。難道sub_401065函數的返回值是0x3000(0x2000+0x1000)?


正如你所懷疑,並不是那麽簡單。來看一下sub_40107D返回前發生了什麽:



首先把第一個參數的地址傳給了EDX,然後把EDX減去4。還知道現在EDX保存的指針指向哪裏麽?看一下堆棧的結構:



在EDX減去4後指向了棧上返回地址的位置,然後,在第三行,給返回地址增加了0x2B。這表示當前函數sub_40107D的返回地址被修改了,它將跳轉到代碼的其他地方。


為了檢查它會跳轉到哪裏,返回來看一下sub_401065:



的返回地址是0x401074。但是你知道它被增加了0x2B。所以sub_40107D將會返回到0x40109F(0x401074+0x2B)。切換到下一個視圖找到這個返回地址的位置。



一點也不意外返回地址的位置出現了花指令,按U轉換成數據,然後在0x40109F的位置按C再轉成代碼:



BBIN导航看到了最終EAX的值是0xC0DE!


總結一下,通過剛才分析,BBIN导航學習到了一種比較流行的反-反匯編技術叫做返回地址替換。因為惡意代碼欺騙了IDA,將調用函數中的返回地址替換掉了,導致IDA解析出來的返回地址並不是它原版真實的返回地址。


4)  分析sub_4010B2函數


現在BBIN导航來看一個不完整的sub_4010B2函數



中間代碼忽略



如果你進入到這個函數看反匯編代碼,你將看到很多的反匯編代碼在用各種指令來操作EAX寄存器。盡管如此,如果你仔細看就會發現,有一些組合指令都在執行一些無意義的操作。






這是一種比較簡單的混淆技術,這些被嵌入在正常代碼中間的花指令除了讓手動分析變得更難以外,對程序的執行流程不會有任何影響。


處理這種花指令的唯一方法就是在它們當中找到規律,如果你找到了花指令的規律,你才可以嚐試編寫腳本來用NOP指令來覆蓋這些花指令,或者使用某種顏色來高亮它們。但是編寫腳本不在本篇教程範圍之內。


如果你再仔細分析一下這些花指令,你會發現隻有3條指令會映像最終EAX的值:





這表示最終EAX的值是0x1500。


5)  分析sub_40116D函數


最後一個要分析的函數是sub_40116D。



在這個程序中EAX的返回值看上去是0xEBFE。即使如此,你應該馬上能注意到:


MOV FS:0,ESP這條指令告訴BBIN导航它正在安裝一個SHE(標準化異常處理程序)。


異常處理程序被保存成一個單向鏈表結構,每個節點是EXCEPTION_REGISTRATION的結構:

_EXCEPTION_REGISTRATION struc

prev     dd ?

handler dd ?

_EXCEPTION_REGISTRATION   ends


這個結構由兩個字段組成,第一個字段prev是指向下一個EXCEPTION_REGISTRATION結構的指針,第二個字段handler指向異常處理函數。


指向第一個EXCEPTION_REGISTRATION結構永遠被保存在TIB的第一個DWORD字節中。在Win32平台TIB的地址被保存在FS寄存器中,因此指向MOV FS:0,ESP這條指令等於把棧頂的保存的值,設置成了第一個異常處理結構EXCEPTION_REGISTRATION。




在sub_40116D這個函數中,棧的結構應該是這樣的(安裝SHE之後):



那麽問題來了,在這個函數中是否有異常被觸發了?答案是肯定的,先來看看ECX寄存器,它被設置成0了,然後程序嚐試寫入一個DWORD到ECX保存的地址。因為ECX指向了一個未申請內存地址0x00000000,所以一定會觸發非法內存訪問異常(STATUS_ACCESS_VIOLATION-0xC0000005)。



但是異常處理函數的地址是多少呢?在這個例子中,你看到0x15232A1被push到棧上了,但是它並不是一個有效的函數地址。注意上圖中的XOR指令將0x1122300與異常處理函數的地址異或。表示真正的地址是0x15232A1 xor 0x1122300 = 0x4011A1。


你也可以使用IDA中的計算器來計算,(View->Calculator 或者按下SHIFT+/鍵):



現在切換視圖到0x4011A1的位置:



重複BBIN导航之前的套路,把0x4011A1位置的數據轉換成代碼:



你可以看到EAX被賦值了0x512,其他指令隻是恢複棧幀並跳轉到sub_40116D的函數尾部。


總結一下,在這個函數中BBIN导航學到了使用SEH來改變程序的執行流程。SHE通常用來反-反匯編和反調試技術。另外異常處理程序的地址也被XOR混淆了。