Static Analysis
Static Analysis
Decompile APK to Java Source Code
- Unzip APK -> Convert DEX to JAR -> Convert Jar to java src files
- or automate the process using apkx
- Open decompiled code in Android Studio
- Delete the created Android Studio files by default
- Copy the decompiled Java src code to the Java folder
Reverse Engineering Native Libraries
- Are native libraries used? Look for keywords
JavaSystem.loadLibrary
- Look for .so file in the libs/ directory
- Search for the function offset in file
- Load library into any disassembler
Dump Strings
Dump Strings from DEX file
- unzip to extract DEX file using
- Load DEX file into ghidra or use dextra
- Search for keywords such as passwords, keys, seceret, etc...
Dump Strings from native code
Misc Ideas
- Check android documentation for releveant APIs that can be used for this application and search for those
Use Static Analyzers
Dynamic Analysis
Information Gathering
- If using unrooted device, use objection to patch APK [[Frida & Objection cheatsheet]]
- List open files for specified process
- List open connections for specified process
- List connections using netstat
- List loaded native libraries
- Sandbox Inspection: The application data is stored in a sandboxed directory present at
/data/data/<app_package_name>
Debugging with jdb
- Make application show up as debuggable using magsik ```bash adb shell su resetprop ro.debuggable 1 stop start ````
- Setup JDP [[adb Cheatsheet#Debug Debuggable Application with JDP]]
- Start jdb is suspended state
Debug APK with Android Studio
- Decompile project using jadx-gui)
- Save src files
- Create new android studio project
- Replace src files there with decompiled src files
- On the device, choose the app as debug app on the "Developer options" (Uncrackable1 in this tutorial), and make sure you've switched on the "Wait For Debugger" feature.
- Set breakpoint at main activity
onCreate
to bypass root and debugging checks
Dynamic Analysis
Automated
Dynamic Analysis on Non-Rooted Devices
- Patch the apk -> include frida gadget library -> objection communicates with frida gadget api
# Download the Uncrackable APK
$ wget https://raw.githubusercontent.com/OWASP/owasp-mstg/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk
# Patch the APK with the Frida Gadget
$ objection patchapk --source UnCrackable-Level1.apk
# Install the patched APK on the android phone
$ adb install UnCrackable-Level1.objection.apk
# After running the mobile phone, objection will detect the running frida-server through the APK
$ objection explore
Native Code Tracing
- use
frida-trace
andjnitrace
to trace native code calls [[Frida & Objection cheatsheet#Trace Native Calls]]
Tampering and Runtime Instrumentation
Patching, Repackaging, and Re-Signing
- Unpack apk
- Modify the manifest or code
- Repackage the APK
- Generate Code signing certificate
- Re-sign the APK
- Start the app "Developer options" contain the useful "Wait for Debugger" feature, which allows you to automatically suspend an app doing startup until a JDWP debugger connects
Patching React Native applications
Extract JS file
- Main Application code saved at
assets/index.android.bundle
- Beautify the file using JStillery (mindedsecurity.github.io) . Note: use CLI version to avoid code disclosure to 3rd party
Patch JS file
- Unpack the APK archive using
apktool
tool - Copy the content of the file
assets/index.android.bundle
into a temporary file. - Use
JStillery
to beautify and deobfuscate the content of the temporary file. - Put the patched code on a single line and copy it in the original
assets/index.android.bundle
file. - Repack the APK archive using
apktool
Library Injection
Patching the Application's Smali Code
- An Android application's decompiled smali code can be patched to introduce a call to
System.loadLibrary
- Insert the previous code early in the App life cycle such as
onCreate
- add the library libinject.so in the respective architecture folder
- resign the application
Patching Application's Native Library
- Use LIEF (quarkslab.com) to patch elf libraries
Preloading Symbols
- Please note that if the library to be preloaded does not have SELinux context assigned, from Android 5.0 (API level 21) onwards, you need to disable SELinux to make
LD_PRELOAD
work, which may require root.
Dynamic Instrumentation
-
Frida List classes methods js
// Get list of loaded Java classes and methods // Filename: java_class_listing.js Java.perform(function() { Java.enumerateLoadedClasses({ onMatch: function(className) { console.log(className); describeJavaClass(className); }, onComplete: function() {} }); }); // Get the methods and fields function describeJavaClass(className) { var jClass = Java.use(className); console.log(JSON.stringify({ _name: className, _methods: Object.getOwnPropertyNames(jClass.__proto__).filter(function(m) { return !m.startsWith('$') // filter out Frida related special properties || m == 'class' || m == 'constructor' // optional }), _fields: jClass.class.getFields().map(function(f) { return( f.toString()); }) }, null, 2)); }
-
Run the frida script on the pid [[Frida & Objection cheatsheet]]
Process Exploration
- List devices with frida
- [[r2frida cheatsheet#Start the binary with r2frida]]
- [[r2frida cheatsheet#Explore the binary with r2frida]]
- Explore binary with objection
- Explore modules in memory with objection
memory list modules
- Dump memory fridump
- Extract strings from dump
strings *