首页
论坛
课程
招聘

[调试逆向] [原创]mmtls的分析研究与总结

2020-3-5 12:08 3025

[调试逆向] [原创]mmtls的分析研究与总结

2020-3-5 12:08
3025

前言

mmtls是基于1.3的tls协议简化修改而来,根据某公司的描述,这种安全可行,用于短连接的安全模式,也给了其他的公司启发,一方面,使用https在越狱root环境下,也容易被窥探,所以开发一种通用而安全的短连接加密协议,确实有些必要,我们想看看到底是如何实现的,所以抓个包,hook下数据来看看。

(不太清楚在这样的氛围下,能不能讨论这个,所以我决定先写一部分,要是可以继续说,再写后半部分,大家参考这种实现,实现出自己的通用加密传输协议)

关于mmtls的介绍可以阅读这篇文章

官方介绍

我们如何入手分析呢?

1.抓包

抓包显然是没有办法看到啥的,不过我们只关心短连接,所以我们需要一个环境来触发短连接的mmtls初始化,而且我们只关心mmtls,并不关心其他的信息,所以,我们可以利用一个早期版本,理由是,早期版本可以屏蔽掉长连接,而强制使用短连接。

2.算法

显然我们应该先对算法,有一些了解,甚至我们应该先阅读一下github上的tls1.3的实现,这样我们才能对tls1.3的答题轮廓有些印象,在我们逆向分析的过程中,省去很多的麻烦,所以我们应该先了解以下算法,包括以下算法的原理和使用。
  • ECDH(ecdh主要用于秘钥协商,签名验证)
  • AESGCM(aes gcm 带校验的aes加密算法,相比于之前的aes cbc要更安全)
  • hkdf扩展(hkdf扩展是用来扩展秘钥的)
  • sha256(哈希算法,基本上用于验证数据)
  • hmac(签名)

Hook

为了便于分析,我们会一次把以上的算法进行hook一次,弄清数据的来龙去脉,这也是分析协议最关键的技巧,跟着数据走,以数据为核心,来进行逆向,不用太在意到底是经过了那些算法,我们只需关心,数据在哪里变化了。所以我选取了PC版本26231,找出上面算法的hook地址,找算法地址其实不复杂,因为基于openssl的算法,搜关键字啥的就行了。为了方便大家对照,我在这里公布地址的列表:
  • BuildWriteBuffer 0xA17B3A (发送数据)
  • GenEcdhPublicKey 0xA475AC
  • GenEcdhPublicKey 0xA475AC
  • GenEcdhPriKey 0xA475C8
  • ClientChannelReceive 0xA18FFD
  • AesGcmCrypterCrypt 0xA6124B
  • AesGcmCrypterCryptFinish 0xA61434
  • OpenSslCryptoUtilHkdfExpand 0xA47827
  • OpenSslCryptoUtilHkdfExpandFinish 0xA478BC
  • OpenSslCryptoUtilEcdh 0xA4816B
  • OpenSslCryptoUtilEcdhFinish 0xA482CF
  • OpenSslCryptoUtilSHA256Update 0xA489A0
  • OpenSslCryptoUtilSHA256Final 0xA48A65
  • OpenSslCryptoUtilSHA256FinalFinish 0xA48B07
  • OpenSslCryptoUtilHMacSHA256 0xA4810D
  • OpenSslCryptoUtilHMacSHA256Finish 0xA4815F

