首页   

无壳app的libmsaoaidsec.so frida反调试绕过姿势

看雪学苑  · 互联网安全  · 昨天

正文

当前许多应用通过集成libmsaoaidsec.so实现针对 Frida 的反调试机制,其核心逻辑是在应用启动过程中,当加载libmsaoaidsec.so动态库时,会通过pthread_create()创建独立线程,并在该线程内执行反调试函数,主动扫描 Frida 进程、端口、内存特征等痕迹。若检测到 Frida 存在,则触发进程终止或崩溃。


针对这种机制的绕过思路可以从破坏反调试线程的加载或执行入手,文章会对不同的app进行测试,对于使用libmsaoaidsec.so来进行反调试的app,思路是一样的。


定位

通过hook dlopen()函数根据最后加载的so文件来确定程序是在加载哪个so之后退出的。


function hook_dlopen(){
//Android8.0之后加载so通过android_dlopen_ext函数
var android_dlopen_ext = Module.findExportByName(null,"android_dlopen_ext");
console.log("addr_android_dlopen_ext",android_dlopen_ext);
Interceptor.attach(android_dlopen_ext,{
onEnter:function(args){
var pathptr = args[0];
if(pathptr!=null && pathptr != undefined){
var path = ptr(pathptr).readCString();
console.log("android_dlopen_ext:",path);
}
},
onLeave:function(retvel){
console.log("leave!");
}
})
}
hook_dlopen()


如下,可以看到加载完libmsaoaidsec.so之后程序就退出了。




接下来我们找一个时机,就是在加载libmsaoaidsec.so的时候打印它里面创建的线程。


function hook_dlopen(){
var android_dlopen_ext = Module.findExportByName(null,"android_dlopen_ext");
console.log("addr_android_dlopen_ext",android_dlopen_ext);
Interceptor.attach(android_dlopen_ext,{
onEnter:function(args){
var pathptr = args[0];
if(pathptr!=null && pathptr != undefined){
var path = ptr(pathptr).readCString();
if(path.indexOf("libmsaoaidsec.so")!=-1){
console.log("android_dlopen_ext:",path);
hook_pthread()
}
}
},
onLeave:function(retvel){

}
})
}

function hook_pthread() {
var pth_create = Module.findExportByName("libc.so", "pthread_create");
console.log("[pth_create]", pth_create);
Interceptor.attach(pth_create, {
onEnter: function (args) {
var module = Process.findModuleByAddress(args[2]);
if (module != null) {
console.log("address", module.name, args[2].sub(module.base));
}
},
onLeave: function (retval) {}
});
}

function main(){
hook_dlopen()
}

main()


如下看打印结果,有兴趣的小伙伴可以利用IDA反编译libmsaoaidsec.so跳转到这些地址去看这些函数都干了什么事情。



反调试绕过

现在已经知道了是哪些函数来检测的frida,然后一个很重要的事情就是找到一个时机去把这几个函数都替换掉或者nop掉。


如果去IDA里分析的话,跳转到这几个函数的地址,通过交叉引用查看他们的上一级函数,会发现最终他们都会聚集到init_proc函数里,这是一个初始化函数,在so加载时会自动被调用,而且是so加载过程中最先执行的函数,那么就要找一个比init_proc函数执行更早的一个时机来把检测frida的函数替换掉或者nop掉。


在so文件的链接过程中linker里的call_constructors()函数会触发构造函数,对初始化函数进行注册,然后执行初始化函数,注册的初始化函数会放在.init_array函数列表里,可以在调用call_constructors()函数的时候动态替换so文件里检测frida的函数的地址,使它指向自定义的空函数。


姿势1

替换函数


function hook_dlopen(){
//Android8.0之后加载so通过android_dlopen_ext函数
var android_dlopen_ext = Module.findExportByName(null,"android_dlopen_ext");
console.log("addr_android_dlopen_ext",android_dlopen_ext);
Interceptor.attach(android_dlopen_ext,{
onEnter:function(args){
var pathptr = args[0];
if(pathptr!=null && pathptr != undefined){
var path = ptr(pathptr).readCString();
if(path.indexOf("libmsaoaidsec.so")!=-1){
console.log("android_dlopen_ext:",path);
hook_call_constructors()
}
}
},
onLeave:function(retvel){
//console.log("leave!");
}
})
}

