180 lines
5.7 KiB
Python
180 lines
5.7 KiB
Python
import asyncio, colorama, os, re, string, sys, unidecode
|
|
from colorama import Fore, Style
|
|
from autorecon.config import config
|
|
|
|
def slugify(name):
|
|
return re.sub(r'[\W_]+', '-', unidecode.unidecode(name).lower()).strip('-')
|
|
|
|
def e(*args, frame_index=1, **kvargs):
|
|
frame = sys._getframe(frame_index)
|
|
|
|
vals = {}
|
|
|
|
vals.update(frame.f_globals)
|
|
vals.update(frame.f_locals)
|
|
vals.update(kvargs)
|
|
|
|
return string.Formatter().vformat(' '.join(args), args, vals)
|
|
|
|
def fformat(s):
|
|
return e(s, frame_index=3)
|
|
|
|
def cprint(*args, color=Fore.RESET, char='*', sep=' ', end='\n', frame_index=1, file=sys.stdout, printmsg=True, verbosity=0, **kvargs):
|
|
if printmsg and verbosity > config['verbose']:
|
|
return ''
|
|
frame = sys._getframe(frame_index)
|
|
|
|
vals = {
|
|
'bgreen': Fore.GREEN + Style.BRIGHT,
|
|
'bred': Fore.RED + Style.BRIGHT,
|
|
'bblue': Fore.BLUE + Style.BRIGHT,
|
|
'byellow': Fore.YELLOW + Style.BRIGHT,
|
|
'bmagenta': Fore.MAGENTA + Style.BRIGHT,
|
|
|
|
'green': Fore.GREEN,
|
|
'red': Fore.RED,
|
|
'blue': Fore.BLUE,
|
|
'yellow': Fore.YELLOW,
|
|
'magenta': Fore.MAGENTA,
|
|
|
|
'bright': Style.BRIGHT,
|
|
'srst': Style.NORMAL,
|
|
'crst': Fore.RESET,
|
|
'rst': Style.NORMAL + Fore.RESET
|
|
}
|
|
|
|
if config['accessible']:
|
|
vals = {'bgreen':'', 'bred':'', 'bblue':'', 'byellow':'', 'bmagenta':'', 'green':'', 'red':'', 'blue':'', 'yellow':'', 'magenta':'', 'bright':'', 'srst':'', 'crst':'', 'rst':''}
|
|
|
|
vals.update(frame.f_globals)
|
|
vals.update(frame.f_locals)
|
|
vals.update(kvargs)
|
|
|
|
unfmt = ''
|
|
if char is not None and not config['accessible']:
|
|
unfmt += f'{color}[{Style.BRIGHT}{char}{Style.NORMAL}]{Fore.RESET}{sep}'
|
|
unfmt += sep.join(args)
|
|
|
|
fmted = unfmt
|
|
|
|
for _ in range(10):
|
|
try:
|
|
fmted = string.Formatter().vformat(unfmt, args, vals)
|
|
break
|
|
except KeyError as err:
|
|
key = err.args[0]
|
|
unfmt = unfmt.replace('{' + key + '}', '{{' + key + '}}')
|
|
|
|
if printmsg:
|
|
print(fmted, sep=sep, end=end, file=file)
|
|
else:
|
|
return fmted
|
|
|
|
def debug(*args, color=Fore.GREEN, sep=' ', end='\n', file=sys.stdout, **kvargs):
|
|
if config['verbose'] >= 2:
|
|
if config['accessible']:
|
|
args = ('Debug:',) + args
|
|
cprint(*args, color=color, char='-', sep=sep, end=end, file=file, frame_index=2, **kvargs)
|
|
|
|
def info(*args, sep=' ', end='\n', file=sys.stdout, **kvargs):
|
|
cprint(*args, color=Fore.BLUE, char='*', sep=sep, end=end, file=file, frame_index=2, **kvargs)
|
|
|
|
def warn(*args, sep=' ', end='\n', file=sys.stderr,**kvargs):
|
|
if config['accessible']:
|
|
args = ('Warning:',) + args
|
|
cprint(*args, color=Fore.YELLOW, char='!', sep=sep, end=end, file=file, frame_index=2, **kvargs)
|
|
|
|
def error(*args, sep=' ', end='\n', file=sys.stderr, **kvargs):
|
|
if config['accessible']:
|
|
args = ('Error:',) + args
|
|
cprint(*args, color=Fore.RED, char='!', sep=sep, end=end, file=file, frame_index=2, **kvargs)
|
|
|
|
def fail(*args, sep=' ', end='\n', file=sys.stderr, **kvargs):
|
|
if config['accessible']:
|
|
args = ('Failure:',) + args
|
|
cprint(*args, color=Fore.RED, char='!', sep=sep, end=end, file=file, frame_index=2, **kvargs)
|
|
exit(-1)
|
|
|
|
class CommandStreamReader(object):
|
|
|
|
def __init__(self, stream, target, tag, patterns=None, outfile=None):
|
|
self.stream = stream
|
|
self.target = target
|
|
self.tag = tag
|
|
self.lines = []
|
|
self.patterns = patterns or []
|
|
self.outfile = outfile
|
|
self.ended = False
|
|
|
|
# Empty files that already exist.
|
|
if self.outfile != None:
|
|
with open(self.outfile, 'w'): pass
|
|
|
|
# Read lines from the stream until it ends.
|
|
async def _read(self):
|
|
while True:
|
|
if self.stream.at_eof():
|
|
break
|
|
try:
|
|
line = (await self.stream.readline()).decode('utf8').rstrip()
|
|
except ValueError:
|
|
error('{bright}[{yellow}' + self.target.address + '{crst}/{bgreen}' + self.tag + '{crst}]{rst} A line was longer than 64 KiB and cannot be processed. Ignoring.')
|
|
continue
|
|
|
|
if line != '':
|
|
info('{bright}[{yellow}' + self.target.address + '{crst}/{bgreen}' + self.tag + '{crst}]{rst} ' + line.strip().replace('{', '{{').replace('}', '}}'), verbosity=3)
|
|
|
|
# Check lines for pattern matches.
|
|
for p in self.patterns:
|
|
description = ''
|
|
|
|
if match := p.pattern.search(line):
|
|
if p.description:
|
|
description = p.description.replace('{match}', line[match.start():match.end()])
|
|
|
|
# Match and replace substrings.
|
|
matches = p.pattern.findall(line)
|
|
if len(matches) > 0 and isinstance(matches[0], tuple):
|
|
matches = list(matches[0])
|
|
|
|
for match_count, match in enumerate(matches, start=1):
|
|
if p.description:
|
|
description = description.replace('{match' + str(match_count) + '}', match)
|
|
async with self.target.lock:
|
|
with open(os.path.join(self.target.scandir, '_patterns.log'), 'a') as file:
|
|
info('{bright}[{yellow}' + self.target.address + '{crst}/{bgreen}' + self.tag + '{crst}]{rst} {bmagenta}' + description + '{rst}', verbosity=2)
|
|
file.writelines(description + '\n\n')
|
|
else:
|
|
info('{bright}[{yellow}' + self.target.address + '{crst}/{bgreen}' + self.tag + '{crst}]{rst} {bmagenta}Matched Pattern: ' + line[match.start():match.end()] + '{rst}', verbosity=2)
|
|
async with self.target.lock:
|
|
with open(os.path.join(self.target.scandir, '_patterns.log'), 'a') as file:
|
|
file.writelines(f'Matched Pattern: {line[match.start():match.end()]}' + '\n\n')
|
|
|
|
if self.outfile is not None:
|
|
with open(self.outfile, 'a') as writer:
|
|
writer.write(line + '\n')
|
|
self.lines.append(line)
|
|
self.ended = True
|
|
|
|
# Read a line from the stream cache.
|
|
async def readline(self):
|
|
while True:
|
|
try:
|
|
return self.lines.pop(0)
|
|
except IndexError:
|
|
if self.ended:
|
|
return None
|
|
else:
|
|
await asyncio.sleep(0.1)
|
|
|
|
# Read all lines from the stream cache.
|
|
async def readlines(self):
|
|
lines = []
|
|
while True:
|
|
line = await self.readline()
|
|
if line is not None:
|
|
lines.append(line)
|
|
else:
|
|
break
|
|
return lines
|