注:本文使用了自編譯魔改的Frida!!!
分析
通過hook dlopen
,打印加載的so,發現到libmsaoaidsec.so
後frida就閃退,由此可知libmsaoaidsec.so
中有檢測frida的邏輯。
通常很多檢測frida的邏輯都會使用fopen
函數打開/proc/self/
中的文件( 如/proc/self/maps
),以此來尋找是否存在frida的特徵。
而fopen底層的系統調用號是__NR_openat
,嘗試使用https://github.com/ngiokweng/Frida-Seccomp來監控該系統調用。
Hook驗證猜想
在保存的log裡搜索libmsaoaidsec.so
,目標是調用棧中出現libmsaoaidsec.so
的那些。
第一個打開了:/proc/15547/cmdline
第二個打開了:/proc/self/maps
第一個大機率不是檢測點,而是其他某些操作?因為不論是在注入frida前後,它的內容都不會變。
而第二個則大機率是檢測點,通過hook來驗證下。
由於0x18a34
是由.init_proc
裡的函數調用的,因此不能直接hook,而是要先hook .init_proc
,再hook 0x18a34
。
或者通過方法二( 取巧 ): 這種取巧的方式來hook .init_proc
裡調用的函數。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| let flag = false; function hook_libmsaoaidsec(offset){ let baseAddr = Module.findBaseAddress("libmsaoaidsec.so")
Interceptor.attach(baseAddr.add(0x18a34), { onEnter: function(){ console.log("[0x18a34] call"); }, onLeave: function(){ console.log("[0x18a34] leave")
} })
}
function hook_constructor() { if (Process.pointerSize == 4) { var linker = Process.findModuleByName("linker"); } else { var linker = Process.findModuleByName("linker64"); } var addr_call_function =null; var addr_g_ld_debug_verbosity = null; var addr_async_safe_format_log = null; if (linker) { var symbols = linker.enumerateSymbols(); for (var i = 0; i < symbols.length; i++) { var name = symbols[i].name; if (name.indexOf("call_function") >= 0){ addr_call_function = symbols[i].address; } else if(name.indexOf("g_ld_debug_verbosity") >=0){ addr_g_ld_debug_verbosity = symbols[i].address; ptr(addr_g_ld_debug_verbosity).writeInt(2); } else if(name.indexOf("async_safe_format_log") >=0 && name.indexOf('va_list') < 0){ addr_async_safe_format_log = symbols[i].address; } } } if(addr_async_safe_format_log){ Interceptor.attach(addr_async_safe_format_log,{ onEnter: function(args){ this.log_level = args[0]; this.tag = ptr(args[1]).readCString() this.fmt = ptr(args[2]).readCString() if(this.fmt.indexOf("c-tor") >= 0 && this.fmt.indexOf('Done') < 0){ this.function_type = ptr(args[3]).readCString(), this.so_path = ptr(args[5]).readCString(); var strs = new Array(); strs = this.so_path.split("/"); this.so_name = strs.pop(); this.func_offset = ptr(args[4]).sub(Module.findBaseAddress(this.so_name)) console.log("func_type:", this.function_type, '\nso_name:',this.so_name, '\nso_path:',this.so_path, '\nfunc_offset:',this.func_offset ); if(this.so_name == "libmsaoaidsec.so"){ hook_libmsaoaidsec(this.func_offset) } } }, onLeave: function(retval){ } }) } }
|
會發現0x18a34
只有call沒有leave
在IDA中查看0x18a34
如下,但沒有看明白具體檢測了maps的什麼…
Bypass方案
1、IO重定向maps
複製一份正常的maps保存到/data/app/<pkg>
下
1
| cp /proc/`pidof tv.danmaku.bili`/maps /data/app/tv.danmaku.bili-tk5wLG_ePdtCr4YILKNN1w==/bili_maps
|
hook替換成正常的maps
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| var idx = 0; function test(){ let open = Module.getExportByName("libc.so", "open");
Interceptor.attach(open, { onEnter: function (args) { let fileName = args[0].readCString(); if(fileName.indexOf("/proc/self/maps") != -1){
if(idx == 1 || idx == 2){ Memory.protect(args[0], 4096, 'rwx'); Memory.writeUtf8String(args[0],"/data/app/tv.danmaku.bili-tk5wLG_ePdtCr4YILKNN1w==/bili_maps") console.log("io 重定向....") console.log("idx: " + idx) } idx++; } }, onLeave: function (retval) { } } ); }
|
2、不加載libmsaoaidsec.so
來源:http://www.yxfzedu.com/article/10603
看來libmsaoaidsec.so
裡都是檢測的邏輯,沒有包含業務代碼,因此不加載也不影響APP正常運行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function hook_dlopen_anti(soName = '') { 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(); if(path.indexOf('libmsaoaidsec.so') >= 0){ ptr(pathptr).writeUtf8String(""); } console.log('path: ',path) } } }); }
|