本文首發於“合天智匯”公眾號,未經允許,禁止轉發!
上次我們對主函式分析完成了,逆向入門分析實戰(一)那麼這次我們對子函式IsAlreadyRun進行分析。
C語言程式碼
IsAlreadyRun函式的C語言程式碼如下圖所示:
下面對其彙編程式碼進行分析:
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
從官網可以看到對應的函式解釋,詳細介紹了這個函式的作用,引數,返回值等:
三個引數lpMutexAttributes,bInitialOwner,lpName中第三個引數lpName的意思是互斥物件的名稱,另外兩個在此處不展開介紹了,感興趣的可以去檢視msdn文件。現在我們再回過頭來仔細看一下ida Pro給的反彙編程式碼:
是不是和MSDN上的三個引數反過來就對應上了?第一條push指令對應的是lpName這個引數,所以根據ida pro右邊給出的備註,可以得知這個互斥物件的名稱是TEST。上一次也提到過,函式呼叫完成後,VC中,會使用eax暫存器來儲存函式的返回值。在這裡也是一樣的,call ds:CreateMutexA的返回值會存入eax暫存器。
2. 跳轉分析
我們繼續分析下面的彙編程式碼:
根據call __chkesp可知是呼叫了棧平衡錯誤檢測函式,這裡我們無需理會。之後,
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的方式。
執行完這條指令後,會到loc_40107F位置,根據pop出棧指令、call __chkesp、retn等指令可知,這是子函式IsAlreadyRun呼叫完要返回主函式。
那麼,IsAlreadyRun函式的返回值是多少呢?返回值存在eax中,由前面可知,eax在CreateMutexA函式的返回值為0情況下,eax值為0(xor
eax,eax的作用),所以IsAlreadyRun函式的返回值也是0,即IsAlreadyRun返回值為false。
對應的C語言程式碼:
即,當hMutex = ::CreateMutex(NULL, FALSE, "TEST")執行後得到的hMutex為0時的場景,子函式IsAlreadyRun直接執行return FALSE;
2.2. CreateMutexA返回值不為0
之後,分析CreateMutexA函式的返回值不為0的情況:
此時,由於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語言程式碼:
也就是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月。