吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1976|回复: 1
收起左侧

[会员申请] 申请会员ID:moriv4

[复制链接]
吾爱游客  发表于 2024-3-13 01:22
申 请 ID :moriv4
个人邮箱:985811440@qq.com


熟悉技术: X86汇编、C/C++软件开发

原创技术文章:

单机游戏的逆向分析:气球塔防6   (Bloons TD 6)

前言
气球塔防系列游戏最早是在4399等Flash游戏网站上推出,从第一代到第四代人气越来越高,被称为塔防游戏三巨头之一(加上植物大战僵尸和王国保卫战)。
后来NinjaKiwi公司使用Unity引擎重构了这款游戏,推出了第五六代在多个平台上发售。游戏中玩家需要放置防御塔,击破气球,夺回猴子们的城镇。



本文将分析此游戏中的金币、经验、猴币等数值在汇编层面的表现方式和修改过程。使用的工具是x64dbg和CE,CE用于查找数值地址,x64dbg用于调试汇编代码。
提示:阅读本文需要了解X64汇编(包括SSE2浮点数指令集)和上述两个工具的使用方法。



文件目录
进入游戏安装文件夹,看到有 UnityPlayer.dll, GameAssembly.dll等动态链接库文件,进入Data目录有il2cpp_data文件夹。说明此游戏使用的是

Unity框架的 il2cpp 技术进行生成打包。游戏的业务逻辑在GameAssembly.dll中提前编译好了,如果不出意外,我们要调试的目标代码片段就在其中。
关于mono和il2cpp的差异对比,这篇帖子写得非常详细:通杀爆改 Unity FPS 游戏系列-第三章:il2cpp mono 差异  (感谢原作者 lyl610abc
本文将使用动态调试的方法分析,大家如果有兴趣可自行使用 dump工具还原符号静态分析。






数值搜索
选择地图进入到关卡内,初始金额850,放置几个防御塔改变金额并用CE搜索此数值。先尝试搜索4字节整数类型,没有找到。再试单精度浮点,又没有找到。
最后使用双精度浮点终于找到了目标数值。但不要高兴的太早!CE修改此处数值为9999后,再在游戏里放置一个新塔,这里的数值居然变回原来正确的了。
我们的修改没有产生任何作用!这也是经常会遇到的一个情况,此处是纯显示的结果量,表达式计算完成后写入此地址,程序并不会读取这个值参与实际运算。
所以我在文章开头说要了解SSE2浮点数指令集,如果不看汇编代码就没法改。





反汇编调试

运行xdbg64,附加到BloonTD6进程上,在内存页面转到之前用CE搜索得到的地址,右键菜单中选择浮点数->Double,可以看到显示数值为15。

在此内存地址处下硬件断点->写入->8字节。在游戏中把塔卖掉后,触发中断,代码地址为GameAssembly.dll+0x3B3F62,如下图所示:


分析如下:

函数申请30h个字节的栈空间用于局部变量,然后

(1)开始时把xmm6寄存器保存在栈上。

(2)最后从栈上恢复xmm6。xmm6相当于临时寄存器变量,借来用一下。

(3)把xmm1的值赋值给xmm6。xmm1相当于参数,从外部传入,值为计算后的金额。

(4)把xmm6写入内存[rbx+28h],此处地址是之前用CE找到的那个。

(5)调用函数,作用不明。

函数退出前平衡堆栈。可以看到目标写入地址的后一个数据是改变前的金额,即 [rbx+30h]


xmm1的金额数值是从哪里来的?

在函数调用堆栈页面转到上一个调用,如下图所示:


(1)xmm0为原金额,xmm6为售价,此处进行浮点数加法运算。新金额=原金额+售价。

(2)将xmm0的值传递给xmm1,作为参数调用接下来的函数。

(3)调用之前分析过的的函数


经过一些尝试发现,在addsd xmm0, xmm6指令之后,且在call 指令之前 下断点,此时用x64dbg修改xmm寄存器的低64位双精度浮点值,

修改后的值可在游戏中生效。开局即可放置5级防御塔。接着看看其他片段,使用二分法下断点,修改xmm寄存器的值,可找出影响内存值的

关键代码片段!




那么,xmm0的金额数值是从哪里来的?

多次下断点,单步步过调试发现:addsd xmm0, xmm6指令前面一条call指令,它产生了xmm0的值!

跟踪进去发现有两次跳转。



然后来到了一个超级复杂的函数,我用红框标出的代码区域能产生金额,但此处又被多个其他地方调用。初步判断有数值加密算法,

每次取金额时要用两个浮点数相减才得到,这里地址也是来回变动。计算完成后保存金额时要用两个浮点数相加,分别保存到对应内存地址。

存在一个对称结构,怀疑是用C#getter和setter方法修饰了一些属性。


分析到此处不准备继续深入了。购买塔、道具、获得经验、猴币,代码相似,平级关系,这里不再重复。

在调试时找到了一个全局常量,单精度浮点数,值为一千万,地址 ds:[0x7FFB8F8900A4] 。可以把它拿来做修改时的常数使用。


制作修改补丁

之前分析的 addsd xmm0, xmm6 代码处,如果把 xmm0的值设置为一个很大的数,就可以实现无限钱。每当卖出一个塔时就重置金额。

但我选择在购买塔的 subsd xmm0, xmm6 代码处修改(购买塔时触发的硬件写入断点),因为购买功能常用,在此处注入代码更合适。

我们要写的代码有点长,原地放不下,就在GameAssembly.dll代码结束处的有效文件偏移处写,加上两个jmp语句搞定。


金钱修改
[Asm] 纯文本查看 复制代码
; GameAssembly.dll+0x3F38F5  前7个字节 改为 
jmp GameAssembly.dll+0x291EB70
nop
nop 

; GameAssembly.dll+0x291EB70
movss xmm0,dword ptr ds:[0x7FFB8F8900A4]  ; 一千万浮点常数
cvtss2sd xmm0,xmm0                                      
xor r8d,r8d                                           
jmp  GameAssembly.dll+0x3F38F5


代码处右键->补丁->修补文件,保存为GameAssembly.dll替换原来的即可。

总结

本文讲解了一个塔防游戏的逆向思路,在关键数值加密的情况下修改了游戏内金额,使用代码注入的方式制作了修改补丁。

友情提示:游戏检测到异常数值后,Ninja账号会被标记,但不影响单机游玩体验。


发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2024-3-13 11:17
今天开放注册,自己来注册吧。

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 07:46

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表