如何在不发送数据包的情况下计算校验和?

22 投票
5 回答
23683 浏览
提问于 2025-04-16 17:22

我正在使用scapy这个工具,我想创建一个数据包,并计算它的校验和,但不想发送这个数据包。有没有办法做到这一点呢?

谢谢。

5 个回答

2

在scapy/packet.py文件中添加这个补丁:

+    def checksum_silent(self):
+        """
+        Internal method that recalcs checksum without the annoying prints
+        **AFTER old checksums are deleted.**
+        """
+
+        for f in self.fields_desc:
+            if isinstance(f, ConditionalField) and not f._evalcond(self):
+                continue
+            fvalue = self.getfieldval(f.name)
+            if isinstance(fvalue, Packet) or (f.islist and f.holds_packets and type(fvalue) is list):
+                fvalue_gen = SetGen(fvalue,_iterpacket=0)
+                for fvalue in fvalue_gen:
+                    fvalue.checksum_silent()
+        if self.payload:
+            self.payload.checksum_silent()

然后,不要再调用 pkt.show2() 这个函数了,直接调用 pkt.checksum_silent() 就可以了。(记得先执行 del pkt[IP].chksumdel pkt[UDP].chksum 等等,正如之前的回答所示。)

这个函数应该会更快,而且不会有任何输出。(可能还需要去掉其他一些东西;我只是简单地把这段代码拼凑在一起,测试过确保它在计算校验和时不会有输出。)

44

我也试着避免使用show2(),因为它会打印出数据包。我在源代码中找到了一个更好的解决办法:

del packet.chksum
packet = packet.__class__(bytes(packet))

这段代码可以重新生成数据包,并且确保校验和是正确的,而且不会打印任何内容。实际上,这就是show2()在打印之前在后台运行的内容。

14

你需要在创建数据包之后,删除里面的 .chksum 值;然后再调用 .show2() 方法。

>>> from scapy.layers.inet import IP
>>> from scapy.layers.inet import ICMP
>>> from scapy.layers.inet import TCP
>>> target = "10.9.8.7"
>>> ttl = 64
>>> id = 32711
>>> sport = 2927
>>> dport = 80
>>> pak = IP(dst=target, src = "100.99.98.97", ttl=ttl, flags="DF", id=id, len=1200, chksum = 0)/TCP(flags="S", sport=sport, dport=int(dport), options=[('Timestamp',(0,0))], chksum = 0)
>>> del pak[IP].chksum
>>> del pak[TCP].chksum
>>> pak.show2()
###[ IP ]###
  version   = 4L
  ihl       = 5L
  tos       = 0x0
  len       = 1200
  id        = 32711
  flags     = DF
  frag      = 0L
  ttl       = 64
  proto     = tcp
  chksum    = 0x9afd
  src       = 100.99.98.97
  dst       = 10.9.8.7
  \options   \
###[ TCP ]###
     sport     = 2927
     dport     = www
     seq       = 0
     ack       = 0
     dataofs   = 8L
     reserved  = 0L
     flags     = S
     window    = 8192
     chksum    = 0x2c0e
     urgptr    = 0
     options   = [('Timestamp', (0, 0)), ('EOL', None)]
>>>

撰写回答