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, **kvargs): 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 += color + '[' + Style.BRIGHT + char + Style.NORMAL + ']' + Fore.RESET + sep unfmt += sep.join(args) fmted = unfmt for attempt 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 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 # 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 config['verbose'] >= 2: if line != '': info('{bright}[{yellow}' + self.target.address + '{crst}/{bgreen}' + self.tag + '{crst}]{rst} ' + line.replace('{', '{{').replace('}', '}}')) # Check lines for pattern matches. for p in self.patterns: matches = p.pattern.findall(line) for match in matches: async with self.target.lock: with open(os.path.join(self.target.scandir, '_patterns.log'), 'a') as file: if p.description: if config['verbose'] >= 1: info('{bright}[{yellow}' + self.target.address + '{crst}/{bgreen}' + self.tag + '{crst}]{rst} {bmagenta}' + p.description.replace('{match}', match) + '{rst}') file.writelines(p.description.replace('{match}', match) + '\n\n') else: if config['verbose'] >= 1: info('{bright}[{yellow}' + self.target.address + '{crst}/{bgreen}' + self.tag + '{crst}]{rst} {bmagenta}Matched Pattern: ' + match + '{rst}') file.writelines('Matched Pattern: ' + match + '\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