Android Pentest Note
Contents
Concept
Structure
- AndroidManifest file contains the application’s structure
- Res folder contains all the resources that the application needs to run , including user interface layout, icons, audio, etc.
- The most interesting files for us are the classes.dex files because they are the compiled java files. The .dex extension stands for Dalvik EXecutable. So we need to decompile these dex files to get the java classes.
Tools
- Apktool : tool for reverse engineering Android apk files. In this case we are using to extract files from apk and rebuild.
- Keytool : Java tool for creating keys/certs, that comes with the JDK.
- Jarsigner : Java tool for signing JAR/APK files, that comes with the JDK.
- Zipalign : archive alignment tool, that comes with the Android SDK.
- JD-GUI : To view java code.
- dex2jar : Converts Android dex files to class/jar files.
- MobSF : Mobile Security Framework (MobSF) is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing.
- Adb : is a versatile command-line tool that lets you communicate with a device.
- Frida : Dynamic Binary Instrumentation tool.
- How to Frida work? : Frida is writing code directly in process memory. When you attach frida to a running application, frida on the background uses ptrace to hijack the thread. A bootstrapper populates this thread and starts a new one, connecting to the frida server that is running on the device and loads a dynamically generated library that has the frida agent along with our instrumentation code. This last part is where all the magic happens. The hijacked thread is being restored to its original state and resumes, then the process continues normally. (https://erev0s.com/blog/frida-code-snippets-for-android/).
- APKLab : extension VSCode for apk (good).
Decompile and compile
Unpack file apk
unzip application.apk
To decompile an
apktool d -r -s application.apk
or
apktool d application.apk
or
java -jar Bytecode-Viewer-2.10.12.jar -> load apk file
or
using extension ApkLap in Visual Studio Code
or
using jadx
(https://github.com/skylot/jadx/releases/download/v1.2.0/jadx-gui-1.2.0-no-jre-win.exe)
Convert the Dex files into standard class files
sh d2j-dex2jar.sh application/classes.dex
(classes.dex have from unzip application)
Use the JD (Java Decompiler) to inspect the source
java -jar jd-gui.jar classes-dex2jar.jar
or
java -jar recaf-2.20.1-J8-jar-with-dependencies.jar --input=classes-dex2jar.jar
\
- Once you have made your changes, you need to repack the APK. This will create a my_application.apkfile:
To recompile(build) the apk
- After modify apk file (smili code,…) you can recompile apk app
apktool b -f -d application
- or
using APKLap in VSCode (https://github.com/APKLab/APKLab)
- After recompiling (building) the apk the new apk will be generated in Dist folder.(using apk tools)
- New apk save in : Application -> Dist -> application.apk
- The APK must be signed before you run on your device.
- Before signing an apk, create a key if you don’t have an existing one. If prompted for a password, create your own password.\
- To generate a key
keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
- Sign the apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore my_application.apk alias_name
- Verify apk (Option)
jarsigner -verify -verbose -certs my_application.apk
- Finally, the apk must be aligned for optimal loading:
./zipalign -v 4 my_application.apk my_application-aligned.apk
- You have a my_application-aligned.apk file, which you can install onto your device.
Using Adb and Frida interact Android
Adb
adb devices
: list devicesadb connect IP:Port
: connect to devicesadb shell
: spawn shelladb root
: run with root useradb backup -apk -shared com.android.insecurebankv2
(android:allowBackup=“true” in AndroidMainfest.xml) : backup apk filecat backup.ab
| ( dd bs=24 count=0 skip=1; cat) | zlib-flate-uncompress > backup.tar : read backup file
Frida
wget https://github.com/frida/frida/releases/download/15.0.0/frida-inject-15.0.0-android-x86.xz
: downloadadb push frida-server /data/local/tmp
: push Frida server to Androiadb shell "chmod 755 /data/local/tmp/frida-server"
: set permission Frida binariadb shell "/data/local/tmp/frida-server" &
: run Frida-server in AndroidFrida-ps -U
: list running processFrida-ps -aU | grep -i "name"
: check process name
Example Frida
Login bypass
- APP : Sieve (download apk -> adb install sieve.apk)
- A function named “checkKeyResult”. If the boolean value is true, the application redirects the flow to loginSuccessful() function if false then to loginFailed().
- Frida has support for binding with multiple languages like Python,C,.NET and Swift. However, we are using python to demonstrate the bypass
- Check process name :
frida-ps -aU | grep -i "sieve"
Java.perform(function () {
var MainActivity = Java.use('com.mwr.example.sieve.MainLoginActivity'); //Obtain referrence of the Activity currently running
MainActivity.checkKeyResult.implementation = function (b) { //Obtain reference of the function whcih needs to be called
send('checkKeyResult');
this.checkKeyResult(true); //Calling the function and passing the boolean parameter as true
console.log('Done:');
};
});
- Run:
frida -U --no-pause -l bypass.js -f appname
Check root bypass - APP : bankinsecurev2 (download apk -> adb install bankinsecurev2.apk)
- The application uses two functions to check whether the device is rooted or not as shown below in the decompiled APK of the InsecureBank app: doesSUexist, doesSuperuserApkExist
- Script bypass:
Java.perform(function () {
var MainActivity = Java.use('com.android.insecurebankv2.PostLogin');
MainActivity.doesSUexist.implementation = function () {
console.log('Done: doesSUexist');
return false;
};
MainActivity.doesSuperuserApkExist.implementation = function (b) {
console.log('Done: doesSuperuserApkExist');
return false;
};
});
- Running:
frida -U --no-pause -l bypass.js -f appname
Real world - Check emulator:
- In class StringUtil
- Check root:
- In class RootUtil
- Bypass check emulator and root (overload 2 method a() in StringUtil and a() in RootUtil):
Java.perform(function(){
console.log('\nBypass emulator detection');
var StringUtil = Java.use('package.name');
console.log('\nHijacking a() function in StringUtil class');
StringUtil.a.overload('java.lang.String').implementation = function(){
console.log('\nInside the a() function');
return true;
};
console.log('\nEmulator detection bypassed');
console.log('\nBypass root detection');
var RootUtil = Java.use('package.name');
console.log('\nHijacking a() function in RootUtil class');
RootUtil.a.overload('android.content.Context').implementation = function(){
console.log('\nInside the a() function');
return false;
};
console.log('\nRoot detection bypassed');
});
- Running:
frida -U --no-pause -l bypass.js -f appname
Refer
https://frida.re/docs
https://11x256.github.io/Frida-hooking-android-part-1/
https://11x256.github.io/Frida-hooking-android-part-2/
https://notsosecure.com/pentesting-android-apps-using-frida/