ctf-2011

old assets from capture-the-flag ictf 2011

git clone https://9o.is/git/ctf-2011.git

streams.py

(15967B)


      1 #!/usr/bin/python
      2 #Compiles TCP packets in to associated streams
      3 #Josh Smith
      4 #Rochester Institute of Technology
      5 
      6 from scapy.all import *
      7 from optparse import OptionParser
      8 from subprocess import Popen, PIPE
      9 import os,sys
     10 
     11 conf.verb = 0
     12 
     13 class Stream:
     14     def __init__(self):
     15         self.packets   = []
     16         self.source_ip = None
     17         self.source_port = None
     18         self.dest_ip   = None
     19         self.dest_port = None
     20         self.window    = None
     21         self.isn       = None
     22         self.seq_num   = None
     23         self.ack_num   = None
     24         self.handshake = False
     25         self.raw       = ""
     26         self.content   = ""
     27         self.contains_flag = False
     28     
     29     def summary(self):
     30         return "TCP Stream: "+self.source_ip+':'+str(self.source_port)+ \
     31             ' -> '+self.dest_ip+':'+str(self.dest_port)+ \
     32             ' Length: '+str(len(self.raw))
     33 
     34 class Streams:
     35     def __init__(self, myself=None):
     36         self.filter  = filter
     37         self.streams = []
     38         self.stream  = None
     39         self.myself = myself
     40 
     41     def parse(self, packet):
     42         """Returns the related stream"""
     43         
     44         if len(self.streams) > 10000:
     45             self.streams = self.streams[-10000:]
     46         
     47         if not packet.haslayer(TCP):
     48             return None
     49         
     50         plen = 0
     51         #SYN Packet - New Stream
     52         #print "WINDOW: %s" % str(packet.window)
     53         if packet[TCP].flags == 2:
     54             return self.parse_syn(packet)
     55 
     56         #SYNACK Packet - Response to initial SYN
     57         elif packet[TCP].flags == 18:
     58             return self.parse_synack(packet)
     59                 
     60             #ACK - Possible Response to SYNACK or Data Response
     61         elif packet[TCP].flags == 16:
     62             return self.parse_ack(packet)
     63 
     64             #PSHACK - Possible Server pushing data to client
     65         elif packet[TCP].flags == 24:
     66             return self.parse_pshack(packet)
     67 
     68             #FINACK Packet
     69         elif packet[TCP].flags == 17:
     70             return self.parse_finack(packet)
     71 
     72             #FIN PSH Ack Packet
     73         elif packet[TCP].flags == 25:
     74             return self.parse_finpshack(packet)
     75 
     76             #RST ACK
     77         elif packet[TCP].flags == 20:
     78             return self.parse_rstack(packet)
     79             
     80         else:
     81             return None
     82             #continue
     83 
     84     def parse_syn(self, packet):
     85         #print "SYN - New Stream Seq: %d" % packet[TCP].seq
     86         self.stream = Stream()
     87         self.streams.append(self.stream)
     88         self.stream.packets.append(packet)
     89         self.stream.isn    = packet[TCP].seq
     90         self.stream.seq_num   = packet[TCP].seq
     91         self.stream.source_ip = packet[IP].src
     92         self.stream.source_port = packet[TCP].sport
     93         self.stream.dest_ip   = packet[IP].dst
     94         self.stream.dest_port = packet[TCP].dport
     95         
     96         return self.stream
     97 
     98     def parse_synack(self, packet):
     99         #print "SYN-ACK"
    100         if not self.stream:
    101             #print "No Stream Yet...stray SYNACK"
    102             return None
    103 
    104         for i in range(len(self.streams)):
    105             s = self.streams[i]
    106 
    107             if packet[TCP].ack == (s.packets[0][TCP].seq + 1):
    108                 #print "Response to SYN found"
    109                 self.streams[i].packets.append(packet)
    110                 self.streams[i].seq_num = packet[TCP].seq
    111                 self.streams[i].ack_num = packet[TCP].ack
    112 
    113                 return self.streams[i]
    114         
    115         return None
    116 
    117     def parse_ack(self, packet):
    118         placed = False
    119         #print "ACK"
    120 
    121         if not self.stream:
    122             #print "No Stream Yet...stray ACK"
    123             return 0
    124 
    125         for i in range(len(self.streams)):
    126             plen = 0
    127             s = self.streams[i]
    128             if Raw in s.packets[-1]:
    129                 plen = len(s.packets[-1][Raw])
    130     
    131             if packet[IP].src == s.dest_ip and Raw in packet:
    132                 if packet[TCP].sport == 80:
    133                     data = str(packet[Raw])[str(packet[Raw]).find("\n\n") + 4:]
    134                 else:
    135                     data = str(packet[Raw])
    136 
    137                 s.raw += data
    138 
    139             if not s.handshake and packet[TCP].seq == (s.packets[0][TCP].seq + 1) and packet[TCP].ack == (s.packets[1][TCP].seq + 1):
    140                 #print "Final ACK for handshake found"
    141                 self.streams[i].packets.append(packet)
    142                 self.streams[i].seq_num = packet[TCP].seq
    143                 self.streams[i].ack_num = packet[TCP].seq
    144                 self.streams[i].handshake   = True
    145                 placed = True
    146 
    147                 return self.streams[i]
    148 
    149             elif s.handshake and packet[TCP].ack == (s.packets[-1][TCP].seq + plen):
    150                 #print "Found stream data - ACK"
    151                 self.streams[i].packets.append(packet)
    152                 self.streams[i].seq_num = packet[TCP].seq
    153                 self.streams[i].ack_num = packet[TCP].ack
    154                 placed = True
    155                 
    156                 if packet[IP].src == self.myself:
    157                     self.streams[i].content += '#[#span class=out#]#'+ \
    158                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    159                 elif packet[IP].dst == self.myself:
    160                     self.streams[i].content += '#[#span class=in#]#'+ \
    161                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    162                 else:
    163                     self.streams[i].content += '#[#span class=unknwon#]#'+ \
    164                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    165                 
    166                 return self.streams[i]
    167 
    168             elif s.handshake and packet[TCP].ack == (s.packets[-1][TCP].ack) and packet[TCP].seq == (s.packets[-1][TCP].seq + plen):
    169                 #print "Found stream data - ACK"
    170                 self.streams[i].packets.append(packet)
    171                 self.streams[i].seq_num = packet[TCP].seq
    172                 self.streams[i].ack_num = packet[TCP].ack
    173                 placed = True
    174                 
    175                 if packet[IP].src == self.myself:
    176                     self.streams[i].content += '#[#span class=out#]#'+ \
    177                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    178                 elif packet[IP].dst == self.myself:
    179                     self.streams[i].content += '#[#span class=in#]#'+ \
    180                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    181                 else:
    182                     self.streams[i].content += '#[#span class=unknwon#]#'+ \
    183                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    184                 
    185                 return self.streams[i]
    186 
    187             elif s.handshake and packet[TCP].seq == (s.packets[-1][TCP].ack):
    188                 #print "Found stream data - ACK"
    189                 self.streams[i].packets.append(packet)
    190                 self.streams[i].seq_num = packet[TCP].seq
    191                 self.streams[i].ack_num = packet[TCP].ack
    192                 placed = True
    193                 
    194                 if packet[IP].src == self.myself:
    195                     self.streams[i].content += '#[#span class=out#]#'+ \
    196                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    197                 elif packet[IP].dst == self.myself:
    198                     self.streams[i].content += '#[#span class=in#]#'+ \
    199                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    200                 else:
    201                     self.streams[i].content += '#[#span class=unknwon#]#'+ \
    202                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    203                 
    204                 return self.streams[i]
    205 
    206             elif s.handshake and packet[TCP].seq == (s.packets[-1][TCP].seq):
    207                 #print "Found stream data - ACK"
    208                 self.streams[i].packets.append(packet)
    209                 self.streams[i].seq_num = packet[TCP].seq
    210                 self.streams[i].ack_num = packet[TCP].ack
    211                 placed = True
    212                 
    213                 if packet[IP].src == self.myself:
    214                     self.streams[i].content += '#[#span class=out#]#'+ \
    215                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    216                 elif packet[IP].dst == self.myself:
    217                     self.streams[i].content += '#[#span class=in#]#'+ \
    218                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    219                 else:
    220                     self.streams[i].content += '#[#span class=unknwon#]#'+ \
    221                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    222                 
    223                 return self.streams[i]
    224 
    225         return None
    226 
    227     def parse_pshack(self, packet):
    228         placed = False
    229         #print "PSH-ACK"
    230         if not self.stream:
    231             #print "No Stream Yet...Stray PSH-ACK"
    232             return None
    233 
    234         for i in range(len(self.streams)):
    235             plen = 0
    236             s = self.streams[i]
    237             if Raw in s.packets[-1]:
    238                 plen = len(s.packets[-1][Raw])
    239 
    240             if not s.handshake:
    241                 continue
    242 
    243             if packet[IP].src == s.dest_ip and Raw in packet:
    244                 if packet[TCP].sport == 80:
    245                     data = str(packet[Raw])[str(packet[Raw]).find("\n\n") + 4:]
    246                 else:
    247                     data = str(packet[Raw])
    248 
    249                 s.raw += data
    250 
    251 
    252             if s.handshake and packet[TCP].seq == (s.packets[-1][TCP].seq + plen) and packet[TCP].ack == s.packets[-1][TCP].ack:
    253                 #print "Found stream data - PSHACK"
    254                 self.streams[i].packets.append(packet)
    255                 self.streams[i].seq_num = packet[TCP].seq
    256                 self.streams[i].ack_num = packet[TCP].ack
    257                 placed = True
    258                 
    259                 if packet[IP].src == self.myself:
    260                     self.streams[i].content += '#[#span class=out#]#'+ \
    261                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    262                 elif packet[IP].dst == self.myself:
    263                     self.streams[i].content += '#[#span class=in#]#'+ \
    264                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    265                 else:
    266                     self.streams[i].content += '#[#span class=unknwon#]#'+ \
    267                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    268                 
    269                 return self.streams[i]
    270 
    271             elif s.handshake and packet[TCP].ack == (s.packets[-1][TCP].seq + plen):
    272                 #print "Found stream data - PSHACK"
    273                 self.streams[i].packets.append(packet)
    274                 self.streams[i].seq_num = packet[TCP].seq
    275                 self.streams[i].ack_num = packet[TCP].ack
    276                 placed = True
    277                 
    278                 if packet[IP].src == self.myself:
    279                     self.streams[i].content += '#[#span class=out#]#'+ \
    280                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    281                 elif packet[IP].dst == self.myself:
    282                     self.streams[i].content += '#[#span class=in#]#'+ \
    283                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    284                 else:
    285                     self.streams[i].content += '#[#span class=unknwon#]#'+ \
    286                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    287                 
    288                 return self.streams[i]
    289 
    290             elif (s.handshake and packet[TCP].seq == (s.packets[-1][TCP].seq)) or (s.handshake and packet[TCP].seq == (s.packets[-1][TCP].ack)):
    291                 #print "Found stream data - PSHACK"
    292                 self.streams[i].packets.append(packet)
    293                 placed = True
    294                 
    295                 if packet[IP].src == self.myself:
    296                     self.streams[i].content += '#[#span class=out#]#'+ \
    297                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    298                 elif packet[IP].dst == self.myself:
    299                     self.streams[i].content += '#[#span class=in#]#'+ \
    300                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    301                 else:
    302                     self.streams[i].content += '#[#span class=unknwon#]#'+ \
    303                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    304                 
    305                 return self.streams[i]
    306 
    307         return None
    308 
    309     def parse_finack(self, packet):
    310         placed = False
    311 
    312         if not self.stream:
    313             return 0
    314 
    315         for i in range(len(self.streams)):
    316             plen = 0
    317             s = self.streams[i]
    318             if Raw in s.packets[-1]:
    319                 plen = len(s.packets[-1][Raw])
    320 
    321             if not s.handshake:
    322                 continue
    323 
    324             if s.handshake and packet[TCP].ack == s.packets[-1][TCP].seq or (s.handshake and packet[TCP].seq == s.packets[-1][TCP].ack) or (s.handshake and packet[TCP].seq == s.packets[-1][TCP].seq):
    325                 #print "Found stream data - FINACK"
    326                 self.streams[i].packets.append(packet)
    327                 placed = True
    328                 
    329                 if packet[IP].src == self.myself:
    330                     self.streams[i].content += '#[#span class=out#]#'+ \
    331                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    332                 elif packet[IP].dst == self.myself:
    333                     self.streams[i].content += '#[#span class=in#]#'+ \
    334                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    335                 else:
    336                     self.streams[i].content += '#[#span class=unknwon#]#'+ \
    337                         '\n'.join(map(lambda x: x.rstrip('\r').__repr__()[1:-1], str(packet[TCP].payload).split('\n'))) +'#[#/span#]#'
    338                 
    339                 return self.streams[i]
    340 
    341         return None
    342 
    343     def parse_finpshack(self, packet):
    344         placed = False
    345 
    346         if not self.stream:
    347             return 0
    348 
    349         for i in range(len(self.streams)):
    350             s = self.streams[i]
    351 
    352             if not s.handshake:
    353                 continue
    354 
    355             if s.handshake and packet[TCP].seq == s.packets[-1][TCP].ack:
    356                 self.streams[i].packets.append(packet)
    357                 placed = True
    358                 
    359                 return self.streams[i]
    360 
    361         return None
    362 
    363     def parse_rstack(self, packet):
    364         placed = False
    365 
    366         if not self.stream:
    367             return 0
    368 
    369         for i in range(len(self.streams)):
    370             s = self.streams[i]
    371             if not s.handshake:
    372                 continue
    373 
    374                 if s.handshake and packet[TCP].ack == s.packets[-1][TCP].ack:
    375                    self.streams[i].packets.append(packet)
    376                    placed = True
    377                 
    378                 return self.streams[i]
    379 
    380         return None