by 知識小集 · Lefe_x
最近各大“媒體”都在報導《iOS應用逆向與安全》這本書,這是自“小黃書”出版後的又一本關於逆向安全的書。而目前很多 iOS 開發者對逆向還非常“小白”,以至於盲目地覺得逆向很難、很厲害。而這本書的出現,無疑為逆向這個世界開啟了另一扇窗,我們一起看看這扇窗裡究竟“藏”了什麼。本文並不打算介紹書中具體細節,只是說明每一章都講了哪些內容,點到為止。
第一章 概述
本章主要對逆向整體進行描述,分別從應用中存在的風險、如何保護應用的安全、和開發工具的使用來介紹。而我覺得本章的核心是掌握逆向的流程和作用,瞭解 APP 開發中需要注意的安全問題。
逆向流程: 逆向的整個流程基本是相同的,而這些流程可以總結為:
- 獲取應用的 ipa 包,解密(如果是越獄應用則不需要解密),匯出標頭檔案;
- 通過介面檢視 APP 的佈局,從佈局中找到對應的標頭檔案,檢視關鍵函式;
- hook 相關函式,達到你的目的;
- 靜態分析加動態除錯分析關鍵函式;
- 模擬或篡改原有 APP 的邏輯;
- 達到自己的目的。
**應用場景:**掌握逆向肯定非常有用,如果你想從事安全方面的工作,可以深究,否則不必投入太多的精力,畢竟正向開發中很少用到逆向知識。學習逆向知識可以總結為:
- 借鑑第三方 APP 的實現思路,比如某個功能是如何實現的、介面使用了哪一型別的 View,資料庫結構是什麼樣的等等;
- 加深對正向開發的理解,比如 runtime;
- 普及安全知識,瞭解逆向可以做什麼後,在開發中你就會知道哪些資訊會被別人獲取到,比如某個 APP 根據本地的資料判斷是否可以使用付費的資源,這明顯使用逆向即可使用付費資源;
第二章 越獄裝置
本章主要講解越獄在逆向中的作用及越獄工具的使用。這裡需要強調一點,逆向不一定需要越獄,而想要更好地掌握逆向的原理,一臺越獄裝置是必不可少的。目前市面上很多越獄工具,也提供了一鍵越獄,讀者可自行搜尋。
登入越獄裝置:
手機越獄後,會安裝一個 Cydia 的軟體,它主要用來在越獄手機上安裝各種工具,相當於越獄中的 “App Store” 。想要讀取越獄裝置中的資原始檔,必須進行遠端登入。搞伺服器的同學都知道使用 SSH 進行遠端登入,而登入越獄裝置也可以使用 SSH 登入。通過 Cydia 搜尋 OpenSSH 來安裝即可,安裝完後執行:
sudo ssh root@手機ip地址
複製程式碼
登入成功即可對越獄裝置進行操作了。作者還介紹了其它登入越獄裝置的方式,使用公鑰匙登入,USB 登入。
檔案目錄:
如果想檢視裝置的檔案系統,在 Mac 上可使用 iFunBox,手機端需要安裝 Apple File Conduit 2 。安裝成功後,即可通過 iFunBox 檢視手機的目錄結構,比如安裝的 APP 沙盒目錄,系統自代 APP 的沙盒目錄,各種 Frameworks 等等。
越獄必備工具
- adv-cmds: 執行 ps 命令報錯,需要安裝這個工具;
- appsync: 讓系統不再驗證簽名,以免安裝應用失敗;
- iFile:在手機上檢視檔案目錄;
- scp:終端命令,把遠端裝置的檔案複製到另一個裝置;
- Cydia Substrate:允許第三方開發者在越獄系統的方法中打一些補丁或擴充套件方法。
第三章 逆向工具詳解
你可能僅僅停留在對這些工具(dumpdecrypted、Clutch、class-dump、Reveal、Cycript、Charles、Wireshark)的使用上,比如我。而作者卻給我們講解了原理,可見他的功力很深。
dumpdecrypted
AppStore 中的應用都是經過加密的,而逆向的前提需要把加密的內容解密出來。dumpdecrypted 這個工具就是專幹這件事的。當然,如果你不想解密,可以直接從越獄市場上下載被解密的 APP。不過有時候越獄市場上沒有你要的應用就不得不自行解密了。它的原理引用作者的原話:
dumpdecrypted 是一個開源的工具,它會注入可執行檔案,動態地從記憶體中 dump 出解密後的內容。
Clutch
除了使用 dumpdecrypted 進行解密,Clutch 也可以做到。不過作者提到使用這個經常會出錯,建議使用 dumpdecrypted。
class-dump
class-dump 的作用是從可執行檔案中匯出類、方法、屬性資訊的工具,這裡需要強調一下可執行檔案,被解密的 APP 應用中會有一個可執行檔案(Mach-O)。可以從 xxx.app 中的 info.plist 檔案找到 Executable file 它的值即是 xxx.app 的可執行檔案。使用 MatchOView 可以檢視 Mach-O 檔案。
匯出 We.app 的標頭檔案:
class-dump -H ~/Desktop/reverse/ipa/We.app -o ~/Desktop/reverse/header/we
複製程式碼
Reveal
是用來檢視APP介面的工具,檢視第三方 APP 不一定非用越獄裝置。
Cycript
Cycript 是一個允許開發者使用 Objective-C++ 和 JavaScript 組合語法檢視及修改執行時 APP 的記憶體資訊的工具。在逆向中主要用來驗證某些猜測是否正確,檢視介面資訊等。比如檢視當前顯示的 VC,某個物件執行某個函式後的結果,動態修改某個 UI 的資訊。
Charles、Wireshark
介紹了這兩個抓包工具的使用。
第四章 開發儲備
這一章主要介紹正向開發的一些知識,而這些知識對逆向開發很重要。
ipa 包
獲取應用的 ipa 包,主要可以通過兩種方式獲取:
- 從 iTunes 中獲取,目前的 iTunes 中已不支援,需要下載低版本的 iTunes。 下載;
- 直接從越獄裝置獲取,其實直接從各種助手中無需越獄裝置即可下載越獄應用,獲取到 ipa 包;
應用包的構建過程:
- compile:使用 Clang 編譯原始檔;
- link:將編譯生成的目標檔案連結成一個可執行檔案;
- storyboard:編譯專案中的 storyboard 檔案;
- plist:生成 plist 檔案;
- asset:將需要的資原始檔複製到 App 目錄下;
- dsym:生成符號檔案;
- codesign:對 App 進行簽名;
- package:打包。
介面與事件傳遞
介紹了 iOS 中的 UI 、事件傳遞和事件響應。
類與方法
主要介紹了類的底層實現,OC 中的訊息機制,runtime 的一些使用場景。
App簽名
正向開發中,每個同學都會經歷一次蘋果的證照配置。而作者在這裡主要講解了 App 簽名的原理,這樣為逆向重簽名做好鋪墊。
第五章 分析與除錯
前面四章主要為後四章做一個鋪墊,從接下來的章節中正式開啟了逆向。本章主要從靜態分析和動態除錯來介紹逆向。
靜態分析,指在不允許 App 的前提下對程式分析的一種方法。一般有以下幾種方式:
- 基於 ipa 和 app 包;
- 基於檔案格式;
- 基於二進位制反彙編;
反彙編
反彙編主要有兩個工具:Hopper 和 IDA。而這兩個工具可以檢視原始碼實現的彙編程式碼,關鍵還可以檢視虛擬碼。以前一直覺得 Hopper 不好用就沒用,今天下載了一個用起來發現比 IDA 用著舒服。
Hopper 只支援 Mac 和 Linux,相對於 IDA 比較弱一些。而 IDA 支援 Windows 平臺。
靜態庫分析
有時候想看某個靜態庫的實現,其實也可以使用 Hopper 檢視他的彙編程式碼。
➜ 5.1 靜態分析 ls
Crashlytics UserLogin
➜ 5.1 靜態分析 lipo -info Crashlytics
Architectures in the fat file: Crashlytics are: armv7 armv7s i386 x86_64 arm64
➜ 5.1 靜態分析 lipo Crashlytics -thin arm64 -output Crashlytics_arm64
➜ 5.1 靜態分析 mkdir Objects
➜ 5.1 靜態分析 cd Objects
➜ Objects ar -x ../Crashlytics_arm64
➜ Objects grep "Upload" -rn ./
Binary file .//CLSReportsController.o matches
Binary file .//CLSCrashReportingController.o matches
Binary file .//CLSNetworkClient.o matches
➜ Objects otool -l Crashlytics.o|grep bitcode
sectname __bitcode
➜ Objects ld -r -arch arm64 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk -bitcode_bundle ./*.o -o ../output
複製程式碼
動態除錯
動態除錯是在程式執行的時候執行一系列操作,比如獲取某個物件的值,執行上下文等。
LLDB 動態除錯:正向開發中常會使用到 LLDB 來除錯程式,而在逆向中它也發揮很大作用。
用 Xcode 除錯第三方應用:使用 Xcode 在非越獄裝置中除錯第三方應用、進行符號的還原、檢視帶符號的堆疊呼叫。不過除錯的時候需要一個第三方應用。
Theos
越獄開發中除了 Thoes 外還有一個叫 iOSOpenDev 的工具,功能和 Thoes 是一樣的,不同點是iOSOpenDev 是整合到 Xcode 中使用的,而 MonkeyDev 和 iOSOpenDev 屬於同一型別的工具。
MonkeyDev
MonkeyDev 是作者開發的一個工具,主要用 Xcode 進行越獄開發。具體使用可以檢視 MonkeyDev 的 wiki 。
第六章 逆向進階
這一章,看著比較吃力。很多都沒接觸到,這裡簡單的做個介紹,如果以後用到這部分內容再繼續深究。
程式載入
在程式執行 Main 函式之前,都做了哪些事。
Mach-O 檔案格式
對於每個 ipa 包,都會包含一個可執行檔案,而這個檔案就是 Mach-O 檔案。
ARM 彙編
逆向如果想看懂程式碼,那麼必須學會彙編。
hook
hook 直譯為 鉤子,通過 hook 可以改變程式執行邏輯。hook 最常見的有以下三種方式:
- MethodSwizzle:
通過 runtime 交換方法的實現。
- fishhook:
fishhook 是 facebook 開源的一個庫。
A library that enables dynamically rebinding symbols in Mach-O binaries running on iOS.
- Cydia Substrate:
動態庫
特點:
- 存在形式有 .dylib,.framework 和連結符號 .tdb;
- 它的格式和普通二進位制檔案沒有區別;
- 它的好處是可以只保留一份檔案和記憶體空間,從而能夠被多個程式使用,例如系統動態庫;
- 可減小可執行檔案的體積,不需要連結到目標檔案。
在逆向中會經常用到動態庫,比如使用 Reveal 除錯第三方應用時需要把 RevealServer. framework 注入到 APP 程式中。可以通過引入標頭檔案的方式呼叫 和 dlopen 動態載入的方式呼叫動態庫。
第七章 實戰演練
這章主要應用前幾章學到的知識。而逆向開發可以在越獄裝置和非越獄裝置中開發。
越獄裝置
目標是給 WhatsApp 長按訊息新增一個收藏選單,並在設定中新增已收藏的訊息。分別在越獄裝置、非越獄裝置進行分析。
- 下載 WhatsApp 使用 dumpdecrypted 解密;
- 使用 class-dump 匯出標頭檔案,匯出標頭檔案時加上 -A 引數可以顯示方法在檔案中的實現地址;
- 符號還原,方便後續使用 lldb 進行除錯;
- 分析某個應用時,需要從介面入手,使用 Reveal 檢視介面的層級結構,定位到具體的檢視控制器,從標頭檔案找到對應的方法;
- 根據找到的方法,使用 lldb 新增斷點,驗證是否會呼叫對應的方法,以確定是否為需要找的方法;
- 使用 Hopper 檢視虛擬碼,猜測具體的實現方式;
非越獄裝置
目標是給 WhatsApp 新增自動回覆功能。越獄裝置分析有諸多繁瑣的工作,比如匯出標頭檔案,使用 Reveal,使用 LLDB 除錯不方便等。所以作者把這些功能都整合到了 MonkeyDev 這個工具中,通過 MonkeyDev 新建工程將自動整合 class-dump、符號還原、Reveal、Cycript、注入動態庫、自動重簽名等一系列重複性的工作,可以直接在非越獄裝置上進行逆向分析。具體使用參考
Frida 實戰應用
Frida 是一款跨平臺的注入工具,通過注入 JS 與 Native 的 JS 引擎進行互動,從而執行 Native 的程式碼進行 hook 和動態呼叫。這個工具可以用於 Android 和 iOS,它可以通過一段 JS 來除錯應用。
第八章 安全保護
前面講了這麼多可以除錯別人的 App 如同除錯自己的一樣,這就需要在開發的過程中來保護我們自己的 App 免受攻擊,重要的資料需要進行加密處理。而本章主要講有哪些手段可以保護我們的 App 儘可能的不被破解。主要採用的手段有:
- 資料加密:靜態字串、本地儲存及網路傳輸加密
不管是本地的資料還是網路中傳輸的資料,對敏感資料需要採用加密演算法進行加密處理,而常用的加密演算法有 AES,RSA。對於網路傳輸的資料可以使用 AES+RSA 的方式對資料進行加密,如果使用 Https 的方式需要對證照進行校驗。而對於一些常量字串有時候也需要加密處理,以防止被靜態分析。這裡作者提使用 libclang 方式,具體 原始碼。
- 靜態混淆:類名、方法名、屬性的混淆;
使用 class-dump 匯出的標頭檔案很容易根據名字知道某個類,方法的作用,這時候需要對類名,方法名進行混淆。第一種方法:通過巨集定義混淆,在 pch 檔案中比如這樣寫 #define MyClass 89s343ss
。網上有一個開源的庫 ios-class-guard。第二種方法:二進位制修改,修改可執行檔案的 __obj_classname
和 objc_methname
。
- 動態保護:反除錯、注入檢測、hook 檢測,越獄檢測、簽名檢測等;
雖然靜態混淆後不能猜到類名方法名的作用,但是如果採用動態的方式還是能知道某些方法的引數、以及加密後的資料等。這就是要防動態除錯。
- 反除錯:主要通過阻止除錯去附加和檢測偵錯程式是否存在。主要有 ptrace、sysctl、syscall、ARM 等方式;
- 反反除錯:過濾掉反除錯機制;
- 反注入:檢測當前有沒有其它模組注入;
- hook 檢測:檢測是否被惡意的 hook 掉了;
- 完整性校驗:load command、程式碼校驗、重簽名校驗;
- 程式碼混淆:提高分析難度
未混淆的程式碼可以通過 Hopper 和 IDA 等彙編工具得到彙編程式碼,甚至可以得到對應的虛擬碼。為了提高分析難度,需要對程式碼進行混淆。混淆主要通過 LLVM。
知識小集是一個團隊公眾號,主要定位在移動開發領域,分享移動開發技術,包括 iOS、Android、小程式、移動前端、React Native、weex 等。每週都會有 原創 文章分享,我們的文章都會在公眾號首發。歡迎關注檢視更多內容。