查看原文
其他

一种基于frida和drony的针对flutter抓包的方法

beimingyouyu 看雪学苑 2022-07-01

本文为看雪论坛优秀文章

看雪论坛作者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





- End -



看雪ID:beimingyouyu

https://bbs.pediy.com/user-home-767367.htm

  *本文由看雪论坛 beimingyouyu 原创,转载请注明来自看雪社区。



另外,贴心提示本次再印刷还没购买0day安全正书籍的小伙伴抓紧时间啦!


点击以下小程序即可预购!

推荐文章++++

* 老树开花,一例新上传的KimSuky老样本分析

* 茴字的三种写法之angr符号执行寻找Flag

* IO-FILE中的stdin介绍

* 反汇编代码还原之除数为2的幂

* 用麒麟框架深入分析实模式二进制文件







公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



求分享

求点赞

求在看


“阅读原文”一起来充电吧!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存