In the mobile environment, while debuggers are legal and legitimate development tools, they can also be used to reverse mobile banking and payment applications. This article describes some of the possible anti-debug techniques.
Using a debugger is a reversing technique that gives insight into an application. Equipped with such a tool, an attacker can inject malicious code into a banking application, or create a stub application, replacing the legitimate banking application, or modify some parts of the logic of the targeted application. Sometimes changing the value of a boolean variable is enough to compromise security.
Debugging is a very effective way to reverse run-time application behavior. A debugger allows, among other things, an attacker to go through the application flow, stop the execution of the application at arbitrary points, watch the state and values of variables, and finally, read and modify the memory used by the application.
Therefore, it is important, in the context of Real-Time Application Self-Protection (RASP), to actively prevent debuggers from being attached to mobile banking and payment applications.
An anti-debug system can choose, as a primary countermeasure, to prevent a debugger from being attached and, as a secondary countermeasure, to reactively terminate the application if the primary countermeasure has been circumvented and an active debugger is detected.
A general technique is to try to detect the presence of known debuggers and reversing tools, like the Frida Instrumentation framework, by checking their signature on the mobile operating system’s files, packages, processes, etc.
Anti-Debug Techniques for Mobile Banking & Payment Applications for iOS
iOS runs on a XNU kernel, which is a Unix-like hybrid kernel. This allows the use of several anti-debug techniques that are common to all the operating systems running on Unix-like kernels, including Android.
Using the PT_DENY_ATTACH flag is a very well known technique to implement anti-debugging in iOS.
Using ptrace with PT_DENY_ATTACH validates that no other debugger may attach to the protected process. If a debugger tries to attach, the process will then terminate.
Note that ptrace and the PT_DENY_ATTACH flag are not part of the public iOS API, and as such, it may prevent an iOS banking or payment application using it to be published in the Apple store.
In iOS, it is possible to use sysctl to detect a debugger attached to a process. Sysctl is a function from the iOS API that can retrieve information about a process, especially if it’s been debugged.
Anti-Debug Techniques for Mobile Banking & Payment Applications for Android
In Android, there are two possible debugging systems:
- A Java-level debugger using JDWP (Java Debug Wire Protocol), which is the debug protocol between a debugger and the Java VM.
- A ptrace-based debugger acting on the native Android Linux kernel.
Obviously, protecting mobile and payment applications from being debugged must take into account both JWDP and ptrace debuggers.
For a Java-based Android application, it’s not difficult to allow it to be debugged. It is enough to change its manifest file and a few other similar resources.
Using the Debuggable Flag
The android:debuggable attribute indicates if the process allows debugging or not. If that value has been set to true, then a debugger can be attached.
The value Debug.threadCpuTimeNanos is an indicator of the time the application is using to execute. Since debuggers significantly slow normal execution, this is a way to detect them.
Using JDWP-Related Data Structures
The Dalvik VM holds certain registers accessible via the DvmGlobals structure.
That structure gives information about the presence of debuggers. A similar structure can be exploited in the Android RunTime (ART) to give information about debuggers.
The defenses mentioned before are useless against ptrace based debuggers. Classical Linux techniques must be used against such native code debuggers.
It is possible to monitor the "TracerPid" field located in the status file of the process. The value of "TracerPid" for ‘no process attached’ is 0, so a value different from 0 means that a debugger is attached or that there are attempts in that direction.
Force Debug of a Dummy Process
It is possible to exploit the fact that only one debugger at a time can attach to a process. By doing so, the debugger can be prevented from attaching to the current process by forcing it to automatically debug a dummy child process.
Anti-Anti-Debug or How to Prevent Bypassing Debugger Detection
Finally, a sophisticated way of detecting debuggers is to detect anti-anti-debug measures. There is a list of known hooks that can be performed to prevent some of the aforementioned techniques from working. It is possible to detect the presence of these hooks to detect attempts to counter anti-debug.
References and Further Reading
- Read more articles about application security for mobile banking applications (2018 - today), by Martin Rupp, Stefan Hansen and more
- MASC Mobile App Security Core (2019), Web page by Cryptomathic
- PCI Mobile Payment Acceptance Security Guidelines for Developers version 2 (September 2017), by the Emerging Technologies, PCI Security Standards Council