Textobot-TB插件進程級API詳解&基礎篇完結

導讀

0x00.交個朋友

0x01.Frida簡介

0x02.界面類API

0x03.按鍵類API

0x04.工具類API

0x05.基礎篇完結

0x06.定製服務

0x07.關於劉柏江


0x00.交個朋友

手遊從業者模擬器玩家請關注雲遊模擬器PantaWin;

Android開發者請關注雲遊模擬器
PantaWin/PantaMac/PantaLinux;

iOS越獄開發者請關注曉文框架Textobot;

Android插件開發者請關注飛度框架Fridobot;

移動調試器重度用戶請關注利達調試器LidaDbg;

我們的產品推薦使用git下載和更新,在碼雲搜索geekneo即可。


0x01.Frida簡介

我注意到Frida是2015年,那時Frida剛面世一年多,但是功能已經把我震撼到了。多平臺支持、腳本化、Native橋接、高級插樁等功能對於逆向工程和動態分析的效率提升那是相當的巨大。

Frida最大的特色就是用JavaScript腳本化了動態插樁這一過程。我們通過編寫JavaScript代碼就可以達到利用Native+
Substrate/Substitution/Detours/FishHook等組合編寫的動態分析模塊效果。同時,Frida對於Native的橋接工作也是做得非常出色,我們可以用JavaScript非常輕鬆的調用Native的函數和Objective-C類接口,所以也就可以寫出很強大的腳本代碼了。

但是有一個很大的侷限性就是,Frida需要藉助桌面平臺的客戶端發送JavaScript代碼到目標App。如果是通過frida-gatget模塊注入又需要修改目標App,所以不管用哪種方式要持久化的執行JavaScript,在官方提供的接口裡面都沒有現成的。針對這個缺陷,Textobot用TB插件的模式彌補了Frida沒有持久化的問題。同時,為了方便編寫實用的TB插件,Textobot還導出了一些輔助性的C API。這個在
TBROOT/Template/textobot.js中可以看到它的用法,如下:

<code>// ensure our module is loaded
const libtextobot = Module.load('/Library/MobileSubstrate/DynamicLibraries/textobot.dylib');
function TB_api(name, rettype, argstype) {
    return new NativeFunction(libtextobot.getExportByName(name), rettype, argstype);
}
​
// pickup textobot APIs
const textobot = {
    TB_logpath      : TB_api('TB_logpath', 'pointer', []),
    TB_logbuff      : TB_api('TB_logbuff', 'pointer', []),
    TB_logflush     : TB_api('TB_logflush', 'int', []),
    TB_dialog       : TB_api('TB_dialog','int', ['pointer']),
    TB_system       : TB_api('TB_system','int', ['pointer']),
    TB_root_system  : TB_api('TB_root_system', 'int', ['pointer']),
    TB_window       : TB_api('TB_window', 'pointer', []),
    TB_touch        : TB_api('TB_touch', 'int', ['int', 'int']),
    TB_swipe        : TB_api('TB_swipe', 'int', ['int', 'int', 'int', 'int']),
    // API likes TB_*_new should call TB_sptr_free to free the heap memory
    // see free function bellow
    TB_appdir_new   : TB_api('TB_appdir_new', 'pointer', []),
    TB_docdir_new   : TB_api('TB_docdir_new', 'pointer', []),
    TB_tmpdir_new   : TB_api('TB_tmpdir_new', 'pointer', []),
    TB_urlget_new   : TB_api('TB_urlget_new', 'pointer', ['pointer']),
    TB_urlpost_new  : TB_api('TB_urlpost_new', 'pointer', ['pointer', 'pointer']),
    TB_sptr_free    : TB_api('TB_sptr_free', 'void', ['pointer']),
    // ...
    // see https://gitee.com/geekneo/Textobot/blob/master/Doc/api.md for more APIs
};
​
// put the string to textobot's native buffer
function puts(s) {
    // logbuff's size is 4096
    if (s.length >= 4096) {
        console.log('Ignoring long string ' + s.length);
        return;
    }
    textobot.TB_logbuff().writeUtf8String(s);
    return textobot.TB_logbuff();
}
​
// wrap logger util
function logs(s) {
    puts(s);
    textobot.TB_logflush();
}
​
// wrap free util
function free(ptr) {
    var sptr = puts(ptr.toString(16));
    textobot.TB_sptr_free(sptr);
}
​
// slow logger, usually for global log
console.log("The textobot template plugin's log file is at " + 
    textobot.TB_logpath().readUtf8String());
