作者:
胡一米
·
2016/06/16 10:44
Author:衛士通攻防實驗室([email protected])
0x00 引言
顧名思義,注入這種技術就是將程式碼或DLL注入到另外一個正在執行的程式中,以實現隱藏自身或其他目的。常見病毒根據其需求會選擇不同的注入方式,但每種注入方式都是值得我們瞭解和學習的。本系列文章打算把常見病毒的注入方式分門別類地進行彙總,在每個類別中選擇一個有代表性的病毒,逆向分析該病毒的注入方式,並展示給各位讀者,以供大家學習和參考。
作為本系列的第一篇,筆者將介紹利用WriteProcessMemory()函式進行的DLL注入。作為該類注入方式的代表DesktopLayer.exe也很具有分析價值,下面開始進入正文。此外,筆者忠心希望本系列能給讀者一點啟發和幫助,但由於筆者知識有限,才疏學淺,文中不當或錯誤之處還請各位讀者包容和指正。
- 分析工具:IDA,OD,CFF等。
- 分析環境:Win7 x86 Vmware
- 樣本地址:百度能搜到一堆,實在弄不到,再聯絡筆者吧。
0x01 樣本概況
Name
|
DesktopLayer.exe
|
Size
|
55.00 KB (56320 bytes)
|
MD5
|
FF5E1F27193CE51EEC318714EF038BEF
|
該病毒是近一兩年出現的,功能全面,結構合理,是個不錯的分析和學習物件。為了讓讀者更順利的進行分析和學習,筆者在2.1-2.3節逆向分析介紹了實現注入之前的程式碼功能,如果對這部分不感興趣或是不打算逆向這個樣本,可以直接跳到2.4節。
0x02 詳情分析
一、 脫殼
A. 一層脫殼
樣本被加了UPX 2.90殼。UPX殼最主要的目的是減小程式的體積,其特點是較高的壓縮率和較快的解壓速率,與TMD、VMP這類殼的設計理念完全不同,這類殼更注重對程式碼提供保護的殼。UPX是免費軟體,其官網上可以找到每個UPX版本的加殼程式和相應脫殼程式,網址為http://upx.sourceforge.net/。這裡筆者也懶得去網上翻了,直接手動脫殼就可以了,其脫殼後的入口點模樣如下:

B. 二層脫殼
脫殼之後的樣本仍然壓縮了大量的程式碼,深入分析之後,可以判斷為是變形UPX殼。由於UPX是開源的,所以很多同行會根據需要修改UPX的原始碼。該變型殼首先解碼UPX解碼部分的程式碼,然後利用UPX的解碼程式碼再次解碼惡意功能的程式碼。其中,第一次解碼完成後,會跳入該地址繼續執行,該地址與3.1.1節所述的UPX程式碼基本相同,等完成其解碼之後,可以再次Dump,其最終的入口點如下:

經過二層脫殼之後,會發現樣本的圖示已經改變:

圖中左側為原始圖示,右側為完全脫殼之後的圖示。
二、 第一次執行分析
當正確地脫掉兩層殼之後,就會看到這段程式原本的模樣:

下面開始著重分析其功能,首先是獲取測試機的預設瀏覽器及其位置,其獲取方式是查詢登錄檔中,HKCR\http\shell\open\command
的鍵值:

在筆者分析機中,該值為:

即預設的IE瀏覽器,位置為C:\Program Files\InternetExplorer\iexplore.exe。而後會透過FindFirstFile()函式判斷是否存在該檔案,即iexplore.exe:

如果不存在,那麼會在幾個預設位置進行查詢:

如果存在,則繼續後續操作。接下來會建立互斥體。進而,會透過GetModuleFileName()函式獲取自身執行體所在位置和檔名:

進而會將自身執行體的檔名與DesktopLayer.exe比較:

由於筆者獲取到的樣本名字是dnf_srv.exe,顯然與之不同。那麼,樣本會以此判斷以下7個目錄是否可以有讀寫許可權:
- %ProgramFiles%
- %CommonProgramFiles%
- %HOMEDRIVE%%HOMEPATH%
- %APPDATA%
- SystemDirectory
- WindowsDirectory
- TempPath
當找到第一個有許可權的目錄是,在該資料夾下建立名為Mirosoft的資料夾。在筆者的測試機中,%HOMEDRIVE%%HOMEPATH%是有相應許可權的,即會在C:\Users\zzz目錄下,建立Microsoft資料夾。並將dnf_srv.exe重新命名為DesktopLayer.exe,並複製到C:\Users\zzz\Microsoft資料夾下:


