注入MFCdll
大约 4 分钟cpp
概述
向目标进程注入 MFC DLL 是游戏外挂的一贯做法,图形界面方便用户使用
注入器
制作控制台应用程序用于注入之后制作的 MFC DLL 客户端,下面是控制台应用程序的完整代码。逻辑是先在目标进程中申请指定大小的内存空间,然后向其中写入 dll 文件的路径,最终通过 CreateRemoteThread 调用申请的内存空间 - 使用 LoadLibraryA 以加载库文件的方式 - 即运行注入的 dll
// A038Injector.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <Windows.h>
char windowClassName[] = "MainWindow";// pvz 窗口类
char windowTitle[] = R"(植物大战僵尸中文版)";// pvz 窗口标题
char dllPath[] = R"(D:\source\cpp\windowsapi\Debug\A038PVZMFCdll.dll)";// dll路径
int main()
{
std::cout << "PVZ Injector,向 PVZ 中注入MFC DLL\n";
// 使用窗口类、窗口标题获取窗口句柄
HWND hwnd = FindWindowA(windowClassName, windowTitle);// 获取窗口句柄
printf("窗口句柄:%p\r\n", hwnd);
// 根据窗口句柄获取进程PID
DWORD pid = 0;// 目标进程PID
GetWindowThreadProcessId(hwnd, &pid);// 通过窗口句柄获取窗口进程PID
printf("目标进程PID:%d\r\n", pid);
// 获取目标进程句柄
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);// 通过PID获取目标进程句柄
printf("进程句柄:%p\r\n", handle);
/**
* 向目标进程中申请内存空间,下面逐个介绍参数:
* 1. handle: 目标进程句柄
* 2. NULL:
* 3. 4 * 1024:申请的内存空间大小,32位系统会保证4K对齐,所以一次最少申请4K=4*1024
* 4. MEM_COMMIT:申请的内存的性质,这里表示物理内存或者页面内存
* 5. PAGE_EXECUTE_READWRITE:申请的内存空间可读写
*/
void *mem = VirtualAllocEx(handle, NULL, 10 * 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE /*PAGE_EXECUTE_READWRITE=0x40,表示这块内存区域可读写,可执行*/);
if (mem == NULL) {
printf("在目标进程申请内存失败,无法注入代码!!!");
return 0;
}
printf("已在目标进程申请内存空间:%p\r\n", mem);
/**
* 向申请的内存区域写入准备好的自定义代码 - 将上面的裸函数写入目标进程中自己申请的内存区域
* 向IDE中编译的控制台应用程序中注入代码后通过 `x32dbg.exe` 查看申请的内存区域的首地址
* 有可能看到 jmp 代码,则需要 vs2017 中修改 C++ 优化为禁用状态
* 查看图片:https://www.xdfznh.club/kbp/cpp/编译cpp程序禁用优化.png
* 第三个参数 dllPath 在案例 “远程线程注入代码” 中是裸函数,这里填写自定义的dll绝对路径
* 后面的 CreateRemoteThread 通过 LoadLibraryA 调用申请内存,即调用了自定义 dll
*/
bool retWriteProcessMemory = WriteProcessMemory(handle, mem, dllPath, 0x300, 0);
printf("向申请的内存空间注入MFC DLL收到的响应:%d\r\n", retWriteProcessMemory);
// 调用申请内存中注入的DLL
::CreateRemoteThread(handle, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, mem, 0, 0);
system("pause");
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
MFC DLL
创建MFC DLL项目

添加对话框资源
按照下面步骤为项目添加对话框资源,并新增关联类 CDialogMainCls
然后在项目同名的入库文件 A038PVZMFCdll01.cpp 中初始化并显示对话框
// CA038PVZMFCdll01App 初始化
#include "CDialogMainCls.h"
BOOL CA038PVZMFCdll01App::InitInstance()
{
CWinApp::InitInstance();
CDialogMainCls dialogCls;
dialogCls.DoModal();
return TRUE;
}
非阻塞显示对话框
采用创建子线程的方式显示对话框就不会阻塞 mfc dll 线程的继续执行
// 唯一的 CA038PVZMFCdll01App 对象
CA038PVZMFCdll01App theApp;
// CA038PVZMFCdll01App 初始化
#include "CDialogMainCls.h"
void showDialogDo() {
CDialogMainCls dialogCls;
dialogCls.DoModal();
}
DWORD WINAPI showDialog(LPVOID paramPoint) {
AFX_MANAGE_STATE(AfxGetStaticModuleState());
showDialogDo();
FreeLibraryAndExitThread(theApp.m_hInstance,777);// 退出对话框后结束
// FreeLibrary(theApp.m_hInstance);
return 1;
}
BOOL CA038PVZMFCdll01App::InitInstance()
{
CWinApp::InitInstance();
::CreateThread(0, 0, showDialog, 0, 0, 0);
return TRUE;
}
