iOS APP 反编译

29 篇文章 0 订阅
12 篇文章 0 订阅

原文地址 http://bbs.feng.com/read-htm-tid-672262.html


看不懂的请飘过,不要继续。
这不是给新手看的,也代表你不需要解决程序的修改问题。
这些技巧不只用于游戏的修改。




下載 Windows 工具

Windows : 
winscp http://winscp.net/eng/download.php
PuTTY http://putty.very.rulez.org/latest/x86/putty.exe

Mac / Linux :
用內置的 Terminal 便可


没 wifi 用 iPhone Tunnel Suite 3.0
http://bbs.feng.com/read-htm-tid-597149.html

没 wifi 苹果电脑用 iPhoneSSH
http://bbs.feng.com/read-htm-tid-720564.html



iPhone/iPod Touch 在 cydia 內安裝 deb 包
安装这些 deb 包最方便的方法是在 Cydia 内搜索及直接安装,这里提供的下载包及依赖包的链接下载点是方便手工安装时用

OpenSSH (openssh) 及 OpenSSL(openssl) (与iPhone/iPod Touch 终端操作)
http://apt.saurik.com/debs/openssh_6.1p1-11_iphoneos-arm.deb(更新支持 iPhone 5 / iPad 4)
http://apt.saurik.com/debs/openssh_5.2p1-8_iphoneos-arm.deb
http://apt.saurik.com/debs/openssl_0.9.8k-9_iphoneos-arm.deb

unzip 及 zip (解压缩及压缩打包工具)
http://apt.saurik.com/debs/unzip_5.52-5p_iphoneos-arm.deb(更新支持 iPhone 5 / iPad 4)
http://apt.saurik.com/debs/zip_2.32-5p_iphoneos-arm.deb(更新支持 iPhone 5 / iPad 4)
http://apt.saurik.com/debs/unzip_5.52-5_iphoneos-arm.deb
http://apt.saurik.com/debs/zip_2.32-5_iphoneos-arm.deb

vbindiff (iPhone 上的十六进制查看差异及修改器)
http://apt.saurik.com/debs/vbindiff_3.0b1-3p_iphoneos-arm.deb(更新支持 iPhone 5 / iPad 4)
http://apt.saurik.com/debs/vbindiff_3.0b1-3_iphoneos-arm.deb

ldid (更新支持 FAT binary)
及 ldone 0.2
http://bbs.feng.com/read-htm-tid-3970533.html


Link Identity Editor (ldid) 及 Darwin CC Tools (odcctools)(修改后用 ldid 签名, odcctools 包括 otool, linker , assembler汇编)
http://apt.saurik.com/debs/ldid_610-5_iphoneos-arm.deb
odcctools v782 包括 otool, linker , assembler汇编 (更新支持 armv6 及 armv7)
 odcctools_782-2_iphoneos-arm.deb (2.12 MB, 下载次数: 951) 
http://apt.saurik.com/debs/odcctools_286-8_iphoneos-arm.deb
http://apt.saurik.com/debs/uuid_1.6.0-2p_iphoneos-arm.deb(更新支持 iPhone 5 / iPad 4)
http://apt.saurik.com/debs/uuid_1.6.0-2_iphoneos-arm.deb

Diff Utilities (diffutils) (文本差异工具 diff)
http://apt.saurik.com/debs/diffutils_2.8.1-6_iphoneos-arm.deb

less (文本查看工具)
http://apt.saurik.com/debs/less_418-3_iphoneos-arm.deb

Vi IMproved (vim) 或 nano (文本编辑工具)

(更新支持 utf-8) ->     vim_7.1-4_iphoneos-arm.deb (4.05 MB, 下载次数: 277) 
vim --cmd "set encoding=utf-8" test.txt

http://apt.saurik.com/debs/vim_7.1-3_iphoneos-arm.deb
http://apt.saurik.com/debs/ncurses_5.7-9_iphoneos-arm.deb

http://apt.saurik.com/debs/nano_2.0.7-5_iphoneos-arm.deb
http://apt.saurik.com/debs/ncurses_5.7-9_iphoneos-arm.deb

Debug server for iOS 7 (armv7/arm64) :  debugserver.zip (428.99 KB, 下载次数: 73) 
这个 debugserver 程序就是配合实现远程调试, 
在iPhone : /usr/bin/debugserver <远程主机的IP地址>:<端口号> --attach=<进程ID>
例如 debugserver 192.168.1.20:2088 --attach 962
例如 debugserver 192.168.1.20:2088 /var/mobile/Applications/AAEF8906-2E33-4A1E-81FF-D51BC325945A/ff3.app/ff3

远程主机可以是 Mac 运行 lldb, gdb 或是 IDA (见下面下载 IDA 64 Plus for Windows)
lldb (for Mac)  lldb.zip (77.57 KB, 下载次数: 19) 
(启动 lldb 后) gdb-remote <iOS 设备 的IP地址>:<端口号> 
例如 (lldb) gdb-remote 192.168.1.21:2088 


GNU Debugger (gdb-1821) (程序调试工具) iOS 7.0 (32 bits) 更新
 gdb-1821.deb (7.58 MB, 下载次数: 716) 

GNU Debugger (gdb) (程序调试工具) v1708 iOS 5.0 更新
http://bbs.feng.com/read-htm-tid-3897370.html

GNU Debugger (gdb) (程序调试工具) iOS 4.3.x 更新
http://apt.saurik.com/debs/gdb_1518-11_iphoneos-arm.deb
http://apt.saurik.com/debs/ncurses_5.7-9_iphoneos-arm.deb
http://apt.saurik.com/debs/readline_6.0-7_iphoneos-arm.deb
http://apt.saurik.com/debs/sqlite3_3.5.9-12_iphoneos-arm.deb
http://apt.saurik.com/debs/sqlite3-lib_3.5.9-2_iphoneos-arm.deb
http://apt.saurik.com/debs/sqlite3-dylib_3.5.9-1_iphoneos-arm.deb


