本文只是交流技术,如有侵权请联系我删除。
知识星球:https://t.zsxq.com/kNlj4
前言:
上一篇文章我们提到 我们使用github开源魔改好的frida server
但是仍然有一些厂商的server不能通过,那么这篇文章针对百度加固 进行快速通过frida反调试,首先针对JAVA API部分第一节已经提到不再多说。
大家可以 看看 参考文章 APP使用frida反调试检测绕过 - 树大招疯 - 博客园
测试样本一 百度加固 小米汽车 1.8.2
按照检测思路,一般会用pthread_create起线程
绕过的方法很简单,直接nop掉pthread_create或者替换检测函数的代码逻辑都可以
function create_pthread_create() {
const pthread_create_addr = Module.findExportByName(null, "pthread_create");
const pthread_create = new NativeFunction(pthread_create_addr, "int", ["pointer", "pointer", "pointer", "pointer"]);
// new NativeCallback(...)
// NativeCallback用于创建一个新的回调函数,在这个回调中,我们可以定义拦截后的行为。这里是重写pthread_create函数的逻辑。
// pargparg1,parg2,parg3是pthread_create的四个参数,通常是:
// parg0: 线程的地址或 ID。
// parg1: 线程的栈大小。
// parg2: 线程的入口地址(即线程函数)。
// parg3: 传递给线程的参数
return new NativeCallback((parg0, parg1, parg2, parg3) => {
// 获取线程入口地址的模块信息
const module = Process.findModuleByAddress(parg2);
const so_name = module.name;
const baseAddr = module.base;
// 打印线程的相关信息
console.log("pthread_create", so_name, "0x" + parg2.sub(baseAddr).toString(16), "0x" + parg3.toString(16));
// 调用原始的 pthread_create 执行线程创建
return pthread_create(parg0, parg1, parg2, parg3);
}, "int", ["pointer", "pointer", "pointer", "pointer"]);
}
function replace_thread() {
var new_pthread_create = create_pthread_create();
var pthread_create_addr = Module.findExportByName(null, "pthread_create");
//替换 pthread_create 函数
Interceptor.replace(pthread_create_addr, new_pthread_create);
}
// 启动初次替换
replace_thread();
测试样本二 百度加固 追书神器 3.45.38
用第一个js会导致卡死:由于使用 Process.findModuleByName
时出现卡死(即程序挂起、无响应等问题),有几种可能的原因,通常涉及到模块加载状态、权限问题或程序的多线程操作等
所以流程改变一下换一种方式 条条大路同罗马:
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(path)
}
},
onLeave: function (retval) {
}
});
}
hook_dlopen()
我们先确定 哪个so退出了 是 libmsaoaidsec.so
案例1的js代码可以得到 libmsaoaidsec.so 的进程偏移
pthread_create libmsaoaidsec.so 0x1c544 0x731552b960
pthread_create libmsaoaidsec.so 0x1b8d4 0x0
pthread_create libmsaoaidsec.so 0x26e5c 0x0
采用另一种方式nop掉
function hook_dlopen(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(soName) >= 0) {
locate_init()
}
}
}
}
);
}
function locate_init() {
let secmodule = null
Interceptor.attach(Module.findExportByName(null, "__system_property_get"),
{
// _system_property_get("ro.build.version.sdk", v1);
onEnter: function (args) {
secmodule = Process.findModuleByName("libmsaoaidsec.so")
var name = args[0];
if (name !== undefined && name != null) {
name = ptr(name).readCString();
if (name.indexOf("ro.build.version.sdk") >= 0) {
// 这是.init_proc刚开始执行的地方,是一个比较早的时机点
// do something
// hook_pthread_create()
bypass()
}
}
}
}
);
}
function hook_pthread_create() {
console.log("libmsaoaidsec.so --- " + Process.findModuleByName("libmsaoaidsec.so").base)
Interceptor.attach(Module.findExportByName("libc.so", "pthread_create"), {
onEnter(args) {
let func_addr = args[2]
console.log("The thread function address is " + func_addr)
}
})
}
function nopFunc(parg2) {
// 修改内存保护,使其可写
Memory.protect(parg2, 4, 'rwx');
// 使用 Arm64Writer 写入 'ret' 指令
var writer = new Arm64Writer(parg2);
writer.putRet();
writer.flush();
writer.dispose();
console.log("nop " + parg2 + " success");
}
function bypass(){
let module = Process.findModuleByName("libmsaoaidsec.so")
nopFunc(module.base.add(0x1c544))
nopFunc(module.base.add(0x1b8d4))
nopFunc(module.base.add(0x26e5c))
}
// pthread\_create libmsaoaidsec.so 0x1c544 0x731552b960\
// pthread\_create libmsaoaidsec.so 0x1b8d4 0x0\
// pthread\_create libmsaoaidsec.so 0x26e5c 0x0
setImmediate(hook_dlopen, "libmsaoaidsec.so")
my:
let WX = 15232101239