Deep Analysis of Android Rootnik Malware Using Advanced Anti-Debug and Anti-Hook, Part I: Debugging in The Scope of Native Layer By Kai Lu Published: 2017-01-26 · Archived: 2026-04-05 20:14:17 UTC Recently, we found a new Android rootnik malware which uses open-sourced Android root exploit tools and the MTK root scheme from the dashi root tool to gain root access on an Android device. The malware disguises itself as a file helper app and then uses very advanced anti-debug and anti-hook techniques to prevent it from being reverse engineered. It also uses a multidex scheme to load a secondary dex file. After successfully gaining root privileges on the device, the rootnik malware can perform several malicious behaviors, including app and ad promotion, pushing porn, creating shortcuts on the home screen, silent app installation, pushing notification, etc.  In this blog, I’ll provide a deep analysis of this malware. A Quick Look at the Malware The malware app looks like a legitimate file helper app that manages your files and other resources stored on your Android phone. Figure 1. The malware app icon installed https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 1 of 13 Figure 2. A view of the malware app We decompiled the APK file, as shown in Figure 3. https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 2 of 13 Figure 3. Decompile the malware app’s apk file Its package name is com.web.sdfile. First, let’s look at its AndroidManifest.xml file. Figure 4. AndroidManifest.xml file inside the malware app’s apk file We can’t find the main activity com.sd.clip.activity.FileManagerActivity, service class, or broadcast class in Figure 4.  Obviously, the main logic of the file helper app is not located in the classes.dex.  After analysis, it was discovered that the malware app uses the multidex scheme to dynamically load a secondary dex file and execute it. How Rootnik Works I. Workflow of Rootnik The following is the workflow of the android rootnik malware. Figure 5. An overview of the android rootnik malware’s workflow II. Going deep into the first dex file https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 3 of 13 The following is a code snippet of the class SecAppWrapper. Figure 6. A code snippet of the class SecAppWrapper The execution flow is shown below. Static code block -> attachBaseContext -> onCreate The static code block loads the dynamic link library libSecShell.so into the folder assets, and the program enters into the native layer, performs several anti-debug operations, decrypts the secondary dex file, and then uses a multidex scheme to load the decrypted secondary dex file, which is actually the main logic of the real application. The class DexInstall is actually the class MultiDex, and it refers to https://android.googlesource.com/platform/frameworks/multidex/+/d79604bd38c101b54e41745f85ddc2e04d978af2/library/src/android/support/mult The program then invokes the method install of DexInstall to load the secondary dex file.  The invoking of the method install of DexInstall is executed in native layer. Figure 7. Installing the secondary dex file In function attachBaseContext, the program loads the class com.sd.clip.base.MyApplication, which is the execution entry of the secondary dex. The method attach of Helper is a native method. In function onCreate, the program executes the method onCreate of the class com.sd.clip.base.MyApplication. That’s it. The first dex file is rather simple. Next, we’ll do a deep analysis of the native layer code, which is very complicated and tricky. III. The scope of the native layer code As described above, the native layer code uses some advanced anti-debug and anti-hook techniques, and also uses several decryption algorithms to decrypt some byte arrays to get the plain text string. The following is part of the export functions in libSecShell.so.  It becomes harder to analyze due to obfuscated function names. https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 4 of 13 Figure 8. Part of export functions in libSecShell.so All anti-debug native code is located in function JNI_Onload. As described in the last section, the method attach of class Helper in java scope is a native method. The program dynamically registers this method in native layer.  The following is a snippet of the ARM assembly code that registers native method in native layer. Figure 9. Dynamically register native method in native layer The function RegisterNatives is used to register a native method. Its prototype is shown below. jint RegisterNatives(JNIEnv *env,jclass clazz, const JNINativeMethod* methods,jint nMethods) The definition of JNINativeMethod is shown below. typedef struct { const char* name; const char* signature; void* fnPtr; } JNINativeMethod; The first variable name is the method name in Java. Here, it’s the string “attach”. The third variable, fnPtr, is a function pointer that points to a function in C code.  https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 5 of 13 We next need to find the location of the anti-debug code and bypass it, analyze how the secondary dex file is decrypted, and the dump the decrypted secondary dex file from memory. Let’s look at the following code in IDA: Figure 10. Code snippet around anti-debug code Based on our deep analysis, the instruction at address 0xF832 is a jump to address loc_F924. After tracing some code, we found the anti-debug code. Figure 11. The location of the anti-debug code The function p7E7056598F77DFCC42AE68DF7F0151CA() performs the anti-debug operations. The following is its graphic execution flow, which is very complicated. Figure 12. The graphic execution flow of anti-debug code The following are some methods of anti-debug and anti-hook used in the malware. 1. Detect some popular hook frameworks, such as Xposed, substrate, adbi, ddi, dexposed. Once found, hook it using these popular hook frameworks. It then kills the related process. https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 6 of 13 Figure 13. Detection of Xposed hook framework Figure 14. Finding the hook feature 2. It then uses an kind of multi-process ptrace to implement anti-debug, which is tricky a little.  Here we don’t plan to provide a detailed analysis of the anti-debugging implementation mechanism, but only give some simple explanations. We can see that there are two processes named com.web.sdfile. Figure 15. Two processes named com.web.sdfile     The following is a snippet of multi-process anti-debug code. Figure 16. A snippet of anti-debug code https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 7 of 13 3. The program also uses inotify to monitor the memory and pagemap of the main process. It causes the memory dumping to be incomplete.  The two processes use pipe to communicate with each other. In short, these anti-debug and anti-hook methods create a big obstacle for reversing engineering.  So bypassing these anti-methods is our first task.  Let’s try to bypass them. As described in Figure 10, the instruction at offset 0x0000F832 jumps to loc_F924, and then the program executes these anti-debug codes. We can dynamically modify the values of some registers or some ARM instructions to change the execution flow of the program when dynamically debugging.  When the program executes the instruction “SUBS R1, R0, #0” at offset 0xF828, we modify the value of register R0 to a non-zero value, which makes the condition of the instruction “BNE  loc_F834” become true. This allows the program to jump to loc_F834.   Figure 17. How to bypass the anti-debug code Next, we dynamically debug it, bypass the anti-debug, and then dump the decrypted secondary dex file. The dynamic debugging is shown below. Figure 18. Modifying the value of R0 to non-zero Figure 19. Jump to local_75178834 Next,  jump to local_751788D8, as follows. https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 8 of 13 Figure 20. Decryption function for the secondary dex The function p34D946B85C4E13BE6E95110517F61C41 is the decryption function. The register R0 points to the memory storing the encrypted dex file, and the value of R1 is the size of file and is equal to 0x94A3E(608830). The encrypted dex file is secData0.jar in the folder assets in the apk package. The following is the file secData0.jar. Figure 21. The file secData0.jar in the folder assets in the apk package Figure 22.  The content of the decrypted secondary apk file in memory We can now dump the memory of the decrypted file to the file decrypt.dump. https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 9 of 13 The decrypted file is a zip format file, and it contains the secondary dex file. After decryption, the program decompresses the decrypted secondary apk to a dex file. The function p3CBBD6F30D91F38FCD0A378BE7E54877 is used to decompress the file. Next, the function unk_75176334 invokes the java method install of class com.secshell.shellwrapper.DexInstall to load the secondary dex. Figure 23. Decompressing the decrypted secondary apk and loading the secondary dex file Figure 24. Calling the method install via Jni Here we finish the analysis of native layer and get the decrypted the secondary apk file, then will analyze the apk file in the part II of this blog. The Decryption Function That Decrypts secData0.jar in Native Layer: int __fastcall sub_7518394C(int result, _BYTE *a2, int a3) { int v3; // r1@1 int v4; // r3@5 unsigned int v5; // r3@7 int v6; // r6@7 int v7; // r5@7 char v8; // r2@8 int v9; // r4@9 int v10; // r3@9 int v11; // r7@11 _BYTE *v12; // r6@12 https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 10 of 13 int v13; // r4@13 _BYTE *v14; // r1@15 int v15; // [sp+0h] [bp-138h]@1 int v16; // [sp+4h] [bp-134h]@1 _BYTE *v17; // [sp+8h] [bp-130h]@1 int v18; // [sp+10h] [bp-128h]@5 char v19[256]; // [sp+1Ch] [bp-11Ch]@6 int v20; // [sp+11Ch] [bp-1Ch]@1 v17 = a2; v16 = result; v20 = _stack_chk_guard; v15 = a3; v3 = 0; if ( result <= 0x1FFFF ) { v3 = 0x20000 - result; if ( 0x20000 - result > a3 ) v3 = a3; v15 = a3 - v3; if ( v3 > 0 ) { v18 = dword_751AF650; v4 = 0; do { v19[v4] = v4; ++v4; } while ( v4 != 256 ); v5 = 0; v6 = 0; v7 = 0; do { v6 = (*(_BYTE *)(v18 + v5) + (unsigned __int8)v19[v7] + v6) & 0xFF; v8 = v19[v7]; v5 = (v5 + 1) & -((v5 + 1 <= 0xF) + ((v5 + 1) >> 31)); https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 11 of 13 v19[v7] = v19[v6]; v19[v6] = v8; ++v7; } while ( v7 != 256 ); v9 = 0; result = 0; v10 = 0; while ( v9 != v16 ) { v10 = (v10 + 1) & 0xFF; v11 = (unsigned __int8)v19[v10]; ++v9; result = (v11 + result) & 0xFF; v19[v10] = v19[result]; v19[result] = v11; } v12 = v17; do { v10 = (v10 + 1) & 0xFF; v13 = (unsigned __int8)v19[v10]; result = (result + v13) & 0xFF; v19[v10] = v19[result]; v19[result] = v13; *v12++ ^= v19[(v13 + (unsigned __int8)v19[v10]) & 0xFF]; } while ( v12 != &v17[v3] ); } } if ( v15 > 0 ) { v14 = &v17[v3]; result = (int)v14; do *v14++ ^= 0xACu; while ( (signed int)&v14[-result] < v15 ); } https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 12 of 13 if ( v20 != _stack_chk_guard ) result = ((int (*)(void))unk_75173E48)(); return result; } Source: https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer https://blog.fortinet.com/2017/01/24/deep-analysis-of-android-rootnik-malware-using-advanced-anti-debug-and-anti-hook-part-i-debugging-in-the-scope-of-native-layer Page 13 of 13 do { v6 = (*(_BYTE *)(v18 + v5) + (unsigned __int8)v19[v7] + v6) & 0xFF; v8 = v19[v7]; v5 = (v5 + 1) & -((v5 + 1 <= 0xF) + ((v5 + 1) >> 31)); Page 11 of 13