Linux /proc目录下和ELF反调试有关的文件
wchan
/proc/[pid]/wchan显示进程sleep时,kernel当前运行的函数。调试状态下,wchan文件会显示ptrace_stop。
cmdline
/proc/[pid]/cmdline文件存放进程的命令内容。使用GDB这类的调试器时,调试会fork一个子进程,然后执行ELF程序。此时,ELF文件就可以通过getppid()获取父进程pid,然后检测cmdline中是否存在gdb关键字,来判断程序的调试状态。
stat家族
/proc/[pid]/stat文件包含对应进程的状态信息,主要用于ps命令。此文件由kernel源文件kernel/msm/fs/proc/array.c定义。当进程处于调试状态时,在stat文件的第三个字段处,会显示小写t,表示Tracing stop.(适用于Linux 2.6.33之后,也就是Android 2.3.x之后的版本)
/proc/[pid]/statm,该文件包含对应进程的页面内存状态信息。
/proc/[pid]/status文件是/proc/[pid]/stat和/proc/[pid]statm两文件的集合,更易阅读。status文件除了TracerPid字段外,第二行的state字段也能够用来判断进程是否处于被调试状态(Tracing stop)
反调试相关的文件除了/proc/[pid]目录,在/proc/[pid]/task/tid/目录下应该有线程的状态信息文件,同样可以用来做反调试检测。
同时,从Linux手册的说明可以看到stat文件是由kernel中的array.c定义的(实际上还有base.c等),因此可以通过修改array.c、base.c绕过检测TracerPid、State的反调试。具体修改思路是:
- array.c下的task_state_array数组,把stopping、tracing stop改成sleeping状态,使得stat文件接收不到tracing stop、stopping的状态值;
- array.c下的task_state函数,将其中的tpid恒置为0,其中的ppid表示父进程的pid,能被父进程检测的反调试利用,但修改后估计会影响所有父子进程的正常运行。
- base.c下的proc_pid_wchan函数,修改/proc/[pid]/wchan的返回逻辑,使得返回的函数信息中包含trace字样时,仍按正常状态返回,wchan文件也就不会显示ptrace_stop了。
感谢参考:
https://xhyeax.github.io/2019/09/13/android-source-mod-anti-antidebug/
https://www.freebuf.com/sectool/83509.html