某音为何抓包困难? 如何抓包?

[复制链接]
查看1212 | 回复0 | 2024-12-4 13:51:20 | 显示全部楼层 |阅读模式

立即注册,突破游客限制,与技术大牛交流切磋,畅享海量资源,让你的技术之路不再孤单!

您需要 登录 才可以下载或查看,没有账号?立即注册

×
某音采取的不是 https协议 所以常用的抓包软件无法解析数据包抓取 比如 小黄鸟 小蓝鸟

某音系列采取的是GQUIC协议



根据从网上查到的一些公开怎么应对GQUIC协议抓包的方法,大多都是在想办法去绕过这个协议。如,修改路由规则来阻止UDP上443端口的流量使其被动地降级到HTTPS,或者逆向分析调整QUIC配置使其直接降级到HTTPS。还有一些其他方法,如Dump SSL中的KeyLog,然后再使用Wireshark解密。这个方法用来抓取HTTPS特别好用,对于QUIC来说则只支持IETF标准下的QUIC,本例中的APP使用的是早期的GQUIC,它有着一套自己的加密方式QUIC Crypto,所以并不适用。



QUIC协议结构
截图202412041346038299.png

怎么解密GQUIC数据包
     GQUIC Crypto 使用了前向安全机制,即双方先计算出一个临时的初始密钥,用于对握手阶段的信息进行加密。后续再基于这个初始密钥,进一步计算出会话密钥,用于加密后续的通信数据。这样做的优点就在于,即使服务器的私钥后续被泄露,也无法解密之前已经完成的通信记录。所以想要解密GQUIC数据包,则必须也按照这个步骤先计算出初始密钥,再计算出会话密钥。

想要解密GQUIC数据包至少需要四个材料:预主密钥(premaster secret)、CHLO握手数据包,REJ握手数据包,和随机数(Diversification Nonce)。其中后三者都可以通过抓包工具直接获得,但是,预主密钥的生成依赖于各自的私钥和对方的公钥,公钥信息可以从握手数据包中提取,私钥信息则是保密的。因此,解密GQUIC数据包的关键实际上就是怎么去获取私钥。当然,获取服务器的私钥不太现实,但是获取客户端的私钥还是有一定操作空间的。
    目前商用的QUIC协议大多都是基于已开源的项目,因此在分析采用QUIC协议的客户端时,可以先确定其使用的是哪个开源项目后再去分析该项目的开源代码,根据从代码中提取到的特征去逆向分析客户端,使其能直接定位到生成私钥的地方,然后再通过Hook获取。至于怎么通过特征去逆向分析,那办法就多了,最简单的莫过于通过字符串去定位,总之对于有经验的人来说就是小case。
    以某茄APP为例,它使用了Google的cronet库GitHub - google/quiche, 所以通过分析cronet的开源代码后通过从代码中提取到的字符串”Key exchange failure“特征,成功地定位到了生成私钥的地方。
截图202412041348204174.png
然后再使用Frida hook,代码如下
  1. function OnCreatePrivateKey(imgBase)
  2. {
  3.     var cornetBase = Module.findBaseAddress(imgBase);
  4.     if (cornetBase == null)
  5.     {
  6.         console.log("can't found the cornet\n");
  7.         return;
  8.     }
  9.     var onCreatePrivateKeyFun =  cornetBase.add(0x1E524C);
  10.     if (onCreatePrivateKeyFun == null)
  11.     {
  12.         console.log("bad onCreatePrivateKeyFun");
  13.         return;
  14.     }
  15.     if (onCreatePrivateKeyFun.readU64().toString(16) != "97fff8b8910163e8")
  16.     {
  17.         console.log(`bad feature${ onCreatePrivateKeyFun.readU64().toString(16)}`);
  18.         return;
  19.     }
  20.     Interceptor.attach(onCreatePrivateKeyFun, {
  21.         onEnter: function(args)
  22.         {
  23.             var private_key_ptr = new NativePointer(this.context.x0);
  24.             var len = this.context.x1.toUInt32();
  25.             if (len != 32)
  26.             {
  27.                 console.log("bad private key");
  28.             }
  29.             else
  30.             {
  31.                 var private_key = private_key_ptr.readByteArray(32);
  32.                 var private_key_hex = Array.prototype.map.call(new Uint8Array(private_key), x => ('00' +
  33.                 x.toString(16)).slice(-2)).join('');
  34.                  
  35.                 console.log(`hit OnCreatePrivateKey and the key is ${private_key_hex} the len is ${len}`)
  36.             }
  37.             
  38.         }
  39.     })
  40.     console.log("success found onCreatePrivateKeyFun")
  41. }
复制代码
现在已经能获取到私钥了,然后再根据上述的步骤去生成密钥就可以对数据包解密了,不会也没关系,后面有开源代码。

实战
    上面讲了很多东西, 现在要做的就是怎么将这些东西全部给用起来,我在Google开源库GitHub - google/quiche的基础上实现了这些功能,并成功地应用到了某茄APP(某音同系列)上,效果如下:
截图202412041350243828.png
至于某音的话朋友说和这个一样,不过我没尝试,不想去折腾它的反调试了。
    至于具体的实现,这里就不讲了,不然篇幅实在太大,我会把代码上传到Github上,感兴趣的自己去研究吧。
https://github.com/google/quiche

这个人还没有签名
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

图文推荐
大神求
大神求
6 天前
热门排行