15151841470 发表于 2023-4-25 13:32

HOOK某龙游戏

主要针对X86游戏的HOOK
ide环境准备:VS2022、MFC.dll文件创建X86、多字节版本

1.Hook初始化1.1 Hook类的封装
#pragma once
class Hook5
{
public:
      //-这个是构造函数, 用于初始化一个Hook5对象。它接受4个参数 :
      //-hook地址 : HOOK的位置, 也就是要替换的地址。
      //- hookTargetAdress : 跳转目标位置, 也就是HOOK跳转过去执行的地址。
      //- oldAdress : 要替换的原始5字节代码, 用于后续恢复HOOK。
      //- offset : m_hook返回地址相对于hook地址的偏移, 用于计算HOOK返回后执行的地址。
      Hook5(DWORD hook地址,DWORD hookTargetAdress,BYTE oldAdress, DWORD offset=5);

      //析构函数
      ~Hook5();      
public:
      BOOL Hook();
      BOOL UnHook();

public:
//由于使用了 #pragma pack(1) 指令,结构体中的成员变量 jmp 和 offset 将会紧密地排列在一起,
//不会产生字节对齐的空隙。这样构造的跳转指令在执行时可以直接跳转到指定的地址。
#pragma pack(1)
      typedef struct JmpCode5
      {
                BYTE jmp;
                DWORD offset;      
                JmpCode5() {
                        jmp = 0xE9;
                        offset = 0;
                }
      }JmpCode5;
#pragma pack()
public:
      static DWORD m_hook地址;
      static DWORD m_hook返回地址;
               JmpCode5 m_jmpCode5;//跳转指令
               BYTE m_oldCode;//原始代码
               BOOL m_init;//是否初始化
               BOOL m_hooked;      //是否HOOK

};

此类的作用是用于实现函数钩子(function hooking)的功能。函数钩子是一种常用的技术,用于拦截并修改程序中指定函数的行为,常用于软件调试、病毒分析、游戏修改等领域。

Hook5类实现了一个对5字节函数进行HOOK的功能,通过构造函数传入要替换的地址、跳转目标地址、原始5字节代码和返回地址相对于hook地址的偏移等参数,通过调用Hook函数实现对指定函数的拦截,并将原始函数的执行流程跳转到指定的目标函数地址,从而实现对函数行为的修改。同时,Hook5类也提供了UnHook函数用于恢复原始函数。

Hook5 类的方法包括:

构造函数 Hook5:用于初始化 Hook5 类对象,传入 hook 地址、跳转目标地址、原始 5 字节代码和偏移量;
析构函数 ~Hook5:用于释放 Hook5 对象;
Hook:实现函数 hook 的方法,将跳转指令写入 hook 地址处,并保存原有代码内存属性.同时修改内存属性为 PAGE_EXECUTE_READWRITE,最后恢复内存属性;
UnHook:取消函数 hook 的方法,将原有代码复制回 hook 地址处,同时恢复内存属性。

1.2 Hook类的实现
#include "pch.h"
#include "Hook5.h"

DWORD Hook5::m_hook地址 = 0;

DWORD Hook5::m_hook返回地址 = 0;

//构造函数
Hook5::Hook5(DWORD hook地址, DWORD hookTargetAdress, BYTE oldAdress, DWORD offset)
{
      Call_输出调试信息("hook地址:%x    hookTargetAdress:%x", hook地址, hookTargetAdress);

      m_hook地址 = hook地址;
      m_hook返回地址 = hook地址 + offset;
      m_jmpCode5.offset = hookTargetAdress - hook地址 - 0x5;
      memcpy_s(m_oldCode, 5, oldAdress, 5);
      m_init = TRUE;
      m_hooked = FALSE;
}
//
Hook5::~Hook5()
{
      if (m_hooked)
      {
                UnHook();
      }
}

BOOL Hook5::Hook()
{
      if (!m_init)
      {
                return FALSE;
      }
      if (m_hooked)return TRUE;
      __try
      {
                Call_输出调试信息("开始hook test");
                //1.修改内存页面属性
                //参数1:要修改的内存地址
                //参数2:要修改的内存大小
                //参数3:新的内存属性
                //参数4:保存原来的内存属性
                DWORD dwOldProtect;
                VirtualProtect((LPVOID)Hook5::m_hook地址, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);

                //2.将跳转指令写入到m_hook地址处
                memcpy_s((void*)Hook5::m_hook地址, 5, &m_jmpCode5, 5);

                //3.恢复内存页面属性
                VirtualProtect((LPVOID)Hook5::m_hook地址, 5, dwOldProtect, &dwOldProtect);
                m_hooked = TRUE;
                return TRUE;
      }
      __except(1)
      {
                Call_输出调试信息("拦截异常");
      }
      return 0;
}


