rtexit-method 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +55 -55
- package/packaged-assets/.agents/skills/rt-android-intent-exploitation/SKILL.md +251 -0
- package/packaged-assets/.agents/skills/rt-apk-repackaging/SKILL.md +270 -0
- package/packaged-assets/.agents/skills/rt-cross-platform-mobile/SKILL.md +290 -0
- package/packaged-assets/.agents/skills/rt-frida-advanced/SKILL.md +355 -0
- package/packaged-assets/.agents/skills/rt-mobile-malware-c2/SKILL.md +265 -0
- package/packaged-assets/.agents/skills/rt-mobile-ssl-pinning/SKILL.md +338 -0
- package/packaged-assets/.agents/skills/rt-mobile-static-deep/SKILL.md +262 -0
- package/tools/installer/commands/install.js +4 -2
- package/tools/installer/lib/asset-manifest.js +6 -1
- package/tools/installer/lib/copy-assets.js +8 -8
- package/tools/installer/lib/profiles.js +250 -0
- package/tools/installer/lib/prompts.js +18 -1
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-cross-platform-mobile
|
|
3
|
+
description: "Cross-platform mobile app testing — React Native (JS bundle extraction, hermes bytecode), Flutter (libflutter.so reverse engineering, reFlutter), Xamarin (DLL extraction, IL2CPP), Ionic/Cordova (WebView injection), Unity mobile games. Each framework has unique reverse engineering and bypass techniques completely different from native Android/iOS."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
> 🐳 **Docker Environment (Recommended):** `docker exec -it rtexit-kali bash`
|
|
7
|
+
|
|
8
|
+
# rt-cross-platform-mobile — React Native, Flutter, Xamarin, Cordova
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Cross-platform frameworks compile differently than native apps — standard Android/iOS testing approaches often fail. Each framework requires specific tools and techniques.
|
|
13
|
+
|
|
14
|
+
**Identify framework:**
|
|
15
|
+
```bash
|
|
16
|
+
docker exec rtexit-kali bash -c "
|
|
17
|
+
unzip -l target.apk | grep -iE 'flutter|hermes|xamarin|cordova|react|unity'
|
|
18
|
+
# hermes.bytecode → React Native (Hermes engine)
|
|
19
|
+
# libflutter.so → Flutter
|
|
20
|
+
# assemblies/*.dll → Xamarin
|
|
21
|
+
# www/index.html → Cordova/Ionic
|
|
22
|
+
# libunity.so → Unity
|
|
23
|
+
"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## React Native
|
|
29
|
+
|
|
30
|
+
### Detect & Extract JS Bundle
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
docker exec rtexit-kali bash -c "
|
|
34
|
+
# Unzip APK
|
|
35
|
+
unzip target.apk -d /tmp/target_apk
|
|
36
|
+
|
|
37
|
+
# Find JS bundle
|
|
38
|
+
find /tmp/target_apk -name '*.bundle' -o -name '*.js' | head -20
|
|
39
|
+
# Common paths:
|
|
40
|
+
# assets/index.android.bundle
|
|
41
|
+
# assets/App.bundle
|
|
42
|
+
# res/raw/*.bundle
|
|
43
|
+
|
|
44
|
+
# Check if Hermes bytecode (compiled) or plain JS
|
|
45
|
+
file /tmp/target_apk/assets/index.android.bundle
|
|
46
|
+
# 'Hermes bytecode' = compiled
|
|
47
|
+
# 'ASCII text' or 'data' = plain JS (just read it!)
|
|
48
|
+
"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Plain JS Bundle — Read Directly
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
docker exec rtexit-kali bash -c "
|
|
55
|
+
# Plain JS bundle = goldmine of secrets, API endpoints, logic
|
|
56
|
+
cat /tmp/target_apk/assets/index.android.bundle | \
|
|
57
|
+
python3 -c \"import sys; import jsbeautifier; print(jsbeautifier.beautify(sys.stdin.read()))\" > /tmp/bundle_pretty.js
|
|
58
|
+
|
|
59
|
+
# Hunt secrets
|
|
60
|
+
grep -iE 'api_key|apikey|secret|password|token|endpoint|https?://' /tmp/bundle_pretty.js | sort -u | head -50
|
|
61
|
+
|
|
62
|
+
# Find all hardcoded URLs
|
|
63
|
+
grep -oE 'https?://[^\"]+' /tmp/bundle_pretty.js | sort -u
|
|
64
|
+
"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Hermes Bytecode — Decompile
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
docker exec rtexit-kali bash -c "
|
|
71
|
+
# Install hermes-dec
|
|
72
|
+
pip3 install hermes-dec
|
|
73
|
+
|
|
74
|
+
# Decompile Hermes bytecode to JS
|
|
75
|
+
hermes-dec /tmp/target_apk/assets/index.android.bundle > /tmp/decompiled.js
|
|
76
|
+
|
|
77
|
+
# Alternative: hbctool
|
|
78
|
+
pip3 install hbctool
|
|
79
|
+
hbctool disasm /tmp/target_apk/assets/index.android.bundle /tmp/hbc_out/
|
|
80
|
+
cat /tmp/hbc_out/instruction.hasm | grep -i 'secret\|key\|token'
|
|
81
|
+
"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### React Native SSL Pinning Bypass
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
// rn-ssl-bypass.js
|
|
88
|
+
Java.perform(() => {
|
|
89
|
+
// OkHttp (RN Android uses this)
|
|
90
|
+
try {
|
|
91
|
+
const CertPinner = Java.use('okhttp3.CertificatePinner');
|
|
92
|
+
CertPinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {
|
|
93
|
+
console.log('[*] RN OkHttp CertificatePinner bypassed');
|
|
94
|
+
};
|
|
95
|
+
} catch(e) {}
|
|
96
|
+
|
|
97
|
+
// react-native-ssl-pinning package bypass
|
|
98
|
+
try {
|
|
99
|
+
const OkHttpClientProvider = Java.use('com.facebook.react.modules.network.OkHttpClientProvider');
|
|
100
|
+
OkHttpClientProvider.createClientBuilder.implementation = function() {
|
|
101
|
+
const b = this.createClientBuilder();
|
|
102
|
+
const emptyPinner = Java.use('okhttp3.CertificatePinner$Builder').$new().build();
|
|
103
|
+
b.certificatePinner(emptyPinner);
|
|
104
|
+
return b;
|
|
105
|
+
};
|
|
106
|
+
} catch(e) {}
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Flutter
|
|
113
|
+
|
|
114
|
+
### Identify Flutter Version
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
docker exec rtexit-kali bash -c "
|
|
118
|
+
adb pull \$(adb shell pm path com.target.app | cut -d: -f2 | tr -d '\r') /tmp/target.apk
|
|
119
|
+
unzip /tmp/target.apk -d /tmp/flutter_apk
|
|
120
|
+
strings /tmp/flutter_apk/lib/arm64-v8a/libflutter.so | grep -E '^[0-9]+\.[0-9]+\.[0-9]'
|
|
121
|
+
# Also check:
|
|
122
|
+
strings /tmp/flutter_apk/lib/arm64-v8a/libflutter.so | grep 'Flutter '
|
|
123
|
+
"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Extract Dart Code (flutter_assets)
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
docker exec rtexit-kali bash -c "
|
|
130
|
+
# Flutter stores compiled Dart in flutter_assets/kernel_blob.bin or snapshot_blob.bin
|
|
131
|
+
ls /tmp/flutter_apk/assets/flutter_assets/
|
|
132
|
+
|
|
133
|
+
# Use Doldrums or reFlutter to extract
|
|
134
|
+
pip3 install doldrums 2>/dev/null
|
|
135
|
+
doldrums /tmp/flutter_apk/assets/flutter_assets/kernel_blob.bin /tmp/dart_out/
|
|
136
|
+
|
|
137
|
+
# Hunt secrets in extracted Dart
|
|
138
|
+
grep -r 'apiKey\|secret\|password\|endpoint' /tmp/dart_out/
|
|
139
|
+
"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### reFlutter — Patch Flutter SSL
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
docker exec rtexit-kali bash -c "
|
|
146
|
+
# reFlutter patches libflutter.so to remove SSL pinning
|
|
147
|
+
pip3 install reFlutter
|
|
148
|
+
|
|
149
|
+
# Patch + rebuild APK
|
|
150
|
+
reFlutter target.apk
|
|
151
|
+
# Output: release.RE.apk (with patched Flutter engine)
|
|
152
|
+
|
|
153
|
+
# Sign and install
|
|
154
|
+
java -jar /opt/uber-apk-signer.jar -a release.RE.apk --out ./signed/
|
|
155
|
+
adb install signed/release.RE-aligned-debugSigned.apk
|
|
156
|
+
|
|
157
|
+
# Set up Burp proxy
|
|
158
|
+
# reFlutter redirects all traffic to 127.0.0.1:8083
|
|
159
|
+
adb reverse tcp:8083 tcp:8080
|
|
160
|
+
# Now Burp intercepts all Flutter HTTPS traffic
|
|
161
|
+
"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Frida for Flutter (Native Hook)
|
|
165
|
+
|
|
166
|
+
```javascript
|
|
167
|
+
// flutter-ssl-bypass.js — hook BoringSSL directly
|
|
168
|
+
|
|
169
|
+
setTimeout(() => {
|
|
170
|
+
const lib = Process.getModuleByName('libflutter.so');
|
|
171
|
+
if (!lib) { console.log('libflutter.so not loaded'); return; }
|
|
172
|
+
|
|
173
|
+
// Find ssl_verify_peer_cert (varies by version)
|
|
174
|
+
// Use: $ nm -D libflutter.so | grep ssl_verify
|
|
175
|
+
// Or: $ objdump -d libflutter.so | grep -A5 "ssl_verify_peer"
|
|
176
|
+
|
|
177
|
+
// Common Flutter 3.x offset (find yours with nm/objdump)
|
|
178
|
+
const exports = ['ssl_verify_peer_cert', 'ssl_crypto_x509_session_verify_cert_chain'];
|
|
179
|
+
exports.forEach(name => {
|
|
180
|
+
const addr = Module.findExportByName('libflutter.so', name);
|
|
181
|
+
if (addr) {
|
|
182
|
+
Interceptor.replace(addr, new NativeCallback(() => {
|
|
183
|
+
console.log('[*] Flutter ' + name + ' bypassed');
|
|
184
|
+
return 1;
|
|
185
|
+
}, 'int', ['pointer', 'pointer', 'int', 'pointer']));
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}, 500);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Xamarin
|
|
194
|
+
|
|
195
|
+
### Extract .NET Assemblies
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
docker exec rtexit-kali bash -c "
|
|
199
|
+
# Xamarin embeds .NET DLLs in assemblies/ directory
|
|
200
|
+
unzip target.apk 'assemblies/*' -d /tmp/xamarin_apk
|
|
201
|
+
|
|
202
|
+
# Assemblies are compressed in newer Xamarin — decompress
|
|
203
|
+
cd /tmp/xamarin_apk/assemblies/
|
|
204
|
+
# Try: LZ4 compressed
|
|
205
|
+
python3 -c \"
|
|
206
|
+
import lz4.frame, os
|
|
207
|
+
for f in os.listdir('.'):
|
|
208
|
+
if f.endswith('.dll'):
|
|
209
|
+
try:
|
|
210
|
+
with open(f, 'rb') as fin:
|
|
211
|
+
data = fin.read()
|
|
212
|
+
if data[:4] == b'XALZ': # Xamarin LZ4 header
|
|
213
|
+
decompressed = lz4.frame.decompress(data[8:])
|
|
214
|
+
with open(f + '.dec', 'wb') as fout:
|
|
215
|
+
fout.write(decompressed)
|
|
216
|
+
print('Decompressed:', f)
|
|
217
|
+
except: pass
|
|
218
|
+
\"
|
|
219
|
+
"
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
docker exec rtexit-kali bash -c "
|
|
224
|
+
# Decompile DLLs with ILSpy or dnSpy equivalent (ilspycmd)
|
|
225
|
+
dotnet tool install ilspycmd -g 2>/dev/null || true
|
|
226
|
+
~/.dotnet/tools/ilspycmd /tmp/xamarin_apk/assemblies/App.dll > /tmp/app_source.cs
|
|
227
|
+
|
|
228
|
+
# Or use monodis
|
|
229
|
+
monodis /tmp/xamarin_apk/assemblies/App.dll > /tmp/app.il
|
|
230
|
+
|
|
231
|
+
# Hunt secrets
|
|
232
|
+
grep -i 'apiKey\|secret\|password\|baseUrl\|endpoint' /tmp/app_source.cs
|
|
233
|
+
"
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Ionic / Cordova
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
docker exec rtexit-kali bash -c "
|
|
242
|
+
# Cordova is basically a WebView app — JS source in www/
|
|
243
|
+
unzip target.apk 'assets/www/*' -d /tmp/cordova_apk
|
|
244
|
+
|
|
245
|
+
# Read JS directly — no compilation
|
|
246
|
+
cat /tmp/cordova_apk/assets/www/js/app.js | head -200
|
|
247
|
+
grep -r 'apiKey\|secret\|baseUrl\|password' /tmp/cordova_apk/assets/www/ -r
|
|
248
|
+
|
|
249
|
+
# Cordova plugins are often vulnerable
|
|
250
|
+
ls /tmp/cordova_apk/assets/www/plugins/
|
|
251
|
+
|
|
252
|
+
# Intercept traffic — no special bypass needed usually
|
|
253
|
+
# Just set Burp proxy + trust cert
|
|
254
|
+
"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Unity Mobile Games
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
docker exec rtexit-kali bash -c "
|
|
263
|
+
# Unity stores game logic in libil2cpp.so (IL2CPP) or in assets (Mono)
|
|
264
|
+
unzip target.apk 'lib/arm64-v8a/libil2cpp.so' 'assets/bin/Data/*' -d /tmp/unity_apk
|
|
265
|
+
|
|
266
|
+
# Check if Mono (easier) or IL2CPP
|
|
267
|
+
ls /tmp/unity_apk/assets/bin/Data/*.assets
|
|
268
|
+
|
|
269
|
+
# Mono: extract with AssetRipper or UABE
|
|
270
|
+
# IL2CPP: use Il2CppInspector or il2cpp-analyzer
|
|
271
|
+
|
|
272
|
+
# Secrets often in GameConfig.json or hardcoded in Assembly-CSharp.dll (Mono)
|
|
273
|
+
find /tmp/unity_apk -name '*.json' | xargs grep -i 'api\|key\|token\|secret'
|
|
274
|
+
"
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Related Skills
|
|
280
|
+
- `rt-frida-advanced` — hook any of these frameworks at runtime
|
|
281
|
+
- `rt-mobile-ssl-pinning` — framework-specific pinning bypass
|
|
282
|
+
- `rt-exploit-android` — full Android methodology
|
|
283
|
+
- `rt-exploit-ios` — full iOS methodology
|
|
284
|
+
- `rt-mobile-static-deep` — MobSF + automated analysis
|
|
285
|
+
|
|
286
|
+
## References
|
|
287
|
+
- https://github.com/Impact-I/reFlutter
|
|
288
|
+
- https://github.com/nicowillis/doldrums (Dart extractor)
|
|
289
|
+
- https://github.com/nicowillis/hermes-dec
|
|
290
|
+
- https://attack.mitre.org/techniques/T1601/ — Modify System Image
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rt-frida-advanced
|
|
3
|
+
description: "Advanced Frida dynamic instrumentation for mobile and desktop — custom hook scripts, API interception, memory scanning, bypass root/jailbreak/SSL detection at runtime, Frida gadget for non-rooted devices, process injection, stalking, code tracing, heap inspection. Works on Android + iOS + Windows + Linux. The single most powerful mobile hacking tool. Docker: rtexit/kali:v3.1 has frida-tools pre-installed."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
> 🐳 **Docker Environment (Recommended):** `docker exec -it rtexit-kali bash`
|
|
7
|
+
|
|
8
|
+
# rt-frida-advanced — Dynamic Instrumentation for Mobile Hacking
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Frida is the foundation of modern mobile pentesting. It injects a JavaScript engine into any running process and lets you hook, modify, and trace ANY function at runtime — without source code, without recompilation, without root (via Gadget). This skill covers advanced usage beyond basic Objection.
|
|
13
|
+
|
|
14
|
+
**When to use:**
|
|
15
|
+
- Bypass SSL pinning in apps that survive standard Objection bypass
|
|
16
|
+
- Understand how an app communicates with its backend
|
|
17
|
+
- Bypass root/jailbreak detection to run dynamic analysis
|
|
18
|
+
- Extract hardcoded keys, decrypt traffic, hook crypto functions
|
|
19
|
+
- Trace exact function calls to find logic flaws
|
|
20
|
+
- Any app where you need runtime visibility
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Setup in Docker + Android
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Docker has frida-tools installed
|
|
28
|
+
docker exec rtexit-kali bash -c "frida --version"
|
|
29
|
+
|
|
30
|
+
# Connect ADB to device (real device or emulator)
|
|
31
|
+
# Option A: USB device passed through to Docker
|
|
32
|
+
docker exec rtexit-kali bash -c "adb devices"
|
|
33
|
+
|
|
34
|
+
# Option B: ADB over TCP (emulator on host)
|
|
35
|
+
docker exec rtexit-kali bash -c "adb connect 192.168.200.1:5555 && adb devices"
|
|
36
|
+
|
|
37
|
+
# Push frida-server to Android device
|
|
38
|
+
docker exec rtexit-kali bash -c "
|
|
39
|
+
# Get device architecture
|
|
40
|
+
adb shell getprop ro.product.cpu.abi
|
|
41
|
+
# arm64-v8a → download frida-server-<ver>-android-arm64
|
|
42
|
+
|
|
43
|
+
# Download matching frida-server
|
|
44
|
+
FRIDA_VER=\$(pip3 show frida | grep Version | awk '{print \$2}')
|
|
45
|
+
wget https://github.com/frida/frida/releases/download/\${FRIDA_VER}/frida-server-\${FRIDA_VER}-android-arm64.xz
|
|
46
|
+
unxz frida-server-\${FRIDA_VER}-android-arm64.xz
|
|
47
|
+
adb push frida-server-\${FRIDA_VER}-android-arm64 /data/local/tmp/frida-server
|
|
48
|
+
adb shell chmod 755 /data/local/tmp/frida-server
|
|
49
|
+
adb shell /data/local/tmp/frida-server &
|
|
50
|
+
"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Core: Hooking Functions
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
// hook-template.js — hook any Java method
|
|
59
|
+
|
|
60
|
+
Java.perform(() => {
|
|
61
|
+
// Hook a specific method
|
|
62
|
+
const TargetClass = Java.use('com.example.app.CryptoUtils');
|
|
63
|
+
|
|
64
|
+
TargetClass.encrypt.overload('java.lang.String', 'java.lang.String').implementation = function(data, key) {
|
|
65
|
+
console.log('[*] encrypt called');
|
|
66
|
+
console.log(' data: ' + data);
|
|
67
|
+
console.log(' key: ' + key);
|
|
68
|
+
|
|
69
|
+
// Call original and capture result
|
|
70
|
+
const result = this.encrypt(data, key);
|
|
71
|
+
console.log(' result: ' + result);
|
|
72
|
+
return result;
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Run hook script
|
|
79
|
+
docker exec rtexit-kali bash -c "
|
|
80
|
+
frida -U -f com.example.app -l hook-template.js --no-pause
|
|
81
|
+
# -U = USB device
|
|
82
|
+
# -f = spawn app fresh (ensures hooks before init)
|
|
83
|
+
# --no-pause = don't stop at start
|
|
84
|
+
"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## SSL Pinning Bypass — Manual Frida Script
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
// ssl-bypass-universal.js — works when Objection fails
|
|
93
|
+
|
|
94
|
+
Java.perform(() => {
|
|
95
|
+
// Bypass OkHttp3 CertificatePinner
|
|
96
|
+
try {
|
|
97
|
+
const CertificatePinner = Java.use('okhttp3.CertificatePinner');
|
|
98
|
+
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {
|
|
99
|
+
console.log('[*] OkHttp3 CertificatePinner.check bypassed');
|
|
100
|
+
};
|
|
101
|
+
CertificatePinner.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function() {
|
|
102
|
+
console.log('[*] OkHttp3 CertificatePinner.check (cert array) bypassed');
|
|
103
|
+
};
|
|
104
|
+
} catch(e) {}
|
|
105
|
+
|
|
106
|
+
// Bypass TrustManagerImpl
|
|
107
|
+
try {
|
|
108
|
+
const TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl');
|
|
109
|
+
TrustManagerImpl.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {
|
|
110
|
+
console.log('[*] TrustManagerImpl.verifyChain bypassed for: ' + host);
|
|
111
|
+
return untrustedChain;
|
|
112
|
+
};
|
|
113
|
+
} catch(e) {}
|
|
114
|
+
|
|
115
|
+
// Bypass X509TrustManager
|
|
116
|
+
try {
|
|
117
|
+
const X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
|
|
118
|
+
const SSLContext = Java.use('javax.net.ssl.SSLContext');
|
|
119
|
+
const TrustManager = Java.registerClass({
|
|
120
|
+
name: 'com.frida.TrustManager',
|
|
121
|
+
implements: [X509TrustManager],
|
|
122
|
+
methods: {
|
|
123
|
+
checkClientTrusted: function(chain, authType) {},
|
|
124
|
+
checkServerTrusted: function(chain, authType) {},
|
|
125
|
+
getAcceptedIssuers: function() { return []; }
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
const ctx = SSLContext.getInstance('TLS');
|
|
129
|
+
ctx.init(null, [TrustManager.$new()], null);
|
|
130
|
+
SSLContext.setDefault(ctx);
|
|
131
|
+
console.log('[*] SSLContext TrustManager replaced');
|
|
132
|
+
} catch(e) {}
|
|
133
|
+
|
|
134
|
+
// Bypass Conscrypt verifyHostname
|
|
135
|
+
try {
|
|
136
|
+
const OkHostnameVerifier = Java.use('okhttp3.internal.tls.OkHostnameVerifier');
|
|
137
|
+
OkHostnameVerifier.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(host, session) {
|
|
138
|
+
return true;
|
|
139
|
+
};
|
|
140
|
+
} catch(e) {}
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
docker exec rtexit-kali bash -c "
|
|
146
|
+
frida -U -f com.target.app -l ssl-bypass-universal.js --no-pause
|
|
147
|
+
"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Root Detection Bypass
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
// root-bypass.js
|
|
156
|
+
|
|
157
|
+
Java.perform(() => {
|
|
158
|
+
// RootBeer bypass
|
|
159
|
+
try {
|
|
160
|
+
const RootBeer = Java.use('com.scottyab.rootbeer.RootBeer');
|
|
161
|
+
RootBeer.isRooted.implementation = function() {
|
|
162
|
+
console.log('[*] RootBeer.isRooted() bypassed → false');
|
|
163
|
+
return false;
|
|
164
|
+
};
|
|
165
|
+
RootBeer.isRootedWithoutBusyBoxCheck.implementation = function() { return false; };
|
|
166
|
+
} catch(e) {}
|
|
167
|
+
|
|
168
|
+
// File existence checks for su binary
|
|
169
|
+
const File = Java.use('java.io.File');
|
|
170
|
+
File.exists.implementation = function() {
|
|
171
|
+
const path = this.getAbsolutePath();
|
|
172
|
+
if (path.includes('su') || path.includes('supersu') || path.includes('magisk') || path.includes('busybox')) {
|
|
173
|
+
console.log('[*] File.exists blocked for: ' + path);
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
return this.exists();
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Runtime.exec bypass (blocks 'which su', 'su', etc.)
|
|
180
|
+
const Runtime = Java.use('java.lang.Runtime');
|
|
181
|
+
Runtime.exec.overload('java.lang.String').implementation = function(cmd) {
|
|
182
|
+
if (cmd.includes('su') || cmd.includes('which') || cmd.includes('busybox')) {
|
|
183
|
+
console.log('[*] Runtime.exec blocked: ' + cmd);
|
|
184
|
+
throw Java.use('java.io.IOException').$new('Command blocked by Frida');
|
|
185
|
+
}
|
|
186
|
+
return this.exec(cmd);
|
|
187
|
+
};
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Memory Scanning — Find Secrets at Runtime
|
|
194
|
+
|
|
195
|
+
```javascript
|
|
196
|
+
// memory-scan.js — scan process memory for keys, tokens, secrets
|
|
197
|
+
|
|
198
|
+
Process.enumerateRanges('r--').forEach(range => {
|
|
199
|
+
try {
|
|
200
|
+
Memory.scanSync(range.base, range.size, 'Bearer ').forEach(match => {
|
|
201
|
+
const token = match.address.readUtf8String(200);
|
|
202
|
+
console.log('[TOKEN] @' + match.address + ': ' + token.substring(0, 100));
|
|
203
|
+
});
|
|
204
|
+
} catch(e) {}
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Scan for specific patterns
|
|
208
|
+
const patterns = [
|
|
209
|
+
{ name: 'AWS Key', pattern: 'AKIA' },
|
|
210
|
+
{ name: 'JWT', pattern: 'eyJ' },
|
|
211
|
+
{ name: 'API Key header', pattern: 'X-Api-Key' },
|
|
212
|
+
];
|
|
213
|
+
|
|
214
|
+
Process.enumerateRanges('r--').forEach(range => {
|
|
215
|
+
patterns.forEach(p => {
|
|
216
|
+
try {
|
|
217
|
+
Memory.scanSync(range.base, range.size, p.pattern).forEach(match => {
|
|
218
|
+
console.log('[' + p.name + '] @' + match.address + ': ' + match.address.readUtf8String(100));
|
|
219
|
+
});
|
|
220
|
+
} catch(e) {}
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Stalker — Trace Every Function Call
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
// trace-calls.js — trace all calls in a specific class
|
|
231
|
+
|
|
232
|
+
Java.perform(() => {
|
|
233
|
+
const TargetClass = Java.use('com.example.app.AuthManager');
|
|
234
|
+
|
|
235
|
+
// Trace ALL methods in class
|
|
236
|
+
Object.getOwnPropertyNames(TargetClass).forEach(method => {
|
|
237
|
+
try {
|
|
238
|
+
TargetClass[method].implementation = function() {
|
|
239
|
+
console.log('[CALL] AuthManager.' + method + '(' + Array.from(arguments).join(', ') + ')');
|
|
240
|
+
const result = this[method].apply(this, arguments);
|
|
241
|
+
console.log('[RET] AuthManager.' + method + ' → ' + result);
|
|
242
|
+
return result;
|
|
243
|
+
};
|
|
244
|
+
} catch(e) {}
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Frida Gadget — Non-Rooted Devices
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
# Gadget = inject Frida as a shared library into the APK
|
|
255
|
+
# No root required!
|
|
256
|
+
|
|
257
|
+
docker exec rtexit-kali bash -c "
|
|
258
|
+
# 1. Decompile APK
|
|
259
|
+
apktool d target.apk -o target_decompiled
|
|
260
|
+
|
|
261
|
+
# 2. Download frida-gadget .so for target arch
|
|
262
|
+
wget https://github.com/frida/frida/releases/download/16.x.x/frida-gadget-16.x.x-android-arm64.so.xz
|
|
263
|
+
unxz frida-gadget-16.x.x-android-arm64.so.xz
|
|
264
|
+
mv frida-gadget-16.x.x-android-arm64.so target_decompiled/lib/arm64-v8a/libfrida-gadget.so
|
|
265
|
+
|
|
266
|
+
# 3. Inject gadget loader into smali (MainActivity.smali)
|
|
267
|
+
# Add to onCreate() before super.onCreate():
|
|
268
|
+
# invoke-static {}, Lcom/example/app/MainActivity;->loadLibrary()V
|
|
269
|
+
# Actually: add System.loadLibrary('frida-gadget') call in smali
|
|
270
|
+
|
|
271
|
+
# 4. Repackage + sign
|
|
272
|
+
apktool b target_decompiled -o target_patched.apk
|
|
273
|
+
uber-apk-signer -a target_patched.apk --out ./signed/
|
|
274
|
+
|
|
275
|
+
# 5. Install + run — app waits for Frida to attach
|
|
276
|
+
adb install signed/target_patched-aligned-debugSigned.apk
|
|
277
|
+
adb shell am start -n com.example.app/.MainActivity
|
|
278
|
+
# App pauses → attach Frida
|
|
279
|
+
frida -U Gadget -l your-script.js
|
|
280
|
+
"
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## iOS Frida
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
docker exec rtexit-kali bash -c "
|
|
289
|
+
# iOS: frida-server installed via Sileo on jailbroken device
|
|
290
|
+
# Connect via SSH tunnel
|
|
291
|
+
ssh -p 2222 root@192.168.200.50
|
|
292
|
+
|
|
293
|
+
# List processes
|
|
294
|
+
frida-ps -H 192.168.200.50
|
|
295
|
+
|
|
296
|
+
# Attach to iOS app
|
|
297
|
+
frida -H 192.168.200.50 -n 'TargetApp' -l ssl-bypass-ios.js
|
|
298
|
+
"
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
```javascript
|
|
302
|
+
// ssl-bypass-ios.js — iOS SSL pinning bypass
|
|
303
|
+
|
|
304
|
+
ObjC.schedule(ObjC.mainQueue, () => {
|
|
305
|
+
// NSURLSession bypass
|
|
306
|
+
try {
|
|
307
|
+
const NSURLSessionTask = ObjC.classes.NSURLSessionTask;
|
|
308
|
+
Interceptor.attach(NSURLSessionTask['- resume'].implementation, {
|
|
309
|
+
onEnter: function() {
|
|
310
|
+
const task = new ObjC.Object(this.context.x0);
|
|
311
|
+
console.log('[*] NSURLSession resume: ' + task.currentRequest().URL().absoluteString());
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
} catch(e) {}
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
// Bypass SecTrustEvaluate (common pinning method)
|
|
318
|
+
Interceptor.replace(Module.findExportByName('Security', 'SecTrustEvaluate'), new NativeCallback((trust, result) => {
|
|
319
|
+
console.log('[*] SecTrustEvaluate bypassed');
|
|
320
|
+
const p = Memory.alloc(4);
|
|
321
|
+
Memory.writeS32(p, 1); // kSecTrustResultProceed
|
|
322
|
+
result.writePointer(p);
|
|
323
|
+
return 0; // errSecSuccess
|
|
324
|
+
}, 'int', ['pointer', 'pointer']));
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Useful One-Liners
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
# List all loaded classes
|
|
333
|
+
docker exec rtexit-kali bash -c "frida -U -f com.target.app --eval 'Java.perform(() => { Java.enumerateLoadedClasses({ onMatch: (c) => console.log(c), onComplete: () => {} }) })' --no-pause 2>&1 | grep -i 'auth\|crypto\|pin\|cert\|ssl'"
|
|
334
|
+
|
|
335
|
+
# Watch all HTTP traffic class
|
|
336
|
+
docker exec rtexit-kali bash -c "frida -U -n com.target.app -l /opt/frida-scripts/watch-http.js"
|
|
337
|
+
|
|
338
|
+
# Dump all SharedPreferences
|
|
339
|
+
docker exec rtexit-kali bash -c "objection -g com.target.app explore --startup-command 'android sslpinning disable'"
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Related Skills
|
|
345
|
+
- `rt-exploit-android` — Android testing methodology
|
|
346
|
+
- `rt-exploit-ios` — iOS testing methodology
|
|
347
|
+
- `rt-mobile-ssl-pinning` — deep SSL pinning bypass techniques
|
|
348
|
+
- `rt-apk-repackaging` — inject Frida gadget into APK
|
|
349
|
+
- `rt-cross-platform-mobile` — Flutter/React Native specific bypasses
|
|
350
|
+
|
|
351
|
+
## References
|
|
352
|
+
- https://frida.re/docs/javascript-api/
|
|
353
|
+
- https://github.com/interference-security/frida-scripts
|
|
354
|
+
- https://codeshare.frida.re (community scripts)
|
|
355
|
+
- https://attack.mitre.org/techniques/T1625/ — Hooking
|