前言
文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口均已做脱敏处理。严正声明禁止用于商业和非法用途,否则由此产生的一切后果与作者本人无关。若有侵权,请在vx【amuncocoL】联系作者。
背景
学习抓包检测遂对Ins进行简单的分析,旨在记录踩坑学习。
抓包
首先对海外的app进行抓包我是使用charles[Enternal Proxy] + 🚀 进行抓包~
打开app很明显的unknown
映入眼帘...
定位
起初我以为sslpinning问题导致抓包失败,我随即安装了ssl-kill-switch3 [https://github.com/NyaMisty/ssl-kill-switch3]
然而也没有什么用...
然后搜到看雪的一篇文章https://bbs.kanxue.com/thread-277430.htm
,但是并未通过文章解决成功,可能是版本太老了?
不能放弃,根据以往的经验先frida hook *[NSBundle *]
var NSBundle = ObjC.classes.NSBundle['- pathForResource:ofType:'].implementation;Interceptor.attach(NSBundle, { onEnter: function (args) { var source = ObjC.Object(args[2]); console.log(`pathForResource: ${ObjC.Object(args[2])} ofType: ${ObjC.Object(args[3])}`); }, onLeave: function (retval) { }})
输出如下:
pathForResource: SessionlessLatencyConfig ofType: json.gzpathForResource: zh-Hans ofType: lprojpathForResource: Info ofType: plistpathForResource: fbt_language_pack ofType: binpathForResource: FOACaaRootViewController ofType: nibpathForResource: FOACaaRootView ofType: nibpathForResource: BKCdsBottomSheetViewController ofType: nibpathForResource: BKCdsBottomSheetView ofType: nibpathForResource: BKCdsScreenViewController ofType: nibpathForResource: BKCdsScreenView ofType: nibpathForResource: BKCdsFullScreenViewController ofType: nibpathForResource: BKCdsFullScreenView ofType: nibpathForResource: CACerts ofType: plistpathForResource: FacebookSDKStrings ofType: bundlepathForResource: SessionlessSamplingConfig ofType: json.gz
起初对输出没有发现什么特殊的,省略踩了一些坑。 再重新看输出的时候发现了CACerts
这个关键字样,打开IPA包内容查看此plist文件其内容如下
到这一步, 我说白了 那就很有意思了。
NSBundle为切入点
把上边的frida代码修改打印下堆栈
var NSBundle = ObjC.classes.NSBundle['- pathForResource:ofType:'].implementation;Interceptor.attach(NSBundle, { onEnter: function (args) { var source = ObjC.Object(args[2]);if (source.toString().indexOf('CACerts') !== -1) { console.log(`pathForResource: ${ObjC.Object(args[2])} ofType: ${ObjC.Object(args[3])}`); console.log(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("n")); } }, onLeave: function (retval) { }})
输入如下:
pathForResource: CACerts ofType: plist0x11124e63c FBSharedFramework!CRYPTO_memcmp0x1123f7c7c FBSharedFramework!IGDirectMessagePowerupsTextIsEligible0x1123fb17c FBSharedFramework!EVP_CipherFinal0x11180d0a4 FBSharedFramework!X509_get_ext0x11180ceac FBSharedFramework!X509_get_ext0x11180a738 FBSharedFramework!X509_verify_cert0x11180a480 FBSharedFramework!X509_verify_cert0x111808aa0 FBSharedFramework!RSA_free0x111807f74 FBSharedFramework!RSA_free0x1114a3334 FBSharedFramework!proxygen::TraceEvent::hasEnded() const0x1114b8ec8 FBSharedFramework!EVP_MD_CTX_reset0x1114b549c FBSharedFramework!EVP_PKEY_get1_EC_KEY0x1114c3828 FBSharedFramework!MSGOpenPathRenderedNotificationGetSequenceId0x1114b8668 FBSharedFramework!EVP_MD_CTX_reset0x1114a34c0 FBSharedFramework!proxygen::TraceEvent::hasEnded() const0x11143fe68 FBSharedFramework!folly::IPAddress::IPAddress()
原来是在FBSharedFramework
中做的小手段,IDA舔包启动...
X509_verify_cert
伪代码如下:
int __cdecl X509_verify_cert(X509_STORE_CTX *ctx){ __int64 v1; // x19 __int64 v2; // x0 __int64 v3; // x0 __int64 v4; // x8 __int64 v5; // x0 int v6; // w8 int result; // w0 __int64 v8; // x20 int v9; // w9 int v10; // w11 __int64 v11; // x0 __int64 v12; // x0 __int64 v13; // x0 __int64 v14; // x0 __int64 v15; // x0 __int64 v16; // x0 int v17; // w8 int *v18; // x8 __int64 v19; // x20 __int64 v20; // x22 __int64 v21; // x0 int v22; // w21 __int64 v23; // x0 __int64 v24; // x0 __int64 v25; // x0 __int64 v26; // x0 v2 = ((__int64 (__fastcall *)(X509_STORE_CTX *))sub_400C)(ctx); v3 = ((__int64 (__fastcall *)(__int64))sub_8D04)(v2);if ( !v4 || *(_QWORD *)(v1 + 152) ) { v5 = ((__int64 (__fastcall *)(__int64))sub_19B1078)(v3); ((void (__fastcall *)(__int64))sub_1679C)(v5); v6 = 69;LABEL_3: *(_DWORD *)(v1 + 176) = v6;return -1; } v8 = *(_QWORD *)(v1 + 232);do v3 = ((__int64 (__fastcall *)(__int64))sub_1D17C)(v3);while ( v10 );if ( v9 <= 0 ) { v11 = ((__int64 (__fastcall *)(__int64))sub_19B1078)(v3); ((void (__fastcall *)(__int64))sub_1679C)(v11); v6 = 1; goto LABEL_3; } v12 = ((__int64 (__fastcall *)(__int64))OPENSSL_sk_new_null)(v3); *(_QWORD *)(v1 + 152) = v12;if ( !v12 || !(unsigned int)((__int64 (__fastcall *)(__int64, _QWORD))OPENSSL_sk_push)(v12, *(_QWORD *)(v1 + 8)) ) { X509_free(*(X509 **)(v1 + 8)); v13 = sub_19B1078(); ((void (__fastcall *)(__int64))sub_15900)(v13); v6 = 17; goto LABEL_3; } *(_DWORD *)(v1 + 148) = 1; v14 = ((__int64 (__fastcall *)(__int64, _QWORD))sub_441AB8)(v1, *(_QWORD *)(v1 + 8));if ( (_DWORD)v14 || (v15 = ((__int64 (__fastcall *)(__int64, _QWORD))sub_1C5AC)(v14, *(_QWORD *)(v1 + 8)), v16 = ((__int64 (__fastcall *)(__int64))sub_1E23BE8)(v15), result = ((__int64 (__fastcall *)(__int64))sub_11680)(v16), v17) ) {if ( !v8 ) goto LABEL_27; v18 = *(int **)(v8 + 8);if ( !v18 ) goto LABEL_27;if ( *v18 < 1 ) goto LABEL_27; v19 = *(_QWORD *)(v1 + 8); v20 = *(_QWORD *)(v1 + 232); X509_free(*(X509 **)(v20 + 32)); *(_QWORD *)(v20 + 24) = 0LL; *(_QWORD *)(v20 + 32) = 0LL; *(_QWORD *)(v20 + 44) = -1LL; v21 = sub_1C5AC(); v22 = ((__int64 (__fastcall *)(__int64))sub_32C3498)(v21);if ( v22 || (*(_BYTE *)(v20 + 40) & 5) == 0 && (*(_DWORD *)(v20 + 44) & 0x80000000) != 0 ) { v23 = ((__int64 (__fastcall *)(_QWORD))sub_448A40)(*(_QWORD *)(v1 + 152));if ( v22 >= 1 ) { v24 = ((__int64 (__fastcall *)(__int64))sub_6038)(v23); result = ((__int64 (__fastcall *)(__int64))sub_1A2B8CC)(v24);if ( result ) {if ( (*(_BYTE *)(v20 + 56) & 1) != 0 || (result = sub_448904()) != 0 ) { *(_DWORD *)(v1 + 172) = 0; *(_QWORD *)(v1 + 184) = v19; result = ((__int64 (__fastcall *)(__int64))sub_6C84)(1LL); goto LABEL_28; } } goto LABEL_29; }if ( v22 < 0 ) { *(_QWORD *)(v1 + 172) = 0x1100000000LL; *(_QWORD *)(v1 + 184) = v19; result = -1; goto LABEL_29; } v25 = ((__int64 (__fastcall *)(__int64))sub_6038)(v23); result = ((__int64 (__fastcall *)(__int64))sub_1A2B8CC)(v25);if ( !result ) {LABEL_29:if ( !*(_DWORD *)(v1 + 176) ) *(_DWORD *)(v1 + 176) = 1;return result; } v26 = sub_95E14(); result = ((__int64 (__fastcall *)(__int64))sub_1E23BE8)(v26); }else {LABEL_27: result = sub_441B1C(); }LABEL_28:if ( result > 0 )return result; goto LABEL_29; }return result;}
总结为一句话,该函数X509_verify_cert
用于 OpenSSL 的证书链验证,在iOS应用中常见于HTTPS连接中对服务端证书进行校验的地方。
frida hook看下返回值
Interceptor.attach(Module.getExportByName("FBSharedFramework", "X509_verify_cert"), { onEnter: function (args) { }, onLeave: function (retval) { console.log("retval: ", retval); }});
输出如下:
retval: 0x0retval: 0x0retval: 0x0
0x0代表证书校验失败
那我反手直接一个replace
Interceptor.attach(Module.getExportByName("FBSharedFramework", "X509_verify_cert"), { onEnter: function (args) { }, onLeave: function (retval) { retval.replace(0x1); console.log("retval: ", retval); }});
okay了!
最后
本人思路可能并非最好
旨在记录
有写错的,或者有什么问题,欢迎大家评论。
ps: 兔哥的文章模板真难用,给他找了个新的,嘻嘻~
下期见~
原文始发于微信公众号(二进制科学):【iOS逆向】Instagram抓包小记
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论