项目地址: https://github.com/chroblert/JC-AntiPtrace

环境:kali2020,ndkr17c,arm64,pixel2,android8.1

一、适用场景

Android 绕开TEE 绕过安卓反调试_参考资料

描述:zygote通过fork()系统调用,fork出一个app

app内通过ptrace(PTRACE_TRACEME,0,0,0);将父进程zygote做为自己的tracer

这样其他进程就无法ptrace()到app进程了

二、创建反调试app Demodemo版app放在GitHub中,app-debug.apk

app运行后查看/proc//status中的TracerPid

Android 绕开TEE 绕过安卓反调试_Android 绕开TEE_02

使用frida进行调试,可以看到显示报错如下:

Android 绕开TEE 绕过安卓反调试_android绕过反调试方法_03

注:对于这种很简单的反调试,frida可以用-f进行绕过。

Android 绕开TEE 绕过安卓反调试_#define_04

三、绕过ptrace反调试

(一)、思路(这里主要来自看雪论坛https://bbs.pediy.com/thread-260731.htm)使用ptrace附加zygote进程

拦截zygote的fork调用,在fork子进程时候获取当前进程名称,判断是不是我们想要的那个应用,若是则保存子进程pid

获取到子进程pid后,再拦截子进程的系统调用,判断此系统调用是不是ptrace,并且参数是PTRACE_TRACEME

拦截到指定系统调用后,修改调用参数,让ptrace(PTRACE_TRACEME);执行失败

(二)、差异:

由于ptrace对底层架构的依赖很高,同一份代码不适用于所有架构的手机,因而原作者给出的代码不适用于我的需求,我这里的是android 8.1,pixel2,arm64。有些代码需要做一些变换,如下:ARM32 (AARCH32)ARM64 (AARCH64)

PTRACE_GETREGSPTRACE_GETREGSET
pidpid
NULLNT_PRSTATUS
struct pt_regs *{ struct user_pt_regs *ubf, size_t len }
GETREGSNT_PRSTATUS
PTRACE_SETREGSPTRACE_SETREGSET有些结构体在arm64中的头文件中的声明不一样,也需要重新define,如下:#define pt_regs user_pt_regs
#define uregs regs
#define ARM_r0 regs[0]
#define ARM_r7 regs[7]
#define ARM_1r regs[30]
#define ARM_sp sp
#define ARM_pc pc
#define ARM_cpsr pstate
#define NT_PRSTATUS 1
#define NT_foo 1关于传参和返回值用的寄存器也有些差异,如下:archsyscall NRreturnarg0arg1arg2arg3arg4arg5
armr7r0r0r1r2r3r4r5
arm64x8x0x0x1x2x3x4x5
x86eaxeaxebxecxedxesiediebp
x86_64raxraxrdirsirdxr10r8r9

(三)、实现

代码在GitHub仓库中:[https://github.com/chroblert/JC-AntiPtrace](https://github.com/chroblert/JC-AntiPtrace)

(四)、使用查看zygote64的pid

Android 绕开TEE 绕过安卓反调试_#define_05

我这里的手机是arm64的,所有用zygote64的pid4979

执行编译后的JC-AntiPtrace-v1-arm64-1214.o程序./JC-AntiPtrace-v1-arm64-1214.o -p 4979 -t com.zer0ne_sec.ptrace.jnitest -n 117 -r1 -e

执行frida附加

效果如下:

Android 绕开TEE 绕过安卓反调试_系统调用_06

成功拦截并修改ptrace()系统调用的结果,frida成功hook

(五)、使用说明JC-AntiPtrace-v1-arm64.o [-v] -p -t [-n ] [-r [-e]]

options:
-v : verbose
-p : pid of zygote or zygote64
-t : application name of to hook
-n : syscalll number to hook(十进制)
117:ptrace
220:clone
260:wait
-r : update return value of the syscallno
-h : show helper
-e : detach when updated return value

(1)、用于监控系统调用JC-AntiPtrace-v1-arm64.o [-v] -p  -t  [-n ]

-v: 表示显示详细输出,包含有每个系统调用的参数值与返回值

-p: 表示zygote进程的pid

-t: 要监控的app的名称

-n:表示监控某一个特定的系统调用

(2)、用于绕过ptrace反调试JC-AntiPtrace-v1-arm64.o [-v] -p  -t  [-n 117] [-r0 [-e]]

-v: 表示显示详细输出,包含有每个系统调用的参数值与返回值

-p: 表示zygote进程的pid

-t: 要监控的app的名称

-n:表示监控某一个特定的系统调用

-r: 表示要修改返回值为某个值。-r后面紧跟数值

-e: 表示修改返回值后就detach

四、总结

本篇文章及代码只是对简单ptrace反调试的一种绕过,仅供研究。之后会继续研究其他ptrace反调试的场景,

参考资料:[使用ptrace过ptrace反调试](https://bbs.pediy.com/thread-260731.htm)

参考资料:[一种绕过ptrace反调试的方法]()

参考资料:[ptrace.h](https://sites.uclouvain.be/SystInfo/usr/include/sys/ptrace.h.html)

参考资料:[在Android操作系统中设置永久环境变量]()

参考资料:[Shared Library Injection on Android 8.0](https://fadeevab.com/shared-library-injection-on-android-8/)

参考资料:[NT_PRSTATUS](https://www.man7.org/linux/man-pages/man2/ptrace.2.html)

参考资料:[arm64 vs arm32](https://undo.io/resources/arm64-vs-arm32-whats-different-linux-programmers/)

参考资料:[linux沙箱之ptrace](https://blog.betamao.me/2019/02/02/Linux%E6%B2%99%E7%AE%B1%E4%B9%8Bptrace/)

参考资料:[arm64: ptrace: reload a syscall number after ptrace operations](https://patchwork.kernel.org/project/linux-arm-kernel/patch/1406020499-5537-2-git-send-email-takahiro.akashi@linaro.org/)

参考资料:[ptrace change syscall number arm64](https://stackoverflow.com/questions/63620203/ptrace-change-syscall-number-arm64)

参考资料:[linux system call table](https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md)