Android dynamic debugging of seven weapons-Hooking (lower), Android hooking
0x00
As mobile security becomes increasingly popular, various debugging tools are emerging one after another. However, no tool is omnipotent due to different environments and requirements. In addition, the tool is dead, and people are active. If you can understand the principle of the tool and combine your own experience, you can also create your own debugging weapon. Therefore, I will share some debugging tools and methods that I often use or original in this series of articles, hoping to play a catalyst role in domestic mobile security research.
The directory is as follows:
Seven Weapons for dynamic debugging in Android-Smali Instrumentation
Dynamic debugging of seven weapons in Android: peacock-Ida Pro
Android dynamic debugging of seven weapons-Hooking (I)
Android dynamic debugging of seven weapons-Hooking (bottom)
Debugging seven weapons in Android: Jasper knife-Customized DVM
Dynamic debugging of seven weapons in Android-Customized Kernel
Android dynamic debugging of the Overlord gun of seven weapons-Anti-debugging
The fist of seven types of Android dynamic debugging-Tricks & Summary
All the code and tools mentioned in the article can be downloaded from my github at: https://github.com/zhengmin1989/TheSevenWeapons
0x01 hook the native layer using function hooks
We can dynamically load the User-Defined so file and run the functions in the so file, but we cannot hook the target function, here we need to use the function Hook Technology to achieve this. The basic principle of function hook is to first use mprotect () to change the original code segment to readable, writable, and executable, and then modify the code at the entrance of the original function, so that the pc pointer jumps to the hook function in the so file Dynamically Loaded, after the hook function is executed, let the pc pointer jump back to the original function.
The hook5 logic of the program used for injection is not much changed compared with the previous hook4, and only the step of "calling dlclose to uninstall the so file" is missing, because the hook function we want to execute is in so, we do not need to call dlclose for uninstallation. The basic steps are as follows:
Save the status of the current Register-> get the mmap, dlopen, dlsym, dlclose address-> call mmap to allocate a memory space to save parameter information-> call dlopen to load the so file-> call dlsym to find the target function address-> Use ptrace_call to execute the target function-> recover registers status
The main code logic of hook5 is as follows:
We know that the arm processor supports two instruction sets: one is the arm Instruction Set and the other is the thumb instruction set. Therefore, the hook function may be compiled into an arm instruction set or a thumb instruction set. The Thumb instruction set can be seen as a subset of the compression form of arm commands. It is proposed to reduce the amount of code and has 16 bit code density. The Thumb command system is incomplete and only supports general functions. If necessary, you still need to use ARM commands, such as when entering an exception. Note that the length of the thumb command is not fixed, but the arm command is a fixed 32-bit length.
To make it easier for everyone to understand the hook principle, we should first consider the arm instruction set, because arm is simpler than thumb and does not need to consider the instruction length. Therefore, we need to compile the so of target and hook into the arm instruction set form. How can this problem be solved? Simply add ". arm" after the file name in Android. mk (the actual file does not need to be added ).
After the instruction set is determined, we can see the most important logic for implementing the hook. This logic is implemented in the so after the injection. First, we need a struct to save the assembly code and hook address:
Let's take a look at the injection logic. The most important function is hook_direct (). It has three parameters. One parameter is the structure we first defined to save the assembly code and the hook address, the second is the address of the original function we want to hook, and the third is the function we use to execute the hook. The function source code is as follows:
Although android has ASLR, there is no PIE, so the program image is fixed at the address 0x8000. Therefore, we use the mprotect () function to convert the entire target code segment to RWX, in this way, we can modify the code at the function entrance. Whether the modification is successful can be viewed through cat/proc/[pid]/maps:
Then we need to determine the target function address. There are two methods. If the target program itself is not strip, all the symbrs exist. Therefore, you can use dlopen () and dlsym () methods to obtain the target function address. However, in many cases, the target program will be strip, especially binary files that can be directly run will be directly strip by default. For example, the sevenWeapons () function name in target will be removed during compilation, so we cannot find this function if we use dlsym. At this time, we need to use ida or objdump to locate the target function address. For example, we can use objdump to find the address of the sevenWeapons (int number) function in the target program:
Although the binary value of target is strip, the starting address of sevenWeapons () is 0x84f4. "Mov r2, r0" is the command for loading the number parameter, and then <printf @ plt> is called to output the result. The last parameter is the address of the hook function to be executed. This address is very simple. Because it is a function in so, you can directly write the function name when calling hook_direct.
Hook_direct (& eph, hookaddr, my_sevenWeapons );
Next, let's take a look at how to modify the function entry. First, let's save the address of the original function and the first three commands of the function. Then we changed the first command of the target function to LDR pc, [pc, #0], which means to jump to the address indicated by the PC pointer, since the value read from the pc register is actually the address of the Current Instruction plus 8, we save the following two instructions as the address of the hook function. In this case, we can control the address of the PC jump to the hook function.
Finally, we call the hook_cacheflush () function to refresh the instruction cache. Although the previous operation modified the commands in the memory, the modified commands may have been cached. If the modified commands are executed again, the CPU may give priority to the commands in the cache, the modified command cannot be executed. Therefore, we need to use a hidden system call to refresh the cache. The hook_cacheflush () code is as follows:
After refreshing the cache and executing the original function, the pc pointer will jump to our custom hook function. The code in the hook function is as follows:
First, in the hook function, we can obtain the parameters of the original function, and we can modify the parameters of the original function, for example, multiply the number by 2. Then we use hook_precall (& eph); to restore the content of the original function. The hook_precall () content is as follows:
In hook_precall (), we first restore the original three commands, and then use hook_cacheflush () to refresh the memory. After processing, we can execute the original function orig_sevenWeapons (number. After execution, if we want to hook this function again, we need to call hook_postcall (& eph) to modify the three original commands.
Next we will use hook5 and libinject2.so to inject the target program:
We can see that after the injection, we have successfully obtained the value of the parameter number, and "Hello, LiBieGou !" The subsequent number is doubled.
0x02 use adbi to implement hook on the JNI Layer
The previous section describes how to hook native-layer functions. Next, let's talk about how to use adbi to hook functions at the JNI layer. Adbi is an injection framework on the android platform and is open-source. The Hook principle is the same as the technology we introduced earlier. This framework supports arm and thumb instruction sets, and also supports location of the symbol function through strings.
First, we need an example to explain, so I wrote the program test2.
After clicking the button in the program, the program will call Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI (JNIEnv * env, jobject thiz, jint a, jint B) function in so to calculate the result of. The default values are a = 1 and B = 1. Next I will teach you how to use adbi to hook this JNI function.
Because adbi is an injection framework, after we download the source code, we only need to figure out the example in the source code. The Hijack folder is a saved program for injection. It works the same way as hook5.c, so no modification is required. We only need to modify the code in example, that is, the source code of the so file to be injected.
First, create two files, hookjni. c and hookjni_arm.c, In the/adbi-master/instruments/example folder ". "Hookjni_arm.c" is actually a shell used to compile the hook function entry into the arm instruction set. The content is as follows:
The purpose of this file is only to compile it using the arm instruction set. We can see that there is an additional ". arm" behind "hookjni_arm.c" in Android. mk ":
Let's take a look at "hookjni. c ":
This code is very similar to the code I mentioned in the previous section. my_init () is used for hook operations. We need to provide the so file name and function name that we want to hook, then provide the hook function address for the thumb Instruction Set and arm instruction set.
My_Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI () is the provided hook function. We changed both a and B to 10 in this hook function. In addition, we also use the counter global variable to control the number of hooks. Here we set counter to 3. After three hooks, no hooks will be performed.
After editing the code, we only need to execute "build. sh" in the root directory of adbi for compilation:
After compilation, copy hijack and libexample. so to the/data/local/tmp directory. Then use hijack for injection:
Then, click the button and we can see that we have successfully modified the values of a and B to 10, and then 1 + 1 = 20 is displayed.
Through cat adbi_example.log, we can see the log printed during the hook process:
We can see that adbi is hooked through the thumb instruction set, because the test2 program is compiled using the thumb instruction set. In fact, the hook thumb instruction set is similar to the arm instruction set. You can find the logic of the hook thumb Instruction Set in "/adbi-master/instruments/base:
In fact, the h-> jumpt [20] character array stores the code that controls the pc pointer to jump to the hook function address under the thumb instruction set. The Hook process is the same as that of the arm instruction set.
0x03 use Cydia or Xposed to implement JAVA layer hook
There are already many articles and examples about Cydia and Xposed, so we will not repeat them here. Here we recommend the thin dance and my articles, and basically we will know how to use these two frameworks:
Android. Hook framework xposed (Http traffic monitoring) http://drops.wooyun.org/papers/7488
Android. Hook frame Cydia (shell-removing machine) http://drops.wooyun.org/tips/8084
How to Use Android Hook to cheat http://drops.wooyun.org/tips/8416
I personally feel that the Xposed framework is better, mainly because the authors of Cydia have not updated the Cydia framework for a long time, and not only many bugs do not support ART. However, there are a lot of good debugging software/plug-ins based on the two frameworks, so sometimes you still need to use Cyida.
Next we recommend several useful plug-ins Based on Cydia and Xposed:
1) ZjDroid: ZjDroid is a dynamic reverse analysis module based on Xposed Framewrok. The reverse analyzer can do the following through ZjDroid: 1. DEX File Memory dump 2. Memory BackSmali Based on Dalvik key pointer, effectively crack mainstream reinforcement solutions 3. dynamic monitoring of sensitive APIs 4. dump of data in the specified memory area 5. Obtain DEX information loaded by the application. 6. Obtain the loading class information of the specified DEX file. 7. dump Dalvik java heap information. 8. Run the lua script dynamically in the target process. Https://github.com/halfkiss/ZjDroid
2) XPrivacy: XPrivacy is a module application based on the Xposed framework. It can manage the privacy disclosure permissions of all applications and adopt a spoofing policy for applications that may cause crashes, provide forged information, such as the IMEI number of a mobile phone. Https://github.com/M66B/XPrivacy
3) Introspy: Introspy is a black box testing tool that can track and analyze mobile apps and detect security issues. This tool supports many cryptographic libraries and custom hooks. Https://github.com/iSECPartners/Introspy-Android
0x04 Introspy practice
We use evilapk400 on alictf as an example to explain how to use introspy to debug programs. Evilapk400 uses a relatively complex dex shelling technology. If you do not use a custom dalvik shelling tool for shelling, it will be very troublesome. However, if we use another method, we can directly obtain the string, key, and IV Information of the encryption algorithm through dynamic debugging.
First, install cyida.apk and Introspy-Android Config.apk on your mobile phone. Then, use eclipse to open the "Introspy-Android Core" source code and add a custom hook function. Although Introspy hooks the password library by default, it does not hook some strings functions. Therefore, we manually add a hook for String. equals:
Then we compile and generate and install Introspy-Android Core.apk on the mobile phone. Then install EvilApk400. Entrospy-Android Config and check com. ali. encryption.
Next, open evilapk400, enter the desired content, and click log on.
Then we can use adb logcat to see the output information of Introspy:
Log makes it easy to see that evilapk400 uses DES encryption. Through log, we get the ciphertext, Key, and IV, so we can write a python program to calculate the final answer:
0x05 Summary
This article introduces native layer, JNI layer, and JAVA layer hook, which can basically meet our needs for android hook. In addition, all the code and tools mentioned in the article can be downloaded from my github at: https://github.com/zhengmin1989/TheSevenWeapons
0x06 references
Author: steamed rice @ aliyunju security. For more technical articles, visitAlibaba Cloud universal security blog