function hook_call_constructors() {
let linker = null;
if (Process.pointerSize === 4) {
linker = Process.findModuleByName("linker");
} else {
linker = Process.findModuleByName("linker64");
}
let call_constructors_addr, get_soname
let symbols = linker.enumerateSymbols();
for (let index = 0; index < symbols.length; index++) {
let symbol = symbols[index];
if (symbol.name === "__dl__ZN6soinfo17call_constructorsEv") {
call_constructors_addr = symbol.address;
} else if (symbol.name === "__dl__ZNK6soinfo10get_sonameEv") {
get_soname = new NativeFunction(symbol.address, "pointer", ["pointer"]);
}
}
console.log(call_constructors_addr)
var listener = Interceptor.attach(call_constructors_addr, {
onEnter: function (args) {
console.log("hooked call_constructors")
var module = Process.findModuleByName("libmsaoaidsec.so")
if (module != null) {
Interceptor.replace(module.base.add(0x1c544), new NativeCallback(function () {
console .log("0x1c544:替换成功")
}, "void", []))
Interceptor.replace(module.base.add(0x1b8d4), new NativeCallback(function () {
console.log("0x1b8d4:替换成功")
}, "void", []))
Interceptor.replace(module.base.add(0x26e5c), new NativeCallback(function () {
console.log("0x26e5c:替换成功")
}, "void", []))
listener.detach()
}

},
})
}
function main(){
hook_dlopen()
}

main()


如下成功绕过了


姿势2

nop函数


function nop_addr(addr) {
Memory.protect(addr, 4 , 'rwx');
var w = new Arm64Writer(addr);
w.putRet();
w.flush();
w.dispose();
}

function hook_dlopen(){
//Android8.0之后加载so通过android_dlopen_ext函数
var android_dlopen_ext = Module.findExportByName(null,"android_dlopen_ext");
console.log("addr_android_dlopen_ext",android_dlopen_ext);
Interceptor.attach(android_dlopen_ext,{
onEnter:function(args){
var pathptr = args[0];
if(pathptr!=null && pathptr != undefined){
var path = ptr(pathptr).readCString();
if(path.indexOf("libmsaoaidsec.so")!=-1){
console.log("android_dlopen_ext:",path);
hook_call_constructors()
}
}
},
onLeave:function(retvel){
//console.log("leave!");
}
})
}

function hook_call_constructors() {
let linker = null;
if (Process.pointerSize === 4) {
linker = Process.findModuleByName("linker");
} else {
linker = Process.findModuleByName("linker64");
}
let call_constructors_addr, get_soname
let symbols = linker.enumerateSymbols();
for (let index = 0; index < symbols.length; index++) {
let symbol = symbols[index];
if (symbol.name === "__dl__ZN6soinfo17call_constructorsEv") {
call_constructors_addr = symbol.address;
} else if (symbol.name === "__dl__ZNK6soinfo10get_sonameEv") {
get_soname = new NativeFunction(symbol.address, "pointer", ["pointer"]);
}
}
console.log(call_constructors_addr)
var listener = Interceptor.attach(call_constructors_addr, {
onEnter: function (args) {
console.log("hooked call_constructors")
var module = Process.findModuleByName("libmsaoaidsec.so")
if (module != null) {
nop_addr(module.base.add(0x1c544))
console.log("0x1c544:替换成功")
nop_addr(module.base.add(0x1b8d4))
console.log("0x1b8d4:替换成功")
nop_addr(module.base.add(0x26e5c))
console.log("0x26e5c:替换成功")
listener.detach()
}

},
})
}
function main(){
hook_dlopen()
}

main()


如下也可以绕过






图片


看雪ID:Bileton  比尔顿

https://bbs.kanxue.com/user-home-993971.htm

*本文为看雪论坛文章,由 Bileton  比尔顿 原创,转载请注明来自看雪社区


# 往期推荐

1、2024春秋杯网络安全联赛冬季赛-RE所有题目WP

2、安卓签名校验-探讨

3、pyd文件逆向

4、AMSI简介及绕过方法总结

5、2025 HGAME WEEK1 RE WP



图片



球分享

球点赞

球在看


点击阅读原文查看更多

推荐文章
© 2024 精读
删除内容请联系邮箱 2879853325@qq.com