Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Protobuf网络无法识别的流前缀_Python_C#_Protocol Buffers_Reverse Engineering_Protobuf Net - Fatal编程技术网

Python Protobuf网络无法识别的流前缀

Python Protobuf网络无法识别的流前缀,python,c#,protocol-buffers,reverse-engineering,protobuf-net,Python,C#,Protocol Buffers,Reverse Engineering,Protobuf Net,我正试图对类星体RAT协议结构进行反向工程。 Quasar是一个用C#编写的远程管理工具,它是开源的,可以在这里在线找到。 我已经设法扭转了大部分,现在可以从python脚本连接到Quasar服务器客户端。有一个问题仍然悬而未决,似乎从客户端发送到服务器的每个字节流都以一个3字节字段开始,该字段未在Quasar的protobuf类中注册。此字段似乎提供不包括前缀字节的消息长度。在该块中可以看到,例如为大小为0x2d2的数组生成的前缀字节流,这些是附加到消息的前缀字节 0x0A, 0xCF, 0

我正试图对类星体RAT协议结构进行反向工程。 Quasar是一个用C#编写的远程管理工具,它是开源的,可以在这里在线找到。

我已经设法扭转了大部分,现在可以从python脚本连接到Quasar服务器客户端。有一个问题仍然悬而未决,似乎从客户端发送到服务器的每个字节流都以一个3字节字段开始,该字段未在Quasar的protobuf类中注册。此字段似乎提供不包括前缀字节的消息长度。在该块中可以看到,例如为大小为0x2d2的数组生成的前缀字节流,这些是附加到消息的前缀字节

0x0A, 0xCF, 0x05
如果我决定在序列化消息之前更改消息字段,则此字节流将更改,但第一个0x0A字节除外。似乎如果我继续向消息字段追加字节,第二个字节会增长,如果我溢出第二个字节(使其达到0xff),它将增加第三个字节,并将第二个字节重置为0x80。但是这个数学对我来说毫无意义,因为这个字段应该返回数组的大小,但在我可以计算的任何合理公式下都没有。我知道protobuf net可以生成PreLengthPrefix字节,以消息的长度作为前缀,但这里的情况并非如此


任何帮助都将不胜感激。

编码规则如下:

基本上,每个字段都编码为字段头(也称为“标记”),后跟一个有效负载。字段标题是一个“变量”(参见编码指南),其值是由字段编号和导线类型组成的整数。导线类型是3个最低有效位,字段号是其余的(移位3位)。对于0x0A(二进制1010),导线类型为2(二进制010),字段号为1

如何处理有效负载取决于导线类型。对于导线类型2(长度前缀),您应该期待下一个:

  • 一个变量,表示有效负载的长度(以字节为单位),然后
  • 实际有效负载的多少字节
不幸的是,protobuf在没有模式的情况下是不明确的,因此知道有长度前缀的数据并不能告诉您数据是什么;长度前缀的有效负载可以是:

  • UTF-8字符串
  • 原始BLOB(
    字节
  • 子消息
  • 某种基本类型的“压缩”数组(整数/浮点数等)——记住长度前缀是字节数,而不是元素数;这些元素甚至不一定是固定大小的(它们本身可以是变量)


在许多方面,wire类型的目的不是告诉您如何解释数据,而是告诉您如何跳过(或只是逐字存储)如果字段不是您所知道的字段,则返回该字段。例如,其他人正在使用API的V3,而您只将架构更新为V2;他们向您的V2 API发送V3消息;V3有您不关心的额外字段-反序列化器在命中字段时不需要中断,因此导线类型告诉它如何忽略该字段(即,查找下一个字段的规则是什么)。否则,我们可以只使用模式信息,而不在有效负载中存储导线类型(尽管它也可以通过“打包”对重复的原始数据进行优化)数组-由序列化程序决定是否进行编码,例如长度前缀与大量字段头/值对。

因此它不仅仅是一个“变量”?你能详细解释一下吗?也许我在读编码的时候没有理解。因为我知道第一个字节0x0a表示它是字符串的一种类型?@MarcGravell嘿,我已经检查了你所说的,我似乎明白为什么0x0a的前缀应该表示字段1-类型stringin protobuf字段头(“标记”),3个LSB代表导线类型。因此:取字段号(1)并左移这3位,得到二进制1000。现在将其与导线类型“长度前缀”相结合,即2(二进制010),得到二进制1010-或十六进制:0A。如果你有一个完整的有效载荷,可以引导你遍历每一块。在决定时,显然要颠倒这一点:
(tag&7)
给出了导线类型,
(tag>>3)
给你数字。这显然是在varint解码之后。好吧,你已经说得很清楚了,如何确定2是长度前缀还是字符串,这是解码器必须进行的猜测?