iOS App 的逆向工程: Hacking on Lyft

jopen 9年前發布 | 51K 次閱讀 iOS開發 移動開發 Hacking on Lyft


如果你曾經想要知道某一部分代碼如何工作,或者很同情某些人程序里的 Bug,你要是有代碼,通常可以看看那部分代碼。但是,如果沒有代碼可怎么辦? 在這個演講里,Conrad 講到了很多可以逆向 App 的概念和工具,這些方法和工具可以用來 debug 別人的庫和你自己的代碼。他還展示了逆向 iOS 版本的 Lyft (譯者注:Lyft 是美國 Uber 之外的另一款打車軟件),并且成功注入代碼,探測網絡流量,給我們活靈活現地展示逆向的藝術。通過 Conrad 的逆向技術,你也能成功地把 App Store 里所有的 App 的代碼都暴露在你面前。

Sign up to be notified of new videos — we won’t email you for any other reason, ever.

介紹(0:00)

我是 Conrad Kramer ,工作在 Workflow 的一枚 iOS 工程師,今天要跟大家聊聊 iOS Apps 逆向工程那些事兒。通常來說,逆向工程就是試圖只通過最終產物來了解它背后工作原理的過程。在 iOS app 的世界里,這意味著你在沒有源代碼的前提下,只通過從 App Store 下載的 .app 來發現你想要的信息。

在做逆向工程的時候,會遇到兩個痛點:

  1. 使用的工具 通常很難用,因為這些工具本身就缺乏文檔,而且很不出名。他們總是崩潰出錯,而且沒人去修復這些錯誤。另外,花時間找到他們以及用好他們都很難。
  2. 一旦你開始用這些工具了,清楚自己的目標也很重要,因為有太多事情可以干了。此外,你還能用工具去逆向蘋果自己的框架,盡管他是閉源的。我們可以用這些技術來探索 UIKit 的某個 bug,或者某個 app 里的 bug。

所以逆向的第一步是像自己發問:“為什么這個 bug 會發生?他們在 UI 里用了哪些組件?” 比如,如果你很好奇一個 app 里是否用了 collection view 或者 table view”,你其實很容易回答這個問題,看一眼就好了。但是如果你問:“他們的 REST API 是什么結構的?”,這個時候逆向工程就能幫你一探究竟。

逆向 Lyft(1:44)

我決定通過一個項目來開始這個主題,目標是: Lyft’s iOS app ,它整個都是用 Swift 完成的。首先要做的事是我們了解我們感興趣的點。假設我對 REST API 很感興趣,比如我想要在另一個平臺或者在 web 上寫一個 Lyft 客戶端,我可以看看他們的 API 然后產生好奇:“他們的 URL scheme 是什么樣子的?”,當你想對 Lyft 做深度鏈接的時候,你就不得不解決這個問題。對 Workflow 來說,相關性就更高了,因為 Workflow 就是一個自動工具,我們集成了很多不同的 app。我總是需要做些類似的事情,來發現一些不公開的私有 URL scheme。

窺視 Lyft(2:48)

從 iTunes 下載下來的 Lyft 是一個 .IPA 文件(其實就是 zip 格式的)。它有很多的元數據,像 Info.plist 文件,資源文件,圖片,本地化的字符串以及很多類似的文件。這里面也包含一些可執行文件,那些被編譯了的代碼就在里面。另外,因為 Lyft 是用 swift 寫的,所以還包含很多附加的框架。

Lyft 現在看來是一個完完全全的黑盒子。我們不能直接的看透它,但我們依然有能力從特定的一些角度窺視到。一種方法就是通過監測網絡流量來觀察他的 API, 同時還能看到有哪些信息被它發送到了 Lyft 的服務器,這些通常對 App 而言是沒有什么傷害的。

然后,我們還能 注入代碼 ,真的非常爽。當 app 運行的時候,你可以打探打探這些 app 里被實例化而且存活的對象。當停止運行的時候,我們可以嘗試去研究下 .app 是如何被組織的,同時通過特定的視角來看這些代碼。

探測網絡流量 - Charles 演示(4:08)

Charles 是一個 HTTPS 代理工具,它可以讓流量在發往服務器前攔截網絡流量。我們可以用這個工具來觀察所有從 Lyft app 流向服務器的請求。

Lyft 事實上通過 SSL 加密了它的所有流量。但這些都很好破,通過 中間人攻擊 的方法來解決這個問題。其實就是替換了加密證書。

當你在用 Lyft 的時候,Lyft 不斷的把你的地理位置發給 Lyft 的服務器。 對車輛的請求和取消等操作會以格式化后的 JSON 在 Charles 中呈現出來。用 Charles,你會看到 app 里和網絡交互的所有內容。

向 Lyft 里注入代碼 - Cycript 演示(7:44)

