校验和udp计算python

2024-06-10 23:24:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我要计算要发送的UDP头数据包的校验和:

packetosend = """60 00 00 00 00 24 3a 40 20 02 c0 a8 01 50 00 01 00 00 
00 00 00 00 09 38 20 02 c0 a8 01 50 00 01 00 00 00 00 00 00 09 6f"""

所以我需要加入这个utf-16(不是问题)并计算这个特定包的校验和。我该怎么做?

谢谢!

编辑:是的,这是一个ICMPv6数据包的IPv6头,无论如何,我想知道的是公式,以及它是如何工作的。

我将给出另一个ICMP ping echo(v4)包的示例:

packet = """
08 00 d1 15 76 0c 00 07 bf d3 55 4a ad b5 03 00   // "d1 15" is the packet checksum 
08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17
18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37"""

谢谢。


Tags: 编辑packetping数据包校验utf公式d1
2条回答

在我看来这不像是一个UDP包。它看起来像ICMPv6数据包的IPv6头,但数据包的实际负载丢失。

IPv6头do not contain a checksum

对于ICMP,校验和是“从Type字段开始的ICMP消息的补码和的16位补码。”One's complement arithmetic涉及进位的特殊处理。

def carry_around_add(a, b):
    c = a + b
    return (c & 0xffff) + (c >> 16)

def checksum(msg):
    s = 0
    for i in range(0, len(msg), 2):
        w = ord(msg[i]) + (ord(msg[i+1]) << 8)
        s = carry_around_add(s, w)
    return ~s & 0xffff

为了计算正确的校验和,当然必须从正确的msg开始,这意味着至少要先将校验和字段归零,并且可能还需要添加“虚拟头”,具体取决于您使用的协议。

Scapy(http://www.secdev.org/projects/scapy,GPLv2)中有一个可靠的校验和函数可以正确处理endianness问题。

在Python2.7中,scapy's utils.py:

if struct.pack("H",1) == "\x00\x01": # big endian
    def checksum(pkt):
        if len(pkt) % 2 == 1:
            pkt += "\0"
        s = sum(array.array("H", pkt))
        s = (s >> 16) + (s & 0xffff)
        s += s >> 16
        s = ~s
        return s & 0xffff
else:
    def checksum(pkt):
        if len(pkt) % 2 == 1:
            pkt += "\0"
        s = sum(array.array("H", pkt))
        s = (s >> 16) + (s & 0xffff)
        s += s >> 16
        s = ~s
        return (((s>>8)&0xff)|s<<8) & 0xffff

这对于任何使用IP头校验和(IP、TCP、UDP、ICMP)的协议都是正确的。但是,UDP还有一种特殊情况,即计算为0x0000的校验和应作为0xffff传输。上面的函数不解释这个问题,所以对于UDP,您必须处理这个特殊情况。

相关问题 更多 >