内容参考于:易道云信息技术研究院VIP课
上一个内容:游戏底层功能对接类GameProc的实现
码云地址(master 分支):https://gitee.com/dye_your_fingers/titan
码云版本号:44c54d30370d3621c1e9ec3d7fa1e2a028e773e9
代码下载地址,在 titan 目录下,文件名为:titan-接管游戏连接服务器的操作.zip
链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg
提取码:q9n5
--来自百度网盘超级会员V4的分享
HOOK引擎,文件名为:黑兔sdk升级版.zip
链接:https://pan.baidu.com/s/1IB-Zs6hi3yU8LC2f-8hIEw
提取码:78h8
--来自百度网盘超级会员V4的分享
以 游戏底层功能对接类GameProc的实现 它的代码为基础进行修改
HOOK下图红框位置:0x10617046(通过之前分析找到的)
然后在注入的时候做HOOK发现,会崩溃,然后发现hook的点没有被游戏加载,解决办法我们在HOOK之前手动的把模块加载进入,不等游戏加载了
黑兔sdk升级:首先点击属性
找到下图红框位置,主要时看$(htd)\indude,如果下图红框位置不显示 $(htd)\indude
而显示不同选项,如下图红框
这时把配置这一行设置成跟下图一样,就好了
下载完升级版的黑兔std头文件可能无法正常加载到项目中,所以要手动加,首先检查它的目录对不对,如下图红框,我这里是对的,我的头文件就放在了那里
如果不对,首先点击下图红框位置
选择头文件所在目录,这样就把头文件设置好了
然后设置dll库,库目录是下图红框位置,手动设置方法与上方设置头文件一样
全部搞完之后,选择下图重新扫描解决方案,就不会报红了(就算报红也能编译通过)
这里补充一个东西:就是当执行了黑兔SDK,但是在创建项目的时候下图红框里的东西不存在
首先不打开项目启动 Visual Studio 然后选择选项:
然后看下图红框里的目录
查看目录中是否有下图红框里的两个文件,如果没有就复制到上图红框目录下
如下图
GameProc.cpp文件的修改:新加 _OnConnect函数,修改了 InitInterface函数、LoadBase函数
- #include "pch.h"
- #include "GameProc.h"
- #include "extern_all.h"
-
- // typedef bool(GameWinSock::* U)(char*, unsigned);
-
-
-
- bool _OnConnect(HOOKREFS2) {
- /*
- 根据虚函数表做HOOK的操作
- 截取 ecx 获取 winsock 的值(指针)
- */
- unsigned* vtable = (unsigned*)_EDX;
- //WinSock = (GameWinSock *)_ECX;
- /*
- 联合体的特点是共用一个内存
- 由于 GameWinSock::OnConnect 的 OnConnect函数是 GameWinSock类的成员函数
- 直接 vtable[0x34 / 4] = (unsigned)&GameWinSock::OnConnect; 这样写语法不通过
- 所以使用联合体,让语法通过
- */
- union {
- unsigned value;
- bool(GameWinSock::* _proc)(char*, unsigned);
- } vproc;
-
- /*
- vproc._proc = &GameWinSock::OnConnect; 这一句是把我们自己写的调用connect函数的地址的出来
- */
- vproc._proc = &GameWinSock::OnConnect;
- /*
- InitClassProc函数里做的是给指针赋值的操作
- InitClassProc(&GameWinSock::_OnConnect, vtable[0x34/4]);这一句的意思是把
- GameWinSock类里的_OnConnect变量的值赋值成vtable[0x34/4],这个 vtable[0x34/4] 是虚表里的函数
- vtable[0x34/4]是游戏中调用connect函数的函数地址,经过之前的分析调用connect是先调用了虚表中的
- 一个函数,然后从这个函数中调用了connect函数
- */
- InitClassProc(&GameWinSock::_OnConnect, vtable[0x34/4]);
- CString str;
- str.Format(L"===vtable:%X", vtable[0x34 / 4]);
- AfxMessageBox(str);
- DWORD oldPro,backProc;
- VirtualProtect(vtable, 0x100, PAGE_EXECUTE_READWRITE, &oldPro);
- vtable[0x34 / 4] = vproc.value;
- VirtualProtect(vtable, 0x100, oldPro, &backProc);
- return true;
- }
-
- GameProc::GameProc()
- {
- hooker = new htd::hook::htdHook2();
- Init();
- InitInterface();
- }
-
- void GameProc::LoadBase()
- {
- LoadLibraryA("fxnet2.dll");
- }
-
- void GameProc::Init()
- {
- }
-
-
-
- void GameProc::InitInterface()
- {
- LoadBase();
- MessageBoxA(0, "1", "1", MB_OK);
- hooker->SetHook((LPVOID)0x10617046, 0x1, _OnConnect, 0, true);
- }
新加GameWinSock.h文件:
- #pragma once
- class GameWinSock
- {
- typedef bool(GameWinSock::* PROC)(char*, unsigned);
- public:
- static PROC _OnConnect;
- bool OnConnect(char* ip, unsigned port);
- };
-
新加GameWinSock.cpp文件:
- #include "pch.h"
- #include "GameWinSock.h"
- #include "extern_all.h"
-
- GameWinSock::PROC GameWinSock::_OnConnect{};
- // 这个函数拦截了游戏的连接
- bool GameWinSock::OnConnect(char* ip, unsigned port)
- {
- // this是ecx,HOOK的点已经有ecx了
- WinSock = this;
- MessageBoxA(0, ip, ip, MB_OK);
- bool b = (this->*_OnConnect)(ip, port);
- // 下方注释的代码时为了防止多次注入,导致虚函数地址不恢复问题导致死循环,通过一次性HOOK也能解决
- /*unsigned* vtable = (unsigned*)this;
- vtable = (unsigned*)vtable[0];
- union {
- unsigned value;
- bool(GameWinSock::* _proc)(char*, unsigned);
- } vproc;
- vproc._proc = _OnConnect;
- DWORD oldPro, backProc;
- VirtualProtect(vtable, 0x100, PAGE_EXECUTE_READWRITE, &oldPro);
- vtable[0x34 / 4] = vproc.value;
- VirtualProtect(vtable, 0x100, oldPro, &backProc);*/
-
- return b;
- }
htdMfcDll.cpp文件的修改:修改了 InitInstance函数
- // htdMfcDll.cpp: 定义 DLL 的初始化例程。这是一个MFC的dll
- //
-
- #include "pch.h"
- #include "framework.h"
- #include "htdMfcDll.h"
- #include "extern_all.h"
-
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
-
- // 注释掉下方宏,以入口点注入的方式注入
- // #define WNDHOOK
- #ifdef WNDHOOK
- typedef struct htdDll
- {
- HHOOK keyHook;
- unsigned KbdProc;
- unsigned SetDll;
-
- }*PHtdDll;
- void htdSetDll(htdDll hDll);
- htdDll mDll;
- #endif
-
- BEGIN_MESSAGE_MAP(ChtdMfcDllApp, CWinApp)
- END_MESSAGE_MAP()
-
-
- // ChtdMfcDllApp 构造
-
- ChtdMfcDllApp::ChtdMfcDllApp()
- {
-
- }
-
- ChtdMfcDllApp theApp;
- ChtdMfcDllApp* PtheApp;
-
- HHOOK keyHook;
- LRESULT CALLBACK KeyCallBack(int nCode, WPARAM w, LPARAM l);
-
- BOOL ChtdMfcDllApp::InitInstance()
- {
- CWinApp::InitInstance();
- PtheApp = this;
- #ifdef WNDHOOK
- mDll.KbdProc = (DWORD)(KeyCallBack);
- mDll.SetDll = 0;
- #else
- keyHook = SetWindowsHook(WH_KEYBOARD, KeyCallBack);// 代码一开始,在这注册一个键盘事件的钩子
- #endif
- PGameProc = new GameProc();
- return TRUE;
- }
-
- // 钩子处理事件
- LRESULT CALLBACK KeyCallBack(int nCode, WPARAM w, LPARAM l)
- {
-
- if (nCode == 0)
- {
- if ((l & (1 << 31)) == 0)
- {
- switch (w)
- {
- case VK_HOME:
-
- if (PtheApp->wndMain == NULL)
- {
-
- PtheApp->wndMain = new CUI();
- PtheApp->wndMain->Create(IDD_MAIN);
-
- }
-
- PtheApp->wndMain->ShowWindow(TRUE);
- break;
- }
- }
- }
- return CallNextHookEx(keyHook, nCode, w, l);
- }
- #ifdef WNDHOOK
- void htdInit(htdDll* hDll)
- {
- hDll->KbdProc = mDll.KbdProc;
- hDll->keyHook = mDll.keyHook;
- hDll->SetDll = mDll.SetDll;
- }
-
- void htdSetDll(htdDll hDll)
- {
- mDll = hDll;
- }
- #else
- void htdInit()
- {
- }
- #endif
新加extern_all.h文件:
- /*
- 此文件是用来存放全局变量、全局函数(通用函数)
- */
- #pragma once
- #include "GameWinSock.h"
- #include "GameProc.h"
-
- extern GameWinSock* WinSock;
- extern GameProc* PGameProc;
- extern void InitClassProc(LPVOID proc_addr, unsigned value);
新加extern_all.cpp文件
- /*
- 此文件是用来存放全局变量、全局函数(通用函数)
- */
- #include "pch.h"
- #include "extern_all.h"
- GameWinSock* WinSock = nullptr;
- GameProc* PGameProc = nullptr;
-
- void InitClassProc(LPVOID proc_addr, unsigned value)
- {
- unsigned* writer = (unsigned*)proc_addr;
- writer[0] = value;
- }