日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

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

作者:一線碼農聊技術 ? 更新時間: 2022-10-30 編程語言

一、背景

前段時間在訓練營上課的時候就有朋友提到一個問題,為什么 Windbg 附加到 C# 程序后,程序就處于中斷狀態了?它到底是如何實現的?其實簡而言之就是線程的遠程注入,這一篇就展開說一下。

二、實現原理

1. 基本思路

WinDbg 在附加進程的時候,會注入一個線程到?C# 進程?中,注入成功后,會執行一個?DbgBreakPoint()?函數,其實就是?int 3?,這時候 CPU 就會執行 3 號中斷函數,將當前進程的所有線程進行暫停,文字不好理解的話,畫一個圖大概就是這樣。

口說無憑,接下來用上一個簡單案例演示一下。

2. 案例演示

首先寫一個簡單的 C# 程序,不斷的輸出時間和標號,代碼如下:

????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 附加,你可以發現 Command 自動切換到了?8?號線程,通過 k 命令可以看到最上面是一個 int 3 中斷,截圖如下:

這里就有一個想法了,既然 WinDbg 可以注入,為何我的程序就注入不得呢?既然我的程序可以注入,那就可以做一些我想做的事情。

3. 自定義注入

有了自定義注入的想法,接下來的實現步驟大概是這樣的。

  • 注入一個線程到 C# 程序中。
  • 讓程序加載一個 dll 文件。
  • 在 dll 中做一些我想做的業務邏輯。

接下來新建一個 C++ 的動態鏈接庫,在 DLLMain 入口函數的 ?DLL_PROCESS_ATTACH?事件中寫一個 printf 函數,如果在 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("?總部,總部,我已經成功打入內部!ul_reason_for_call=%d\n ",?ul_reason_for_call);
??break;
?}
?return?TRUE;
}

要被加載的?MyInject.dll?已經構建完畢,接下來就用 Win32 API 的?CreateRemoteThread()?實現遠程注入,但注入之前需要做三件事情。

  • 獲取 C# 程序的 進程句柄。
  • 在 C# 進程中申請一塊內存空間,存放加載的 path 路徑。
  • 調用 LoadLibraryW 函數在 C# 進程中實現 dll 加載。

過程有了,新建一個 C++ 控制臺程序?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.?獲取進程ID
?DWORD??procID?=?GetPid(L"ConsoleApp4.exe");

?//2.?獲取進程句柄
?HANDLE?hProcess?=?OpenProcess(PROCESS_ALL_ACCESS,?FALSE,?procID);

?//3.?在目標進程中開辟一塊空間
?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.?讓目標線程調用?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. 函數執行完后,釋放這塊空間。
?WaitForSingleObject(hThread,?-1);
?VirtualFreeEx(hProcess,?pRemoteAdress,?1,?MEM_DECOMMIT);

?system("pause");
?return?0;
}

萬事具備,接下來我們將?ConsoleApplication1.exe?啟動,可以成功觀察到 ConsoleApp4.exe 上已經注入成功的輸出,截圖如下:

三:總結

這就是對 WinDbg 實現注入攔截的一個衍生知識,整體思路還是很明朗的,當然有注入,就有反注入,比如下面兩條策略。

設置進程的保護屬性。

屏蔽 或者 混淆 Win32 的 LoadLibraryW 函數。

原文鏈接:https://mp.weixin.qq.com/s/XO5Ec3M111_2xiOUy7f0-w

欄目分類
最近更新