主线程调用过环境检查以及防止游戏崩溃

先给大家说两种情况,也许这些情况都是你遇见过的。

案例一,逆向软件,调试游戏找到了某个CALL,我们编写DLL,把这个call写入到DLL中,然后把DLL注入到软件内部,对这个CALL进行调用,发生游戏直接崩溃报错的情况。

又或则直接用代码注入器编写内联汇编直接注入代码导致崩溃。(有的时候代码注入器不会出问题,因为他是进程挂靠的方式 优于DLL中非主线程调用的方式)

图片

在这里插入图片描述

案例二,编写了具有单一功能或则是一系列功能的DLL,测试以后功能正确,代码无误,可是总是在长时间运行时出现莫名其妙的崩溃情况。

其实这两种情况都是因为非主线程调用函数导致的。

第一种情况,检测调用 环境,非主线程调用导致崩溃,当然前提是你的函数编写正确,不正确也会导致崩溃。

第二种情况,是长时间运行,导致数据访问冲突,而产生的崩溃,同样,如果用主线程队列去调用就可以完全避免了。

那么我们来看看主线程调用的代码实现方式。

有两个函数可以实现主线程调用

SetWindowLong 和SetWindowsHookEx

基本方式相差不大

图片
在这里插入图片描述

DWORD Call_Hook主线程()
{
	HWND hGame=Call_获取窗口句柄();
	DWORD ndThreadId=GetWindowThreadProcessId(hGame,NULL);
	if(ndThreadId!=0)
	{
		g_Hook返回=SetWindowsHookEx(WH_CALLWNDPROC,Call_主线程回调函数,NULL,ndThreadId);
	}
	return 1;
}

函数名以用中文替代
重新设置的回调函数如下
调用代码写在这个函数里即可,被回调函数调用的即相当于主线程调用的函数。

并且代码中也列举了几个函数CALL调用的例子

LRESULT CALLBACK Call_主线程回调函数(int nCode,WPARAM wParam,LPARAM lparam)
{
	CWPSTRUCT *lpArg=(CWPSTRUCT*)lparam;//结构  hwnd message wParam lParam
	if (nCode==HC_ACTION)//自己进程的消息
	{
		if (lpArg->hwnd==Call_获取窗口句柄()&&lpArg->message==g_My消息ID)//我们自己的消息  
		{
			switch (lpArg->wParam)
			{
				T封包参数*封包;
				
				T寻路参数*寻路;
				
				T坐标夹参数*坐标夹参数;
				
				T坐标夹 坐标夹;
				
				T走路参数*走路;
				
				case ID_发送明文包:
				
				Call_输出调试信息("YYC3D   主线程调用明文发包\r\n");
				
				封包=(T封包参数*)lpArg->lParam;
				
				Call_明文发包(封包->nd包长,封包->p);
				
				return 1;
				
				break;
				
				case ID_寻路:
				
				Call_输出调试信息("YYC3D   主线程调用寻路\r\n");
				
				寻路=(T寻路参数*)lpArg->lParam;
				
				Call_寻路(寻路->nfX,寻路->nfY);
				
				return 1;
				
				break;
				
				case ID_按键:
				
				Call_输出调试信息("YYC3D   主线程调用按键Call\r\n");
				
				Call_按键((DWORD)lpArg->lParam);
				
				return 1;
				
				break;
				
				case ID_控件点击:
				
				Call_输出调试信息("YYC3D   主线程调用控件点击Call\r\n");
				
				Call_控件点击((DWORD)lpArg->lParam);
				
				return 1;
				
				break;
				
				case ID_控件选择:
				
				Call_输出调试信息("YYC3D   主线程调用控件选择Call\r\n");
				
				Call_控件选择((DWORD)lpArg->lParam);
				
				return 1;
				
				break;
				
				case ID_计算坐标夹:
				
				Call_输出调试信息("YYC3D   主线程调用计算坐标夹\r\n");
				
				坐标夹参数=(T坐标夹参数*)lpArg->lParam;
				
				坐标夹=Call_计算坐标夹(坐标夹参数->nfX,坐标夹参数->nfY);
				
				return 1;
				
				break;
				
				case ID_走路:
				
				Call_输出调试信息("YYC3D   主线程调用走路Call\r\n");
				
				走路=(T走路参数*)lpArg->lParam;
				
				Call_走路(走路->nfX,走路->nfY);
				
				return 1;
				
				break;
			}
		}
	}
	return CallNextHookEx(g_Hook返回,nCode,wParam,lparam);
}

然后需要调用什么函数的时候

直接发送消息即可

这样代码执行再久也不会发生数据访问冲突而导致崩溃了。

例如

void Msg_走路(FLOAT X,FLOAT Y)
{
	T走路参数 走路;
	走路.nfX=X;
	走路.nfY=Y;
	::SendMessageA(Call_获取窗口句柄(),g_My消息ID,ID_走路,(LPARAM)&走路);
}
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值