GNU Debugger (gdb) (程序调试工具)
http://apt.saurik.com/debs/gdb_962-5_iphoneos-arm.deb
http://apt.saurik.com/debs/ncurses_5.7-9_iphoneos-arm.deb
http://apt.saurik.com/debs/readline_6.0-7_iphoneos-arm.deb
http://apt.saurik.com/debs/sqlite3_3.5.9-12_iphoneos-arm.deb
http://apt.saurik.com/debs/sqlite3-lib_3.5.9-1_iphoneos-arm.deb
http://apt.saurik.com/debs/sqlite3-dylib_3.5.9-1_iphoneos-arm.deb

adv-cmds (ps 工具)
http://apt.saurik.com/debs/adv-cmds_119-5_iphoneos-arm.deb

grep (grep 文本搜索工具)
http://apt.saurik.com/debs/grep_2.5.4-3_iphoneos-arm.deb


ARM 参考书籍

http://bbs.feng.com/read-htm-tid-363306.html



 (主要是看第三章 Chapter 3)





[fly]修改及用 gdb 调试游戏流程[/fly]

(1) 安装及试玩游戏,每个游戏的修改方法都不同,没有玩过这游戏,怎样知道要修改什么呢?
这教程用了 Final Fantasy 2 作例子

(2) 用 iTunes 安装 Final Fantasy 2 破解版本(未破解的不能反汇编)

(3) 用putty / ssh 连接iPhone / iPod Touch,假设你的iPhone / iPod Touch 的IP地址是192.168.1.104

Connection type: 选 SSH
Port 选 22
按 Open



PuTTY 连接 192.168.1.104 后

Login 输入 root
Password(假设你没有更改密码) 输入 alpine

Mac / Linux Terminal 内输入
ssh 


