2009-11-20 154 views
4

我想计算出我想要发送一个UDP报头数据包的校验: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回波(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""" 

感谢。

+1

当你看着'hashlib'的文档时,你看到了什么? – 2009-11-20 11:11:08

回答

8

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

IPv6报头do not contain a checksum

对于ICMP,校验和是“以类型字段开始的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,这意味着至少第一归零校验和字段,并且还可能需要加入“虚拟头”,取决于协议你正在使用。

+1

我想知道如何将函数校验和中的w线改为这个 w =(ord(msg [i])<< 8)+(ord(msg [i + 1])) – 2012-10-01 11:34:55

+0

@Jason,输入什么类型是您的函数校验和所必需的? – 2014-04-03 16:44:16

+0

请注意,该校验和函数假定输入“msg”参数的长度为偶数。奇数长度输入发生异常。这种惯用的解决方案是在校验和计算过程中使用填充字节,而不是作为数据包的一部分进行传输。 (例如,在校验和函数中,检查msg是否是奇数长度,如果是,则将msg重新分配给:msg + =“\ x00”。) – pfa 2014-08-24 15:56:02

4

有一个稳固的校验和功能,可以正确处理Scapy中的字节顺序问题(http://www.secdev.org/projects/scapy,GPLv2)。

在Python 2.7,Scapy的的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你必须处理这个特殊情况。