You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于WinDivert的TCP数据包校验和计算错误排查求助

TCP校验和计算异常排查求助

我之前标记为已解决的TCP校验和计算代码仅适配特定场景,多数情况下无法正常工作。当前我使用WinDivert捕获TCP数据包,目标是通过计算校验和识别畸形数据包。从WinDivert获取的字节数组为大端字节序,我已查阅TCP校验和相关RFC文档,也针对"若段中待校验的首部与文本字节数为奇数,需在右侧补零"的规则添加了长度校验,但校验和计算仍频繁出错:

  • 无负载的40字节数据包,源IP为172.64.151.73、目的IP为192.168.50.134时计算正确,但地址反转后结果完全错误;
  • 多数带负载的数据包计算结果也不正确。

实现代码

public override ushort ComputeChecksum(byte[] ipv4Header, byte[] transportHeader, byte[] payload)
{
    int pseudoHeaderLength = 12; // Pseudo-header is 12 bytes
    int tcpLength = transportHeader.Length;
    int payloadLength = payload.Length;
    int totalLength = pseudoHeaderLength + tcpLength + payloadLength;
    bool isOddLength = (totalLength % 2 != 0);

    byte[] pseudoHeaderAndTcpSegment = new byte[totalLength + (isOddLength ? 1 : 0)];
    Console.WriteLine($"pseudoHeaderLength:{pseudoHeaderLength} transportHeader.Length:{tcpLength} payloadLength:{payloadLength} totalLength:{totalLength} newTotalLength:{pseudoHeaderAndTcpSegment.Length} OddLength:{isOddLength}");

    // Copy Source IP address (4 bytes)
    Buffer.BlockCopy(ipv4Header, 12, pseudoHeaderAndTcpSegment, 0, 4);
    Console.WriteLine((BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", "));
    Console.WriteLine("");

    // Copy Destination IP address (4 bytes)
    Buffer.BlockCopy(ipv4Header, 16, pseudoHeaderAndTcpSegment, 4, 4);
    Console.WriteLine((BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", "));
    Console.WriteLine("");

    // Zero byte (1 byte)
    pseudoHeaderAndTcpSegment[8] = 0;

    // Protocol (1 byte)
    pseudoHeaderAndTcpSegment[9] = ipv4Header[9];
    Console.WriteLine((BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", ") + " Protocol:" + ipv4Header[9]); // ipv4Header[9] prints 6 like it should
    Console.WriteLine("");

    // TCP length (2 bytes)
    pseudoHeaderAndTcpSegment[10] = (byte)((tcpLength + payloadLength) >> 8);
    pseudoHeaderAndTcpSegment[11] = (byte)(tcpLength & 0xFF);
    Console.WriteLine((BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", "));
    Console.WriteLine("");

    // Make a copy of the transport header to zero out the checksum
    byte[] transportHeaderCopy = new byte[tcpLength];
    Buffer.BlockCopy(transportHeader, 0, transportHeaderCopy, 0, tcpLength);
    transportHeaderCopy[16] = 0; // Zero out the checksum field (16th byte)
    transportHeaderCopy[17] = 0; // Zero out the checksum field (17th byte)
    Console.WriteLine((BitConverter.ToString(transportHeaderCopy).Replace("-", " ") + ", "));
    Console.WriteLine("");

    // Copy the modified TCP header with zeroed checksum field
    Buffer.BlockCopy(transportHeaderCopy, 0, pseudoHeaderAndTcpSegment, 12, tcpLength);
    Console.WriteLine("TCPHeader:" + (BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", "));
    Console.WriteLine("");

    // Copy the payload
    Buffer.BlockCopy(payload, 0, pseudoHeaderAndTcpSegment, 12 + tcpLength, payload.Length);
    if (isOddLength)
    {
        Console.WriteLine("Odd Length adding a zero");
        pseudoHeaderAndTcpSegment[totalLength] = 0;
    }
    Console.WriteLine("Payload:" + (BitConverter.ToString(pseudoHeaderAndTcpSegment).Replace("-", " ") + ", "));
    Console.WriteLine("");

    return ComputeChecksum(pseudoHeaderAndTcpSegment);
}

protected static ushort ComputeChecksum(byte[] data)
{
    int length = data.Length;
    int i = 0;
    long sum = 0;

    while (length > 1)
    {
        sum += BinaryPrimitives.ReadUInt16BigEndian(data.AsSpan(i, 2));
        i += 2;
        length -= 2;

        if (sum > 0xFFFF)
        {
            sum = (sum & 0xFFFF) + (sum >> 16);
        }
    }

    if (length > 0)
    {
        sum += data[i] << 8;
    }

    while ((sum >> 16) != 0)
    {
        sum = (sum & 0xFFFF) + (sum >> 16);
    }

    return (ushort)(~sum);
}

调用代码及调试失败示例

调用代码:

ushort computedTcpChecksum = PacketData.TCPHeader.ComputeChecksum(ipv4HeaderBytes, transportHeaderBytes, payloadBytes);
string newTcpChecksumHex = computedTcpChecksum.ToString("X4");

调试输出:

PacketDetailsForm SrcIp:192.168.50.134 DstIp:192.168.50.1 Length:94 ClonedIpHeaderLength:24064 ThreadId:2
pseudoHeaderLength:12 transportHeader.Length:20 payloadLength:54 totalLength:86 newTotalLength:86 OddLength:False
C0 A8 32 86 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00,

C0 A8 32 86 C0 A8 32 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00,

C0 A8 32 86 C0 A8 32 01 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00,  Protocol:6

C0 A8 32 86 C0 A8 32 01 00 06 00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00,

E2 B6 00 35 38 F9 6A 6F 2D F7 BC D5 50 18 04 02 00 00 00 00,

TCPHeader:C0 A8 32 86 C0 A8 32 01 00 06 00 14 E2 B6 00 35 38 F9 6A 6F 2D F7 BC D5 50 18 04 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00,

Payload:C0 A8 32 86 C0 A8 32 01 00 06 00 14 E2 B6 00 35 38 F9 6A 6F 2D F7 BC D5 50 18 04 02 00 00 00 00 76 37 01 00 00 01 00 00 00 00 00 00 0A 66 75 6E 63 74 69 6F 6E 61 6C 06 65 76 65 6E 74 73 04 64 61 74 61 09 6D 69 63 72 6F 73 6F 66 74 03 63 6F 6D 00 00 01 00 01,

TCP OriginalCheck:58920 E628, OurCheck:48147 BC13 

我已处理奇数长度补零、置零原校验和字段,并按规则计算补码和,但问题仍未解决。单独使用ComputeChecksum(byte[] data)计算IPv4校验和始终正确,可排除该方法问题。尝试调整伪首部中TCP长度字段的字节顺序也无效,怀疑存在大小端问题但无法定位,恳请协助排查问题原因。


内容的提问来源于stack exchange,提问作者UnSure

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:02:02