(4) 进入游戏路径目录内(先决条件是已用 PuTTy / Terminal 连接iPhone / iPod Touch)
输入


  1. cd /var/mobile/Applications/*/FinalFantasy2.app

复制代码

(5) 到上一层路径目录建立 cheat 临时工作路径目录及游戏程式临时修改档
输入


  1. cd ..

  2. mkdir -p cheat

  3. cd cheat


  4. cp -p ../FinalFantasy2.app/FinalFantasy2 FinalFantasy2.original

复制代码

(6) 反汇编原游戏程式


  1. otool -tv FinalFantasy2.original &gt; FinalFantasy2.original.txt

复制代码

(7) 查看反汇编代码分析并找出要修改的地方(每个游戏的修改地方都不同, 这点最难)
要修改游戏,你会有以下的困难或问题:

(i) 没有高阶源代码,只有反汇编代码 
反汇编代码分析是困难的但绝对不是不可能作分析,你可以找到些不错的ARM Assembly的参考书 
在上面亦已提供了一些很好的 ARM 指令参考 
常见的是以下这些基本的指令及其执行条件码:

MOV 或 MVN 寄存器数值的传送操作
ADD 或 SUB 加减的算术操作
CMP 或 CMN 比较操作
AND、ORR、EOR 逻辑操作
B、BL、BNE、BGE 分支/跳转指令
MUL 乘法操作 或 LSL 是 二进制左移,左移一位,即十进制乘2倍
LDR 或 STR 加载及存储数据


每个指令都可加上执行条件码根据上一个运算、逻辑或比较指令的结果决定是否执行指令

执行条件码 (Condition Codes):
① CS 及 CC(Carry)进位条件码,CS=进位,否则=CC(不进位).
② EQ 及 NE (Equal 或 Zero)相等或零条件码,EQ=运算结果为相等或零时,否则=NE(不相等).
③ VS 及 VC(Overflow)溢出条件码。 VS=溢出,否则=VC(不溢出)。
④ PL 及 MI 条件码。 PL(Plus/Positive)=结果为正,MI(Minus/Negative)=结果为负。

⑤ GT 及 LT 条件码。 GT(Greater Than)=大于(PL+VC+NE / MI+VS+NE),LT(Less Than)=小于(MI+VC / PL+VS)。
⑥ GE 及 LE 条件码。 GE(Greater Than or Equal)=大或等于(PL+VC / MI+VS),LE(Less Than or Equal)=小或等于(MI+VC / PL+VS / EQ)。
⑦ HI 及 LO 条件码。 HI(Higher Than)=无符号数(unsigned)高于(CS+NE),LO(Lower Than)=无符号数(unsigned)低于(CC)。
⑧ HS 及 LS 条件码。 HS(Higher or Same)=无符号数(unsigned)高于或相等(CS/EQ),LS(Lower or Same)=无符号数(unsigned)低于或相等(CC/EQ)。
⑨ AL 及 NV 条件码。 条件码默认为AL(Always)=无条件执行,NV(Never)是AL的相反=不执行。


例子及其注解意思

  1. CMP R0, R1       @寄存器数值 R0 及 R1 的比较

  2. MOVGT R2, R0     @如果结果 R0 &gt;(大于) R1,则执行MOV R2, R0即 R2=R0

  3. MOVLE R2, R1     @如果结果 R0 &lt;=(小或等于) R1,则执行MOV R2, R1即 R2=R1

复制代码

  1. LDR R1, [R0]     @意思是 R1 = *R0,从R0指向的地址处的数据载入到寄存器 R1

  2. STR R1, [R0]     @意思是 *R0 = R1,把寄存器 R1内的数据写到 R0 内指向的地址处

复制代码



(ii) 看不懂游戏程式流程,没法分析 
有很多人都喜欢用 IDA Pro Advanced 去做分析, 无疑这软件是个非常好的静态分析工具,它有图形视图显示代码流程作搜索及深层分析。除了可分析反汇编代码外,亦可反汇编一些 otool 不能处理的工作。 但 IDA Pro Advanced 在iPhone 的程式只适合做静态的分析。

你可以在这里下载 IDA Pro Advanced 5.2 及其参考书,建议你使用功能及视图比较强大的 Windows 版本。 
http://bbs.feng.com/read-htm-tid-363306.html 
IDA 64 Plus for Windows 百度云网盘下载 : http://pan.baidu.com/s/1sjGXZQl  



只看代码是不能作分析,要配合动态调试去了解程式的细节在实际运行时发生的数据及变化。在第15步就有用 gdb 作动态调试的例子去设置断点、继续、跟踪及分析代码。gdb 的参考书可在上面的链接下载。

(iii) 找不到游戏的数据例如金钱,经验值,装备,等级暂存在那?

方法一:在 gdb 设置断点分析
ARM CPU 有个特性便是一些加减计算要传送到CPU寄存器(register) 进行,因此你会经常看到这些要找的数据会先从内存用LDR 指令载入到寄存器, 经过一些计算(加或减)后及防溢位判断后便用STR 指令存储这寄存器回内存地址。

另外由于这些程式大多是用 Objective C 或 C++ 语言写成,这些程序员会用一些描述性的函数名,例如带有 Money, Price, Gold, Exp, Item, Life, Level 字段等。

利用这两点便可以将程序锁定在某些函数上,再利用 gdb 调试工具暂停在某些点一步一步地单步执行及查看一些寄存器,印证是否与你要找的数据是否有关。

    在FinalFantasy2 的这实例中, 是用这方法找到修改点
    用 less 工具去找寻 Money
    putty / Terminal 输入


  1. less FinalFantasy2.original.txt

复制代码

在 less 工具內输入


  1. /Money

复制代码

去开始找寻(按 N 键去继续找寻),便会找到这段代码像是要存储金钱数据(SetMoney),0007b218是进入这段代码的开始地址


  1. __ZN14cFF2GlobalWork19sysGAMEPrm_SetMoneyEj:

  2. 0007b218 e59f300c ldr r3, [pc, #12] ; 0x7b22c

  3. 0007b21c e580120c str r1, [r0, #524]

  4. 0007b220 e1510003 cmp r1, r3

  5. 0007b224 8580320c strhi r3, [r0, #524]

  6. 0007b228 e12fff1e bx lr

复制代码

首先在iPhone或iPod Touch 开始Final Fantasy 2 直至游戏已 Resume及进入游戏。


    ① 在PuTTY / Terminal 找FinalFantasy2 的运行中的进程编号(process id)

    PuTTY / Terminal 输入


  1. ps ax

复制代码

得到


  1. 1115   ??  Ss     1:30.86 /var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/FinalFantasy2.app/FinalFantasy2

复制代码

找到FinalFantasy2 游戏现时运行中的进程编号是 1115

    ② 用gdb 进入调试运行中的进程编号1115
    PuTTY / Terminal 输入


  1. gdb -p 1115

复制代码

此时游戏会暂停,音乐也暂停

    ③ 用gdb 设定断点breakpoint在十六进制地址0x7b218

    PuTTY / Terminal 输入


  1. break *0x7b218

复制代码

④ 继续 continue 游戏
    PuTTY / Terminal 输入


  1. c

复制代码

⑤ 将Final Fantasy 2 游戏进入战斗,战胜后游戏会在十六进制地址0x7b218处停止

    ⑥ 暂停后,离开这分支__ZN14cFF2GlobalWork19sysGAMEPrm_SetMoneyEj
    PuTTY / Terminal 输入


  1. finish

复制代码

⑦ 反汇编现时地址上面的代码


  1. disassem $pc-28 $pc

复制代码

得到


  1. 0x0003baac &lt;_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 180&gt;: bl 0x78e30 &lt;_ZN14cFF2GlobalWork8InstanceEv&gt;

  2. 0x0003bab0 &lt;_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 184&gt;: mov r4, r0

  3. 0x0003bab4 &lt;_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 188&gt;: bl 0x78e30 &lt;_ZN14cFF2GlobalWork8InstanceEv&gt;

  4. 0x0003bab8 &lt;_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 192&gt;: bl 0x7b230 &lt;_ZN14cFF2GlobalWork19sysGAMEPrm_GetMoneyEv&gt;

  5. 0x0003babc &lt;_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 196&gt;: add r1, r0, r5

  6. 0x0003bac0 &lt;_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 200&gt;: mov r0, r4

  7. 0x0003bac4 &lt;_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 204&gt;: bl 0x7b218 &lt;_ZN14cFF2GlobalWork19sysGAMEPrm_SetMoneyEj&gt;

复制代码

这时会发现在_ZN14cFF2GlobalWork19sysGAMEPrm_GetMoneyEv
及_ZN14cFF2GlobalWork19sysGAMEPrm_SetMoneyEj
中间0x0003babc 地址的代码add r1, r0, r5 是最可疑的


    ⑧ 取消断点1及设定新断点breakpoint在十六进制地址0x0003babc 及重新继续continue 游戏
    PuTTY / Terminal 输入


  1. disable 1

  2. break *0x3babc

  3. c

复制代码

在iPhone或iPod Touch查看现时游戏的金钱例如是4888,将Final Fantasy 2 游戏进入战斗,战胜后游戏会新断点2地址0x3babc处停止

    ⑨ 当游戏在新断点2暂停时查看寄存器就发现 r0 是当时的金钱余额及 r5 是战胜后得到的金钱
    PuTTY / Terminal 输入


  1. i r $r0 $r1 $r5 $pc

复制代码

⑩ 假设已找到应修改的地址是 0003babc,便可继续下面第(8)步

方法二:在 gdb 搜索内存数据值及设置观察点(watchpoint) 

    游戏的数据都会暂存在堆(heap)内存, 于游戏退出前储存在 iPhone 或 iPod Touch的闪存记忆体内, 一些经验值或金钱的数字是比较独特,在内存重复出现的机会不多,这些唯一的数字便可用这方法去进行搜索。

    这里用了 Zenonia 2 v1.0 作例子,下面的游戏截图便看到用一个独特的经验值数字 672 去开始这方法



    ① 在 PuTTY / Terminal 用  ps ax  的指令找到 ZENONIA2 游戏现时运行中的进程编号是 1123

    ② 使用 gdb 进入运行中的进程编号 1123
    PuTTY / Terminal 输入


  1. gdb -p 1123

复制代码

此时游戏会暂停,音乐也暂停

    ③ 用 gdb 输入这些指令包括,内存开始地址(0x800000)、结束地址(0x880000)及要搜索的数字672如下:

    PuTTY / Terminal 输入


  1. set $x=0x800000

  2. while(*++$x!=672 && $x<0x880000)

  3. end

复制代码

④ 输入 end 之后等候数十秒 ....,待gdb去搜索这段内存地址

    ⑤ gdb 搜索完毕后
    PuTTY / Terminal 输入


  1. p/x $x

复制代码

得到


  1. $1 = 0x85e28c

复制代码

这代表 gdb 已找到在 0x85e28c 的内存地址的存储数字是 672

    PuTTY / Terminal 输入


  1. x/dw 0x85e28c

复制代码

得到确认 0x85e28c 的内存地址的存储数字是 672


  1. 0x85e28c:    672

复制代码

⑥ 用 gdb 继续搜索
    PuTTY / Terminal 输入 (或按方向键 ↑ 4次,然后回车,免重复输入)


  1. while(*++$x!=672 && $x<0x880000)

  2. end

复制代码

再等十多秒,gdb 搜索完毕后
    PuTTY / Terminal 输入


  1. p/x $x

复制代码

得到


  1. $2 = 0x880000

复制代码

这代表 gdb 已到结束的地址 0x880000,都没有找到。这也表示数字 672 是唯一出现在 0x85e28c 要找的内存范围内。

    ⑦ 用 gdb 更改内存地址 0x85e28c 的存储数字为 1000
    PuTTY / Terminal 输入


  1. set {int}0x85e28c=1000

复制代码

也可以用


  1. set *0x85e28c=1000

复制代码

PuTTY / Terminal 输入


  1. x/dw 0x85e28c

复制代码

得到确认已成功更改数字


  1. 0x85e28c:    1000

复制代码

⑧ 继续 continue 游戏
    PuTTY / Terminal 输入


  1. c

复制代码

⑨ 在回到游戏里退出 STATUS 画面再进入 STATUS,画面内数据重刷后,确认已成功更改经验值数字为1000



    留意:由于游戏数据在堆(heap)内存的地址不是固定的,所以每次运行的进程都要再搜索新的内存地址。另外,搜索的内存地址范围也会改变,如果在 0x800000 至 0x880000 范围内找不到的话,就要往后试 0x880000 至0x900000 新的范围。

         另外:用相同搜索方法也可以找到金钱数字在这次运行进程是在内存地址 0x874c04

    ⑩ 找到经验值地址后便可设置观察点(watchpoint)于内存地址 0x85e28c

    设置观察点的目的是当内存地址值被读或被写时,会显示数据及暂停程序

    PuTTY / Terminal 输入


  1. watch *0x85e28c

复制代码

及继续游戏
    PuTTY / Terminal 输入


  1. c

复制代码

留意:游戏在观察点(watchpoint) 生效下运行是非常的慢,有些游戏是不能正常运作,有时候手机也要重启,所以下面的步骤是不一定可以进行的

    ⑪ 将游戏进入战斗打怪后程序便会暂停在 0x9f508 地址,gdb 会显示


  1. Hardware watchpoint 1: *8774284


  2. Old value = 1000

  3. New value = 1086

  4. 0x0009f508 in CMvPlayer::CheckLevelUp ()

复制代码

PuTTY / Terminal 输入


  1. x/14i $pc-16

复制代码

得到


  1. 0x9f4f8 &lt;_ZN9CMvPlayer12CheckLevelUpEj+60&gt;:    b.n    0x9f508 <_ZN9CMvPlayer12CheckLevelUpEj+76>

  2. 0x9f4fa &lt;_ZN9CMvPlayer12CheckLevelUpEj+62&gt;:    adds    r0, r4, #0

  3. 0x9f4fc &lt;_ZN9CMvPlayer12CheckLevelUpEj+64&gt;:    movs    r1, #1

  4. 0x9f4fe &lt;_ZN9CMvPlayer12CheckLevelUpEj+66&gt;:    movs    r2, #0

  5. 0x9f500 &lt;_ZN9CMvPlayer12CheckLevelUpEj+68&gt;:    subs    r5, r5, r3

  6. 0x9f502 &lt;_ZN9CMvPlayer12CheckLevelUpEj+70&gt;:    bl    0x9f338 <_ZN9CMvPlayer9OnLevelUpEii>

  7. 0x9f506 &lt;_ZN9CMvPlayer12CheckLevelUpEj+74&gt;:    movs    r3, #1

  8. 0x9f508 &lt;_ZN9CMvPlayer12CheckLevelUpEj+76&gt;:    str    r5, [r4, r6]

  9. 0x9f50a &lt;_ZN9CMvPlayer12CheckLevelUpEj+78&gt;:    cmp    r3, #0

  10. 0x9f50c &lt;_ZN9CMvPlayer12CheckLevelUpEj+80&gt;:    beq.n    0x9f516 <_ZN9CMvPlayer12CheckLevelUpEj+90>

  11. 0x9f50e &lt;_ZN9CMvPlayer12CheckLevelUpEj+82&gt;:    cmp    r5, #0

  12. 0x9f510 &lt;_ZN9CMvPlayer12CheckLevelUpEj+84&gt;:    beq.n    0x9f516 <_ZN9CMvPlayer12CheckLevelUpEj+90>

  13. 0x9f512 &lt;_ZN9CMvPlayer12CheckLevelUpEj+86&gt;:    movs    r5, #0

  14. 0x9f514 &lt;_ZN9CMvPlayer12CheckLevelUpEj+88&gt;:    b.n    0x9f4c6 <_ZN9CMvPlayer12CheckLevelUpEj+10>

复制代码

PuTTY / Terminal 输入


  1. i r $r5 $r4 $r6 $pc

  2. p/x $r4+$r6

复制代码

得到


  1. r5             0x43E    1086

  2. r4             0x85DC00    8772608

  3. r6             0x68c    1676

  4. pc             0x9f508    652552


  5. $5 = 0x85e28c

复制代码

这时确认了 0x9f508 地址这句代码
    str    r5, [r4, r6]
    的意思是,r4 + r6 = 0x85e28c ,把寄存器 r5 内的数字(1086) 写到 0x85e28c 的地址
 
    程序因要写进这0x85e28c 的地址,所以暂停了,这就是观察点(watchpoint) 的强大功能。

    PuTTY / Terminal 输入


  1. bt

复制代码

得到


  1. #0  0x0009f508 in CMvPlayer::CheckLevelUp ()

  2. #1  0x0009ff2e in CMvPlayer::DoUpdate ()

  3. #2  0x00094744 in CMvObject::Update ()

  4. #3  0x000969cc in CMvObjectMgr::Update ()

  5. #4  0x000662e6 in CMvGameState::UpdateGame ()

复制代码

这时就可根据上面得到的信息在这段代码的前后范围进行跟踪、设置断点及进一步的分析


有新的方法时,再继续更新 ............

(iv) 不知道修改点在那及改为什么?
修改程序是不能插入程序代码,主要原因是移位后的程序是不能运行的。一般的做法是找到要修改的位置在原档案位置修改代码改为你需要的指令。 修改点一定要经过分析代码后再不断地用动态分析确定后,在适当的地方重覆试验及调试验证修改后的结果 。

一些RPG游戏的特性,例如是金钱或经验值是会在战斗后重算及更新,一般都是要找到及修改更新数据前的指令。金钱的修改点也可以修改在买卖装备时的指令。连续升级的修改主要是看该游戏是怎样升级,例如 Inotia 2是根据经验值去升级,只要找到判断经验值的指令代码地址,修改其判断的指令便可。

对于游戏来说,一般的指令修改例子如下:

① 修改寄存器的增加数字例如 
    Final Fantasy II 增加战胜后所得金钱 
    地址 0003babc 
    add r1, r0, r5 
    改为 
    add r1, r0, r5, lsl #5 

② 修改寄存器减少的数字为零例如 
    Inotia 2 v 1.1.0 不扣技能点 
    地址 00021b9c 
    sub r3, #1 
    改为 
    sub r3, #0 

    地址 00037b46 
    sub r1, #1 
    改为 
    sub r1, #0 

③ 修改比较的寄存器例如 
    花儿朵朵开-v1.0 不死作弊版 (这里 r2 寄存器是花朵已绽放的数量)
    地址 00004ee8 
    cmp r2, r3 
    改为 
    cmp r2, #1 ; 0x1 

④ 修改arm 32 位为两个arm thumb 16 位代码例如 
    Inotia 2 v 1.1.0 roll点全18 
    地址 0005c404 
    bl 0x9914 
    改为 
    mov r0, #9 
    mov r0, #9 

    地址 0005c404, 0005c40e, 0005c41c, 0005c426 
    bl 0x9914 
    改为 
    mov r0, #9 
    mov r0, #9 

⑤ 要删除代码便要用 nop (no operation) 取代 
    thumb 16 bits nop 是 46c0  
    arm 32 bits nop 是 e1a00000


(8) 在FinalFantasy2 的这实例中,假设已找到应修改的地址是 0003babc,代码是 e0801005


  1. 0003bab8        eb00fddc        bl 0x7b230

  2. 0003babc        e0801005        add r1, r0, r5   @意思是 r1 = r0 +r5 ; r0 是当时的金钱余额; r5 是战胜后得到的金钱

  3. 0003bac0        e1a00004        mov r0, r4

  4. 0003bac4        eb00fdd3        bl 0x7b218     @分支到函数名 __ZN14cFF2GlobalWork19sysGAMEPrm_SetMoneyEj 去更新金錢余额

复制代码

(9) 修改目标 : 将所得金钱乘大32倍
0003babc的应修改目标代码是


  1. add r1, r0, r5, lsl#5 @意思是 r1 = r0 +( r5 二进制左移五位,即十进制乘大32倍)

复制代码

(10) 找新ARM指令代码
add r1, r0, r5 的ARM指令代码是 e0801005
修改目标是要找到 add r1, r0, r5, lsl#5 的ARM指令代码 ?

用 vim 或 nano 建立 armtest.s 如下


  1.     .file &quot;armtest.s&quot;

  2.     .globl _main

  3.     .code 32

  4. _main:

  5.     add r1, r0, r5

  6.     add r1, r0, r5, lsl #5

复制代码

留意: 一些程式反汇编后是ARM Thumb, ARM Thumb 是16 bits 而ARM 是32 bits. ARM 32 bits 及 ARM Thumb 的分别请找上面 ARM Assembler 的参考(ARM Thumb 的可用指令是比 ARM 32 bits 少)。 如果要找 ARM Thumb 代码要将上面的.code 32改为.code 16 及加上 .thumb_func _main 如下


  1.     .code 16

  2.     .thumb_func _main

复制代码




汇编 arm 输入


  1. as armtest.s -o armtest.o ; otool -tv armtest.o

复制代码

便看到


  1. (__TEXT,__text) section

  2. _main:

  3. 00000000    e0801005    add r1, r0, r5

  4. 00000004    e0801285    add r1, r0, r5, lsl #5

复制代码

及得到add r1, r0, r5, lsl #5 目标ARM指令代码为 e0801285

(11) 建立修改程式第一版FinalFantasy2.v1及用十六进制修改器修改代码

输入


  1. cp -p FinalFantasy2.original FinalFantasy2.v1      

  2. vbindiff FinalFantasy2.v1

复制代码

进入vibindiff 后按G及输入地址3AABC跳到要修改的位置如下



留意: 在第8步时找到的位置是0003Babc,但修改程式的位置要减去十六进制0x1000得到3Aabc
(0x3babc 减 0x1000 等于 0x3aabc)

E键开始修改,将
05 10 80 E0
改为
85 12 80 E0

然后按Esc键及Y键确认修改

最后按Q键离开 vbindiff 修改器

如下



留意: 修改器显示的 05 10 80 E0 与反汇编的代码 e0801005 的位置顺序是倒的

(12) 反汇编修改程式第一版 v1 及比较原版本 original
输入


  1. otool -tv FinalFantasy2.v1 &gt; FinalFantasy2.v1.txt

  2. diff FinalFantasy2.original.txt FinalFantasy2.v1.txt

复制代码

也可以用 otool -otV


得到


  1. < FinalFantasy2.original:

  2. ---

  3. > FinalFantasy2.v1:

  4. 59597c59597

  5. < 0003babc    e0801005    add    r1, r0, r5

  6. ---

  7. > 0003babc    e0801285    add    r1, r0, r5, lsl #5

复制代码

(13) 对修改程式第一版重新签名
输入


  1. ldid -s FinalFantasy2.v1

复制代码

(14) 将签名后的程式放回程式路径进行测试
首先备份原程式(留意:要用mv移动不要用cp)
输入


  1. mv ../FinalFantasy2.app/FinalFantasy2 ../FinalFantasy2.app/FinalFantasy2.bak

复制代码

安装修改后的程式及更新权限
输入


  1. cp -p FinalFantasy2.v1 ../FinalFantasy2.app/FinalFantasy2

  2. chown mobile:mobile ../FinalFantasy2.app/FinalFantasy2

  3. chmod 0755 ../FinalFantasy2.app/FinalFantasy2

复制代码

(15) 用 gdb 调试游戏

调试是用 gdb,在这里的目的是设置断点使游戏暂停,查看CPU的寄存器,印证修改是否成功。由于游戏占用很多内存,在游戏运行时调试再加ssh 连接很多时候都会崩溃。所以用 iPod Touch 3代 或 iPhone 3GS 做这项工作会有优势。

首先在iPhone或iPod Touch 开始Final Fantasy 2 直至游戏已Resume及进入游戏。

在iPhone或iPod Touch查看现时游戏的金钱例如是 7223

① 在putty / Terminal 找 FinalFantasy2 的运行中的进程编号 (process id)

PuTTY / Terminal 输入


  1. ps ax

复制代码

得到


  1. 1115   ??  Ss     1:30.86 /var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/FinalFantasy2.app/FinalFantasy2

复制代码

找到 FinalFantasy2 游戏现时运行中的进程编号是 1115

② 用 gdb 进入调试运行中的进程编号 1115
PuTTY / Terminal 输入


  1. gdb -p 1115

复制代码

此时游戏会暂停,音乐也暂停

③ 用 gdb 设定断点breakpoint在十六进制地址 0x3babc (即在第8步时找到的位置0003babc)
PuTTY / Terminal 输入


  1. break *0x3babc

复制代码

④ 继续 continue 游戏
PuTTY / Terminal 输入


  1. c

复制代码

⑤ 将Final Fantasy 2 游戏进入战斗,战胜后游戏会在十六进制地址 0x3babc处停止


⑥ 暂停后,查看 CPU 寄存器 register (info register 指令)
PuTTY / Terminal 输入


  1. i r $r0 $r1 $r5 $pc

复制代码

得到


  1. r0             0x1c37    7223

  2. r1             0x25    37

  3. r5             0x25    37

  4. pc             0x3babc    244412

复制代码

印证了 r0=7223 是现时的金钱
游戏暂停在 pc=0x3babc


⑦ 查看下一步将要运行的反汇编指令
PuTTY / Terminal 输入


  1. x/i $pc

复制代码

得到 add r1, r0, r5, lsl #5,印证成功修改指令


  1. 0x3babc <_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG+196>:    add    r1, r0, r5, lsl #5

复制代码

⑧ 运行下一步 stepi 指令
PuTTY / Terminal 输入


  1. si

复制代码

查看 CPU 寄存器 register (info register 指令)
PuTTY / Terminal 输入


  1. i r $r0 $r1 $r5 $pc

复制代码

得到


  1. r0             0x1c37    7223

  2. r1             0x20d7    8407

  3. r5             0x25    37

  4. pc             0x3bac0    244416

复制代码

此时印证了 r1 = r0 +( r5 x 32)
            = 7223 + (27 x 32)
            = 8407

查看下一步将要运行的反汇编指令
putty / Terminal 输入


  1. x/i $pc

复制代码

得到


  1. 0x3bac0 <_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG+200>:    mov    r0, r4

复制代码

⑨ 继续 continue 游戏
PuTTY / Terminal 输入


  1. c

复制代码

⑩ Final Fantasy 2 游戏显示战胜后得到37的金钱,但实际金钱余额是 8407印证修改游戏已成功

⑪ 离开 gdb

按下Ctrl+C 组合键停止执行进程

PuTTY / Terminal 输入


  1. quit

复制代码

及按 y 键确认离开 gdb


留意:在上面第⑥步暂停时,你可以输入指令去更改CPU 寄存器 register
例如输入
set $r5=1000
去试试增加金钱数目


(16) 假设已调试完成,便可将修改后的程式打包发布

进入游戏路径目录内,输入


  1. cd /var/mobile/Applications/*/FinalFantasy2.app

