过某交友软件frida反调试

今天在分析一款交友软件时遇见了frida反调试,收获挺大的,于是记录一下。

frida是逆向人员的神器,有了它就事半功倍,但正是因为frida太有名了,因此出现了很多检测方案,这个软件就检测了frida,不管是attach模式还是spawn模式都附加不上。

一般来说,frida检测由如下几个方面:

  • 检测frida-server文件名
  • 检测27042默认端口
  • 双进程保护
  • 检测D-Bus
  • 检测/proc/pid/maps映射文件
  • 检测/proc/pid/tast/tid/stat或/proc/pid/tast/tid/status

前三种可以通过改文件名、改端口和以spawn模式启动过掉,检测D-Bus可以通过hook系统库函数,比如strstr、strcmp等等,最后两种检测可以更改frida-server的特征从而达到隐藏的效果,这个可以具体参照这篇文章手动编译Hluda Frida Server,下面看具体演示

这里直接使用hluda server,它更改了frida的诸多特征,自己使用时记得把文件名给改了,并且换个端口,不要使用默认端口

过某交友软件frida反调试_文件名

然后以spawn模式启动应用,主要是为了过掉双进程保护(虽然这个应用是没有双进程保护的~~)

过某交友软件frida反调试_进程保护_02

然后就。。。挂掉了,纳尼,神马情况,缓缓情绪,虽然hluda server改了很多特征,但也还有特征能够发现

先不说hluda server,先说说正常的frida server附加进应用之后它的/proc/pid/maps的文件的变化

过某交友软件frida反调试_Memory_03

很明显的发现出现了/data/local/tmp/re.frida.server/***,等等,re.frida.server是什么呢?这是当使用frida server的时候自动创建的,里面存放着frida的功能模块。

过某交友软件frida反调试_文件名_04

那么当使用hluda server会发生什么变化呢?

过某交友软件frida反调试_Memory_05

过某交友软件frida反调试_Memory_06

可以发现re.frida.server已经没有了,反而变成了一串没有意义的字符串,并且功能模块文件名也被混淆了,那么为什么还是被检测到了呢?会不会是D-Bus检测呢?别急,认真比对正常的与附加后的/proc/pid/maps文件,发现正常的maps里面是没有/data/local/tmp路径下的模块映射的,但附加了frida之后,不管模块名有没有被混淆,/data/local/tmp路径名总会出现的,见下图:

过某交友软件frida反调试_Memory_07

因此应用完全有理由去检测maps文件里是否有/data/local/tmp目录下的模块映射,所以我就尝试着伪造一个/proc/pid/maps文件,去掉所有有关/data/local/tmp的映射,并且hook open函数让其打开我伪造的maps文件,具体代码如下:

function main() {
    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 = "/data/data/com.xyz.qingtian/maps";
    var file = new File(fakePath, "w");
    var buffer = Memory.alloc(512);
    Interceptor.replace(openPtr, new NativeCallback(function (pathnameptr, flag) {
        var pathname = Memory.readUtf8String(pathnameptr);
        var realFd = open(pathnameptr, flag);
        if (pathname.indexOf("maps") >= 0) {
            while (parseInt(read(realFd, buffer, 512)) !== 0) {
                var oneLine = Memory.readCString(buffer);
                if (oneLine.indexOf("tmp") === -1) {
                    file.write(oneLine);
                }
            }
            var filename = Memory.allocUtf8String(fakePath);
            return open(filename, flag);
        }
        var fd = open(pathnameptr, flag);
        return fd;
    }, 'int', ['pointer', 'int']));
}
setImmediate(main)

 

很惊喜的发现成功过掉了frida检测

过某交友软件frida反调试_Memory_08