惡意樣本脫殼-GandCrab2.0 脫殼筆記分析記錄

GandCrab2.0 脫殼筆記分析記錄

有人在2018年的時候就分析過了惡意樣本分析,相關資料可以查看參考部分。由於裏邊有很多可以學習和總結的脫殼技術,因此重新分析這個樣本,這篇文章暫時不做加密和勒索實際功能分析,如果要看分析樣本形成勒索的過程以及相關分析報告,可以直接跳到參考部分,這篇文章主要關注的是脫殼相關的一些技術細節的分析,由於文章是我個人的一些分析和總結,因此會有一些不足,比較趨向於像我這樣剛接觸惡意軟件分析,由於很多樣本在分析前需要脫殼之後才能看到核心功能,因此這裏重點關注脫殼過程,主要內容如下

  • 解密並dump出shellCode

  • 解密並dump出PE1

  • 解密並dump出encrpt.dll

解密並dump出shellCode

使用IDA打開病毒母體,來到入口函數,經過分析後程序會解密出資源文件的內容

在這裏插入圖片描述
調用VirtualProtect函數修改shell_code的屬性爲可讀寫,這裏的VirtualPtotect函數是通過動態獲取的函數指針

在這裏插入圖片描述

之後調用函數sub_401014shell_code解密並調用

在這裏插入圖片描述
爲了能進一步分析shell_code,需要在動態調試階段dump下來,因此這裏使用x32dbg調試母體病毒,在程序調用shell_code的時候,單步進入後dump下來,如下是來到執行調用shell_code的位置

在這裏插入圖片描述

此時選擇單步進入,來到shell_code的入口處,如下

在這裏插入圖片描述

此時將內存dump下,步驟爲在內存窗口點擊右鍵-->選擇 在內存佈局中轉到

在這裏插入圖片描述
之後跳轉到內存佈局,之後選中對應的內存位置一般使用這個方式跳轉到內存佈局文件,默認會選擇指定的內存,然後右鍵保存爲文件,之後命名爲shell_code.bin,如下

在這裏插入圖片描述

使用ida分析shell_code的功能。

ShellCode功能分析

現在主要對shellcode的功能分析,這部分主要會完成如下功能

  • 解密PE1文件
  • 動態填充encrypt.dll文件
  • 反射調用encrypt.dll

解密並dump出PE1

在執行解密PE1這個文件之前,需要弄清楚幾個問題

  • [ebp-0A0h]保存的內容是什麼
  • 動態獲取kernel32.dll函數是如何保存的
  • 解密的PE1文件什麼時候選擇dump

初始化數據和導入APIs

[ebp-0A0h]保存的內容是什麼

在動態調試階段注意如下指令

mov     eax, [ebp-8Ch]
mov     ecx, [ebp-3Ch]
lea     eax, [ecx+eax-38h]
mov     [ebp-8], eax
mov     eax, [ebp-8]
mov     [ebp-0A0h], eax ;這裏賦值給[ebp-0xA0]

動態調試階段內內存內容如下

在這裏插入圖片描述

根據內存中的內容可以知道,這裏保存的是一個PE文件,不過是被加密了在後面會執行解密,在執行解密前,程序動態保存了kernel32.dll GetProcAddress函數在棧上使用。如下

在這裏插入圖片描述

通過這個手段,分別將需要的函數保存在了當前的棧上,主要獲取的函數包括

 mov dword ptr ss:[ebp-38],eax  ;VirtualProtect 
 mov dword ptr ss:[ebp-48],eax  ;VirutalAlloc
 mov dword ptr ss:[ebp-24],eax  ;VirutalProtect
 mov dword ptr ss:[ebp-5c],eax  ;VirutalFree
 mov dword ptr ss:[ebp-44],eax  ;GetVersionExA
 mov dword ptr ss:[ebp-38],eax  ;TerminateProcess

這些字符串在dump出的shell_code中靜態分析顯示如下

在這裏插入圖片描述

