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 /proc目录下和ELF反调试有关的文件

同时,从Linux手册的说明可以看到stat文件是由kernel中的array.c定义的(实际上还有base.c等),因此可以通过修改array.c、base.c绕过检测TracerPid、State的反调试。具体修改思路是:

  1. array.c下的task_state_array数组,把stopping、tracing stop改成sleeping状态,使得stat文件接收不到tracing stop、stopping的状态值;
  2. array.c下的task_state函数,将其中的tpid恒置为0,其中的ppid表示父进程的pid,能被父进程检测的反调试利用,但修改后估计会影响所有父子进程的正常运行。
  3. 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

https://www.52pojie.cn/thread-940605-1-1.html