iOS逆向工程
Class Dump
安裝
class-dump是可以把OC執行時的宣告的資訊匯出來的工具,可以把未經加密的app的標頭檔案匯出來。下載原始碼解壓後,將class-dump複製到/usr/bin/class-dump
,同時開啟Terminal,賦予其執行許可權:
sudo chmod 777 /usr/bin/class-dump
說明:class-dump的物件必須是未經加密的可執行檔案,從Appstore下載的都是經過加密的,需要脫殼,最好是從越獄渠道下載app來進行dump
使用
class-dump -H xxx.app -o test
Theos
安裝
- 安裝Command Line Tools
- 安裝MacPorts軟體,從官網根據Mac本身的版本下載
- 安裝完MacPorts後開啟終端輸入
sudo port -v self update
更新MacPorts到最新版本 - 更新完MacPorts後安裝DPKG檔案,在終端輸入
sudo port -f install dpkg
- 配置環境變數,在
~./bash_profile
中加上這兩句:
export THEOS=/opt/theos
export PATH=/opt/theos/bin/:$PATH
- 在
/opt/theos
路徑下載安裝sudo git clone --recursive https://github.com/theos/theos.git
sudo git clone -b stableversion https://github.com/haorenqq/theos/ $THEOS
- 下載ldid工具到THEOS的bin目錄下
- 在終端執行如下語句:
git clone git://git.saurik.com/ldid.gitcd ldidgit submodule update --init./make.shcp -f ./ldid $THEOS/bin/ldid
- 下載附件解壓,將附件中的openssl 資料夾放到 ldid 資料夾下
- 將附件的make.sh放入ldid資料夾下替換同名檔案
- 開啟附件裡面的Specifications資料夾,裡面應該有8個檔案
- iPhoneOS開頭的四個檔案放到下面的目錄下(如果沒有,請自己建立一個)
/應用程式/Xcode/Content/Developer/Platforms/IphoneOS.platform/Developer/Library/Xcode/Specifications
- iPhone Simulator 開頭的另外四個檔案放入下面的目錄下(如果沒有,請同樣建立一個)。
/應用程式/Xcode/Content/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications
- 之後在下面的目錄下建立usr資料夾,usr資料夾下再建立一個名為bin的資料夾
/應用程式/Xcode/Content/Developer/Platforms/iPhoneSimulator.platform/Developer/
之後的目錄應該是/應用程式/Xcode/Content/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin
iOS OpenDev
安裝
如果還是遇到安裝失敗,但是在/opt下面還是建立了三個目錄:
- iosopendev
- iosopendevsetup
- iosopendevuninstall
在iosopendevsetup/bin
裡面已經有一個shell指令碼:iod-setup
。安裝的過程就是執行iod-setup。
直接執行:sudo ./iod-setup base
發現總是在下載某個東西時失敗,sublime iod-setup
來定位,發現有三個downloadGithubTarball的地方,直接註釋掉,然後手動去下載這三個東西,並拷貝到iosopendev目錄。手動下載:
https://github.com/kokoabim/iOSOpenDev
https://github.com/kokoabim/iOSOpenDev-Xcode-Templates
https://github.com/kokoabim/iOSOpenDev-Framework-Header-Files
拷貝:
sudo cp -r iosopendev-master/* /opt/iosopendev/
(iosopendev裡,sudo mkdir templates)
sudo cp -r iosopendev-xcode-templates-master/* /opt/iosopendev/templates
(iosopendev裡,sudo mkdir frameworks)
sudo cp -r iosopendev-framework-header-files-master/* /opt/iosopendev/frameworks
再次安裝:sudo ./iod-setup base
指定最新xcode sdk:sudo ./iod-setup sdk -sdk iphoneos
成功,表現為:
-
~/library/developer/xcode
裡面會多出Templates/iosopendev
-
sublime ~/.bash_profile
會看到:
export iOSOpenDevPath=/opt/iOSOpenDev
export iOSOpenDevDevice=
export PATH=/opt/iOSOpenDev/bin:$PATH
-
啟動xcode,新建工程,多出一個“iOSOpenDev”的模板。
在終端執行~/.bash_profile
, ~/.bash_login
or ~/.profile
這3個檔案你在你電腦中看是否能找到,我是找到~/.bash_profile
這個檔案,然後設定下面的環境變數
export iOSOpenDevPath=/opt/iOSOpenDev
export iOSOpenDevDevice=
非固定值,使用者需要先在已經越獄的iphone上點選設定-網路-檢視當前網路的IP地址,填入
export PATH=/opt/iOSOpenDev:$PATH
export PATH=/opt/local/bin:$PATH
export PATH=/opt/local/sbin:$PATH
在裝置上安裝OpenSSH並且在裝置上新增SSH簽名:
- 在Cydia裡搜尋OpenSSH安裝,建議更改SSH的預設密碼,預設密碼是:alpine。更改方法是在Mac上登陸裝置的SSH.命令
ssh root@<裝置IP>
,登陸後輸入命令passwd root
,輸入新密碼。
接下來給SSH新增簽名:
- 在
iOSOpenDev/bin/
資料夾下執行:./iosod sshkey -h <裝置IP>
中間問你是否繼續,當然yes,詢問密碼預設是alpine。如果期間失敗了重新試下,可能是裝置螢幕關閉會斷網,這樣就不用密碼也可以登陸裝置SSH了。
使用
使用Logos tweak工程模板建立工程,接著在Build Settings
中iOSOpenDevDevice設定為自己裝置的IP地址,裝置與你的Mac要在一個區域網內。
為了方便的除錯,還要在工程裡設定一些引數。這裡介紹下這些引數的意義,首先開啟程式設定TARGETS裡的工程:
- iOSOpenDevCopyOnBuild 布林值YES/NO 預設是NO:是否把生成的可執行檔案拷貝到
/var/root/iOSOpenDevBuilds/[project name]/[executable name]
路徑下,是為了方便那些遠端SSH控制的程式,可能暫時用不到 - iOSOpenDevDevice 設定你裝置的IP
- iOSOpenDevInstallOnProfiling 布林值 預設為YES,是否在build for profiling的時候直接遠端安裝到裝置上
- iOSOpenDevPath 不要修改此項,是iOSOpenDev的安裝路徑
- iOSOpenDevRespringOnInstall 布林值 預設為YES,是否在安裝後重啟SpringBoard
由於我們需要引用標頭檔案,所以還需要在Build Settings
中將Header Search Paths
中加一行/opt/theos/include
到TARGETS > Build Phases > Link Binary With Libraries
新增檔案/opt/iOSOpenDev/lib/libsubstrate.dylib
下面我們實現hook SpringBoard,當SPringBoard啟動的時候,我們就彈出一個Alert。
在.xm中加以下程式碼:
#import <SpringBoard/SpringBoard.h>
%hook SpringBoard
- (void)applicationDidFinishLaunching:(id)application {
%orig;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Welcome" message:@"Welcome to your iPhone!" delegate:nil cancelButtonTitle:@"Thanks" otherButtonTitles:nil];
[alert show];
[alert release];
}
%end
由於用到了UIAlertView屬於UIKit的東西,所以我們要新增連結庫UIKit.framework。
編譯的時候不能像正常的App點Run,點選Product->Build For->Build For Profiling
或者Command+Shift+i
,配置好裝置IP,程式會自動安裝到裝置裡,SpringBoard會重啟,重啟後應該就能看到Alert了。
-
如果遇到
CodeSign error: code signing is required for product type ‘Dynamic Library’ in SDK ‘iOS xx’
錯誤
看提示是跟簽名有關,找到工程的Code Signing Identity 專案,選擇Don’t Code Sign,用Xcode開啟/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Specifications/iPhoneOSProductTypes.xcspec
檔案,看到一項CODE_SIGNING_ALLOWED
,在com.apple.package-type.static-library.static
項中是NO,而在com.apple.package-type.static-library.dynamic
項中是YES。修改成NO,再次重啟,編譯成功。
Reveal
安裝
破解
- 輸入
rm ~/Library/Preferences/com.ittybittyapps.Reveal.plist
- 重啟電腦
這並不是完全破解,而是一直迴圈30天試用
整合
把Reveal整合到專案裡有兩種方式:
- 新增Reveal的framework到工程裡(不推薦)
- 啟動
Reveal --> Help --> Show Reveal Library in Finder
,拖動新增Reveal.framework
到工程中。選中Copy items into destination group's folder (if needed)
以及當前的targets - 確保
Summary--> Linked Frameworks and Libraries
目錄下,包含以下三個framework:Reveal.FrameworkCFNetwork.frameworkQuartzCore.frameworkCoreGraphics.framework
- TARGETS中設定命令
TARGETS --> Settings --> Other Linker Flags -->
新增命令-ObjC
- 執行程式,切換到Reveal,左上部分下拉框選擇當前執行的程式就可以操作了
- 用LLDB命令(推薦)
- 開啟終端,在終端裡輸入
touch ~/.lldbinit
命令來進行建立 - 然後在輸入
open ~/.lldbinit
命令,以文字編輯器開啟此檔案 - 把如下字元複製到文字編輯器裡:
command alias zxp_reveal_load_sim expr (Class)NSClassFromString(@"IBARevealLoader") == nil ? (void *)dlopen("/Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/libReveal.dylib", 0x2) : ((void*)0)
command alias zxp_reveal_start expr (void)[(NSNotificationCenter*)[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStart" object:nil];
command alias 其格式為:command alias 別名 LLDB命令,因此如上zxp_reveal_start和zxp_reveal_load_sim就是我設定的別名,也可以替換成自己喜歡的名字
- 然後執行專案,暫停app,這時候輸入
zxp_reveal_load_sim
,然後再輸入zxp_reveal_start
,即可在Reveal裡審查你的UI元素了 - 兩條命令順利的話,控制檯則會列印
INFO: Reveal Server started (Protocol Version 25).
這條資訊,如果最後未能正常輸出,那就要好好檢查一下第一條命令裡的dlopen裡包含的路徑是否正確了
MesaSQLite
安裝
OpenSSH
越獄安裝源:Cydia/Telesphoreo (http://apt.saurik.com)
SSH服務,就能使用ssh和scp命令來實現遠端登入和遠端複製檔案功能ssh root@192.168.2.50
scp xxx.deb root@192.168.2.50:/var/root
OpenSSH預設密碼是alphine,安裝後建議立即修改登入密碼,需要修改的賬號有2個:root和mobilessh root@192.168.2.50
passwd
syslogd
越獄安裝源:syslogd (http://apt.saurik.com)
syslogd是用於記錄類UNIX中系統日誌 的守護程式,我們可以通過/var/log/syslog/
看到對應的log輸出
安裝完成後重啟手機
執行tail命令(需要安裝Core Utilities源),終端上執行的Log就會列印實時出來了tail -f /var/log/syslog
例如在hook程式碼中列印NSLog
%hook SBScreenShotter
-(void)saveScreenshot:(BOOL)screenshot {
%orig;
NSLog(@"hello: saveScreenshot: is called");
}
%end
Filter設定成com.apple.springboard,安裝並執行裝置,ssh連上終端後輸入下面命令,在截圖之後就能看見對應的日誌了grep hello /var/log/syslog
GDB
越獄安裝源:radare (http://cydia.radare.org/)
全名The GNU Project Debugger,類UNIX作業系統中最強大的動態除錯工具之一
gdbinit是GDB的初始化甲苯,在GDB啟動過程中執行,對GDB有一定優化作用。下載之後,解壓得到gdbinit複製到iOS的/var/root目錄下,並重新命名為.gdbinit即可:scp /Users/Downloads/Gdbinit-master/gdbinit root@192.168.2.50:/var/root/.gdbinit
除錯
通過ssh方式登入遠端手機ssh root@192.168.2.50
使用gdb開啟除錯gdb
gdb注入程式attach PID
或者attach ProcessName
例如attach SpringBoard
,命令完成後,程式停止,等待我們輸入進一步命令。
注意:所有GDB命令涉及的正確地址必須來自本機二進位制檔案,可以通過dyld_decache獲得,從SDK中的到的二進位制檔案與本機通常不同
常用GDB命令:
-
b
break 設定斷點b function
在函式起始位置設定斷點
例如:b object_getClass
-
b *address
在記憶體地址設定斷點
例如:b *(0x59000 + 0x00009218)
同一程式在每次啟動時在記憶體中的位置都會發生一定偏移某行程式碼地址 = ASLR造成的偏移 + 本行程式碼在檔案中的地址
ASLR可以通過
info sh
或info share
檢視,offset標註了此二進位制檔案在記憶體中的ASLR偏移。
目的碼在檔案中的地址可以通過IDA得到。 info b
檢視斷點資訊disable breakpointNumber
禁用某個斷點enable breakpointNumber
啟用某個斷點delete breakpointNumber
刪除某個斷點
ni
nexti 執行下一條指令,不進入函式體si
stepi 執行下一條指令,進入函式體-
p
print 列印-
p $r0
列印暫存器r0中的值
-
pt
ptype 列印某處的資料型別(無法列印Object-C型別)po
print-object 列印Object-C型別x
examine 列印指標指向的資料的值-
set
設定某個值set $r0 = 0x1
** IDA宜靜,GDB宜動 **
LLDB
因為Apple已經棄gdb投lldb,所以很多gdb的指令已經不再適用,我們需要配置lldb來進行除錯
- 配置debugserver
- 在iOS中安裝debugserver
debugserver執行在iOS上,顧名思義,它作為服務端,實際執行LLDB(作為客戶端)傳過來的命令,再把執行結果反饋給LLDB,顯示給使用者,即所謂的“遠端除錯”。在預設情況下,iOS上並沒有安裝debugserver,只有在裝置連線過一次Xcode,並在Window→Devices
選單中新增此裝置後,debugserver才會被Xcode安裝到iOS的/Developer/usr/bin/
目錄下。 - 拷貝debugserver到本機
scp root@iOSIP:/Developer/usr/bin/debugserver ~/debugserver
- 給debugserver新增task_for_pid許可權,下載ent.xml到OSX的
/Users/
目錄,然後執行:/opt/theos/bin/ldid -Sent.xml debugserver
注意,此處-S
選項與ent.xml
之間是沒有空格的
正常情況下,上面這條命令會在5秒內執行完畢。如果ldid卡住了,執行超時,就換一種方案:下載ent.plist到/Users/
,然後執行:codesign -s - --entitlements ent.plist -f debugserver
- 將經過處理的debugserver拷回iOS
scp ~/debugserver root@iOSIP:/usr/bin/debugserver
ssh root@iOSIP
root# chmod +x /usr/bin/debugserver
這裡之所以把處理過的debugserver存放在iOS的/usr/bin/
下,而沒有覆蓋/Developer/usr/bin/
下的原版debugserver,一是因為原版debugserver是不可寫的,無法覆蓋;二是因為/usr/bin/
下的命令無須輸入全路徑就可以執行,即在任意目錄下執行debugserver
都可啟動處理過的debugserver。 - 在iOS上用debugserver來attach程式
debugserver *:1234 -a "SpringBoard"
成功後會顯示: - 在OSX上用lldb遠端除錯
首先在Terminal中執行lldb,然後輸入以下命令:process connect connect://iOSIP:1234
注意,這條命令執行耗時比較長
執行成功後會顯示: - 獲取ASLR的offset
image list -o -f
其中第一列[X]是image的序號,不用管;第二列是ASLR的offset(也就是對應image的虛擬記憶體slide);第三列是image的全路徑和slide之後的基地址,也不用管~所以第二列就是我們需要的資訊。
更多LLDB指令,參考GDB和LLDB指令對照表
Cycript
越獄安裝源:Cydia/Telesphoreo (http://apt.saurik.com/)
可以寫App的指令碼語言,測試函式功能
ssh root@192.168.2.50
cycript
出現 cy#
提示符,說明成功啟動Cycriptctrl+D
退出Cycript
程式注入方式呼叫Cycript測試函式:
- 找到程式名或PID,例如如下SpringBoard程式PID是597
ps ax | grep SpringBoard
- 接下來輸入
cycript -p 597
或cycript -p SpringBoard
,把Cycript鉤到SpringBoard上,這時Cycript就已經執行在SpringBoard程式裡了。 - 開始測試,cy語句不以引號作為結尾,所以每次只能輸入一條語句
cy# var alertView = [[UIAlertView alloc] initWithTitle:@"iOSRE" message:@"test" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]
cy# [alertView show]
cy# [alertView release]
執行上面語句後,SpringBoard就會彈出對話方塊了
- 測試截圖程式碼
cycript -p SpringBoard
var shotter = [SBScreenShotter sharedInstance]
[shotter saveScreenshot:YES]
- 彩色閃屏程式碼
cycript -p SpringBoard
var flash = [SBScreenFlash mainScreenFlasher]
var color = [UIColor magentaColor]
[flash flashColor:color withCompletion:nil]
ARM彙編
OC/C/C++ 操作物件:變數
ARM彙編 操作物件:暫存器、記憶體、棧暫存器是CPU的變數,記憶體是更多的變數,效能差於暫存器,前兩者是全域性變數,棧是本地變數
- 資料操作指令
op{cond}{s} Rd, Rn, Op2
- 記憶體操作指令
op{cond}{type} Rd, {Rn, Op2}
基礎指令:- LDR:將資料從記憶體讀出,存到暫存器
- STR:將資料從暫存器讀出,存到記憶體
- 分支指令
- 無條件分支
- 條件分支
ARM呼叫規則
- 前言 prologs
- LR入棧
- R7入棧
- R7 = SP
- 將需保留的暫存器原始值入棧
- 為本地變數開闢空間
- 後記 epilogs
- 釋放本地變數佔用空間
- 將需保留的暫存器原始值出棧
- R7出棧
- LR出棧,PC = LR
函式前4個引數放在R0~R3中,其他引數放在棧中,返回值放在R0中
暫存器用途:
- R0~R3:傳參和返回值
- R7:指標,指向母函式與被呼叫子函式在棧中的交界
- R13:SP暫存器
- R14:LR暫存器,儲存返回地址
- R15:PC暫存器
一些例子
相關文章
- iOS逆向工程 iOS工具篇iOS
- ios逆向工程連結iOS
- iOS開發之逆向工程iOS
- iOS 逆向工程(工具介紹)- 學習整理iOS
- iOS逆向工程之Clutch砸殼(圖文多)iOS
- Mybatis逆向工程MyBatis
- 逆向工程核心原理(1)逆向基礎
- mybatis的逆向工程MyBatis
- 小白的MyBatis逆向工程MyBatis
- iOS逆向筆記iOS筆記
- iOS逆向資料iOS
- iOS逆向工具-TheosiOS
- Mybatis逆向工程和新版本MybatisPlus3.4逆向工程的使用MyBatisS3
- iOS逆向工程,(狗神)沙梓社大咖免費技術分享。iOS
- 收藏的爬蟲逆向工程爬蟲
- 逆向工程加密函式:AES加密函式
- 【SSM-MyBatis框架】逆向工程SSMMyBatis框架
- Delphi逆向工程筆記[1]筆記
- Delphi逆向工程筆記[2]筆記
- Delphi逆向工程筆記[3]筆記
- Delphi逆向工程筆記[4]筆記
- Delphi逆向工程筆記[5]筆記
- iOS逆向環境搭建iOS
- iOS逆向之旅 — 總綱iOS
- iOS逆向入門解析iOS
- iOS逆向之工具使用iOS
- 筆記:MyBatis逆向工程 - Win/Mac筆記MyBatisMac
- Maven外掛生成myBatis逆向工程MavenMyBatis
- mybatis逆向工程和SSM框架整合MyBatisSSM框架
- iOS逆向 程式碼注入+HookiOSHook
- iOS逆向——從RSA說起iOS
- iOS逆向之 程式碼注入iOS
- Alone_Monkey 逆向IOSiOS
- ibatis和myBatis的逆向工程使用MyBatis
- PowerDsigner 16逆向工程匯入mysqlMySql
- mybatis入門基礎(九)----逆向工程MyBatis
- 淺談VB6逆向工程(1)
- 淺談VB6逆向工程(2)