Frida檢測是一種常見的安卓逆向技術(shù),常用于防止應(yīng)用程序被反向工程。如果您遇到了Frida檢測,您可以嘗試以下方法來繞過它:
-
使用Magisk Hide模塊:Magisk是一個(gè)強(qiáng)大的安卓root工具,它附帶了一個(gè)Magisk Hide模塊,可以幫助您隱藏root權(quán)限。這可以幫助您繞過Frida檢測。
-
使用Xposed框架:Xposed框架可以幫助您實(shí)現(xiàn)一些高級的安卓逆向技術(shù),包括繞過Frida檢測。您可以使用Xposed模塊來隱藏您的應(yīng)用程序信息。
-
使用Frida Gadget:Frida Gadget是一個(gè)用于Frida檢測的小型應(yīng)用程序,可以幫助您繞過檢測。將其與Frida一起使用,可以幫助您實(shí)現(xiàn)高級的安卓逆向技術(shù)。
?apk案例分析
在使用frida 附加時(shí)候發(fā)現(xiàn)進(jìn)程退出,我們首先查看是在哪里結(jié)束進(jìn)程的
function hook_dlopen() {
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
{
onEnter: function (args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
console.log("load " + path);
}
}
}
);
}
?通過 dlopen可以發(fā)現(xiàn)在模塊libnative-lib.so 執(zhí)行處進(jìn)程結(jié)束
?分析模塊libnative-lib.so,找關(guān)鍵位置
?有兩處位退出進(jìn)程位置函數(shù) check_loop通過maps 內(nèi)存中的關(guān)鍵字符串查找檢測frida.
void __fastcall __noreturn check_loop(void *a1)
{
for ( i = 0; ; ++i )
{
fd = open("/proc/self/maps", 0);
if ( fd >= 1 )
{
while ( read(fd, buf, 0x200u) >= 1 )
{
v11 = buf;
v10 = "frida";
haystack = buf;
needle = "frida";
if ( strstr(buf, "frida") )
{
v1 = getpid();
kill(v1, 9);
}
if ( sscanf(buf, "%x-%lx %4s %lx %*s %*s %s", &buf[516], &buf[512], &v5, &v4, s) == 5
&& v5 == 114
&& v6 == 112
&& !v4 )
{
strlen(s);
}
}
}
close(fd);
sleep(1u);
}
}
?通過斷點(diǎn)標(biāo)記這兩處進(jìn)程退出位置方便后續(xù)返回查看
修改位置有兩處,直接IDA keypath nop掉重打包,或這利用frida hook.下面用frida hook方式nop掉結(jié)束進(jìn)程的兩處關(guān)鍵點(diǎn)??
1.nop 掉0x9498處exit調(diào)用
?2.nop 掉0x92C2處kill
?實(shí)現(xiàn)代碼如下
//指令輸出
function dis(address, number) {
for (var i = 0; i < number; i++) {
var ins = Instruction.parse(address);
console.log("address:" + address + "--dis:" + ins.toString());
address = ins.next;
}
}
/*call_function
static void call_function(const char* function_name __unused,
linker_ctor_function_t function,
const char* realpath __unused //加載的當(dāng)前模塊路徑
)
}*/
function hook() {
//call_function("DT_INIT", init_func_, get_realpath());
var linkermodule = Process.getModuleByName("linker");
var call_function_addr = null;
var symbols = linkermodule.enumerateSymbols();
for (var i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
if (symbol.name.indexOf("__dl__ZL13call_functionPKcPFviPPcS2_ES0_") != -1) {
call_function_addr = symbol.address;
}
}
Interceptor.attach(call_function_addr, {
onEnter: function (args) {
var type = ptr(args[0]).readUtf8String();
var address = args[1];
var sopath = ptr(args[2]).readUtf8String();
console.log("loadso:" + sopath + "--addr:" + address + "--type:" + type);
if (sopath.indexOf("libnative-lib.so") != -1) {
var libnativemodule = Process.getModuleByName("libnative-lib.so");
var base = libnativemodule.base;
//nop kill
// .text:000092BA B loc_92BC
// .text:000092BC ; ---------------------------------------------------------------------------
// .text:000092BC
// .text:000092BC loc_92BC ; CODE XREF: check_loop(void *)+5E↑j
// .text:000092BC BLX getpid
// .text:000092C0 MOVS R1, #9 ; sig
// .text:000092C2 BLX kill
console.log("---------------- nop kill begin -------------")
dis(base.add(0x92BA).add(1), 10);
//方式一修改內(nèi)存
// Memory.protect(base.add(0x92C2), 4, 'rwx');
// base.add(0x92C2).writeByteArray([0x00, 0xbf, 0x00, 0xbf]);
//方式二修改內(nèi)存
var patchaddr=base.add(0x92C2);
Memory.patchCode(patchaddr, 4, patchaddr => {
var cw = new ThumbWriter(patchaddr);
cw.putNop();
var cw = new ThumbWriter(patchaddr.add(0x2));
cw.putNop();
cw.flush();
});
console.log("++++++++++++ nop kill end +++++++++++++")
dis(base.add(0x92BA).add(1), 10);
// nop exit
// .text:0000948E CMP R0, #0
// .text:00009490 BEQ loc_949C
// .text:00009492 B loc_9494
// .text:00009494 ; ---------------------------------------------------------------------------
// .text:00009494
// .text:00009494 loc_9494 ; CODE XREF: anti_frida_loop(void)+26↑j
// .text:00009494 MOV.W R0, #0xFFFFFFFF ; status
// .text:00009498 BLX exit
console.log("--------------- nop exit begin -------------")
dis(base.add(0x948E).add(1), 10); //keystone
Memory.protect(base.add(0x9498), 4, 'rwx');
base.add(0x9498).writeByteArray([0x00, 0xbf, 0x00, 0xbf]);
console.log("+++++++++++++++ nop exit end +++++++++++++")
dis(base.add(0x948E).add(1), 10);
}
}
})
}
function main(){
hook();
}
setImmediate(main);
?總結(jié):
繞過Frida檢測的方法有很多種,以下是一些可能的方法:
1. 使用Frida Bypass插件:這是一款Frida插件,可以自動(dòng)繞過Frida檢測,并讓Frida無法對應(yīng)用程序進(jìn)行監(jiān)控。
2. 使用Frida Gadget庫:這是一個(gè)動(dòng)態(tài)Frida庫,可以在運(yùn)行時(shí)注入Frida,以避免被檢測到。
3. 修改應(yīng)用程序代碼:通過修改應(yīng)用程序代碼,可以讓Frida無法監(jiān)控應(yīng)用程序。
4. 使用防檢測框架:有些防檢測框架可以繞過Frida的檢測,例如Xposed框架、VirtualXposed、Magisk等。文章來源:http://www.zghlxwxcb.cn/news/detail-556626.html
5. 使用其他工具:除了Frida,還有其他工具可以用來監(jiān)控應(yīng)用程序,例如Xposed、Cydia Substrate等。如果使用這些工具,F(xiàn)rida將無法監(jiān)控應(yīng)用程序。文章來源地址http://www.zghlxwxcb.cn/news/detail-556626.html
到了這里,關(guān)于android frida檢測繞過的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!