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):
|
||||
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):
|
||||
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}'
|
||||
])
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
appdirs
|
||||
colorama
|
||||
impacket
|
||||
psutil
|
||||
requests
|
||||
toml
|
||||
unidecode
|
||||
|
|
Loading…
Reference in New Issue