📜 ⬆️ ⬇️

Debugging Android applications without source codes: native methods

What is this article about


In the two previous articles, I talked about how to debug Android applications without Java source code and about some features of installing breakpoints . If a dear reader has not yet read these articles, I strongly recommend starting with them, and only then read this article.

It just so happened that so far I have been talking exclusively about debugging Dalvik bytecode and have not said a word about debugging native methods. And after all, it is in the native methods that the most tasty things are often hidden — tricky defenses, interesting malware features, zero-day vulnerabilities. Therefore, today I’m compressed, without “water”, I’ll tell you how to debug native methods without C / C ++ source code (or what, dear reader, they are written there).

In order to benefit from my story, you need to be a bit "in the subject." In particular, it is desirable that the reader

That's probably all the knowledge and skills that will be needed by the reader. Let's go to the tools.

Instruments


Today we will need:

We turn to the preparation.
')

Training


It is assumed that the reader is experienced enough to independently perform the following preparatory actions:

Now that all the preparations have been completed, you can proceed to debugging itself.

Debugging


The idea is to push our application directly under two debuggers: under the debugger built into NetBeans - to debug Dalvik bytecode, and under gdb - exclusively to debug calls to native methods. It sounds a little strange, but in practice it works quite well. Although not always - see the next section “Pitfalls”.

So, if the reader has completed all the preparatory steps from the previous “Preparation” section, now a reassembled application is probably running on his device or emulator, NetBeans is open on the computer, and debugging is somewhere after calling System.load(...) or System.loadLibrary(...) , but before the first call to the native method. And the reader is already aware of which library in which JNI functions correspond to which native methods. From this we begin.

Next comes step by step instructions. It was written for Windows, but I think it will work for Linux and MacOS. Please follow the instructions exactly:
  1. Command abd shell open the ADB console of your device or emulator. Find the PID of your application process using the ps command in the ADB console. In the same console, run the command:
     gdbserver :5039 --attach %PID% 
    where %PID% is the PID process of your application. In response, gdbserver should output something like:
     Attached; pid = %PID% Listening on port 5039 
    From now on, debugging in NetBeans will freeze. Those. Of course, you can click on the buttons there, but it is useless because the application that you are trying to debug in NetBeans is currently stopped under the GDB debugger. Do not panic, everything should be so!
  2. Open a new console on your computer, run the command
     adb forward tcp:5039 tcp:5039 
  3. In the same console, run gdb from the Android NDK:
     gdb libMyNativeLibrary.so 
    where libMyNativeLibrary.so is the very .so library where the JNI functions of interest are located. The library should be located on your computer in a directory that for gdb is current at startup. This will open the gdb console.
  4. In the gdb console, type the following commands:
     (gdb) target remote :5039 
    After these manipulations, a message like this should appear in the gdb console.
     Remote debugging using :5039 0x4009d58c in ?? () 
    and in the ADB console (it’s still open, remember?) something like
     Remote debugging from host 127.0.0.1 
  5. In the gdb console, run
     (gdb) info functions 
    to see the list of functions. In the list, among other functions, should be the JNI functions that interest you, something like:
     0x5b5f7bac Java_my_app_for_debug_MainActivity_coolNativeMethod 0x5b5f7c0c Java_my_app_for_debug_MainActivity_anotherCoolNativeMethod 0x5b5f7c1c Java_my_app_for_debug_MainActivity_theCoolestNativeMethodEver 
  6. In the gdb console, put breakpoints to the addresses of the functions you are interested in, in our case this
     (gdb) break *0x5b5f7bac (gdb) break *0x5b5f7c0c (gdb) break *0x5b5f7c1c 
  7. Resume the execution of your application using the c command in the gdb console. After executing this command, debugging in NetBeans will “freeze” and you can again debug Dalvik bytecode.

Now, every time there is a call to the native method in Dalvik bytecode, like
 const/high16 v8, 0x4100 invoke-static {v8}, Lmy/app/for/debug/MainActivity;->theCoolestNativeMethodEver(F)V 
debugging in NetBeans will freeze, but gdb will please you with messages like
 Breakpoint 1, 0x5b5f7c1c in Java_my_app_for_debug_MainActivity_theCoolestNativeMethodEver () from libMyNativeLibrary.so 

That is actually it. Further x/i $pc , stepi - generally forward to debug one ARM instruction after another (remember, I said at the beginning that the ARM assembler will be needed? - well, here ...)

Underwater rocks


Oh, there are a lot of them. A whole garden of pitfalls. Here are the most memorable bugs that caught me when using GNU gdb (GDB) 7.4.1 in conjunction with GNU gdbserver (GDB) 7.4.1 on Android 4.0.3 in the Ainol Aurora device ( the old one ):

  1. If after some time your gdb falls off regularly from gdbserver by watchdog timeout, run set watchdog 18000 in the gdb console - this should help.
  2. Sometimes as a result of the info functions in the list of functions, not the addresses of functions in memory are displayed, but offsets in the .so file, for example:
     0x000c0bac Java_my_app_for_debug_MainActivity_coolNativeMethod 0x000c0c0c Java_my_app_for_debug_MainActivity_anotherCoolNativeMethod 0x000c0c1c Java_my_app_for_debug_MainActivity_theCoolestNativeMethodEver 
    In this case, check or libMyNativeLibrary.so really lies in the directory that for gdb is current at startup, and restart gdb again with the same command gdb libMyNativeLibrary.so .
  3. Sometimes, as a result of the info functions , the list of functions displays the addresses of functions in memory and offsets in the .so file, for example:
     0x5b5f7bac Java_my_app_for_debug_MainActivity_coolNativeMethod 0x5b5f7c0c Java_my_app_for_debug_MainActivity_anotherCoolNativeMethod 0x5b5f7c1c Java_my_app_for_debug_MainActivity_theCoolestNativeMethodEver 0x000c0bac Java_my_app_for_debug_MainActivity_coolNativeMethod 0x000c0c0c Java_my_app_for_debug_MainActivity_anotherCoolNativeMethod 0x000c0c1c Java_my_app_for_debug_MainActivity_theCoolestNativeMethodEver 
    Ignore offsets in the .so file, put breakpoints on the addresses of functions in memory.
  4. If the break command for function names works fine, you are lucky, if not ... well, actually it doesn't work for me, so in this article I put breakpoints on the function addresses.
  5. set stop-on-solib-events may not work. It does not work for me.
  6. From time to time you will see the words Cannot access memory at address 0x1 . Ignore.

I am sure that this is not a complete list of glitches, which is fraught with the debugging of native methods without source codes, and that other researchers will find completely different, unique glitches that have not caught me. If anyone else finds - please share in the comments. Also in the comment please ask questions and / or make technical amendments to the text. I will try to answer as quickly as possible, but if I’m stupid, please be patient. I will try to answer all.

Happy debugging!



PS A request to the minus article unsubscribe in the comments what exactly did not like. I will try to fix it if possible.

PPS The article is a big plus, so the topic of debugging and reversing engineering is interesting to people and I will share my experience further. What were the disadvantages of the article in the beginning I did not understand - but oh well, let's write off the random fluctuations of habrasils.

PPPS If anyone needs technical assistance on the topic of the article - contact me, maybe I can help.

Source: https://habr.com/ru/post/151192/


All Articles