ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

whatsapp逆向协议--漏洞分析

2021-07-27 12:05:56  阅读:1016  来源: 互联网

标签:逆向 -- 32 self secret key whatsapp data conn


whatsapp逆向协议--漏洞分析

任何一个软件都不可能无懈可击,只要你用心去研究。
WhatsApp也一样存在漏洞,whatsapp中的漏洞,可以利用其来发送私聊和群聊,还可以伪造似乎来自可信源的假消息。

抓包分析WhatsApp后,发现WhatsApp使用protobuf2 protocol协议来进行加解密。
将protobuf2数据转变成JSON格式就可以看到了真实的参数,这些参数可以发送和修改参数来检查WhatsApp的安全。
请阅读下面的完整技术分析。
访问密钥
可以在生成 QR 码之前从 WhatsApp Web 的密钥生成阶段获取密钥:
在这里插入图片描述

获取这些密钥后,我们需要获取用户扫描二维码时由手机发送到 WhatsApp Web 的“秘密”参数:

在这里插入图片描述

让我们从 WhatsApp Web 开始。在生成二维码之前,WhatsApp Web 会生成用于加密和解密的公钥和私钥。

在这里插入图片描述
让我们称我们的私钥“ priv_key_list”和我们的公钥“ pub_key_list ” 。

这些密钥是通过使用 curve25519_donna 使用随机 32 字节创建的。
在这里插入图片描述
为了解密数据,我们开始创建解密代码。这将从 WhatsApp Web 获取私钥而不是随机字节,因为我们需要具有相同的密钥才能解密数据:

self.conn_data[ “private_key” ] = curve25519.Private( “”. join( [chr(x) for x in priv_key_list]))
self.conn_data[ “public_key” ] = self.conn_data[ “private_key” ].get_public( )

断言(self.conn_data[ “public_key” ].serialize() == “”. join( [chr(x) for x in pub_key_list]))

然后,创建二维码后,用手机扫描后,我们可以通过 websocket 将以下信息发送到 Whatsapp Web:
在这里插入图片描述
这里最重要的参数是secret,然后传递给setSharedSecret。这会将secret分成多个部分,并配置我们需要的所有加密功能,以解密 WhatsApp 流量。

首先,我们可以看到从字符串 ‘e’ 到 Array 的转换以及一些将秘密分成两部分的切片:‘n’,它是前 32 个字节和 ‘a’,它是第 64 个字节的字符到 ‘t’ 的结尾。
在这里插入图片描述
如果我们深入研究函数’’ E.SharedSecret’,我们可以看到它使用了两个参数,即前 32 个字节和来自 QR 生成的私钥:
在这里插入图片描述
在此之后,我们可以更新我们的 python 代码并添加以下行:

self.conn_data[ “shared_secret” ] = self.conn_data[ “private_key” ].get_shared_key(curve25519.Public(self.conn_data[ “secret” ][:32]), lambda key: key)

接下来我们有 80 字节的 expended:
在这里插入图片描述

通过深入我们可以看到该函数使用了 HKDF 函数。所以我们找到了函数 ‘pyhkdf’ 并在我们的代码中使用它以与 WhatsApp 相同的方式扩展密钥:

shared_expended = self.conn_data[ “shared_secret_ex” ] = HKDF (self.conn_data[ “shared_secret” ], 80)

我们接下来有 ​​hmac 验证函数,它将扩展数据作为参数 ‘e’ 并将其分为 3 个参数:

i – shared_expended 的前 32 个字节
r - 从 32 字节开始的 32 字节
o – 64 字节中的 16 字节
还有参数“s”,它是参数“n”和“a”的串联,来自之前的函数,它构成了我们的秘密的一部分。
在这里插入图片描述

然后函数 HmacSha256 将使用参数 ‘r’ 调用,它将使用参数 ‘s’ 对数据进行签名,然后我们将收到 hmac 验证器,该验证器将与切片的 ‘r’ 进行比较’t’ 从 32 字节到 64 字节,而 ‘t’ 是我们在数组格式中的秘密,如前所见。
在这里插入图片描述

在 python 中,它看起来像这样:
check_hmac = HmacSha256(shared_expended[32:64], self.conn_data[ “secret” ][:32] + self.conn_data[ “secret” ][64:]) if check_hmac != self.conn_data[ “secret” ][ 32:64]:引发ValueError(“错误 hmac 不匹配”)
在这里插入图片描述

该块中最后一个与加密相关的函数是“aesCbcDecrypt”,它使用参数“s”,该参数是从字节 64 到 expended shared 结尾的数据和来自秘密的字节 64 的数据之间的连接,以及“i”是前 32bytes 的 expended shared。
在这里插入图片描述
结果是我们稍后将使用的解密密钥。因此,如果我们翻译代码,它将如下所示:
keysDecrypted = AESDecrypt(shared_expended[:32], shared_expended[64:] + self.conn_data[ “secret” ][64:]) 解密后,我们将得到新的 ‘t’,即前 32 个字节,即加密密钥,以及接下来的 32 个字节,即 mac 密钥:
self.conn_data[ “key” ][ “aes_key” ] = keysDecrypted[:32]
self.conn_data[ “key” ][ “mac_key” ] = keysDecrypted[32:64]

