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:
parent
65fc104b2d
commit
851ffbd316
|
@ -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') + '"'
|
||||||
|
])
|
|
@ -12,5 +12,5 @@ class LookupSID(ServiceScan):
|
||||||
|
|
||||||
def manual(self, service, plugin_was_run):
|
def manual(self, service, plugin_was_run):
|
||||||
service.add_manual_command('Lookup SIDs', [
|
service.add_manual_command('Lookup SIDs', [
|
||||||
'lookupsid.py [username]:[password]@{address}'
|
'impacket-lookupsid \'[username]:[password]@{address}\''
|
||||||
])
|
])
|
||||||
|
|
|
@ -19,14 +19,14 @@ class WinRMDetection(ServiceScan):
|
||||||
|
|
||||||
def manual(self, service, plugin_was_run):
|
def manual(self, service, plugin_was_run):
|
||||||
service.add_manual_commands('Bruteforce logins:', [
|
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):', [
|
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):', [
|
service.add_manual_commands('Evil WinRM (gem install evil-winrm):', [
|
||||||
'evil-winrm -u <user> -p <password> -i {address}',
|
'evil-winrm -u \'<user>\' -p \'<password>\' -i {address}',
|
||||||
'evil-winrm -u <user> -H <hash> -i {address}'
|
'evil-winrm -u \'<user>\' -H \'<hash>\' -i {address}'
|
||||||
])
|
])
|
||||||
|
|
|
@ -4,7 +4,7 @@ import argparse, asyncio, importlib.util, inspect, ipaddress, math, os, re, sele
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import appdirs, colorama, impacket, requests, toml, unidecode
|
import appdirs, colorama, impacket, psutil, requests, toml, unidecode
|
||||||
from colorama import Fore, Style
|
from colorama import Fore, Style
|
||||||
except ModuleNotFoundError:
|
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')
|
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.plugins import Pattern, PortScan, ServiceScan, Report, AutoRecon
|
||||||
from autorecon.targets import Target, Service
|
from autorecon.targets import Target, Service
|
||||||
|
|
||||||
VERSION = "2.0.30"
|
VERSION = "2.0.31"
|
||||||
|
|
||||||
if not os.path.exists(config['config_dir']):
|
if not os.path.exists(config['config_dir']):
|
||||||
shutil.rmtree(config['config_dir'], ignore_errors=True, onerror=None)
|
shutil.rmtree(config['config_dir'], ignore_errors=True, onerror=None)
|
||||||
|
@ -92,18 +92,36 @@ def calculate_elapsed_time(start_time, short=False):
|
||||||
else:
|
else:
|
||||||
return ', '.join(elapsed_time)
|
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():
|
for task in asyncio.all_tasks():
|
||||||
task.cancel()
|
task.cancel()
|
||||||
|
|
||||||
|
processes = []
|
||||||
|
|
||||||
for target in autorecon.scanning_targets:
|
for target in autorecon.scanning_targets:
|
||||||
for process_list in target.running_tasks.values():
|
for process_list in target.running_tasks.values():
|
||||||
for process_dict in process_list['processes']:
|
for process_dict in process_list['processes']:
|
||||||
try:
|
try:
|
||||||
process_dict['process'].kill()
|
parent = psutil.Process(process_dict['process'].pid)
|
||||||
except ProcessLookupError: # Will get raised if the process finishes before we get to killing it.
|
processes.extend(parent.children(recursive=True))
|
||||||
|
processes.append(parent)
|
||||||
|
except psutil.NoSuchProcess:
|
||||||
pass
|
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']:
|
if not config['disable_keyboard_control']:
|
||||||
# Restore original terminal settings.
|
# Restore original terminal settings.
|
||||||
termios.tcsetattr(sys.stdin.fileno(), termios.TCSADRAIN, terminal_settings)
|
termios.tcsetattr(sys.stdin.fileno(), termios.TCSADRAIN, terminal_settings)
|
||||||
|
@ -114,9 +132,28 @@ async def start_heartbeat(target, period=60):
|
||||||
async with target.lock:
|
async with target.lock:
|
||||||
count = len(target.running_tasks)
|
count = len(target.running_tasks)
|
||||||
|
|
||||||
tasks_list = ''
|
tasks_list = []
|
||||||
if config['verbose'] >= 1:
|
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')
|
current_time = datetime.now().strftime('%H:%M:%S')
|
||||||
|
|
||||||
|
@ -153,24 +190,42 @@ async def keyboard():
|
||||||
if len(input) > 0 and input[0] == 's':
|
if len(input) > 0 and input[0] == 's':
|
||||||
input = input[1:]
|
input = input[1:]
|
||||||
for target in autorecon.scanning_targets:
|
for target in autorecon.scanning_targets:
|
||||||
count = len(target.running_tasks)
|
async with target.lock:
|
||||||
|
count = len(target.running_tasks)
|
||||||
|
|
||||||
tasks_list = []
|
tasks_list = []
|
||||||
if config['verbose'] >= 1:
|
if config['verbose'] >= 1:
|
||||||
for key, value in target.running_tasks.items():
|
for tag, task in target.running_tasks.items():
|
||||||
elapsed_time = calculate_elapsed_time(value['start'], short=True)
|
elapsed_time = calculate_elapsed_time(task['start'], short=True)
|
||||||
tasks_list.append('{bblue}' + key + '{rst}' + ' (elapsed: ' + elapsed_time + ')')
|
|
||||||
|
|
||||||
tasks_list = ':\n ' + '\n '.join(tasks_list)
|
task_str = '{bblue}' + tag + '{rst}' + ' (elapsed: ' + elapsed_time + ')'
|
||||||
else:
|
|
||||||
tasks_list = ''
|
|
||||||
|
|
||||||
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 count > 1:
|
if processes:
|
||||||
info('{bgreen}' + current_time + '{rst} - There are {byellow}' + str(count) + '{rst} scans still running against {byellow}' + target.address + '{rst}' + tasks_list)
|
task_str += ' (PID' + ('s' if len(processes) > 1 else '') + ': ' + ', '.join(processes) + ')'
|
||||||
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.append(task_str)
|
||||||
|
|
||||||
|
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:
|
else:
|
||||||
input = input[1:]
|
input = input[1:]
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "autorecon"
|
name = "autorecon"
|
||||||
version = "2.0.30"
|
version = "2.0.31"
|
||||||
description = "A multi-threaded network reconnaissance tool which performs automated enumeration of services."
|
description = "A multi-threaded network reconnaissance tool which performs automated enumeration of services."
|
||||||
authors = ["Tib3rius"]
|
authors = ["Tib3rius"]
|
||||||
license = "GNU GPL v3"
|
license = "GNU GPL v3"
|
||||||
|
@ -14,6 +14,7 @@ python = "^3.8"
|
||||||
appdirs = "^1.4.4"
|
appdirs = "^1.4.4"
|
||||||
colorama = "^0.4.5"
|
colorama = "^0.4.5"
|
||||||
impacket = "^0.10.0"
|
impacket = "^0.10.0"
|
||||||
|
psutil = "^5.9.4"
|
||||||
requests = "^2.28.1"
|
requests = "^2.28.1"
|
||||||
toml = "^0.10.2"
|
toml = "^0.10.2"
|
||||||
Unidecode = "^1.3.1"
|
Unidecode = "^1.3.1"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
appdirs
|
appdirs
|
||||||
colorama
|
colorama
|
||||||
impacket
|
impacket
|
||||||
|
psutil
|
||||||
requests
|
requests
|
||||||
toml
|
toml
|
||||||
unidecode
|
unidecode
|
||||||
|
|
Loading…
Reference in New Issue