复制代码

到上一层路径目录


  1. cd ..

复制代码

建立 IPA 所要的路径及档案及删除不需要的备份档案


  1. rm -fr Payload

  2. mkdir -p Payload

  3. cp -pr FinalFantasy2.app Payload/

  4. rm -fr Payload/FinalFantasy2.app/FinalFantasy2*.bak

复制代码

打包 ipa 为 FinalFantasy2_v1.ipod4g.ipa


  1. zip -r FinalFantasy2_v1.ipod4g.ipa Payload iTunesArtwork

复制代码

找现时的路径


  1. pwd

复制代码

得到


  1. /var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

复制代码

用 winscp 或Terminal 的 scp 指令传送这档作发布


  1. /var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/FinalFantasy2_v1.ipod4g.ipa

复制代码

XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 是随机路径


(17) 其他有用的技巧

① 由于修改游戏的程式代码是很少量, 相对重覆调试及动态分析工作比较多,此教程便介绍了用iPhone 的工具直接做修改及反汇编。这样对于少量修改程式代码及重覆在iPhone调试是比较要传回PC做修改是更有效率的。

② 调试的工具 gdb 是比较难用,但有些方法是可提高使用 gdb 的效率。

例如:在 gdb 建立宏 macro define
在 iphone 建立这档案(~/.gdbinit) 内容为


  1. define ascii_char

  2. set $_c=*(unsigned char *)($arg0)

  3. if ( $_c < 0x20 || $_c > 0x7E )

  4. printf '.'

  5. else

  6. printf '%c', $_c

  7. end

  8. end

  9. document ascii_char

  10. Print the ASCII value of arg0 or &#39;.&#39; if value is unprintable

  11. end


  12. define hex_quad

  13. printf '%02X %02X %02X %02X  %02X %02X %02X %02X',  \

  14. *(unsigned char*)($arg0), *(unsigned char*)($arg0 + 1),  \

  15. *(unsigned char*)($arg0 + 2), *(unsigned char*)($arg0 + 3), \

  16. *(unsigned char*)($arg0 + 4), *(unsigned char*)($arg0 + 5), \

  17. *(unsigned char*)($arg0 + 6), *(unsigned char*)($arg0 + 7)

  18. end

  19. document hex_quad

  20. Print eight hexadecimal bytes starting at arg0

  21. end


  22. define hexdump

  23. printf '%08X : ', $arg0

  24. hex_quad $arg0

  25. printf ' - '

  26. hex_quad ($arg0+8)

  27. printf ' '


  28. ascii_char ($arg0)

  29. ascii_char ($arg0+1)

  30. ascii_char ($arg0+2)

  31. ascii_char ($arg0+3)

  32. ascii_char ($arg0+4)

  33. ascii_char ($arg0+5)

  34. ascii_char ($arg0+6)

  35. ascii_char ($arg0+7)

  36. ascii_char ($arg0+8)

  37. ascii_char ($arg0+9)

  38. ascii_char ($arg0+0xA)

  39. ascii_char ($arg0+0xB)

  40. ascii_char ($arg0+0xC)

  41. ascii_char ($arg0+0xD)

  42. ascii_char ($arg0+0xE)

  43. ascii_char ($arg0+0xF)


  44. printf '\n'

  45. end

  46. document hexdump

  47. Display a 16-byte hex/ASCII dump of arg0

  48. end


  49. define hexdump1

  50. hexdump $arg0

  51. x/8h $arg0

  52. printf '\n'

  53. disassem $arg0 $arg0+16

  54. printf '\n'

  55. end

  56. document hexdump1

  57. Display a 16-byte hex/ASCII dump and disassembly of arg0

  58. end

