教你如何動(dòng)態(tài)調(diào)試?iOS App(反編譯App)開(kāi)篇
通過(guò)本文你能了解?iOS?逆向的基本知識(shí),對(duì)?iOS App?的安全有一定了解。然后能舉一反三,在?自家?App?找到危險(xiǎn)漏洞加以預(yù)防,保證?戶數(shù)據(jù)安全。?
在安全領(lǐng)域,攻與防永遠(yuǎn)存在。哪怕是?iPhone?有著強(qiáng)大的安全防護(hù)機(jī)制,也擋不住那些極客們一次?一次的好奇,開(kāi)發(fā)了很多強(qiáng)?且便利的?工具。本文就是在這些極客們提供的工具的基礎(chǔ)上完成的!
準(zhǔn)備工具
Mac?電腦和越獄?iPhone??機(jī)?
查看手機(jī)系統(tǒng)目錄工具: iFunbox?或?iTools
網(wǎng)絡(luò)分析工具:Charles
反編譯?具:Hopper,?IDA Pro
查看頭文件工具:class-dump
砸殼工具:dumpdecrypted,?Clutch
調(diào)試器器:lldb?或?gdb
調(diào)試工具:Cycript
HTTP(S)?抓包
HTTP?抓包
第一步:獲取?MAC IP
按下Option鍵,同時(shí)點(diǎn)擊?Mac?菜單欄上的?無(wú)線?網(wǎng)?Icon,能看到當(dāng)前電腦的?IP?地址。 或在終端輸入?ifconfig en0?也可查看。
第?步:設(shè)置代理
保證?機(jī)和電腦在同一?WIFI?下,在手機(jī)上,點(diǎn)擊“設(shè)置->?無(wú)線局域?網(wǎng)->連接的WiFi”,設(shè)置HTTP代理理:?
服務(wù)器器:為?Mac?電腦?IP?地址(如192.168.1.122)
端口:8888
第三步:抓包
在電腦端,打開(kāi)?Charles。使?機(jī)發(fā)?生?網(wǎng)絡(luò)請(qǐng)求,Charles?會(huì)彈出一個(gè)詢問(wèn)的對(duì)話框
點(diǎn)擊“Allow”允許,Charles?會(huì)出現(xiàn)手機(jī)的?HTTP?請(qǐng)求記錄列表。
HTTPS?抓包
第一步: 獲取證書(shū)安裝地址
安裝?SSL?證書(shū)到?機(jī)設(shè)備。點(diǎn)擊?Help -> SSL Proxying -> Install Charles Root Certificate on a Mobile Device
出現(xiàn)彈窗得到地址?chls.pro/ssl
第二步:iPhone?安裝證書(shū)
在?機(jī)?Safari?瀏覽器輸?地址?chls.pro/ssl,出現(xiàn)證書(shū)安裝頁(yè)面,點(diǎn)擊安裝,?機(jī)設(shè)置有密碼的輸入密碼進(jìn)行安裝
第三步:配置代理理?host
Charles?設(shè)置?Proxy。選擇?Proxy -> SSL Proxying Settings...
勾選?Enable SSL Proxying,點(diǎn)擊?Add
Host?設(shè)置要抓取的?HTTPS?接?,Port?填寫(xiě)?443。
讓手機(jī)重新發(fā)送?
HTTPS?請(qǐng)求,可看到抓包。
注意:不抓包請(qǐng)關(guān)閉手機(jī)?HTTP?代理理,否則斷開(kāi)與電腦連接后會(huì)連不上網(wǎng)!
拿到?.h?頭文件
從?AppStore?直接下載的?ipa, 蘋(píng)果公司對(duì)其做了 FairPlay DRM?技術(shù)進(jìn)?行行加密保護(hù),?法直接使? class-dump 工具獲取頭文件。但是如果是通過(guò)?development?打包出來(lái)的話的?App 的話,是可以直接使用?class-dump?查看所有頭?件的,此部分介紹就是通過(guò)此情況來(lái)說(shuō)明如何獲取?.h??件的。 此處不再介紹?class-dump 工具的安裝過(guò)程,具體步驟請(qǐng)直接百度。
進(jìn)?到 appName.ipa?所在?錄,修改擴(kuò)展名為?.zip,然后解壓文件,得到?appName.app。
然后執(zhí)行:
class-dump -H appName.app -o ./headers/
命令執(zhí)行完成后,會(huì)在當(dāng)前?錄下的?headers 目錄?里里看到?app?所有頭?件。 如果添加參數(shù)?-A -S?會(huì)在頭文件?里里標(biāo)記處類?法和屬性的?IMP?地址(模塊偏移前基地址)。
class-dump -H -A -S appName.app -o ./headers/
SSH?訪問(wèn)手機(jī)?件?錄
在你的越獄手機(jī)上使用?Cydia?應(yīng)用市場(chǎng)安裝?OpenSSH,并保證?Mac?和?iPhone?處于同?個(gè)WIFI下,在?MAC?終端輸入:ssh root@IP?,IP?替換為?iPhone?的?IP?地址
輸?默認(rèn)密碼:alpine即可進(jìn)? iPhone?終端。
使用?Clutch?反編譯?App
第一步:重新簽名?debugserver
取得?debugserver?有兩種?式。
第一種是在?Mac?電腦中拿到
進(jìn)入路路徑?/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/8.3/DeveloperDiskImage.dmg?(其中路路徑?里里8.3,代表?iOS?系統(tǒng)版本,需與準(zhǔn)備的越獄?機(jī)系統(tǒng)版本保持一致)。雙擊?DeveloperDiskImage.dmg,將目錄里的?usr/bin/debugserver?復(fù)制到指定文件夾中。
第二種是在越獄手機(jī)里拿到
如果手機(jī)連接過(guò)手機(jī)并通過(guò)?XCode?調(diào)試過(guò)?app,會(huì)在?機(jī)?里里的?/Developer/usr/bin/ 目錄下?生成一個(gè)?debugserver 文件。通過(guò)?iFunbox?導(dǎo)出?至?Mac?桌面。或使? scp?命令?cpoy?出 來(lái)。
第二步:重簽名?debugserver
即給?debugserver?添加?task_for_pid?權(quán)限 創(chuàng)建?entitlements.plist,添加如下四個(gè)?key:
com.apple.springboard.debugapplications?
get-task-allow
task_for_pid-allow
run-unsigned-code
key?對(duì)應(yīng)的?value?都設(shè)為設(shè)為?ture
將?entitlements.plist?和?debugserver?放在同?個(gè)目錄下,執(zhí)?行行以下命令:
codesign -s - --entitlements entitlements.plist -f debugserver
此命令會(huì)重新簽名?debugserver,將簽名后的?debugserver?拷??手機(jī)系統(tǒng)的?/usr/bin/ 目錄下。注意:不要將?debugserver?拷貝至?/Developer/usr/bin/?路徑下
第三步: 通過(guò)?Clutch?拿到反編譯后的?App?可執(zhí)行文件
將下載好的?Clutch?放?手機(jī)的?/usr/bin/?路徑下。然后,給?Clutch?賦予權(quán)限,通過(guò)?SSH?登錄到手機(jī),進(jìn)? /usr/bin/?執(zhí)行?chmod a+x ./Clutch?。 通過(guò)命令?Clutch -i?,列出所有的可被?Clutch?的應(yīng)用。
對(duì)指定序號(hào)的應(yīng)用進(jìn)行脫殼,如企業(yè)微信,序號(hào)是1,命令是?Clutch -d 1?。執(zhí)行完成后,會(huì)得到脫殼后的?ipa。
第四步:使用?class-dump?拿到?.h?頭文件
使用上文?【拿到.h頭?件】?介紹的方法拿到脫殼后的?App?頭文件和并記下要打斷點(diǎn)的方法的?IMP?地址。
動(dòng)態(tài)調(diào)試?App
本?動(dòng)態(tài)調(diào)試?到的調(diào)試器器是?lldb。
第?步:使?iPhone?進(jìn)?等待掛載狀態(tài)
SSH?登錄到手機(jī),執(zhí)行?ps -e?命令得到?App PID?或項(xiàng)目名稱。
進(jìn)入?/usr/bin/?執(zhí)行?./debugserver IP:port -a PID|appProjectName?。 其中第一個(gè)參數(shù)?IP?可以替換為?Mac?電腦?IP地址,或者使用?*?通配符,允許所有?IP?調(diào)試;第二個(gè) 參數(shù)?port?隨便寫(xiě)一個(gè)就行。第四個(gè)參數(shù) 可以指定要調(diào)試?App?的?PID?或項(xiàng)目名稱。?如要調(diào)試的?PID?為?6019?的搜狗輸?法項(xiàng)目名稱為SogouInput,則命令即為:
./debugserver *:1234 -a 6019?或?./debugserver *:1234 -a ‘SogouInput’
此命令執(zhí)行完成后,app會(huì)進(jìn)?等到掛載狀態(tài),app會(huì)被卡住點(diǎn)擊無(wú)反應(yīng)。正常現(xiàn)象!
如果此命令報(bào)錯(cuò),如出現(xiàn)?Segmentation fault: 11?等情況,說(shuō)明?App?做了反動(dòng)態(tài)調(diào)試保護(hù)。遇到此種情況,需先確定?App?采?了哪種保護(hù)?案,然后進(jìn)一步找到對(duì)應(yīng)措施,干掉它的反動(dòng)態(tài)調(diào)試保護(hù)。
第二步:監(jiān)聽(tīng)進(jìn)程,進(jìn)?掛載狀態(tài)
重新打開(kāi)一個(gè)?Mac?終端執(zhí)行?lldb?進(jìn)入?lldb?調(diào)試狀態(tài)。然后輸?
process connect connect://iPhoneIP:port
iPhoneIP?替換為?iPhone?的?IP?地址;port?改為剛才指定的端口,即?1234。 待命令執(zhí)行完成后,App?即進(jìn)?掛載狀態(tài)。
第三步:獲取?App?的?ASLR?偏??移量
ASLR偏移量其實(shí)就是虛擬內(nèi)存的地址相對(duì)于模塊基地址的偏移量。有兩個(gè)概念需要熟悉一下:
模塊在內(nèi)存中的起始地址?----?模塊基地址
ASLR偏移?----?虛擬內(nèi)存起始地址與模塊基地址的偏移量
在?lldb?調(diào)試器器模式下,執(zhí)?行行?imge list -o -f
模塊偏移后的基地址?= ASLR?偏移量?+?模塊偏移前基地址(?法的?IMP?地址)
上?面這個(gè)公式是尤為重要的,因?yàn)?Class-dump?中顯示的都是“模塊偏移前基地址”,?而?lldb?要操作的都是“模塊偏移后的基地址”。所以從?Class-dump?到?lldb?要做一個(gè)地址偏移量的轉(zhuǎn)換。
?此,已得到了App?的?ASLR?偏移量和?法的?IMP?地址。
第四步:打斷點(diǎn),調(diào)試
在?lldb?模式下執(zhí)?行行,?br s -a 'ASLR?偏移量+ IMP'?,然后執(zhí)?行行?c?,使?App?跑起來(lái),觸發(fā)一個(gè)?法調(diào)用,就會(huì)進(jìn)入斷點(diǎn)模式。輸入?po $arg1?打印第?個(gè)參數(shù)。 然后,配合著抓包工具?Charles(?比如分析網(wǎng)絡(luò)請(qǐng)求加密邏輯)?和?Class-dump(?比如修改某個(gè)類的方法返回值)等?具,你就可以隨意動(dòng)態(tài)調(diào)試?App 了,就像在?XCode??里里調(diào)試一樣!
?br?命令說(shuō)明
br dis 1 --?禁?(disable)編號(hào)為1的斷點(diǎn)
?br en 1 --?啟用(enable)編號(hào)為1的斷點(diǎn)
?br dis --?禁用所有斷點(diǎn)
br en --?啟用所有斷點(diǎn)
br del 1 --?刪除(delete)編號(hào)為1的斷點(diǎn)?
br del --?刪除所有斷點(diǎn)
br list -- 列出所有斷點(diǎn)
使用?dumpdecrypted?破殼?App
dumpdecrypted?脫殼工具的原理理是:將應(yīng)用程序運(yùn)行起來(lái)(iOS?系統(tǒng)會(huì)先解密程序再啟動(dòng)),然后將內(nèi)存中的解密結(jié)果?dump?寫(xiě)?入文件中,得到一個(gè)新的可執(zhí)行程序。
第一步:?生成?.dylib 文件
在終端進(jìn)?到下載后的目錄中,?cd dumpdecrypted-master?,然后執(zhí)行?make?,即可生成?dumpdecrypted.dylib
第?步:找到?App?的?Documents 文件夾路路徑
通過(guò)?SSH?登錄到?iPhone,然后執(zhí)行?ps -e?查看進(jìn)程,獲取要破殼的進(jìn)程?PID。然后執(zhí)行?cycript -p PID?附加到?PID?進(jìn)程上。最后執(zhí)
[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]?得到?Documents 文件夾路路徑。
?第三步:開(kāi)始破殼
將第一步生成的?dumpdecrypted.dylib?拷?貝到第二步得到的?.../Documents/?路路徑下,命令如下:
scp ~/dumpdecrypted.dylib root@IP:/var/mobile/Containers/Data/Application/2B4C6281-C015-4FF3-A8EC-5E5C7554D447/Documents?(將路徑?里里的UDID?替換為你的要破殼的?App?的?UDID)
進(jìn)?入?Documents 目錄下,執(zhí)?
?DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/ Application/BFED82A3-3238-4F41-B797-C1CB584CBE05/appProjectNa (路徑里的?UDID?替換為你的要破殼的?App?的?UDID;將?appProjectName?替換為要破殼?App?的項(xiàng)?名稱)
待命令執(zhí)行完,會(huì)在當(dāng)前目錄?生成?一個(gè)名為?appProject.decrypted?的文件,這個(gè)就是破殼后的?App?可執(zhí)?文件,要的就是它!使用?Class-dump?即可得到頭文件。或使? Hopper?或?IDA Pro?進(jìn)?反編譯。
給你的?App?添加反動(dòng)態(tài)調(diào)試機(jī)制
?ptrace
為了?便便應(yīng)用軟件的開(kāi)發(fā)和調(diào)試,從Unix的早期版本開(kāi)始就提供了一種對(duì)運(yùn)行中的進(jìn)程進(jìn)行跟蹤和控制的手段,那就是系統(tǒng)調(diào)用?ptrace()。 通過(guò)?ptrace?可以對(duì)另?個(gè)進(jìn)程實(shí)現(xiàn)調(diào)試跟 蹤,同時(shí)?ptrace?還提供了一個(gè)?常有?的參數(shù)那就是?PTDENYATTACH,這個(gè)參數(shù)用來(lái)告訴系統(tǒng),阻止調(diào)試器器依附。
所以最常用的反調(diào)試方案就是通過(guò)調(diào)用ptrace來(lái)實(shí)現(xiàn)反調(diào)試。?
sysctl
當(dāng)?個(gè)進(jìn)程被調(diào)試的時(shí)候,該進(jìn)程會(huì)有一個(gè)標(biāo)記來(lái)標(biāo)記?己正在被調(diào)試,所以可以通過(guò)?sysctl?去查看當(dāng)前進(jìn)程的信息,看有沒(méi)有這個(gè)標(biāo)記位即可檢查當(dāng)前調(diào)試狀態(tài)。 檢測(cè)到調(diào)試器就退出,或者制造崩潰,或者隱藏工程,當(dāng)然也可以定時(shí)去查看有沒(méi)有這個(gè)標(biāo)記。
syscall
為從實(shí)現(xiàn)從用戶態(tài)切換到內(nèi)核態(tài),系統(tǒng)提供了一個(gè)系統(tǒng)調(diào)?函數(shù)?syscall,上?面講到的?ptrace?也是通過(guò)系統(tǒng)調(diào)用去實(shí)現(xiàn)的。 在Kernel Syscalls27 這?里里可以找到?ptrace?對(duì)應(yīng)的編號(hào)。
26. ptrace 801e812c T
所以如下的調(diào)?等同于調(diào)用?ptrace:syscall(26,31,0,0,0);
arm
syscall?是通過(guò)軟中斷來(lái)實(shí)現(xiàn)從用戶態(tài)到內(nèi)核態(tài),也可以通過(guò)匯編?svc?調(diào)用來(lái)實(shí)現(xiàn)。?
覺(jué)得不錯(cuò)的話,歡迎關(guān)注我的公眾號(hào)哦!