想要知道某個 apk 要怎麼連線
許多 apk 也都是用網路獲取服務以及下載資訊,不過都是 https 連線相當地安全。即使是用 tcpdump 等等工具,其實都只會看到加密過的資料在傳來傳去,不知道裡面參數到底是什麼。
那麼有沒有辦法知道這個 apk 是如何發起連線的呢?
是可以的,既然手機上有安裝 apk,資訊是都在裡面的,雖然大部分都沒有辦法反組譯回到原本的 java 程式,但是還是可以透過類似 asm 的 smali 語言看到在做些什麼事,
再透過 smalidea 的幫忙,更可以利用 Android-Studio 遠端連線到 Android-Emulator 上的這隻程式,看看目前正在執行那段程式,記憶體上是什麼樣的值。
用 apktool 反組譯 apk
首先得先裝到 apk,網路上現在有很多 apk 的收集網站,可以挑一個就可以把想到版本的 apk 給抓下來。
那麼反組譯 apk 是容易的,只要透過 apktool 就可以,如果是 Arch Linux 的話就 yay 安裝即可。
$ yay -S apktool
#open url to download apk
$ apktool d install/apks/com.she.eReader_2021-04-16.apk
$ ls com.she.eReader_2021-04-16/smali*
如此就可以看到這個 apk 的 code 都被反組譯在 smali 等等的資訊夾裡面了,大致上透過這些就可以推斷原本的 jave 是怎麼寫的,有那一些 classes 以及裡面有那些 methods。
安裝 smalidea 到 Android-Studio
雖然可以看到 apk 裡面的 smali 的 code 了,但要憑空猜測會有什麼結果其實是相當困難,尤其是遇到網路傳回來的資料,是要真的跑過連過才會知道的,所以如果真的可以在程式跑得時候能夠中斷暫停下來,好好地觀察上面各個變數以及暫存器上的值就再好也不過了。
而 Android-Studio 上面就有一個 plugin 可以方便顯示 smali 語言在執行時期的資訊,叫做 smalidea,可以在他們的官方網站下載並且手動安裝上。
不過官方 github 的說明以及網路上查到怎麼接上去的方法實在太眼花撩亂,底下就分享我最近自行試過可以成功接上遠端 Android Process 的步驟當作參考
- 安裝 Android-Studio (4.2.1)
- 安裝 smalidea 的 plugin (smalidea-0.06.zip)
- File -> Open 選擇剛剛 apktool 解開的目錄 com.she.eReader_2021-04-16
- 在 smali2 上右鍵選擇 Mark Directory as Generated Source Root
- 也許需要在 smali 上也要 Mark Directory as Generated Source Root
- 關掉重開,接著 Android-Studio 會自行重新 reconfigurate
- 在 Android-Emulator 上安裝 apk,順便執行
- Run -> Attach Debugger to Android Process
如果能夠看到像這樣的話,應該可以正常選擇到 Process 遠端接上去了。
使用 Android-Emulator 來跑
能夠用 debugger 接上去正在跑的 apk,查到網頁的說明是有幾種方法。而通常可以下載到的 apk,應該都不是 Debug mode,所以是接不上去的。
雖然嘗試過用 apktool 然後更改 AndroidManifest.xml 自行加上 debug mode 再包起來,其實也是無法安裝,畢竟沒有相同的簽章。而其他的方法可能都需要一隻 rooted 的手機更改才行。
所以最方便推薦地就還是用 Android-Emulator 來跑了,環境也相對乾淨。
而特別注意的是,看到 smalidea 的 issue/16 說到,要正確看到 register 的話,最好是 Android 11(R) 之後。
的確是如此,原本用的 emulator 是跑 api-28 的,雖然可以接上去設定中斷點看到 memory 放什麼,但 register 都選不到,必須要換成 api-30 的 emulator 才都可以。
遠端 debug apk
那麼就已想要的部份設定中斷點觀察吧,一開始想做的就是看看怎麼樣下載資料的,所以稍微查找了一下把斷點停在要 connect() 之前。
如下圖一樣,而右下的部份就可以選擇 register 來觀察,以這邊為例其實就可以看到送出去的 https 的 url 是什麼,以及 requestHeaders 是帶出去些什麼選項。
雖然沒有那麼直接,但已經知道怎麼發 http request 了,就可以來自行寫個小程式連連看是不是也可以下載,
curl -v -L --http1.1 \
-H 'Os: Android' \
-H 'Accept: Application/json-v1' \
-H 'Ver: 5.83' \
-H 'App: HamiBook' \
-H 'Vendor: google' \
-H 'Model: sdk_gphone_x86_arm' \
-H 'OsVer: 11' \
-H 'Accept-Encoding: identity' \
-H 'User-Agent: Dalvik/2.1.0 (Linux; U; Android 11; sdk_gphone_x86_arm Build/RSR1.201013.001)' \
--output a.zip \
"https://bookfeed.kollect.com.tw/books/getBookByParms?sessionKey=guest&book_id=0100320028&format=5&resolution=432&device=gphone&isTrial=0&type=r&pkgid=PKG_10001"
執行下去是真的可以的,雖然抓回來的 a.zip 還不是真正的 zip 檔案,不過是的確有東西大量的存起來,接著就來看但原本 apk 下載完之後接下來都做些什麼處理,用相同的方式繼續即可。
也許
為了這個又裝了很巨大的 Android-Studio,也必須要另外跑一個 Android-Emulator,不過如果能夠都知道如何處理這些網路服務的話,最終其實就是連 Android-Emulator 都不必跑的,也會更 reliable。感謝 apktool 以及 smalidea 提供了這麼有趣的東西。
更新 2021-06-17
def extract(book_id, data_dir):
m = hashlib.md5()
md5_input = ''.join([d for d in book_id if d not in ['3', book_id[-1]]])
m.update(md5_input.encode('ascii'))
zip_pswd = m.hexdigest()
print(md5_input)
print(zip_pswd)
zip_path = data_dir / f'{book_id}.zip'
with zipfile.ZipFile(zip_path) as z:
z.extract(
'content.pdf',
path=data_dir / f'{book_id}', pwd=m.hexdigest().encode())