复制代码

在用 gdb 调试时输入


  1. hexdump1 $pc

复制代码

便可列出$pc位置后十六位的内容及反汇编的代码


③ 在断点设定一些要自动运行的指令

下面的意思是建立断点1
及在断点1停止时运行查看一些暂存器(i r $r0 $r1 $r5 $pc)及反汇编下四个指令代码(x/4i $pc)


  1. break *0x3babc

  2. commands 1

  3. i r $r0 $r1 $r5 $pc

  4. x/4i $pc

  5. end

复制代码

④ 在 gdb 断点暂停时,是可改变内存及指令
FinalFantasy2 的例子,0x0003babc地址的指令是
输入


  1. x/i 0x0003babc

复制代码

得到代码是


  1. add r1, r0, r5

复制代码

输入


  1. x/xw 0x0003babc

复制代码

得到代码数值是


  1. 0xe0801005

复制代码

改变指令代码数值输入


  1. set {int}0x0003babc = 0xe0801285

复制代码

检查改变后的指令输入


  1. x/i 0x0003babc

复制代码

得到改变后的指令代码是


  1. add r1, r0, r5, lsl #5

复制代码

这样就不用离开 gdb 即时看到修改代码后的效果


⑤ gdb 执行到程序中其他地址的命令
    例子:
    stepi                           单步执行一个机器指令(命令步入函数)
    nexti                           单步执行一个机器指令(命令步过函数)
    nexti 2                        继续执行机器指令的数目为 2 个指令
    finish                          继续执行至当前函数结束后,停止于其调用点
    until *0x7b224            继续执行至特定地址*0x7b224
    jump *0x3baac           跳转至特定地址*0x3baac 执行


