【发布时间】:2020-08-08 06:07:58
【问题描述】:
我正在尝试对 Quasar RAT protobuf 协议结构进行逆向工程。 Quasar 是一个用 C# 编写的远程管理工具,它是开源的,可以在这里在线找到。 https://github.com/quasar/QuasarRAT
我已经设法扭转了大部分情况,现在我可以从 python 脚本连接到 Quasar 服务器客户端。无论一个问题仍然存在,似乎从客户端发送到服务器的每个字节流都以一个 3 字节字段开头,该字段未在 Quasar 的 protobuf 类中注册。该字段似乎提供了不包括前缀字节的消息长度。正如在此块中可以看到的示例,为大小为 0x2d2 的数组生成的前缀字节流,这些是附加到消息的前缀字节。
0x0A, 0xCF, 0x05
如果我决定在序列化消息之前更改消息字段,那么除了第一个 0x0A 字节之外,这个字节流将会改变。似乎如果我继续将字节附加到消息字段,第二个字节会增长,并且如果我溢出第二个字节(使其达到 0xff 以上) - 它会增加第三个字节并将第二个字节重置为0x80。但是数学对我来说根本没有意义,因为这个字段应该返回数组的大小,但不在任何我可以计算的合理公式下。我知道 protobuf-net 可以生成 PreLengthPrefix 字节来为消息添加前缀,但这里不是这样。
任何帮助将不胜感激。
【问题讨论】:
-
所以它不仅仅是一个“varint”?
-
您能详细说明一下吗?也许我在阅读编码时错过了理解。据我了解,第一个字节 0x0a 表示它是一种字符串?
-
@MarcGravell 嘿,我已经检查了你所说的话,这似乎是有道理的>
-
在 protobuf 字段头(“标签”)中,3 个 LSB 代表线路类型。所以:取你的字段 number (1) 并左移 3 位,给你二进制 1000。现在将它与“长度前缀”的线类型结合起来,即 2(二进制 010),你得到二进制 1010 - 或十六进制:0A。如果您有完整的有效负载,protogen.marcgravell.com/decode 可以引导您完成每一部分。在决定时,显然要反过来:
(tag & 7)给你电线类型,(tag >> 3)给你号码。很明显,这是在 varint 解码之后。 -
好吧,你已经说得很清楚了,如何确定 2 是长度前缀还是字符串,解码器必须猜测吗?
标签: python c# protocol-buffers reverse-engineering protobuf-net