From 03507785e82ee3df0f8f08af6f2578d9dd03afa9 Mon Sep 17 00:00:00 2001 From: Shu-xueyuan <35594064+Shu-xueyuan@users.noreply.github.com> Date: Mon, 22 Jan 2024 16:08:18 +0800 Subject: [PATCH 1/4] Update inet.py Fix UDP packet unable to calculate validity when carrying AH extension header --- scapy/layers/inet.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/scapy/layers/inet.py b/scapy/layers/inet.py index f46ed7f5e4e..d054a702d40 100644 --- a/scapy/layers/inet.py +++ b/scapy/layers/inet.py @@ -755,6 +755,12 @@ def post_build(self, p, pay): elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr): # noqa: E501 ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_TCP, self.underlayer, p) # noqa: E501 p = p[:16] + struct.pack("!H", ck) + p[18:] + elif self.underlayer.name == "AH" and isinstance(self.underlayer.underlayer, IP): + ck = in4_chksum(socket.IPPROTO_TCP, self.underlayer.underlayer, p) + p = p[:16] + struct.pack("!H", ck) + p[18:] + elif self.underlayer.name == "AH" and (conf.ipv6_enabled and isinstance(self.underlayer.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer.underlayer, scapy.layers.inet6._IPv6ExtHdr)): # noqa: E501 + ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_TCP, self.underlayer.underlayer, p) # noqa: E501 + p = p[:16] + struct.pack("!H", ck) + p[18:] else: log_runtime.info( "No IP underlayer to compute checksum. Leaving null." @@ -833,6 +839,18 @@ def post_build(self, p, pay): if ck == 0: ck = 0xFFFF p = p[:6] + struct.pack("!H", ck) + p[8:] + elif self.underlayer.name == "AH" and isinstance(self.underlayer.underlayer, IP): + ck = in4_chksum(socket.IPPROTO_UDP, self.underlayer.underlayer, p) + # According to RFC768 if the result checksum is 0, it should be set to 0xFFFF # noqa: E501 + if ck == 0: + ck = 0xFFFF + p = p[:6] + struct.pack("!H", ck) + p[8:] + elif self.underlayer.name == "AH" and (isinstance(self.underlayer.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer.underlayer, scapy.layers.inet6._IPv6ExtHdr)): # noqa: E501 + ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_UDP, self.underlayer.underlayer, p) # noqa: E501 + # According to RFC2460 if the result checksum is 0, it should be set to 0xFFFF # noqa: E501 + if ck == 0: + ck = 0xFFFF + p = p[:6] + struct.pack("!H", ck) + p[8:] else: log_runtime.info( "No IP underlayer to compute checksum. Leaving null." From 50c07af330f34340d0839d9ca8079e460d9080b8 Mon Sep 17 00:00:00 2001 From: Shu-xueyuan <35594064+Shu-xueyuan@users.noreply.github.com> Date: Fri, 22 Mar 2024 10:27:45 +0800 Subject: [PATCH 2/4] Update inet.py --- scapy/layers/inet.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scapy/layers/inet.py b/scapy/layers/inet.py index d054a702d40..325df766075 100644 --- a/scapy/layers/inet.py +++ b/scapy/layers/inet.py @@ -755,10 +755,10 @@ def post_build(self, p, pay): elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr): # noqa: E501 ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_TCP, self.underlayer, p) # noqa: E501 p = p[:16] + struct.pack("!H", ck) + p[18:] - elif self.underlayer.name == "AH" and isinstance(self.underlayer.underlayer, IP): + elif self.underlayer and self.underlayer.name == "AH" and isinstance(self.underlayer.underlayer, IP): ck = in4_chksum(socket.IPPROTO_TCP, self.underlayer.underlayer, p) p = p[:16] + struct.pack("!H", ck) + p[18:] - elif self.underlayer.name == "AH" and (conf.ipv6_enabled and isinstance(self.underlayer.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer.underlayer, scapy.layers.inet6._IPv6ExtHdr)): # noqa: E501 + elif self.underlayer and self.underlayer.name == "AH" and ((conf.ipv6_enabled and isinstance(self.underlayer.underlayer, scapy.layers.inet6.IPv6)) or isinstance(self.underlayer.underlayer, scapy.layers.inet6._IPv6ExtHdr)): # noqa: E501 ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_TCP, self.underlayer.underlayer, p) # noqa: E501 p = p[:16] + struct.pack("!H", ck) + p[18:] else: @@ -839,13 +839,13 @@ def post_build(self, p, pay): if ck == 0: ck = 0xFFFF p = p[:6] + struct.pack("!H", ck) + p[8:] - elif self.underlayer.name == "AH" and isinstance(self.underlayer.underlayer, IP): + elif self.underlayer and self.underlayer.name == "AH" and isinstance(self.underlayer.underlayer, IP): ck = in4_chksum(socket.IPPROTO_UDP, self.underlayer.underlayer, p) # According to RFC768 if the result checksum is 0, it should be set to 0xFFFF # noqa: E501 if ck == 0: ck = 0xFFFF p = p[:6] + struct.pack("!H", ck) + p[8:] - elif self.underlayer.name == "AH" and (isinstance(self.underlayer.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer.underlayer, scapy.layers.inet6._IPv6ExtHdr)): # noqa: E501 + elif self.underlayer and self.underlayer.name == "AH" and (isinstance(self.underlayer.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer.underlayer, scapy.layers.inet6._IPv6ExtHdr)): # noqa: E501 ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_UDP, self.underlayer.underlayer, p) # noqa: E501 # According to RFC2460 if the result checksum is 0, it should be set to 0xFFFF # noqa: E501 if ck == 0: From a5fa87dce6b779a55f74d67a1711301d9c4d6e0a Mon Sep 17 00:00:00 2001 From: Shu-xueyuan <35594064+Shu-xueyuan@users.noreply.github.com> Date: Fri, 22 Mar 2024 10:41:35 +0800 Subject: [PATCH 3/4] Update inet.uts --- test/scapy/layers/inet.uts | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/test/scapy/layers/inet.uts b/test/scapy/layers/inet.uts index 5b98c1c74f3..3b5408f2bb5 100644 --- a/test/scapy/layers/inet.uts +++ b/test/scapy/layers/inet.uts @@ -396,10 +396,29 @@ assert pkt.options[0][1] == (b'\xe3\xa0,\xdc\xe4\xae\x87\x18\xad{\xab\xd0b\x12\x assert TCP(bytes(pkt)).options[0][0] == "MD5" = IP, TCP & UDP checksums (these tests highly depend on default values) + +def transferPacket(pkt): + packet = hexdump(pkt, dump=True).split('\n') + packet = list(map(lambda x: x.split(" ")[1], packet)) + return " ".join(packet).strip().split(" ") + pkt = IP() / TCP() bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x7ccd and bpkt.payload.chksum == 0x917c +Ah_dicts = {'nh': 6, 'payloadlen': 2, 'reserved': 0, 'spi': 1, 'seq': 0, 'icv': b'\x00\x00\x00\x00'} +pkt = IP(proto=51) / AH(**Ah_dicts) / TCP() +bpkt = IP(raw(pkt)) +assert bpkt.chksum == 0x7c90 +packetStr = transferPacket(pkt) +tcpCheckSum = int("".join(packetStr[-4:-2]), 16) +assert tcpCheckSum == 0x917c + +pkt = IPv6(nh=51) / AH(**Ah_dicts) / TCP() +packetStr = transferPacket(pkt) +tcpCheckSum = int("".join(packetStr[-4:-2]), 16) +assert tcpCheckSum == 0x8f7d + pkt = IP(len=40) / TCP() bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x7ccd and bpkt.payload.chksum == 0x917c @@ -412,6 +431,18 @@ pkt = IP() / TCP() / ("A" * 10) bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x7cc3 and bpkt.payload.chksum == 0x4b2c +pkt = IP(proto=51) / AH(**Ah_dicts) / TCP() / ("A" * 10) +bpkt = IP(raw(pkt)) +assert bpkt.chksum == 0x7c86 +packetStr = transferPacket(pkt) +tcpCheckSum = int("".join(packetStr[-14:-12]), 16) +assert tcpCheckSum == 0x4b2c + +pkt = IPv6(nh=51) / AH(**Ah_dicts) / TCP() / ("A" * 10) +packetStr = transferPacket(pkt) +tcpCheckSum = int("".join(packetStr[-14:-12]), 16) +assert tcpCheckSum == 0x492d + pkt = IP(len=50) / TCP() / ("A" * 10) bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x7cc3 and bpkt.payload.chksum == 0x4b2c @@ -424,6 +455,13 @@ pkt = IP(options=[IPOption_RR()]) / TCP() / ("A" * 10) bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x70bc and bpkt.payload.chksum == 0x4b2c +pkt = IP(proto=51, options=[IPOption_RR()]) / AH(**Ah_dicts) / TCP() / ("A" * 10) +bpkt = IP(raw(pkt)) +assert bpkt.chksum == 0x707f +packetStr = transferPacket(pkt) +tcpCheckSum = int("".join(packetStr[-14:-12]), 16) +assert tcpCheckSum == 0x4b2c + pkt = IP(len=54, options=[IPOption_RR()]) / TCP() / ("A" * 10) bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x70bc and bpkt.payload.chksum == 0x4b2c @@ -436,10 +474,30 @@ pkt = IP(options=[IPOption_Timestamp()]) / TCP() / ("A" * 10) bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x2caa and bpkt.payload.chksum == 0x4b2c +pkt = IP(proto=51, options=[IPOption_Timestamp()]) / AH(**Ah_dicts) / TCP() / ("A" * 10) +bpkt = IP(raw(pkt)) +assert bpkt.chksum == 0x2c6d +packetStr = transferPacket(pkt) +tcpCheckSum = int("".join(packetStr[-14:-12]), 16) +assert tcpCheckSum == 0x4b2c + pkt = IP() / UDP() bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x7cce and bpkt.payload.chksum == 0x0172 +Ah_dicts = {'nh': 17, 'payloadlen': 2, 'reserved': 0, 'spi': 1, 'seq': 0, 'icv': b'\x00\x00\x00\x00'} +pkt = IP(proto=51) / AH(**Ah_dicts) / UDP() +bpkt = IP(raw(pkt)) +assert bpkt.chksum == 0x7c9c +packetStr = transferPacket(pkt) +udpCheckSum = int("".join(packetStr[-2:]), 16) +assert udpCheckSum == 0x0172 + +pkt = IPv6(nh=51) / AH(**Ah_dicts) / UDP() +packetStr = transferPacket(pkt) +udpCheckSum = int("".join(packetStr[-2:]), 16) +assert udpCheckSum == 0xff72 + pkt = IP(len=28) / UDP() bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x7cce and bpkt.payload.chksum == 0x0172 @@ -455,6 +513,18 @@ pkt = IP() / UDP() / ("A" * 10) bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x7cc4 and bpkt.payload.chksum == 0xbb17 +pkt = IP(proto=51) / AH(**Ah_dicts) / UDP() / ("A" * 10) +bpkt = IP(raw(pkt)) +assert bpkt.chksum == 0x7c92 +packetStr = transferPacket(pkt) +udpCheckSum = int("".join(packetStr[-12:-10]), 16) +assert udpCheckSum == 0xbb17 + +pkt = IPv6(nh=51) / AH(**Ah_dicts) / UDP() / ("A" * 10) +packetStr = transferPacket(pkt) +udpCheckSum = int("".join(packetStr[-12:-10]), 16) +assert udpCheckSum == 0xb918 + pkt = IP(len=38) / UDP() / ("A" * 10) bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x7cc4 and bpkt.payload.chksum == 0xbb17 @@ -467,6 +537,13 @@ pkt = IP(options=[IPOption_RR()]) / UDP() / ("A" * 10) bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x70bd and bpkt.payload.chksum == 0xbb17 +pkt = IP(proto=51, options=[IPOption_RR()]) / AH(**Ah_dicts) / UDP() / ("A" * 10) +bpkt = IP(raw(pkt)) +assert bpkt.chksum == 0x708b +packetStr = transferPacket(pkt) +udpCheckSum = int("".join(packetStr[-12:-10]), 16) +assert udpCheckSum == 0xbb17 + pkt = IP(len=42, options=[IPOption_RR()]) / UDP() / ("A" * 10) bpkt = IP(raw(pkt)) assert bpkt.chksum == 0x70bd and bpkt.payload.chksum == 0xbb17 From 45aee45ae81a3f46b800b0902ae66b6bbf1e9cba Mon Sep 17 00:00:00 2001 From: Shu-xueyuan <35594064+Shu-xueyuan@users.noreply.github.com> Date: Wed, 17 Apr 2024 10:55:22 +0800 Subject: [PATCH 4/4] Update inet.py --- scapy/layers/inet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scapy/layers/inet.py b/scapy/layers/inet.py index 325df766075..24464f7ccc9 100644 --- a/scapy/layers/inet.py +++ b/scapy/layers/inet.py @@ -755,7 +755,7 @@ def post_build(self, p, pay): elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr): # noqa: E501 ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_TCP, self.underlayer, p) # noqa: E501 p = p[:16] + struct.pack("!H", ck) + p[18:] - elif self.underlayer and self.underlayer.name == "AH" and isinstance(self.underlayer.underlayer, IP): + elif self.underlayer and self.underlayer.name == "AH" and isinstance(self.underlayer.underlayer, IP): # noqa: E501 ck = in4_chksum(socket.IPPROTO_TCP, self.underlayer.underlayer, p) p = p[:16] + struct.pack("!H", ck) + p[18:] elif self.underlayer and self.underlayer.name == "AH" and ((conf.ipv6_enabled and isinstance(self.underlayer.underlayer, scapy.layers.inet6.IPv6)) or isinstance(self.underlayer.underlayer, scapy.layers.inet6._IPv6ExtHdr)): # noqa: E501 @@ -839,7 +839,7 @@ def post_build(self, p, pay): if ck == 0: ck = 0xFFFF p = p[:6] + struct.pack("!H", ck) + p[8:] - elif self.underlayer and self.underlayer.name == "AH" and isinstance(self.underlayer.underlayer, IP): + elif self.underlayer and self.underlayer.name == "AH" and isinstance(self.underlayer.underlayer, IP): # noqa: E501 ck = in4_chksum(socket.IPPROTO_UDP, self.underlayer.underlayer, p) # According to RFC768 if the result checksum is 0, it should be set to 0xFFFF # noqa: E501 if ck == 0: