
In the
last article I reviewed the OWASP Mobile TOP 10 and then I didn’t have a good case to demonstrate the need to protect the source code. An interesting case for the demonstration appeared only recently, and who are interested in looking at our experience in circumventing environmental checks, let's take a cat.
When evaluating the work of one of the projects, our team immediately realized that the case would not be easy. The developers approached well the issue of information protection in the program and implemented checks of the state of the execution environment. The application did not start under any of the following conditions:
- the unit was rutted;
- emulator was used;
- USB connection;
- using developer mode.
The developers did not obfustirovat the source code and was not embedded test for modification of the code, which allowed me to analyze the ways in which the checks were performed and perform the necessary manipulations with them.
')
So, let's begin. According to the OWASP Mobile TOP 10, which we use as a basic testing methodology at Hacken, source code analysis (Reverse Engineering) - this vulnerability includes the analysis of binary files for determining source code, libraries, algorithms, etc. Software such as IDA Pro, Hopper, otool and other reverse engineering tools can provide insight into the internal workings of an application. This can be used to search for application vulnerabilities, extract critical information such as backend server, encryption keys or intellectual property.
For basic static analysis, I used an interesting tool such as MobSF, which performed decompilation and basic static analysis. After decompiling, I was interested in java- and smali-codes of the program. Java code is needed for analysis, and we will make changes to the smali code. In more detail, how smali and java correspond can be read
here .
After reviewing the list of classes, I found a file that is responsible for checking the phone’s rudeness (see Fig. 1) - rootingcheck / RootBeerNative.java.
Fig. 1. List of application classesAfter analyzing the class, it became clear that we need to further look for calls to the checkForRoot () and setLogDebugMessage () functions (see. Fig. 2).
Fig. 2. The source code of the classroom check for ruttingUsing the grep command, we get the following results, which show us which files have a call to the checkForRoot () and setLogDebugMessage () methods.
Search results:root @ kali: ~ / Desktop # grep -nr 'RootBeerNative' ******** _ v_0.9.2 /
********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:1:.class public Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:17: sput-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:28: sput-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:57: sget-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/o/CM.smali:591: new-instance v1, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:593: invoke-direct {v1}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:685: new-instance v0, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:687: invoke-direct {v0}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:689: invoke-static {}, Lrootingcheck/RootBeerNative;->?()Z ********_v_0.9.2/smali/o/CM.smali:753: new-instance v4, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:755: invoke-direct {v4}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:764: invoke-virtual {v4, v3}, Lrootingcheck/RootBeerNative;->checkForRoot([Ljava/lang/Object;)I ********_v_0.9.2/smali/o/xZ$5.smali:257: new-instance v1, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/xZ$5.smali:259: invoke-direct {v1}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/xZ$5.smali:261: invoke-static {}, Lrootingcheck/RootBeerNative;->?()Z
root @ kali: ~ / Desktop # grep -nr 'setLogDebugMessages' ******** _ v_0.9.2 / ********_v_0.9.2/smali/o/CM.smali:599: invoke-virtual {v1, v0}, Lrootingcheck/RootBeerNative;->setLogDebugMessages(Z)I ********_v_0.9.2/smali/o/CM.smali:761: invoke-virtual {v4, v0}, Lrootingcheck/RootBeerNative;->setLogDebugMessages(Z)I
But these were not all checks. After analyzing the class MainActivity.java, function calls were found, where the “su”, “test-keys” and “which” strings are passed, with which the test is performed (see. Fig. 3).
Fig.3. Check for ruttingAnd again, using the grep command, we search for somo-files for rutting checks:
Search results:root @ kali: ~ / Desktop # grep -nr 'su' ******** _ v_0.9.2 / ********_v_0.9.2/smali/o/CM.smali:443: const-string v2, "su" ********_v_0.9.2/smali/o/CM.smali:706: const-string v2, "su" ********_v_0.9.2/smali/o/xZ$5.smali:172: const-string v1, "su" ********_v_0.9.2/smali/o/xZ$5.smali:347: const-string v0, "su"
root @ kali: ~ / Desktop # grep -nr 'test-keys' ******** _ v_0.9.2 / ********_v_0.9.2/smali/o/xZ$5.smali:141: const-string v1, "test-keys" ********_v_0.9.2/smali/o/xZ$5.smali:374: const-string v0, "test-keys"
root @ kali: ~ / Desktop # grep -nr 'which' ******** _ v_0.9.2 / ********_v_0.9.2/smali/o/CM.smali:437: const-string v2, "which"
In the article I will show only one of the found modifications of checks for rutting. After a small manipulation, namely, a shift of 1 to 0 - checks for rutovnost removed.
Fig. 4. The variable value is one if the phone is rooted
Fig. 5. Now the value of the variable is zero if the phone is rootedAfter that - the program can be assembled, signed with its release key and launched on a mobile phone. But if not two BUT! Namely:
- check USB connection;
- Developer mode enable check - USB connection and enabled Developer mode enable dynamic analysis.
Developer mode check is turned off in the same way as rutting check - changing the unit to zero in the checks
In the MainActivity.java class, we find the line that is responsible for checking the Developer mode (see Figure 6). After this grep, we look for files in which the line “development_settings_enabled” is present and modify the check - change 1 to 0 (see Fig. 7 and 8).
Fig. 6. Check whether Developer mode is enabled on the phoneSearch results:grep -nr "development_settings_enabled" ******** _ v_0.9.2 \ Binary file ********_v_0.9.2\/build/apk/classes.dex matches ********_v_0.9.2\/smali/o/xZ$1.smali:49: const-string v1, "development_settings_enabled"
Fig. 7. The place where you need to modify
Fig. 8. ModificationAfter all the manipulations, you can run the program in Developer mode.
Next, disable the USB connection check. This check is in the class MainActivity.java (see Figure 9). Without the use of grep, we find a line in MainActivity.smali, we find a line that contains a string with a USB check — android.hardware.usb.action.USB_STATE. After that, in the smali-code, we modify the string to any other permissions, which returns “false” (see Fig. 10).
Fig. 9. Check for USB connection in the MainActivity.java code
Fig. 10. Line code to be deleted in MainActivity.smaliIt now remains to generate your release key and sign the application with it. This is done as follows:
- You need to install two applications: Keytool and Jarsinger.
- Run the application assembly command:
- apktool b C: \ Users \ User \ Desktop \ ********
- Next: cd ******** \ dist \
- Next: Keytool.exe -genkey -alias key.keystore -keyalg RSA -validity 20000 -keystore key.keystore
- Next: Jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore key.keystore ********. Apk key.keystore
- Next: jarsigner -verify -verbose -certs ********. Apk
That's basically all the manipulations and finished. Now install the application on your phone using adb install or from the smartphone directory and you can conduct dynamic testing for vulnerabilities.
After installing the application, launch it (see Fig. 11 and Fig. 12).
 |  |
Fig. 11. Turn on Developer mode and connect USB | Fig. 12. Running the application |
findingsOn a practical example, I showed how you can turn off some checks on the state of the execution environment. Further, with the help of other tools, we analyzed the vulnerability, but this is another story ...
What may cause neglect to protect the code:
- these are roundabouts of certain checks that are invested in the program
- the introduction of third-party code, after which the program can be published and used as malicious
How can I defend myself? At
Hacken, we decided not to reinvent the wheel and offered the client to obfuscate the source code and use functions that verify the modification of the source code.
PS
You can use a more advanced analysis method — this is smali debugging. You can read more about this in the
manual .
For reference, I have formulated a list of strings that is used to check for rutting:
- “Test-keys”;
- "/system/app/Superuser.apk";
- "/ sbin / su";
- "/ system / bin / su";
- "/ system / xbin / su";
- "/ data / local / xbin / su";
- "/ data / local / bin / su";
- "/ system / sd / xbin / su";
- "/ system / bin / failsafe / su";
- "/ data / local / su";
- "/ su / bin / su";
- "/ system / xbin / which";
- “Su”;
- “Which".