Use IDA to view the assembly code, combined with the Tombstone file generated by the Android system, to analyze the crash of the Android app program

Table of contents

1. Introduction to IDA tools

2. Product and problem scenario description

3. View the Tombstone file

4. Use IDA to open the .so dynamic library file, view the context of the assembly code, and locate the line of code that crashed in the C++ source code

4.1. Use IDA to open the .so dynamic library file

4.2. Switch to Text View text view mode

4.3. According to the offset relative to the function, find the corresponding position in the assembly code and check the nearby assembly context

4.4. Find the corresponding C++ source code location through the assembly code context

4.5. Using a null pointer to call a class member function, why does it crash at the function call?

5. Finally


VC++ common function development summary (column article list, welcome to subscribe, continuous update...) https://blog.csdn.net/chenlycly/article/details/124272585 C++ software exception troubleshooting series tutorial from entry to mastery (column article list , Welcome to subscribe, keep updating...) https://blog.csdn.net/chenlycly/article/details/125529931 C++ software analysis tools from entry to mastery case collection (column article is being updated...) https:/ /blog.csdn.net/chenlycly/article/details/131405795 C/C++ basics and advanced (column articles, continuously updated...) https://blog.csdn.net/chenlycly/category_11931267.htmlWe        are investigating When the software is abnormal, sometimes it may be necessary to use the IDA disassembly tool to view the assembly code of the binary file to assist in analyzing the problem. Recently, I used the IDA tool to check the crash of the app program in the Android system. I used IDA to open the .so dynamic library file to view the assembly code context, combined with the information in the Tombstone file automatically generated by the Android system, and finally found the cause of the crash. . Today we will talk about the detailed investigation process of this problem for your reference or reference.

1. Introduction to IDA tools

       IDA is a powerful interactive static disassembly tool produced by Hex-Rays Company in Belgium. It can directly disassemble the assembly code of binary files. It is the best and most powerful static disassembly software in the field of software reverse engineering and security analysis. It has become an indispensable tool for many software security analysts! It supports multiple platforms such as Windows and Linux, and supports dozens of CPU instruction sets such as Intel X84, X64, ARM, and MIPS. IDA not only supports opening .dll library files on Windows platform, but also supports opening .so library files on Linux platform.

IDA was developed by a talented Russian programmer, llfak Guilfanov, who founded Hex-Rays in Belgium in 2005 as the founder and CEO.

Many people may not know that Russia is very powerful in the software field and is a country rich in talented programmers . For example, the most powerful static disassembly tool IDA we are talking about here was written by Russians! Jetbrains, the company of the popular IDE development tools IDEA , PyChram and WebStorm, was created by three talented Russian programmers! The load balancing and reverse proxy open source library Nginx widely used in the IT field and the ClickHouse open source library well-known in the field of big data are both written by Russians!

Russians have strong logical thinking. Russia is rich in mathematicians and chemists, such as the great mathematician Euler and the chemist Mendeleev who invented the periodic table of elements!

Huawei's self-developed database is named after GaussDB ( GaussDB ), and Huawei's server operating system is named after EulerOS ( EulerOS )! Salute to the greats!

2. Product and problem scenario description

       The problem in this article is an embedded hardware device . The Android system is used in the device and our application is running on the device. The main body of the application program is an Android app program developed in Java , and the app program communicates with the remote server through the underlying business module implemented in C++ .

The app program operates the underlying C++ module by calling the encapsulated JNI interface. In this case, the crash occurred in the underlying C++ module. Although the crash occurred in the underlying C++ module, the underlying C++ module is also running in the process of the app program, so it directly leads to the crash of the app program.

       When the app program crashes, the Android system perceives it and generates a Tombstone (tombstone) file containing abnormal crash information . This file is similar to the CoreDump file generated in the Linux system. When we analyze the abnormal crash of the software, we analyze these files. .

       We first opened the Tombstone file, checked the specific exception type of the abnormal crash and the function call stack at the time of the crash, but through the Tombstone file, we only know which function the crash occurred in. The code in the function is relatively long, and it is impossible to locate where the crash occurred. which line.

       So, we use IDA to open the .so module file displayed in the function call stack to view the assembly code, check the context near the assembly code that crashed, and finally find the line of C++ source code that crashed.

