首页
社区
课程
招聘
[原创]小菜花的frida-svc-interceptor
2021-11-5 17:57 40619

[原创]小菜花的frida-svc-interceptor

2021-11-5 17:57
40619

一、目标

现在很多App不讲武德了,为了防止 openat 、read、kill 等等底层函数被hook

1,干脆就直接通过syscall的方式来做

2,或者就直接通过内联汇编svc的方式去做


最近在研究svc bypass,想用一个通用点的方案来实现它,继而继续进行io重定向。。。,嗯,io重定向的好处就不说了。


听说的方案有

1,ptrace直接搞(ps:还在看资料)

2,找到svc指令地址,继续去inlinehook它


我们今天采用第二种方法,用frida来实现

  • frida momory search svc

  • parse insn and count call_number

  • frida native hook svc



二、步骤

1,参考了葫芦娃dumpDex扫描内存的思路

2,frida是可以直接hook svc的,也不用地址减0x4

3,上frida脚本

let target_code_hex;
let call_number_openat;
let call_number_faccessat;
let arch = Process.arch;
if ("arm" === arch){
    target_code_hex = "00 00 00 EF";
    call_number_openat = 322;
    call_number_faccessat = 334;
}else if("arm64" === arch){
    target_code_hex = "01 00 00 D4";
    call_number_openat = 56;
    call_number_faccessat = 48;
}else {
    console.log("arch not support!")
}

if (arch){
    console.log("\nthe_arch = " + arch);
    // 直接Process.enumerateModules(),可能会因为某些地址不可读造成非法访问
    Process.enumerateRanges('r--').forEach(function (range) {
        if(!range.file || !range.file.path){
            return;
        }
        let path = range.file.path;
        if ((!path.startsWith("/data/app/")) || (!path.endsWith(".so"))){
            return;
        }
        let baseAddress = Module.getBaseAddress(path);
        let soNameList = path.split("/");
        let soName = soNameList[soNameList.length - 1];
        console.log("\npath = " + path + " , baseAddress = " + baseAddress + " , rangeAddress = " + range.base + " , size = " + range.size);

        Memory.scan(range.base, range.size, target_code_hex, {
            onMatch: function (match){
                let code_address = match;
                let code_address_str = code_address.toString();
                if (code_address_str.endsWith("0") || code_address_str.endsWith("4") || code_address_str.endsWith("8") || code_address_str.endsWith("c")){
                    console.log("--------------------------");
                    let call_number = 0;
                    if ("arm" === arch){
                        // call_number = (code_address.sub(0x4).readS16() - 28672);  // 0x7000
                        call_number = (code_address.sub(0x4).readS32()) & 0xFFF;
                    }else if("arm64" === arch){
                        call_number = (code_address.sub(0x4).readS32() >> 5) & 0xFFFF;
                    }else {
                        console.log("the arch get call_number not support!")
                    }
                    console.log("find svc : so_name = " + soName + " , address = " + code_address + " , call_number = " + call_number + " , offset = " + code_address.sub(baseAddress));

                    // hook svc __NR_openat
                    if (call_number_openat === call_number){
                        let target_hook_addr = code_address;
                        let target_hook_addr_offset = target_hook_addr.sub(baseAddress);
                        console.log("find svc openat , start inlinehook by frida!")
                        Interceptor.attach(target_hook_addr, {
                            onEnter: function (args){
                                console.log("\nonEnter_" + target_hook_addr_offset + " , __NR_openat , args[1] = " + args[1].readCString());
                                this.new_addr = Memory.allocUtf8String("/proc/self/status11");
                                args[1] = this.new_addr;
                                console.log("onEnter_" + target_hook_addr_offset + " , __NR_openat , args[1] = " + args[1].readCString());
                            }, onLeave: function (retval){
                                console.log("onLeave_" + target_hook_addr_offset + " , __NR_openat , retval = " + retval)
                            }
                        });

                    }
                    // hook svc __NR_faccessat
                    if (call_number_faccessat === call_number){
                        let target_hook_addr = code_address;
                        let target_hook_addr_offset = target_hook_addr.sub(baseAddress);
                        console.log("find svc faccessat , start inlinehook by frida!")
                        Interceptor.attach(target_hook_addr, {
                            onEnter: function (args){
                                console.log("\nonEnter_" + target_hook_addr_offset + " , __NR_faccessat , args[1] = " + args[1].readCString());
                                // this.new_addr = Memory.allocUtf8String("/proc/self/status11");
                                // args[1] = this.new_addr;
                                console.log("onEnter_" + target_hook_addr_offset + " , __NR_faccessat , args[1] = " + args[1].readCString());
                            }, onLeave: function (retval){
                                console.log("onLeave_" + target_hook_addr_offset + " , __NR_faccessat , retval = " + retval)
                            }
                        });

                    }
                }
            }, onComplete: function () {}
        });

    });
}


