Reverse Engineering Stack Exchange is a question and answer site for researchers and developers who explore the principles of a system through analysis of its structure, function, and operation. Join them; it only takes a minute:

I am a noob to the reversing world. I have a Android Java application which uses a shared library via JNI and I would like to set a breakpoint in the shared library. The shared library is stripped so as I far as I understand I can set breakpoints by address only. I have put the shared object through IDA and have a couple of positions I would like to set breakpoints but I am unsure on how I can calculate this or even if this is possible. I am using gdbserver on Android attaching to the process and connecting from Mac OSX using gdb in the NDK. I have been trying to calculate the memory address by taking what /proc/'pid'/smap gives me and calculating an offset from the IDA assembly I have. Is this the right direction? Is this even possible?

1 Answer
1

I've been doing the same/similar stuff recently, and while you can get it to work, it's not that easy.

It helps if you have a rooted android device, a terminal emulator to run gdbserver, and, if possible, a terminal emulator that can open more than one window, so you kan kill the gdbserver from the second window if it hangs up. Also, a real keyboard on the android device helps, as it's much easier to repeat commands when you have real cursor keys.

You don't need to connect your Droid to your mac using an USB cable. I started gdbserver like this:

You can add the "IDA Address" of the function to the Map address. For example, in my library:

The two functions i was interested in had "IDA addresses" BA584 and BA99C.

The address in /proc/maps said 688D0000 as base address of the executable segment.

The real function addresses were 6898A584/6898A99C, which is base address + "IDA address" in both cases.

There are two things to consider when you check you really found the correct address:

You can't use the gdb disassemble command as it relies on functions and symbols. Use the x/i command to disassemble. For example, in my case, x/20i 0x6898A584 to see the 20 instructions at this address.

The arm has two different modes, Thumb mode and ARM mode. If gdb has no symbols, it might choose the wrong one when disassembling, making your GDB disassembly not resemble the IDA disassembly at all.

Use set arm force-mode arm and set arm force-mode thumb to try both. For example, this is what IDA told me about my BA584 function:

My application crashed various times when i was debugging it, which made gdbserver lose sync with gdb, resulting in lots of "Ignoring packet error" messages from gdb. Killing gdbserver (thus the 2nd window), restarting the application, and reconnecting gdb seemed to be the only remedy in these cases. When you restart the application, make sure you re-check /proc/..../maps for the .so base address, it stays the same most of the time but changes sometimes, especially when there's some time between invocations. You'll notice my address (0x6890F584) in the above example does not match the one i told you earlier, this is because in the example, the map base address had changed to 68855000.