萌新對C++編寫的動態庫逆向分析
0x00 樣本資訊
病毒名稱:DLL.dll
MD5 值:9810a578f60f8ff2e376769adac9ef38
SHA1:c605455357fe22654a7b974a2a7d301a1b0d064e
SHA256:57e486fe50782e9fdfe73974baa88b553ba58eb5f99ef7386817a3d2e27430f5
這是小編準備的C++學習資料,加小編C/C++學習群:825414254,加群即可獲取哦!

QQ截圖20190309205647.jpg
0x01 行為分析
在分析的過程中,發現程式碼中使用了大量的 ECX 暫存器(thiscall呼叫約定使用ECX暫存器傳遞this指標),並且在給ECX暫存器賦值之後馬上呼叫了函式,所以我斷定這應該是一個使用C++編寫的樣本。下面我將開始正式的分析。
我們檢視其匯出表,發現只匯出了一個函式Run911(),所以,我們從這個函式入手分析這個樣本。

image
當有程式載入這個動態庫時,首先會給將DLL模組控制代碼儲存到全域性變數中。

image
Run911()函式,首先建立了一個執行緒。

image
1、執行緒中初始化一個與通訊有關的類CCommunicate:

image
2、呼叫CCommunicate類的成員函式ConnectServer連線到伺服器:

image
3、如果連線成功,建立了一個與通訊有關的執行緒。

image
(1)該執行緒使用選擇模型與伺服器程序通訊:

image
(2)如果接收到的資料長度小於等於0,則銷燬當前類:

image
(3)否則呼叫CCommunicate類的DealPacket函式對接收到的資料包處理。

image
(4)DealPacket函式對收到的資料進行儲存、解碼、儲存解碼後的資料,解析獲得真正的資料,儲存要傳送的真正的資料。

image
(5)在完成對資料包的解析後呼叫CCommunicate類中的成員變數this[33],該變數是個函式指標,但是該指標在類的建構函式中並沒有初始化,該成員變數的初始化是在CManager類中進行初始化的,將CManager類this指標傳遞給CCommunicate類中this[33]進行儲存。
4、如果與伺服器連線成功則傳送本機的資訊到伺服器。

image
5、構造了一個CManager類的派生類CKernelManager類,在虛基類CManager中會儲存當前通訊類的this指標,將CKernelManager類的this指標儲存至通訊類的成員變數this[33]中,而CKernelManager類的this指標儲存的是CKernelManager的虛表地址,所以每當通訊類收到資料時,就會呼叫虛表在中的函式。
CKernelManager的虛表中的函式AnalyseReceiveData_KernelManager()實現的功能是根據接收到的資料的第一個位元組的不同而選擇不同的功能
Case 0:CMD管理,建立一個執行緒執行CMD管理功能。

image
Case 10:程序管理,建立一個執行緒執行程序管理功能

image
Case 30:視窗管理,建立一個執行緒執行視窗管理功能。

image
Case 50:檔案管理,建立一個執行緒執行檔案管理功能。

image
Case 51:通知管理,建立一個執行緒執行通知管理功能。

image
Case 80:桌面管理,建立一個執行緒執行桌面管理功能。

image
Case 204:回傳204。

image
6、循壞等待退出訊號。

image
對上面的6個不同的功能執行緒進行分析。
1、Case 0:Cmd管理:
建立一個新的通訊類物件,用來接收伺服器傳送的有關CMD管理的資料。

image
連線至伺服器

image
建立CManager的派生類CCmdManager的物件。

image
(1)初始化成員變數,CCmdManager的成員變數如下:

image
(2)建立了兩條管道,分別用於向CMD輸入資料和從CMD中讀出資料。

image

image
(3)獲得cmd.exe的完整路徑:

image
(4)以隱藏的方式啟動cmd.exe程序,並且設定標準輸入輸出為管道。

image
(5)向伺服器傳送資料1;

image
(6)啟動一個CmdManagerWorkThread執行緒對管道中的資料進行處理,管道中的資料並且將管道中的資料傳送到伺服器。

image
等待退出訊號:

image
CCmdManager的虛表中的函式AnalyseReceiveData_CmdManager()實現的功能:如果接收到的資料第一個位元組為2,設定this[2]的Event為授信,否則,將收到的資料寫入到CMD管道中。