BOOL Hook5::UnHook()
{
      if (!m_init)
      {
                return FALSE;
      }
      __try
      {
                Call_输出调试信息("开始UnHook test");
                //1.修改内存页面属性
                //参数1:要修改的内存地址
                //参数2:要修改的内存大小
                //参数3:新的内存属性
                //参数4:保存原来的内存属性
                DWORD dwOldProtect = 0;
                VirtualProtect((LPVOID)Hook5::m_hook返回地址, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);

                //2.将跳转指令写入到m_hook地址处
                memcpy_s((void*)Hook5::m_hook地址, 5, &m_oldCode, 5);

                //3.恢复内存页面属性
                VirtualProtect((LPVOID)Hook5::m_hook地址, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
                m_hooked = FALSE;
                return TRUE;
      }
      __except (1)
      {
                Call_输出调试信息("拦截异常");
      }
      return 0;
}
以上就是基本的Hook类封装,所有X86 5字节的Hook都可以调用这个封装,接下来我们以Hook某龙的lua为例,简单调用这层Hook类封装。

2.Hook某龙
2.1 MFC资源dialog创建

2.2窗口类创建(略过,详情请查阅 A星算法04剑网3)

2.3.窗口模态显示(略过,详情请查阅 A星算法04剑网3)

2.4 HOOK和Unhook点击事件函数创建

2.5 Hook地址的初始化
#define HookAdressOffset 0x29C243(此为hook目标地址的偏移)
BYTE oldAdress = { 0x51, 0xFF, 0x30, 0xFF, 0xD6 };//原始代码

Hook5 hook5((DWORD)GetModuleHandle(NULL) + HookAdressOffset, (DWORD)MyHookFunction, oldAdress, 0x5);

2.6 hook钩子函数业务的编写
__declspec(naked) void MyHookFunction()
{
      __asm
      {
                //保存寄存器
                pushad
                mov lua_click,ebx
                mov lua_env, ecx
                mov lua_dostring, esi
                mov lua_state, eax

                //恢复标志寄存器
                popad
      }

      //调用输出调试信息函数
      Call_输出调试信息("<%s--------%s>\n",(char*)lua_click, (char*)lua_env);
      __asm
      {
                //调用原函数,Call_输出调试信息可能会改变ecx,eax,esi的值,所以要重新赋值
                //0111C243 | 51 | push ecx |
                //0111C244 | FF30 | push dword ptr ds : |
                //0111C246 | FFD6 | call esi | call lua_dostring
                mov ecx, lua_env
                push ecx
                mov eax, lua_state
                push dword ptr ds :
                mov esi, lua_dostring
                call esi


                //跳转到原来的函数
                jmp Hook5::m_hook返回地址
      }
}

2.7 Hook点击事件调用Hook5类的Hook业务函数(记得引入Hook5.h)
void HmainDialogASM02::OnBnClickedButton1()
{
      if (!hook5.m_hooked) {// 只有未 Hook 时才执行
                if (hook5.Hook())
                {
                        Call_输出调试信息("successful hook");
                }
      }
      
}

//unhook按钮
void HmainDialogASM02::OnBnClickedButton2()
{
      if (hook5.m_hooked){// 只有已 Hook 时才执行
                if (hook5.UnHook())
                {
                        Call_输出调试信息("successful Unhook");
                }
      }
      

}

3.生成DLL注入游戏





我们发现成功拦截了游戏的LUA接口,获取到所有的LUA详细信息并打印输出。

实战环节略有缺失,本文主要是作为笔记的补充以及思路的提供,读者如果有不懂之处,可私信。

言归正传,本案例的核心功能是实现对Hook功能的封装,即Hook5类。开发者可根据业务需要,调用此HOOK封装,本案例主要是通过MFC DLL的形式注入,开发人员可以自行选择注入方法。当然也可以不用我这个方法,采用外部读取目标进程的形式也不是不可以。

ruanrongwei 发表于 2023-4-25 16:49

哇塞,我居然不知道这是什么游戏

fireandice 发表于 2023-4-25 18:07

这代码风格,盲猜是专业出身

hading 发表于 2023-4-25 20:48

可以,估计能实现很多功能了吧

xj1992628 发表于 2023-4-25 23:50

盲猜一手易语言出身

zhy1992 发表于 2023-4-26 08:50

很厉害 修改游戏

qq824356421 发表于 2023-4-26 09:31

这是什么游戏?楼主

15151841470 发表于 2023-4-26 11:56

qq824356421 发表于 2023-4-26 09:31
这是什么游戏?楼主

看图识别游戏{:1_926:}

jjghaa1234 发表于 2023-4-26 12:06

虽然不知道这是什么游戏,但是阻止不了我学习的步伐,大佬厉害,感谢分享

kantal 发表于 2023-4-26 19:52

这代码风格,盲猜是专业出身~~
页: [1] 2 3
查看完整版本: HOOK某龙游戏