From 6100333bd73e8a2aca61d2bec3de31b3d2b113d0 Mon Sep 17 00:00:00 2001 From: Tib3rius <48113936+Tib3rius@users.noreply.github.com> Date: Tue, 18 Jan 2022 20:00:33 -0500 Subject: [PATCH] Fixed / improved pattern matching. {match} will output as the entire matched string. {match1} will output as the first matched group. {match2} etc. --- autorecon/default-plugins/http_server.py | 2 +- autorecon/default-plugins/rpc.py | 2 +- autorecon/default-plugins/smb.py | 17 +++++++++- autorecon/io.py | 40 +++++++++++++----------- autorecon/main.py | 2 +- pyproject.toml | 2 +- 6 files changed, 42 insertions(+), 23 deletions(-) diff --git a/autorecon/default-plugins/http_server.py b/autorecon/default-plugins/http_server.py index 15ad379..0b1afe7 100644 --- a/autorecon/default-plugins/http_server.py +++ b/autorecon/default-plugins/http_server.py @@ -14,7 +14,7 @@ class NmapHTTP(ServiceScan): def configure(self): self.match_service_name('^http') self.match_service_name('^nacn_http$', negative_match=True) - self.add_pattern('Server: ([^\n]+)', description='Identified HTTP Server: {match}') + self.add_pattern('Server: ([^\n]+)', description='Identified HTTP Server: {match1}') self.add_pattern('WebDAV is ENABLED', description='WebDAV is enabled') async def run(self, service): diff --git a/autorecon/default-plugins/rpc.py b/autorecon/default-plugins/rpc.py index cbb128c..fcf650f 100644 --- a/autorecon/default-plugins/rpc.py +++ b/autorecon/default-plugins/rpc.py @@ -51,7 +51,7 @@ class GetArch(ServiceScan): def configure(self): self.match_service_name(['^msrpc']) self.match_port('tcp', 135) - self.add_pattern(' is ((32|64)-bit)', description='Identified Architecture: {match}') + self.add_pattern(' is ((32|64)-bit)', description='Identified Architecture: {match1}') async def run(self, service): await service.execute('getArch.py -target {address}', outfile='{protocol}_{port}_rpc_architecture.txt') diff --git a/autorecon/default-plugins/smb.py b/autorecon/default-plugins/smb.py index 08b1459..438e712 100644 --- a/autorecon/default-plugins/smb.py +++ b/autorecon/default-plugins/smb.py @@ -53,11 +53,26 @@ class Enum4Linux(ServiceScan): if service.target.ipversion == 'IPv4': await service.execute('enum4linux -a -M -l -d {address} 2>&1', outfile='enum4linux.txt') +class LookupSID(ServiceScan): + + def __init__(self): + super().__init__() + self.name = 'lookupsid' + self.tags = ['default', 'safe', 'active-directory'] + + def configure(self): + self.match_service('tcp', 445, '^microsoft\-ds') + + def manual(self, service, plugin_was_run): + service.add_manual_command('Lookup SIDs', [ + 'lookupsid.py [username]:[password]@{address}' + ]) + class NBTScan(ServiceScan): def __init__(self): super().__init__() - self.name = "nbtscan" + self.name = 'nbtscan' self.tags = ['default', 'safe', 'netbios', 'active-directory'] def configure(self): diff --git a/autorecon/io.py b/autorecon/io.py index f7a4ccb..3ccace6 100644 --- a/autorecon/io.py +++ b/autorecon/io.py @@ -126,30 +126,34 @@ class CommandStreamReader(object): # Check lines for pattern matches. for p in self.patterns: - matches = p.pattern.findall(line) - if len(matches) > 0 and isinstance(matches[0], tuple): - matches = list(matches[0]) - match_count = 1 description = '' - for match in matches: + + # Match and replace entire pattern. + match = p.pattern.search(line) + if match: if p.description: - if match_count == 1: - description = p.description.replace('{match}', match) - description = description.replace('{match' + str(match_count) + '}', match) - else: - info('{bright}[{yellow}' + self.target.address + '{crst}/{bgreen}' + self.tag + '{crst}]{rst} {bmagenta}Matched Pattern: ' + match + '{rst}', verbosity=2) + 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]) + + match_count = 1 + for match in matches: + if p.description: + description = description.replace('{match' + str(match_count) + '}', match) + match_count += 1 + async with self.target.lock: with open(os.path.join(self.target.scandir, '_patterns.log'), 'a') as file: - file.writelines('Matched Pattern: ' + match + '\n\n') - - match_count += 1 - - if matches: - async with self.target.lock: - with open(os.path.join(self.target.scandir, '_patterns.log'), 'a') as file: - if p.description: 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('Matched Pattern: ' + line[match.start():match.end()] + '\n\n') if self.outfile is not None: with open(self.outfile, 'a') as writer: diff --git a/autorecon/main.py b/autorecon/main.py index 94c9653..70812a1 100644 --- a/autorecon/main.py +++ b/autorecon/main.py @@ -17,7 +17,7 @@ from autorecon.io import slugify, e, fformat, cprint, debug, info, warn, error, from autorecon.plugins import Pattern, PortScan, ServiceScan, Report, AutoRecon from autorecon.targets import Target, Service -VERSION = "2.0.13" +VERSION = "2.0.14" if not os.path.exists(config['config_dir']): shutil.rmtree(config['config_dir'], ignore_errors=True, onerror=None) diff --git a/pyproject.toml b/pyproject.toml index 60d11dc..f48bb82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "autorecon" -version = "2.0.13" +version = "2.0.14" description = "A multi-threaded network reconnaissance tool which performs automated enumeration of services." authors = ["Tib3rius"] license = "GNU GPL v3"