查看字符串內容

在這裏插入圖片描述

由此可以知道這個主要是爲了避免殺毒軟件所查殺,因此在解密shellc_code並運行後,動態階段解密後導入。

繼續往下來到如下指令

push    dword ptr [ebp-44h] ; ptr_GetVersionExA
push    100000h
push    dword ptr [ebp-0A8h] ; buff_1
call    sub_4497

這裏的[ebp-0x0A8]實際指向的是新的一個程序塊,這部分的內容還沒有被修復

在這裏插入圖片描述

dump下這個文件命名爲stage2.bin

在這裏插入圖片描述
拖入ida分析後保存,這部分的節區等信息沒有被填充,如下

在這裏插入圖片描述

這部分也是需要在後面的修復中使用的。

動態獲取kernel32.dll函數是如何保存的

根據上面的分析shell_code在運行階段動態導入了需要使用的API保存在棧上。

解密的PE1文件什麼時候選擇dump

在前面的準備階段完成後開始調用VirtualAlloc分配一塊內存
image-20200518120642921.png

將返回的內存指針保存在了[ebp-0x10],這裏命名內存塊爲new_pe1_buff,然後調用sub_4170函數執行解密

在這裏插入圖片描述

執行解密前的new_pe1_buff的內存內容

在這裏插入圖片描述

解密後

在這裏插入圖片描述

此時將內存的數據保存解密後的內存爲PE1.exe,這樣就能獲取解密後的PE1數據了。

下面的過程主要是分析內存修復PE文件的過程

往下繼續分析,在解密PE1文件後,接着調用VirtualProtect函數修改了[ebp-0xA8]內存屬性爲0x40,對照了MSDN的文檔後知道,修改爲可讀寫屬性,如下

#參考https://docs.microsoft.com/zh-cn/windows/win32/memory/memory-protection-constants
PAGE_EXECUTE_READWRITE
0x40

在這裏插入圖片描述

修改完屬性後就將[ebp-0xA8]的數據清空,目的是接下來就會對這個內存重新導入新的數據塊 call sub_435D函數實際是調用了memset函數,如下

在這裏插入圖片描述

在這裏插入圖片描述
在清空前的[ebp-0xA8]內存

在這裏插入圖片描述

執行後清空掉這塊內存,目的是後續重組一個PE文件

在這裏插入圖片描述

重組一個PE文件,需要的數據包括

  • [ebp-0x10]
  • [ebp-0x90]

開始組裝新的PE文件,調用sub_3EE函數複製頭部信息,內容保存在[ebp-0xA8]

push    dword ptr [eax+14h];指向section->PointerToRawData
push    dword ptr [ebp-34h];指向了 new_pe1_dos_header
push    dword ptr [ebp-90h];這裏指向的[ebp-0xA8]
call    sub_43EE

這裏的[eax+0x14]是.text節區在文件內的大小映射到[ebp-0xA8]內。如下是動態調試時參數

在這裏插入圖片描述

之後完成後就將[ebp-0x10]的節區按照文件大小映射到內存中,執行前
在這裏插入圖片描述

執行復制函數後,

在這裏插入圖片描述

這裏就將複製完了第一部分內容,後面還要繼續複製節區數據和IAT修復。

複製section

在複製完header部分後後面,接着開始修復節區和IAT表。首先獲取節區大小

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
根據[ebp-0xB0]當做節區索引,如果小於當前的節區表大小,則跳入複製節區表

在這裏插入圖片描述

在這裏插入圖片描述

讀取下一個節區

在這裏插入圖片描述

重複複製完成後,開始修復IAT表

修復IAT

在這裏插入圖片描述

設置完成導入表和導出表後,執行讀取符號

在這裏插入圖片描述

這裏將[ebp-0x90]命名爲payload.dll

在這裏插入圖片描述

修復完成所有的函數後,最後跳轉執行PE1.exe,來到最後跳轉位置

在這裏插入圖片描述

