#!/usr/bin/env python
# CIT CTF damned traffic - working with pcaps - Nibbles - StalkR
# Tries some manipulations over pcap files
from scapy.all import *

# concat payloads (doesn't take offset into account) and write binary file
def concat_payloads(pcap_file, out_file):
  pcap = rdpcap(pcap_file)
  f = open(out_file,'w')
  for p in pcap:
    f.write(str(p.payload))
  f.close()

# reassemble payloads (takes offset into account, so some data overlap) and write binary file
def reassemble_payload(pcap_file, out_file):
  pcap = rdpcap(pcap_file)
  result = ''
  for i in range(len(pcap)):
    data = str(pcap[i].payload)
    offset = pcap[i].frag*8
    if offset>len(result): # never matches with our packets, but still here in case
      print "inserting %i padding at position %i" % (offset-len(result), offset)
      result += '\x00'*(offset-len(result))+data
    else:
      result = result[:offset] + data + result[offset+len(data):]
  open(out_file,'w').write(result)

# maybe some information is hidden in the bytes that are overlapping, extract them
def extract_overlapping_bytes(pcap_file, out_file):
  pcap = rdpcap(pcap_file)
  previous_packet = ''
  length = 0
  result = ''
  for i in range(len(pcap)):
    p = pcap[i]
    offset = pcap[i].frag*8
    if offset < length: # 240 248
      overlap = str(previous_packet.payload)[offset-length:]
      print "Extracting %i overlap bits: %s" % (length-offset, repr(overlap))
      result += overlap
    length = offset+len(p.payload)
    previous_packet = p
  open(out_file,'w').write(result)

# build another pcap with overlapping bits removed (UDP.len field not fixed)
def remove_overlaps(pcap_file, out_file):
  pcap = rdpcap(pcap_file)
  out = []
  for i in range(len(pcap)-1):
    p = pcap[i]
    offset = p.frag*8 # 0
    length = len(p.payload) # 248
    next_offset = pcap[i+1].frag*8 # 240
    remove = offset+length-next_offset
    if remove > 0:
      p = IP(str(p)[:-remove])
      print "Packet %i: removing last %i bytes" % (i, remove)
    else:
      print "Packet %i: not removing anything" % (i)
    out.append(p)
  if len(pcap)>0:
    out.append(pcap[len(pcap)-1])
  wrpcap(out_file, out)

# fixes the length of the UDP.len and clears the MF (more fragments) bit in last packet
def fix_udp_length_and_MF(pcap_file, out_file):
  pcap = rdpcap(pcap_file)
  total_length = 0
  for p in pcap:
    total_length += len(p.payload)
  print "%s: total length = %i" % (pcap_file, total_length)
  pcap[0].payload.len=total_length
  pcap[0].payload.chksum=None
  pcap[0] = IP(str(pcap[0]))
  pcap[len(pcap)-1].flags=0x2
  pcap[len(pcap)-1].chksum=None
  pcap[len(pcap)-1] = IP(str(pcap[len(pcap)-1]))
  wrpcap(out_file, pcap)

files = ['rebuild_0-53-65.pcap', 'rebuild_0-53-154.pcap', 'rebuild_0-129-65.pcap', 'rebuild_0-129-154.pcap', 'rebuild_1-53-65.pcap', 'rebuild_1-53-154.pcap', 'rebuild_1-129-65.pcap', 'rebuild_1-129-154.pcap']
for fe in files:
  f = fe[:-5] # remove .pcap extension
  concat_payloads(fe, f+'.concat')
  reassemble_payload(fe, f+'.reassembled')
  extract_overlapping_bytes(fe, f+'.overlaps')
  remove_overlaps(fe, f+'_nolap.pcap')
  fix_udp_length_and_MF(f+'_nolap.pcap', f+'_nolap_udp.pcap')

