Plugin updates, bug fix, and feature update.

A few manual plugin updates (command formatting etc.)
Fixed bug where processes were left running after AutoRecon is cancelled and/or times out.
Status messages now include PIDs of running processes if verbosity >= 2.

Closes #183
Fixes #184
This commit is contained in:
Tib3rius 2023-01-10 16:24:14 -05:00
parent 65fc104b2d
commit 851ffbd316
6 changed files with 101 additions and 27 deletions

View File

@ -0,0 +1,17 @@
from autorecon.plugins import ServiceScan
class BruteforceSMB(ServiceScan):
def __init__(self):
super().__init__()
self.name = 'Bruteforce SMB'
self.tags = ['default', 'safe', 'active-directory']
def configure(self):
self.match_service('tcp', 445, '^microsoft\-ds')
self.match_service('tcp', 139, '^netbios')
def manual(self, service, plugin_was_run):
service.add_manual_command('Bruteforce SMB', [
'crackmapexec smb {address} --port={port} -u "' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '" -p "' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '"'
])

View File

@ -12,5 +12,5 @@ class LookupSID(ServiceScan):
def manual(self, service, plugin_was_run):
service.add_manual_command('Lookup SIDs', [
'lookupsid.py [username]:[password]@{address}'
'impacket-lookupsid \'[username]:[password]@{address}\''
])

View File

@ -19,14 +19,14 @@ class WinRMDetection(ServiceScan):
def manual(self, service, plugin_was_run):
service.add_manual_commands('Bruteforce logins:', [
'crackmapexec winrm {address} -d ' + self.get_global('domain', default='<domain>') + ' -u ' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + ' -p ' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt')
'crackmapexec winrm {address} -d \'' + self.get_global('domain', default='<domain>') + '\' -u \'' + self.get_global('username_wordlist', default='/usr/share/seclists/Usernames/top-usernames-shortlist.txt') + '\' -p \'' + self.get_global('password_wordlist', default='/usr/share/seclists/Passwords/darkweb2017-top100.txt') + '\''
])
service.add_manual_commands('Check login (requires credentials):', [
'crackmapexec winrm {address} -d ' + self.get_global('domain', default='<domain>') + ' -u <username> -p <password> -x "whoami"'
'crackmapexec winrm {address} -d \'' + self.get_global('domain', default='<domain>') + '\' -u \'<username>\' -p \'<password>\''
])
service.add_manual_commands('Evil WinRM (gem install evil-winrm):', [
'evil-winrm -u <user> -p <password> -i {address}',
'evil-winrm -u <user> -H <hash> -i {address}'
'evil-winrm -u \'<user>\' -p \'<password>\' -i {address}',
'evil-winrm -u \'<user>\' -H \'<hash>\' -i {address}'
])

View File

