首页
社区
课程
招聘
[转帖][讨论][原创]iOS逆向工程——cronet抓包SSL Pinning
发表于: 6天前 320

[转帖][讨论][原创]iOS逆向工程——cronet抓包SSL Pinning

6天前
320

本文章中所有内容仅供学习交流使用,不用于其他任何目的,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关;本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文涉及的技术而导致的任何意外,作者均不负责。


打开 App 下拉抓主页抓包,抓不到商品信息数据,只有一些零散无用数据。先猜测可能是常见的 SSL Pinning,iOS 里用 SSL Kill Switch 开启后重试,仍然不行,依旧只有无用数据。

使用Frida,挂载app进程

找到了在这个路径下,Frameworks\Cronet.framework,把下面的文件导入到本地并进行反编译分析

获得了请求方法的地址,加上ASLR,在几个地址打断点,发生了断点,确认了是cronet进行网路请求

源码中校验位置

SSL_CTX_set_custom_verify(ssl_ctx_.get(), SSL_VERIFY_PEER, CertVerifyCallback);

SSL CTX set session cache_mode(
Ssl ctx .get(),SSL SESS CACHE CLIENT | SSL SESS CACHE NO INTERNAL),SsL CTX sess set new_cb(ssl ctx .get(),Newsessioncallback);SSL_CTX set_timeout(ssl_ctx_.get(),1*60*60 /* one hour */);
SsL CTX set grease enabled(ssl ctx .get(),1);

我们直接搜关键字没搜索到可以找一些特征值搜索

可以看到他下面有一个60 * 60 也就是3600,转一下16进制就是 0xE10!!!这里不用考虑大小端因为是立即数
ida 搜索一下

一共涉及到三个函数我们一个一个看
前两个明显不是
第三个感觉比较像 3600是最后一个参数
贴一下反编译代码

__int64 sub_25A3DC()
{
  __int64 v0; // x19
  __int64 v1; // x0
  __int64 v2; // x0
  __int64 v3; // x0
  __int64 v4; // x21
  __int64 v5; // x0

  v0 = sub_BA758(16);
  *(_QWORD *)(v0 + 8) = 0;
  sub_340DBC();
  *(_DWORD *)v0 = sub_2E9678(0, 0, 0, 0, 0);
  v1 = sub_2F1BD4();
  v2 = sub_2E7BB8(v1);
  sub_2E9950(v0 + 8, v2);
  sub_2E50CC(*(_QWORD *)(v0 + 8), sub_25A4F0, 0);
  sub_2E970C(*(_QWORD *)(v0 + 8), 1);
  sub_2E9130(*(_QWORD *)(v0 + 8), 1, sub_2597E0);
  sub_2E9074(*(_QWORD *)(v0 + 8), 769);
  sub_2EBE88(*(_QWORD *)(v0 + 8), sub_25A520);
  sub_2EBDBC(*(_QWORD *)(v0 + 8), 3600);
  v3 = sub_2E9764(*(_QWORD *)(v0 + 8), 1);
  v4 = *(_QWORD *)(v0 + 8);
  v5 = sub_16F420(v3);
  sub_2E8E8C(v4, v5);
  sub_2E96C0(*(_QWORD *)(v0 + 8), sub_25A550);
  sub_2892E4(*(_QWORD *)(v0 + 8));
  return v0;
}

同时满足三个参数和最后一个函数的只有这个

 sub_2E9130(*(_QWORD *)(v0 + 8), 1, sub_2597E0);

所以说关键的函数应该是sub_2597E0

我们需要看下sub_2597E0干了什么

__int64 __fastcall sub_2597E0(__int64 a1)
{
  __int64 v2; // x0
  __int64 v3; // x0

  v2 = sub_25A340();
  v3 = sub_259808(v2, a1);
  return sub_259818(v3);
}

实际上应该返回数字代表状态,是否检验通过 实际的检测在sub_259818里面
如下 兴趣的可以简单看下逻辑

