Categories: androidpython

smalidea remote debugging with android-studio

想要知道某個 apk 要怎麼連線

許多 apk 也都是用網路獲取服務以及下載資訊,不過都是 https 連線相當地安全。即使是用 tcpdump 等等工具,其實都只會看到加密過的資料在傳來傳去,不知道裡面參數到底是什麼。

那麼有沒有辦法知道這個 apk 是如何發起連線的呢?

是可以的,既然手機上有安裝 apk,資訊是都在裡面的,雖然大部分都沒有辦法反組譯回到原本的 java 程式,但是還是可以透過類似 asmsmali 語言看到在做些什麼事,
再透過 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 的步驟當作參考

  1. 安裝 Android-Studio (4.2.1)
  2. 安裝 smalidea 的 plugin (smalidea-0.06.zip)
  3. File -> Open 選擇剛剛 apktool 解開的目錄 com.she.eReader_2021-04-16
  4. 在 smali2 上右鍵選擇 Mark Directory as Generated Source Root
  5. 也許需要在 smali 上也要 Mark Directory as Generated Source Root
  6. 關掉重開,接著 Android-Studio 會自行重新 reconfigurate
  7. 在 Android-Emulator 上安裝 apk,順便執行
  8. 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())
yumaokao

Recent Posts

Invoke Method with JDWP

smali breakpoin...

2 年 ago

tetris3d with plotly

魔術磁力方塊好好玩 魔術磁力方...

3 年 ago

AliasDict, a python dict for alias resolver

用 dict 存 alias ...

3 年 ago

hashcat sha256 from mac address

只給一天期限的憑證檔案 去年幫...

3 年 ago

python rich with asyncio

python rich 畫圖很...

3 年 ago