設為首頁收藏本站

艾歐踢論壇

 找回密碼
 立即註冊

QQ登錄

只需一步,快速開始

搜索
熱搜: 活動 交友 discuz
查看: 314|回復: 0
打印 上一主題 下一主題

Android App 逆向入門之三:監聽 app 封包

[複製鏈接]
跳轉到指定樓層
樓主
發表於 2022-12-12 21:12:07 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
前置作業前置作業一共有兩項:
  • 準備 proxy
  • 設置手機
Proxy 的部分其實任選一套都可以,我是用常見的 Burp Suite,其他軟體的設置應該也都大同小異。
首先,先到 Proxy -> Options 裡面新增 Proxy Listeners,bind to address 的部分記得選 all interfaces,手機才連的到:

電腦的 proxy 就這樣設置完成了,接著我們來設定手機。
在開始設定以前,記得要先讓手機跟電腦連到同一個 wifi,才會在同樣的網路底下。再來,在電腦上看一下自己的內網 IP 是多少,前往手機裡的設定 => 連線 => Wi-Fi,接著編輯連到的網路,設置手動 proxy,讓手機的流量 proxy 到電腦去。
然後我們要在手機上安裝 Burp Suite 的憑證,手機上直接造訪 http://burpsuite 即可,會下載一個檔案叫做 cert.der,記得改名成 cert.cer 後點開就可以安裝憑證。
到這邊為止,手機上的準備就完成了。
改造 apk這次拿來示範的 apk 在這裡:https://github.com/aszx87410/demo/raw/master/android/demoapp-http.apk
App 的內容很簡單,就是按下按鈕以後會發 request,只要有監聽到就代表成功了。裝上 app 之後可以先試試看,你應該會發現儘管上面那些都設定好了,proxy 還是一片空白。
原因就如同我開頭講的一樣,在 Android 官方文件裡有一個章節就在講這個:Network security configuration
而改造方法也很簡單,基本上不需要動到程式碼,因此我們先用 Apktool 把 apk 解開。
接著打開 AndroidManifest.xml,找到 <application> 的地方,看一下有沒有 android:networkSecurityConfig 這個屬性,沒有的話就加上去:android:networkSecurityConfig="@xml/network_security_config",有的話就記住 xml 的名稱。
再來我們去 res/xml 底下,新增 network_security_config.xml,內容為:
  1. <span class="token prolog"><?xml version="1.0" encoding="utf-8"?></span>
  2. <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>network-security-config</span><span class="token punctuation">></span></span>
  3.   <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>base-config</span> <span class="token attr-name">cleartextTrafficPermitted</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  4.     <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>trust-anchors</span><span class="token punctuation">></span></span>
  5.       <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>certificates</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>system<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
  6.       <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>certificates</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>user<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
  7.     <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>trust-anchors</span><span class="token punctuation">></span></span>
  8.   <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>base-config</span><span class="token punctuation">></span></span>
  9. <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>network-security-config</span><span class="token punctuation">></span></span>
複製代碼

這個檔案內容代表這個 app 信任所有憑證,包括使用者自行安裝的憑證也是。如果 app 裡面本來就有這個檔案,你可以把內容取代成上面的,確保 app 有信任使用者的憑證。
接著把 apk 打包裝回去,再按下按鈕看看,應該就能從 proxy 看到攔截到的流量:

Certificate pinning如果上面的動作做完以後,proxy 還是監聽不到,那就代表 app 裡面可能有其他安全性的設置,例如說 certificate pinning。
什麼是 certificate pinning 呢?如果網頁有用 https,就代表伺服器有一個 https 的憑證,而 certificate pinning 就代表 app 裡有指定某個 domain 對應到的憑證應該要是什麼,如果憑證不符,就代表有人在中間搞事,所以拒絕連線。
以熱門的 library OkHttp 為例,文件上就有寫說應該怎麼實作這個功能:
  1. <span class="token class-name">String</span> hostname <span class="token operator">=</span> <span class="token string">"publicobject.com"</span><span class="token punctuation">;</span>
  2. <span class="token class-name">CertificatePinner</span> certificatePinner <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CertificatePinner<span class="token punctuation">.</span>Builder</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  3.     <span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>hostname<span class="token punctuation">,</span> <span class="token string">"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="</span><span class="token punctuation">)</span>
  4.     <span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  5. <span class="token class-name">OkHttpClient</span> client <span class="token operator">=</span> <span class="token class-name">OkHttpClient<span class="token punctuation">.</span>Builder</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  6.     <span class="token punctuation">.</span><span class="token function">certificatePinner</span><span class="token punctuation">(</span>certificatePinner<span class="token punctuation">)</span>
  7.     <span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  8. <span class="token class-name">Request</span> request <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Request<span class="token punctuation">.</span>Builder</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  9.     <span class="token punctuation">.</span><span class="token function">url</span><span class="token punctuation">(</span><span class="token string">"https://"</span> <span class="token operator">+</span> hostname<span class="token punctuation">)</span>
  10.     <span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  11. client<span class="token punctuation">.</span><span class="token function">newCall</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">execute</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
