=======================================
注入dll后直接用*来读取地址,和游戏自己读取地址是没有区别的
但是我们是在另一个线程读取的
而主线程这个时候也在读取,那么就会访问冲突
所以需要主线程调用,把我们的代码让主程序去调用
当然如果用ReadProcessMemory之类的出错的概率就很小了
毕竟这是远程读取内存,当然也可以在dll里面使用
但是依然存在,运行若干个小时后就莫名GG
所以不管怎么样都需要主线程调用
可以利用SetWindowHook和SetWindowLong
#pragma once
#include "HookGameMainThread.h.h"
#include "BaseAdress.h"
#include "GameStruct.h"
ACtion_Struct action;
UINT myMsg = RegisterWindowMessageA("myMsg");//注册一个消息
HWND game_wnd_handle;
HHOOK hhook;
LRESULT CALLBACK GameWndProc(
_In_ int nCode, //消息代码
_In_ WPARAM wParam, //指定消息是否由当前线程发送,如果是,则它是非零的,不是则为0
_In_ LPARAM lParam //指向CWPSTRUCT结构的指针
)
{
CWPSTRUCT *wpstruct = (CWPSTRUCT*)lParam;
//typedef struct tagCWPSTRUCT {
// LPARAM lParam; //接收的消息
// WPARAM wParam;
// UINT message; // 注册的消息值,一般用于分类
// HWND hwnd; //窗口的句柄,用于接收消息
//}
//如果nCode==HC_ACTION,那么为主程序调用,也就是进程的消息
if (nCode == HC_ACTION)
{
//判断是不是我们的窗口,并且是我们指定的消息
if (wpstruct->hwnd == game_wnd_handle && wpstruct->message == myMsg)
{
switch (wpstruct->wParam) //wParam接受我们送过来的msg
{
case MSG_TEST:
//Monster_Struct monster;
//monster.getData();
//monster.print_monter();
action.getData();
//Debug_Print("\n已获取数值\n");
action.print_Info();
action.useAction((char*)wpstruct->lParam);
return 1;
break;
default:
break;
}
return 1;
}
}
//如果nCode<0,那么窗口过程必须交给其他人处理
return CallNextHookEx(hhook, nCode, wParam, lParam);
}
int HookMainThread()
{
game_wnd_handle = getGameWndHandle();
DWORD threadId = GetWindowThreadProcessId(game_wnd_handle, NULL);
if (threadId != 0)
{
hhook = SetWindowsHookExA(WH_CALLWNDPROC, GameWndProc, 0, threadId);
//1 钩子的类型,这里用WH_CALLWNDPROC 用于主程序调用
// 系统将消息发送到目标窗口过程之前监视消息
//2 回调函数的地址,指向钩子过程的指针
//3 DLL的句柄,包含指向的钩子过程lpfn参数,暂且填0
//4 线程ID,如果填写了这个,那么参数3便必须填0,暂且就这样记着
//成功返回钩子句柄,失败返回0
//您将安装一个钩子过程来监视系统中某些类型的事件
//https://msdn.microsoft.com/zh-cn/ms644990
return 0;
}
return -1;
}
int msgTest(LPARAM t)
{
SendMessageA(game_wnd_handle, myMsg, MSG_TEST, t);
return 1;
}
int UnHook()
{
UnhookWindowsHookEx(hhook);
return 1;
}