​
// fast log, usually for hooker with better performance
logs('The textobot template plugin is running ...');
​
function demo_impl() {
    const appdir = textobot.TB_appdir_new();
    // show a dialog
    // the first line is TITLE
    // the left lines is CONTENT
    textobot.TB_dialog(puts(
        'Textobot Tips' +
        '\n' +
        'The textobot template plugin is running inside ' +
        appdir.readUtf8String()
    ));
​
    // API ends with _new should call free deallocate the heap memory
    free(appdir);
}/<code>

當前的Textobot是以獨立模塊的方式集成Frida,所以只能提供C API,然後通過Frida的NativeFunction橋接一下才可以使用。這樣的模式使用起來稍微麻煩一些,直接擴展Frida的JavaScript運行時當然是最佳方案了,這個留著後面更新時再說了吧,我們現階段的目標是穩定、夠用。

Frida的使用需要iOS SDK開發經驗,門檻略高。關於它的詳細使用方法請參考官方文檔,在這裡我們著重指出對於Textobot而言最核心的一點,Objective-C橋接。

<code>const NSURL = ObjC.classes.NSURL;
Interceptor.attach(NSURL['- initWithString:'].implementation, {
    onEnter: function (args) {
        var inst = new ObjC.Object(args[2]);
        logs(inst.UTF8String() + '\ninitWithString\n' + backtrace(this.context) + '\n');
    }
});/<code>

我們通過ObjC.classes就可以導入Objective-C類到JavaScript,這個和Pyobjus的autoclass是一樣的效果。然後就可以調用類的方法了,非常方便。

Textobot-TB插件進程級API詳解&基礎篇完結


0x02.界面類API

<code>int TB_dialog(const char *lines);
在運行的App內彈出一個提示框;
lines[0] = title:提示框標題;
lines[1...] = content:提示框內容;/<code>



0x03.按鍵類API

<code>int TB_touch(int x, int y);
x:點擊x座標;
y:點擊y座標;
​
int TB_swipe(int x1, int y1, int x2, int y2);
x1,y1:滑動起始座標;
x2,y2:滑動終止座標;
Note:iOS版本小於10.0的系統需要安裝TBROOT/iOS/Util/SimulateTouch-iOS8_9.deb插件;
/<code>



0x04.工具類API

<code>const char *TB_logpath();
獲取日誌文件路徑;
​
char *TB_logbuff();
獲取日誌文件可寫入的內存地址;
​
int TB_logflush();
如果對TB_logbuff返回的地址寫入了日誌字符串,使用此函數刷新至文件;
如果創建日誌文件失敗,則返回errno指向的值;
​
樣例代碼:
// put the string to textobot's native buffer
function puts(s) {
    // logbuff's size is 4096
    if (s.length >= 4096) {
        console.log('Ignoring long string ' + s.length);
        return;
    }
    textobot.TB_logbuff().writeUtf8String(s);
    return textobot.TB_logbuff();
}
​
// wrap logger util
function logs(s) {
    // 寫入緩存
    puts(s);
    // 寫入文件
    textobot.TB_logflush();
}
​
​
UIWindow *TB_window();
獲取當前顯示的UIWindow對象;
​
void TB_system(const char *cmds);
以當前App所在的用戶組同步執行cmds命令;
​
void TB_root_system(const char *cmds);
以root用戶異步執行cmds命令;
​
char *TB_appdir_new();
獲取當前運行的App根目錄,需要調用TB_sptr_free釋放返回內存;
​
樣例代碼:
// wrap free util
function free(ptr) {
    // 將NativePointer對象轉為字符串並寫入內部緩存
    var sptr = puts(ptr.toString(16));
    // 釋放字符串內容指向的內存
    textobot.TB_sptr_free(sptr);
}
​
const appdir = textobot.TB_appdir_new();
...
free(appdir);
​
​
char *TB_docdir_new();
獲取當前運行的App文檔目錄,需要調用TB_sptr_free釋放返回內存;
​
char *TB_tmpdir_new();
獲取當前運行的App臨時目錄,需要調用TB_sptr_free釋放返回內存;
​
char *TB_urlget_new(const char *url);
執行HTTP Get請求,需要調用TB_sptr_free釋放返回內存;
​
char *TB_urlpost_new(const char *url, const char *body);
執行HTTP Post請求,需要調用TB_sptr_free釋放返回內存;
​
void TB_sptr_free(const char *sptr);
釋放字符串內容指向的內存地址,比如"0x188880000";/<code> 