⑥ gdb 调试记录的命令
    例子:
    set logging file ./log1.txt      设定记录档
    set logging on                     开始记录
    set logging off                     停止记录


⑦ 学习别人修改程序的方法 
看别人修改程序是最好的学习方法,只要你有原版本及修改后的版本,就可以知道修改的地址及方法
例如: 




解压后将两个 ipa 文件,用 winscp 传到iPhone 路径 /var/root/flower 内

在 PuTTY / Terminal 连接iPhone / iPod Touch后 

输入

  1. cd /var/root/flower 

复制代码

解压原游戏版本程序 
在 PuTTY / Terminal 输入

  1. unzip *-v1.0.ipa 

  2. mv Payload/FlowerChainCN.app/FlowerChainCN FlowerChainCN.original 

复制代码

删除不需要的的路径及档案 
在 PuTTY / Terminal 输入

  1. rm -fr Payload/ iTunesArtwork *.ipa 

复制代码

解压不死作弊修改版程序 
在 PuTTY / Terminal 输入

  1. unzip *-v1.0.ipod4g.ipa 

  2. mv Payload/FlowerChainCN.app/FlowerChainCN FlowerChainCN.patched 

复制代码

删除不需要的的路径及档案 
在 PuTTY / Terminal 输入

  1. rm -fr Payload/ iTunesArtwork *.ipa 

