Xiangxiang's Personal Site

Machine Learning & Security Engineer
生命不息,折腾不止,留下一点活着的记录.

View on GitHub
6 April 2024

Frida detection and bypass (Android)

by xiangxiang

0x01 Detection

1.1 Port

1.2 Dual Process (ptrace)

1.3 /proc/<pid>/maps

1.4 /proc/<pid>/status

1.5 /proc/<pid>/task/<tid>/stat

1.6 /proc/<pid>/task/<tid>/status

1.7 /proc/<pid>/fd

1.8 injection (memory modification)

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
void dumpprelude(unsigned char *f)
{
    int i;
    int c;
    for(i=0; i<32; i++){
        fprintf(stderr, "%02x", *(f+i));
    }
    fprintf(stderr, "\npress enter...\n");
    read(0, &c, 1);
}

int f(int x)
{
    fprintf(stderr, "f says hi!\n");
    return ++x;
}

int main(int argc, char *argv[])
{
    int x;
    dumpprelude((unsigned char*)f);
    dumpprelude((unsigned char*)f);
    memcpy((void*)f, "\xf3\x0f\x1e\xfa\x55", 5);     // Mock injection
    dumpprelude((unsigned char*)f);
    x = f(13);
    fprintf(stderr, "x is %d\n", x);
    exit(EXIT_SUCCESS);
}

0x02 Bypass

Two main ideas

2.1 Special frida

void * m = mmap(nullptr, len, map.perms | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
memcpy(m, reinterpret_cast<void *>(map.start), len);
mprotect(m, len, map.perms);
mremap(m, len, len, MREMAP_FIXED | MREMAP_MAYMOVE, reinterpret_cast<void *>(map.start));

2.2 Patch detection code

2.3 Custom kernel

My custom kernel hack for kernel 4.19

 static inline struct task_struct *get_proc_task(const struct inode *inode)
 {
-       return get_pid_task(proc_pid(inode), PIDTYPE_PID);
+       struct task_struct * p = get_pid_task(proc_pid(inode), PIDTYPE_PID);
+       char tcomm[64];
+       if (p->flags & PF_WQ_WORKER)
+               wq_worker_comm(tcomm, sizeof(tcomm), p);
+       else
+               __get_task_comm(tcomm, sizeof(tcomm), p);
+       if (strstr(tcomm, "frida") || strstr(tcomm, "gmain") || strstr(tcomm, "gum-js") || strstr(tcomm, "linjector") ||  strstr(tcomm, "gdbus"))
+               return NULL;
+       return p;
 }
+static int bypass_show_map_vma(struct vm_area_struct *vma) {
+        struct file *file = vma->vm_file;
+        vm_flags_t flags = vma->vm_flags;
+        if (file && file->f_path.dentry && (strstr(file->f_path.dentry->d_iname, "frida-") || strstr(file->f_path.dentry->d_iname, "/data/local/tmp/")))
+                return 1;
+        if (file && file->f_path.dentry && strstr(file->f_path.dentry->d_iname, "libart.so") && (flags & VM_EXEC))
+                return 1;
+        if (file && file->f_path.dentry && (strstr(file->f_path.dentry->d_iname, "memfd:jit-cache") || strstr(file->f_path.dentry->d_iname, "memfd:jit-zygote-cache")))
+                return 1;
+        return 0;
+}
+
 static void
 show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
 {
@@ -360,6 +372,9 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
        dev_t dev = 0;
        const char *name = NULL;

+        if (bypass_show_map_vma(vma) == 1)
+                return;
+
        if (file) {
                struct inode *inode = file_inode(vma->vm_file);
                dev = inode->i_sb->s_dev;
@@ -369,6 +384,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)

        start = vma->vm_start;
        end = vma->vm_end;
+
        show_vma_header_prefix(m, start, end, flags, pgoff, dev, ino);

        /*
@@ -393,6 +409,11 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
                        name = "[vdso]";
                        goto done;
                }
+
+               if ((flags & VM_EXEC)) {
+                        name = "[vdso]";
+                       goto done;
+               }

                if (vma->vm_start <= mm->brk &&
                    vma->vm_end >= mm->start_brk) {
@@ -846,6 +867,9 @@ static int show_smap(struct seq_file *m, void *v)
        struct vm_area_struct *vma = v;
        struct mem_size_stats mss;

+        if (bypass_show_map_vma(vma) == 1)
+                return 0;
+
        memset(&mss, 0, sizeof(mss));

        smap_gather_stats(vma, &mss);

refs

tags: android frida security