欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

在C#程序中注入惡意DLL的方法詳解

 更新時(shí)間:2022年09月04日 11:39:40   作者:一線碼農(nóng)聊技術(shù)  
為什么?Windbg?附加到?C#?程序后,程序就處于中斷狀態(tài)了?它到底是如何實(shí)現(xiàn)的?其實(shí)簡(jiǎn)而言之就是線程的遠(yuǎn)程注入,這一篇就展開說一下

一、背景

前段時(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)文章

最新評(píng)論