复制代码

反汇编原游戏程式及保存反汇编文本文件为 FlowerChainCN.original.txt 
在 PuTTY / Terminal 输入

  1. otool -tv FlowerChainCN.original &gt; FlowerChainCN.original.txt 

复制代码

反汇编不死作弊修改版程式及保存反汇编文本文件为 FlowerChainCN.patched.txt
在 PuTTY / Terminal 输入

  1. otool -tv FlowerChainCN.patched &gt; FlowerChainCN.patched.txt 

复制代码

比较两个版本及找出差异 
在 PuTTY / Terminal 输入

  1. diff FlowerChainCN.original.txt FlowerChainCN.patched.txt 

复制代码

得到

  1. < FlowerChainCN.original: 

  2. --- 

  3. > FlowerChainCN.patched: 

  4. 3060c3060 

  5. < 00004ee8 e1520003 cmp r2, r3 

  6. --- 

  7. > 00004ee8 e3520001 cmp r2, #1 ; 0x1 

复制代码

原版本列在左边及把差异列在右边并输出差异文本保存为 FlowerChainCN.diff.txt
在 PuTTY / Terminal 输入

  1. diff -y --left-column FlowerChainCN.original.txt FlowerChainCN.patched.txt &gt; FlowerChainCN.diff.txt 