下一個工具真的很贊,叫 Cycript 。使用這個工具的時候需要一個越獄設備,注入代碼到 app 里。Cycript 可以讓你看到別人的代碼,當然你自己寫的 app 也逃不過。這個工具是 Objective-C 和 Javascript 的混合 app,只用輸入 Objective-C 的代碼到控制臺里,就能在 app 運行這些代碼。它的交互編程環境(REPL)比 LLDB 的要好很多。盡管它不能中斷,設置斷點等等,但他對運行時代碼非常友好。你可以直接輸入下面的代碼,基本上都是 Objective-C :

var application = [UIApplication sharedApplication];
[application openURL:[NSURL URLWithString:@"https://google.com"]];

我 SSH 進入我的破解過的 iPhone 6 以后,打開 Lyft,運行 Cycript,我可以通過選擇功能來獲取一個運行時的類實例,比如 view controller 的,或者統計類的實例。作為開發者,要確定設置 ACL 來防止特定 api key 的權限問題。如果 app 能拿到這些 key,那 Cycript 也一定能拿到。

你也可以修改 app 里的 views。比如,用 UIApp.keyWindow.recursiveDescription 通過內存尋址,把 “呼叫車輛” 的按鈕變成綠色。

var b = new Instance (ADDRESS)
b.backgroundColor = [UIColor greenColor]

Cycript 甚至還支持 tab 智能提示。這個功能不但對于逆向很有用,你還可以來測試你自己的 app,比如快速換個顏色測試測試效果什么的。

Q: 用 Crcript 測試自己的 app 的時候,設備一定需要越獄么?

Conrad: 對你自己的 app 的話,并不需要。在 cycript.org 官網上,提供了一些如何把這個工具嵌入到你自己的 app 的文檔。

解密可執行文件 - dumpdecrypted 演示(11:28)

接下來,我們就要來感受下 app 運行時真正的代碼了。這個稍微有些復雜,而且需要設備越獄,我們的演示會比較簡單。因為有能力重簽名我們的設備,所以蘋果會加密商店里所有的 app,防止 app 被大家共享。然而,對于一個越獄設備來說,所有的這些加密的 app 都是可以被解密的。我從其他人那里 fork 了一個 repo,叫 dumpdecrypted ,原作者寫這個是為了導出一個 app 的資源,我 fork 了一份,是為了讓它能夠支持所有的框架,畢竟現在很多 app 都含有 frameworks。

用它的時候,你只要簡單的 clone 到本地,然后執行make,再在你越獄后的設備上對 app 執行一下。我對 Lyft 的 app 執行了這個,很快就解密了所有的文件。你看這些文件的時候,會發現所有的 framework 都以.decrypted后綴結尾。比較有意思的一些模塊是 Lyft,LyftKit 和 LyftSDK,但是我們還發現了它還用了 SocketRocket,Stripe,Pusher,Mixpanel 等等的庫。

分析可執行文件 - IDA 演示(13:47)

要分析我們導出的文件,查看源代碼,我們要到 IDA ,和 Hopperclass-dump 類似的一個工具。當在編譯一個 app 的時候,XCode 會創建一個由匯編組成的可執行文件。IDA 能很漂亮的輸出這些可執行文件里的匯編代碼,并且相互連接起來,你因此會看到一個由匯編代碼組成的圖。盡管 IDA 很貴,但是它的 免費版本 已經夠用了。除了 64 位以外,基本都有。

要找到 Lyft 的 URL scheme,我們可以在 IDA 里執行一個簡單的搜索,關鍵字是openURL,在類似的反編譯工具中,Objective-C 是相對友好和容易的,因為它對于工作原理是相對透明的,Swift 就相對較差,很多工具還沒有很好的支持 Swift,Swift 的匯編代碼也更混亂,它的類信息很難被提取出來,不過,多練習練習,看看這些匯編,你會發現一些技巧來捕獲你所想找的信息。

使用 IDA 的圖表視野,我們發現了_TZFV4Lyft15DeepLinkManager13handleOpenURLfMS0_FCSo5NSURLSb,看起來是個很亂的字符串,然而我們依然可以發現LyftDeepLinkManager,handleOpenURL, 和NSURL這幾個關鍵詞。這些看似隨機的字符串其實是有解釋的,雖然沒有文檔來說明。如果想要了解這些字符串的含義,可以看看 Mike Ash 的博客里一篇叫做 Friday Q&A 的文章,這些模糊的東西都有解釋。比如_T意思是這是一個 Swift 的符號,F意思是這是一個函數,4Lyft是一個模塊名稱,等等。

尋找 Lyft 的 URL Scheme(18:23)

想要從我們所見之中發現 URL scheme,我們就要用開發者的思維來思考。

一個 URL scheme 結構大概是這樣的:

lyft://action?parameter=value 