三、总结

0, 这里样本是mov x8(r7) 调用号 和svc 0 紧挨着的情况,也可以持续向上访问地址查找目标寄存器指令适配的更好一点

1, 这里只对目标app的so进行了内存扫描,同理也可以对系统库进行内存扫描

2,用了同步的Memory.scan扫描方式,为了区分到底是哪个目标so文件

3,这里只是frida attach脚本,同理可以改成frida spawn方式,选个好的注入时机就好了

4,这是只搞了两个系统调用号,同理可以多搞一点

5,落地成Dobby实现,如果直接DobbyHook svc地址的话,进入new_func一切正常,进org_func的时候就开始闪退了,那是因为x8(r7)寄存器的值变了,导致系统调用号没了,进而闪退。此时可以 svc address - 0x4 去 hook 也是可以的,当然前提是mov和svc指令紧挨着

6,感觉稳定的生产环境之一应该是用riru模块来搞
7,当然此方案有一定局限性,比如svc在扫描的内存之外,inlinehook特征等等

8,  git地址:https://github.com/huaerxiela/frida-script

9,很简单的思路,好像也是va核心io的思路。。。


四、参考文献

https://bbs.pediy.com/thread-269895.htm 批量检测android app的so中是否有svc调用 

反调试及绕过 https://jmpews.github.io/2017/08/09/darwin/%E5%8F%8D%E8%B0%83%E8%AF%95%E5%8F%8A%E7%BB%95%E8%BF%87/

bypass svc 0 PTRACE_TRACEME https://bbs.pediy.com/thread-212404.htm

http://91fans.com.cn/post/fridasyscallinterceptor/【奋飞】Frida-syscall-interceptor

https://bbs.pediy.com/thread-268283.htm [原创]iOS反反调试助手

https://bbs.pediy.com/thread-260731.htm [原创]使用 ptrace 过 ptrace 反调试





[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2021-11-10 14:50 被huaerxiela编辑 ,原因: 优化脚本
收藏
点赞17
打赏
分享
最新回复 (15)
雪    币: 2944
活跃值: (3921)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
0xEA 2021-11-5 18:35
2
0
花哥nb
雪    币: 2649
活跃值: (1541)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hhhaiai 2021-11-5 18:47
3
0
mark
雪    币: 111
活跃值: (1404)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
我是红领巾 2021-11-8 11:22
4
0
花哥牛逼
雪    币: 4821
活跃值: (5206)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
mb_aoooaosd 2021-11-8 12:39
5
0
花哥牛逼
雪    币: 120
活跃值: (1593)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
jmpews 2021-11-8 14:17
6
0
https://github.com/jmpews/Dobby/blob/master/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.cc
雪    币: 181
活跃值: (2868)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huaerxiela 2021-11-8 14:50
7
0
jmpews https://github.com/jmpews/Dobby/blob/master/builtin-plugin/SupervisorCallMonitor/supervisor_call_mon ...

看到插件了,dobby牛批

最后于 2021-11-8 14:50 被huaerxiela编辑 ,原因:
雪    币: 19
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
only1500 2021-11-9 15:45
8
0
花哥牛逼
雪    币: 5
活跃值: (985)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
恋一世的爱 2021-11-30 15:14
9
0
当无法解密so,且text地址也被隐藏了,明确知道使用的是SVC调用syscall, 对于SVC如何做到通杀hook呢(有啥方案可以直接hook 系统so呢,做到通杀?)
雪    币: 52
活跃值: (506)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
万里星河 2021-12-1 13:37
10
0
社会我花哥
雪    币: 181
活跃值: (2868)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huaerxiela 2021-12-1 16:13
12
0
恋一世的爱 当无法解密so,且text地址也被隐藏了,明确知道使用的是SVC调用syscall, 对于SVC如何做到通杀hook呢(有啥方案可以直接hook 系统so呢,做到通杀?)
1,我这边的设想是,so链接之后,立马扫描内存,然后hook
那要是加壳的话,可以放到init段执行完,再扫描内存,但这个时机有没有检测啥的就不好说了
2,hook系统so,直接扫描指令特征hook就完了,这部分思路已经在virtualApp的io里面有体现了了
雪    币: 5037
活跃值: (1265)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
PanzerT 2021-12-2 15:30
13
0
https://github.com/acceleratorCYR/monitorSVC/blob/master/attach.c
雪    币: 181
活跃值: (2868)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huaerxiela 2021-12-8 09:18
14
0
PanzerT https://github.com/acceleratorCYR/monitorSVC/blob/master/attach.c
哥哥牛批,好东西,学习了
雪    币: 576
活跃值: (2035)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kakasasa 2021-12-8 11:21
15
0
感谢分享
雪    币: 122
活跃值: (1370)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
koflfy 1 2022-3-11 23:22
16
0
mark
游客
登录 | 注册 方可回帖
返回