1- from argparse import ArgumentParser
2- from netaddr import IPNetwork , IPRange , IPGlob
3- from Interlace .lib .core .output import OutputHelper , Level
41import os .path
5- from os import access , W_OK
62import sys
7- from re import compile
8- from random import sample , choice
3+ from argparse import ArgumentParser
94from math import ceil
5+ from random import sample , choice
6+
7+ from netaddr import IPNetwork , IPRange , IPGlob
8+
9+ from Interlace .lib .threader import Task
1010
1111
1212class InputHelper (object ):
@@ -78,134 +78,148 @@ def _get_cidr_to_ips(cidr_range):
7878 return ips
7979
8080 @staticmethod
81- def _replace_variable_for_commands (commands , variable , replacements ):
82- tmp_commands = set ()
81+ def _process_port (port_type ):
82+ if "," in port_type :
83+ return port_type .split ("," )
84+ elif "-" in port_type :
85+ tmp = port_type .split ("-" )
86+ begin_range = int (tmp [0 ])
87+ end_range = int (tmp [1 ])
88+ if begin_range >= end_range :
89+ raise Exception ("Invalid range provided" )
90+ return list (range (begin_range , end_range + 1 ))
91+ return [port_type ]
8392
84- test = list ()
85-
86- for replacement in replacements :
87- for command in commands :
88- test .append (str (command ).replace (variable , str (replacement )))
89-
90- tmp_commands .update (test )
91- return tmp_commands
92-
9393 @staticmethod
94- def _replace_variable_array (commands , variable , replacement ):
95- tmp_commands = set ()
96- counter = 0
94+ def _pre_process_commands (command_list , task_name , is_global_task = True ):
95+ """
96+ :param command_list:
97+ :param task_name: all tasks have 'scope' and all scopes have unique names, global scope defaults ''
98+ :param is_global_task: when True, signifies that all global tasks are meant to be run concurrently
99+ :return: list of possibly re-adjusted commands
100+ """
101+ task_block = []
102+ sibling = None
103+ global_task = None
104+ for command in command_list :
105+ command = str (command ).strip ()
106+ if not command :
107+ continue
108+ # the start or end of a command block
109+ if command .startswith ('_block:' ) and command .endswith ('_' ):
110+ new_task_name = command .split ('_block:' )[1 ][:- 1 ].strip ()
111+ # if this is the end of a block, then we're done
112+ if task_name == new_task_name :
113+ return task_block
114+ # otherwise pre-process all the commands in this new `new_task_name` block
115+ for task in InputHelper ._pre_process_commands (command_list , new_task_name , False ):
116+ task_block .append (task )
117+ sibling = task
118+ continue
119+ else :
120+ # if a blocker is encountered, all commands following the blocker must wait until the last
121+ # command in the block is executed. All block commands are synchronous
122+ if command == '_blocker_' :
123+ global_task = sibling
124+ continue
125+ task = Task (command )
126+ # if we're in the global scope and there was a previous _blocker_ encountered, we wait for the last
127+ # child of the block
128+ if is_global_task and global_task :
129+ task .wait_for (global_task .get_lock ())
130+ # all but the first command in a block scope wait for its predecessor
131+ elif sibling and not is_global_task :
132+ task .wait_for (sibling .get_lock ())
133+ task_block .append (task )
134+ sibling = task
135+ return task_block
97136
98- test = list ()
137+ @staticmethod
138+ def _pre_process_hosts (host_ranges , destination_set , arguments ):
139+ for host in host_ranges :
140+ host = host .replace (" " , "" )
141+ for ips in host .split ("," ):
142+ # check if it is a domain name
143+ if ips .split ("." )[- 1 ][0 ].isalpha ():
144+ destination_set .add (ips )
145+ continue
146+ # checking for CIDR
147+ if not arguments .nocidr and "/" in ips :
148+ destination_set .update (InputHelper ._get_cidr_to_ips (ips ))
149+ # checking for IPs in a range
150+ elif "-" in ips :
151+ destination_set .update (InputHelper ._get_ips_from_range (ips ))
152+ # checking for glob ranges
153+ elif "*" in ips :
154+ destination_set .update (InputHelper ._get_ips_from_glob (ips ))
155+ else :
156+ destination_set .add (ips )
99157
100- if not variable in sample (commands , 1 )[0 ]:
101- return commands
158+ @staticmethod
159+ def _replace_variable_with_commands (commands , variable , replacements ):
160+ def add_task (t , item_list ):
161+ if t not in set (item_list ):
162+ item_list .append (t )
102163
164+ tasks = []
103165 for command in commands :
104- test .append (str (command ).replace (variable , str (replacement [counter ])))
105- counter += 1
166+ for replacement in replacements :
167+ if command .name ().find (variable ) != - 1 :
168+ new_task = command .clone ()
169+ new_task .replace (variable , replacement )
170+ add_task (new_task , tasks )
171+ else :
172+ add_task (command , tasks )
173+ return tasks
106174
107- tmp_commands .update (test )
108- return tmp_commands
175+ @staticmethod
176+ def _replace_variable_array (commands , variable , replacement ):
177+ if variable not in sample (commands , 1 )[0 ]:
178+ return
109179
180+ for counter , command in enumerate (commands ):
181+ command .replace (variable , str (replacement [counter ]))
110182
111183 @staticmethod
112184 def process_commands (arguments ):
113- commands = set ()
185+ commands = list ()
114186 ranges = set ()
115187 targets = set ()
116188 exclusions_ranges = set ()
117189 exclusions = set ()
118- final_commands = set ()
119- output = OutputHelper (arguments )
120190
121191 # removing the trailing slash if any
122- if arguments .output :
123- if arguments .output [- 1 ] == "/" :
124- arguments .output = arguments .output [:- 1 ]
192+ if arguments .output and arguments .output [- 1 ] == "/" :
193+ arguments .output = arguments .output [:- 1 ]
125194
126195 if arguments .port :
127- if "," in arguments .port :
128- ports = arguments .port .split ("," )
129- elif "-" in arguments .port :
130- tmp_ports = arguments .port .split ("-" )
131- if int (tmp_ports [0 ]) >= int (tmp_ports [1 ]):
132- raise Exception ("Invalid range provided" )
133- ports = list (range (int (tmp_ports [0 ]), int (tmp_ports [1 ]) + 1 ))
134- else :
135- ports = [arguments .port ]
196+ ports = InputHelper ._process_port (arguments .port )
136197
137198 if arguments .realport :
138- if "," in arguments .realport :
139- real_ports = arguments .realport .split ("," )
140- elif "-" in arguments .realport :
141- tmp_ports = arguments .realport .split ("-" )
142- if int (tmp_ports [0 ]) >= int (tmp_ports [1 ]):
143- raise Exception ("Invalid range provided" )
144- real_ports = list (range (int (tmp_ports [0 ]), int (tmp_ports [1 ]) + 1 ))
145- else :
146- real_ports = [arguments .realport ]
199+ real_ports = InputHelper ._process_port (arguments .realport )
147200
148201 # process targets first
149202 if arguments .target :
150203 ranges .add (arguments .target )
151204 else :
152- targetFile = arguments .target_list
205+ target_file = arguments .target_list
153206 if not sys .stdin .isatty ():
154- targetFile = sys .stdin
155- for target in targetFile :
156- if target .strip ():
157- ranges .add (target .strip ())
207+ target_file = sys .stdin
208+ ranges .update ([target .strip () for target in target_file if target .strip ()])
158209
159210 # process exclusions first
160211 if arguments .exclusions :
161212 exclusions_ranges .add (arguments .exclusions )
162213 else :
163214 if arguments .exclusions_list :
164215 for exclusion in arguments .exclusions_list :
165- exclusions_ranges .add (target .strip ())
166-
167- # removing elements that may have spaces (helpful for easily processing comma notation)
168- for target in ranges :
169- target = target .replace (" " , "" )
170-
171- for ips in target .split ("," ):
172-
173- # check if it is a domain name
174- if ips .split ("." )[- 1 ][0 ].isalpha ():
175- targets .add (ips )
176- continue
177- # checking for CIDR
178- if not arguments .nocidr and "/" in ips :
179- targets .update (InputHelper ._get_cidr_to_ips (ips ))
180- # checking for IPs in a range
181- elif "-" in ips :
182- targets .update (InputHelper ._get_ips_from_range (ips ))
183- # checking for glob ranges
184- elif "*" in ips :
185- targets .update (InputHelper ._get_ips_from_glob (ips ))
186- else :
187- targets .add (ips )
216+ exclusion = exclusion .strip ()
217+ if exclusion :
218+ exclusions .add (exclusion )
188219
189220 # removing elements that may have spaces (helpful for easily processing comma notation)
190- for exclusion in exclusions_ranges :
191- exclusion = exclusion .replace (" " , "" )
192-
193- for ips in exclusion .split ("," ):
194- # check if it is a domain name
195- if ips .split ("." )[- 1 ][0 ].isalpha ():
196- targets .add (ips )
197- continue
198- # checking for CIDR
199- if not arguments .nocidr and "/" in ips :
200- exclusions .update (InputHelper ._get_cidr_to_ips (ips ))
201- # checking for IPs in a range
202- elif "-" in ips :
203- exclusions .update (InputHelper ._get_ips_from_range (ips ))
204- # checking for glob ranges
205- elif "*" in ips :
206- exclusions .update (InputHelper ._get_ips_from_glob (ips ))
207- else :
208- exclusions .add (ips )
221+ InputHelper ._pre_process_hosts (ranges , targets , arguments )
222+ InputHelper ._pre_process_hosts (exclusions_ranges , exclusions , arguments )
209223
210224 # difference operation
211225 targets -= exclusions
@@ -218,46 +232,40 @@ def process_commands(arguments):
218232 random_file = choice (files )
219233
220234 if arguments .command :
221- commands .add (arguments .command .rstrip ('\n ' ))
235+ commands .append (arguments .command .rstrip ('\n ' ))
222236 else :
223- for command in arguments .command_list :
224- commands .add (command .rstrip ('\n ' ))
237+ commands = InputHelper ._pre_process_commands (arguments .command_list , '' )
225238
226- final_commands = InputHelper ._replace_variable_for_commands (commands , "_target_" , targets )
227- final_commands = InputHelper ._replace_variable_for_commands ( final_commands , "_host_" , targets )
239+ commands = InputHelper ._replace_variable_with_commands (commands , "_target_" , targets )
240+ commands = InputHelper ._replace_variable_with_commands ( commands , "_host_" , targets )
228241
229242 if arguments .port :
230- final_commands = InputHelper ._replace_variable_for_commands ( final_commands , "_port_" , ports )
243+ commands = InputHelper ._replace_variable_with_commands ( commands , "_port_" , ports )
231244
232245 if arguments .realport :
233- final_commands = InputHelper ._replace_variable_for_commands ( final_commands , "_realport_" , real_ports )
246+ commands = InputHelper ._replace_variable_with_commands ( commands , "_realport_" , real_ports )
234247
235248 if arguments .random :
236- final_commands = InputHelper ._replace_variable_for_commands ( final_commands , "_random_" , [random_file ])
249+ commands = InputHelper ._replace_variable_with_commands ( commands , "_random_" , [random_file ])
237250
238251 if arguments .output :
239- final_commands = InputHelper ._replace_variable_for_commands ( final_commands , "_output_" , [arguments .output ])
252+ commands = InputHelper ._replace_variable_with_commands ( commands , "_output_" , [arguments .output ])
240253
241254 if arguments .proto :
242255 if "," in arguments .proto :
243256 protocols = arguments .proto .split ("," )
244257 else :
245258 protocols = arguments .proto
246- final_commands = InputHelper ._replace_variable_for_commands ( final_commands , "_proto_" , protocols )
247-
259+ commands = InputHelper ._replace_variable_with_commands ( commands , "_proto_" , protocols )
260+
248261 # process proxies
249262 if arguments .proxy_list :
250- proxy_list = list ()
251- for proxy in arguments .proxy_list :
252- if proxy .strip ():
253- proxy_list .append (proxy .strip ())
254-
255- if len (proxy_list ) < len (final_commands ):
256- proxy_list = ceil (len (final_commands ) / len (proxy_list )) * proxy_list
257-
258- final_commands = InputHelper ._replace_variable_array (final_commands , "_proxy_" , proxy_list )
263+ proxy_list = [proxy for proxy in arguments .proxy_list if proxy .strip ()]
264+ if len (proxy_list ) < len (commands ):
265+ proxy_list = ceil (len (commands ) / len (proxy_list )) * proxy_list
259266
260- return final_commands
267+ InputHelper ._replace_variable_array (commands , "_proxy_" , proxy_list )
268+ return commands
261269
262270
263271class InputParser (object ):
0 commit comments