用IDA Pro反编译逆向分析并修改手机游戏

时隔多年,我再次下载了IDA Pro,开始反编译分析并修改手机游戏,怕自己忘记了方法,便写了下来,当然,我本人并不是相关专业毕业的,仅仅是多年前在网上遇到了做游戏破解的朋友,加入了他们的团队,学习了些皮毛,因此,下面我写的东西,都是我自己的看法,全当抛砖引玉,并不一定正确,错误的地方,还请大家指正,谢谢

对于手机游戏的破解,在以前,可以用相关的修改器,也可以修改存档,但这些都不是我喜欢的方法,我习惯从游戏主程序出发,逆向分析程序走向,从源头上来修改,要逆向分析程序走向,那么就要用到逆向分析软件IDA Pro【交互式反汇编器专业版】

IDA Pro【交互式反汇编器专业版】是什么?

  • 交互式反汇编器专业版(Interactive Disassembler Professional),人们常称其为IDA Pro,或简称为IDA。是目前最棒的一个静态反编译软件,为众多0day世界的成员和ShellCode安全分析人士不可缺少的利器!IDA Pro是一款交互式的,可编程的,可扩展的,多处理器的,交叉Windows或Linux WinCE MacOS平台主机来分析程序, 被公认为最好的花钱可以买到的逆向工程利器。IDA Pro已经成为事实上的分析敌意代码的标准并让其自身迅速成为攻击研究领域的重要工具。它支持数十种CPU指令集其中包括Intel x86,x64,MIPS,PowerPC,ARM,Z80,68000,c8051等等。

具体请看:

https://baike.baidu.com/item/IDA%20Pro

因为维基上没有词条【奇怪】,我就用了百度百科,请理解

IDA Pro【交互式反汇编器专业版】官网:

https://www.hex-rays.com/products/ida/

但正版的价格非常贵,我是买不起的【文末我会给出破解版的下载地址】,如果你条件允许,一定要支持,这个是非常NB的软件

一 下载IDA Pro【交互式反汇编器专业版】

下载后并解压【解压路径不能有中文】

进入解压包打开IDA_Pro_7.5_绿化工具.exe

打开后,输入y,并回车,进行破解和配置

完成后,桌面上会出现IDA Pro【交互式反汇编器专业版】的快捷方式

  • 32位的电脑用IDA Pro (32-bit)
  • 64位的电脑用IDA Pro (64-bit)
二 开始分析游戏

我以安卓版的Inotia3 【艾诺迪亚3】来作为例子分析【文末我会给出下载地址】

提取游戏主程序,因为游戏的安装包实际上就是一个压缩包,安装的过程就相当于是解压,将后缀名apk修改为zip

解压并进入lib\armeabi,libgame.so就是手机游戏的主程序了,当然,并不是所有的游戏都是so,还有其他的,有的游戏lib下面有多个so,对应不同arm构架的手机,有arm64-v8a,armeabi-v7a,armeabi

打开桌面上的IDA Pro (64-bit)【我是64位的电脑】

选择File-Open,找到刚刚的libgame.so并打开

IDA Pro【交互式反汇编器专业版】会自动识别arm构架,不用修改,点【OK】

开始反编译【左下角的16进制地址在跳动】

反编译完成【左下角的16进制地址没有了】

那么应该怎么来分析呢?

首先要明确,在游戏编译过程中,会有相关的【函数名】,比如

  • 金钱:一般是money,gold,coin等
  • 经验:一般是Experience,Exp
  • 技能点:一般是SkillPoint,Skill,Point
  • 升级:一般是Level
  • 掉落物品:一般是DropItem

那么我们就以最为俗气的金钱为例来分析

在用IDA Pro【交互式反汇编器专业版】反编译完成后,看下图中的Function name,上面提到的【函数名】就在Function name中,进行查找【Ctrl+F】,找【money】

出现很多的结果

英语不差的应该都看明白了这些【函数名】的意思了

  • GetMoney【得到金钱】
  • SetMoney【设置金钱】
  • AddMoney【增加金钱】
  • MinusMoney【减少金钱】

那么我们以【MinusMoney】来看,争取0元够

双击选择【MinusMoney】,这一段就是【MinusMoney】的arm汇编代码

这样看起来不太方便,那么我们来转换一下,转换成图形视图,那就更直观方便分析了

右键【MinusMoney】区域,选择【Graph view】

现在看看,是不是更直观了呢?

看看【函数名】,有GetMoney【得到金钱】,也有SetMoney【设置金钱】,很显然,这段的意思就是,得到金钱,计算后再设置金钱,就是如此简单

再进行下一步前,我们还要来看看arm指令集

其实我也只懂些简单的指令,具体请看:arm指令集