image
2、Case 10,30:程序視窗管理(程序管理與視窗管理使用相同的回撥函式,只是傳入的引數不同,所以此處放在一起分析,)
前面的初始化過程和CMD管理相同,同樣是建立一個通訊類的物件,伺服器連線,接收與程序視窗相關的資料。
建立CManager的派生類CCmdManager的物件,根據回撥函式傳入的引數不同,使用不同的初始化函式。
如果為10,使用SendLocalProcessInfo函式列舉本機的程序資訊並將其傳送給伺服器。

image

image
如果為30,使用SendLocalWindowInfo函式列舉本機的視窗資訊並將其傳送給伺服器。

image

image
CProcessWindowManager的虛表中的函式AnalyseReceiveData_ProcessWindowManager根據接收到資料的第一個位元組使用不同的功能。
Case 11呼叫SendLocalProcessInfo傳送本地程序資訊,重新列舉當前程序資訊,然後傳送給伺服器(和初始化時使用同一個函式)。
Case 13呼叫TerminateProcessByProcessID函式殺死指定的程序。

image
Case 31 呼叫SendLocalWindowInfo傳送本地程序資訊,重新列舉當前視窗資訊,然後傳送給伺服器(和初始化時使用同一個函式)。
Case 33 呼叫ShowWindowByWindowHandle函式顯示指定視窗。

image
Case 34 傳送殺死視窗的訊息,然後向伺服器傳送本地視窗資訊。

image
3、Case 50 檔案管理
前面的初始化過程和CMD管理相同,同樣是建立一個通訊類的物件,伺服器連線,接收與程序視窗相關的資料。
建立CManager的派生類CFileManager的物件。

image
(1)初始化成員變數,CFileManager成員變數如下:

image
(2)呼叫CFileManagerWork函式遍歷本機所有磁碟中的物件並且獲得磁碟儲存空間及可用空間的資訊,並將其傳送給伺服器。

image

image

image

image

image
CFileManager的虛表中的函式AnalyseReceiveData_FileManager根據接收到資料的第一個位元組使用不同的功能。
Case 52 呼叫FindFilesInSpecificDirectory在指定的目錄下搜尋檔案。

image

image
Case 54 呼叫CreateFileInSpecificDircetory 在指定的目錄下建立檔案。

image

image
Case 55 呼叫FullFileInSpecificDirectory儲存檔案。

image

image

image
Case 58 呼叫CreatFile函式在當前目錄下建立一個檔案。

image
Case 59 呼叫MoveFileDirectory函式移動函式的目錄。

image
Case 60 開啟或執行檔案。

image
4、Case 51 通知管理
前面的初始化過程和CMD管理相同,同樣是建立一個通訊類的物件,伺服器連線,接收與程序視窗相關的資料,建立CManager的派生類CTalkManager的物件。

image
CTalkManager的虛表中的函式AnalyseReceiveData_Talkger接收到資料的第一個位元組為30 設定當前事件授信,呼叫DialogBoxParamA顯示一個DialogBox對話方塊。

image
5、Case 80 桌面管理
前面的初始化過程和CMD管理相同,同樣是建立一個通訊類的物件,伺服器連線,接收與程序視窗相關的資料,建立CManager的派生類CScreenManager的物件。
(1) 初始化成員變數

image
(2)建立一個執行緒用於傳送桌面截圖。

image
CScreenManager的虛表中的函式AnalyseReceiveData_ScreenManager根據接收到資料的第一個位元組使用不同的功能。
Case 21 阻止鍵盤和滑鼠輸入事件到達應用

image
Case 82 設定退出事件授信

image
Case 85解除鍵盤和滑鼠事件並且將滑鼠和鍵盤事件傳送至伺服器

image
Case 87 將剪貼簿的內容傳送至伺服器

image

image
Case 89 向剪貼簿中填寫內容

image

image
0x02 總結
本次分析的動態庫在總體思路上不是很難,但是由於是由C++編寫的,涉及到了很對有關類和物件的知識,所以在繼承多型這卡了好久,最後是參考《C++反彙編及逆向技術分析》這本書才將整個程式搞清楚的,其中設計到的很多逆向C++的方法我將在後面專門整理一下。