
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)設(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)
- 實(shí)驗(yàn)方法步驟
- API觀察:觀察SDK公開API;
- .o對象觀察:觀察dump之后獲得的.o對象;
- 偽代碼觀察:觀察關(guān)鍵.o反編譯得出的偽代碼邏輯;
- 注意事項(xiàng)
- 注意Hopper的偽代碼生成在不同platform下可能有所不同;
- 注意分析目標(biāo)可能使用的系統(tǒng)API;
- 注意分析目標(biāo)可能存在的問題;
實(shí)驗(yàn)過程記錄
首先,使用classdump或者h(yuǎn)opper對BugTags.framework進(jìn)行分析,如圖:

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

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


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


其余兩個(gè)平臺的截圖由于沒有更多有用的信息,在這里就不放出來了。
接下來,我們可以在之前的function dump中找到對應(yīng)的三個(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);
}