Checksum/CRC Microsoft NDIS数据包逆向工程

Checksum/CRC reverse engineering of Microsoft NDIS packet

我正在尝试解码一个似乎包含 2 字节 CRC/校验和字段的 42 字节数据包

这是在 HLK (WHQL) 测试中发送的 Microsoft NDIS 数据包(类型 IPX)

我已经解码了 NDIS 的大部分内容 header 但我似乎无法弄清楚 CRC/Checksum 算法

45 字节数据包示例(仅用于解释解码字段):

char packet_bytes[] = {
  0x02, 0xe4, 0x55, 0xee, 0x12, 0x56, 0x02, 0x93,
  0x19, 0x40, 0x89, 0x00, 0x00, 0x1f, 0xaa, 0xaa,
  0x03, 0x00, 0x00, 0x00, 0x81, 0x37, 0x4e, 0x44,
  0x49, 0x53, 0x01, 0x49, 0x03, 0x00, 0x98, 0xd4,
  0x58, 0x55, 0x25, 0xf5, 0x39, 0x00, 0x14, 0x00,
  0x00, 0x00, 0x49, 0x4a, 0x4b
};


Raw: 02e455ee1256029319408900001faaaa0300000081374e4449530149030098d4585525f5390014000000494a4b

解码字段:

802.2 ethernet header: (Wireshark decoding)
  02e455ee1256 : Destination
  029319408900 : Source
  001f : Length
  
Logical_link Control: (Wireshark decoding)
  aa : DSAP
  aa : SSAP
  03 : Control
  000000 : Organization
  8137 : Type (Netware IPX/SPX)
  
NDIS header: (my estimation for NDIS decoded fields)
  4e444953 : NDIS ascii String ("NDIS")
  01 : Unknown
  49 : payload counter start (first byte of payload, with increasing value afterwards)
  0300 : Payload length ( = 0003)
  98d4 : test identification number (equal on all packets of the same test)
  5855 : Assumed to be checksum
  25f53900 : Packet counter ( = 0039f525, Increases gradually per packet) 
  14000000 : Payload offset ( = 00000014), offset from start of NDIS header to start of payload
  494a4b : Payload (3 bytes of increasing counter 49,4a,4b)

要尝试理解具有最少数据包字节的校验和算法, 我捕获了最小数据包大小(42 字节)

这些数据包包括上面的 headers 但根本没有负载

并尝试使用 reveng CRC decoder 对它们进行逆向工程,但未能找到任何已知的 CRC 算法

示例 42 字节数据包:

02e455ee1256029319408900001caaaa0300000081374e444953016b000098d495262502000014000000
02e455ee1256029319408900001caaaa0300000081374e44495301a2000098d481ef3802000014000000
02e455ee1256029319408900001caaaa0300000081374e4449530152000098d47f3f3b02000014000000
02e455ee1256029319408900001caaaa0300000081374e44495301d0000098d476c14302000014000000
02e455ee1256029319408900001caaaa0300000081374e44495301f7000098d4539a6602000014000000
02e455ee1256029319408900001caaaa0300000081374e44495301b6000098d444db7502000014000000
02e455ee1256029319408900001caaaa0300000081374e44495301a6000098d431eb8802000014000000
02e455ee1256029319408900001caaaa0300000081374e444953016a000098d40627b402000014000000

逆向 CRC:

reveng.exe -w 16 -s 02e455ee1256029319408900001caaaa0300000081374e444953016b000098d495262502000014000000 02e455ee1256029319408900001caaaa0300000081374e44495301a2000098d481ef3802000014000000 02e455ee1256029319408900001caaaa0300000081374e4449530152000098d47f3f3b02000014000000 02e455ee1256029319408900001caaaa0300000081374e44495301d0000098d476c14302000014000000 02e455ee1256029319408900001caaaa0300000081374e44495301f7000098d4539a6602000014000000 02e455ee1256029319408900001caaaa0300000081374e44495301b6000098d444db7502000014000000 02e455ee1256029319408900001caaaa0300000081374e44495301a6000098d431eb8802000014000000 02e455ee1256029319408900001caaaa0300000081374e444953016a000098d40627b402000014000000
reveng.exe: no models found

仅尝试对 NDIS header 部分进行逆向工程:

4e444953016b000098d495262502000014000000
4e44495301a2000098d481ef3802000014000000
4e4449530152000098d47f3f3b02000014000000
4e44495301d0000098d476c14302000014000000
4e44495301f7000098d4539a6602000014000000
4e44495301b6000098d444db7502000014000000
4e44495301a6000098d431eb8802000014000000
4e444953016a000098d40627b402000014000000

reveng.exe -w 16 -s 4e444953016b000098d495262502000014000000 4e44495301a2000098d481ef3802000014000000 4e4449530152000098d47f3f3b02000014000000 4e44495301d0000098d476c14302000014000000 4e44495301f7000098d4539a6602000014000000 4e44495301b6000098d444db7502000014000000 4e44495301a6000098d431eb8802000014000000 4e444953016a000098d40627b402000014000000
reveng.exe: no models found

如有任何帮助,我们将不胜感激。

这似乎是 Internet 校验和,在 RFC 1071 中描述,是根据 NDIS header 计算的数据包的一部分。

简而言之,需要将header中的所有内容(除了16位校验和字段本身)作为16位值相加,然后将进位(如果有的话)加到最低位结果的16位(从而形成补码和),最后将所有位取反,计算出这个补码和的补码。

对于您列出的示例数据包,手动计算步骤如下。

  1. 给定整个数据包:
02e455ee1256029319408900001faaaa0300000081374e4449530149030098d4585525f5390014000000494a4b
  1. 仅提取 NDIS header 部分,不带负载:
4e4449530149030098d4585525f5390014000000
  1. 拆分为 16 位值:
4e44
4953
0149
0300
98d4
5855
25f5
3900
1400
0000
  1. 用零替换校验和字段:
4e44
4953
0149
0300
98d4
0000
25f5
3900
1400
0000
  1. 将所有这些 16 位值加在一起:
1A7A9
  1. 这里,最低16位为A7A9,算术进位为1。因此,将这些加在一起(作为 16 位字),形成 so-called 的补码和:
  0001
+ A7A9
= A7AA
  1. 现在,反转所有位(应用按位 NOT 运算),得到一个的补码:
~ A7AA
= 5855
  1. 将此校验和放回原位(我们暂时清零):
4e44
4953
0149
0300
98d4
5855
25f5
3900
1400
0000

如果您只想检查校验和,请执行以下操作。

  1. 首先,取原始的 NDIS header(作为 16 位值):
4e44
4953
0149
0300
98d4
5855
25f5
3900
1400
0000
  1. 然后总结所有这些:
1FFFE
  1. 同样,将进位添加到16位LSB部分:
  0001
+ FFFE
= FFFF

如果结果的所有位都是1(即如果结果是FFFF),则检查成功。