reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -0,0 +1,365 @@
# Android 高级逆向参考
> 覆盖 Native SO 分析、Frida 高级用法、SSL Pinning 绕过、Root 检测对抗、加固脱壳、Flutter/React Native 逆向。
---
## Native SO 逆向
### 分析流程
```text
1. 从 APK 中提取 .so 文件
unzip app.apk lib/arm64-v8a/*.so -d extracted/
2. 确认架构和基本信息
file libxxx.so
rabin2 -I libxxx.so
3. 找 JNI 入口
- 搜索 JNI_OnLoad(动态注册)
- 搜索 Java_com_xxx_yyy(静态注册)
- nm -D libxxx.so | grep -i java
4. IDA/Ghidra 加载分析
- 导入 JNI 头文件(jni.h 类型)
- 标注 JNIEnv* 参数
- 找 RegisterNatives 调用(动态注册的函数表)
5. 定位关键逻辑
- 从 Java 层 native 方法名追踪
- 从字符串(密钥、URL、错误信息)交叉引用
- 从 crypto 库函数(AES/MD5/SHA)调用追踪
```
### JNI 函数注册
```c
// 静态注册:函数名 = Java_包名_类名_方法名
JNIEXPORT jstring JNICALL Java_com_example_app_Security_getSign(
JNIEnv *env, jobject thiz, jstring input) { ... }
// 动态注册:在 JNI_OnLoad 中调用 RegisterNatives
static JNINativeMethod methods[] = {
{"getSign", "(Ljava/lang/String;)Ljava/lang/String;", (void*)native_getSign},
};
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;
vm->GetEnv((void**)&env, JNI_VERSION_1_6);
jclass clazz = env->FindClass("com/example/app/Security");
env->RegisterNatives(clazz, methods, sizeof(methods)/sizeof(methods[0]));
return JNI_VERSION_1_6;
}
```
### IDA 中分析 JNI 的技巧
```text
1. 导入 JNI 类型库
File → Load File → Parse C Header → jni.h
2. 标注第一个参数为 JNIEnv*
右键参数 → Set type → JNIEnv*
这样 env->FindClass / env->GetMethodID 等调用会自动识别
3. 找 RegisterNatives
搜索对 JNIEnv vtable offset 0x35C (ARM64) 的调用
→ 第三个参数是 JNINativeMethod 数组
→ 从数组中提取所有 native 函数地址
```
---
## Frida 高级用法
### Hook Native 函数
```javascript
// Hook libc 函数
Interceptor.attach(Module.findExportByName("libc.so", "open"), {
onEnter: function(args) {
this.path = args[0].readUtf8String();
console.log("[open] " + this.path);
},
onLeave: function(retval) {
if (this.path.includes("su") || this.path.includes("magisk")) {
console.log("[open] Blocked root check: " + this.path);
retval.replace(-1); // 返回失败
}
}
});
// Hook 自定义 SO 中的函数
var base = Module.findBaseAddress("libsecurity.so");
var targetFunc = base.add(0x1234); // 偏移地址
Interceptor.attach(targetFunc, {
onEnter: function(args) {
console.log("arg0: " + args[0].readUtf8String());
},
onLeave: function(retval) {
console.log("return: " + retval.readUtf8String());
}
});
```
### Hook Java 方法
```javascript
Java.perform(function() {
// Hook 实例方法
var Security = Java.use("com.example.app.Security");
Security.getSign.implementation = function(input) {
console.log("[getSign] input: " + input);
var result = this.getSign(input); // 调用原方法
console.log("[getSign] output: " + result);
return result;
};
// Hook 构造函数
Security.$init.overload('java.lang.String').implementation = function(key) {
console.log("[Security.<init>] key: " + key);
this.$init(key);
};
// Hook 重载方法
Security.encrypt.overload('java.lang.String', 'int').implementation = function(data, mode) {
console.log("[encrypt] data=" + data + " mode=" + mode);
return this.encrypt(data, mode);
};
});
```
### 内存搜索与修改
```javascript
// 搜索内存中的字符串
Process.enumerateModules().forEach(function(module) {
if (module.name === "libtarget.so") {
Memory.scan(module.base, module.size, "48 65 6C 6C 6F", { // "Hello"
onMatch: function(address, size) {
console.log("Found at: " + address);
}
});
}
});
// 修改内存(patch 指令)
var addr = Module.findBaseAddress("libsecurity.so").add(0x5678);
Memory.patchCode(addr, 4, function(code) {
var writer = new Arm64Writer(code, {pc: addr});
writer.putNop(); // 替换为 NOP
writer.flush();
});
```
---
## SSL Pinning 绕过
### 通用方案(推荐)
```javascript
// Frida 通用 SSL Pinning 绕过
// 来源: https://github.com/0xCD4/SSL-bypass
Java.perform(function() {
// 1. TrustManager 绕过
var TrustManager = Java.registerClass({
name: 'com.custom.TrustManager',
implements: [Java.use('javax.net.ssl.X509TrustManager')],
methods: {
checkClientTrusted: function(chain, authType) {},
checkServerTrusted: function(chain, authType) {},
getAcceptedIssuers: function() { return []; }
}
});
// 2. SSLContext 替换
var SSLContext = Java.use('javax.net.ssl.SSLContext');
var sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, [TrustManager.$new()], null);
// 3. OkHttp CertificatePinner 绕过
try {
var CertificatePinner = Java.use('okhttp3.CertificatePinner');
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {};
} catch(e) {}
});
```
### 各框架绕过
| 框架 | 绕过方法 |
|------|---------|
| OkHttp3 | Hook `CertificatePinner.check` 返回空 |
| Retrofit | 同 OkHttp(底层用 OkHttp) |
| Volley | Hook `HurlStack` 的 SSL 工厂 |
| Flutter | Hook `dart:io` 的 `SecurityContext`(需要特殊脚本) |
| React Native | Hook `OkHttpClientProvider` |
| WebView | Hook `WebViewClient.onReceivedSslError` |
### Flutter 专项
```javascript
// Flutter SSL Pinning 绕过(需要找到 ssl_verify_peer_cert 函数)
var flutter_lib = Module.findBaseAddress("libflutter.so");
// 搜索 ssl_verify_peer_cert 的特征码
var pattern = "FF 03 05 D1 FD 7B 0F A9"; // ARM64 特征
Memory.scan(flutter_lib, Module.findModuleByName("libflutter.so").size, pattern, {
onMatch: function(address) {
Interceptor.replace(address, new NativeCallback(function() {
return 0; // 返回成功
}, 'int', []));
}
});
```
---
## Root 检测绕过
### 常见检测方式
| 检测方式 | 绕过方法 |
|---------|---------|
| 检查 `/system/app/Superuser.apk` | Hook `File.exists()` 返回 false |
| 检查 `su` 命令 | Hook `Runtime.exec()` 拦截 su 调用 |
| 检查 `/proc/self/mounts` | Hook 文件读取,过滤 magisk 相关 |
| SafetyNet/Play Integrity | Magisk Hide / Zygisk + Shamiko |
| 检查 Magisk 包名 | 随机化 Magisk 包名 |
| 检查 `/data/adb/` | Hook `opendir`/`access` |
### Frida 通用 Root 绕过
```javascript
Java.perform(function() {
// Hook File.exists
var File = Java.use("java.io.File");
File.exists.implementation = function() {
var path = this.getAbsolutePath();
var blacklist = ["su", "Superuser", "magisk", "busybox", "xposed"];
for (var i = 0; i < blacklist.length; i++) {
if (path.toLowerCase().includes(blacklist[i])) {
return false;
}
}
return this.exists();
};
// Hook System.getProperty
var System = Java.use("java.lang.System");
System.getProperty.overload('java.lang.String').implementation = function(key) {
if (key === "ro.debuggable" || key === "ro.secure") {
return "1";
}
return this.getProperty(key);
};
});
```
---
## 加固/壳识别与脱壳
### 常见加固厂商
| 加固 | 识别特征 | 脱壳方式 |
|------|---------|---------|
| 360 加固 | `libjiagu.so`、`com.stub.StubApp` | FART / Frida dump dex |
| 腾讯乐固 | `libshell*.so`、`com.tencent.StubShell` | FART / BlackDex |
| 梆梆加固 | `libDexHelper.so`、`com.secneo.apkwrapper` | FART |
| 爱加密 | `libexec.so`、`s.h.e.l.l` | Frida dump |
| 网易易盾 | `libnesec.so` | Frida dump |
| 娜迦 | `libnaga.so` | Frida dump |
### 通用脱壳方法
```text
方法 1: FART(ART 环境脱壳)
- 刷入 FART ROM 或使用 Frida 版 FART
- 自动 dump 所有 ClassLoader 加载的 dex
方法 2: Frida DEX Dump
- frida -U -f com.target.app -l dex_dump.js
- 在 DexFile::OpenMemory 处 hook,dump 内存中的 dex
方法 3: BlackDex
- 免 root 脱壳工具
- 直接安装 BlackDex APK,选择目标应用脱壳
方法 4: 手动 dump
- 用 Frida 枚举所有 ClassLoader
- 找到应用的 ClassLoader → 获取 DexFile 对象
- 读取 dex 内存区域并保存
```
### Frida DEX Dump 脚本
```javascript
Java.perform(function() {
Java.enumerateClassLoaders({
onMatch: function(loader) {
try {
var dexFiles = loader.getDexFileList();
console.log("ClassLoader: " + loader);
console.log(" DEX files: " + dexFiles);
} catch(e) {}
},
onComplete: function() {}
});
});
```
---
## React Native / Flutter 逆向
### React Native
```text
1. 解压 APK → assets/index.android.bundle(JS 代码)
2. 格式化 JS → 搜索 API 地址、密钥、签名逻辑
3. 如果有 Hermes 字节码(.hbc 文件)→ 用 hermes-dec 反编译
4. Hook: 用 Frida hook Java 层的 ReactBridge
```
### Flutter
```text
1. Flutter 代码编译为 libapp.so(Dart AOT)
2. 无法直接反编译为 Dart 源码
3. 分析方法:
- reFlutter 工具:patch libflutter.so 获取 snapshot
- Doldrums:解析 Dart snapshot 恢复类/函数信息
- Frida hook libflutter.so 中的关键函数
4. 网络分析:Flutter 不走系统代理,需要特殊处理 SSL
```
---
## 工具速查
| 工具 | 用途 | 安装 |
|------|------|------|
| jadx | Java 反编译 | 已在 bootstrap 中 |
| apktool | 解包/重打包 | 已在 bootstrap 中 |
| Frida | 动态 Hook | `pip install frida-tools` |
| Objection | Frida 封装(更易用) | `pip install objection` |
| MobSF | 自动化移动安全分析 | Docker 部署 |
| BlackDex | 免 root 脱壳 | APK 安装 |
| FART | ART 脱壳 | 刷入 ROM 或 Frida 版 |
| hermes-dec | Hermes 字节码反编译 | npm 安装 |
| reFlutter | Flutter 逆向辅助 | pip 安装 |
| Magisk + Shamiko | Root 隐藏 | 刷入 |
---
## 参考资源
| 资源 | 说明 | 链接 |
|------|------|------|
| OWASP MASTG | 移动安全测试指南 | https://mas.owasp.org/ |
| FridaBypassKit | 通用绕过框架 | https://github.com/okankurtuluss/FridaBypassKit |
| SSL-bypass | 通用 SSL Pinning 绕过 | https://github.com/0xCD4/SSL-bypass |
| awesome-frida | Frida 资源合集 | https://github.com/dweinstein/awesome-frida |
| Android Security Awesome | Android 安全资源 | https://github.com/ashishb/android-security-awesome |

