一种基于frida和drony的针对flutter抓包的方法
本文为看雪论坛优秀文章
看雪论坛作者ID:beimingyouyu
一. 使用frida解除
flutter证书验证
Flutter是Google使用Dart语言开发的移动应用开发框架,使用一套Dart代码就能快速构建高性能、高保真的iOS和Android应用程序。
由于Dart使用Mozilla的NSS库生成并编译自己的Keystore,导致我们就不能通过将代理CA添加到系统CA存储来绕过SSL验证。为了解决这个问题,就必需要研究libflutter.so。
当向Burp发送HTTPS流量时,Flutter应用程序会抛出一个错误,可以将其作为起点进行溯源:
E/flutter (10371): [ERROR:flutter/runtime/dart_isolate.cc(805)] Unhandled exception:
E/flutter (10371): HandshakeException: Handshake error in client (OS Error:
E/flutter (10371): NO_START_LINE(pem_lib.c:631)
E/flutter (10371): PEM routines(by_file.c:146)
E/flutter (10371): NO_START_LINE(pem_lib.c:631)
E/flutter (10371): PEM routines(by_file.c:146)
E/flutter (10371): CERTIFICATE_VERIFY_FAILED: self signed certificate in certificate chain(handshake.cc:352))
E/flutter (10371): #0 _rootHandleUncaughtError. (dart:async/zone.dart:1112:29)
E/flutter (10371): #1 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (10371): #2 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
E/flutter (10371): #3 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:116:13)
E/flutter (10371): #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:173:5)
该错误显示了触发错误的位置:handshake.cc:352,代码如下所示:
if (ret == ssl_verify_invalid) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
}
这是ssl_verify_peer_cert函数的一部分,该函数返回ssl_verify_result_t的枚举,枚举定义在ssl.h的第2290行:
enum ssl_verify_result_t BORINGSSL_ENUM_INT {
ssl_verify_ok,
ssl_verify_invalid,
ssl_verify_retry,
};
经过试验,将ssl_verify_peer_cert的返回值更改为ssl_verify_ok (=0)的话仍会因为上面的ssl_send_alert()函数调用而失败,因此需要找另一个hook点。handshake.cc的代码段上方有一段验证证书链的方法:
ret = ssl->ctx->x509_method->session_verify_cert_chain(
hs->new_session.get(), hs, &alert)
? ssl_verify_ok
: ssl_verify_invalid;
session_verify_cert_chain函数定义在ssl_x509.cc,此函数返回布尔值类型,并且没有像ssl_verify_peer_cert函数那样的问题,可以作为hook的目标。在该方法里可以看到有两个字符串可以辅助定位方法,如图1-1所示。
图1-1 所需hook函数中有辨识度较高字符串
之后在ida中的strings可以找到并定位函数为sub_3A5564,过程如图1-2到1-4所示:
图1-2 stirngs搜索到目标字符串
图1-3 查看调用函数
图1-4 确定本函数为目标函数
图1-5 利用前10字节定位函数
后面可以在frida中编写脚本,使用函数前10字节定位,在运行时将返回函数改为true即可绕过证书链检查实现抓包,示例如下:
function hook_ssl_verify_result(address)
{
Interceptor.attach(address, {
onEnter: function(args) {
send("Disabling SSL validation")
},
onLeave: function(retval)
{
send("Retval: " + retval)
retval.replace(0x1);
}
});
}
function disablePinning()
{
var m = Process.findModuleByName("libflutter.so");
var pattern = "2d e9 f0 4f a3 b0 81 46 50 20 10 70"
var res = Memory.scan(m.base, m.size, pattern, {
onMatch: function(address, size){
send('[+] ssl_verify_result found at: ' + address.toString());
// Add 0x01 because it's a THUMB function
hook_ssl_verify_result(address.add(0x01));
},
onError: function(reason){
send('[!] There was an error scanning memory');
},
onComplete: function()
{
send("All done")
}
});
}
之所以address.add(0x01)是因为看到这么个说明:在32位ARM上, 对于ARM函数, 此地址的最低有效位必须设置为0, 对于Thumb函数, 此地址必须设置为1。
针对64位flutter.so同样可以搜索ssl_client来定位函数,并通过函数前面的一串字节进行定位,过程如图1-6到图1-9。
图1-6 strings搜索ssl_client
图1-7 查找ssl_client的交叉引用
图1-8 找到ssl_client的引用位置
图1-9 通过函数头部字节定位
针对64位flutter.so的hook代码示例如下,地址不再需要+1。
function hook_ssl_verify_result(address) {
Interceptor.attach(address, {
onEnter: function(args) {
console.log("Disabling SSL validation")
},
onLeave: function(retval) {
console.log("Retval: " + retval);
retval.replace(0x1);
}
});
}
function hookFlutter() {
var m = Process.findModuleByName("libflutter.so");
var pattern = "FF 03 05 D1 FD 7B 0F A9 9A E3 05 94 08 0A 80 52 48 00 00 39 16 54 40 F9 56 07 00 B4 C8 02 40 F9 08 07 00 B4";
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);
},
onError: function(reason){
console.log('[!] There was an error scanning memory');
},
onComplete: function() {
console.log("All done")
}
});
}
执行后即可使用packet capture进行抓包,如图1-10所示。但是使用代理还有问题,需要使用drony来配合代理进行抓包。
图1-10 通过函数头部字节定位
二. 使用drony与fiddler联合抓包
drony 是一个十分方便的VPN软件,drony会在你的手机上创建一个VPN,将手机上的所有流量都重定向到drony自身,这样drony就可以管理所有手机上的网络流量,甚至可以对手机上不同APP的流量进行单独配置。
进入首页后左滑进行设置,页面如图1-11到图1-13所示:
图1-11 主页面
图1-12 设置页面
图1-13 设置页面
设置到代理后回到主页面点击off启动,即可在fiddler查看到抓取的内容,如图1-14所示:
图1-14 抓包页面
参考:
https://www.jianshu.com/p/ada10d2976f2
https://zhuanlan.zhihu.com/p/139645460
看雪ID:beimingyouyu
https://bbs.pediy.com/user-home-767367.htm
*本文由看雪论坛 beimingyouyu 原创,转载请注明来自看雪社区。
推荐文章++++
求分享
求点赞
求在看