整个代码将如下所示:
self.conn_data[ “private_key” ] = curve25519.Private( “”. join( [chr(x) for x in priv_key_list]))
self.conn_data[ “public_key” ] = self.conn_data[ “private_key” ].get_public( )
断言(self.conn_data[ “public_key” ].serialize() == “”. join( [chr(x) for x in pub_key_list]))
self.conn_data[ “secret” ] = base64.b64decode(ref_dict[ “secret” ])
self.conn_data[ “shared_secret” ] = self.conn_data[ “private_key” ].get_shared_key(curve25519.Public(self.conn_data[ “secret”) ” ][:32]), lambda键: 键)
shared_expended = self.conn_data[ “shared_secret_ex” ] = HKDF (self.conn_data[ “shared_secret” ], 80)
check_hmac = HmacSha256(shared_expended[32:64], self.conn_data[ “secret” ][:32] + self.conn_data[ “secret” ][64:])
if check_hmac != self.conn_data[ “secret” ][32:64]:
raise ValueError( “Error hmac mismatch” )
keysDecrypted = AESDecrypt(shared_expended[:32], shared_expended[64:] + self.conn_data[ “secret” ][64:])
self.conn_data[ “key” ][ “aes_key” ] = keysDecrypted[:32]
self.conn_data[ “key” ][ “mac_key” ] = keysDecrypted[32:64]
因此,在我们拥有可以重新生成所需的所有加密参数的代码后,我们可以继续解密过程。
消息分为两部分:标签和数据。我们将使用以下函数来解密消息:
def
解密传入消息(self, message): message = base64.b64decode(message)
message_parts = message.split( “,” , 1)
self.message_tag = message_parts[0]
content = message_parts[1]
check_hmac = hmac_sha256(self.conn_data[ “mac_key” ], content[32:])
if check_hmac != content[:32]:
raise ValueError( “Error hmac mismatch” )
self.decrypted_content = AESDecrypt(self.conn_data[ “aes_key” ], content[32:])
self.decrypted_seralized_content = whastsapp_read(self.decrypted_content, True)
返回self.decrypted_seralized_content
如您所见,我们接收 base64 格式的数据以便轻松复制 Unicode 数据,在 Burp 中,我们可以通过简单地按ctrl+b将数据编码为 base64,并将其传递给函数decrypt_incomping_message。该函数从内容中分离标签,并通过比较hmac_sha256 (self.conn_data[“ mac_key ”], content[32:]) 和 content[:32] 来检查我们的密钥是否可以解密数据。
如果一切正常,我们可以继续使用我们的 aes 密钥和 32 字节内容的 AES 解密步骤。
此内容首先包含 IV ,其大小为 aes 块大小,然后是实际数据:
self.decrypted_content = AESDecrypt(self.conn_data[ “aes_key” ], content[32:])
此函数的输出将是一个 protobuf,如下所示:
在这里插入图片描述
为了将其转换为 json,我们将使用“ whatsapp_read ”函数。
WhatsApp 加密解释(解密传入消息):
为了解密消息,我们首先必须了解 WhatsApp 协议的工作原理,因此我们从调试函数e.decrypt 开始:
在这里插入图片描述

该函数将触发readNode,其代码如下:
在这里插入图片描述

我们将所有代码翻译成 python 来表示相同的函数,如下所示:
在这里插入图片描述
此代码首先从流中读取一个字节并将其移动到char_data。 然后它尝试使用函数read_list_size读取传入流的列表大小。
然后我们得到另一个字节,我们将其称为token_byte,它将传递给read_string,如下所示:
在这里插入图片描述

此代码使用 getToken并将我们的参数作为令牌数组中的位置传递:
在这里插入图片描述
这是whatsapp在通信中发送的第一项,然后我们翻译了函数readString中的所有函数并继续调试:
在这里插入图片描述
接下来您可以在函数 readNode 中看到函数“readAttributes”:
在这里插入图片描述

这个函数只是继续从流中读取更多字节,并通过我们之前在解析“action”标记时看到的相同标记列表来解析它们,它看起来像这样:
在这里插入图片描述

因此,WhatsApp 发送的第二个参数是对信使的实际操作,我们可以看到 WhatsApp 发送了{add:”replay”},这意味着新消息到达。
基本上,我们将继续执行代码,直到到达 readNode 的末尾,这将为我们提供已发送消息的三个部分:

  1. 一些令牌
  2. 一些令牌属性
  3. 编码的 protobuf 消息
    所以,到目前为止,我们通过将所有函数重写为 python 来轻松获得第一和第二部分,这是非常简单的。
    在这里插入图片描述

接下来我们必须处理第三个参数,即 protobuf 并对其进行解密。
要获取 protobuf,我们可以查看 Whatsapp 实现的 protobuf 方案,然后将其复制到一个干净的 .proto 文件中,该文件可以从这里获得:
在这里插入图片描述

索引也可以从 Whatsapp protobuf 模式复制并使用命令编译为 python protobuf 文件,然后我们可以使用protobuf生成的python函数轻松地将protobuf转换为json……
在这里插入图片描述

…结果将如下所示:

在这里插入图片描述

在我们的扩展中实现之后,我们能够解密通信:
在这里插入图片描述

WhatsApp 加密解释(加密传入消息)
加密过程与加密几乎相同,但顺序相反,反转writeNode函数,设定标记和标记属性,我们将它们转换为它在标记列表中的位置,然后以与在readNode 中所做的相同的方式重新实现所有函数,代码非常简单;首先我们检查我们得到的节点的长度是否为三。然后我们将标记属性的数量乘以 2 并将其传递给writeListStart,它将写入列表字符的开头和列表大小(与我们在readNode 中看到的相同),有了开始列表后,我们将进入writeString,它执行与readString相同的事情,因为您可以看到“action”转换为十,即标记索引中的“action”位置,依此类推。
通过这种方式,我们重新构建数据,因此我们解密和加密消息的代码将如下所示:

在这里插入图片描述

为了简化加密过程,还可以更改实际的writeChildren函数并添加了另一个实例类型以使加密更简单:
在这里插入图片描述
在这里插入图片描述
结果就是传入数据的加密和解密。

标签:逆向,--,32,self,secret,key,whatsapp,data,conn
来源: https://blog.csdn.net/beipomamu/article/details/119135898

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有