拦截Android Flutter应用程序流量的研究
字数 1343 2025-08-22 18:37:22
拦截Android Flutter应用程序流量的研究与实践
1. Flutter应用流量拦截概述
Flutter是谷歌开源的移动开发框架,使用Dart语言编写。由于以下特性,Flutter应用的流量拦截与传统Android应用有所不同:
- Dart不使用系统CA存储
- Dart使用编译到应用程序中的CA列表
- Android上默认不支持代理设置
2. HTTP流量拦截方法
2.1 常规代理设置的问题
传统方法(如BurpSuite代理设置)对Flutter应用无效,因为:
HttpClient类默认忽略系统代理设置- 环境变量方法在Android上无效(所有应用都是zygote进程的子进程)
2.2 解决方案
方法一:修改应用代码
client.findProxy = (uri) {
return "PROXY 10.153.103.222:8888";
};
局限性:仅适用于白盒测试,无法用于黑盒评估。
方法二:使用iptables重定向
- 在root设备上安装ProxyDroid
- 配置将所有流量路由到代理服务器
- 优点:无需修改应用,适用于黑盒测试
3. HTTPS流量拦截的挑战与解决方案
3.1 问题根源
- Dart使用Mozilla的NSS库生成并编译自己的Keystore
- 无法通过系统CA存储绕过SSL验证
- 错误示例:
HandshakeException: Handshake error in client
CERTIFICATE_VERIFY_FAILED: self signed certificate in certificate chain
3.2 技术分析
关键函数调用链:
ssl_verify_peer_cert(handshake.cc)session_verify_cert_chain(ssl_x509.cc)OPENSSL_PUT_ERROR宏定义(err.h)
3.3 Frida Hook实现
步骤1:定位关键函数
var m = Process.findModuleByName("libflutter.so");
var pattern = "2d e9 f0 4f a3 b0 82 46 50 20 10 70";
Memory.scan(m.base, m.size, pattern, {
onMatch: function(address, size){
console.log('[+] ssl_verify_result found at: ' + address.toString());
}
});
步骤2:Hook并修改返回值
function hook_ssl_verify_result(address){
Interceptor.attach(address, {
onLeave: function(retval) {
retval.replace(0x1); // 强制返回true(1)
}
});
}
完整脚本
function disablePinning(){
var m = Process.findModuleByName("libflutter.so");
var pattern = "2d e9 f0 4f a3 b0 82 46 50 20 10 70";
var res = Memory.scan(m.base, m.size, pattern, {
onMatch: function(address, size){
console.log('[+] ssl_verify_result found at: ' + address.toString());
hook_ssl_verify_result(address.add(0x01)); // THUMB函数需要+1
}
});
}
setTimeout(disablePinning, 1000);
4. SSL Pinning绕过技术
4.1 SecurityContext方式的Pinning
常见实现:
ByteData data = await rootBundle.load('certs/burp.crt');
SecurityContext context = new SecurityContext();
context.setTrustedCertificatesBytes(data.buffer.asUint8List());
client = HttpClient(context: context);
绕过方法:前述的Frida脚本已可绕过,因为底层仍依赖BoringSSL验证。
4.2 ssl_pinning_plugin方式
典型代码:
List<String> hashes = new List<String>();
hashes.add("randomhash");
await SslPinningPlugin.check(
serverURL: "https://www.nviso.eu",
sha: SHA.SHA1,
allowedSHAFingerprints: hashes
);
Frida Hook方法:
function disablePinning(){
var SslPinningPlugin = Java.use("com.macif.plugin.sslpinningplugin.SslPinningPlugin");
SslPinningPlugin.checkConnexion.implementation = function() {
console.log("Disabled SslPinningPlugin");
return true;
}
}
Java.perform(disablePinning);
5. 实践步骤总结
-
环境准备:
- Root设备
- 安装MagiskTrustUserCerts模块
- 配置ProxyDroid或iptables
-
HTTP拦截:
- 使用iptables将所有流量重定向到Burp
-
HTTPS拦截:
- 注入Frida脚本绕过证书验证
- 注意THUMB模式函数需要地址+1
-
Pinning绕过:
- 根据具体实现选择Hook点
- Java实现的插件可直接Hook Java层
6. 技术原理总结
- Dart特性:自包含CA存储,不依赖系统设置
- BoringSSL稳定性:函数签名长期保持兼容
- 模式搜索可靠性:特定字节模式在库中唯一
- 通用性:方法适用于大多数Flutter应用
7. 注意事项
- 不同Flutter版本可能需要调整模式字符串
- 非root设备需要其他重定向方案
- 企业级应用可能有额外的保护措施
- 测试前应确认目标应用的Flutter版本
8. 扩展思考
- 自动化检测Flutter应用的方法
- 非root环境下的解决方案
- 针对Flutter Web和桌面应用的适配
- 对抗更高级别的证书固定方案
通过本教学文档,安全研究人员可以全面掌握拦截和分析Flutter应用流量的关键技术,为移动应用安全评估提供有效工具和方法。