397 lines
9.7 KiB
Markdown
397 lines
9.7 KiB
Markdown
---
|
|
name: reverse-engineering-mobile
|
|
description: 'Use for mobile app reverse engineering: Android APK analysis, iOS IPA
|
|
analysis, dex/smali reversing, native library (.so) analysis, keychain/keystore
|
|
extraction, SSL pinning bypass, root:REDACTED detection bypass, and mobile app
|
|
security research.'
|
|
version: 1.0.0
|
|
platforms:
|
|
- linux
|
|
- macos
|
|
- windows
|
|
triggers:
|
|
- reverse
|
|
- engineering
|
|
- mobile
|
|
- app
|
|
- android
|
|
- apk
|
|
- analysis
|
|
- ios
|
|
- ipa
|
|
- dex
|
|
- smali
|
|
- reversing
|
|
depends_on: []
|
|
metadata:
|
|
tags:
|
|
- reverse
|
|
- engineering
|
|
- mobile
|
|
---
|
|
|
|
# Reverse Engineering — Mobile Applications
|
|
|
|
## Trigger Conditions
|
|
|
|
- Android APK decompilation and analysis
|
|
- iOS IPA analysis and decryption
|
|
- DEX/Smali code analysis and modification
|
|
- Native library (.so / .dylib) reversing
|
|
- SSL/TLS pinning bypass
|
|
- root:REDACTED detection bypass
|
|
- Keychain/Keystore data extraction
|
|
- Mobile API traffic analysis
|
|
- App sandbox exploration
|
|
- Mobile cryptography analysis
|
|
- Frida script development for mobile
|
|
- Obfuscated mobile app analysis
|
|
- React Native / Flutter / Unity app reversing
|
|
- Mobile game modification
|
|
|
|
## Core Methodology
|
|
|
|
### 1. Android APK Analysis
|
|
|
|
**Decompilation pipeline:**
|
|
```bash
|
|
# 1. Extract APK
|
|
adb shell pm path com.target.app
|
|
adb pull /data/app/.../base.apk
|
|
|
|
# 2. Decompile with JADX (Java source)
|
|
jadx -d output --deobf --deobf-min 3 base.apk
|
|
|
|
# 3. Decompile with apktool (resources + smali)
|
|
apktool d base.apk -o apktool_output
|
|
|
|
# 4. Analyze manifest
|
|
cat apktool_output/AndroidManifest.xml
|
|
# Look for: exported activities, permissions, deep links, providers
|
|
|
|
# 5. Search for API endpoints
|
|
grep -rE 'https?://' output/ --include='*.java' | \
|
|
grep -v '\.xml' | sort -u
|
|
|
|
# 6. Search for crypto keys/secrets
|
|
grep -rE '(api_key|secret|password|token|AES|RSA)' output/ --include='*.java'
|
|
|
|
# 7. Analyze native libraries
|
|
unzip base.apk 'lib/*'
|
|
file lib/arm64-v8a/*.so
|
|
# Reverse with IDA/Ghidra
|
|
```
|
|
|
|
**Smali modification:**
|
|
```smali
|
|
# Bypass root detection:
|
|
# Original:
|
|
invoke-static {}, Lcom/target/RootDetector;->isRooted()Z
|
|
move-result v0
|
|
if-eqz v0, :cond_not_rooted
|
|
|
|
# Patched:
|
|
const/4 v0, 0x0 # always return false
|
|
|
|
# Bypass SSL pinning:
|
|
# Find the pinning class, override the check method
|
|
.method public verify(Ljava/lang/String;Ljava/security/cert/X509Certificate;)Z
|
|
.registers 3
|
|
const/4 v0, 0x1
|
|
return v0
|
|
.end method
|
|
```
|
|
|
|
**Rebuild and sign:**
|
|
```bash
|
|
# Rebuild with apktool
|
|
apktool b apktool_output -o modified.apk
|
|
|
|
# Sign with uber-apk-signer
|
|
java -jar uber-apk-signer.jar -a modified.apk
|
|
|
|
# Or with apksigner (Android SDK)
|
|
apksigner sign --ks my.keystore modified.apk
|
|
```
|
|
|
|
### 2. iOS IPA Analysis
|
|
|
|
**IPA extraction:**
|
|
```bash
|
|
# Extract IPA (from jailbroken device or decrypted dump)
|
|
unzip TargetApp.ipa -d ipa_output
|
|
|
|
# Analyze binary
|
|
file Payload/TargetApp.app/TargetApp
|
|
otool -l Payload/TargetApp.app/TargetApp # load commands
|
|
otool -Iv Payload/TargetApp.app/TargetApp # imports
|
|
strings Payload/TargetApp.app/TargetApp | head -100
|
|
|
|
# Class-dump (Objective-C headers)
|
|
class-dump Payload/TargetApp.app/TargetApp > headers.txt
|
|
|
|
# Hopper Disassembler or IDA for full analysis
|
|
# Ghidra also supports Mach-O
|
|
```
|
|
|
|
**Frida on iOS:**
|
|
```bash
|
|
# Install Frida on jailbroken device
|
|
# List processes
|
|
frida-ps -U
|
|
|
|
# Attach to app
|
|
frida -U -f com.target.app --no-pause
|
|
|
|
# Script — bypass SSL pinning
|
|
frida -U -f com.target.app --no-pause -l ssl_bypass.js
|
|
```
|
|
|
|
### 3. SSL Pinning Bypass
|
|
|
|
**Android — Frida universal bypass:**
|
|
```javascript
|
|
// ssl_pinning_bypass.js
|
|
Java.perform(function() {
|
|
// OkHttp 3
|
|
try {
|
|
var CertificatePinner = Java.use('okhttp3.CertificatePinner');
|
|
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {};
|
|
CertificatePinner.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function() {};
|
|
} catch(e) {}
|
|
|
|
// TrustManager
|
|
var TrustManager = Java.registerClass({
|
|
name: 'custom.TrustManager',
|
|
implements: [Java.use('javax.net.ssl.X509TrustManager')],
|
|
methods: {
|
|
checkClientTrusted: function(chain, authType) {},
|
|
checkServerTrusted: function(chain, authType) {},
|
|
getAcceptedIssuers: function() { return []; }
|
|
}
|
|
});
|
|
|
|
var TrustManagerFactory = Java.use('javax.net.ssl.TrustManagerFactory');
|
|
var tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
|
tmf.init(null);
|
|
var trustManagers = tmf.getTrustManagers();
|
|
// Replace with our trust manager
|
|
});
|
|
|
|
// iOS — bypass
|
|
var SSLKillSwitch = ObjC.classes.NSURLSession;
|
|
// Or hook SecTrustEvaluate:
|
|
Interceptor.attach(
|
|
Module.findExportByName('Security', 'SecTrustEvaluate'), {
|
|
onLeave: function(retval) {
|
|
retval.replace(0); // errSecSuccess
|
|
}
|
|
}
|
|
);
|
|
```
|
|
|
|
**Android — network security config:**
|
|
```xml
|
|
<!-- Create res/xml/network_security_config.xml -->
|
|
<network-security-config>
|
|
<base-config>
|
|
<trust-anchors>
|
|
<certificates src="system" />
|
|
<certificates src="user" />
|
|
</trust-anchors>
|
|
</base-config>
|
|
<debug-overrides>
|
|
<trust-anchors>
|
|
<certificates src="user" />
|
|
</trust-anchors>
|
|
</debug-overrides>
|
|
</network-security-config>
|
|
```
|
|
|
|
### 4. root:REDACTED Detection Bypass
|
|
|
|
**Android — common detection methods:**
|
|
```java
|
|
// Detection checks to bypass:
|
|
// 1. Check for su binary
|
|
Runtime.getRuntime().exec("which su")
|
|
|
|
// 2. Check for Superuser.apk
|
|
new File("/system/app/Superuser.apk").exists()
|
|
|
|
// 3. Check build tags
|
|
Build.TAGS.contains("test-keys")
|
|
|
|
// 4. Check for Magisk
|
|
new File("/sbin/.magisk").exists()
|
|
|
|
// 5. Check for dangerous properties
|
|
System.getProperty("ro.build.selinux")
|
|
|
|
// Frida bypass:
|
|
Java.perform(function() {
|
|
// Hook all detection methods
|
|
var RootBeer = Java.use('com.scottyab.rootbeer.RootBeer');
|
|
RootBeer.isRooted.implementation = function() { return false; };
|
|
|
|
// Hook file existence checks
|
|
var File = Java.use('java.io.File');
|
|
File.exists.implementation = function() {
|
|
var path = this.getAbsolutePath();
|
|
if (path.indexOf("su") >= 0 || path.indexOf("magisk") >= 0) {
|
|
return false;
|
|
}
|
|
return this.exists();
|
|
};
|
|
});
|
|
```
|
|
|
|
### 5. Native Library (.so) Analysis
|
|
|
|
**Extraction and analysis:**
|
|
```bash
|
|
# Extract from APK
|
|
unzip app.apk 'lib/*'
|
|
|
|
# Analyze with Ghidra/IDA
|
|
ghidraRun
|
|
# Load .so file, set base address, analyze
|
|
|
|
# Or with radare2
|
|
r2 lib/arm64-v8a/libnative.so
|
|
aaa
|
|
afl
|
|
pdf @ main
|
|
|
|
# Identify JNI functions (Java_ prefix)
|
|
strings libnative.so | grep "^Java_"
|
|
```
|
|
|
|
**JNI function naming:**
|
|
```
|
|
Java_{package_name}_{class_name}_{method_name}
|
|
Example: Java_com_target_app_crypto_NativeLib_encrypt
|
|
|
|
// JNI signature:
|
|
JNIEXPORT jstring JNICALL
|
|
Java_com_target_app_crypto_NativeLib_encrypt(
|
|
JNIEnv *env,
|
|
jobject thiz,
|
|
jstring input
|
|
);
|
|
```
|
|
|
|
**Frida — hook native function:**
|
|
```javascript
|
|
// Find exported function
|
|
var encryptFunc = Module.findExportByName('libnative.so', 'Java_com_target_encrypt');
|
|
Interceptor.attach(encryptFunc, {
|
|
onEnter: function(args) {
|
|
// args[0] = JNIEnv*, args[1] = jobject, args[2] = jstring
|
|
var input = Java.vm.getEnv().getStringUtfChars(args[2], null).readCString();
|
|
console.log('encrypt input:', input);
|
|
},
|
|
onLeave: function(retval) {
|
|
var result = Java.vm.getEnv().getStringUtfChars(retval, null).readCString();
|
|
console.log('encrypt output:', result);
|
|
}
|
|
});
|
|
```
|
|
|
|
### 6. Keychain/Keystore Extraction
|
|
|
|
**Android KeyStore:**
|
|
```bash
|
|
# Requires root
|
|
adb root
|
|
adb shell
|
|
su
|
|
|
|
# KeyStore files
|
|
ls /data/misc/keystore/
|
|
ls /data/system/locksettings/
|
|
|
|
# Shared preferences (often contain tokens)
|
|
ls /data/data/com.target.app/shared_prefs/
|
|
cat /data/data/com.target.app/shared_prefs/*.xml
|
|
|
|
# SQLite databases
|
|
ls /data/data/com.target.app/databases/
|
|
sqlite3 /data/data/com.target.app/databases/*.db ".tables"
|
|
```
|
|
|
|
**iOS Keychain:**
|
|
```bash
|
|
# Requires jailbreak
|
|
# Keychain-Dumper
|
|
./keychain_dumper -a # all entries
|
|
./keychain_dumper -g # generic passwords
|
|
./keychain_dumper -i # internet passwords
|
|
|
|
# Or with Frida
|
|
frida -U SpringBoard -l keychain_dump.js
|
|
```
|
|
|
|
### 7. Framework-Specific Analysis
|
|
|
|
**React Native:**
|
|
```bash
|
|
# JS bundle extraction
|
|
unzip app.apk 'assets/index.android.bundle'
|
|
# Deobfuscate
|
|
# Look for fetch/axios calls in bundle
|
|
|
|
# Native modules
|
|
grep -r 'ReactMethod' android/
|
|
```
|
|
|
|
**Flutter:**
|
|
```bash
|
|
# Flutter apps have libapp.so (AOT compiled)
|
|
# Extract and analyze with Ghidra
|
|
# Flutter symbols are preserved in debug builds
|
|
unzip app.apk 'lib/*/libapp.so'
|
|
|
|
# For JIT builds, look at kernel_blob.bin
|
|
unzip app.apk 'assets/flutter_assets/kernel_blob.bin'
|
|
```
|
|
|
|
**Unity:**
|
|
```bash
|
|
# Extract assets
|
|
unzip app.apk 'assets/bin/Data/*'
|
|
|
|
# Decompile with Il2CppDumper
|
|
# Dump IL2CPP metadata
|
|
Il2CppDumper.exe assets/bin/Data/Managed/Metadata/global-metadata.dat \
|
|
lib/arm64-v8a/libil2cpp.so output/
|
|
|
|
# Results: script.json (method names), dump.cs (C# stubs)
|
|
```
|
|
|
|
## Implementation Standards
|
|
|
|
- All mobile RE produces working modifications or analysis
|
|
- Provide both static and dynamic analysis approaches
|
|
- Include Frida scripts for common bypasses
|
|
- Document app architecture and data flow
|
|
- No partial analysis — complete or nothing
|
|
|
|
## Output Format
|
|
|
|
For mobile RE tasks:
|
|
1. **App Identification** — platform, framework, version, protections
|
|
2. **Static Analysis** — decompiled code, strings, API endpoints, crypto
|
|
3. **Dynamic Analysis** — traffic, behavior, Frida hooks
|
|
4. **Security Mechanisms** — pinning, root detection, obfuscation
|
|
5. **Bypass Methods** — working patches, Frida scripts, modified APKs
|
|
6. **Data Extraction** — stored credentials, tokens, keys
|
|
|
|
Всё, брат.
|
|
|
|
|
|
## Related
|
|
- `skill android-forensics` — форензика
|
|
- `skill reverse-engineering-binary` — native libs
|
|
- `skill web-exploitation` — API реверс
|