• 9.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-接管游戏连接服务器的操作


    内容参考于:易道云信息技术研究院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(通过之前分析找到的)

    0c9bf77d18b245ccbecfa464854f34cc.png

    然后在注入的时候做HOOK发现,会崩溃,然后发现hook的点没有被游戏加载,解决办法我们在HOOK之前手动的把模块加载进入,不等游戏加载了

    f8a063028bc841aa881252ffd5f37e6f.png

    黑兔sdk升级:首先点击属性

    c8ae5c991bd74562b876ef4850f3f84c.png

    找到下图红框位置,主要时看$(htd)\indude,如果下图红框位置不显示 $(htd)\indude

    3b1f7683727247fca7cb42e28802a53b.png

    而显示不同选项,如下图红框

    7a4e8df1f19e4173ad95c303d51295c9.png

    这时把配置这一行设置成跟下图一样,就好了

    8aa3e7906c724fe099ad93bf29964510.png

    下载完升级版的黑兔std头文件可能无法正常加载到项目中,所以要手动加,首先检查它的目录对不对,如下图红框,我这里是对的,我的头文件就放在了那里

    140e9956815e4f6c9916caa0f603cf91.png

    如果不对,首先点击下图红框位置

    0dcfa8f6841c4454b4b12763477a3640.png

    选择头文件所在目录,这样就把头文件设置好了

    5d38be97bc27443a9835609a94aeb31b.png

    然后设置dll库,库目录是下图红框位置,手动设置方法与上方设置头文件一样

    c0fc81d646b947cd92157331f193ef74.png

    全部搞完之后,选择下图重新扫描解决方案,就不会报红了(就算报红也能编译通过)

    54e02e8edfad465bbb4e8a96584b1ad3.png

    这里补充一个东西:就是当执行了黑兔SDK,但是在创建项目的时候下图红框里的东西不存在

    a586f30d202b432ab1a872382f8118e9.png

    首先不打开项目启动 Visual Studio 然后选择选项:

    2e1a0100265b42dca36f9f7ae5f98f72.png

    然后看下图红框里的目录

    2bbb6b5e3a8f4d5299ece250ac6ffb96.png

    查看目录中是否有下图红框里的两个文件,如果没有就复制到上图红框目录下

    3389192a715041a29039f6037ece627b.png

    如下图

    c36c945fa75a46f7ae8b1d53a35ca713.png


    GameProc.cpp文件的修改:新加 _OnConnect函数,修改了 InitInterface函数、LoadBase函数

    1. #include "pch.h"
    2. #include "GameProc.h"
    3. #include "extern_all.h"
    4. // typedef bool(GameWinSock::* U)(char*, unsigned);
    5. bool _OnConnect(HOOKREFS2) {
    6. /*
    7. 根据虚函数表做HOOK的操作
    8. 截取 ecx 获取 winsock 的值(指针)
    9. */
    10. unsigned* vtable = (unsigned*)_EDX;
    11. //WinSock = (GameWinSock *)_ECX;
    12. /*
    13. 联合体的特点是共用一个内存
    14. 由于 GameWinSock::OnConnect 的 OnConnect函数是 GameWinSock类的成员函数
    15. 直接 vtable[0x34 / 4] = (unsigned)&GameWinSock::OnConnect; 这样写语法不通过
    16. 所以使用联合体,让语法通过
    17. */
    18. union {
    19. unsigned value;
    20. bool(GameWinSock::* _proc)(char*, unsigned);
    21. } vproc;
    22. /*
    23. vproc._proc = &GameWinSock::OnConnect; 这一句是把我们自己写的调用connect函数的地址的出来
    24. */
    25. vproc._proc = &GameWinSock::OnConnect;
    26. /*
    27. InitClassProc函数里做的是给指针赋值的操作
    28. InitClassProc(&GameWinSock::_OnConnect, vtable[0x34/4]);这一句的意思是把
    29. GameWinSock类里的_OnConnect变量的值赋值成vtable[0x34/4],这个 vtable[0x34/4] 是虚表里的函数
    30. vtable[0x34/4]是游戏中调用connect函数的函数地址,经过之前的分析调用connect是先调用了虚表中的
    31. 一个函数,然后从这个函数中调用了connect函数
    32. */
    33. InitClassProc(&GameWinSock::_OnConnect, vtable[0x34/4]);
    34. CString str;
    35. str.Format(L"===vtable:%X", vtable[0x34 / 4]);
    36. AfxMessageBox(str);
    37. DWORD oldPro,backProc;
    38. VirtualProtect(vtable, 0x100, PAGE_EXECUTE_READWRITE, &oldPro);
    39. vtable[0x34 / 4] = vproc.value;
    40. VirtualProtect(vtable, 0x100, oldPro, &backProc);
    41. return true;
    42. }
    43. GameProc::GameProc()
    44. {
    45. hooker = new htd::hook::htdHook2();
    46. Init();
    47. InitInterface();
    48. }
    49. void GameProc::LoadBase()
    50. {
    51. LoadLibraryA("fxnet2.dll");
    52. }
    53. void GameProc::Init()
    54. {
    55. }
    56. void GameProc::InitInterface()
    57. {
    58. LoadBase();
    59. MessageBoxA(0, "1", "1", MB_OK);
    60. hooker->SetHook((LPVOID)0x10617046, 0x1, _OnConnect, 0, true);
    61. }

    新加GameWinSock.h文件:

    1. #pragma once
    2. class GameWinSock
    3. {
    4. typedef bool(GameWinSock::* PROC)(char*, unsigned);
    5. public:
    6. static PROC _OnConnect;
    7. bool OnConnect(char* ip, unsigned port);
    8. };

    新加GameWinSock.cpp文件:

    1. #include "pch.h"
    2. #include "GameWinSock.h"
    3. #include "extern_all.h"
    4. GameWinSock::PROC GameWinSock::_OnConnect{};
    5. // 这个函数拦截了游戏的连接
    6. bool GameWinSock::OnConnect(char* ip, unsigned port)
    7. {
    8. // this是ecx,HOOK的点已经有ecx了
    9. WinSock = this;
    10. MessageBoxA(0, ip, ip, MB_OK);
    11. bool b = (this->*_OnConnect)(ip, port);
    12. // 下方注释的代码时为了防止多次注入,导致虚函数地址不恢复问题导致死循环,通过一次性HOOK也能解决
    13. /*unsigned* vtable = (unsigned*)this;
    14. vtable = (unsigned*)vtable[0];
    15. union {
    16. unsigned value;
    17. bool(GameWinSock::* _proc)(char*, unsigned);
    18. } vproc;
    19. vproc._proc = _OnConnect;
    20. DWORD oldPro, backProc;
    21. VirtualProtect(vtable, 0x100, PAGE_EXECUTE_READWRITE, &oldPro);
    22. vtable[0x34 / 4] = vproc.value;
    23. VirtualProtect(vtable, 0x100, oldPro, &backProc);*/
    24. return b;
    25. }

    htdMfcDll.cpp文件的修改:修改了 InitInstance函数

    1. // htdMfcDll.cpp: 定义 DLL 的初始化例程。这是一个MFC的dll
    2. //
    3. #include "pch.h"
    4. #include "framework.h"
    5. #include "htdMfcDll.h"
    6. #include "extern_all.h"
    7. #ifdef _DEBUG
    8. #define new DEBUG_NEW
    9. #endif
    10. // 注释掉下方宏,以入口点注入的方式注入
    11. // #define WNDHOOK
    12. #ifdef WNDHOOK
    13. typedef struct htdDll
    14. {
    15. HHOOK keyHook;
    16. unsigned KbdProc;
    17. unsigned SetDll;
    18. }*PHtdDll;
    19. void htdSetDll(htdDll hDll);
    20. htdDll mDll;
    21. #endif
    22. BEGIN_MESSAGE_MAP(ChtdMfcDllApp, CWinApp)
    23. END_MESSAGE_MAP()
    24. // ChtdMfcDllApp 构造
    25. ChtdMfcDllApp::ChtdMfcDllApp()
    26. {
    27. }
    28. ChtdMfcDllApp theApp;
    29. ChtdMfcDllApp* PtheApp;
    30. HHOOK keyHook;
    31. LRESULT CALLBACK KeyCallBack(int nCode, WPARAM w, LPARAM l);
    32. BOOL ChtdMfcDllApp::InitInstance()
    33. {
    34. CWinApp::InitInstance();
    35. PtheApp = this;
    36. #ifdef WNDHOOK
    37. mDll.KbdProc = (DWORD)(KeyCallBack);
    38. mDll.SetDll = 0;
    39. #else
    40. keyHook = SetWindowsHook(WH_KEYBOARD, KeyCallBack);// 代码一开始,在这注册一个键盘事件的钩子
    41. #endif
    42. PGameProc = new GameProc();
    43. return TRUE;
    44. }
    45. // 钩子处理事件
    46. LRESULT CALLBACK KeyCallBack(int nCode, WPARAM w, LPARAM l)
    47. {
    48. if (nCode == 0)
    49. {
    50. if ((l & (1 << 31)) == 0)
    51. {
    52. switch (w)
    53. {
    54. case VK_HOME:
    55. if (PtheApp->wndMain == NULL)
    56. {
    57. PtheApp->wndMain = new CUI();
    58. PtheApp->wndMain->Create(IDD_MAIN);
    59. }
    60. PtheApp->wndMain->ShowWindow(TRUE);
    61. break;
    62. }
    63. }
    64. }
    65. return CallNextHookEx(keyHook, nCode, w, l);
    66. }
    67. #ifdef WNDHOOK
    68. void htdInit(htdDll* hDll)
    69. {
    70. hDll->KbdProc = mDll.KbdProc;
    71. hDll->keyHook = mDll.keyHook;
    72. hDll->SetDll = mDll.SetDll;
    73. }
    74. void htdSetDll(htdDll hDll)
    75. {
    76. mDll = hDll;
    77. }
    78. #else
    79. void htdInit()
    80. {
    81. }
    82. #endif

    新加extern_all.h文件:

    1. /*
    2. 此文件是用来存放全局变量、全局函数(通用函数)
    3. */
    4. #pragma once
    5. #include "GameWinSock.h"
    6. #include "GameProc.h"
    7. extern GameWinSock* WinSock;
    8. extern GameProc* PGameProc;
    9. extern void InitClassProc(LPVOID proc_addr, unsigned value);

    新加extern_all.cpp文件

    1. /*
    2. 此文件是用来存放全局变量、全局函数(通用函数)
    3. */
    4. #include "pch.h"
    5. #include "extern_all.h"
    6. GameWinSock* WinSock = nullptr;
    7. GameProc* PGameProc = nullptr;
    8. void InitClassProc(LPVOID proc_addr, unsigned value)
    9. {
    10. unsigned* writer = (unsigned*)proc_addr;
    11. writer[0] = value;
    12. }

     

  • 相关阅读:
    redis,mongoDB,mysql,Elasticsearch区别
    深度学习服务器(Linux)开发环境搭建教程
    jQuery学习:核心函数和核心对象
    Arduino框架下通过TFT_eSPI库驱动ESP32+合宙1.54“ 电子墨水屏(e-paper)显示
    PPP协议和MAC地址、IP地址及ARP协议三者之间的关系(3.2)
    C++周周练【第一周】
    Hive谓词下推之FULL JOIN
    13年过去了,Spring官方竟然真的支持Bean的异步初始化了!
    【LeetCode】15、三数之和
    【数据结构】单链表
  • 原文地址:https://blog.csdn.net/qq_36301061/article/details/136306664