這個過程其實不用去過分關注,因爲程序的核心程序並不在後面的節區複製和修復IAT過程,我們dump出的PE1.exe已經可以用作靜態分析和動態調試了,經過分析後發現在解密完成PE1.exe之後的操作屬於擾亂分析的一個手段實際程序會跳轉到PE1.exe內執行解密encrypt.dll,這個在後面的動態調試PE1.exe中可以得到證明,分析的好處就是對內存加載PE以及修復PE的過程有了更熟悉了一些。

解密並dump出encrpt.dll

根據前面的分析可以知道,shell_code的主要功能是解密出PE1程序然後執行,釋放的PE1並沒有被寫入到本地,這樣就可以減少被查殺的概率,直接是無文件方式執行,同樣的encrypt.dll也不會被寫入到本地中,而是解密後反射運行,如下是dump的過程。

首先程序先解密出encrypt.dll程序

在這裏插入圖片描述

之後獲取dll內的ReflectLoader函數

在這裏插入圖片描述

利用反射調用的方式執行encrypt.dll,關於反射調用可以看stephenfewer開源的項目,和一般的利用注射器(進程注入dll)方式利用VirtualAlloc,WriteProcessMemory,CreateRemoteThread,LoadLibrary等當時的注入不同,注射器方式需要寫入dll到本地然後利用LoadLibrary函數加載dll觸發dll內的DllMain會被執行,反射調用會在當前運行的進程加載dll然後執行。

在獲取到ReflectiveLoader之後調用VirtualProtect函數修改encrypt.dll的屬性爲可執行

在這裏插入圖片描述

這裏就完成了PE1的核心功能

  • 解密encrypt.dll
  • 調用encrypt.dll內的導出符號ReflectiveLoader函數然後執行encyrpt.dll

接下來就是核心encrypt.dll的分析,在分析之前需要dump出這個dll文件。這一步我在分析和調試的時候走了很多彎路,例如一直調試母體病毒,分析shell_code的解密功能,包括解密出了PE1之後的程序,不過在多次調試和分析中,對這種內存解密和加載PE文件的方式也熟悉了不少。

dump核心的encrypt.dll可以建立在第二階段獲取的PE1.exe這個文件內,直接使用x32dbg調試PE1.exe文件,在分析PE1.exe時可以知道,程序要執行encrypt.dll前會調用VirtualProtect函數修改內存屬性,由此可以知道此事的encrypt.dll是解密完成了,因此我們直接在調試的PE1.exeVirtualProtect函數上設置斷點,需要注意的是這個函數會被調用兩次,因此我們只需要在第一次命中斷點後選擇dump下來即可,設置斷點的選擇在如下位置方便獲取到參數

在這裏插入圖片描述

設置好斷點後運行程序,在第一次斷下來後查看內存,如下

在這裏插入圖片描述

此時選擇dump下來保存,即可獲取到了核心的encrypt.dll

總結

首先程序會解密出shellCode來解密出第一階段的PE1程序,PE1負責解密出encrypt.dll,之後通過反射調用的方式來運行惡意行爲。從這個過程中可以看出這個過程是一個無文件方式,相比較於注射器來完成的進程注入方式,反射調用更加隱蔽。

一些常用的脫殼點可以在脫殼階段使用:

關鍵內存Api斷點

如果是進程注入的方式會選擇在VirtualProtect,WriteProcessMemeory VirtualAlloc函數設置斷點分別獲取解密的PE文件,這種脫殼方式可以稱爲關鍵內存Api斷點;例如上面的脫殼過程,可以設置斷點在VirtualProtect,VirtualAlloc上,程序運行後分別關注每個次斷點內存中的內存,然後每次都dump下來,然後做分析即可,可以不用去關心實際的一些解密過程。

ESP定律

如果是壓縮殼類的,可以考慮ESP定律手段,這個資料比較多,也容易上手,這個我會在分析兩個壓縮殼的樣本。

參考

來源

基本分析

詳細分析1

詳細分析2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章