View File

@@ -0,0 +1,230 @@
# APK 安全测试速查
> 基于 OWASP MASTG(Mobile Application Security Testing Guide)整理。
> 覆盖静态分析、动态分析、网络通信、数据存储、认证授权、代码保护六大维度。
---
## 静态分析检查清单
### Manifest 审计
```text
□ android:debuggable="true" → 可调试(生产环境不应出现)
□ android:allowBackup="true" → 数据可备份提取
□ android:exported="true" 的组件 → 暴露的 Activity/Service/Receiver/Provider
□ 自定义权限 protectionLevel → 是否为 normal(应为 signature)
□ intent-filter 中的 scheme → 自定义 deeplink 是否可被劫持
□ android:usesCleartextTraffic="true" → 允许明文 HTTP
□ minSdkVersion 过低 → 可能缺少安全特性
```
### 代码审计关键点
```text
□ 硬编码密钥/Token(搜索 "key"、"secret"、"password"、"api_key")
□ 不安全的随机数(java.util.Random 而非 SecureRandom)
□ 不安全的加密(ECB 模式、DES、MD5 用于密码)
□ WebView 配置(setJavaScriptEnabled + addJavascriptInterface = RCE 风险)
□ SQL 注入(rawQuery 拼接用户输入)
□ 路径遍历(ContentProvider 的 openFile 未校验路径)
□ 日志泄露(Log.d/Log.i 输出敏感信息)
□ 剪贴板泄露(ClipboardManager 存储敏感数据)
□ 隐式 Intent 泄露(sendBroadcast 未指定包名)
```
### 第三方库审计
```text
□ 过时的 OkHttp/Retrofit 版本(已知漏洞)
□ 过时的 WebView 内核
□ 含已知漏洞的 SDK(检查 CVE)
□ 广告 SDK 数据收集范围
□ 推送 SDK 配置(是否泄露 token)
```
---
## 动态分析检查清单
### Frida Hook 优先目标
| 目标 | Hook 点 | 目的 |
|------|---------|------|
| 登录认证 | `LoginActivity.login()` | 观察凭证处理 |
| 签名生成 | `*Sign*`、`*sign*`、`*encrypt*` | 还原签名算法 |
| SSL Pinning | `CertificatePinner.check` | 绕过抓包 |
| Root 检测 | `*root*`、`*su*`、`*magisk*` | 绕过检测 |
| 加密操作 | `javax.crypto.Cipher` | 提取密钥/IV |
| Token 存储 | `SharedPreferences.getString` | 观察 token 读写 |
| 网络请求 | `OkHttpClient.newCall` | 观察请求构造 |
### 常用 Frida 一行命令
```bash
# 追踪所有加密操作
frida-trace -U -f com.target.app -j '*Cipher*!*'
# 追踪所有 HTTP 请求
frida-trace -U -f com.target.app -j '*OkHttp*!*'
# 追踪 SharedPreferences 读写
frida-trace -U -f com.target.app -j '*SharedPreferences*!*'
# 追踪所有 native 函数调用
frida-trace -U -f com.target.app -i 'Java_*'
```
### Objection 快速命令
```bash
# 连接
objection -g com.target.app explore
# 常用命令
android hooking list activities
android hooking list services
android sslpinning disable
android root disable
android clipboard monitor
env # 查看应用目录
sqlite connect <db_path> # 连接数据库
```
---
## 网络通信安全
### 抓包配置
```text
方法 1: 系统代理 + Burp/mitmproxy
- 设置 WiFi 代理 → Burp 监听地址
- 安装 CA 证书到设备
- Android 7+ 需要 network_security_config 或 Frida 绕过
方法 2: VPN 模式(推荐)
- 使用 HttpCanary / Packet Capture
- 不需要 root,不需要配置代理
- 但无法解密 SSL Pinning 的流量
方法 3: Frida + r2frida
- 直接在进程内拦截网络调用
- 不受代理/VPN 限制
```
### 检查项
```text
□ 是否使用 HTTPS(所有 API 调用)
□ 是否有 SSL Pinning(证书绑定)
□ 证书验证是否正确(不接受自签名)
□ 是否有证书透明度(CT)检查
□ API 密钥是否在请求中明文传输
□ Token 是否有过期机制
□ 是否有请求签名防篡改
□ 是否有重放攻击防护(nonce/timestamp)
□ WebSocket 是否加密
□ 是否有敏感数据在 URL 参数中(会被日志记录)
```
---
## 数据存储安全
### 检查位置
| 位置 | 风险 | 检查命令 |
|------|------|---------|
| SharedPreferences | 明文存储 token/密码 | `adb shell cat /data/data/pkg/shared_prefs/*.xml` |
| SQLite 数据库 | 未加密的敏感数据 | `adb pull /data/data/pkg/databases/` |
| 外部存储 | 任何应用可读 | `adb shell ls /sdcard/Android/data/pkg/` |
| 应用日志 | 泄露调试信息 | `adb logcat \| grep pkg` |
| 备份文件 | allowBackup=true | `adb backup -f backup.ab pkg` |
| 键盘缓存 | 输入历史 | 检查 `inputType` 是否为 `textPassword` |
| 截图保护 | 敏感页面可截图 | 检查 `FLAG_SECURE` |
### 加密存储方案对比
| 方案 | 安全性 | 说明 |
|------|--------|------|
| SharedPreferences 明文 | ❌ | root 后直接读取 |
| EncryptedSharedPreferences | ✓ | AndroidX Security 库 |
| SQLCipher | ✓ | 加密 SQLite |
| Android Keystore | ✓✓ | 硬件级密钥保护 |
| 自定义 AES 加密 | ⚠️ | 取决于密钥管理 |
---
## 认证与授权
### 常见漏洞
| 漏洞 | 测试方法 |
|------|---------|
| 弱密码策略 | 尝试 123456、password 等 |
| 无锁定机制 | 暴力破解登录接口 |
| Token 不过期 | 登出后重放旧 token |
| 越权访问 | 修改请求中的 user_id |
| 短信验证码可爆破 | 4/6 位数字无频率限制 |
| OAuth 配置错误 | redirect_uri 可篡改 |
| 生物认证绕过 | Hook BiometricPrompt |
| 设备绑定绕过 | 修改 device_id |
### 测试 Payload
```bash
# 越权测试
curl -H "Authorization: Bearer USER_A_TOKEN" \
"https://api.target.com/users/USER_B_ID/profile"
# Token 重放
# 1. 正常登录获取 token
# 2. 登出
# 3. 用旧 token 请求 → 应该返回 401
# 短信验证码爆破
for code in $(seq 0000 9999); do
curl -X POST "https://api.target.com/verify" \
-d "phone=13800138000&code=$code"
done
```
---
## 代码保护评估
| 保护措施 | 检测方法 | 绕过难度 |
|---------|---------|---------|
| ProGuard 混淆 | jadx 查看类名是否为 a/b/c | 低(只是重命名) |
| 字符串加密 | 搜索解密函数,Hook 获取明文 | 中 |
| 反调试 | 尝试 attach debugger | 中(Frida 可绕过) |
| Root 检测 | 在 root 设备上运行 | 中(通用脚本绕过) |
| 模拟器检测 | 在模拟器上运行 | 低-中 |
| 完整性校验 | 修改 APK 后安装 | 中(patch 校验函数) |
| 加固/壳 | 查看入口类和 .so | 中-高(需脱壳) |
| Native 保护 | 核心逻辑在 .so | 高(需 IDA 分析) |
| VMP 虚拟化 | 代码被虚拟化执行 | 极高 |
---
## 快速测试流程(30 分钟)
```text
1. [5min] 解包 + Manifest 审计
apktool d app.apk
检查 debuggable/allowBackup/exported/cleartext
2. [10min] 代码快速审计
jadx -d out app.apk
搜索: password, key, secret, token, http://
3. [5min] 网络测试
配置代理 → 操作 APP → 检查是否有明文/弱加密
4. [5min] 存储检查
adb shell → 检查 shared_prefs 和 databases
5. [5min] 动态验证
Frida hook 关键函数 → 确认发现
```

