How To Protect Your Code: Top 3 Anti-Debugging Methods

Threat actors utilize numerous anti-analysis techniques, one of the most common of which is Anti-Debugging, to make post-detection analysis more difficult. In the malware they create and the ways they use to avoid detection and analysis by cybersecurity experts and solutions, threat actors have shown to be more inventive.

On the other hand, anti-debugging is a burden to malware analysts since it can slow down the process of reverse-engineering the code, making it more difficult to figure out how it works.

What is Anti-Debugging? 

Static analysis and dynamic analysis techniques are often used by hackers to learn more about an application and how it works. This assists them in identifying attack vectors that can be exploited to uncover app flaws. In most cases, this is accomplished by attaching a debugger to the app.

Debuggers are useful in the development process, but they can also be used for malicious purposes. They can provide hackers access to the app's code and its logic. Anti-debugging is a method of preventing debuggers from attaching to the application. 

Top 3 Anti-Debugging Methods 

Anti-debugging techniques allow programs to defend themselves even when they are not being developed in a secure environment. To enable an app to identify the existence of a debugger, a number of alternative strategies are used. We'll look at some of the most essential ones here.

Anti-JDWP Debugging 

JDWP stands for "Java Debug Wire Protocol". It is the debug protocol used for communication between a debugger and the Java virtual machine. Java-based android applications are not difficult to debug. Some of those methods are listed below.

1) Using the Debuggable Flag 

The "android:debuggable" attribute in the manifest file of the android app determines if the debugging using JDWP is enabled for the app. If the value is set to true, that means the debugging is allowed. This means the app has been tampered with.

The code below shows how we can check the same programmatically. 

public static boolean isDebuggable(Context context){ 

 return ((context.getApplicationContext().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0); 

}

 

2) Timer Checks 

Debugging an app slows down its process execution. We can analyze the time difference between executions to confirm if the debugger is attached or not. Programmatically, we can check the value of Debug.threadCpuTimeNanos as it is the time that the app is using to execute.

The following code can be used to do timer checks.

static boolean detect_threadCpuTimeNanos(){ 

 long start = Debug.threadCpuTimeNanos(); 

 for(int i=0; i<1000000; ++i

     continue

 long stop = Debug.threadCpuTimeNanos(); 

 if(stop - start < 10000000) { 

     return false

 } else

     return true

 }

}

 

3) JDWP Related Data Structures 

"DvmGlobals" structure in Dalvik machine can be used to access the global virtual machine state. It gives information about the debugger. Similarly, Android RunTime (ART) has a similar structure which can be exploited to get information about debuggers. One such example of the structure is shown below.

struct DvmGlobals

 bool jdwpAllowed; // debugging allowed for this process?

 bool jdwpConfigured; // has debugging info been provided?  

 JdwpTransportType jdwpTransport

 bool jdwpServer

 char* jdwpHost

 int jdwpPort

 bool jdwpSuspend

 Thread* threadList

 bool nativeDebuggerActive

 bool debuggerConnected; /* debugger or DDMS is connected */

 bool    debuggerActive; /* debugger is making requests */  

 JdwpState* jdwpState

};

Anti-Native Debugging 

Apart from JAVA debuggers, there is another category of debuggers based on pTrace similar to Linux. To prevent these types of debuggers from attaching to the applications, we can try the below methods.

1) Monitoring TracerPid 

We can monitor the TracerPid field that can be found in the status file of the process. If the value of TracerPid is 0, then that means there's no attached debugger. But if the value of TracerPid is anything other than 0, then that means some debugger is trying to attach to the process.

We can see an example of checking the status file in the following example. 

$ adb shell ps -A | grep com.example.test 

u0_a271 17657 573 4302108 50600 ptrace_stop 0 t com.example.test $ adb shell cat /proc/17657/status | grep -e "^TracerPid:" | sed "s/^TracerPid:\t//" TracerPid: 11839 

$ adb shell ps -A | grep 11839 

u0_a271 11839 11837 14024 4548 poll_schedule_timeout 0 S lldb-server

 

2) Creating a Dummy Process 

Another way we can prevent ptrace based debuggers is by creating a dummy process. That way if any debugger tries to attach to the process then it'll be forced to attach to the dummy child process.

Below is an example of code that can be used to fork a child process. 

void fork_and_attach() { 

 int pid = fork();

 if (pid == 0) { 

     int ppid = getppid(); 

     if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0) { 

        waitpid(ppid, NULL, 0);

        ptrace(PTRACE_CONT, NULL, NULL); 

     } 

 } 

}

Final Thoughts

Almost every software attack starts with reverse-engineering the code to figure out how it works and locate vulnerabilities to exploit. Attackers can tamper with the code, evade security constraints, change app behavior, and steal secret keys and sensitive data once they understand the internal dynamics of the target application. Utilizing the above-mentioned anti-debugging techniques on the other hand will certainly go a long way.

 

Published on Apr 28, 2022
Ajay Pandita
Written by Ajay Pandita
Ajay Pandita is a Penetration Tester working as a security analyst. Ajay specializes in performing pen tests on Android, iOS, and Web applications. He is OSCP certified and aims to become a Red Teamer. His journey started from web development and system administration and has 10+ years of experience in Linux. Alongside work, he spends his time doing CTFs. He also enjoys playing racing games and is a big fan of Red Bull F1 racing.

Questions?

Chat With Us

Using Other Product?

Switch to Appknox

2 Weeks Free Trial!

Get Started Now