damyan-deshev/ssl-pinning-toolkit
GitHub: damyan-deshev/ssl-pinning-toolkit
面向授权安全研究的 Android TLS 证书锁定检测工具包,通过 Frida hook 和原生库指纹识别实现对现代 Android 应用多层 TLS 实现的可重复审计。
Stars: 0 | Forks: 0
# Android TLS 检查工具包
用于检查 Android TLS pinning 攻击面的授权研究工具包:包含 Frida hooks、原生库指纹以及适用于现代 arm64 应用的可重复验证协议。
本仓库特意仅包含工具和协议。不包含目标 APK、提取的应用资产、流量捕获、凭据、生产日志或客户数据。
## 1) 目的
现代 Android 应用通常结合使用 Java pinning、Cronet、原生 BoringSSL 路径、剥离的符号以及特定构建的原生库。本项目旨在使这项工作保持可检查性:
- 通过 build-id、`.rodata` 哈希或 ELF header 哈希来识别原生库指纹;
- 将已知构建映射到明确的 hook 目标和签名;
- 将探测模式和签名窗口与活动 hooks 分离;
- 记录验证过程,以便结果可重复且可审查。
## 2) 本仓库的作用
- 在受控的 Android 测试环境中提供用于授权 TLS 检查的 Frida agent。
- 检测特定的原生库构建,并应用已知、可审查的 hook 偏移量。
- 支持可选的 anchor 扫描,以检查未知构建而无需自动推导偏移量。
- 为安全分析师和工程师的可重复工作流提供简短和详细的测试协议。
## 3) 本仓库的局限性
- 不包含目标应用程序、提取的 APK 内容、流量捕获或私人测试数据。
- 不授予测试第三方系统的授权。
- 不能自动解决每一个自定义加密或应用层加密方案。
- 不包含完整的熵追踪器或基于 Stalker 的分析。
- 当前版本不支持 32 位架构。
## 4) 受众与角色
- 管理人员:阅读第 1、5、8 和 13 节以了解进展和成果。
- 分析师:遵循 `TESTING_PROTOCOL_EXTENDED.md` 中的协议。
- 工程师:使用 `sigdb.py`,更新 `sig_db.json`,并运行 `ssl_kill.js`。
## 5) 安全与授权
仅测试您被明确授权分析的应用程序。使用专用的测试设备、合成账户和经过净化的测试夹具。请勿使用个人或生产账户。
## 6) 仓库结构
- `ssl_kill.js`:执行 SSL 绕过和签名数据库查找的 Frida agent。
- `sig_db.json`:以 build-id 或哈希为键的签名数据库。
- `sigdb.py`:用于提取库指纹和添加数据库条目的辅助工具。
- `TESTING_PROTOCOL.md`:简短的分步测试指南。
- `TESTING_PROTOCOL_EXTENDED.md`:适用于混合受众的详细协议。
## 7) 支持的环境
- 仅限 Android arm64(当前版本)。
- 带有 Frida server 的已 root 设备。
- 带有 Python 3、Frida CLI 和 ADB 的主机。
## 8) 核心概念(通俗语言 + 技术细节)
### 8.1 签名数据库
签名数据库(`sig_db.json`)将特定的库构建映射到我们要 hook 的函数偏移量。“构建”通过以下方式识别:
1. `build_id`(最佳情况)
2. `.rodata` 哈希(备选方案)
3. ELF header 哈希(最后手段)
数据库 schema 刻意保持简单并具备前瞻性:
```
{
"schema_version": 1,
"offset_base": "module",
"arm64": {
"libcronet.so": {
"enable_anchor_scan": true,
"probe_defaults": { "enabled": false, "min_hits": 1, "deadline_sec": 12 },
"builds": {
"build_id:abcd...": {
"source": "build_id",
"targets": [
{
"name": "x509_verify_cert",
"offset": "0x1234",
"hook": "ret1",
"sig": {
"win1": { "off": "0x0", "bytes": "fd7bbfa9fd030091", "mask": "ffffffffffffffff" },
"win2": { "off": "0x18", "bytes": "f40300aa", "mask": "ffff00ff" }
}
}
]
}
},
"anchors": [
{ "id": "boringssl_global_config", "type": "string", "value": "Global configuration for BoringSSL" }
]
}
}
}
```
### 8.2 模块基址偏移量
所有偏移量都是相对于模块基址的。请勿使用 `.text` 相对偏移量。这可以避免与 ASLR 混淆并保持计算简单:
```
module_base + offset = hook_address
```
### 8.3 Hook 类型
Hook 类型刻意仅限于简单的返回值覆盖:
- `ret1`:强制成功(返回 1)
- `ret0`:强制成功(返回 0)
### 8.4 签名窗口(字节 + 掩码)
每个目标可以选择包含双窗口签名检查:
- `win1`:靠近函数序言(稳定性检查)
- `win2`:深入函数内部(版本检查)
每个窗口包含长度相等的 `bytes` 和 `mask`。掩码允许将与重定位相关的字节进行通配处理。
### 8.5 探测与提交
目标可以从 `probe` 模式(仅计数)开始,并在达到足够命中次数后提升为活动模式。
- 可以为每个库设置 `probe_defaults`。
- 仅头部指纹匹配仅保持探测模式,除非签名匹配。
这可以保持 hooks 稳定,并避免调用未知的代码路径。
### 8.4 Anchor 扫描
当构建未知时,脚本可以扫描字符串锚点(错误消息)以帮助定位验证逻辑。这由以下内容控制:
```
"enable_anchor_scan": true
```
Anchor 扫描仅记录候选地址。目前尚不能自动推导偏移量。
## 9) 基本工作流程(简版)
1. 从 APK 中提取目标库。
2. 使用 `sigdb.py` 提取库指纹。
3. 查找验证函数偏移量(手动分析)。
4. 在 `sig_db.json` 中注册偏移量。
5. 使用 `ssl_kill.js` 运行应用程序。
6. 初始化数据库并重新扫描。
7. 验证 TLS 拦截。
## 10) 命令示例
指纹提取:
```
python sigdb.py fingerprint /path/to/libcronet.so
```
注册目标:
```
python sigdb.py add --db sig_db.json --arch arm64 --lib libcronet.so \
--elf /path/to/libcronet.so \
--target x509_verify_cert:0x1234:ret1 \
--target ssl_get_verify_result:0x5678:ret0
```
注册带有签名的目标(按目标,有序):
```
python sigdb.py add --db sig_db.json --arch arm64 --lib libcronet.so \
--elf /path/to/libcronet.so \
--target x509_verify_cert:0x1234:ret1 \
--sig @sig_x509.json \
--target ssl_get_verify_result:0x5678:ret0 \
--sig @sig_verify_result.json
```
签名文件示例(`sig_x509.json`):
```
{
"win1": { "off": "0x0", "bytes": "fd7bbfa9fd030091", "mask": "ffffffffffffffff" },
"win2": { "off": "0x18", "bytes": "f40300aa", "mask": "ffff00ff" }
}
```
运行 Frida:
```
frida -U -f com.target.app -l ssl_kill.js --no-pause
```
## 11) RPC 用法(技术性)
Frida 脚本期望通过 RPC 传递数据库:
伪流程:
1. 加载脚本
2. 调用 `init(db_json)`
3. 调用 `rescan()`
示例(Python,最小化):
```
import frida, json
device = frida.get_usb_device()
pid = device.spawn(["com.target.app"])
session = device.attach(pid)
with open("sig_db.json", "r", encoding="utf-8") as fh:
db = json.load(fh)
script = session.create_script(open("ssl_kill.js", "r", encoding="utf-8").read())
script.load()
script.exports.init(db)
script.exports.rescan()
device.resume(pid)
```
## 12) 测试协议
- 使用 `TESTING_PROTOCOL.md` 获取简短检查清单。
- 使用 `TESTING_PROTOCOL_EXTENDED.md` 获取详细的 SOP 和故障排除指南。
## 13) 操作说明(实用指南)
- 如果存在 build-id,它是最可靠的匹配键。
- 仅头部匹配被视为弱匹配;建议使用签名以确保安全使用。
- 如果启用了 anchor 扫描,在大型模块上可能会很慢。仅在必要时使用。
- 务必验证偏移量是基于模块的。错误的偏移量可能导致应用程序崩溃。
- Cronet 可能通过 `android_dlopen_ext` 加载;脚本会 hook 该路径。
## 14) 故障排除(快速)
- Frida 无法附加:验证 frida-server 版本和 root 状态。
- 未应用 hooks:检查数据库条目、指纹键和偏移量。
- 代理中无流量:验证 CA 安装以及应用是否使用 Cronet。
- Anchor 扫描无日志输出:字符串可能已被剥离或压缩。
## 15) 局限性与未来工作
当前局限性:
- 仅限 arm64
- 没有从 anchors 自动进行 XREF 解析
- 没有针对应用层加密的熵追踪
未来可能的工作:
- 自动 ADRP/ADD XREF 解析
- 可选的熵追踪器(Stalker)用于 ALE 发现
- 支持其他架构
## 16) 支持与上报
如果您遇到阻碍:
1. 捕获日志和错误。
2. 保存库文件和指纹输出。
3. 上报给工程师以进行偏移量提取和数据库更新。
由 [Damyan Deshev](https://github.com/damyan-deshev) 维护 - 本地优先软件、安全研究工具、确定性诊断和实用的产品系统。
标签:Android安全, arm64, BoringSSL, Cronet, ELF解析, Frida Hook, Homebrew安装, SSL Pinning绕过, TLS检查, 云资产清单, 原生库分析, 安全合规, 授权测试, 数据可视化, 测试协议, 目录枚举, 移动安全, 移动应用安全, 网络代理, 网络安全, 自定义脚本, 逆向工程, 隐私保护