Upgraded config/global/plugins searching.
AutoRecon will now search for config/global/plugins in the current directory, then the ~/.config/AutoRecon directory, unless being overridden by command line options.
This commit is contained in:
parent
9249273389
commit
6bc2a51059
|
@ -42,7 +42,7 @@ configurable_boolean_keys = [
|
|||
config = {
|
||||
'protected_classes': ['autorecon', 'target', 'service', 'commandstreamreader', 'plugin', 'portscan', 'servicescan', 'global', 'pattern'],
|
||||
'config_dir': config_dir,
|
||||
'global_file': os.path.join(config_dir, 'global.toml'),
|
||||
'global_file': None,
|
||||
'ports': None,
|
||||
'max_scans': 50,
|
||||
'max_port_scans': None,
|
||||
|
@ -51,7 +51,7 @@ config = {
|
|||
'port_scans': None,
|
||||
'service_scans': None,
|
||||
'reports': None,
|
||||
'plugins_dir': os.path.join(config_dir, 'plugins'),
|
||||
'plugins_dir': None,
|
||||
'add_plugins_dir': None,
|
||||
'outdir': 'results',
|
||||
'single_target': False,
|
||||
|
|
|
@ -19,17 +19,20 @@ from autorecon.targets import Target, Service
|
|||
|
||||
VERSION = "2.0.0"
|
||||
|
||||
def install():
|
||||
if not os.path.exists(config['config_dir']):
|
||||
shutil.rmtree(config['config_dir'], ignore_errors=True, onerror=None)
|
||||
os.makedirs(config['config_dir'], exist_ok=True)
|
||||
open(os.path.join(config['config_dir'], 'VERSION-' + VERSION), 'a').close()
|
||||
shutil.copy(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'config.toml'), os.path.join(config['config_dir'], 'config.toml'))
|
||||
shutil.copy(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'global.toml'), os.path.join(config['config_dir'], 'global.toml'))
|
||||
shutil.copytree(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'default-plugins'), os.path.join(config['config_dir'], 'plugins'))
|
||||
|
||||
if not os.path.exists(config['config_dir']):
|
||||
install()
|
||||
else:
|
||||
if not os.path.exists(os.path.join(config['config_dir'], 'config.toml')):
|
||||
shutil.copy(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'config.toml'), os.path.join(config['config_dir'], 'config.toml'))
|
||||
if not os.path.exists(os.path.join(config['config_dir'], 'global.toml')):
|
||||
shutil.copy(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'global.toml'), os.path.join(config['config_dir'], 'global.toml'))
|
||||
if not os.path.exists(os.path.join(config['config_dir'], 'plugins')):
|
||||
shutil.copytree(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'default-plugins'), os.path.join(config['config_dir'], 'plugins'))
|
||||
if not os.path.exists(os.path.join(config['config_dir'], 'VERSION-' + VERSION)):
|
||||
pass
|
||||
|
||||
|
@ -728,14 +731,38 @@ async def scan_target(target):
|
|||
autorecon.scanning_targets.remove(target)
|
||||
|
||||
async def run():
|
||||
# Find config file.
|
||||
if os.path.isfile(os.path.join(os.getcwd(), 'config.toml')):
|
||||
config_file = os.path.join(os.getcwd(), 'config.toml')
|
||||
elif os.path.isfile(os.path.join(config['config_dir'], 'config.toml')):
|
||||
config_file = os.path.join(config['config_dir'], 'config.toml')
|
||||
else:
|
||||
config_file = None
|
||||
|
||||
# Find global file.
|
||||
if os.path.isfile(os.path.join(os.getcwd(), 'global.toml')):
|
||||
config['global_file'] = os.path.join(os.getcwd(), 'global.toml')
|
||||
elif os.path.isfile(os.path.join(config['config_dir'], 'global.toml')):
|
||||
config['global_file'] = os.path.join(config['config_dir'], 'global.toml')
|
||||
else:
|
||||
config['global_file'] = None
|
||||
|
||||
# Find plugins.
|
||||
if os.path.isdir(os.path.join(os.getcwd(), 'plugins')):
|
||||
config['plugins_dir'] = os.path.join(os.getcwd(), 'plugins')
|
||||
elif os.path.isdir(os.path.join(config['config_dir'], 'plugins')):
|
||||
config['plugins_dir'] = os.path.join(config['config_dir'], 'plugins')
|
||||
else:
|
||||
config['plugins_dir'] = None
|
||||
|
||||
parser = argparse.ArgumentParser(add_help=False, description='Network reconnaissance tool to port scan and automatically enumerate services found on multiple targets.')
|
||||
parser.add_argument('targets', action='store', help='IP addresses (e.g. 10.0.0.1), CIDR notation (e.g. 10.0.0.1/24), or resolvable hostnames (e.g. foo.bar) to scan.', nargs='*')
|
||||
parser.add_argument('-t', '--targets', action='store', type=str, default='', dest='target_file', help='Read targets from file.')
|
||||
parser.add_argument('-p', '--ports', action='store', type=str, help='Comma separated list of ports / port ranges to scan. Specify TCP/UDP ports by prepending list with T:/U: To scan both TCP/UDP, put port(s) at start or specify B: e.g. 53,T:21-25,80,U:123,B:123. Default: %(default)s')
|
||||
parser.add_argument('-m', '--max-scans', action='store', type=int, help='The maximum number of concurrent scans to run. Default: %(default)s')
|
||||
parser.add_argument('-mp', '--max-port-scans', action='store', type=int, help='The maximum number of concurrent port scans to run. Default: 10 (approx 20%% of max-scans unless specified)')
|
||||
parser.add_argument('-c', '--config', action='store', type=str, default=os.path.join(config['config_dir'], 'config.toml'), dest='config_file', help='Location of AutoRecon\'s config file. Default: %(default)s')
|
||||
parser.add_argument('-g', '--global-file', action='store', type=str, dest='global_file', help='Location of AutoRecon\'s global file. Default: ' + os.path.join(config['config_dir'], 'global.toml'))
|
||||
parser.add_argument('-c', '--config', action='store', type=str, default=config_file, dest='config_file', help='Location of AutoRecon\'s config file. Default: %(default)s')
|
||||
parser.add_argument('-g', '--global-file', action='store', type=str, dest='global_file', help='Location of AutoRecon\'s global file. Default: %(default)s')
|
||||
parser.add_argument('--tags', action='store', type=str, default='default', help='Tags to determine which plugins should be included. Separate tags by a plus symbol (+) to group tags together. Separate groups with a comma (,) to create multiple groups. For a plugin to be included, it must have all the tags specified in at least one group. Default: %(default)s')
|
||||
parser.add_argument('--exclude-tags', action='store', type=str, default='', metavar='TAGS', help='Tags to determine which plugins should be excluded. Separate tags by a plus symbol (+) to group tags together. Separate groups with a comma (,) to create multiple groups. For a plugin to be excluded, it must have all the tags specified in at least one group. Default: %(default)s')
|
||||
parser.add_argument('--port-scans', action='store', type=str, metavar='PLUGINS', help='Override --tags / --exclude-tags for the listed PortScan plugins (comma separated). Default: %(default)s')
|
||||
|
@ -772,8 +799,18 @@ async def run():
|
|||
print('AutoRecon v' + VERSION)
|
||||
sys.exit(0)
|
||||
|
||||
def unknown_help():
|
||||
if '-h' in unknown:
|
||||
parser.print_help()
|
||||
print()
|
||||
|
||||
# Parse config file and args for global.toml first.
|
||||
if not args.config_file:
|
||||
unknown_help()
|
||||
fail('Error: Could not find config.toml in the current directory or ~/.config/AutoRecon.')
|
||||
|
||||
if not os.path.isfile(args.config_file):
|
||||
unknown_help()
|
||||
fail('Error: Specified config file "' + args.config_file + '" does not exist.')
|
||||
|
||||
with open(args.config_file) as c:
|
||||
|
@ -788,6 +825,7 @@ async def run():
|
|||
elif key == 'add-plugins-dir':
|
||||
config['add_plugins_dir'] = val
|
||||
except toml.decoder.TomlDecodeError:
|
||||
unknown_help()
|
||||
fail('Error: Couldn\'t parse ' + args.config_file + ' config file. Check syntax.')
|
||||
|
||||
args_dict = vars(args)
|
||||
|
@ -800,10 +838,16 @@ async def run():
|
|||
elif key == 'add-plugins-dir' and args_dict['add_plugins_dir'] is not None:
|
||||
config['add_plugins_dir'] = args_dict['add_plugins_dir']
|
||||
|
||||
if not config['plugins_dir']:
|
||||
unknown_help()
|
||||
fail('Error: Could not find plugins directory in the current directory or ~/.config/AutoRecon.')
|
||||
|
||||
if not os.path.isdir(config['plugins_dir']):
|
||||
unknown_help()
|
||||
fail('Error: Specified plugins directory "' + config['plugins_dir'] + '" does not exist.')
|
||||
|
||||
if config['add_plugins_dir'] and not os.path.isdir(config['add_plugins_dir']):
|
||||
unknown_help()
|
||||
fail('Error: Specified additional plugins directory "' + config['add_plugins_dir'] + '" does not exist.')
|
||||
|
||||
plugins_dirs = [config['plugins_dir']]
|
||||
|
@ -830,6 +874,7 @@ async def run():
|
|||
continue
|
||||
|
||||
if c.__name__.lower() in config['protected_classes']:
|
||||
unknown_help()
|
||||
print('Plugin "' + c.__name__ + '" in ' + filename + ' is using a protected class name. Please change it.')
|
||||
sys.exit(1)
|
||||
|
||||
|
@ -839,17 +884,20 @@ async def run():
|
|||
else:
|
||||
print('Plugin "' + c.__name__ + '" in ' + filename + ' is not a subclass of either PortScan, ServiceScan, or Report.')
|
||||
except (ImportError, SyntaxError) as ex:
|
||||
unknown_help()
|
||||
print('cannot import ' + filename + ' plugin')
|
||||
print(ex)
|
||||
sys.exit(1)
|
||||
|
||||
for plugin in autorecon.plugins.values():
|
||||
if plugin.slug in autorecon.taglist:
|
||||
unknown_help()
|
||||
fail('Plugin ' + plugin.name + ' has a slug (' + plugin.slug + ') with the same name as a tag. Please either change the plugin name or override the slug.')
|
||||
# Add plugin slug to tags.
|
||||
plugin.tags += [plugin.slug]
|
||||
|
||||
if len(autorecon.plugin_types['port']) == 0:
|
||||
unknown_help()
|
||||
fail('Error: There are no valid PortScan plugins in the plugins directory "' + config['plugins_dir'] + '".')
|
||||
|
||||
# Sort plugins by priority.
|
||||
|
@ -857,7 +905,12 @@ async def run():
|
|||
autorecon.plugin_types['service'].sort(key=lambda x: x.priority)
|
||||
autorecon.plugin_types['report'].sort(key=lambda x: x.priority)
|
||||
|
||||
if not config['global_file']:
|
||||
unknown_help()
|
||||
fail('Error: Could not find global.toml in the current directory or ~/.config/AutoRecon.')
|
||||
|
||||
if not os.path.isfile(config['global_file']):
|
||||
unknown_help()
|
||||
fail('Error: Specified global file "' + config['global_file'] + '" does not exist.')
|
||||
|
||||
global_plugin_args = None
|
||||
|
@ -920,11 +973,14 @@ async def run():
|
|||
else:
|
||||
autorecon.patterns.append(Pattern(compiled))
|
||||
except re.error:
|
||||
unknown_help()
|
||||
fail('Error: The pattern "' + pattern['pattern'] + '" in the global file is invalid regex.')
|
||||
else:
|
||||
unknown_help()
|
||||
fail('Error: A [[pattern]] in the global file doesn\'t have a required pattern variable.')
|
||||
|
||||
except toml.decoder.TomlDecodeError:
|
||||
unknown_help()
|
||||
fail('Error: Couldn\'t parse ' + g.name + ' file. Check syntax.')
|
||||
|
||||
other_options = []
|
||||
|
|
Loading…
Reference in New Issue