3. View the Tombstone file

       Take the Tombstone file automatically generated by the Android system when the crash occurs from the embedded device, open the file, and see the following information:

First of all, the reason for the current crash is: null pointer dereference, null pointer reference, that is, the use of a null pointer in the program causes a crash . Immediately afterwards, I saw the function call stack when the crash occurred. From the stack, the crash occurred in the CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp function in the libxxservice_hddll.so dynamic library. The specific function name can be seen in the call stack, indicating that there are function symbols in the .so dynamic library file. But you can't see the specific code line number, you can only see the offset relative to the function CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp:

#00 pc 0000000000075200  /xxxkyui/lib64/libxxservice_hddll.so (CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp(mtmsg::CMtMsg*, unsigned int, unsigned int)+1048) (BuildId: d6e3064a3e1a03d9bea3c4496e78cb4942d187d1)

The code in the CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp function is relatively long, and we cannot determine which line of code the crash occurred on.

Of course, if the problem is inevitable, or it is easy to reproduce, you can add printing to print out the values ​​​​of all pointers used in the function. After the crash, we can check the log to make sure. But some problems are difficult to reproduce, we still need to master some analysis methods!

       Since the specific function name and the offset relative to the function (first address) can be seen from the function call stack, we can use the IDA disassembly tool to view the assembly code context of the module libxxservice_hddll.so where the function is located to assist in locating the problem.

4. Use IDA to open the .so dynamic library file, view the context of the assembly code, and locate the line of code that crashed in the C++ source code

4.1. Use IDA to open the .so dynamic library file

       The Android system used by our embedded hardware devices, the main control CPU is based on the ARM architecture, and the code of the program is also compiled in the environment of the ARM platform. The IDA disassembly tool supports the ARM platform, so you can directly use IDA to open the program The binaries view the assembly code.

       Start IDA directly on the Windows system, and the following window will pop up:

Click the New button to disassemble a new file, and the main IDA window will pop up. Then directly drag the libxxservice_hddll.so file into the IDA main window to open it, and you will be prompted to open the file with 64-bit IDA, as follows:

The libxxservice_hddll.so dynamic library is a 64-bit program, so use 64-bit IDA to open it:

We opened 32-bit IDA earlier.

       So find the installation path through the desktop shortcut, start the 64 version of IDA in the path, then drag libxxservice_hddll.so into the IDA main window, and then pop up to select the format to open the binary file, as shown below:

IDA will automatically recognize the type of the binary file and open it in the default file format.

4.2. Switch to Text View text view mode

        After opening the binary file, the Graphic View view mode will be displayed by default:

 To right-click, click the "Text View" menu item in the pop-up right-click menu to switch to the text mode page, as follows:

4.3. According to the offset relative to the function, find the corresponding position in the assembly code and check the nearby assembly context

        First, we need to find where the CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp function is found in the assembly code displayed by IDA. Click Jump -> Jump to function... in the menu bar to open the following window:

Click the Search button at the bottom of the window, and enter the function name OnTextImageCreateBannerInfoRsp in the pop-up window:

Then click the OK button, search for the function in the function list, and double-click it to directly jump to the assembly code of the function, as shown below:

It can be seen that the function address (function first address) of this function is 0x0000000000074DE8, according to the offset of the relative function displayed in the Tombstone file:

#00 pc 0000000000075200  /xxxkyui/lib64/libxxservice_hddll.so (CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp(mtmsg::CMtMsg*, unsigned int, unsigned int)+1048) (BuildId: d6e3064a3e1a03d9bea3c4496e78cb4942d187d1)

Calculate the new address:

