解剖室一:BugTags的控制臺日志收集

解剖也有美感

BugTags 是目前最好的App運(yùn)行時(shí)狀態(tài)數(shù)據(jù)收集的第三方解決方案之一,官網(wǎng)上沒有明顯位置的簡介,所以需要更多了解請移步到BugTags

實(shí)驗(yàn)序號:001
實(shí)驗(yàn)名稱:解剖BugTags的控制臺日志收集方式
實(shí)驗(yàn)時(shí)間:2016年10月10日
實(shí)驗(yàn)地點(diǎn):學(xué)霸君(上海)辦公室
實(shí)驗(yàn)?zāi)康模赫{(diào)查BugTags對于控制臺的日志收集方案


實(shí)驗(yàn)原理、實(shí)驗(yàn)流程或裝置示意圖

實(shí)驗(yàn)原理:通過反編譯獲取對應(yīng)的邏輯塊,對邏輯塊代碼進(jìn)行分析


實(shí)驗(yàn)流程示意圖.jpg

實(shí)驗(yàn)設(shè)備及材料

實(shí)驗(yàn)材料:
a、BugTags SDK Version:1.3.1

實(shí)驗(yàn)設(shè)備:
a、Hopper (反編譯)
b、Xcode (驗(yàn)證結(jié)論)


實(shí)驗(yàn)方法步驟及注意事項(xiàng)

  1. 實(shí)驗(yàn)方法步驟
  • API觀察:觀察SDK公開API;
  • .o對象觀察:觀察dump之后獲得的.o對象;
  • 偽代碼觀察:觀察關(guān)鍵.o反編譯得出的偽代碼邏輯;
  1. 注意事項(xiàng)
  • 注意Hopper的偽代碼生成在不同platform下可能有所不同;
  • 注意分析目標(biāo)可能使用的系統(tǒng)API;
  • 注意分析目標(biāo)可能存在的問題;

實(shí)驗(yàn)過程記錄

首先,使用classdump或者h(yuǎn)opper對BugTags.framework進(jìn)行分析,如圖:

class-dump.png

和大多數(shù)第三方提供的SDK一樣,BugTags也提供了四種平臺下靜態(tài)庫文件,其中x86_64和i386是提供給模擬器使用,ARM提供給真機(jī)使用。然后使用otool來查看靜態(tài)庫中的.o對象,如圖:

真慶幸一個(gè)屏幕裝得下

根據(jù)上圖的結(jié)果,我們可以找出疑似Log收集的類BTGLoggerCatcher。當(dāng)然還可以看到一些SDK內(nèi)部的其他功能。接著,我們用Hopper來進(jìn)一步對這個(gè)類進(jìn)行分析,如圖:

Function List 1
Function List 2

相關(guān)方法很顯然有setTrackingConsoleLog:和updateConsoleLogs兩個(gè)。
分析setTrackingConsoleLog:

ARM7 Platform
x86_64

其余兩個(gè)平臺的截圖由于沒有更多有用的信息,在這里就不放出來了。

接下來,我們可以在之前的function dump中找到對應(yīng)的三個(gè)block:

三個(gè)Block

接著,我們在其中一個(gè)block反編譯出來的偽代碼中找到了蛛絲馬跡:


蛛絲馬跡

顯然,我們直接去看一看updateConsoleLog的邏輯應(yīng)該就可以找到我們需要的結(jié)果了:


宇宙真理

從這段偽代碼中,我們大概可以看到Bugtags中用到了幾個(gè)叫asl_xxx的API,于是我在Xcode中搜索了一下找到了asl.h這個(gè)頭文件,并且查看了一些函數(shù)說明,得出猜想,BugTags使用了這些API完成對控制臺日志的收集。于是我仿照偽代碼寫了一段代碼來進(jìn)行了驗(yàn)證。

- (void)query {
    pid_t pid = getpid();
    asl_object_t query = asl_new(ASL_TYPE_QUERY);
    asl_object_t searched = asl_search(nil, query);
    
    asl_object_t msgObj = aslresponse_next(searched);
    
    while (msgObj) {
        if (pid == atol(asl_get(msgObj, "PID"))) {
            long mid = atoll(asl_get(msgObj, "ASLMessageID"));
            long time = atol(asl_get(msgObj, "Time"));
            long timeNano = atol(asl_get(msgObj, "TimeNanoSec"));
            const char *msg = asl_get(msgObj, ASL_KEY_MSG);
            
            printf("pid: %d ASLMessageID: %ld Time: %ld TimeNanoSec: %ld Message: %s\n", pid, mid, time, timeNano, msg);
        }
        msgObj = aslresponse_next(searched);
    }
    
    aslresponse_free(searched);
    asl_free(query);
}

感謝各位看官
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容