
Secure Mobile Application
Development
Part 8: Debug Protection
Jahmel Harris, Technical Director
An easy way for an attacker to understand and modify the application is by attaching a debugger. Like with many binary protection techniques, it should be accepted that with enough time and effort and attacker will be able to bypass these client side controls. Depending on the sensitivity of the data used in the application, or the operations it performs, it may be a requirement to implement novel and unique approaches to debug detection to stay ahead of a malicious attacker.
iOS
The most common solution to detect the presence of a debugger is to make an assembly call to the ptrace() system call with the PT_DENY_ATTACH argument. As the call is being made directly in assembly, an attacker cannot simple hook the ptrace wrapper function. In order to increase the difficulty further, the syscall should be scattered inline though out the code base. This has the effect of increasing the number of places an attacker would need to discover and remove the debug protection.
A second approach that should be employed is viewing the kp_proc.p_flag flag returned by a call to sysctl() which indicates the presence of a debugger. If this flag is '-1', the application should exit. Sample code can be found here.
Android
Although Android will no longer allow any application distributed with Google Play to have the debuggable flag set to true in the Android Manifest, if an application is distributed in another way (such as direct download) care should be taken to make sure this flag is not set. This can protect users from having their instances of the application debugged whilst in use to allow an attacker to either enter the application sandbox or dump application secrets.
As an attacker though, it is possible to download an application and add the debuggable flag back into the AndroidManifest file, or hook the application to have it read this value as true.
To protect against this, we should periodically check whether the application is being debugged as well as before any particularly sensitive operations. This can be done by checking whether FLAG_DEBUGGABLE is set for our application in the ApplicationInfo class and by checking isDebuggerConnected and System.Diagnostics.Debugger.IsAttached. See here for sample code.