C/C++实现DLL注入(入门),完整过程

这篇教程介绍了C/C++中如何实现DLL注入的入门步骤,包括创建DLL项目、使用Detours库、编写DLL代码、创建靶子程序以及编写DLL注入程序。教程详细解释了Detours的功能,并提供了详细的代码示例,帮助初学者理解DLL注入的核心思路和步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是DLL注入

所谓DLL注入,就是将一个DLL(动态链接库)放入要被注入的进程的内存空间里,让它成为进程的一部分。

关于本教程

本教程是一个入门教程,实践的内容是用DLL注入一个自己写的简单的WinForms窗体程序,在DLL中使用了Detours库,用于修改被注入程序窗口提示函数的内存地址。
本教程使用的IDE为Visual Studio

关于Detours:

Detours是一个由微软开发的可以用于捕获系统API、拦截函数的函数库

需要创建的项目:

  1. 一个DLL项目
  2. 一个用于注入DLL的(中转)程序
  3. 一个用于被注入的靶子程序

开始!GET STARTED

第一步:创建一个DLL项目

在VS中创建一个DLL项目,新建源文件myhook.cpp

第二步:下载并准备好Detours

下载地址: https://github.com/microsoft/detours
解压后,打开x86/x64(根据自己的CPU选择) Native Tools Command Prompt
在这里插入图片描述
cd到当前目录后,输入nmake:
在这里插入图片描述
附完成后效果图:
在这里插入图片描述
目录结构如下:
在这里插入图片描述
将include目录下的detours.h与lib.X64目录下的detours.lib复制到项目根目录
右键项目,选择添加-现有项,选中以上两个文件。
在这里插入图片描述

第三步:写DLL代码

在myhook.cpp中写入如下代码:

#include "pch.h"
#include "detours.h"

// 该变量用于引用MessageBox函数
static int (WINAPI* RealMessageBox)(HWND, LPCTSTR, LPCTSTR, UINT) = MessageBox;

// 该函数是要替换的假MessageBox函数
static int WINAPI MyMessageBox(HWND, LPCTSTR, LPCTSTR, UINT) {
	return RealMessageBox(NULL, L"My Hook successfully cracked!", L"Hey", MB_OK);
}

void StartHook() {
	DetourRestoreAfterWith();
	// 开始Detour事务
	DetourTransactionBegin();
	// 更新线程信息(执行事务的线程)
	DetourUpdateThread(GetCurrentThread());
	// 将拦截的函数附加到原函数的地址上
	DetourAttach((PVOID*)&RealMessageBox, MyMessageBox);
	// 提交事务
	DetourTransactionCommit();
}

(提示C++新手:WINAPI是宏)
再打开dllmain.cpp,编辑代码如下(新增处已表明注释):

#include "pch.h"
#include "framework.h"

VOID __declspec(dllexport) exportFunction() { // 添加导出函数(内容随便写)
    OutputDebugString(L"导出函数执行!");
}

extern void StartHook(); // 添加myhook.cpp中的函数的声明

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH: 
        StartHook(); // 添加启动钩子
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

完工,Ctrl+B生成。

第四步:创建用于被注入的(靶子)程序 [快速完成]

这里我们创建了一个简单的WinForms(C#)项目
在这里插入图片描述
双击打开Form1.cs设计,拖入一个按钮控件(如果找不到工具箱,请在上方选择视图-工具箱):
在这里插入图片描述
双击按钮,进入button1_Click()函数,写入:

private void button1_Click(object sender, EventArgs e)
{
	MessageBox.Show("正常的窗口文字");
}

效果:
在这里插入图片描述
好了,上方选择Release,Ctrl+B,环节完毕。

第五步:开始写DLL注入程序(中转站)[远程线程注入]

创建一个普通的C++控制台项目
先上代码:

#include <iostream>
#include <Windows.h>
using namespace std;

int main()
{
    HANDLE ProcessHandle;
    HANDLE ThreadHandle;
    LPVOID MemoryPointer;
    wchar_t dllPath[] = L"D:\\hzyfiles\\C-workspace(VS)\\DLL注入-完整过程\\Dll1\\x64\\Release\\Dll1.dll"; // 这里写自己的路径
    DWORD pid;

    cout << "输入程序PID:";
    cin >> pid;

    cout << "正在打开进程...";
    ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, false, pid); // 打开进程
    if (!ProcessHandle) {
        cout << "失败!" << endl;
        return 1;
    }
    cout << "成功!" << endl;

    cout << "正在开辟虚拟内存...";
    MemoryPointer = VirtualAllocEx(ProcessHandle, NULL, sizeof(dllPath), MEM_COMMIT, PAGE_READWRITE);
    if (!MemoryPointer) {
        cout << "失败!" << endl;
        return 1;
    }
    cout << "成功!" << endl;

    cout << "正在写入内存...";
    if (!WriteProcessMemory(ProcessHandle, MemoryPointer, (LPVOID)dllPath, sizeof(dllPath), NULL)) {
        cout << "失败!" << endl;
        return 1;
    }
    cout << "成功!" << endl;

    PTHREAD_START_ROUTINE LoadLibraryFunctionPointer = (PTHREAD_START_ROUTINE)GetProcAddress(
        GetModuleHandle(L"Kernel32"),
        "LoadLibraryW"
    );

    if (!LoadLibraryFunctionPointer) {
        cout << "Kernel32-LoadLibraryW函数未找到!" << endl;
        return 1;
    }

    cout << "正在创建远程线程...";
    ThreadHandle = CreateRemoteThread(ProcessHandle, NULL, 0, LoadLibraryFunctionPointer, MemoryPointer, 0, NULL);
    if (!ThreadHandle) {
        cout << "失败!" << endl;
        return 1;
    }
    cout << "成功!" << endl;
    CloseHandle(ProcessHandle);
    CloseHandle(ThreadHandle);

    return 0;
}
如果你是新手,我们可以一起分析一下这段代码的核心思路:

在靶子程序中执行LoadLibraryW函数,来达到将自己的DLL注入到靶子程序的效果。

核心步骤如下:
  1. 打开进程,获得进程句柄(OpenProcess)
  2. 在进程的虚拟内存中开辟一块空间(大小即为我们DLL路径所需要的内存空间)(目的:让靶子程序能够识别这块内存,从而将其带入为LoadLibraryW的参数)(VirtualAllocEx)
  3. 将DLL的路径写入这块内存(WriteProcessMemory)
  4. 远程在靶子进程内创建一个线程,在线程内执行LoadLibrary函数(CreateRemoteThread)

打开WinForms程序,记录其PID
附:CMD中的PID获取命令:tasklist | findstr [程序名],记录第二列的数字即可

程序执行后,我们再点击按钮,可以看到:
在这里插入图片描述
NICE

总结(仅重点)

  1. Detours库可以执行修改函数地址的操作
  2. DLL注入(远程线程注入)的核心只有四步,见上一节

如文章有不足之处,请大佬指点,3Q

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值