上一篇文章介绍了DLL注入的方法,本次的实验内容是向游戏中注入我们自己的DLL,在游戏中有很多线程,每个线程的内存是不同的,所以读取内存的时候,一定要确定 读的是哪个线程的内存,注入的时候也需要注意,我们使用定时器的方法,将DLL注入到主线程
找到我们需要调用的函数地址
__asm
{
push avg1
call wow.60c1f0
add esp, 4
mov res, eax
}
准备DLL
//MFC_DLL.cpp
//显示我的窗口
DWORD WINAPI showmywindow(LPVOID arg)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CPAGE0 p0; //创建一个窗口
p0.DoModal(); //以模态方式显示窗口
return 0;
}
BOOL CMFCDLLApp::InitInstance()
{
CWinApp::InitInstance();
//新起一个线程 防止主线程卡死
::CreateRemoteThread(GetCurrentProcess(),0,0,showmywindow,0,0,0);
return TRUE;
}
//CPAGE0.cpp
//读取四字节的内存地址
int R4(UINT_PTR paddr)
{
HWND hwindow = FindWindowA("GxWindowClassD3d", "魔兽世界");
DWORD pid = 0, tid = 0;
tid = GetWindowThreadProcessId(hwindow,&pid);
HANDLE hp = OpenProcess(PROCESS_ALL_ACCESS,0,pid);
unsigned int res = 0;
ReadProcessMemory(hp,(LPCVOID)paddr,&res,4,0);
return res;
}
//定时器回调函数
VOID CALLBACK time_fun(HWND h, UINT arg2, UINT_PTR arg3_id, DWORD time)
{
KillTimer(h, 1111); // 关闭定时器 不然会每毫秒执行一次
//获取主线程ID
DWORD main_THid = GetCurrentThreadId();
printf("主线程id:%d \n", main_THid);
const char* avg1 = "player";
UINT_PTR hujia_base = 0;
UINT_PTR get_hujia = 0x60C1F0;
//调用游戏中的函数
__asm
{
push avg1
call get_hujia
add esp, 4
mov hujia_base, eax
}
//读取四个字节
DWORD hujia = R4(R4(hujia_base + 0xD0) + 0x174);
printf("护甲值为%d \n",hujia);
}
//获取护甲按钮
void CPAGE0::OnBnClickedButton1()
{
HWND hwindow = FindWindowA("GxWindowClassD3d","魔兽世界");
printf("窗口句柄:%p \n", hwindow);
//使用计时器 将DLL挂在主线程上
::SetTimer( hwindow //窗口句柄
,1111 //定时器ID 随便给一个就行
,1 //每隔1毫秒执行一次 time_fun
,time_fun ); //回调函数
}
//显示控制台按钮
void CPAGE0::OnBnClickedButton2()
{
AllocConsole();
//输出重定向到控制台 CONOUT$=控制台屏幕输出
FILE *pfile = NULL;
freopen_s(&pfile,"CONOUT$","w+t",stdout);
}
注入程序
int main()
{
char wind_title[] = "魔兽世界";
char DLL_PATH[] = "D:\\CODE\\YJX\\030\\mfc\\MFC_DLL\\Debug\\MFC_DLL.dll";
//根据窗口标题 找到窗口句柄
HWND h = FindWindowA(NULL, wind_title);
printf("窗口句柄为:%p \n",h);
//根据窗口句柄 找到进程PID
DWORD PID = 0;
GetWindowThreadProcessId(h,&PID); //结果写入PID 第二个参数为输出参数
printf("进程PID:%d \n",PID);
//获取目标进程的权限
HANDLE ph = OpenProcess(PROCESS_ALL_ACCESS,0,PID);
//在目标进程中分配内存空间
void* mem = VirtualAllocEx(ph,NULL,4*1024,MEM_COMMIT,0x40);
printf("分配内存:%d \n", mem);
//向目标进程注入DLL
bool ret = WriteProcessMemory(ph, mem, DLL_PATH,0x300,0);
printf("注入结果:%d \n", ret);
//调用注入的代码
CreateRemoteThread(ph,0,0,(LPTHREAD_START_ROUTINE)LoadLibraryA, mem,0,0);//LoadLibraryA 为 DLL 的地址,也是线程被创建之后 所要执行的内容
printf("调用完成 \n");
getchar();
return 0;
}
结果展示