iOS APP 反编译
原文地址?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)
輸入
cd /var/mobile/Applications/*/FinalFantasy2.app
復制代碼
(5) 到上一層路徑目錄建立?cheat?臨時工作路徑目錄及游戲程式臨時修改檔
輸入
cd ..
mkdir -p cheat
cd cheat
cp -p ../FinalFantasy2.app/FinalFantasy2 FinalFantasy2.original
復制代碼
(6) 反匯編原游戲程式
otool -tv FinalFantasy2.original > 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的相反=不執行。
例子及其注解意思
CMP R0, R1? ?? ? @寄存器數值 R0 及 R1 的比較
MOVGT R2, R0? ???@如果結果 R0 >(大于) R1,則執行MOV R2, R0即 R2=R0
MOVLE R2, R1? ???@如果結果 R0 <=(小或等于) R1,則執行MOV R2, R1即 R2=R1
復制代碼
LDR R1, [R0]? ???@意思是 R1 = *R0,從R0指向的地址處的數據載入到寄存器 R1
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 輸入
less FinalFantasy2.original.txt
復制代碼
在 less 工具內輸入
/Money
復制代碼
去開始找尋(按 N 鍵去繼續找尋),便會找到這段代碼像是要存儲金錢數據(SetMoney),0007b218是進入這段代碼的開始地址
__ZN14cFF2GlobalWork19sysGAMEPrm_SetMoneyEj:
0007b218 e59f300c ldr r3, [pc, #12] ; 0x7b22c
0007b21c e580120c str r1, [r0, #524]
0007b220 e1510003 cmp r1, r3
0007b224 8580320c strhi r3, [r0, #524]
0007b228 e12fff1e bx lr
復制代碼
首先在iPhone或iPod Touch 開始Final Fantasy 2 直至游戲已 Resume及進入游戲。
? ? ① 在PuTTY / Terminal 找FinalFantasy2 的運行中的進程編號(process id)
? ? PuTTY / Terminal 輸入
ps ax
復制代碼
得到
1115? ?????Ss? ???1:30.86 /var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/FinalFantasy2.app/FinalFantasy2
復制代碼
找到FinalFantasy2 游戲現時運行中的進程編號是?1115
? ? ② 用gdb 進入調試運行中的進程編號1115
? ? PuTTY / Terminal 輸入
gdb -p 1115
復制代碼
此時游戲會暫停,音樂也暫停
? ? ③ 用gdb 設定斷點breakpoint在十六進制地址0x7b218
? ? PuTTY / Terminal 輸入
break *0x7b218
復制代碼
④ 繼續 continue 游戲
? ? PuTTY / Terminal 輸入
c
復制代碼
⑤ 將Final Fantasy 2 游戲進入戰斗,戰勝后游戲會在十六進制地址0x7b218處停止
? ? ⑥ 暫停后,離開這分支__ZN14cFF2GlobalWork19sysGAMEPrm_SetMoneyEj
? ? PuTTY / Terminal 輸入
finish
復制代碼
⑦ 反匯編現時地址上面的代碼
disassem $pc-28 $pc
復制代碼
得到
0x0003baac <_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 180>: bl 0x78e30 <_ZN14cFF2GlobalWork8InstanceEv>
0x0003bab0 <_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 184>: mov r4, r0
0x0003bab4 <_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 188>: bl 0x78e30 <_ZN14cFF2GlobalWork8InstanceEv>
0x0003bab8 <_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 192>: bl 0x7b230 <_ZN14cFF2GlobalWork19sysGAMEPrm_GetMoneyEv>
0x0003babc <_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 196>: add r1, r0, r5
0x0003bac0 <_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 200>: mov r0, r4
0x0003bac4 <_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG 204>: bl 0x7b218 <_ZN14cFF2GlobalWork19sysGAMEPrm_SetMoneyEj>
復制代碼
這時會發現在_ZN14cFF2GlobalWork19sysGAMEPrm_GetMoneyEv
及_ZN14cFF2GlobalWork19sysGAMEPrm_SetMoneyEj
中間0x0003babc?地址的代碼add r1, r0, r5 是最可疑的
? ? ⑧ 取消斷點1及設定新斷點breakpoint在十六進制地址0x0003babc?及重新繼續continue 游戲
? ? PuTTY / Terminal 輸入
disable 1
break *0x3babc
c
復制代碼
在iPhone或iPod Touch查看現時游戲的金錢例如是4888,將Final Fantasy 2 游戲進入戰斗,戰勝后游戲會新斷點2地址0x3babc處停止
? ? ⑨ 當游戲在新斷點2暫停時查看寄存器就發現 r0 是當時的金錢余額及 r5 是戰勝后得到的金錢
? ? PuTTY / Terminal 輸入
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 輸入
gdb -p 1123
復制代碼
此時游戲會暫停,音樂也暫停
? ? ③ 用 gdb 輸入這些指令包括,內存開始地址(0x800000)、結束地址(0x880000)及要搜索的數字672如下:
? ? PuTTY / Terminal 輸入
set $x=0x800000
while(*++$x!=672 && $x<0x880000)
end
復制代碼
④ 輸入 end 之后等候數十秒 ....,待gdb去搜索這段內存地址
? ? ⑤ gdb 搜索完畢后
? ? PuTTY / Terminal 輸入
p/x $x
復制代碼
得到
$1 = 0x85e28c
復制代碼
這代表 gdb 已找到在?0x85e28c?的內存地址的存儲數字是?672
? ? PuTTY / Terminal 輸入
x/dw 0x85e28c
復制代碼
得到確認?0x85e28c?的內存地址的存儲數字是?672
0x85e28c:? ? 672
復制代碼
⑥ 用 gdb 繼續搜索
? ? PuTTY / Terminal 輸入 (或按方向鍵 ↑ 4次,然后回車,免重復輸入)
while(*++$x!=672 && $x<0x880000)
end
復制代碼
再等十多秒,gdb 搜索完畢后
? ? PuTTY / Terminal 輸入
p/x $x
復制代碼
得到
$2 = 0x880000
復制代碼
這代表 gdb 已到結束的地址 0x880000,都沒有找到。這也表示數字?672?是唯一出現在?0x85e28c?要找的內存范圍內。
? ? ⑦ 用 gdb 更改內存地址?0x85e28c?的存儲數字為?1000
? ? PuTTY / Terminal 輸入
set {int}0x85e28c=1000
復制代碼
也可以用
set *0x85e28c=1000
復制代碼
PuTTY / Terminal 輸入
x/dw 0x85e28c
復制代碼
得到確認已成功更改數字
0x85e28c:? ? 1000
復制代碼
⑧ 繼續 continue 游戲
? ? PuTTY / Terminal 輸入
c
復制代碼
⑨ 在回到游戲里退出 STATUS 畫面再進入 STATUS,畫面內數據重刷后,確認已成功更改經驗值數字為1000
? ??留意:由于游戲數據在堆(heap)內存的地址不是固定的,所以每次運行的進程都要再搜索新的內存地址。另外,搜索的內存地址范圍也會改變,如果在?0x800000?至?0x880000?范圍內找不到的話,就要往后試?0x880000?至0x900000?新的范圍。
? ?? ?? ?另外:用相同搜索方法也可以找到金錢數字在這次運行進程是在內存地址?0x874c04
? ? ⑩ 找到經驗值地址后便可設置觀察點(watchpoint)于內存地址?0x85e28c
? ? 設置觀察點的目的是當內存地址值被讀或被寫時,會顯示數據及暫停程序
? ? PuTTY / Terminal 輸入
watch *0x85e28c
復制代碼
及繼續游戲
? ? PuTTY / Terminal 輸入
c
復制代碼
留意:游戲在觀察點(watchpoint) 生效下運行是非常的慢,有些游戲是不能正常運作,有時候手機也要重啟,所以下面的步驟是不一定可以進行的
? ? ? 將游戲進入戰斗打怪后程序便會暫停在?0x9f508?地址,gdb 會顯示
Hardware watchpoint 1: *8774284
Old value = 1000
New value = 1086
0x0009f508 in CMvPlayer::CheckLevelUp ()
復制代碼
PuTTY / Terminal 輸入
x/14i $pc-16
復制代碼
得到
0x9f4f8 <_ZN9CMvPlayer12CheckLevelUpEj+60>:? ? b.n? ? 0x9f508 <_ZN9CMvPlayer12CheckLevelUpEj+76>
0x9f4fa <_ZN9CMvPlayer12CheckLevelUpEj+62>:? ? adds? ? r0, r4, #0
0x9f4fc <_ZN9CMvPlayer12CheckLevelUpEj+64>:? ? movs? ? r1, #1
0x9f4fe <_ZN9CMvPlayer12CheckLevelUpEj+66>:? ? movs? ? r2, #0
0x9f500 <_ZN9CMvPlayer12CheckLevelUpEj+68>:? ? subs? ? r5, r5, r3
0x9f502 <_ZN9CMvPlayer12CheckLevelUpEj+70>:? ? bl? ? 0x9f338 <_ZN9CMvPlayer9OnLevelUpEii>
0x9f506 <_ZN9CMvPlayer12CheckLevelUpEj+74>:? ? movs? ? r3, #1
0x9f508 <_ZN9CMvPlayer12CheckLevelUpEj+76>:? ? str? ? r5, [r4, r6]
0x9f50a <_ZN9CMvPlayer12CheckLevelUpEj+78>:? ? cmp? ? r3, #0
0x9f50c <_ZN9CMvPlayer12CheckLevelUpEj+80>:? ? beq.n? ? 0x9f516 <_ZN9CMvPlayer12CheckLevelUpEj+90>
0x9f50e <_ZN9CMvPlayer12CheckLevelUpEj+82>:? ? cmp? ? r5, #0
0x9f510 <_ZN9CMvPlayer12CheckLevelUpEj+84>:? ? beq.n? ? 0x9f516 <_ZN9CMvPlayer12CheckLevelUpEj+90>
0x9f512 <_ZN9CMvPlayer12CheckLevelUpEj+86>:? ? movs? ? r5, #0
0x9f514 <_ZN9CMvPlayer12CheckLevelUpEj+88>:? ? b.n? ? 0x9f4c6 <_ZN9CMvPlayer12CheckLevelUpEj+10>
復制代碼
PuTTY / Terminal 輸入
i r $r5 $r4 $r6 $pc
p/x $r4+$r6
復制代碼
得到
r5? ?? ?? ?? ? 0x43E? ? 1086
r4? ?? ?? ?? ? 0x85DC00? ? 8772608
r6? ?? ?? ?? ? 0x68c? ? 1676
pc? ?? ?? ?? ? 0x9f508? ? 652552
$5 = 0x85e28c
復制代碼
這時確認了?0x9f508?地址這句代碼
? ? str? ? r5, [r4, r6]
? ? 的意思是,r4 + r6 =?0x85e28c?,把寄存器 r5 內的數字(1086) 寫到?0x85e28c?的地址
? ? 程序因要寫進這0x85e28c?的地址,所以暫停了,這就是觀察點(watchpoint) 的強大功能。
? ? PuTTY / Terminal 輸入
bt
復制代碼
得到
#0??0x0009f508 in CMvPlayer::CheckLevelUp ()
#1??0x0009ff2e in CMvPlayer::DoUpdate ()
#2??0x00094744 in CMvObject::Update ()
#3??0x000969cc in CMvObjectMgr::Update ()
#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
0003bab8? ?? ???eb00fddc? ?? ???bl 0x7b230
0003babc? ?? ???e0801005? ?? ???add r1, r0, r5? ?@意思是 r1 = r0 +r5 ; r0 是當時的金錢余額; r5 是戰勝后得到的金錢
0003bac0? ?? ???e1a00004? ?? ???mov r0, r4
0003bac4? ?? ???eb00fdd3? ?? ???bl 0x7b218? ???@分支到函數名 __ZN14cFF2GlobalWork19sysGAMEPrm_SetMoneyEj 去更新金錢余額
復制代碼
(9) 修改目標 : 將所得金錢乘大32倍
0003babc的應修改目標代碼是
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 如下
? ? .file "armtest.s"
? ? .globl _main
? ? .code 32
_main:
? ? add r1, r0, r5
? ? 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 如下
? ? .code 16
? ? .thumb_func _main
復制代碼
匯編 arm 輸入
as armtest.s -o armtest.o ; otool -tv armtest.o
復制代碼
便看到
(__TEXT,__text) section
_main:
00000000? ? e0801005? ? add r1, r0, r5
00000004? ? e0801285? ? add r1, r0, r5, lsl #5
復制代碼
及得到add r1, r0, r5, lsl #5 目標ARM指令代碼為?e0801285
(11) 建立修改程式第一版FinalFantasy2.v1及用十六進制修改器修改代碼
輸入
cp -p FinalFantasy2.original FinalFantasy2.v1? ?? ?
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
輸入
otool -tv FinalFantasy2.v1 > FinalFantasy2.v1.txt
diff FinalFantasy2.original.txt FinalFantasy2.v1.txt
復制代碼
也可以用 otool -otV
得到
< FinalFantasy2.original:
---
> FinalFantasy2.v1:
59597c59597
< 0003babc? ? e0801005? ? add? ? r1, r0, r5
---
> 0003babc? ? e0801285? ? add? ? r1, r0, r5, lsl #5
復制代碼
(13) 對修改程式第一版重新簽名
輸入
ldid -s FinalFantasy2.v1
復制代碼
(14) 將簽名后的程式放回程式路徑進行測試
首先備份原程式(留意:要用mv移動不要用cp)
輸入
mv ../FinalFantasy2.app/FinalFantasy2 ../FinalFantasy2.app/FinalFantasy2.bak
復制代碼
安裝修改后的程式及更新權限
輸入
cp -p FinalFantasy2.v1 ../FinalFantasy2.app/FinalFantasy2
chown mobile:mobile ../FinalFantasy2.app/FinalFantasy2
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 輸入
ps ax
復制代碼
得到
1115? ?????Ss? ???1:30.86 /var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/FinalFantasy2.app/FinalFantasy2
復制代碼
找到 FinalFantasy2 游戲現時運行中的進程編號是?1115
② 用 gdb 進入調試運行中的進程編號 1115
PuTTY / Terminal 輸入
gdb -p 1115
復制代碼
此時游戲會暫停,音樂也暫停
③ 用 gdb 設定斷點breakpoint在十六進制地址?0x3babc?(即在第8步時找到的位置0003babc)
PuTTY / Terminal 輸入
break *0x3babc
復制代碼
④ 繼續 continue 游戲
PuTTY / Terminal 輸入
c
復制代碼
⑤ 將Final Fantasy 2 游戲進入戰斗,戰勝后游戲會在十六進制地址?0x3babc處停止
⑥ 暫停后,查看 CPU 寄存器 register (info register 指令)
PuTTY / Terminal 輸入
i r $r0 $r1 $r5 $pc
復制代碼
得到
r0? ?? ?? ?? ? 0x1c37? ? 7223
r1? ?? ?? ?? ? 0x25? ? 37
r5? ?? ?? ?? ? 0x25? ? 37
pc? ?? ?? ?? ? 0x3babc? ? 244412
復制代碼
印證了 r0=7223 是現時的金錢
游戲暫停在 pc=0x3babc
⑦ 查看下一步將要運行的反匯編指令
PuTTY / Terminal 輸入
x/i $pc
復制代碼
得到?add r1, r0, r5, lsl #5,印證成功修改指令
0x3babc <_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG+196>:? ? add? ? r1, r0, r5, lsl #5
復制代碼
⑧ 運行下一步 stepi 指令
PuTTY / Terminal 輸入
si
復制代碼
查看 CPU 寄存器 register (info register 指令)
PuTTY / Terminal 輸入
i r $r0 $r1 $r5 $pc
復制代碼
得到
r0? ?? ?? ?? ? 0x1c37? ? 7223
r1? ?? ?? ?? ? 0x20d7? ? 8407
r5? ?? ?? ?? ? 0x25? ? 37
pc? ?? ?? ?? ? 0x3bac0? ? 244416
復制代碼
此時印證了 r1 = r0 +( r5 x 32)
? ?? ?? ?? ?= 7223 + (27 x 32)
? ?? ?? ?? ?=?8407
查看下一步將要運行的反匯編指令
putty / Terminal 輸入
x/i $pc
復制代碼
得到
0x3bac0 <_ZN10FF2cBattle12SENRIHIN_CHKEP12thBATMonsterP6X86REG+200>:? ? mov? ? r0, r4
復制代碼
⑨ 繼續 continue 游戲
PuTTY / Terminal 輸入
c
復制代碼
⑩ Final Fantasy 2 游戲顯示戰勝后得到37的金錢,但實際金錢余額是?8407,印證修改游戲已成功。
? 離開 gdb
按下Ctrl+C 組合鍵停止執行進程
PuTTY / Terminal 輸入
quit
復制代碼
及按?y?鍵確認離開 gdb
留意:在上面第⑥步暫停時,你可以輸入指令去更改CPU 寄存器 register
例如輸入
set $r5=1000
去試試增加金錢數目
(16) 假設已調試完成,便可將修改后的程式打包發布
進入游戲路徑目錄內,輸入
cd /var/mobile/Applications/*/FinalFantasy2.app
復制代碼
到上一層路徑目錄
cd ..
復制代碼
建立 IPA 所要的路徑及檔案及刪除不需要的備份檔案
rm -fr Payload
mkdir -p Payload
cp -pr FinalFantasy2.app Payload/
rm -fr Payload/FinalFantasy2.app/FinalFantasy2*.bak
復制代碼
打包 ipa 為 FinalFantasy2_v1.ipod4g.ipa
zip -r FinalFantasy2_v1.ipod4g.ipa Payload iTunesArtwork
復制代碼
找現時的路徑
pwd
復制代碼
得到
/var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
復制代碼
用 winscp 或Terminal 的 scp 指令傳送這檔作發布
/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) 內容為
define ascii_char
set $_c=*(unsigned char *)($arg0)
if ( $_c < 0x20 || $_c > 0x7E )
printf '.'
else
printf '%c', $_c
end
end
document ascii_char
Print the ASCII value of arg0 or '.' if value is unprintable
end
define hex_quad
printf '%02X %02X %02X %02X??%02X %02X %02X %02X',??\
*(unsigned char*)($arg0), *(unsigned char*)($arg0 + 1),??\
*(unsigned char*)($arg0 + 2), *(unsigned char*)($arg0 + 3), \
*(unsigned char*)($arg0 + 4), *(unsigned char*)($arg0 + 5), \
*(unsigned char*)($arg0 + 6), *(unsigned char*)($arg0 + 7)
end
document hex_quad
Print eight hexadecimal bytes starting at arg0
end
define hexdump
printf '%08X : ', $arg0
hex_quad $arg0
printf ' - '
hex_quad ($arg0+8)
printf ' '
ascii_char ($arg0)
ascii_char ($arg0+1)
ascii_char ($arg0+2)
ascii_char ($arg0+3)
ascii_char ($arg0+4)
ascii_char ($arg0+5)
ascii_char ($arg0+6)
ascii_char ($arg0+7)
ascii_char ($arg0+8)
ascii_char ($arg0+9)
ascii_char ($arg0+0xA)
ascii_char ($arg0+0xB)
ascii_char ($arg0+0xC)
ascii_char ($arg0+0xD)
ascii_char ($arg0+0xE)
ascii_char ($arg0+0xF)
printf '\n'
end
document hexdump
Display a 16-byte hex/ASCII dump of arg0
end
define hexdump1
hexdump $arg0
x/8h $arg0
printf '\n'
disassem $arg0 $arg0+16
printf '\n'
end
document hexdump1
Display a 16-byte hex/ASCII dump and disassembly of arg0
end
復制代碼
在用 gdb 調試時輸入
hexdump1 $pc
復制代碼
便可列出$pc位置后十六位的內容及反匯編的代碼
③ 在斷點設定一些要自動運行的指令
下面的意思是建立斷點1
及在斷點1停止時運行查看一些暫存器(i r $r0 $r1 $r5 $pc)及反匯編下四個指令代碼(x/4i $pc)
break *0x3babc
commands 1
i r $r0 $r1 $r5 $pc
x/4i $pc
end
復制代碼
④ 在 gdb 斷點暫停時,是可改變內存及指令
FinalFantasy2 的例子,0x0003babc地址的指令是
輸入
x/i 0x0003babc
復制代碼
得到代碼是
add r1, r0, r5
復制代碼
輸入
x/xw 0x0003babc
復制代碼
得到代碼數值是
0xe0801005
復制代碼
改變指令代碼數值輸入
set {int}0x0003babc = 0xe0801285
復制代碼
檢查改變后的指令輸入
x/i 0x0003babc
復制代碼
得到改變后的指令代碼是
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后?
輸入
cd /var/root/flower?
復制代碼
解壓原游戲版本程序?
在 PuTTY / Terminal 輸入
unzip *-v1.0.ipa?
mv Payload/FlowerChainCN.app/FlowerChainCN FlowerChainCN.original?
復制代碼
刪除不需要的的路徑及檔案?
在 PuTTY / Terminal 輸入
rm -fr Payload/ iTunesArtwork *.ipa?
復制代碼
解壓不死作弊修改版程序?
在 PuTTY / Terminal 輸入
unzip *-v1.0.ipod4g.ipa?
mv Payload/FlowerChainCN.app/FlowerChainCN FlowerChainCN.patched?
復制代碼
刪除不需要的的路徑及檔案?
在 PuTTY / Terminal 輸入
rm -fr Payload/ iTunesArtwork *.ipa?
復制代碼
反匯編原游戲程式及保存反匯編文本文件為 FlowerChainCN.original.txt?
在 PuTTY / Terminal 輸入
otool -tv FlowerChainCN.original > FlowerChainCN.original.txt?
復制代碼
反匯編不死作弊修改版程式及保存反匯編文本文件為 FlowerChainCN.patched.txt
在 PuTTY / Terminal 輸入
otool -tv FlowerChainCN.patched > FlowerChainCN.patched.txt?
復制代碼
比較兩個版本及找出差異?
在 PuTTY / Terminal 輸入
diff FlowerChainCN.original.txt FlowerChainCN.patched.txt?
復制代碼
得到
< FlowerChainCN.original:?
---?
> FlowerChainCN.patched:?
3060c3060?
< 00004ee8 e1520003 cmp r2, r3?
---?
> 00004ee8 e3520001 cmp r2, #1 ; 0x1?
復制代碼
原版本列在左邊及把差異列在右邊并輸出差異文本保存為 FlowerChainCN.diff.txt
在 PuTTY / Terminal 輸入
diff -y --left-column FlowerChainCN.original.txt FlowerChainCN.patched.txt > FlowerChainCN.diff.txt?
復制代碼
用 less 工具打開差異文本 FlowerChainCN.diff.txt
在 PuTTY / Terminal 輸入
less FlowerChainCN.diff.txt?
復制代碼
在 less 工具內搜尋差異分隔字符?|
在 less 工具內輸入
/\|?
復制代碼
得到下面差異的顯示去做進一步分析
00004ee8 e1520003 cmp r2, r3 | 00004ee8 e3520001 cmp r2, #1 ; 0x1
復制代碼
在 PuTTY / Terminal 輸入這句也可看到原版本上下的代碼
grep -C5 '|' FlowerChainCN.diff.txt
復制代碼
或
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 指令集
如果你輸入指令
otool -f FinalFantasy2
復制代碼
就會看到
architecture 0
? ? cputype 12
? ? cpusubtype 6
architecture 1
? ? cputype 12
? ? cpusubtype 9
復制代碼
你可以把 FinalFantasy2 切開為 FinalFantasy2V6
lipo -thin armv6??FinalFantasy2 -output FinalFantasy2V6
chmod +x FinalFantasy2V6
chown mobile:mobile FinalFantasy2V6
復制代碼
及切開為 FinalFantasy2V7
cp -p FinalFantasy2 FinalFantasy2tmp
echo -ne "\x09" | dd bs=1 seek=15 conv=notrunc status=noxfer of=FinalFantasy2tmp
echo -ne "\x06" | dd bs=1 seek=35 conv=notrunc status=noxfer of=FinalFantasy2tmp
lipo -thin armv6 FinalFantasy2tmp -output FinalFantasy2V7
rm FinalFantasy2tmp
chmod +x FinalFantasy2V7
chown mobile:mobile FinalFantasy2V7
復制代碼
但 iPhone 的 otool 不支持反匯編 ARMv7 指令集 (odcctools v782 的 otool 可以支持反匯編 ARMv7 指令集了), 你要用新版本的 IDA Pro /??v782 的 otool 反匯編
在 iPhone 你也許可以反匯編 FinalFantasy2V6, 修改及用 ldid 去簽名
FinalFantasy2V6 簽名后便可替代原版本使用, 游戲來說ARMv6 指令集也可以, 只不過在新的設備上使用時不是最優化.
總結
以上是生活随笔為你收集整理的iOS APP 反编译的全部內容,希望文章能夠幫你解決所遇到的問題。