天天看點

【Android視訊号資訊擷取①】

*在2019年深圳上班的時候 那時候還是個Java 碼農 接觸了一下 Xposed.時隔多年 忘記差不多了 用frida先來練練手 新公司又讓我研究微信視訊号擷取個人的視訊首頁标題清單 *

确定微信版本

  • 不同版本微信hook點不一樣。

預想實作方式

  • 用Xposed去請求注冊一個中轉服務 然後腳本請求中轉服務
    • 實作:可以所有号都去處理業務 也可以用一部分号去做查詢請求
    • 難點:Xp會污染手機環境 微信檢測點太多
  • 用單獨伺服器hook微信去搭建一個中轉 然後腳本請求
    • 實作:利用微信其他端(pc) 協定或者hook 專門分部分号去做服務
    • 難點:pc協定是否穩定 pchook 逆向

服務設計思路

服務應該滿足 組 端 點 可以用sekiro治理

組:不同業務 友善拓展 例如以後需要視訊号 或者其他等業務 防止污染
    端:不同的用戶端處理在某一個組下隻處理同一種業務 友善查詢管理
    點:針對于端去調用某個函數 例如 以後同一個業務下 不同的函數查詢
           

難點

  • 多程序共享資料

    目前解決方案:利用系統廣播來傳遞資料

  • 微信hook位置

    整個項目 最最最麻煩的東西 需要不斷調試 分析

預想期望

搜尋擷取使用者資訊

入參 賬号名

傳回 類json 或者 protobuf (會有唯一賬号id)

擷取使用者首頁視訊

入參 賬号id

傳回 類json 或者 protobuf 首頁視訊資訊 标題 視訊id 等等

實戰分析

打開視訊号主 首頁 查詢 activity :

adb shell dumpsys activity top

com.tencent.mm/.plugin.finder.feed.ui.FinderProfileUI

【Android視訊号資訊擷取①】

但是我并沒有找到資料請求的地方 這個應該是有個中轉的activity 上面這個 應該就是個顯示頁

搜尋一番發現了Monitor這個工具 可以跟蹤執行路徑

【Android視訊号資訊擷取①】

利用GDA或者Jadx跟蹤到這個類 發現這應該就是一個資料組裝的構造函數

【Android視訊号資訊擷取①】

繼續網下翻 可以看到 裡面還有資料解析方法

【Android視訊号資訊擷取①】

是以這個類 我們可以猜到應該就是資料組包和請求的一個類~ 我們寫腳本驗證一下

//請求的資料
let NetSceneFinderUserPage = Java.use("com.tencent.mm.plugin.finder.cgi.eg");
NetSceneFinderUserPage["$init"].overload('java.lang.String', 'long', 'com.tencent.mm.cg.b', 'int', 'com.tencent.mm.protocal.protobuf.chn', 'int', 'long', 'boolean', 'java.lang.String', 'long', 'java.lang.Integer', 'java.lang.Long', 'java.lang.String', 'boolean', 'boolean', 'java.lang.Long', 'int', 'kotlin.g.b.k').implementation = function (str, j, c14425b, i, chnVar, i2, j2, z, str2, j3, num, l, str3, z2, z3, l2, i3, c100738k) {
    console.log('$init is called' + ', ' + 'str: ' + str + ', ' + 'j: ' + j + ', ' + 'c14425b: ' + c14425b + ', ' + 'i: ' + i + ', ' + 'chnVar: ' + chnVar + ', ' + 'i2: ' + i2 + ', ' + 'j2: ' + j2 + ', ' + 'z: ' + z + ', ' + 'str2: ' + str2 + ', ' + 'j3: ' + j3 + ', ' + 'num: ' + num + ', ' + 'l: ' + l + ', ' + 'str3: ' + str3 + ', ' + 'z2: ' + z2 + ', ' + 'z3: ' + z3 + ', ' + 'l2: ' + l2 + ', ' + 'i3: ' + i3 + ', ' + 'c100738k: ' + c100738k);
    let ret = this.$new(str, j, c14425b, i, chnVar, i2, j2, z, str2, j3, num, l, str3, z2, z3, l2, i3, c100738k);
    console.log('$init ret value is ' + ret);
    return ret;
};
//響應的資料
let FinderPreloadTransform = Java.use("com.tencent.mm.plugin.finder.preload.g");
FinderPreloadTransform["a"].overload('com.tencent.mm.protocal.protobuf.cgh', 'java.util.List', 'int').implementation = function (cghVar, list, i) {
    console.log('a is called' + ', ' + 'cghVar: ' + cghVar + ', ' + 'list: ' + list + ', ' + 'i: ' + i);
    let ret = this.a(cghVar, list, i);
    console.log('a ret value is ' + ret);
    return ret;
};
           
【Android視訊号資訊擷取①】

可以看到每次請求确實會走這裡 而且第一個參數就是視訊号的使用者名:

v2_060000231003b20faec8c5e********************@finder

解析響應的list裡面也會包含标題 id等一堆資訊 這樣就拿到了我需要的标題 id 等資訊了

接下來就去找找怎麼執行這個請求

尋找構造函數的交叉引用 有很多

【Android視訊号資訊擷取①】

我們列印一下堆棧 看一下執行流程 (為什麼是列印堆棧而不是選擇交叉引用 因為這個點浪費了我很多 時間 就是它的類很多都是抽象方法 往上手動跟蹤的話 會找到未實作的方法!)

【Android視訊号資訊擷取①】

可以看到我們開始沒有定位到的UI界面 繼續跟進去

【Android視訊号資訊擷取①】

在onCreate 函數中 他會擷取 FinderProfileFeedLoader 對象 繼承 BaseFinderFeedLoader

【Android視訊号資訊擷取①】
【Android視訊号資訊擷取①】

接下來我的思路就變成了 構造 FinderProfileFeedLoader 對象 然後調用requestRefresh() 方法

【Android視訊号資訊擷取①】

構造方法也很簡單 第一個參數是枚舉類型 第二個是使用者名 第三個是chn對象 後面是boolean

hook輸出一下參數列印 如下

【Android視訊号資訊擷取①】

開始構造執行請求

【Android視訊号資訊擷取①】

調用函數 執行重新整理 完美~

【Android視訊号資訊擷取①】

後面發現視訊多 需要翻頁這麼執行就不行了 同上繼續跟蹤

【Android視訊号資訊擷取①】

這麼簡單 翻頁?執行一下就行了

【Android視訊号資訊擷取①】

發現還是第一頁 原來是它第二個構造參數變成了 擷取視訊 id

【Android視訊号資訊擷取①】

可以填充data 或者 自己hook參數 改需要翻頁的視訊id就行了~ 感興趣自己研究一下

待續…