6
6
from abc import ABC , abstractmethod
7
7
from scapy .all import *
8
8
from hackingscripts import util
9
+ from collections import OrderedDict
9
10
10
11
11
12
class HttpPacket (ABC ):
12
- def __init__ (self , version ):
13
+ def __init__ (self , sock_src , version ):
13
14
self .version = version
14
15
self .headers = util .CaseInsensitiveDict ()
15
16
self .payload = None
17
+ self .socket = sock_src
16
18
17
19
@staticmethod
18
- def parse (data ):
20
+ def parse (sock_src , data ):
19
21
index = data .index (b"\r \n " )
20
22
first_line = data [0 :index + 2 ].decode ()
21
23
matches_req = re .match (HttpRequest .PATTERN .decode (), first_line )
22
24
matches_res = re .match (HttpResponse .PATTERN .decode (), first_line )
23
25
if matches_req :
24
- http_packet = HttpRequest (* matches_req .groups ())
26
+ http_packet = HttpRequest (sock_src , * matches_req .groups ())
25
27
elif matches_res :
26
- http_packet = HttpResponse (* matches_res .groups ())
28
+ http_packet = HttpResponse (sock_src , * matches_res .groups ())
27
29
else :
28
30
return None
29
31
@@ -43,8 +45,8 @@ def get_file_path(self):
43
45
class HttpRequest (HttpPacket ):
44
46
PATTERN = b"([A-Z]+) ([^ ]+) HTTP/([0-9.]+)\r \n "
45
47
46
- def __init__ (self , method , uri , version ):
47
- super ().__init__ (version )
48
+ def __init__ (self , socket , method , uri , version ):
49
+ super ().__init__ (socket , version )
48
50
self .method = method
49
51
self .uri = uri
50
52
@@ -58,8 +60,8 @@ def get_file_path(self):
58
60
class HttpResponse (HttpPacket ):
59
61
PATTERN = b"HTTP/([0-9.]+) ([0-9]+) (.*)\r \n "
60
62
61
- def __init__ (self , version , status_code , status_text ):
62
- super ().__init__ (version )
63
+ def __init__ (self , socket , version , status_code , status_text ):
64
+ super ().__init__ (socket , version )
63
65
self .status_code = int (status_code )
64
66
self .status_text = status_text
65
67
self .response_to = None
@@ -150,7 +152,7 @@ def __repr__(self):
150
152
151
153
class TcpConnections :
152
154
def __init__ (self ):
153
- self .connections = {}
155
+ self .connections = OrderedDict ()
154
156
155
157
def __contains__ (self , item : TcpConnection ):
156
158
return str (item ) in self .connections
@@ -189,7 +191,6 @@ def __init__(self, pcap_path, output_dir="extracted_files/", filters=None):
189
191
self ._packets = None
190
192
191
193
def _open_file (self ):
192
- # self._packets = pcapkit.extract(fin=self.pcap_path, store=False, nofile=True)
193
194
self ._packets = rdpcap (self .pcap_path )
194
195
195
196
def extract_all (self ):
@@ -204,6 +205,15 @@ def extract_all(self):
204
205
205
206
print (f"[+] Extracted: { file_path } { util .human_readable_size (len (packet .payload ))} Bytes" )
206
207
208
+ def __iter__ (self ):
209
+ self ._open_file ()
210
+ http_packets = self ._parse_http_packets ()
211
+ self .iter_filtered_packets = self ._apply_filters (http_packets )
212
+ return iter (self .iter_filtered_packets )
213
+
214
+ def __next__ (self ):
215
+ return next (self .iter_filtered_packets )
216
+
207
217
def _apply_filters (self , packets ):
208
218
filtered_packets = packets
209
219
for f in self .filters :
@@ -238,15 +248,16 @@ def get_http_packet(self, packet_iterator, sock_src, initial_packet):
238
248
buff = (next_packet [TCP ].seq , raw (next_packet [TCP ].payload ))
239
249
# potential TCP ZeroWindowProbe
240
250
continue
241
-
251
+
252
+ # TODO: instead of assertions, we should make sure, the seq. is ascending
242
253
assert next_packet [TCP ].seq > prev_seq
243
254
assert next_packet [IP ].frag == 0
244
255
http_buffer += raw (next_packet [TCP ].payload )
245
256
prev_seq = next_packet [TCP ].seq
246
257
else :
247
258
break
248
259
249
- return HttpPacket .parse (http_buffer )
260
+ return HttpPacket .parse (sock_src , http_buffer )
250
261
251
262
def _parse_http_packets (self ):
252
263
@@ -298,7 +309,7 @@ def _parse_http_packets(self):
298
309
parser .add_argument ("-o" , "--output-dir" , help = "Path to destination directory" , default = "extracted_files/" ,
299
310
dest = "output_dir" )
300
311
parser .add_argument ("-l" , "--list" , help = "List available files only" , default = False , action = "store_true" )
301
- parser .add_argument ("-e" , "--extract" , help = "Extract files (default)" , default = True , action = "store_true" )
312
+ parser .add_argument ("-e" , "--extract" , help = "Extract files (default)" , default = False , action = "store_true" )
302
313
parser .add_argument ("-ec" , "--exclude-codes" , help = "Exclude http status codes, default: 101,304,403,404" ,
303
314
default = "101,304,403,404" , dest = "exclude_codes" )
304
315
parser .add_argument ("-ic" , "--include-codes" , help = "Limit http status codes" , type = str ,
0 commit comments