android|frida检测的通用处理逻辑

admin 2024年9月28日14:26:45评论6 views字数 4611阅读15分22秒阅读模式

观前提示:

本文章仅供学习交流,切勿用于非法通途,如有侵犯贵司请及时联系删除

样本包名:Y24uaHNhLmFwcCAxLjMuMTI=

本文没有对混淆的代码和检测函数做下一步定位和验证

0x1 定位反调试所在的so

hook dlopen函数

function hook_dlopen() {
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
{
onEnter: function (args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
LogPrint("android_dlopen_ext_addr onEnter "+ ptr(args[0]).readCString())
}
}
}
);
}

so都是是顺序加载,从命令行中当加载libxloader.so之后,进程就崩溃了,可以猜测反调试点在libxloader.so

android|frida检测的通用处理逻辑
Snipaste_2023-08-24_13-58-19
0x2 寻找检测函数所在位置

hook JNI_OnLoad

function hook_dlopen(){
var android_dlopen_ext_addr = Module.findExportByName(null, "android_dlopen_ext")
Interceptor.attach(android_dlopen_ext_addr, {
onEnter: function(args){
LogPrint("android_dlopen_ext_addr onEnter "+ ptr(args[0]).readCString())
var so_name = ptr(args[0]).readCString()
if ( so_name.indexOf('libxloader.so')> -1){
this.hook = true;
}
}, onLeave:function(retval){
if (this.hook) {
var jniOnload = Module.findExportByName("libxloader.so", "JNI_OnLoad");
LogPrint("jniOnload " +jniOnload)
Interceptor.attach(jniOnload, {
onEnter: function (args) {
LogPrint("Enter libxloader JNI OnLoad");
},
onLeave: function (retval) {
LogPrint("After libxloader JNI OnLoad");
}
});
}

}
})
}

发现执行还没有进入JNI_OnLoad进程就被kill,检测函数比JNI_OnLoad更早执行。

so中init函数执行顺序

.init_proc -> .init_array -> JNI_OnLoad

ida 打开so发现寻找.inti_array没有可疑函数,继续寻找.init_proc,发现有大量代码,不过都是被混淆过的。hook openpthread_create 函数看看

hook_pthread

function hook_pthread(){
var pthread_create_addr = null;
var symbols = Process.findModuleByName("libc.so").enumerateSymbols();
for(var i = 0;i<symbols.length;i++){
var symbol = symbols[i].name;
if(symbol.indexOf("pthread_create")>=0){
pthread_create_addr = symbols[i].address;
}
}
LogPrint("pthread_create_addr,"+pthread_create_addr);
Interceptor.attach(pthread_create_addr,{
onEnter:function(args){
var libxloader_addr = Process.findModuleByName("libxloader.so");
if (libxloader_addr){
LogPrint("pthread_create_addr args[0],args[1],args[2],args[3]:"+args[0]+" "+args[1]+" "+args[2]+" "+args[3]);
LogPrint("libxloader "+libxloader_addr.base) // 0x633d4 0x5f5d8 0x7963c
LogPrint('CCCryptorCreate called from:n' +
Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).join('n') + 'n');
}
},onLeave:function(retval){
LogPrint("retval is:"+retval)
}
})
}

hook open

function libc_open(){
var libcmodule = Process.getModuleByName("libc.so");
var openaddr = libcmodule.getExportByName("open");
openaddr_target = Interceptor.attach(openaddr, {
onEnter: function (args) {
var filepath = ptr(args[0]).readCString();
LogPrint("open:" + filepath);
}, onLeave: function (retval) {
}
});
}

发现还没有创建线程,有读取maps文件,一般检测maps也会检测status文件,将正常mapsstatus都copy过来放到/sdcard/ 目录下,将libc_open函数改造下

function libc_open(){
    const openPtr = Module.getExportByName('libc.so', 'open');
const open = new NativeFunction(openPtr, 'int', ['pointer', 'int']);
var readPtr = Module.findExportByName("libc.so", "read");
var read = new NativeFunction(readPtr, 'int', ['int', 'pointer', "int"]);
var fakePath = "/sdcard/2937_maps";
var fakePath3 = "/sdcard/2937_status";
openaddr_replace_target = openPtr;
Interceptor.replace(openPtr, new NativeCallback(function (pathnameptr, flag) {
var pathname = Memory.readUtf8String(pathnameptr);
LogPrint("open:"+pathname)
if (pathname.indexOf("maps") >= 0 || pathname.indexOf("status") >= 0) {
var temp = pathname.indexOf("maps") >= 0 ? 1 : 2;
switch (temp) {
case 1:
var filename = Memory.allocUtf8String(fakePath);
return open(filename, flag);
break;
case 2:
var filename = Memory.allocUtf8String(fakePath3);
return open(filename, flag);
break;
}
}
var fd = open(pathnameptr, flag);
// Thread.sleep(1)
return fd;
}, 'int', ['pointer', 'int']));
}

运行后app进程居然崩溃了...

android|frida检测的通用处理逻辑

猜测是不是 hook 的某个函数导致的,在JNI_OnLoad函数执行前将所有hook的函数都释放掉,app居然正常启动了,在巧合下过掉了frida的检测.

function hook_dlopen(){
var android_dlopen_ext_addr = Module.findExportByName(null, "android_dlopen_ext")
Interceptor.attach(android_dlopen_ext_addr, {
onEnter: function(args){
LogPrint("android_dlopen_ext_addr onEnter "+ ptr(args[0]).readCString())
var so_name = ptr(args[0]).readCString()
if ( so_name.indexOf('libxloader.so')> -1){
this.hook = true;
}
}, onLeave:function(retval){
if (this.hook) {
var jniOnload = Module.findExportByName("libxloader.so", "JNI_OnLoad");
LogPrint("jniOnload " +jniOnload)
Interceptor.attach(jniOnload, {
onEnter: function (args) {
LogPrint("Enter libxloader JNI OnLoad");
if (openaddr_replace_target){
Interceptor.revert(openaddr_replace_target);
LogPrint("openaddr_replace_target Hook reverted.");
}
Interceptor.detachAll();
LogPrint("pthread_create Hook reverted.");
},
onLeave: function (retval) {
LogPrint("After libxloader JNI OnLoad");
}
});
}

}
})
}
android|frida检测的通用处理逻辑
Snipaste_2023-08-24_14-46-04

hook_pthread中发现0x633d4中有mapsstatus的检测逻辑,可以分析分析

0x3 案例总结

    1.使用魔改的frida

    2.hook dlopen 函数寻找关键so

    3.寻找关键函数在so中的位置

    4.hook pthread_create 函数是否能发现可以函数

    5.hook open函数是否打开了maps status 等文件

    6.hook strstr strcmp 等字符串操作函数,能发现一些可以字符串明文,验证推测

    7.是否需要释放hook的函数

[完]

原文始发于微信公众号(逆向与采集):android|frida检测的通用处理逻辑

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月28日14:26:45
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   android|frida检测的通用处理逻辑https://cn-sec.com/archives/2048984.html

发表评论

匿名网友 填写信息