Scapy TCP Checksum Recalculation Odd behaviour

2k Views Asked by At

I'm trying to do a TCP ACK Spoofing. I sniff one ACK packet from a pcap file and send it in a loop incrementing its ACK number as well as another option field.

Sniffing 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: (Non 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 comes like this: (Which is changing)

None None
27441 60323
27441 58895
27441 57467
27441 56039

After sending, The average time gap between two packets is around 15 ms. (For 1000 Packets) When I check it with Wireshark, it shows "checksum is correct" for the 1st packet and "incorrect" for others.

Spoofing Part: (Little bit 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 comes like this: (Which is not changing)

None None
27441 61751
27441 61751
27441 61751
27441 61751

After sending, The average time gap between two packets is around 10 ms. (For 1000 Packets)

The Checksum is not changing for the 2nd case. The process is quite same. Then what is the problem in the 2nd optimized case? And why the TCP checksum calculated in a loop are wrong for subsequent packets?

Note:

  1. last_4_bit is not the checksum field.
  2. I'm able to see the ack number of the packets being incremented in tcpdump.
1

There are 1 best solutions below

0
On BEST ANSWER

After a extended testing, I saw that, del ack_pkt[TCP].checksum deletes the checksum. But while converting to hex string with str(ack_pkt), I guess, 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)

It 1st prints the checksum as None. But while printing the hex string, I'm able to see that the checksum field is non zero and contains the actual recalculated checksum.

In the non-optimized code, inside the loop, the packet is converted to hex-string and hence it's re-calculating the checksum each time. But in the optimized version, conversion is outside the loop and hence it carries one value only.