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