__int64 __fastcall sub_259818(__int64 result)
{
  __int64 v1; // x19
  __int64 v2; // x0
  __int64 v3; // x0
  __int64 v4; // x22
  __int64 v5; // x1
  __int64 v6; // x0
  __int64 v7; // x1
  __int64 v8; // x22
  __int64 v9; // x23
  __int64 v10; // x24
  __int64 v11; // x0
  char v12; // nf
  char v13; // vf
  __int64 v14; // x8
  unsigned __int8 v15; // w9
  __int64 v16; // x10
  __int64 v17; // x11
  __int64 v18; // x21
  _QWORD *v19; // x25
  __int64 v20; // x26
  __int64 v21; // [xsp+18h] [xbp-168h] BYREF
  _QWORD v22[2]; // [xsp+20h] [xbp-160h] BYREF
  __int64 v23; // [xsp+30h] [xbp-150h] BYREF
  _QWORD v24[2]; // [xsp+38h] [xbp-148h] BYREF
  __int64 v25; // [xsp+50h] [xbp-130h] BYREF
  _QWORD v26[14]; // [xsp+58h] [xbp-128h] BYREF
  _QWORD v27[2]; // [xsp+C8h] [xbp-B8h] BYREF
  unsigned __int64 v28; // [xsp+D8h] [xbp-A8h] BYREF
  unsigned __int64 v29; // [xsp+E0h] [xbp-A0h] BYREF
  _QWORD v30[2]; // [xsp+E8h] [xbp-98h] BYREF
  unsigned __int64 v31; // [xsp+F8h] [xbp-88h] BYREF
  unsigned __int64 v32; // [xsp+100h] [xbp-80h] BYREF
  __int64 v33; // [xsp+108h] [xbp-78h] BYREF
  int v34; // [xsp+114h] [xbp-6Ch]
  _QWORD v35[3]; // [xsp+118h] [xbp-68h] BYREF

  v1 = result;
  if ( *(_DWORD *)(result + 296) != 1 )
    return sub_259B78(result);
  if ( !*(_QWORD *)(result + 136) )
  {
    v2 = sub_2E50D8(*(_QWORD *)(result + 304));
    v3 = sub_16F564(v2);
    sub_1E784(v1 + 136, v3);
    if ( *(_QWORD *)(v1 + 136) )
    {
      v4 = *(_QWORD *)(v1 + 904);
      if ( *(_DWORD *)(v4 + 68) )
      {
        memset(v35, 170, sizeof(v35));
        sub_1229F8(v35);
        sub_16F0D4(v26, *(_QWORD *)(v1 + 136));
        sub_122B50(v35, "certificates", 12, v26);
        sub_12232C(v26);
        sub_122298(v26, v35);
        sub_122A54(v35);
        sub_25B0BC(v4, 74, v1 + 888);
        sub_12232C(v26);
      }
      v34 = -1431655766;
      if ( (unsigned int)sub_259D88(v1) )
      {
        sub_15E058(v1 + 144);
        *(_DWORD *)(v1 + 184) = v34;
        sub_25B194(&v33);
        sub_1E784(v1 + 176, v33);
        *(_DWORD *)(v1 + 296) = 0;
        return sub_259B78(v1);
      }
      *(_QWORD *)(v1 + 288) = sub_12090C();
      v6 = sub_259DD4(v1);
      v8 = v6;
      v9 = v7;
      if ( !v7 || (*(_BYTE *)(v1 + 799) = 1, !(unsigned int)sub_258BC4(v6, v7)) )
      {
        v31 = 0xAAAAAAAAAAAAAAAALL;
        v32 = 0xAAAAAAAAAAAAAAAALL;
        sub_2E91C0(*(_QWORD *)(v1 + 304), &v32, &v31);
        v30[0] = v32;
        v30[1] = v31;
        v28 = 0xAAAAAAAAAAAAAAAALL;
        v29 = 0xAAAAAAAAAAAAAAAALL;
        sub_2E916C(*(_QWORD *)(v1 + 304), &v29, &v28);
        v27[0] = v29;
        v27[1] = v28;
        v10 = *(_QWORD *)(*(_QWORD *)(v1 + 272) + 64LL);
        v11 = sub_25B194(&v25);
        if ( !v9 )
        {
          sub_25B168(v11);
          if ( v12 != v13 )
            v8 = v16;
          else
            v8 = v14;
          if ( v12 != v13 )
            v9 = v17;
          else
            v9 = v15;
        }
        v18 = sub_28B974(v1 + 384);
        v19 = v35;
        sub_EF4A4(v35, v30);
        if ( v35[2] >= 0 )
        {
          v20 = HIBYTE(v35[2]);
        }
        else
        {
          v19 = (_QWORD *)v35[0];
          v20 = v35[1];
        }
        sub_EF4A4(v24, v27);
        sub_15AEFC(v26, v25, v8, v9, v18, v19, v20);
        v22[0] = sub_259DF8;
        v22[1] = 0;
        v21 = v1;
        v23 = sub_25AB48(sub_25AB18, v22, &v21);
        *(_DWORD *)(v1 + 296) = (*(__int64 (__fastcall **)(__int64, _QWORD *, __int64, __int64 *, __int64, __int64))(*(_QWORD *)v10 + 16LL))(
                                  v10,
                                  v26,
                                  v1 + 144,
                                  &v23,
                                  v1 + 280,
                                  v1 + 888);
        sub_C822C(&v23);
        sub_15AFA8(v26);
        sub_BACF0(v24);
        sub_BACF0(v35);
        return sub_259B78(v1);
      }
      sub_D58C8(v26, "VerifyCert", "../../net/socket/ssl_client_socket_impl.cc", 1189);
      v5 = 4294967114LL;
    }
    else
    {
      sub_D58C8(v26, "VerifyCert", "../../net/socket/ssl_client_socket_impl.cc", 1143);
      v5 = 4294967129LL;
    }
    sub_2893C4(v26, v5);
    return 1;
  }
  __break(0);
  return result;
}

已经定位到了检测点 我们开始写hook 看看能不能抓到包

hook检测函数

将返回值始终返回true

最终抓包成功!


传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!

最后于 6天前 被mb_gtqowwmp编辑 ,原因:
收藏
点赞 ・0
打赏
分享
最新回复 (1)
雪    币: 110
活跃值: (9556)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2 楼
666
3天前
0
游客
登录 | 注册 方可回帖
返回