学习使用的工具:逆向工具集
热血江湖外挂
- 1.0:最新版人物信息基址:0x02C166D8;最新版背包存放基址:0x02E3B3E4
- 2.0:最新版物品使用call 为0x00838480
- 3.0:
- 人物基址:0x02C176D8;
- 背包存放基址:0x02E3C3E4;
- 游戏主窗口基址:0x01195F88;
- 使用物品的学习向工CALL:0x008384F0;
- 人物动作基址:0x02E3CD58;
- 动作使用的CALL:0x007139E0;
- 所有对象数组:0x2E64A28;
- 怪物基址:0x427FBA0
- 角色对象基址:0x427FBA0
- 一般游戏开发的时候,相关的使用数据都是放到一个结构或者是一个类中,那么这些数据的具逆具集内存地址相距的比较近;
- 一般内存地址使用CE工具逆向出来后表示为Client.exe+278A75C,表示软件地址加上偏移量为其基址
- 生命值PH: Client.exe+278A75C = 02B8A758
- 内功值MH: Client.exe+278A75C = 02B8A75C
- 进行商品的学习向工买卖实现金币值的变动
- 基址:Client.exe+278A7BC = 02B8A7BC
- OD软件的使用
- 使用dd 02B8A758 查找到人物属性基址块
- 人物属性值以及对应的内存地址
- 基址 02B8A6D8
- +0:人物名字
- +80:生命值(红/HP)
- +84:内功值(蓝/MP)
- +88:愤怒值
- +8C:最大生命值
- +90:最大内功值
- +94:最大值愤怒值
- +98:当前经验值
- +A0:升级到下一级要的经验值
- 势力
- +36:名声
- +34:一字节空间表示等级
- +35:一字节空间表示 几转
- +AC:历练
- 制造
- 熟练度
- 灵兽持有
- 精力
- +C8:攻击
- 武器命中
- +CC:防御
- 武器防御
- +D0:命中
- 对人战斗
- +D4:回避
- 对怪攻击
- 武功回避
- 对怪防御
- +B0:心
- +B4:气
- +B8:体
- +BC:魂
- +E4:金币值
- 气功值分析
- 气功点数:基址 + F0 = 02b8a7c8
- 第num个气功的点数:(一个字节)02B8A6D8+0f0+4*num
- 可能是第num个气功的ID(没有就为0):02B8A6D8+0f0+4*num+2
-
注入DLL
-
创建MFC DLL
-
-
在添加窗口后,需要进行配置,使用才能在动态链接库注入后显示窗口
-
为窗口添加Class
-
修改MFC_DLL.cpp的具逆具集代码
-
使用注入工具讲编译生成的DLL 注入到游戏进程中
-
注:DoModal() 函数是以阻塞的方式去执行的,所以会造成线程阻塞
-
解决方式:将DoModal() 放到新的学习向工线程去执行
-
实现窗口关闭后自动释放DLL
-
使用代码实现动态连接库的注入
- 使用到的windows API
- HWND FindWindow(lpClassName, lpWindowNAme)
- 通过类名指针或窗口名指针获取窗口句柄
- DWORD GetWindowThreadProcessId(hwnd(窗口句柄), lpdwProcessId)
- 获取窗口线程句柄的ID(lpdwProcessId)
- HANDLE WINAPI OpenProcess(dwDesiredAccess(访问权限), bInheritHandle, dwProcessId)
- 开启并创建一个本地进程
- LPVOID WINAPI VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect)
- 分配内存空间
- BOOL WINAPI WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten)
- 向内存中写入数据
- HANDLE WINAPI CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId)
- 为进程创建一个线程
- DWORD WINAPI WaitForSingleObject(hHandle, dwMilliseconds)
- 等待单个对象执行后再进行操作
- BOOL WINAPI CloseHandle(hObject)
- 关闭句柄
- BOOL WINAPI VirtualFreeEx(hProcess, lpAddress, dwSize, dwFreeType)
- 释放内存空间
- BOOL WINAPI CloseHandle(hObject)
- 关闭句柄
- HWND FindWindow(lpClassName, lpWindowNAme)
-
- 步骤
- 获取窗口对应的进程的PID
- 根据PID 获取进程
- 获取游戏进程的PID
- 根据PID 获取进程
- 在目标进程分配内存空间,方便写入DLL 全路径
- 将DLL 全路径写入到目标进程
- 远程注入DLL
- 等待目标进程执行完成
- 释放进程空间
- 关闭线程句柄
- 整数
- QWORD 类型变量 nq前缀 //8字节 无符号整数 不能表示负数
- DWORD 类型变量 nd前缀 //4字节 无符号整数 不能表示负数
- WORD 类型变量 nw前缀 //2字节 无符号整数 不能表示负数
- BYTE 类型变量 nb前缀 //1字节 无符号整数 不能表示负数
- int 带符号类型 ni前缀 //4字节 带符号整数 可表示正负数
- _int64 带符号整型 ni64//8字节 带符号整数 不能表示负数
- UINT 类型变量 ui前缀 // 无符号整数 一般是使用4字节
- //浮点数
- float 单精度浮点数 fl前缀
- double 双精度浮点数 fd前缀
- 字符串
- char*和char [] sz前缀 //PCHAR szp
- CString str前缀
- 结构名 T开头全大写
- 类名 C开头单词首字大写
整合游戏数据步骤
-
新建解决方案GameData
-
创建头文件BaseGame.h和 StructGame.h
- BaseGame.h
- StructGame.h
-
创建源文件StructGame.cpp
- StructGame.cpp
-
配置链接库路径
-
配置 附加包含目录
-
配置 添加库目录
-
-
配置编译输出路径
-
修改输出目录
-
- 在游戏中,对应的具逆具集物品都会有一个结构/类,包含了物品的学习向工一些信息
- 使用物品实际上调用了应该CALL
以金疮药为例
-
寻CALL 的过程
-
使用CE工具找到对象地址指针
-
去查看访问改指针的地址
-
使用OD 工具对这些地址进行动态调试
-
远程注入代码(使用金疮药)
-
背包数据的分析
- 背包在游戏中一般会写成应该结构体/类来存放物品对象
- 物品对象在背包中使用数组的形式存在
- 汇编中数组的访问方式一般是 数组基址 + 4 * i(' i '为数组下标)
- 查找背包数组基址:
- 找到背包的物品格
- 反复讲里面的物品拿出/放入
- 使用CE工具进程分析
-
结果
- 存放背包基址的内存空间:0x02DAF3E4
- 第num 个格子的数据获取
- *背包基址+num*4+0x43C
- 注:0x43 是偏移量
- 物品对象指针 + 0x64 = 物品名字
- 物品对象指针 + 0xf9 = 对物品的描述
- 物品对象指针 + 0xC4C = 物品剩余数量
封装背包结构体
实现初始化方法(getDate())
调试调用
文件结构
封装函数
- 定义基址
- 定义结构
- 实现方法
- 调用方法,实现物品的使用使用
-
文件结构
造成异常的原因:
- 游戏主线程与外挂线程同时访问共享数据区域,造成程序异常
- 让两个线程依次使用共享数据或者将注入线程到主线程
模拟游戏主线程和辅助线程同时执行
- 代码
- 异常
解决方式
-
将程序注入到主线程
-
使用临界区
-
1
-
2、具逆具集代码
-
-
关键词
-
分析思路:从怪物明显的学习向工属性入手:名字、血量等
1*4+427EBA0 //怪物列表基址(1-5)
+8 种类/2E:怪物
+354 显示血条
+C 怪物选中参数
+5f4 怪物血量
+5f8 怪物等级
+360 怪物名字
+1060 怪物位置X
+1068 怪物位置Y
+3C0 怪物生命状态 0活/1死
[0427EBA0] //角色对象指针
+8 //角色分类31人物/2E
+18 //角色名字
-
定义基址
-
定义结构
-
实现结构方法
-
在HOOK 内定义测试方法
-
实现
-
控件调用
-
目录结构
- 思路:
- 通过选中的对象逆向回溯出动作的数组
- 通过动作对象访问逆向回溯到攻击CALL 附近
- 封包断点bp WSASend
-
通过选中动作,利用CE 查找基址
-
使用OD 分析访问内存信息,具逆具集得到基址
动作公式:[02e3bd58]+43c+4*0
-
找动作的CALL
-
使用CE 分析动作对象的调用访问
-
得到一下信息
-
使用OD分析得动作CALL为
-
- 封装动作对象
- 封装动作对象列表
- 封装使用对象功能函数
封装
-
封装基址
-
封装结构
-
实现结构方法
-
添加消息类型
-
在主线程内调用结构体方法
-
发送消息到主线程
-
绑定控件,执行方法
-
文件结构
- 实现怪物选中
- 可能情况:
- 选怪变量被赋值
- 怪物是否被选中的属性
选怪功能相关地址
-
玩家:
[2E63A24] //存放的玩家对象的地址
+3428 玩家是否被选中
-
怪物:
[2E63A24]+1A64
选中怪物时,传入怪物的选中ID
没选中怪物时,值为0xFFFF
(责任编辑:探索)
- 王者荣耀船长介绍
- 有格局的人生哲理句子(大格局有涵养的名句)
- 孔子的名言警句摘抄大全(孔子的名言警句摘抄大全短句)
- 若尔盖草原最佳旅游季节(若尔盖草原旅游3日攻略)
- 《迷失之夜》橙色随从选谁好 橙色随从选择推荐
- 好玩的rpg游戏(steam好玩的rpg游戏)
- wow字体(wow字体大小)
- 对待生活正能量的句子(对待生活正能量的句子简短)
- PUBG武器介绍 2022全武器介绍一览
- 曾国藩家训最经典四句(曾国藩家训最经典四句解释)
- 名人名言大全经典励志100字(名人名言大全经典励志100句)
- 超人总动员(超人总动员2在线观看完整版免费)
- 《征途2手游》“横扫千军”区合国公告
- 励志诗歌大全100首短的(古诗歌大全100首 励志)