在這裡我們單獨封裝了一組高性能的log函數,這個用於頻繁寫日誌時使用,比如需要打印很多App運行時信息時。函數TB_logpath返回值也是對應到TB編輯器Log配置參數的,用於通過VSCode Textobot Editor - AppLog命令返回這一組log函數的輸出。之所以單獨提供這樣的函數,是因為Frida自帶的console.log需要通過IPC傳遞到調度器交給Python的print函數輸出,對於頻繁的輸出,這個性能是不具有任何實用性的,巨慢無比。


0x05.基礎篇完結

好了,到此為止,我們通過8篇文章把Textobot所有的基礎內容完整的介紹了一遍。如果每一篇你都有看完,我想你應該就具備了通過Textobot編寫一些實用TB插件的能力了。以下,我們總結一下Textobot到底為何物。

Textobot是一款基於文本的越獄插件框架,可擴展腳本基於Python實現。目標App動態修改框架,基於Frida JavaScript API實現。Textobot的設計目標是替換現有的Cydia deb插件系統。你可以僅僅使用Python+JavaScript就可以擁有deb/dylib插件的全部能力,並且維護、更新、分發十分容易,開發效率比Native也提高很多。

在Textobot插件的生命週期中,Python運行在系統級別,JavaScript運行在進程級別。代碼編輯器使用VSCode,textobot-editor插件提供腳本代碼編寫、運行、打包等功能。在裝有textobot-editor插件的VSCode中,可以直接編輯Python或者JS代碼發送到手機端執行。


TBROOT/Sample/AppleIDLogin,這個用於演示如何使用Textobot編寫自動化的插件。

TBROOT/Sample/SimpleGUI,這個用於演示如何使用Textobot編寫GUI交互式的插件。

TBROOT/Sample/URLCapture,這個用於演示如何使用Textobot編寫綜合性的插件,同時使用Python系統模式和JavaScript進程模式。

TBROOT/Sample/Httpeek、TBROOT/Sample/Httpeek.src,這個用於演示如何使用Textobot編寫更具現實意義的插件,同時使用Python系統模式、JavaScript進程模式、複用Native插件代碼。


0x06.定製服務

我們團隊雖小,但個個都是一頂三的技術精英,因此技術能力是嚴重過剩的。所以如果您有任何關於iOS/Android底層的疑難雜症、雲遊模擬器掛機/二次開發、曉文/飛度插件定製等方面的個性化需求,歡迎通過私信聯繫我們。


0x07.關於劉柏江

8年移動互聯網從業經驗、精通iOS/Android底層開發/攻防對抗、GikDbg/KiwiVM原作者、幾維安全聯合創始人/股東。

我的自媒體賬號將圍繞PantaEmu、Textobot、Fridobot、LidaDbg為用戶朋友們傳道、授業、解惑。歡迎各位朋友關注、點贊、轉發,謝謝大家。


分享到:


相關文章: