Modify the kernel source code to bypass anti-debugging detection (Android10)

One, Android anti-debugging   

  Anti-debugging plays a very important role in code protection. Although it cannot completely stop the attacker, it can increase the cost of analysis time for the attacker. At present, most Android apps are hardened. In order to prevent the app from being debugged and analyzed, various anti-debugging functions have been added to the hardening function, such as: ptrace yourself, check function execution time, read /proc/$pid/wchan or / proc/$pid/task/$pid/wchan file information to judge the debugging status, read /proc/$pid/stat or /proc/$pid/task/$pid/stat file information to judge the debugging status, read /proc/ The $pid/status or /proc/$pid/task/$pid/status file detects TracerPid, reads and detects the debug process name, detects the debug port, and so on. There are many articles about Android anti-debugging on the Internet. If you want to learn more about Android anti-debugging detection methods, you can look at the methods summarized in [https://bbs.pediy.com/thread-223324.htm]. In this article, we only discuss reading the /proc/$pid/status file and the /proc/$pid/wchan file to check whether the app is being debugged.

2. Analysis of the detection principle of reading /proc/$pid

  1. Read the status file under /proc/$pid to detect that it is debugged

   In the debugging state in Android, the linux kernel will write process status information to /proc/$pid/status or /proc/$pid/task/$pid/status. The TracerPid field is written to the Pid of the process debugging the process. Among them, the current state of the process is written in the State field, and the value is one of the following:

R (running)", "S (sleeping)", "D (disk sleep)", "T (stopped)", "t(tracing stop)", "Z (zombie)",  "X (dead)"

When State is t (tracing stop) or T (stopped), it means it is being debugged and traced. So one of the methods of anti-debugging is to check the value of TracerPid or State by reading the /proc/$pid/status or /proc/$pid/task/$pid/status file through continuous polling . If TracerPid is not 0, it means The process is debugged; if the state value is t (tracing stop) or T (stopped), it is debugged and tracked. As shown below:

 

image

      

   2. Read /proc/$pid/stat, /proc/$pid/task/$pid/stat to detect that it is debugged

    When the process is being debugged, the kernel will write the t flag to the third field in the /proc/$pid/stat and /proc/$pid/task/$pid/stat files.

        3.读取/proc/$pid/wchan、/proc/$pid/task/$pid/wchan

          The content of the wchan file indicates the function that the kernel is currently running when the process sleeps. If the process is debugged, the kernel will write ptrace_stop information in the /proc/$pid/wchan and /proc/$pid/task/$pid/wchan files.

     Three, modify the kernel

         The relevant information codes in the kernel source code and "two" are located in the kernel /fs/proc directory, as shown in the following figure:

image

       1. Modify the State identification value

        The information related to the logo writing is located in the kernel file /fs/proc/array.c , as shown below.

Original code content:

static const char * const task_state_array[] = {

  "R (running)",    /*   0 */  "S (sleeping)",    /*   1 */  "D (disk sleep)",  /*   2 */  "T (stopped)",    /*   4 */  "t (tracing stop)",  /*   8 */  "X (dead)",    /*  16 */  "Z (zombie)",    /*  32 */};

We need to replace the "t (tracing stop)" and "T (stopped)" in the above content with "S (sleeping)". No matter how the App is debugged, the kernel writes in a normal state to counter anti-debugging detection. The modified code is as follows:

static const char * const task_state_array[] = {
   
     "R (running)",    /*   0 */  "S (sleeping)",    /*   1 */  "D (disk sleep)",  /*   2 */  ///ADD START  //"T (stopped)",    /*   4 */  "S (sleeping)",       /*   4 */  ///ADD END  /*  ///ADD START  //"t (tracing stop)",/*   8 */    */  "S (sleeping)",  /*   8 */  /*  ///ADD END  */  "X (dead)",    /*  16 */  "Z (zombie)",    /*  32 */};

 

2. Modify TracerPid related

          The information related to the tag writing is located in the task_state function in the kernel file /fs/proc/array.c, as shown below.

image

Among them, tpid represents the Pid of the process currently being debugged, and we will always modify tpid to 0. You can bypass the detection of TracerPid. After modification as follows:

image

3. Modify the information related to the wchan file

    The file /proc/$pid/wchan, /proc/$pid/task/$pid/wchan kernel write related code path is located in: \fs\proc\base.c, as shown below:

#ifdef CONFIG_KALLSYMS/* * Provides a wchan file via kallsyms in a proper one-value-per-file format. * Returns the resolved symbol.  If that fails, simply return the address. */static int proc_pid_wchan(struct seq_file *m, struct pid_namespace *ns,        struct pid *pid, struct task_struct *task){
   
     unsigned long wchan;  char symname[KSYM_NAME_LEN];
  wchan = get_wchan(task);
  if (lookup_symbol_name(wchan, symname) < 0)    if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))      return 0;    else      return seq_printf(m, "%lu", wchan);  else    return seq_printf(m, "%s", symname);}#endif /* CONFIG_KALLSYMS */

Write the symbol name above and modify it to include the trace keyword in the filter symbol name, and then write sys_epoll_wait. After modification, it looks like this:

#ifdef CONFIG_KALLSYMS/* * Provides a wchan file via kallsyms in a proper one-value-per-file format. * Returns the resolved symbol.  If that fails, simply return the address. */static int proc_pid_wchan(struct seq_file *m, struct pid_namespace *ns,        struct pid *pid, struct task_struct *task){
   
     unsigned long wchan;  char symname[KSYM_NAME_LEN];
  wchan = get_wchan(task);
  if (lookup_symbol_name(wchan, symname) < 0)    if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))      return 0;    else      return seq_printf(m, "%lu", wchan);  else{
   
       ///ADD START    if(strstr(symname,"trace")){
   
             return seq_printf(m, "%s","sys_epoll_wait");    }    ///ADD END    return seq_printf(m, "%s", symname);  }}#endif /* CONFIG_KALLSYMS */

Four, compile and flash

      After the modification is saved, execute the following command in the root directory of the Android source code to compile the flash package and then flash:

​​​​​​​

source build/envsetup.shbrunch oneplus3-userdebug

 

Follow the WeChat public account to get article updates in time:

image

Guess you like

Origin blog.csdn.net/u011426115/article/details/113144592