Thursday, February 9, 2012

Debugging Apps with Native Code - part 2

This is part two of Debugging Apps with Native Code.

Now we have successfully installed a debuggable copy of our application to the device, let’s launch “ndk-gdb” again (I’ve suppressed errors to make the screen cleaner, but you should use the --verbose option for testing): 

Success!  The application is running, and we have successfully attached.  A simple “shared info” command will show that the library was successfully loaded.  Recall from before, our goal is to set a breakpoint, and print the register containing the password.  If we look in IDA, we will see that the function “check()” is exported as “Java_com_jakev_debugnative_MainActivity_check”, and after the “generatePassword” function is called, there is a string compare (“strcmp”) function call.

Let’s set a breakpoint for “generatePasword”, continue, switch to the emulator and enter / submit a password.

We see that our breakpoint has hit, and the debugger has stopped execution.  Let’s now advance to the “strcmp” function.  The code should stop again.  Now all that is left is to examine the registers.  While trying to learn more about ARM, I learned that the return value of a function are placed into register 0 ($r0), and since we are assuming that “generatePassword” is returning our password, let’s use the examiner to view this register:

That looks promising!  Let’s close out of our debugging session and enter this as the password.

As expected “abcdefghij” is the correct password!  I will include the source files for the project and native code if you would like to explore the app or try it for yourself.

The source files and APK are available here.

What is important here is that shared secrets in the application are never safe.  Even through clever obfuscation, they can be obtained.  While this may seem like a boring example, this type of vulnerability exists in popular applications on the Android market today.  Stay tuned for more posts similar to this!