逆向入門分析實戰(二)

合天智匯發表於2020-04-24

本文首發於“合天智匯”公眾號,未經允許,禁止轉發!

 

上次我們對主函式分析完成了,逆向入門分析實戰(一)那麼這次我們對子函式IsAlreadyRun進行分析。

 

C語言程式碼

IsAlreadyRun函式的C語言程式碼如下圖所示:

1.png

下面對其彙編程式碼進行分析:

2.png

rep stosd之前,同樣是入棧操作,我們無需仔細追究,重點關注call函式。

1. CreateMutexA函式

首先根據call ds:CreateMutexA

這一條指令便可得知呼叫了CreateMutex函式(注:CreateMutexA是在Ascii 環境下的,CreateMutexW是unicode環境下的)。

上次我們提到過,在函式呼叫之前,如果有引數需要傳遞,需要使用push先將引數從後往前入棧。那麼我們來看下call ds:CreateMutexA前面的三條push指令分別代表什麼意思?如果查呢?這就用到非常常用的一個文件--msdn文件,這個文件是微軟寫的,介紹了Windows API函式,基本上遇到的函式都可以在這裡查到,比如CreateMutex這個函式對應的地址是:https://docs.microsoft.com/zh-cn/windows/win32/api/synchapi/nf-synchapi-createmutexa

從官網可以看到對應的函式解釋,詳細介紹了這個函式的作用,引數,返回值等:

3.png

三個引數lpMutexAttributes,bInitialOwner,lpName中第三個引數lpName的意思是互斥物件的名稱,另外兩個在此處不展開介紹了,感興趣的可以去檢視msdn文件。現在我們再回過頭來仔細看一下ida Pro給的反彙編程式碼:

4.png

是不是和MSDN上的三個引數反過來就對應上了?第一條push指令對應的是lpName這個引數,所以根據ida pro右邊給出的備註,可以得知這個互斥物件的名稱是TEST。上一次也提到過,函式呼叫完成後,VC中,會使用eax暫存器來儲存函式的返回值。在這裡也是一樣的,call ds:CreateMutexA的返回值會存入eax暫存器。

2. 跳轉分析

我們繼續分析下面的彙編程式碼:

5.png

根據call __chkesp可知是呼叫了棧平衡錯誤檢測函式,這裡我們無需理會。之後,

QQ截圖20200320143435.jpg

mov指令將呼叫CreateMutexA函式的返回值eax先移動到ebp+var_4的地址上,之後又與0對比,如果兩者相等,則跳轉到 loc_40107D位置。即,如果CreateMutexA函式的返回值為0,則跳轉 loc_40107D位置。

下面分兩種情況進行討論,一種是CreateMutexA函式的返回值為0,一種是不為0。

2.1. CreateMutexA返回值為0

首先分析CreateMutexA函式的返回值為0的情況:

跳轉到這個位置之後,執行xor eax,eax這條指令,上次也提到過xor eax,eax直接會將eax的值設定為0,這是很常見的一種將eax置為0的方式。

6.png

執行完這條指令後,會到loc_40107F位置,根據pop出棧指令、call __chkesp、retn等指令可知,這是子函式IsAlreadyRun呼叫完要返回主函式。

7.png

那麼,IsAlreadyRun函式的返回值是多少呢?返回值存在eax中,由前面可知,eax在CreateMutexA函式的返回值為0情況下,eax值為0(xor eax,eax的作用),所以IsAlreadyRun函式的返回值也是0,即IsAlreadyRun返回值為false。

對應的C語言程式碼:

8.png

即,當hMutex = ::CreateMutex(NULL, FALSE, "TEST")執行後得到的hMutex為0時的場景,子函式IsAlreadyRun直接執行return FALSE;

2.2. CreateMutexA返回值不為0

之後,分析CreateMutexA函式的返回值不為0的情況:

9.png

此時,由於eax不為0,所以不會跳轉到loc_40107D這個位置,而是執行call ds:GetLastError執行呼叫GetLastError函式。後面又執行call __chkesp 呼叫棧平衡錯誤檢查函式,我們在這裡無需理會。之後執行cmp eax,0B7h指令,由於GetLastError函式的返回值儲存在eax中,此處其實是在看GetLastError返回值是否等於16進位制的B7,對應10進位制的183。

如果eax的值不等於183,那麼跳轉到loc_40107D,之後和上一種情況一樣,將eax置為0,然後返回主函式。

如果eax的值等於183,則執行mov eax,1指令,然後跳轉到loc_40107F位置,返回主函式。

那麼這個183到底代表什麼意義呢?通過查詢MSDN文件,我們可以得知,它剛好對應常數ERROR_ALREADY_EXISTS。

對比我們寫的C語言程式碼:

0.png

也就是GetLastError函式的返回值等於ERROR_ALREADY_EXISTS時,返回true;否則,返回false。

到此為止,整個程式碼分析完畢。感謝各位耐心的閱讀,如有不當之處,歡迎指出。

參考書籍:

《Windows黑客程式設計技術詳解》甘迪文著--北京:人民郵電出版社,2018年12月。

《C++反彙編與逆向分析技術揭祕》錢松林,趙海旭著--北京:機械工業出版社,2011年9月。

《惡意程式碼分析實戰》 (美)Michael Sikorski / Andrew Honig 著,諸葛建偉,姜輝,張光凱譯 -- 北京:電子工業出版社,2014年4月,原書名:Practical Malware Analysis: The Hands-On Guide to Dissecting Malicious Software。

《組合語言》王爽 著--2版,北京:清華大學出版社,2008年4月。

相關文章