57.第二阶段x64游戏实战-实时监控抓取lua内容
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
本次游戏没法给
内容参考于:微尘网络安全
上一个内容:56.第二阶段x64游戏实战-硬断HOOK实现下载预加载lua
效果图:
游戏中不管操作什么,比如释放技能或者按下了什么键等或打开任务怎么样各种功能它都有可能去调用lua,因为它外层大概率是使用lua写的,通过lua去调用实际的功能,所以希望可以及时抓到调用的lua,调用lua用的是lua_dostring,之前写过lua_dostring的第一个参数是状态指针,第二个参数是lua代码的内容,所以通过对lua_dostring做hook,可以达到实时监控,要注意当释放技能前或按下什么键之前进行hook,因为lua_dostring会有很多地方调用,一直hook会很乱,没办法找我们想要的,所以在做某件事之前进行hook才可以得到我们想要的lua代码,拦截到实时调用的lua后我们也就可以模仿游戏去调用了
hook下图红框位置,注意它是在luaplus.dll模块中
计算机一下偏移,luaplus.dll模块基址00007FFC0E1F0000
hook的位置地址00007FFC0E200370
偏移,0x10370,这个偏移应该不会变,除非更换luaplus的版本,一般都不会换
然后开始之前写一下需要的功能,首先是展示游戏中实时调用的lua,这就需要有两个个开关,打开监控和关闭监控,还要有一个清空按钮(监控的lua分析完不需要了或者监控到的lua不是想要的,就用它给清空了),然后光有监控也不行,还要有一个过滤,比如我们想找打开背包的lua,打开动作的lua肯定是在我们点击背包之后,但是lua_dostring有很多地方调用,打开监控后,肯定能监控到打开背包之前的lua,这个lua是不想要的,所以需要有一个过滤器,把这种不想要的lua过滤掉,有过滤器就要有添加过滤按钮和清空过滤按钮
首先添加一个输入框
输入框的属性
然后给它添加一个变量m_Edit
添加的变量
然后它添加的变量在 MyDialog 类中,然后我们需要在hook触发的异常处理函数中使用,异常处理函数不在 MyDialog 类中,就会导致异常处理函数找不到m_Edit变量,所以需要挪动以下位置
把它放到下图红框位置来,这样异常处理函数就能找到,m_Edit变量了
然后添加一个列表
然后给它添加变量,首先是如下图红框过滤输入框,m_listbox
变量名和类型
添加完后,如下图,它是在MyDialog类中,这里要把它拿出去
拿出去放到下图红框位置,这是因为我们要在异常处理中使用它,异常处理函数不在MyDialog类,会导致找不到 m_listbox 变量,所以放到下图红框位置
然后添加四个按钮,下方添加过滤按钮的功能是把监控到的内容放到过滤的内容中
然后给监控lua按钮添加一个变量
变量名m_Start
到这界面准备工作就差不多了,可以开始写代码了
MyDialog.cpp文件的修改,
首先是监控,要从 OnBnClickedButton13函数开始看,OnBnClickedButton13函数是监控lua按钮的点击后执行的函数,它里面做了硬件hook(上一个内容里也写过),然后它的异常处理函数叫 异常处理1 ,然后通过硬件断点就来到了 异常处理1 函数,在 异常处理1 函数中就是获取lua_dostring函数的参数,然后写到上方的输入框中,写的方式采用mfc的SendMessage函数(看代码里的注释,不是很难)
然后是清空:
void TextToEdit(HWND hEdit, TCHAR* pStr)
{CHARRANGE StCharrange;StCharrange.cpMax = StCharrange.cpMin = GetWindowTextLength(hEdit);//这行代码向hEdit发送EM_SETSEL消息,以设置编辑控件中的当前文本选择范围。StCharrange.cpMin是选择的起始位置,StCharrange.cpMax是选择的结束位置。//由于cpMin和cpMax都被设置为文本的长度,这将选择整个文本。SendMessage(hEdit, EM_SETSEL, StCharrange.cpMin, (LPARAM)StCharrange.cpMax);//这行代码向hEdit发送EM_REPLACESEL消息,用于替换当前选中的文本。FALSE参数表示不更新文本,(LPARAM)pStr是要替换当前选中文本的新文本//。由于上一行代码选中了整个文本,这将替换编辑控件中的所有文本为pStr指向的字符串。SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)pStr);//指示控件滚动到底部。SB_BOTTOM是滚动条位置,表示滚动到控件的底部。SendMessage(hEdit, WM_VSCROLL, SB_BOTTOM, 0);}LONG NTAPI 异常处理1(struct _EXCEPTION_POINTERS* exceptionInfo)
{if (exceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP)//硬断异常{if ((uintptr_t)exceptionInfo->ExceptionRecord->ExceptionAddress == (DWORD64)GetModuleHandleA("LuaPlus.dll") + 0x10370){/**这是ListBox控件的一个方法,用于查找字符串。第一个参数-1表示从列表的末尾开始搜索,第二个参数args是要查找的字符串。也就是从过滤里查找当前lua代码,如果找到了,说明当前lua代码是要被过滤的*/int index = m_listbox.FindString(-1, (char*)exceptionInfo->ContextRecord->Rdx);if (index == LB_ERR){// 从监听里查找,当前lua代码是否已存在,如果存在了就不要展示了vector<CStringA>::iterator result = find(sg_data.begin(), sg_data.end(), (CStringA)(char*)exceptionInfo->ContextRecord->Rdx); //查找3if (result == sg_data.end()) //没找到{// 把当前lua代码放到全局列表中sg_data.push_back((char*)exceptionInfo->ContextRecord->Rdx);// 给lua代码末尾添加换行,也就是添加\nCStringA tmp;tmp = (char*)exceptionInfo->ContextRecord->Rdx;tmp += "\n";TextToEdit(m_Edit.m_hWnd, tmp.GetBuffer());}}//还原处理,还原 or r8, 0xFFFFFFFFFFFFFFFF 这行代码exceptionInfo->ContextRecord->R8 = exceptionInfo->ContextRecord->R8 | 0xFFFFFFFFFFFFFFFF;exceptionInfo->ContextRecord->Rip += 4;return EXCEPTION_CONTINUE_EXECUTION;}}return EXCEPTION_CONTINUE_SEARCH;
}
void MyDialog::OnBnClickedButton13()// 监控lua
{CString Text;m_Start.GetWindowText(Text);if (GLua_Dostring == NULL){GLua_Dostring = (Glua_dostring)GetProcAddress(GetModuleHandleA("LuaPlus.dll"), "lua_dostring");}if (Text == _T("监控lua")){sg_data.clear();Sleep(1000);g_hbHook.m_dr0 = (QWORD)GetModuleHandleA("LuaPlus.dll") + 0x10370;//断点的地址 公共明文call->组包完成的时候-加密之前g_hbHook.m_dr7 = 0x55;//4个断点都可用g_hbHook.m_removeThread[0] = GetCurrentThreadId();//获取当前程序的线程idg_hbHook.setExceptionHandlingFunction(异常处理1);//接管异常g_hbHook.hook();//开始hookm_Start.SetWindowText(_T("关闭监控lua"));}else{g_hbHook.unHook();m_Start.SetWindowText(_T("监控lua"));}
}
上方是监控lua的代码,下方是清空监控的代码
void MyDialog::OnBnClickedButton14()
{CString Text;m_Start.GetWindowText(Text);if (Text == _T("监控lua"))// 监控lue必须是关闭状态{m_Edit.SetWindowText("");// 清空输入框sg_data.clear();// 清空全局监控lue列表}else{AfxMessageBox(_T("请先点击关闭监控lua"));// 如果是监控lue,提示关闭监控lua}
}
下方是添加过滤的代码
unsigned __stdcall Button2(LPVOID lpThread)
{LogA("sg_data.size()=%d", sg_data.size());// 获取全局监控lua得到的数据for (vector<CStringA>::size_type i = 0; i != sg_data.size(); ++i){// 从过滤lua列表中获取一个数据,如果获取到数据index的值非-1// 如果非-1说明获取到了数据,也就是说当前lua代码已经在过滤lua列表中了// 就不再给过滤lua列表中写数据了int index = m_listbox.FindString(-1, sg_data[i]);// 判断过滤lua列表中是否以存在if (index == LB_ERR)// 给过滤lua列表中添加一个lua代码m_listbox.AddString(sg_data[i]);}sg_data.clear();return 0;
}void MyDialog::OnBnClickedButton15()
{CString Text;m_Start.GetWindowText(Text);if (Text == _T("监控lua")){// 开启一个线程去执行添加过滤操作,也就是去调用 Button2函数::CloseHandle((HANDLE)_beginthreadex(NULL, 0, &Button2, this, 0, NULL));}else{AfxMessageBox(_T("请先点击关闭监控lua"));}
}
下方是清空过滤的方法
void MyDialog::OnBnClickedButton16()
{CString Text;m_Start.GetWindowText(Text);if (Text == _T("监控lua")){m_listbox.ResetContent();// 清空过滤列表}else{AfxMessageBox(_T("请先点击关闭监控lua"));}
}