【iOS逆向】Instagram抓包小记

admin 2025年3月24日19:25:17评论25 views字数 6509阅读21分41秒阅读模式

前言

文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口均已做脱敏处理。严正声明禁止用于商业和非法用途,否则由此产生的一切后果与作者本人无关。若有侵权,请在vx【amuncocoL】联系作者。

背景

学习抓包检测遂对Ins进行简单的分析,旨在记录踩坑学习。

抓包

首先对海外的app进行抓包我是使用charles[Enternal Proxy] + 🚀 进行抓包~

打开app很明显的unknown映入眼帘...【iOS逆向】Instagram抓包小记

【iOS逆向】Instagram抓包小记
我让你unknown!

定位

起初我以为sslpinning问题导致抓包失败,我随即安装了ssl-kill-switch3 [https://github.com/NyaMisty/ssl-kill-switch3] 然而也没有什么用...

然后搜到看雪的一篇文章https://bbs.kanxue.com/thread-277430.htm,但是并未通过文章解决成功,可能是版本太老了?

【iOS逆向】Instagram抓包小记
天塌了

不能放弃,根据以往的经验先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文件其内容如下

【iOS逆向】Instagram抓包小记到这一步, 我说白了 那就很有意思了。

【iOS逆向】Instagram抓包小记

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了!【iOS逆向】Instagram抓包小记

【iOS逆向】Instagram抓包小记

最后

本人思路可能并非最好

旨在记录

有写错的,或者有什么问题,欢迎大家评论。

ps: 兔哥的文章模板真难用,给他找了个新的,嘻嘻~

下期见~

原文始发于微信公众号(二进制科学):【iOS逆向】Instagram抓包小记

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年3月24日19:25:17
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【iOS逆向】Instagram抓包小记https://cn-sec.com/archives/3878883.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息