启动注入研究Log

  1. 由于mmtls的必须启动注入,所以需要在dll被load进来就开始注入,这可以利用OD很方便,之后我们可以看到一些日志。


    这里生成了两对ECDH秘钥对,参照官方解释,应该是一对用于加密,一对用于签名校验,因为放弃了原有的tls证书链形式签名校验,可能就采用这种方式来做签名。
  2. 之后看发送数据
    首先可以看到这里对发送的数据进行了一次SHA256计算,之后便发送了,而发送数据从结构上来看应该是tls的clientHello包,但是好像结构并不能完全与之对应,从数据上大致可以分为以下几块:
    • 总大小(00 00 00 D0)
      • 可能是版本(01 03 f1)
      • 内容大小
      • 随机数32
      • 时间戳
      • 一大串不知道啥
      • ECDHPUB1
      • ECDHPUB2
      • 序列号
  3. 看看Serverhello
    Serverhello比较符合tls的规范0x16为协商过程,所以我们将数据
    进行了切割,大体分为四个块,接下来分别以这四个块进行讲解,看看我们理解上的tls1.3与mmtls有什么区别,从文章来理解,砍掉了算法选择,RTT-1就可以协商完成。
  • 第一个数据块
    • 上面可以看到第一个数据块,返回了服务器的pubkey,用于跟我们之前的prikey进行一次ecdh协商然后得出一个32大小的数据。
    • 之后进行一次HKDF的秘钥扩展生成56大小的数据,根据文章描述,应该是对这56的数据进行分开,此时的数据,则为服务器和客户端的共同加解密数据,但是这个数据并不是最终的固定秘钥,而是协商过程用于加解密数据的秘钥。秘钥按照(16 12 16 12)进行分解,作为AES GCM的 key 跟IV,这样便可以进行后续的解密操作。
  • 第二个数据块
    现在就开始解密第二个数据块了,key iv nonce都比较清晰,同理可以解密出来第三部分第四部分。
  • 解密第三个数据块
    第三个块解密出来的数据包含PSK data,以便于后续的直接PSK模式请求。
  • 解密第四个数据块
    第四个数据块包含server finish,服务器返回的数据就完全了,根据server finish可以做一些校验,判断数据是否有错误。
  1. 发送Client Finish
    协商完成以后,客户端要发送client finish的报文,告诉服务器客户端以及完成了解密和协商。
    用第一块数据hdkf扩展出来的加密key iv进行加密即可但是这里的IV做了异或自增加,为了防止重攻击,服务器应该解密之后自增长,这样重复请求就无法解密。
  2. 扩展出业务秘钥
    到这里就和application.data.key.expansion一起扩展出来了真正的业务请求秘钥,现在就是安全的传输模式了。

    总结

    https的流量劫持从这篇文章我们其实了解到,从http时代的流量劫持到https时代都没有彻底解决,以前运营商恶心,现在证书信任依然是个很大的问题,所以我们如果能从mmtls的实现里面,对tls1.3进行改动,应该可以实现一套比较通用的安全传输协议层,而且基本上也与业务无关。


[求职]想求职找工作,请来看雪招聘投递简历!

最后于 2020-3-6 11:03 被大魔头编辑 ,原因: 更新
最新回复 (11)
双峰山 2020-3-5 15:27
2
0
照着GitHub的tls1.3实现就行了,几个细微差别而已。
evilbeast 2020-3-6 02:21
3
0
可以
evilbeast 2020-3-6 02:26
4
0
好文
killpy 2 2020-3-6 06:49
5
0
mark
酷鸟 2020-3-6 11:40
6
0
好文 期待后续
kongkong447 2020-3-26 15:58
7
0
秘钥按照(16 12 16 12)进行分解,作为AES GCM的 key 跟IV
这个看分解  是 (16 16 12 12)
091DDD18   0D7C99F0
091DDD1C   00000010
091DDD20   0D7C9A00
091DDD24   00000010
091DDD28   0D7C9A10
091DDD2C   0000000C
091DDD30   0D7C9A1C
091DDD34   0000000C
孤山飞雪 2020-4-12 11:43
8
0
jingang728627,v,等联系
KongKong20 2020-5-5 10:03
9
0
请教下怎样:屏蔽掉长连接,而强制使用短连接?
找了资料,说是__RunConnect,尝试了修改socekt为-1,还是会再次调用长连接。
往上层找MakesureLonglinkConneted,没找到开始调用的地方。
大魔头 2020-5-6 20:27
10
0
KongKong20 请教下怎样:屏蔽掉长连接,而强制使用短连接? 找了资料,说是__RunConnect,尝试了修改socekt为-1,还是会再次调用长连接。 往上层找MakesureLonglinkConneted ...
新版本是不让屏蔽了的
KongKong20 2020-5-8 09:27
11
0
大魔头 新版本是不让屏蔽了的
我这边用的是一样的老版本:2.6.2.31。
clientHello包长也不是 0x0d,反而大很多0x161,其他字段对得上,就中间的未知多了很多东西
Altai001 2020-5-24 22:46
12
0
解密server的第一个数据块,handshake key expantion 长度为55那个,是怎么来的呢
游客
登录 | 注册 方可回帖
返回