0x0000000000074DE8 + 0x418 (corresponding to 1048 in decimal) =   0x0000000000075200

Then search for the address 0x00000000000075200 in IDA to find the corresponding line of assembly code. The specific method is to click the mouse into the assembly code window (to make the window focus), and then press the shortcut key g to pop up the Jump to address window, and enter the address 0x0000000000075200 calculated above:

Click OK, and it will jump to the corresponding line, as shown below:

4.4. Find the corresponding C++ source code location through the assembly code context

       We are used to seeing the assembly code of the X86 platform, but we are not used to the assembly code of the ARM architecture. Whether it is the name of the assembly instruction or the name of the register, there is a big difference. I feel that the assembly code of the X86 platform is easier to read.

       We have located the location in the assembly code above, but which line of the C++ source code corresponds to the assembly code? In addition, when compiling under Release, the compiler will optimize the C++ code (some variables or function calls may be optimized), resulting in the inconsistency between the assembly code and the C++ code.

       How to match the assembly code with the C++ source code? Do we want to chew on the assembly code sentence by sentence? Forcibly reading the context of assembly code requires a certain level of assembly skills, which is difficult for ordinary people to do. Generally, we use the annotation information in the assembly context to assist reading . In this example, we use the annotation information to quickly read and locate.

Generally, when reading the assembly code context, on the one hand, use the comments in the assembly code, and on the other hand, compare the assembly code with the C++ source code!

       The assembly code line corresponding to the address 0x0000000000075200, the comment immediately below the line of code is the comment of the constant value string:

But can't see the full string. There is a trick here, you can move the mouse over the variable, and the complete content of the variable will be displayed in the form of TooTip, as shown below:

This place is a coincidence, such a string is printed in the log, so find the CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp function in the C++ source code, and find the print of "[CXXXServiceHMpHandler::OnTextImageCreateBannerInfoRsp] dispatch" in the function, and there is indeed this line of printing. As follows:

So I found the approximate line of the C++ source code corresponding to the address 0x0000000000075200, so the null pointer problem in this example should be the ptTip pointer in the above figure, that is, the value of the pointer is null. As a result, calling the value interface with this pointer caused a crash.

       For the introduction of IDA tools and detailed instructions, please refer to my previous article:

Detailed explanation of the use of IDA disassembly tools https://blog.csdn.net/chenlycly/article/details/120635120 Use IDA to view the assembly code context to assist in troubleshooting C++ software exceptions https://blog.csdn.net/chenlycly/article/ details/128942626 Use the disassembly tool IDA to view the context of the abnormal assembly code to assist in the analysis of C++ software exceptions https://blog.csdn.net/chenlycly/article/details/132158574

4.5. Using a null pointer to call a class member function, why does it crash at the function call?

       Why does it crash at the function call? If the called function is an ordinary function (non-virtual function), the function call will generally not crash. If the member variable of the class is accessed inside the function, the call using a null pointer will crash inside the called function instead of crashing call function!

       There is a possibility that the called function is a virtual function . For the call of the virtual function, the address of the virtual function needs to be found in the virtual function table through secondary addressing (the virtual function code segment address, here we need to distinguish the code segment address and data Segment address), in the process of secondary addressing, the null pointer is used as the memory address to access the memory, which triggers a memory access violation and causes a crash.

       In another case, a local variable that occupies a large stack memory is defined in the called function (such as using a structure with a large definition to define a local variable), which causes the stack overflow of the current thread (the stack space occupied by the current thread reaches The upper limit of the stack space allocated when the thread is created). For this kind of thread stack overflow scenario, it may crash at the place where the function is called. We have encountered this kind of problem in the project.

5. Finally

       This article describes in detail how to combine the Tombstone file and the IDA disassembly tool to quickly locate the complete process of the crash, hoping to provide some reference and reference for everyone. In addition, this question explains in detail how to use the IDA disassembly tool.

Guess you like

Origin blog.csdn.net/chenlycly/article/details/132283582