frida反调试经验——动态库加载
LuMingFei
- 关注
frida反调试经验——动态库加载
作为一个初学者,在测试过程中遇到了特殊情况,当使用frida spawn或attach应用时,frida进程会被杀掉,提示process terminated,但spawn出来的APP进程仍然可以正常使用。
这种情况可以判断为APP具有反调试防护,将附加的frida进程杀掉了。
发现检测函数
frida检测函数通常都写在so文件中,因为如果把反调试代码写在app代码里,不是很容易被frida hook掉嘛( *^ _^ *)。写在so文件中,不容易被反编译,也不容易被篡改(需要重新签名),执行效率高(不影响app运行)。
我们可以hook一些app用来加载动态库的函数,查看到底检测代码保存在哪个动态库中。如android_dlopen_ext()
、dlopen()
、do_dlopen()
,find_library()
这些函数都是system.loadlibary底层的逻辑代码。
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);
}
}
}
);
}
通过这个脚本可以查看所有android_dlopen_ext
打开的动态库,我们可以发现,当frida执行到libllvm1624362448.so
这里时,发生了闪退,所以我们暂时确定检测代码就在这个库中。
绕过检测
既然我们定位到了检测的动态库,我们有下面几种绕过的思路。
- hook掉加载动态库的函数,将返回的指针置空,直接避免程序加载检测代码。
Interceptor.attach(Module.findExportByName(null, "dlopen"), {
onEnter: function(args) {
var path = args[0].readCString();
if (path.indexOf(targetSo) !== -1) {
console.log(`Attempt to dlopen ${targetSo} blocked`);
args[0] = ptr(0);
}
}
});
- hook 加载动态库的函数,修改传入的动态库路径,让程序加载无害的代码。但这个假动态库中应该包含所有必要的导出函数,但这些函数不执行任何实际操作。
var fake_so = Memory.allocUtf8String("/path/to/fake_libnllvm1624362448.so");
Interceptor.attach(Module.findExportByName(null, "dlopen"), {
onEnter: function(args) {
var path = args[0].readCString();
if (path.indexOf(targetSo) !== -1) {
console.log(`Redirecting ${targetSo} to fake library`);
args[0] = fake_so;
}
}
});
- 直接本地修改so文件,去掉或修改动态库中的检测代码。
- 动态修改动态库文件,修改内存中检测函数的逻辑。(这段不清楚,抄来的)
Memory.protect(targetAddress, size, 'rwx'); //库被加载到内存后是只读的,修改可写权限
var targetFunction = Module.findExportByName("libtarget.so", "function_name"); //找到函数地址
// 修改函数开头为 ret 指令(直接返回)
Memory.writeByteArray(targetFunction, [0xC0, 0x03, 0x5F, 0xD6]); // ARM64 ret 指令
// 或修改数据
Memory.writeInt(targetAddress, newValue);
//刷新缓存
Memory.patchCode(targetFunction, 4, function(code) {
Memory.writeByteArray(code, [0xC0, 0x03, 0x5F, 0xD6]);
});
//恢复内存保护
Memory.protect(targetAddress, size, 'r-x');
最后附上成功绕过这个app检测的代码:
var targetSo = "libnllvm1624362448.so";
function blockLibrary(functionName) {
var func = Module.findExportByName(null, functionName);
if (func) {
Interceptor.attach(ptr(func), {
onEnter: function(args) {
var path = args[0].readCString();
if (path.indexOf(targetSo) !== -1) {
console.log(`Blocked ${targetSo} in ${functionName}`);
args[0] = ptr(0); // 将路径参数设为 NULL
}
}
});
}
}
blockLibrary("open");
blockLibrary("dlopen");
blockLibrary("android_dlopen_ext");
本文为 LuMingFei 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
frida反调试总结+一把梭
2024-07-23
文章目录