此後,呼叫CreateProcess()建立該程式:

建立該程式之後,程式就呼叫ExitProcess()退出了。
三、 第二次執行分析
此次執行一直到比較執行體名稱的位置之前,都沒有任何變化。而與DesktopLayer.exe比較之後,出現了不同行為。首先是,對ntdll.dll中的ZwWriteVirtualMemory()進行hook操作:

其操作結果為:

而後,會呼叫CreateProcess函式,啟動iexplore.exe程式,該程式的執行體所在位置已於上文中透過查詢登錄檔方式找到:

Createprocess()函式內部會呼叫ZwWriteVirtualMemory()函式,從而執行其經過hook的程式碼,其呼叫棧如下:

其中,sub_402A59即為其HookCode.
四、 HookCode執行分析
HookCode首先完成其正常的WriteVirtualMemory()函式功能:

進而,透過ReadProcessMemory()函式獲取iexplore.exe程式的記憶體資訊:

根據讀取到的記憶體,可以找到後續對iexplore.exe的hook點。
然後,在自身程式內,解碼出rmnsoft.dll,手動載入,並根據匯入表和重定位表進行相應的操作,最後修改頁保護等操作:

當在本地載入完之後,就會把rmnsoft.dll注入到iexplore.exe,這需要分6步進行:
第一步,將DLL寫入iexplore.exe:


特別強調的是,在iexplore.exe中申請的記憶體位置和本程式申請記憶體的位置是一樣的,這樣做的好處是:避免了在iexplore.exe的重定位操作,大大減小了程式碼的複雜度。在筆者的測試機中,其基地址同為0x20010000,如圖:

第二步,將初始化匯入表程式碼寫入iexplorer.exe:

這裡需要指出的是,程式碼內容主要為對PE頭的進行操作的PIC程式碼。
第三步,將修改頁保護相關程式碼寫入iexplorer.exe。

該段程式碼的作用是透過PE頭得到各個區段的頁保護屬性,同樣是PIC程式碼。
第四步,將修復程式碼寫入iexplorer.exe。

該段程式碼會呼叫第1步、第2步、第3步寫入的程式碼。在第5步中,會執行此步驟中的程式碼。
第五步,將相關資料寫入iexplorer.exe。

第六步,在剛剛找到的hook點寫入shellcode,尋找hook點的相關內容見上文:

其中,shellcode內容為:BF 00 00 07 00 68 00 00 08 00 FF D7,長度為0xC。

0x70000和0x80000分別為第3步寫入的程式碼基址和第4步寫入的資料基址。等程式執行到hook點時,會執行shellcode,從而跳到0x70000地址即第3步寫入的程式碼繼續執行進行相關操作。
至此,完整的注入過程和方法已經分析完畢。如果對這部分不是很理解,建議閱讀和學習《程式設計師的自我修養》一書,該書中滿滿的全是乾貨。
下面看一下iexplore.exe的執行效果如何:
執行shellcode:

然後初始化匯入表:

然後,分段判斷並修改程式碼的頁保護:

最後,呼叫DLL main:

此後,該惡意DLL會開始他的行為。
五、rmnsoft.dll分析
該DLL可以在其載入之前dump出來,這裡就不做演示了。此外,該DLL並未有混淆或者加殼等措施,逆向起來比較輕鬆,這裡就不做詳細分析,只做簡要介紹:

如上圖,DLL會建立5個執行緒,其中每個執行緒會實現其相應的惡意功能。
0x03 總結
本文以病毒DesktopLayer.exe為樣本,著重介紹了利用WriteProcessMemory()函式進行DLL注入的方法,簡而言之,可以認為程式直接將所有相關的程式碼和資料直接寫到被注入的程式空間中。其注入的DLL只在記憶體中出現,並未在硬碟中出現過。這種注入方式需要對PE結構有較好的理解,且對DLL裝載過程有很好的理解,建議不熟悉這部分內容的讀者可以閱讀和學習《程式設計師的自我修養》,以進一步獲得提高。
本系列會陸續介紹其他常見病毒的注入方式,希望各位讀者能夠有所收穫。
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!