Как посчитать контрольную сумму пакета без его отправки?

Я использую scapy и хочу создать пакет и вычислить его контрольную сумму, не отправляя его. Есть ли способ сделать это?

Спасибо.


person Dima.Go    schedule 10.05.2011    source источник


Ответы (5)


Вам необходимо удалить значение .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)]
>>>
person This    schedule 20.05.2011
comment
Спасибо. Я нашел другой вариант - преобразовать пакет в строку и воссоздать его, используя эту строку. - person Dima.Go; 24.05.2011
comment
@Дима, спасибо за предложение. Я хотел избежать show2(), потому что весь вывод был ненужным. Возможно, должна быть просто функция пакета recalc. - person Mr. Shickadance; 21.07.2011
comment
@Мистер. Shickadance, вы можете легко отключить stdout на мгновение, переназначив его... например, stdout, null = sys.stdout, open('/dev/null', 'w'); sys.stdout = null. Когда вы закончите, переназначьте снова с помощью sys.stdout = stdout - person This; 21.07.2011
comment
Кажется, я действительно прокомментировал очень похожее решение. Без глушения и прочего... - person Almog Cohen; 11.05.2016
comment
Есть ли способ получить новое поле chksum вместо всего вывода show2()? - person lordlabakdas; 29.12.2016

Я также пытался избежать show2(), потому что он печатает пакет. Я нашел в источнике лучшее решение:

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

Этот код регенерирует пакет с правильной контрольной суммой без какой-либо печати, и на самом деле это то, что show2() запускается в фоновом режиме перед печатью.

person Almog Cohen    schedule 25.07.2012
comment
Реальный и лучший ответ, безусловно. Не пытайтесь извлечь данные из распечатки, которые со временем могут измениться. - person Cukic0d; 10.07.2018
comment
Отличный ответ, спасибо! просто добавил, что вторая строка вызвала у меня значительную и необъяснимую задержку, но поскольку я хотел отправить пакеты, я просто удалил ее, а в процессе отправки пересчитал саму контрольную сумму. Поэтому я использовал del ret_packet.chksum и del ret_packet[UDP].chksum для UDP. - person Shir; 01.01.2020

Добавьте этот патч в 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].chksum и del pkt[UDP].chksum и т. д.), как показано в предыдущем ответе.

Эта функция должна работать быстрее и быть бесшумной. (Также могут быть дополнительные вещи, которые нужно обрезать; я взломал этот код вместе и только проверил, чтобы убедиться, что он молчит с правильной контрольной суммой.)

person K.S.    schedule 24.05.2017

Действительно, функция show2() подсчитывает за вас контрольную сумму, но также распечатывает содержимое пакета по окончании своей работы. Однако у show2() есть небольшой полезный параметр с именем dump. Источник описывает это так:

:param dump: определить, печатает ли он или возвращает строковое значение

Таким образом, установив dump=True, вы можете избежать надоедливого вывода, который функция обеспечивает по умолчанию, и по-прежнему получать нужные вам вычисления.

person Pacopenguin    schedule 10.07.2018
comment
Не пытайтесь извлечь данные из распечатки: это вообще нестабильный API и может быть изменен без предварительного уведомления. - person Cukic0d; 10.07.2018

Вы также можете использовать packet.build(), который возвращает необработанные байты с правильной контрольной суммой. Затем преобразуйте байты в пакет.

>>> import scapy.all as sp
>>> packet = sp.IP(src='127.0.0.1', dst='8.8.8.8')
>>> packet
<IP  src=127.0.0.1 dst=8.8.8.8 |>
>>> sp.IP(packet.build())
<IP  version=4 ihl=5 tos=0x0 len=20 id=1 flags= frag=0 ttl=64 
proto=hopopt chksum=0xebd8 src=127.0.0.1 dst=8.8.8.8 |>
person n.r    schedule 07.07.2019