我們現在要去找到action是什么,parameter可能會是哪些。我首先找到了DeepLinkAbleSwift 協議,了解了深度鏈接的工作原理。通過搜索DeepLinkAble關鍵字,我在一個類里發現了諸如ride,help,invite,profile的請求對象。

我們對如何開始一次打車很好奇,我們可以看一下 Lyft 的DeepLinkToRide類,看看他是如何工作的。想要看這些,你甚至不需要了解匯編,你只需知道如何搜索和掃描匯編中你需要的信息即可。就好比你即使不會法語,卻經常看見到法語,看的足夠多次后,你總是能悟出些東西來。很多時候 IDA 展示給我們的完全就是一種外語,其實我第一次嘗試逆向 Swift 的時候,就是這樣一種感受。

通過大致瀏覽DeepLinkToRide的圖。我發現了一些不同的字符串,比如 “pickup”,“[latitude]”,“[longtitude]”,“destination” 等等。IDA 還展顯示了 ”ridetype“,后面經過測試發現這是個 action,通過查看 “ridetype”,我們發現了 “lyft”, “lyft_line”, “lyft_plus”, 和 “access”,這些都是出行方式。

構造這些不同的 URL 部分,然后測試請求。我發現請求一個出行的 scheme 方式如下:

lyft://ridetype
  ?id=lyft_line
  &pickup[latitude]=0
  &pickup[longitude]=0
  &destination[latitude]=0
  &destination[longitude]=0

現在,我明白了 Lyft 是如何工作的了,我可以集成到 Workflow 里了。這個過程其實就是二進制分析。盡管這些看起來很復雜,但事實上,只要像個開發者一樣思考,其實也那么的難。

Q&A(22:50)

Q: 證書綁定(pinning certificates)能否防止中間人攻擊?

Conrad:證書綁定是一個用來防止中間人攻擊的方法,在實踐中確實很有用,前提是你的手機未越獄。比如 推ter 就在用證書綁定技術。然而,用逆向工具 Cycript 能夠輕松破解。 AFNetworking 支持證書綁定,只要設置一下SSLPinningMode這個屬性。然而… 我們可以用 Cycript,再把它修改成none,如果你的 iPhone 越獄了,或者被人控制了。所以,并沒有一種方案能夠徹底防止你的流量被檢測,如果沒有越獄,倒是一種很好的保護方法。

Q: 是否推薦類似 cocoapods-keys 這樣的工具來混淆字符串?

Conrad: 字符串混淆有以下的好處:

- 如果你用蘋果框架里的私有 API,能很容易的躲避過蘋果審查的自動掃描工具。- 如果那個人并沒有一部越獄的 iPhone,或者它不知道如何解析混淆,他可能很難找到 app 里的字符串。

然而,你無法永遠的把字符串藏起來。比如,在 Cycript 中,你可以輕易地解開混淆。所以字符串混淆也不是沒法破的保護方案。

Q: class-dumpdumpdecryped 的區別是啥?

Conrad: 他們事實上是不同的工具。 dumpecrypted 能將一個 App Store 加密的工具解密。而 class-dump 能將一個解密后得二進制文件去除他的 Objective-C 接口文件,跟 IDA 有點像,不過很遺憾的是:它不支持 Swift。

Q: 導出 Apple framework 的庫,比如: this one ,是不是也是用的 class-dump?

Conrad: 是的,蘋果的框架沒有加密,可以被輕易地導出所有的class。這意味著那些把蘋果的私有interface 放到GitHub上的,你可以輕易地搞定他們。

Q: 逆向工程是否存在法律問題?Lyft 會不會不同意調用他們的私有代碼和 api?

Conrad: 從法律上講,我覺得沒有太多問題。我們通常會跟所有的合作伙伴去聊到我們在做的事情。比如:我剛剛發現的這些東西我都會和 Lyft 討論一下,在他們允許后集成到 Workflow 里。這些技術其實也有很多道德上的考慮。不過話說回來,這些技術也能阻止開發者們胡亂搞,就比如之前逆向 推ter 發現他們上傳用戶手機里裝的 App 列表到他們的服務器上。所以凡事總有兩面,逆向工程只是個工具,善用就好了。

Q: 如何查看蘋果框架的反匯編代碼?

Conrad: 這個的過程跟我之前展示的一個很像,只不過你不再需要一個越獄后的設備。當你把線插到設備上的時候,iTunes 實際上獲取到了設備的符號,你可以在 Xcode 里找到一個大概叫 “device symbol” 文件夾,在 IDA 或者 class-dump 里打開 Apple 的 frameworks,然后展開分析。這些都是沒加密的,而且可以直接拿來用。在修復一些 beta 版本的 UIKit 的 bug 的時候很好使。

Sign up to be notified of new videos — we won’t email you for any other reason, ever.

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!