下面开始分析【MinusMoney】

  • EXPORT INVEN_MinusMoney
    INVEN_MinusMoney
    ; __unwind {
    PUSH {R4,LR}
    MOVS R4, R0
  • MOV,移动指令
  • MOVS R4, R0,将寄存器R0中的值移动到寄存器R4中,通过分析,R0就是物品的价格,经过移动指令,已经将物品价格移动到R4中去了,后续就得看R4了
  • BL INVEN_GetMoney
  • BL,跳转返回指令
  • BL INVEN_GetMoney,跳转到GetMoney,读取现有的金钱数并暂存到寄存器R0中并返回
  • MOVS R3, #0
    CMP R0, R4
  • CMP,比较指令
  • CMP R0, R4,比较寄存器R0(现有金钱)和寄存器R4(物品价格)
  • BCC loc_8C1D6
  • BCC,跳转指令,小于时跳转
  • CMP R0, R4
  • BCC loc_8C1D6
  • 两句的意思是
  • 寄存器R0(现在金钱)小于寄存器R4(物品价格)时,跳转到loc_8C1D6,这样子就是钱不够,买不了
  • 寄存器R0(现在金钱)大于/等于(不小于)寄存器R4(物品价格)时,不跳转,正常购买,并进入下面的计算SUBS R0, R0, R4
  • SUBS R0, R0, R4
  • SUBS,减法指令
  • SUBS R0, R0, R4,R0=R0-R4,现有金钱-物品价格,余下的金钱再暂存到寄存器R0中
  • BL INVEN_SetMoney
  • BL,跳转返回指令
  • BL INVEN_SetMoney,跳转到SetMoney,并将暂存到寄存器R0中的金钱数写入到其他寄存器中,然后返回
  • MOVS R3, #1

通过分析,大家知道要怎么修改了吗?想一下?下面来看看我的想法

  • 修改CMP R0, R4,让R0大于或等于R4,当然我们并不知道R0和R4是多少,不过,arm指令也不知道,他只需要判断这两个数的大小就执行下一步,那就好办了,我们可以这样子修改
  • a CMP R0, R0 相等了吧,不小于了嘛
  • b CMP R4, R4 相等了吧,不小于了嘛
  • c CMP R1, R1 相等了吧,不小于了嘛
  • d CMP R2, R2 相等了吧,不小于了嘛
  • e CMP R0, #0 也可以用R0与0比较,你不至于那么穷吧,金钱为负数?
  • 修改BCC loc_8C1D6,BCC是小于跳,那么可以这样修改
  • a 把BCC loc_8C1D6修改为BEQ loc_8C1D6,BEQ,跳转指令【相等时跳转】,当CMP R0, R4时,相等就跳转,那就是买不了物品,R0与R4相等的可能性很小很小,但还是不保险,万一相等了呢?
  • b 把BCC loc_8C1D6删了,不管R0和R4大小情况,都能购买物品
  • 修改BL INVEN_GetMoney,因为现有金钱R0是通过跳转到INVEN_GetMoney后返回得到的,那么我们可以不去INVEN_GetMoney,直接给R0附一个值
  • a 把BL INVEN_GetMoney这句修改为MOV R0, #1000,给R0附值1000
  • b 把BL INVEN_GetMoney这句修改为MOV R0, R7,一般来说寄存器R7中的值都是比较大的

修改的思路是有了,那么应该怎么修改呢?

修改前,我们要明确,先前我们分析的是arm汇编代码,修改的话,必须要修改机器码,也就是要将arm指令转换成机器码

arm指令转换成机器码,有相关软件,我是请朋友在52破解下载的【感谢DevHjz】,应该没有问题【文末我会给出下载地址】,也可以在线转换:在线arm指令转换机器码

arm汇编代码对应的机器码有16位和32位的,如何区分呢?如下图

  • 转换前在第一行输入.code 16,即16位机器码
  • 转换前在第一行输入.code 32,即32位机器码

CMP R0, R0对应的16位机器码

CMP R0, R0对应的32位机器码

如上图

  • CMP R0, R0的16位机器码是8042,占4位
  • CMP R0, R0的32位机器码是000050E1,占8位

如何确定是16位机器码还是32位机器码呢?可以看原程序中的代码

选中CMP R0, R4,选择Hex View

实际上Hex View就是程序的16进制,CMP R0, R4的机器码是A042,占4位,即16位的机器码

现在将CMP R0, R4修改为CMP R0, R0,即将A042修改为8042

选中A042,右键,选择Edit编辑

修改后,右键,选择Apply changes应用修改

返回IDA View

已经将CMP R0, R4修改成了CMP R0, R0,看来思路没有问题

如果你觉得到此就修改完成了,那么你就错了,这仅仅是在IDA Pro【交互式反汇编器专业版】中修改,测试可行性,要实现真正的修改,还得继续

三 开始修改游戏

找到游戏主程序libgame.so,用十六进制编辑器打开,我用的是UE【UltraEdit】,这个比较主流

打开后

在IDA Pro【交互式反汇编器专业版】中查看修改地址,选中CMP R0, R0,图中底部就是要修改地方的十六进制地址:8C1CA

回到UE中,转到行0x8C1CA

将A042修改为8042,并保存,用apktool解包游戏安装包apk,解包后,将原libgame.so替换为修改后的libgame.so,打包并签名apk,传入手机安装,进游戏测试

安装修改前的游戏apk,去够买物品

进入游戏,来到武器店

试着买一把弹弩,价格是7银0铜,即70

差得有点多,结果显然是买不了

安装修改后的游戏apk,麻利的进入游戏,来到武器店,再次购买,如果不出意外的话,能够成功的0元购。。。。。。我去,还真出意外了,真是怕什么,就来什么?白嫖失败了

这是为什么呢?我明明修改了比较钱够不够的地方啊?难道还有地方要比较?马上去IDA Pro【交互式反汇编器专业版】检查一下

来到【MinusMoney】,鼠标指针移动到图中上面第三个图标上,出现【Jump to xref】

双击那个图标

这就是游戏程序中能够跳转到【MinusMoney】的所有流程,其中【BuyItem】很显眼,双击【BuyItem】,来到【BuyItem】

【BuyItem】中应该还有比较的地方

注意这条arm汇编代码,LDR R0, [SP,#0x20+var_1C],意思是将地址[SP,#0x20+var_1C]中的值读取到寄存器R0中【LDR,读取指令】【STR,写入指令】,结合之前在【MinusMoney】中的分析,应该是将物品的价格从地址[SP,#0x20+var_1C]读取并暂存到寄存器R0中,再进入【MinusMoney】,然后进行比较并计算

[SP,#0x20+var_1C]是地址,非常重要,这段代码有读取他的地方,那么在他前面应该就有写入他的地方,选取地址[SP,#0x20+var_1C],会变色

再往上翻,来到最上面,发现真的还有[SP,#0x20+var_1C],黄色,很显眼【选取[SP,#0x20+var_1C]的原因】,容易发现

应该能看懂了吧?

  • PUSH {R0-R2,R4-R7,LR}
    STR R0, [SP,#0x20+var_1C]
  • STR,写入指令
  • STR R0, [SP,#0x20+var_1C],将暂存到寄存器R0中的物品价格写入到地址[SP,#0x20+var_1C]中
  • BL INVEN_GetMoney
  • BL,跳转返回指令
  • BL INVEN_GetMoney,跳转到GetMoney,读取现有的金钱数并暂存到寄存器R0中并返回
  • LDR R3, [SP,#0x20+var_1C]
  • LDR,读取指令
  • LDR R3, [SP,#0x20+var_1C],将物品价格从地址[SP,#0x20+var_1C]中读取并暂存到寄存器R3中
  • MOVS R6, #6
    CMP R0, R3
  • CMP,比较指令
  • CMP R0, R3,比较寄存器R0(现有金钱)和寄存器R3(物品价格)
  • BCC loc_65680
  • BCC,跳转指令,小于时跳转
  • CMP R0, R3
  • BCC loc_65680
  • 两句的意思是
  • 寄存器R0(现在金钱)小于寄存器R3(物品价格)时,跳转到loc_65680,这样子就是钱不够,买不了
  • 寄存器R0(现在金钱)大于/等于(不小于)寄存器R3(物品价格)时,不跳转,正常购买,并进入下面的计算SUBS R0, R0, R4

看来,真的还有其他地方来判断金钱够不够,修改方法与之前是一样的

把CMP R0, R3修改为CMP R0, R0,即将机器码9842修改为8042

然后在UE中修改libgame.so,方法同前面一样,这儿就不再说了,修改后,打包签名apk,传入手机安装并再次测试

0元购成功,爽啊,并且金钱还变多了,其实这是显示的问题,请往下看

回到IDA Pro【交互式反汇编器专业版】,找到【MinusMoney】

还记得之前的SUBS R0, R0, R4吗?

  • SUBS R0, R0, R4
  • SUBS,减法指令
  • SUBS R0, R0, R4,R0=R0-R4,现有金钱-物品价格,余下的金钱再暂存到寄存器R0中

在上面0元购的过程中,我的金钱R0的值为0,物品价格R4的值为7银0铜,也就是70

SUBS R0, R0, R4,R0=R0-R4,即R0=0-70=-70,原本游戏中是没有负数的,而现在出现了负数,程序就搞不明白了,显示错误

如何解决这个问题呢?很简单嘛

把SUBS R0, R0, R4修改为ADDS R0, R0, R4

  • ADDS R0, R0, R4,R0=R0+R4,现有金钱+物品价格,得到的金钱再暂存到寄存器R0中

即将机器码由001B修改为0019

注意,在将arm汇编代码转换成机器码时,要输入ADD R0, R0, R4,不然转不了

用UE修改libgame.so后,打包签名apk,传入手机,继续测试

终于搞定

如果大家有兴趣,可以来试试修改其他的项目

教程结束
相关软件下载

IDA Pro【交互式反汇编器专业版】:

Google Drive下载

52破解下载

arm汇编转换器:

Google Drive下载

52破解下载

ARM指令集:

Google Drive下载

艾诺迪亚3.apk:

Google Drive下载

查看评论 (1)