Skip to content

Commit 762eb65

Browse files
authored
Merge pull request #60 from iamOgunyinka/flat
Add _block:_ and _blocker_ features as per #52 (flat implementation)
2 parents 2426e0b + 3673de2 commit 762eb65

File tree

8 files changed

+223
-174
lines changed

8 files changed

+223
-174
lines changed

.github/FUNDING.yml

Lines changed: 0 additions & 12 deletions
This file was deleted.

Interlace/interlace.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
#!/usr/bin/python3
2+
23
import sys
4+
35
from Interlace.lib.core.input import InputParser, InputHelper
46
from Interlace.lib.core.output import OutputHelper, Level
57
from Interlace.lib.threader import Pool
68

79

810
def build_queue(arguments, output):
9-
queue = list()
10-
for command in InputHelper.process_commands(arguments):
11-
output.terminal(Level.THREAD, command, "Added to Queue")
12-
queue.append(command)
13-
return queue
11+
task_list = InputHelper.process_commands(arguments)
12+
for task in task_list:
13+
output.terminal(Level.THREAD, task.name(), "Added to Queue")
14+
return task_list
1415

1516

1617
def main():

Interlace/lib/core/input.py

Lines changed: 127 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
from argparse import ArgumentParser
2-
from netaddr import IPNetwork, IPRange, IPGlob
3-
from Interlace.lib.core.output import OutputHelper, Level
41
import os.path
5-
from os import access, W_OK
62
import sys
7-
from re import compile
8-
from random import sample, choice
3+
from argparse import ArgumentParser
94
from 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

1212
class 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

263271
class InputParser(object):

Interlace/lib/core/output.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
from colorclass import Color
2-
from colorclass import disable_all_colors, enable_all_colors, is_enabled
3-
from time import localtime, strftime
41
from enum import IntEnum
2+
from time import localtime, strftime
3+
4+
from colorclass import Color
5+
from colorclass import disable_all_colors
6+
57
from Interlace.lib.core.__version__ import __version__
68

79

@@ -40,7 +42,7 @@ def terminal(self, level, target, command, message=""):
4042
'target': target,
4143
'command': command,
4244
'message': message,
43-
'leader':leader
45+
'leader': leader
4446
}
4547

4648
if not self.silent:

0 commit comments

Comments
 (0)