複製代碼

如果想實作看看的話,可以拿這個 apk 檔來嘗試:https://github.com/aszx87410/demo/raw/master/android/demoapp-pinning.apk
我們一樣用 apktool 解開,接著先照之前那樣,把 network security config 給放進去,再來就是要找到程式碼哪裡有用到 certificate pinner 了。
因為這次的程式碼有開啟 proguard,所以連 okhttp 也被混淆了,直接用 certificatePinner 做關鍵字下去搜尋不一定找得到東西。那怎麼辦呢?我們可以換個方式,在使用這個功能的時候,一定要寫一組 sha256 的值在裡面,所以我們可以搜尋:sha256/
可以找到這樣一個段落:
  1. # virtual methods
  2. <span class="token punctuation">.</span>method <span class="token keyword">public</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token class-name">V</span>
  3.     <span class="token punctuation">.</span>locals <span class="token number">13</span>

  4.     <span class="token punctuation">.</span>line <span class="token number">1</span>
  5.     <span class="token keyword">new</span><span class="token operator">-</span>instance v0<span class="token punctuation">,</span> <span class="token class-name">Ljava</span><span class="token operator">/</span>util<span class="token operator">/</span><span class="token class-name">ArrayList</span><span class="token punctuation">;</span>

  6.     invoke<span class="token operator">-</span>direct <span class="token punctuation">{</span>v0<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token class-name">Ljava</span><span class="token operator">/</span>util<span class="token operator">/</span><span class="token class-name">ArrayList</span><span class="token punctuation">;</span><span class="token operator">-></span><span class="token generics"><span class="token punctuation"><</span>init<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token class-name">V</span>

  7.     <span class="token keyword">const</span><span class="token operator">-</span>string v1<span class="token punctuation">,</span> <span class="token string">"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="</span>

  8.     <span class="token punctuation">.</span>line <span class="token number">2</span>
  9.     filled<span class="token operator">-</span><span class="token keyword">new</span><span class="token operator">-</span>array <span class="token punctuation">{</span>v1<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token class-name">Ljava</span><span class="token operator">/</span>lang<span class="token operator">/</span><span class="token class-name">String</span><span class="token punctuation">;</span>

  10.     move<span class="token operator">-</span>result<span class="token operator">-</span>object v1

  11.     <span class="token keyword">const</span><span class="token operator">-</span>string v2<span class="token punctuation">,</span> <span class="token string">"archive.org"</span>

  12.     <span class="token keyword">const</span><span class="token operator">-</span>string v3<span class="token punctuation">,</span> <span class="token string">"pattern"</span>

  13.     <span class="token punctuation">.</span>line <span class="token number">3</span>
  14.     invoke<span class="token operator">-</span><span class="token keyword">static</span> <span class="token punctuation">{</span>v2<span class="token punctuation">,</span> v3<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token class-name">Lc</span><span class="token operator">/</span>j<span class="token operator">/</span>b<span class="token operator">/</span>d<span class="token punctuation">;</span><span class="token operator">-></span><span class="token function">d</span><span class="token punctuation">(</span><span class="token class-name">Ljava</span><span class="token operator">/</span>lang<span class="token operator">/</span><span class="token class-name">Object</span><span class="token punctuation">;</span><span class="token class-name">Ljava</span><span class="token operator">/</span>lang<span class="token operator">/</span><span class="token class-name">String</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token class-name">V</span>

  15.     <span class="token keyword">const</span><span class="token operator">-</span>string v3<span class="token punctuation">,</span> <span class="token string">"pins"</span>

  16.     invoke<span class="token operator">-</span><span class="token keyword">static</span> <span class="token punctuation">{</span>v1<span class="token punctuation">,</span> v3<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token class-name">Lc</span><span class="token operator">/</span>j<span class="token operator">/</span>b<span class="token operator">/</span>d<span class="token punctuation">;</span><span class="token operator">-></span><span class="token function">d</span><span class="token punctuation">(</span><span class="token class-name">Ljava</span><span class="token operator">/</span>lang<span class="token operator">/</span><span class="token class-name">Object</span><span class="token punctuation">;</span><span class="token class-name">Ljava</span><span class="token operator">/</span>lang<span class="token operator">/</span><span class="token class-name">String</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token class-name">V</span>

  17.     <span class="token keyword">const</span><span class="token operator">/</span><span class="token number">4</span> v3<span class="token punctuation">,</span> <span class="token number">0x0</span>

  18.     <span class="token keyword">const</span><span class="token operator">/</span><span class="token number">4</span> v4<span class="token punctuation">,</span> <span class="token number">0x0</span>
複製代碼

找到之後該做什麼呢?難道要去改 smali,把 certificate pinner 拿掉嗎?其實有更簡單的做法。
從程式碼中可以猜得出來底下那個 archive.org 應該就是綁定的網域,因此只要把這個網域隨便改成其他字串即可,如此一來其他的網域就不會檢查憑證是否相符。
改完以後重新打包 app 並安裝,就能正常監聽到流量。
像上面這樣是去改變使用 certificatePinner 的地方,還有另一個方式是直接去改變 okhttp 的實作,找到 smali 中的 okhttp3/CertificatePinner$Builder.smali,有一個 function 是:
  1. # virtual methods
  2. <span class="token punctuation">.</span>method <span class="token keyword">public</span> varargs <span class="token function">add</span><span class="token punctuation">(</span><span class="token class-name">Ljava</span><span class="token operator">/</span>lang<span class="token operator">/</span><span class="token class-name">String</span><span class="token punctuation">;</span><span class="token punctuation">[</span><span class="token class-name">Ljava</span><span class="token operator">/</span>lang<span class="token operator">/</span><span class="token class-name">String</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token class-name">Lokhttp3</span><span class="token operator">/</span><span class="token class-name">CertificatePinner</span>$<span class="token class-name">Builder</span><span class="token punctuation">;</span>
  3.     <span class="token punctuation">.</span>locals <span class="token number">5</span>
複製代碼

這個就是 okhttp 在處理新增 certificate pinner 時的方法,我們只要這樣改就好了:
  1. # virtual methods
  2. <span class="token punctuation">.</span>method <span class="token keyword">public</span> varargs <span class="token function">add</span><span class="token punctuation">(</span><span class="token class-name">Ljava</span><span class="token operator">/</span>lang<span class="token operator">/</span><span class="token class-name">String</span><span class="token punctuation">;</span><span class="token punctuation">[</span><span class="token class-name">Ljava</span><span class="token operator">/</span>lang<span class="token operator">/</span><span class="token class-name">String</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token class-name">Lokhttp3</span><span class="token operator">/</span><span class="token class-name">CertificatePinner</span>$<span class="token class-name">Builder</span><span class="token punctuation">;</span>
  3.     <span class="token punctuation">.</span>locals <span class="token number">5</span>

  4.     # patch
  5.     <span class="token keyword">const</span><span class="token operator">-</span>string p1<span class="token punctuation">,</span> <span class="token string">"abc"</span>
複製代碼

這樣第一個參數(domain)就永遠是 abc,永遠不會生效。
總結這篇文章中我們學習到了如何自己動手改造 app,拿掉一些防中間人攻擊的機制,例如說改掉 network security config 以及程式碼中處理 certificate pinning 的部分。
對於一般的 app 來說,做到這邊應該就滿夠的了,至少能夠監聽流量,看見 app 到底發送了些什麼。而且跟 VPN 的解法相比,還有另外一個好處,那就是可以二次打包,包出一個把 API 網址換掉也能動的版本,自由度比較高。

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 轉播轉播 分享分享 分享淘帖
回復

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

小黑屋|Archiver|手機版|艾歐踢創新工坊    

GMT+8, 2024-5-16 11:05 , Processed in 0.258738 second(s), 19 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表