View File

@@ -0,0 +1,70 @@
# Frida Bypass Kit — Android 通用安全绕过框架
> 来源:[FridaBypassKit](https://github.com/okankurtuluss/FridaBypassKit)(2025)
> 适用场景:APK 动态分析时需要绕过 root 检测、SSL pinning、模拟器检测、反调试
## 概述
FridaBypassKit 是一个集成了四大绕过能力的 Frida 脚本,无需针对特定 APP 定制,开箱即用。
## 四大绕过能力
### 1. Root 检测绕过
- Hook `File.exists()` 隐藏 su 二进制
- 拦截 `Runtime.exec()` 的 root 检查调用
- 从 PackageManager 隐藏 root 相关包(Magisk、SuperSU 等)
- 修改系统属性使设备看起来未 root
### 2. SSL Pinning 绕过
- Hook `TrustManagerImpl.verifyChain()`
- Hook `TrustManagerImpl.checkTrustedRecursive()`
- 绕过证书链验证
- 返回空证书链避免校验
- 兼容 OkHttp、Retrofit 和自定义实现
### 3. 模拟器检测绕过
- 伪造 TelephonyManager 返回值
- 返回假电话号码和运营商名称
- 修改 Build 属性
### 4. 反调试绕过
- Hook `Debug.isDebuggerConnected()`
- 阻止调试器检测
- 绕过反调试检查
## 使用方法
```bash
# 前置条件
pip install frida-tools
adb push frida-server /data/local/tmp/
adb shell chmod 755 /data/local/tmp/frida-server
adb shell su -c /data/local/tmp/frida-server &
# 注入目标 APP
frida -U -f com.example.app -l FridaBypassKit.js
```
## 其他推荐 Frida 绕过脚本
| 项目 | 特点 | 链接 |
|------|------|------|
| httptoolkit/frida-interception-and-unpinning | 直接 MitM 所有 HTTPS 流量 | [GitHub](https://github.com/httptoolkit/frida-interception-and-unpinning) |
| 0xCD4/SSL-bypass | 通用非定制 SSL 绕过 | [GitHub](https://github.com/0xCD4/SSL-bypass) |
| incogbyte/ssl-bypass gist | 绕过常见 SSL pinning 方法 | [Gist](https://gist.github.com/incogbyte/1e0e2f38b5602e72b1380f21ba04b15e) |
| Zero3141/Frida-OkHttp-Bypass | 专门针对 OkHttp CertificatePinner | [GitHub](https://github.com/Zero3141/Frida-OkHttp-Bypass) |
## 与本包的集成
在 `apk-reverse` 工作流中,当遇到以下情况时使用:
1. APP 检测到 root 拒绝运行 → 启用 Root Detection Bypass
2. 抓包时 HTTPS 请求看不到明文 → 启用 SSL Pinning Bypass
3. APP 检测到模拟器拒绝运行 → 启用 Emulator Detection Bypass
4. 附加 Frida 后 APP 崩溃 → 启用 Debug Detection Bypass
推荐组合使用:先跑完整 FridaBypassKit,再针对性调整。

View File

@@ -0,0 +1,472 @@
# Frida 实战脚本速查
> 精选自 [awesome-frida](https://github.com/dweinstein/awesome-frida)、[Frida-Mobile-Scripts](https://github.com/m0bilesecurity/Frida-Mobile-Scripts)、[frida-codeshare-scripts](https://github.com/zengfr/frida-codeshare-scripts) 等开源项目。
> 按场景分类,直接复制使用。
---
## 通用 Hook 模板
### Hook 任意 Java 方法
```javascript
Java.perform(function() {
var TargetClass = Java.use("com.target.ClassName");
// Hook 无参方法
TargetClass.methodName.implementation = function() {
console.log("[*] methodName called");
var ret = this.methodName();
console.log("[*] return: " + ret);
return ret;
};
// Hook 有参方法
TargetClass.methodName.overload('java.lang.String', 'int').implementation = function(str, num) {
console.log("[*] methodName(" + str + ", " + num + ")");
var ret = this.methodName(str, num);
console.log("[*] return: " + ret);
return ret;
};
});
```
### Hook 构造函数
```javascript
Java.perform(function() {
var TargetClass = Java.use("com.target.ClassName");
TargetClass.$init.overload('java.lang.String').implementation = function(arg) {
console.log("[*] new ClassName(" + arg + ")");
this.$init(arg);
};
});
```
### 枚举所有方法
```javascript
Java.perform(function() {
var TargetClass = Java.use("com.target.ClassName");
var methods = TargetClass.class.getDeclaredMethods();
methods.forEach(function(method) {
console.log(method.toString());
});
});
```
---
## 加密/签名 Hook
### Hook AES 加解密
```javascript
Java.perform(function() {
var Cipher = Java.use("javax.crypto.Cipher");
Cipher.doFinal.overload('[B').implementation = function(input) {
var mode = this.getOpmode ? this.getOpmode() : "?";
console.log("[Cipher.doFinal] mode=" + mode);
console.log(" input: " + bytesToHex(input));
var result = this.doFinal(input);
console.log(" output: " + bytesToHex(result));
return result;
};
// 捕获密钥
var SecretKeySpec = Java.use("javax.crypto.spec.SecretKeySpec");
SecretKeySpec.$init.overload('[B', 'java.lang.String').implementation = function(key, algo) {
console.log("[SecretKeySpec] algo=" + algo + " key=" + bytesToHex(key));
this.$init(key, algo);
};
// 捕获 IV
var IvParameterSpec = Java.use("javax.crypto.spec.IvParameterSpec");
IvParameterSpec.$init.overload('[B').implementation = function(iv) {
console.log("[IvParameterSpec] iv=" + bytesToHex(iv));
this.$init(iv);
};
});
function bytesToHex(bytes) {
var hex = [];
for (var i = 0; i < bytes.length; i++) {
hex.push(('0' + (bytes[i] & 0xFF).toString(16)).slice(-2));
}
return hex.join('');
}
```
### Hook MD5/SHA
```javascript
Java.perform(function() {
var MessageDigest = Java.use("java.security.MessageDigest");
MessageDigest.digest.overload('[B').implementation = function(input) {
console.log("[MessageDigest.digest] algo=" + this.getAlgorithm());
console.log(" input: " + bytesToHex(input));
var result = this.digest(input);
console.log(" hash: " + bytesToHex(result));
return result;
};
MessageDigest.digest.overload().implementation = function() {
console.log("[MessageDigest.digest] algo=" + this.getAlgorithm());
var result = this.digest();
console.log(" hash: " + bytesToHex(result));
return result;
};
});
```
### Hook HMAC
```javascript
Java.perform(function() {
var Mac = Java.use("javax.crypto.Mac");
Mac.doFinal.overload('[B').implementation = function(input) {
console.log("[Mac.doFinal] algo=" + this.getAlgorithm());
console.log(" input: " + bytesToHex(input));
var result = this.doFinal(input);
console.log(" mac: " + bytesToHex(result));
return result;
};
Mac.init.overload('java.security.Key').implementation = function(key) {
var keyBytes = key.getEncoded();
console.log("[Mac.init] key=" + bytesToHex(keyBytes));
this.init(key);
};
});
```
---
## 网络请求 Hook
### Hook OkHttp3 请求/响应
```javascript
Java.perform(function() {
var OkHttpClient = Java.use("okhttp3.OkHttpClient");
var Interceptor = Java.use("okhttp3.Interceptor");
// Hook newCall 获取请求 URL
var RealCall = Java.use("okhttp3.RealCall");
RealCall.execute.implementation = function() {
var request = this.request();
console.log("[OkHttp] " + request.method() + " " + request.url().toString());
var headers = request.headers();
for (var i = 0; i < headers.size(); i++) {
console.log(" " + headers.name(i) + ": " + headers.value(i));
}
var response = this.execute();
console.log("[OkHttp] Response: " + response.code());
return response;
};
});
```
### Hook URL 连接
```javascript
Java.perform(function() {
var URL = Java.use("java.net.URL");
URL.openConnection.overload().implementation = function() {
console.log("[URL] " + this.toString());
return this.openConnection();
};
});
```
### Hook WebView
```javascript
Java.perform(function() {
var WebView = Java.use("android.webkit.WebView");
WebView.loadUrl.overload('java.lang.String').implementation = function(url) {
console.log("[WebView.loadUrl] " + url);
this.loadUrl(url);
};
WebView.evaluateJavascript.implementation = function(script, callback) {
console.log("[WebView.evaluateJavascript] " + script.substring(0, 200));
this.evaluateJavascript(script, callback);
};
});
```
---
## 绕过类 Hook
### 通用 SSL Pinning 绕过
```javascript
Java.perform(function() {
// OkHttp3 CertificatePinner
try {
var CertificatePinner = Java.use("okhttp3.CertificatePinner");
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {
console.log("[*] SSL Pinning bypassed (OkHttp3)");
};
} catch(e) {}
// TrustManagerImpl
try {
var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl");
TrustManagerImpl.verifyChain.implementation = function(untrustedChain) {
console.log("[*] SSL Pinning bypassed (TrustManagerImpl)");
return untrustedChain;
};
} catch(e) {}
// X509TrustManager
try {
var X509TrustManager = Java.use("javax.net.ssl.X509TrustManager");
var TrustManager = Java.registerClass({
name: "com.bypass.TrustManager",
implements: [X509TrustManager],
methods: {
checkClientTrusted: function() {},
checkServerTrusted: function() {},
getAcceptedIssuers: function() { return []; }
}
});
} catch(e) {}
// Network Security Config (Android 7+)
try {
var NetworkSecurityConfig = Java.use("android.security.net.config.NetworkSecurityConfig");
NetworkSecurityConfig.isCleartextTrafficPermitted.implementation = function() { return true; };
} catch(e) {}
});
```
### 通用 Root 检测绕过
```javascript
Java.perform(function() {
// File.exists 绕过
var File = Java.use("java.io.File");
var rootPaths = ["su", "Superuser", "magisk", "busybox", "xposed",
"/system/xbin/su", "/system/bin/su", "/sbin/su",
"/data/local/xbin/su", "/data/local/bin/su"];
File.exists.implementation = function() {
var path = this.getAbsolutePath();
for (var i = 0; i < rootPaths.length; i++) {
if (path.toLowerCase().indexOf(rootPaths[i].toLowerCase()) !== -1) {
console.log("[Root] Blocked: " + path);
return false;
}
}
return this.exists();
};
// Runtime.exec 绕过
var Runtime = Java.use("java.lang.Runtime");
Runtime.exec.overload('java.lang.String').implementation = function(cmd) {
if (cmd.indexOf("su") !== -1 || cmd.indexOf("which") !== -1) {
console.log("[Root] Blocked exec: " + cmd);
throw Java.use("java.io.IOException").$new("Permission denied");
}
return this.exec(cmd);
};
// Build.TAGS 绕过
var Build = Java.use("android.os.Build");
Build.TAGS.value = "release-keys";
});
```
### 反调试绕过
```javascript
Java.perform(function() {
// Debug.isDebuggerConnected
var Debug = Java.use("android.os.Debug");
Debug.isDebuggerConnected.implementation = function() {
console.log("[AntiDebug] isDebuggerConnected → false");
return false;
};
// TracerPid 检测绕过(native 层)
var fopen = Module.findExportByName("libc.so", "fopen");
Interceptor.attach(fopen, {
onEnter: function(args) {
this.path = args[0].readUtf8String();
},
onLeave: function(retval) {
if (this.path && this.path.indexOf("/proc/") !== -1 && this.path.indexOf("/status") !== -1) {
// 可以进一步 hook fgets 修改 TracerPid
}
}
});
});
```
### 模拟器检测绕过
```javascript
Java.perform(function() {
var Build = Java.use("android.os.Build");
Build.FINGERPRINT.value = "google/walleye/walleye:8.1.0/OPM1.171019.011/4448085:user/release-keys";
Build.MODEL.value = "Pixel 2";
Build.MANUFACTURER.value = "Google";
Build.BRAND.value = "google";
Build.DEVICE.value = "walleye";
Build.PRODUCT.value = "walleye";
Build.HARDWARE.value = "walleye";
// TelephonyManager
var TelephonyManager = Java.use("android.telephony.TelephonyManager");
TelephonyManager.getDeviceId.implementation = function() { return "352099001761481"; };
TelephonyManager.getSubscriberId.implementation = function() { return "310260000000000"; };
TelephonyManager.getSimSerialNumber.implementation = function() { return "89014103211118510720"; };
});
```
---
## 数据存储 Hook
### Hook SharedPreferences
```javascript
Java.perform(function() {
var SharedPreferencesImpl = Java.use("android.app.SharedPreferencesImpl");
SharedPreferencesImpl.getString.implementation = function(key, defValue) {
var value = this.getString(key, defValue);
console.log("[SP.get] " + key + " = " + value);
return value;
};
var Editor = Java.use("android.app.SharedPreferencesImpl$EditorImpl");
Editor.putString.implementation = function(key, value) {
console.log("[SP.put] " + key + " = " + value);
return this.putString(key, value);
};
});
```
### Hook SQLite
```javascript
Java.perform(function() {
var SQLiteDatabase = Java.use("android.database.sqlite.SQLiteDatabase");
SQLiteDatabase.rawQuery.implementation = function(sql, args) {
console.log("[SQL] " + sql);
if (args) console.log(" args: " + JSON.stringify(args));
return this.rawQuery(sql, args);
};
SQLiteDatabase.execSQL.overload('java.lang.String').implementation = function(sql) {
console.log("[SQL.exec] " + sql);
this.execSQL(sql);
};
});
```
---
## 脱壳 Hook
### 通用 DEX Dump
```javascript
Java.perform(function() {
Java.enumerateClassLoaders({
onMatch: function(loader) {
try {
var pathList = Java.cast(loader, Java.use("dalvik.system.BaseDexClassLoader")).pathList.value;
var dexElements = pathList.dexElements.value;
for (var i = 0; i < dexElements.length; i++) {
var dexFile = dexElements[i].dexFile.value;
if (dexFile) {
console.log("[DEX] " + dexFile.getName());
// 可以进一步 dump dex 内容
}
}
} catch(e) {}
},
onComplete: function() {}
});
});
```
### Hook ClassLoader.loadClass
```javascript
Java.perform(function() {
var ClassLoader = Java.use("java.lang.ClassLoader");
ClassLoader.loadClass.overload('java.lang.String').implementation = function(name) {
if (name.indexOf("com.target") !== -1) {
console.log("[ClassLoader] " + name);
}
return this.loadClass(name);
};
});
```
---
## 实用工具函数
```javascript
// 字节数组转十六进制
function bytesToHex(bytes) {
if (!bytes) return "null";
var hex = [];
for (var i = 0; i < bytes.length; i++) {
hex.push(('0' + (bytes[i] & 0xFF).toString(16)).slice(-2));
}
return hex.join('');
}
// 打印调用栈
function printStack() {
console.log(Java.use("android.util.Log").getStackTraceString(
Java.use("java.lang.Throwable").$new()));
}
// 打印对象所有字段
function printFields(obj) {
var fields = obj.class.getDeclaredFields();
fields.forEach(function(field) {
field.setAccessible(true);
try {
console.log(" " + field.getName() + " = " + field.get(obj));
} catch(e) {}
});
}
// 搜索内存中的类实例
function findInstances(className) {
Java.choose(className, {
onMatch: function(instance) {
console.log("[Instance] " + instance);
printFields(instance);
},
onComplete: function() {}
});
}
```
---
## 参考资源
| 资源 | 说明 | 链接 |
|------|------|------|
| Frida 官方文档 | API 参考 | https://frida.re/docs/ |
| Frida CodeShare | 社区脚本分享 | https://codeshare.frida.re/ |
| awesome-frida | 资源大全 | https://github.com/dweinstein/awesome-frida |
| frida-codeshare-scripts | 全网最全脚本收集 | https://github.com/zengfr/frida-codeshare-scripts |
| Objection | Frida 封装工具 | https://github.com/sensepost/objection |
| r2frida | radare2 + Frida 集成 | https://github.com/nowsecure/r2frida |