利用Win32 API将DLL注入C#进程的C++实现详解

小满
小满
发布时间:2026-10-15| 5人浏览过
原创

通过深入分析 Windbg 调试器附加 C# 进程时的底层行为,揭示了基于远程线程注入机制实现 DLL 加载的技术原理。本文详细记录如何使用 C++ 控制台程序结合 Win32 API(如 CreateRemoteThread),在目标 C# 进程空间内申请内存并执行 LoadLibraryW,从而成功加载指定 DLL 的完整操作流程。

背景与原理

在调试器工作原理中,当使用 WinDbg 等工具附加到 C# 应用程序时,调试器会向目标进程注入一个线程。该线程执行后会触发 int 3 指令,即调用 DbgBreakPoint()。CPU 响应此中断信号后,会将当前进程的所有线程挂起,从而实现调试控制。理解这一机制是掌握远程注入技术的基础。

既然系统级调试工具可以实现跨进程线程注入,理论上任何具有适当权限的程序均可尝试类似操作,进而实现对目标进程的扩展或修改。

案例演示

第1步:准备目标测试程序

首先构建一个简单的 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 附加其进程。此时命令窗口会自动切换至由调试器注入的 8 号线程,执行 k 命令可查看堆栈顶部存在 int 3 中断帧。这验证了远程线程注入的成功。

第2步:开发待注入的动态链接库 (DLL)

新建一个 C++ 动态链接库项目。在 DllMain 入口函数的 DLL_PROCESS_ATTACH 事件处理分支中添加日志输出逻辑,用于验证注入是否生效。

#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,并将其放置在已知路径下以便后续引用。

第3步:编写远程注入主机程序

创建一个新的 C++ 控制台应用程序(例如 ConsoleApplication1.exe),负责寻找目标进程并完成注入工作。整体流程分为以下环节:

  • 遍历系统进程表,获取目标 C# 程序(如 ConsoleApp4.exe)的进程 ID (PID)。
  • 通过 PID 获取带有 PROCESS_ALL_ACCESS 权限的进程句柄。
  • 在目标进程地址空间中申请可读写内存区域。
  • 将 DLL 的绝对路径写入该内存区域。
  • 调用 LoadLibraryW 函数启动远程线程,使目标进程加载 DLL。
#include <iostream>
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <Tlhelp32.h>

// 根据进程名查找PID
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()
{
 // 替换为实际编译后的DLL路径
 const wchar_t* path = L"D:\\net6\\ConsoleApp1\\x64\\Debug\\MyInject.dll";
 
 // 1. 获取目标进程ID
 DWORD procID = GetPid(L"ConsoleApp4.exe");
 
 // 2. 获取进程句柄
 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
 
 // 3. 在目标进程中开辟一块空间用于存放DLL路径
 LPVOID pRemoteAdress = VirtualAllocEx(hProcess, NULL, wcslen(path) * 2, MEM_COMMIT, PAGE_READWRITE);
 
 // 4. 将DLL路径字符串拷贝到目标进程内存中
 BOOL bRet = WriteProcessMemory(hProcess, pRemoteAdress, path, wcslen(path) * 2, NULL);
 
 // 5. 获取kernel32.dll中的LoadLibraryW地址,并创建远程线程执行它
 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
 );
 
 // 等待线程结束以确保操作完成
 WaitForSingleObject(hThread, -1);
 
 // 清理已分配的远程内存
 VirtualFreeEx(hProcess, pRemoteAdress, 1, MEM_DECOMMIT);
 
 system("pause");
 return 0;
}

结果验证

依次启动目标 C# 程序、注入 DLL 的控制台程序。执行注入程序后,可在原本保持静默或仅有标准输出的 C# 进程终端中看到由 DLL 打印出的提示信息(如“我已经成功打入内部...”)。这表明 LoadLibraryW 已成功在当前上下文中执行并加载了外部代码模块。

总结与安全建议

上述过程还原了类似调试器行为的底层注入手段。虽然该技术常用于合法的自动化脚本注入或第三方服务集成,但也常被恶意软件利用进行无文件攻击或功能劫持。针对此类注入,常见的防御策略包括:

  • 启用操作系统级别的进程完整性控制或保护属性限制。
  • 通过应用层混淆关键 API 调用或使用 EDR 监控异常的 CreateRemoteThread 行为。
  • 校验加载模块的来源合法性。

以上就是在C#程序中注入恶意DLL的方法详解的详细内容,更多关于C#高级攻防技术的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。