@ -4,7 +4,7 @@ import argparse, asyncio, importlib.util, inspect, ipaddress, math, os, re, sele
from datetime import datetime
try:
import appdirs, colorama, impacket, requests, toml, unidecode
import appdirs, colorama, impacket, psutil, requests, toml, unidecode
from colorama import Fore, Style
except ModuleNotFoundError:
print('One or more required modules was not installed. Please run or re-run: ' + ('sudo ' if os.getuid() == 0 else '') + 'python3 -m pip install -r requirements.txt')
@ -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.30"
VERSION = "2.0.31"
if not os.path.exists(config['config_dir']):
shutil.rmtree(config['config_dir'], ignore_errors=True, onerror=None)
@ -92,17 +92,35 @@ def calculate_elapsed_time(start_time, short=False):
else:
return ', '.join(elapsed_time)
def cancel_all_tasks(signal, frame):
# sig and frame args are only present so the function
# works with signal.signal() and handles Ctrl-C.
# They are not used for any other purpose.
def cancel_all_tasks(sig, frame):
for task in asyncio.all_tasks():
task.cancel()
processes = []
for target in autorecon.scanning_targets:
for process_list in target.running_tasks.values():
for process_dict in process_list['processes']:
try:
process_dict['process'].kill()
except ProcessLookupError: # Will get raised if the process finishes before we get to killing it.
parent = psutil.Process(process_dict['process'].pid)
processes.extend(parent.children(recursive=True))
processes.append(parent)
except psutil.NoSuchProcess:
pass
for process in processes:
try:
process.send_signal(signal.SIGKILL)
except psutil.NoSuchProcess: # Will get raised if the process finishes before we get to killing it.
pass
_, alive = psutil.wait_procs(processes, timeout=10)
if len(alive) > 0:
error('The following process IDs could not be killed: ' + ', '.join([str(x.pid) for x in sorted(alive, key=lambda x: x.pid)]))
if not config['disable_keyboard_control']:
# Restore original terminal settings.
@ -114,9 +132,28 @@ async def start_heartbeat(target, period=60):
async with target.lock:
count = len(target.running_tasks)
tasks_list = ''
tasks_list = []
if config['verbose'] >= 1:
tasks_list = ': {bblue}' + ', '.join(target.running_tasks.keys()) + '{rst}'
for tag, task in target.running_tasks.items():
task_str = tag
if config['verbose'] >= 2:
processes = []
for process_dict in task['processes']:
if process_dict['process'].returncode is None:
processes.append(str(process_dict['process'].pid))
try:
for child in psutil.Process(process_dict['process'].pid).children(recursive=True):
processes.append(str(child.pid))
except psutil.NoSuchProcess:
pass
if processes:
task_str += ' (PID' + ('s' if len(processes) > 1 else '') + ': ' + ', '.join(processes) + ')'
tasks_list.append(task_str)
tasks_list = ': {bblue}' + ', '.join(tasks_list) + '{rst}'
current_time = datetime.now().strftime('%H:%M:%S')
@ -153,24 +190,42 @@ async def keyboard():
if len(input) > 0 and input[0] == 's':
input = input[1:]
for target in autorecon.scanning_targets:
count = len(target.running_tasks)
async with target.lock:
count = len(target.running_tasks)
tasks_list = []
if config['verbose'] >= 1:
for key, value in target.running_tasks.items():
elapsed_time = calculate_elapsed_time(value['start'], short=True)
tasks_list.append('{bblue}' + key + '{rst}' + ' (elapsed: ' + elapsed_time + ')')
tasks_list = []
if config['verbose'] >= 1:
for tag, task in target.running_tasks.items():
elapsed_time = calculate_elapsed_time(task['start'], short=True)
tasks_list = ':\n ' + '\n '.join(tasks_list)
else:
tasks_list = ''
task_str = '{bblue}' + tag + '{rst}' + ' (elapsed: ' + elapsed_time + ')'
current_time = datetime.now().strftime('%H:%M:%S')
if config['verbose'] >= 2:
processes = []
for process_dict in task['processes']:
if process_dict['process'].returncode is None:
processes.append(str(process_dict['process'].pid))
try:
for child in psutil.Process(process_dict['process'].pid).children(recursive=True):
processes.append(str(child.pid))
except psutil.NoSuchProcess:
pass
if processes:
task_str += ' (PID' + ('s' if len(processes) > 1 else '') + ': ' + ', '.join(processes) + ')'
tasks_list.append(task_str)
if count > 1:
info('{bgreen}' + current_time + '{rst} - There are {byellow}' + str(count) + '{rst} scans still running against {byellow}' + target.address + '{rst}' + tasks_list)
elif count == 1:
info('{bgreen}' + current_time + '{rst} - There is {byellow}1{rst} scan still running against {byellow}' + target.address + '{rst}' + tasks_list)
tasks_list = ':\n ' + '\n '.join(tasks_list)
else:
tasks_list = ''
current_time = datetime.now().strftime('%H:%M:%S')
if count > 1:
info('{bgreen}' + current_time + '{rst} - There are {byellow}' + str(count) + '{rst} scans still running against {byellow}' + target.address + '{rst}' + tasks_list)
elif count == 1:
info('{bgreen}' + current_time + '{rst} - There is {byellow}1{rst} scan still running against {byellow}' + target.address + '{rst}' + tasks_list)
else:
input = input[1:]
await asyncio.sleep(0.1)

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "autorecon"
version = "2.0.30"
version = "2.0.31"
description = "A multi-threaded network reconnaissance tool which performs automated enumeration of services."
authors = ["Tib3rius"]
license = "GNU GPL v3"
@ -14,6 +14,7 @@ python = "^3.8"
appdirs = "^1.4.4"
colorama = "^0.4.5"
impacket = "^0.10.0"
psutil = "^5.9.4"
requests = "^2.28.1"
toml = "^0.10.2"
Unidecode = "^1.3.1"

View File

@ -1,6 +1,7 @@
appdirs
colorama
impacket
psutil
requests
toml
unidecode