需要帮助识别位操作技术

时间:2016-12-07 17:08:44

标签: bit-manipulation bytecode pcap bytebuffer online-game

我需要帮助确定以下技术。是一个冗长的阅读,所以请尝试遵循。我的问题是,如果这是一个已知的标准,它是否有一个名称,任何人都可以关注或看到这个。有什么好处。另外,如果你想知道,这与一个长期被遗忘的在线PS2游戏上捕获的数据包有关,而且我是一个试图将其带回来的团队的一部分。

请注意,这不是ip协议所描述的大小,此大小表示与实际有效负载相关,而是用于客户端和服务器消耗。 以下内容描述了如何表示消息的大小。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~

真正的数据包长度为94个字节。 在所有ip协议之后,这些是有效载荷数据上的字节5-6 [CF E0]。 另请注意,我们必须将这两个字节解释为小端格式。因此,我们应该将这两个字节视为

[E0 CF] 我们通过取第一个字节的第一个半字节(4位)从这两个字节中确定数据包类。在这种特殊情况下,这只是0xE。然后,我们将此数据包标识为具有0xE的数据包类。这被确定为会话发起者数据包类。

现在,从剩余的半字节和第二个字节确定数据包长度。首先我们将第二个字节转换为十进制,得到0xCF = 207.该值与实际长度之间的差值为207-94 = 113字节。最初我知道这个字节与数据包长度成正比,但只是有一些偏移量。我不确定这个偏移来自哪里。此外,对于不同的数据包,这种偏移似乎也会改变需要更多的研究。

最终,我发现每个数据包类都有不同的偏移量。因此,我只需要检查同一数据包类中的数据包,以确定该数据包类的偏移量。在这样做时,我创建了一个包含所有报告长度的表(在字节5中),并将其与实际数据包长度进行比较。我发现的是

字节5中几乎所有报告的数据包长度都大于0x80 = 128。 另一个字节中的第二个半字节用作数据包长度的乘数类型 每个数据包类具有相关的最小数据包长度和可以表示的最大数据包长度。对于我正在检查的0xC数据包类,最小数据包大小为18个字节,最大数据包大小约为10 * 128 + 17 = 1297个字节。 这导致以下方法从第五和第六字节包头中提取包长度。首先请注意,我们之前已将数据包类确定为0xE,并且与此数据包类关联的最小数据包大小为15个字节。现在,在这种情况下,取第一个字节[0xE0] = 0的第二个半字节,然后乘以128个字节,0 * 128 = 0个字节。现在将此值添加到第二个字节[0xCF] = 207并减去128.所以0 + 207 - 128 = 79.现在我们需要为此数据包类添加最小数据包大小0xE = 15字节最小数据包大小。所以(0 * 128)+(207-128)-15 = 94.这是报告的真实数据包大小。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~

此公式在20,000个后续数据包上进行了测试,并且可以正常运行。但为什么只是为了表明随后的消息大小而陷入困境呢?我认为这是一种加密形式,但邮件的其余部分根本没有加密。该公式被理解,但我没有看到任何好处。我想也许是一种优化数据包大小的方法,只使用一个字节传递一个大于255的数字,但只能保存一个字节,抛出另一个字节产生最大值65,535,所以为什么不抛出另一个字节进入字节流。我确信一个额外的字节不会对网络产生很大的影响,所以可能是什么目的。我想也许其他人会看到什么缺失或与某种记录的标准,协议,模式,技术或某些地方记录的内容有关。

另外,我并不认为上面的公式是由另一个团队成员完成的。

1 个答案:

答案 0 :(得分:0)

我最好的猜测是接收器使用某种形式的可变长度base128编码,如LEB128

但在这种情况下,发送者知道实际最大大小适合11位,迫使编码使用2个字节,并使高字节重载为“类”。这使得标题大小和构造时间不变。接收方可以掩盖类并通过标准解码器运行它。

发送:

len -= minlen[class]
byte[5]=(len&0x7F)|0x80;
byte[6]=(len>>7)|(class<<4);

接收:

class = byte[6]>>4;
byte[6]&=0xF;
len = decode(&byte[5]) + minlen[class];

其中:

int decode(byte* data) {
  int v=*data&0x7F;
  while (*data & 0x80) {
    data++;
    v+=*data&0x7F;
  }
  return v;
}  

另一种可能性是字节[5]被签名,长度由
重建 (int8_t)byte[5] + 128*((byte[6]&0xF)+1) + minlen[byte[6]>>4];
    但我想不出有任何理由以这种方式构建它。