Scapy TCP Checksum Recalculation Odd Behavior

I am trying to do TCP ACK substitution. I sniff one ACK packet from the pcap file and send it in a loop incrementing its ACK number as well as another parameter field.

Forced part: (Prespoofing)

from scapy.all import *
from struct import unpack, pack
pkt = sniff(offline="mptcpdemo.pcap", filter="tcp", count=15)
i=6
while True:
    ack_pkt = pkt[i]
    if ack_pkt.sprintf('%TCP.flags%') == 'A':
        break
    i+=1
del ack_pkt.chksum
del ack_pkt[TCP].chksum
print ack_pkt.chksum, ack_pkt[TCP].chksum
hex2pkt = ack_pkt.__class__

      

Spoofing part: (not optimized)

count=1
while count<5:
    ack_pkt[TCP].ack += 1
    pkt_hex = str(ack_pkt)
    rest = pkt_hex[:-4]
    last_4_bit = unpack('!I',pkt_hex[-4:])[0]
    new_hex_pkt = rest + pack('>I',(last_4_bit+1))
    new_pkt=hex2pkt(new_hex_pkt)    
    #sendp(new_pkt, verbose=0)
    print new_pkt.chksum, new_pkt[TCP].chksum
    count+=1

      

The output looks like this: (What's changing)

None None
27441 60323
27441 58895
27441 57467
27441 56039

      

After sending, the average time between two packets is about 15ms. (For 1000 packets) When I check it with Wireshark

, it shows the "checksum is correct" for the first packet and "wrong" for the others.

Spoofing Part: (slightly optimized)

pkt_hex=str(ack_pkt)
rest1=pkt_hex[:42]
tcp_ack=unpack('!I',pkt_hex[42:46])[0]
rest2=pkt_hex[46:-4]
last_4_bit = unpack('!I',pkt_hex[-4:])[0]
count=1    
while count<5:
    new_hex_pkt = rest1 + pack('>I',(tcp_ack+1)) + rest2 + pack('>I',(last_4_bit+1))
    new_pkt = hex2pkt(new_hex_pkt)
    #sendp(new_pkt, verbose=0)
    print new_pkt.chksum, new_pkt[TCP].chksum
    count+=1

      

The output is this: (which does not change)

None None
27441 61751
27441 61751
27441 61751
27441 61751

      

After sending, the average time between two packets is about 10ms. (For 1000 packages)

The checksum does not change for the second case. The process is the same. Then what is the problem in the second optimized case? And why is the TCP checksum calculated in the loop incorrect for subsequent packets?

Note:

  • last_4_bit is not a checksum field.
  • I can see ack number

    for packages incrementing in tcpdump.
+3


source to share


1 answer


After extensive testing, I saw that it was del ack_pkt[TCP].checksum

removing the checksum. But when converting to a hex string with str(ack_pkt)

, I think it recalculates the checksum. After trying:

ack_pkt = sniff(offline="mptcpdemo.pcap", filter="tcp", count=15)[14]
del ack_pkt[TCP].chksum
print ack_pkt[TCP].chksum
print str(ack_pkt)

      



He 1st outputs the checksum as None

. But when printing the hex string, I can see that the checksum field is nonzero and contains the actual recalculated checksum.

In the unoptimized code inside the loop, the packet is converted to a hexadecimal string and therefore rereads the checksum every time. But in the optimized version, the transformation is outside the loop and therefore only carries one value.

0


source







All Articles