Cross-Platform Framework Testing
Cross-platform frameworks like Flutter, React Native, and Xamarin present unique challenges for security testing due to their non-native runtimes and bundled code.
Framework Detection
Flutter
- •
libflutter.soin APK - •
Flutter.frameworkin IPA - •
kernel_blob.binfile - • Dart snapshots
React Native
- •
index.android.bundle - •
main.jsbundle(iOS) - •
libreactnativejni.so - •
assets/JS files
Xamarin
- •
libmonodroid.so - •
*.dllassemblies - •
Xamarin.*.dllfiles - •
assemblies/folder
# Detect framework from APK
apktool d target.apk -o decompiled
# Flutter detection
ls decompiled/lib/*/libflutter.so
ls decompiled/assets/flutter_assets/
# React Native detection
ls decompiled/assets/index.android.bundle
ls decompiled/lib/*/libreactnativejni.so
# Xamarin detection
ls decompiled/assemblies/*.dll
ls decompiled/lib/*/libmonodroid.soFlutter Security Testing
Flutter Challenge
libapp.so (Android) or the app binary (iOS).
SSL Pinning Bypass
Flutter uses its own HTTP client that doesn't respect system proxy settings by default:
# Method 1: Patch libflutter.so to disable SSL verification
# Download reFlutter
pip install reflutter
# Patch APK
reflutter target.apk
# Install patched APK
adb install target-reflutter.apk
# Configure proxy (reFlutter adds proxy support)
# App will now route through your proxyFrida Flutter Hooks
// Hook Flutter's HTTP client
Java.perform(function() {
// Flutter uses BoringSSL - hook at native level
var sslVerify = Module.findExportByName('libflutter.so', 'ssl_verify_peer_cert');
if (sslVerify) {
Interceptor.attach(sslVerify, {
onLeave: function(retval) {
console.log('[+] SSL verify bypassed');
retval.replace(0);
}
});
}
// Alternative: Hook ssl_crypto_x509_session_verify_cert_chain
var verifyCert = Module.findExportByName('libflutter.so', 'ssl_crypto_x509_session_verify_cert_chain');
if (verifyCert) {
Interceptor.attach(verifyCert, {
onLeave: function(retval) {
retval.replace(1);
}
});
}
});Extracting Dart Code
# Extract Flutter snapshot for analysis
# Clone Doldrums (Dart snapshot analyzer)
git clone https://github.com/nicr0nd/Doldrums.git
cd Doldrums
# Extract snapshot from APK
unzip target.apk -d apk_extracted
cp apk_extracted/lib/arm64-v8a/libapp.so .
# Use Doldrums to extract Dart info
python3 doldrums.py libapp.so
# Alternative: Use darter for snapshot analysis
pip install darter
darter libapp.so --output dart_snapshot.jsonReact Native Security Testing
Extracting JavaScript Bundle
# Extract APK
apktool d target.apk -o decompiled
# Find JS bundle
cat decompiled/assets/index.android.bundle
# If bundle is minified, beautify it
npm install -g js-beautify
js-beautify index.android.bundle > bundle_pretty.js
# Search for sensitive data
grep -i "api_key|password|secret|token" bundle_pretty.js
grep -i "https://" bundle_pretty.js # Find API endpointsHermes Bytecode Extraction
Modern React Native apps often use Hermes engine with bytecode:
# Check if using Hermes (look for HBC header)
xxd decompiled/assets/index.android.bundle | head
# If starts with "c6 1f bc 03" it's Hermes bytecode
# Decompile Hermes bytecode
# Install hermes-dec
npm install -g hermes-dec
# Decompile
hermes-dec index.android.bundle -o decompiled_js/
# Alternative: hbctool
pip install hbctool
hbctool disasm index.android.bundle output.hasmReact Native Frida Hooks
// Hook React Native networking
Java.perform(function() {
// Hook OkHttp (React Native uses it on Android)
var OkHttpClient = Java.use('okhttp3.OkHttpClient$Builder');
OkHttpClient.build.implementation = function() {
console.log('[+] OkHttpClient.build() called');
return this.build();
};
// Hook AsyncStorage
var AsyncStorage = Java.use('com.facebook.react.modules.storage.AsyncStorageModule');
AsyncStorage.multiGet.implementation = function(keys, callback) {
console.log('[AsyncStorage] Getting keys: ' + keys);
return this.multiGet(keys, callback);
};
// Intercept JS bridge calls
var ReactBridge = Java.use('com.facebook.react.bridge.CatalystInstanceImpl');
ReactBridge.jniCallJSFunction.implementation = function(module, method, args) {
console.log('[RN Bridge] ' + module + '.' + method + '(' + args + ')');
return this.jniCallJSFunction(module, method, args);
};
});SSL Pinning Bypass
// React Native typically uses native networking
// Bypass with standard OkHttp hooks (Android)
Java.perform(function() {
var CertificatePinner = Java.use('okhttp3.CertificatePinner');
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(hostname, certs) {
console.log('[+] RN CertificatePinner bypassed for: ' + hostname);
return;
};
});
// For iOS, hook AFNetworking or NSURLSession
if (ObjC.available) {
var AFSecurityPolicy = ObjC.classes.AFSecurityPolicy;
if (AFSecurityPolicy) {
Interceptor.attach(AFSecurityPolicy['- setSSLPinningMode:'].implementation, {
onEnter: function(args) {
args[2] = ptr(0); // AFSSLPinningModeNone
}
});
}
}Xamarin Security Testing
Decompiling .NET Assemblies
# Extract assemblies from APK
apktool d target.apk -o decompiled
ls decompiled/assemblies/
# Decompile with dnSpy (Windows) or ILSpy
# For Linux/Mac, use:
pip install dnfile
# Or use avalonia-ilspy
# Using ILSpy CLI
ilspycmd decompiled/assemblies/App.dll > decompiled_code.cs
# Search for sensitive data
strings decompiled/assemblies/*.dll | grep -i "password|secret|api"Xamarin Frida Hooks
// Hook Xamarin/Mono runtime
Java.perform(function() {
// Find Mono methods
var monoClasses = [];
Java.enumerateLoadedClasses({
onMatch: function(className) {
if (className.includes('mono') || className.includes('Xamarin')) {
monoClasses.push(className);
}
},
onComplete: function() {
console.log('Found Mono classes: ' + monoClasses.length);
}
});
// Hook HTTP client
try {
var HttpClient = Java.use('System.Net.Http.HttpClient');
console.log('[+] Found HttpClient');
} catch(e) {
// Try alternative location
var WebRequest = Java.use('System.Net.WebRequest');
WebRequest.Create.overload('java.lang.String').implementation = function(url) {
console.log('[WebRequest] URL: ' + url);
return this.Create(url);
};
}
});Common Cross-Platform Vulnerabilities
| Vulnerability | Impact | Where to Look |
|---|---|---|
| Hardcoded Secrets | Critical | JS bundles, Dart snapshots, .NET assemblies |
| Exposed API Endpoints | High | Decompiled source code |
| Insecure WebView | High | In-app browsers, OAuth flows |
| Client-Side Logic | Medium | Business logic in JS/Dart |
| Debug Mode Enabled | Medium | Verbose logging, debug menus |
| Source Maps Included | Medium | assets/*.map files |
Recommended Tools
reFlutter
FlutterFramework for Flutter reverse engineering. Patches libflutter.so for SSL bypass and proxy support.
Installation
pip install reflutterhermes-dec
React NativeDecompiler for React Native Hermes bytecode bundles.
Installation
npm install -g hermes-decILSpy
XamarinOpen-source .NET assembly browser and decompiler for Xamarin apps.
Installation
# Download from releasesBlutter
FlutterFlutter/Dart reverse engineering toolkit. Extracts Dart code from snapshots.
Installation
git clone https://github.com/nicr0nd/blutterTesting Checklist
- ☐ Identify cross-platform framework used
- ☐ Extract and decompile bundled code
- ☐ Search for hardcoded credentials/API keys
- ☐ Map API endpoints from source
- ☐ Bypass SSL pinning for traffic interception
- ☐ Check for debug/development modes
- ☐ Test WebView security if present
- ☐ Verify client-side validation isn't sole control
- ☐ Look for source maps or debug symbols
Framework-Specific Proxy Issues