复制代码

用 less 工具打开差异文本 FlowerChainCN.diff.txt
在 PuTTY / Terminal 输入

  1. less FlowerChainCN.diff.txt 

复制代码

在 less 工具内搜寻差异分隔字符 |
在 less 工具内输入

  1. /\| 

复制代码

得到下面差异的显示去做进一步分析

  1. 00004ee8 e1520003 cmp r2, r3 | 00004ee8 e3520001 cmp r2, #1 ; 0x1

复制代码




在 PuTTY / Terminal 输入这句也可看到原版本上下的代码

  1. grep -C5 &#39;|&#39; FlowerChainCN.diff.txt

复制代码

  1. grep -C5 00004ee8  FlowerChainCN.original.txt

复制代码

⑧ 最后送上我自购破解的一个很实用的iPhone小工具 - 64位计算器
这小工具除了可以做64位的计算外,还可以输入文字及显示Unicode的代码


64 Bit Calculator v1.8 更新 (iPhone、iPod touch、iPad 兼容, iOS 4 / iOS 5), 支持 Retina iPad
 64BitCalc-v1.8_ipod4g.ipa (5.69 MB, 下载次数: 161)    

64 Bit Calculator v1.7 更新 (iPhone、iPod touch、iPad 兼容, iOS 4 / iOS 5)
 64BitCalc-v1.7.ipa (3.47 MB, 下载次数: 113) 


64 Bit Calculator v1.2 (iPhone)
 64_Bit_Calc-v1.2.ipod4g.ipa (788 KB, 下载次数: 324) 




64 Bit Calculator v1.2 (iPad)    64_Bit_Calc_iPad-v1.2.ipa (1.49 MB, 下载次数: 628) 






最好的源代码编辑器
Textastic for iPad v4.1  (iPad 兼容, 要求 iOS 5.0):  Textastic_iPad_v4.1_ipod4g.ipa (5.17 MB, 下载次数: 45)    

Textastic for iPhone v4.2  (iPhone, iPod Touch 兼容, 要求 iOS 5.1): Textastic_iPhone_v4.2_ipod4g.ipa (6.87 MB, 下载次数: 67)    



关于 FinalFantasy2 1.0.4 版本 ldid 签名时出现错误信息 Segmentation fault

初代 iPhone 使用ARMv6 指令集, 直到3GS, iPad, IPhone 4设备苹果开始采用了 ARMv7 指令集

如果你输入指令

  1. otool -f FinalFantasy2

复制代码

就会看到

  1. architecture 0

  2.     cputype 12

  3.     cpusubtype 6

  4. architecture 1

  5.     cputype 12

  6.     cpusubtype 9

复制代码

你可以把 FinalFantasy2 切开为 FinalFantasy2V6

  1. lipo -thin armv6  FinalFantasy2 -output FinalFantasy2V6

  2. chmod +x FinalFantasy2V6

  3. chown mobile:mobile FinalFantasy2V6

复制代码

及切开为 FinalFantasy2V7

  1. cp -p FinalFantasy2 FinalFantasy2tmp

  2. echo -ne &quot;\x09&quot; | dd bs=1 seek=15 conv=notrunc status=noxfer of=FinalFantasy2tmp

  3. echo -ne &quot;\x06&quot; | dd bs=1 seek=35 conv=notrunc status=noxfer of=FinalFantasy2tmp

  4. lipo -thin armv6 FinalFantasy2tmp -output FinalFantasy2V7

  5. rm FinalFantasy2tmp

  6. chmod +x FinalFantasy2V7

  7. chown mobile:mobile FinalFantasy2V7

复制代码

但 iPhone 的 otool 不支持反汇编 ARMv7 指令集 (odcctools v782 的 otool 可以支持反汇编 ARMv7 指令集了), 你要用新版本的 IDA Pro /  v782 的 otool 反汇编

在 iPhone 你也許可以反汇编 FinalFantasy2V6, 修改及用 ldid 去签名

FinalFantasy2V6 签名后便可替代原版本使用, 游戏来说ARMv6 指令集也可以, 只不过在新的设备上使用时不是最优化.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值