3
votes

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
Are the generated packets identical in both approaches, except for the checksum fields?Yoel
@Yoel Yes. All the fields are same except for TCP Checksum.RatDon
Regarding the first approach, does inserting the del statements into the count loop trigger correct recalculation of the non-TCP checksum field?Yoel
@Yoel Nope. I just checked with a live traffic. I'm sniffing each TCP ACK packet. Deleting its tcp checksum. Recalculating its TCP checksum and resending it. The whole thing is captured with tcpdump. After analysing, to my surprise, though the system generated ACK and scapy generated ACK packets are identical, they both have different Checksum. Does scapy generate a wrong checksum?RatDon

1 Answers

0
votes

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.