在C#程序中注入惡意DLL的方法詳解
一、背景
前段時(shí)間在訓(xùn)練營(yíng)上課的時(shí)候就有朋友提到一個(gè)問題,為什么 Windbg 附加到 C# 程序后,程序就處于中斷狀態(tài)了?它到底是如何實(shí)現(xiàn)的?其實(shí)簡(jiǎn)而言之就是線程的遠(yuǎn)程注入,這一篇就展開說一下。
二、實(shí)現(xiàn)原理
1. 基本思路
WinDbg 在附加進(jìn)程的時(shí)候,會(huì)注入一個(gè)線程到 C# 進(jìn)程 中,注入成功后,會(huì)執(zhí)行一個(gè) DbgBreakPoint()
函數(shù),其實(shí)就是 int 3
,這時(shí)候 CPU 就會(huì)執(zhí)行 3 號(hào)中斷函數(shù),將當(dāng)前進(jìn)程的所有線程進(jìn)行暫停,文字不好理解的話,畫一個(gè)圖大概就是這樣。
口說無憑,接下來用上一個(gè)簡(jiǎn)單案例演示一下。
2. 案例演示
首先寫一個(gè)簡(jiǎn)單的 C# 程序,不斷的輸出時(shí)間和標(biāo)號(hào),代碼如下:
????internal?class?Program ????{ ????????static?void?Main(string[]?args) ????????{ ????????????for?(int?i?=?0;?i?<?10000;?i++) ????????????{ ????????????????Console.WriteLine($"{DateTime.Now},i={i}"); ????????????????Thread.Sleep(1000); ????????????} ????????} ????}
把程序跑起來后,使用 WinDbg 附加,你可以發(fā)現(xiàn) Command 自動(dòng)切換到了 8
號(hào)線程,通過 k 命令可以看到最上面是一個(gè) int 3 中斷,截圖如下:
這里就有一個(gè)想法了,既然 WinDbg 可以注入,為何我的程序就注入不得呢?既然我的程序可以注入,那就可以做一些我想做的事情。
3. 自定義注入
有了自定義注入的想法,接下來的實(shí)現(xiàn)步驟大概是這樣的。
- 注入一個(gè)線程到 C# 程序中。
- 讓程序加載一個(gè) dll 文件。
- 在 dll 中做一些我想做的業(yè)務(wù)邏輯。
接下來新建一個(gè) C++ 的動(dòng)態(tài)鏈接庫,在 DLLMain 入口函數(shù)的 DLL_PROCESS_ATTACH
事件中寫一個(gè) printf 函數(shù),如果在 C# 程序中輸出來了,就算成功注入了,參考代碼如下:
#include?<Windows.h> #include?<stdio.h> BOOL?APIENTRY?DllMain(HMODULE?hModule, ?DWORD??ul_reason_for_call, ?LPVOID?lpReserved ) { ?switch?(ul_reason_for_call) ?{ ?case?DLL_PROCESS_ATTACH: ??printf("?總部,總部,我已經(jīng)成功打入內(nèi)部!ul_reason_for_call=%d\n ",?ul_reason_for_call); ??break; ?} ?return?TRUE; }
要被加載的 MyInject.dll
已經(jīng)構(gòu)建完畢,接下來就用 Win32 API 的 CreateRemoteThread()
實(shí)現(xiàn)遠(yuǎn)程注入,但注入之前需要做三件事情。
- 獲取 C# 程序的 進(jìn)程句柄。
- 在 C# 進(jìn)程中申請(qǐng)一塊內(nèi)存空間,存放加載的 path 路徑。
- 調(diào)用 LoadLibraryW 函數(shù)在 C# 進(jìn)程中實(shí)現(xiàn) dll 加載。
過程有了,新建一個(gè) C++ 控制臺(tái)程序 ConsoleApplication1.exe
, 整體的參考代碼如下:
#include?<iostream> #include?<Windows.h> #include?<stdio.h> #include?<stdlib.h> #include?<Tlhelp32.h> DWORD?GetPid(const?WCHAR*?szName) { ?HANDLE?hprocessSnap?=?NULL; ?PROCESSENTRY32?pe32?=?{?0?}; ?hprocessSnap?=?CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,?0); ?pe32.dwSize?=?sizeof(PROCESSENTRY32); ?if?(Process32First(hprocessSnap,?&pe32)) ?{ ??do?{ ???if?(!wcscmp(szName,?pe32.szExeFile))?{ ????return?(int)pe32.th32ProcessID; ???} ??}?while?(Process32Next(hprocessSnap,?&pe32)); ?} ?else ?{ ??CloseHandle(hprocessSnap); ?} ?return?0; } int?main() { ?const?wchar_t*?path?=?L"D:\\net6\\ConsoleApp1\\x64\\Debug\\MyInject.dll";?//要注入的dll文件地址 ?//1.?獲取進(jìn)程ID ?DWORD??procID?=?GetPid(L"ConsoleApp4.exe"); ?//2.?獲取進(jìn)程句柄 ?HANDLE?hProcess?=?OpenProcess(PROCESS_ALL_ACCESS,?FALSE,?procID); ?//3.?在目標(biāo)進(jìn)程中開辟一塊空間 ?LPVOID?pRemoteAdress?=?VirtualAllocEx(hProcess,?NULL,?wcslen(path)?*?2,?MEM_COMMIT,?PAGE_READWRITE); ?//4.?將?path?寫入到這塊空間中 ?BOOL?bRet?=?WriteProcessMemory(hProcess,?pRemoteAdress,?path,?wcslen(path)?*?2,?NULL); ?//5.?讓目標(biāo)線程調(diào)用?LoadLibraryW?加載我們注入的?dll ?HMODULE?hModule?=?GetModuleHandle(L"kernel32.dll"); ?LPTHREAD_START_ROUTINE?dwLoadAddr?=?(LPTHREAD_START_ROUTINE)GetProcAddress(hModule,?"LoadLibraryW"); ?HANDLE?hThread?=?CreateRemoteThread( ??hProcess, ??NULL, ??0, ??(LPTHREAD_START_ROUTINE)dwLoadAddr, ??pRemoteAdress, ??NULL, ??NULL ?); ?//6. 函數(shù)執(zhí)行完后,釋放這塊空間。 ?WaitForSingleObject(hThread,?-1); ?VirtualFreeEx(hProcess,?pRemoteAdress,?1,?MEM_DECOMMIT); ?system("pause"); ?return?0; }
萬事具備,接下來我們將 ConsoleApplication1.exe
啟動(dòng),可以成功觀察到 ConsoleApp4.exe 上已經(jīng)注入成功的輸出,截圖如下:
三:總結(jié)
這就是對(duì) WinDbg 實(shí)現(xiàn)注入攔截的一個(gè)衍生知識(shí),整體思路還是很明朗的,當(dāng)然有注入,就有反注入,比如下面兩條策略。
設(shè)置進(jìn)程的保護(hù)屬性。
屏蔽 或者 混淆 Win32 的 LoadLibraryW 函數(shù)。
以上就是在C#程序中注入惡意DLL的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于C#注入惡意DLL的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#?Winform消息通知之系統(tǒng)本地通知local?toast?notification
這篇文章主要為大家介紹了C#?Winform消息通知之系統(tǒng)本地通知local?toast?notification使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08C# CultureInfo之常用InvariantCulture案例詳解
這篇文章主要介紹了C# CultureInfo之常用InvariantCulture案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08Untiy Shader實(shí)現(xiàn)紋理貼圖滾動(dòng)
這篇文章主要為大家詳細(xì)介紹了Untiy Shader實(shí)現(xiàn)紋理貼圖滾動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03C#使用NPOI讀取excel轉(zhuǎn)為DataSet
這篇文章主要為大家詳細(xì)介紹了C#使用NPOI讀取excel轉(zhuǎn)為DataSet,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02C#與C++?dll之間傳遞字符串string?wchar_t*?char*?IntPtr問題
C#與C++?dll之間傳遞字符串string?wchar_t*?char*?IntPtr問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11WPF+Canvas實(shí)現(xiàn)平滑筆跡的示例代碼
這篇文章主要介紹了如何利用WPF+Canvas實(shí)現(xiàn)平滑筆跡效果,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,需要的可以參考一下2022-09-09SQLite之C#版 System.Data.SQLite使用方法
這篇文章主要介紹了SQLite之C#版 System.Data.SQLite使用方法,需要的朋友可以參考下2020-10-10