一例簡單的frida反調(diào)試繞過
前言
最近在分析一款app時遇見了frida反調(diào)試,花了時間簡單學習了一下,有不少收獲,記錄下學習的過程。
拋出問題
frida是一個很強大的hook框架,用的人多了,自然而然就出現(xiàn)了很多檢測方案,這次碰到的app就檢測了frida,可以正常打開,但是當你用frida -f啟動或者attach進程,不久后就會閃退。
常見frida檢測
1.檢測frida-server文件名
2.檢測27042默認端口
3.檢測D-Bus
4.檢測/proc/pid/maps映射文件
5.檢測/proc/pid/tast/tid/stat或/proc/pid/tast/tid/status
6.雙進程保護
前兩種可以通過修改frida-server文件名,改默認端口繞過。雙進程可以通過-f spawn模式啟動繞過。其他的需要去hook修改。
定位
先針對簡單的幾個可能檢測的方式,我修改了文件名,改了端口,也嘗試了spawn啟動,均會在啟動后不久閃退。
這時考慮到其他幾種檢測。
首先用frida去看看載入了哪些so,看看是哪里檢測了,看了個寂寞。
function fridaProcess(){Java.perform(function () {var enumMoudle = Process.enumerateModules();for (var i = 0; i < enumMoudle.length; i++){console.log("", enumMoudle[i].name)}});}setImmediate(fridaProcess,0)

因為so載入的時候,底層最后open去打開的。
所以再用frida去hook應(yīng)用中的open函數(shù),看看讀取了哪些so或者文件,可以看到最后斷在了/proc/self/maps。
var pth = Module.findExportByName(null,"open");Interceptor.attach(ptr(pth),{onEnter:function(args){this.filename = args[0];console.log("",this.filename.readCString())if (this.filename.readCString().indexOf(".so") != -1){args[0] = ptr(0)}},onLeave:function(retval){return retval;}})

稍稍深入
這里當掛上frida后對應(yīng)的maps文件中會出現(xiàn)re.frida.server之類的特征,這是在使用frida server的時候自動創(chuàng)建的,其中存放著frida的功能模塊,可以在載入so的hook腳本輸出中能看到最后也是斷在frida-agent.so。

這里要繞過這個檢測,我是通過備份一個正常啟動時的maps文件(這里前面也講到app不使用frida是能正常啟動不閃退的)。
function main() {const openPtr = Module.getExportByName('libc.so', 'open');const open = new NativeFunction(openPtr, 'int', ['pointer', 'int']);var readPtr = Module.findExportByName("libc.so", "read");var read = new NativeFunction(readPtr, 'int', ['int', 'pointer', "int"]);var fakePath = "/data/data/com.app/maps";var file = new File(fakePath, "w");var buffer = Memory.alloc(512);Interceptor.replace(openPtr, new NativeCallback(function (pathnameptr, flag) {var pathname = Memory.readUtf8String(pathnameptr);var realFd = open(pathnameptr, flag);if (pathname.indexOf("maps") >= 0) {while (parseInt(read(realFd, buffer, 512)) !== 0) {var oneLine = Memory.readCString(buffer);if (oneLine.indexOf("tmp") === -1) {file.write(oneLine);}}var filename = Memory.allocUtf8String(fakePath);return open(filename, flag);}var fd = open(pathnameptr, flag);return fd;}, 'int', ['pointer', 'int']));}setImmediate(main)

然后就可以繼續(xù)調(diào)試了。
總結(jié)
這只是一個簡單的例子,但是確實在這個bypass的過程中學到了東西,只要花時間是去分析,總能找到對應(yīng)的突破口。
往期回顧
記一次APP登錄爆破
商務(wù)咨詢:
0571-87031601
商務(wù)郵箱:
聯(lián)系地址:
浙江省杭州市市民街98號尊寶大廈金尊3301

