2015-08-05 18:36:39 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
The main controller class for Empire.
|
|
|
|
|
|
|
|
This is what's launched from ./empire.
|
|
|
|
Contains the Main, Listener, Agents, Agent, and Module
|
|
|
|
menu loops.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
import sys
|
|
|
|
import cmd
|
|
|
|
import sqlite3
|
|
|
|
import os
|
|
|
|
import hashlib
|
|
|
|
import time
|
|
|
|
# import traceback
|
2015-08-05 18:36:39 +00:00
|
|
|
from pydispatch import dispatcher
|
|
|
|
|
|
|
|
|
|
|
|
# Empire imports
|
|
|
|
import helpers
|
2016-07-21 01:28:27 +00:00
|
|
|
# import http
|
|
|
|
# import encryption
|
|
|
|
# import packets
|
2015-08-05 18:36:39 +00:00
|
|
|
import messages
|
|
|
|
import agents
|
|
|
|
import listeners
|
|
|
|
import modules
|
|
|
|
import stagers
|
|
|
|
import credentials
|
2016-07-21 01:28:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
# make version for Empire
|
|
|
|
VERSION = "1.5.2"
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
2015-11-22 01:03:40 +00:00
|
|
|
# custom exceptions used for nested menu navigation
|
2016-07-21 01:28:27 +00:00
|
|
|
class NavMain(Exception):
|
|
|
|
"""
|
|
|
|
Custom exception class used to navigate to the 'main' menu.
|
|
|
|
"""
|
|
|
|
pass
|
2015-11-22 01:03:40 +00:00
|
|
|
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
class NavAgents(Exception):
|
|
|
|
"""
|
|
|
|
Custom exception class used to navigate to the 'agents' menu.
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class NavListeners(Exception):
|
|
|
|
"""
|
|
|
|
Custom exception class used to navigate to the 'listeners' menu.
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
class MainMenu(cmd.Cmd):
|
|
|
|
"""
|
|
|
|
The main class used by Empire to drive the 'main' menu
|
|
|
|
displayed when Empire starts.
|
|
|
|
"""
|
2016-03-22 00:20:03 +00:00
|
|
|
def __init__(self, args=None, restAPI=False):
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
cmd.Cmd.__init__(self)
|
2016-07-21 01:28:27 +00:00
|
|
|
|
|
|
|
# globalOptions[optionName] = (value, required, description)
|
2015-08-05 18:36:39 +00:00
|
|
|
self.globalOptions = {}
|
|
|
|
|
|
|
|
# empty database object
|
|
|
|
self.conn = self.database_connect()
|
|
|
|
|
2016-03-22 00:20:03 +00:00
|
|
|
# pull out some common configuration information
|
|
|
|
(self.installPath, self.stage0, self.stage1, self.stage2, self.ipWhiteList, self.ipBlackList) = helpers.get_config('install_path,stage0_uri,stage1_uri,stage2_uri,ip_whitelist,ip_blacklist')
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# instantiate the agents, listeners, and stagers objects
|
|
|
|
self.agents = agents.Agents(self, args=args)
|
|
|
|
self.listeners = listeners.Listeners(self, args=args)
|
|
|
|
self.stagers = stagers.Stagers(self, args=args)
|
|
|
|
self.modules = modules.Modules(self, args=args)
|
|
|
|
self.credentials = credentials.Credentials(self, args=args)
|
|
|
|
|
|
|
|
# make sure all the references are passed after instantiation
|
|
|
|
self.agents.listeners = self.listeners
|
|
|
|
self.agents.modules = self.modules
|
|
|
|
self.agents.stagers = self.stagers
|
|
|
|
self.listeners.modules = self.modules
|
|
|
|
self.listeners.stagers = self.stagers
|
|
|
|
self.modules.stagers = self.stagers
|
|
|
|
|
|
|
|
# change the default prompt for the user
|
|
|
|
self.prompt = "(Empire) > "
|
|
|
|
self.do_help.__func__.__doc__ = '''Displays the help menu.'''
|
|
|
|
self.doc_header = 'Commands'
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
dispatcher.connect(self.handle_event, sender=dispatcher.Any)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-11-22 01:03:40 +00:00
|
|
|
# Main, Agents, or Listeners
|
|
|
|
self.menu_state = "Main"
|
|
|
|
|
2016-02-16 06:52:32 +00:00
|
|
|
# parse/handle any passed command line arguments
|
|
|
|
self.args = args
|
|
|
|
self.handle_args()
|
|
|
|
|
2016-03-22 00:20:03 +00:00
|
|
|
# start everything up normally if the RESTful API isn't being launched
|
|
|
|
if not restAPI:
|
|
|
|
self.startup()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
2016-02-16 06:52:32 +00:00
|
|
|
def handle_args(self):
|
|
|
|
"""
|
|
|
|
Handle any passed arguments.
|
|
|
|
"""
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2016-02-16 07:02:18 +00:00
|
|
|
if self.args.listener or self.args.stager:
|
2016-02-16 06:52:32 +00:00
|
|
|
# if we're displaying listeners/stagers or generating a stager
|
2016-02-16 07:02:18 +00:00
|
|
|
if self.args.listener:
|
|
|
|
if self.args.listener == 'list':
|
2016-02-16 06:52:32 +00:00
|
|
|
activeListeners = self.listeners.get_listeners()
|
|
|
|
messages.display_listeners(activeListeners)
|
|
|
|
else:
|
|
|
|
activeListeners = self.listeners.get_listeners()
|
2016-02-16 07:02:18 +00:00
|
|
|
targetListener = [l for l in activeListeners if self.args.listener in l[1]]
|
2016-02-16 06:52:32 +00:00
|
|
|
|
|
|
|
if targetListener:
|
|
|
|
targetListener = targetListener[0]
|
|
|
|
messages.display_listener_database(targetListener)
|
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("\n[!] No active listeners with name '%s'\n" % (self.args.listener))
|
2016-02-16 06:52:32 +00:00
|
|
|
|
|
|
|
else:
|
|
|
|
if self.args.stager == 'list':
|
|
|
|
print "\nStagers:\n"
|
|
|
|
print " Name Description"
|
|
|
|
print " ---- -----------"
|
2016-07-21 01:28:27 +00:00
|
|
|
for stagerName, stager in self.stagers.stagers.iteritems():
|
2016-02-16 06:52:32 +00:00
|
|
|
print " %s%s" % ('{0: <17}'.format(stagerName), stager.info['Description'])
|
|
|
|
print "\n"
|
|
|
|
else:
|
|
|
|
stagerName = self.args.stager
|
|
|
|
try:
|
|
|
|
targetStager = self.stagers.stagers[stagerName]
|
|
|
|
menu = StagerMenu(self, stagerName)
|
|
|
|
|
|
|
|
if self.args.stager_options:
|
|
|
|
for option in self.args.stager_options:
|
|
|
|
if '=' not in option:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("\n[!] Invalid option: '%s'" % (option))
|
2016-02-16 06:52:32 +00:00
|
|
|
print helpers.color("[!] Please use Option=Value format\n")
|
2016-07-21 01:28:27 +00:00
|
|
|
if self.conn:
|
|
|
|
self.conn.close()
|
2016-02-16 06:52:32 +00:00
|
|
|
sys.exit()
|
|
|
|
|
|
|
|
# split the passed stager options by = and set the appropriate option
|
|
|
|
optionName, optionValue = option.split('=')
|
2016-07-21 01:28:27 +00:00
|
|
|
menu.do_set("%s %s" % (optionName, optionValue))
|
2016-02-16 06:52:32 +00:00
|
|
|
|
|
|
|
# generate the stager
|
|
|
|
menu.do_generate('')
|
|
|
|
|
|
|
|
else:
|
|
|
|
messages.display_stager(stagerName, targetStager)
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
print e
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("\n[!] No current stager with name '%s'\n" % (stagerName))
|
2016-02-16 06:52:32 +00:00
|
|
|
|
|
|
|
# shutdown the database connection object
|
2016-07-21 01:28:27 +00:00
|
|
|
if self.conn:
|
|
|
|
self.conn.close()
|
|
|
|
|
2016-02-16 06:52:32 +00:00
|
|
|
sys.exit()
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def startup(self):
|
|
|
|
"""
|
|
|
|
Kick off all initial startup actions.
|
|
|
|
"""
|
|
|
|
|
|
|
|
self.database_connect()
|
|
|
|
|
|
|
|
# restart any listeners currently in the database
|
|
|
|
self.listeners.start_existing_listeners()
|
|
|
|
|
|
|
|
dispatcher.send("[*] Empire starting up...", sender="Empire")
|
|
|
|
|
|
|
|
|
|
|
|
def shutdown(self):
|
|
|
|
"""
|
|
|
|
Perform any shutdown actions.
|
|
|
|
"""
|
|
|
|
|
|
|
|
print "\n" + helpers.color("[!] Shutting down...\n")
|
|
|
|
# self.server.shutdown()
|
|
|
|
dispatcher.send("[*] Empire shutting down...", sender="Empire")
|
|
|
|
|
|
|
|
# enumerate all active servers/listeners and shut them down
|
|
|
|
self.listeners.shutdownall()
|
|
|
|
|
|
|
|
# shutdown the database connection object
|
|
|
|
if self.conn:
|
|
|
|
self.conn.close()
|
|
|
|
|
|
|
|
|
|
|
|
def database_connect(self):
|
2016-07-21 01:28:27 +00:00
|
|
|
"""
|
|
|
|
Connect to the default database at ./data/empire.db.
|
|
|
|
"""
|
2015-08-05 18:36:39 +00:00
|
|
|
try:
|
|
|
|
# set the database connectiont to autocommit w/ isolation level
|
|
|
|
self.conn = sqlite3.connect('./data/empire.db', check_same_thread=False)
|
2016-01-14 20:57:26 +00:00
|
|
|
self.conn.text_factory = str
|
2015-08-05 18:36:39 +00:00
|
|
|
self.conn.isolation_level = None
|
|
|
|
return self.conn
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
except Exception:
|
2015-08-05 18:36:39 +00:00
|
|
|
print helpers.color("[!] Could not connect to database")
|
|
|
|
print helpers.color("[!] Please run database_setup.py")
|
|
|
|
sys.exit()
|
|
|
|
|
2015-11-22 01:03:40 +00:00
|
|
|
# def preloop(self):
|
|
|
|
# traceback.print_stack()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
def cmdloop(self):
|
2015-11-22 01:03:40 +00:00
|
|
|
while True:
|
2015-08-05 18:36:39 +00:00
|
|
|
try:
|
2015-11-22 01:03:40 +00:00
|
|
|
if self.menu_state == "Agents":
|
|
|
|
self.do_agents("")
|
|
|
|
elif self.menu_state == "Listeners":
|
|
|
|
self.do_listeners("")
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
2015-11-22 01:03:40 +00:00
|
|
|
# display the main title
|
|
|
|
messages.title(VERSION)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-11-22 01:03:40 +00:00
|
|
|
# get active listeners, agents, and loaded modules
|
|
|
|
num_agents = self.agents.get_agents()
|
2016-07-21 01:28:27 +00:00
|
|
|
if num_agents:
|
2015-11-22 01:03:40 +00:00
|
|
|
num_agents = len(num_agents)
|
|
|
|
else:
|
|
|
|
num_agents = 0
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-11-22 01:03:40 +00:00
|
|
|
num_modules = self.modules.modules
|
2016-07-21 01:28:27 +00:00
|
|
|
if num_modules:
|
2015-11-22 01:03:40 +00:00
|
|
|
num_modules = len(num_modules)
|
|
|
|
else:
|
|
|
|
num_modules = 0
|
|
|
|
|
2016-03-22 01:50:19 +00:00
|
|
|
num_listeners = self.listeners.get_listeners()
|
2016-07-21 01:28:27 +00:00
|
|
|
if num_listeners:
|
2015-11-22 01:03:40 +00:00
|
|
|
num_listeners = len(num_listeners)
|
|
|
|
else:
|
|
|
|
num_listeners = 0
|
|
|
|
|
|
|
|
print " " + helpers.color(str(num_modules), "green") + " modules currently loaded\n"
|
|
|
|
print " " + helpers.color(str(num_listeners), "green") + " listeners currently active\n"
|
|
|
|
print " " + helpers.color(str(num_agents), "green") + " agents currently active\n\n"
|
|
|
|
|
|
|
|
cmd.Cmd.cmdloop(self)
|
|
|
|
|
|
|
|
# handle those pesky ctrl+c's
|
2015-08-05 18:36:39 +00:00
|
|
|
except KeyboardInterrupt as e:
|
2015-11-22 01:03:40 +00:00
|
|
|
self.menu_state = "Main"
|
|
|
|
try:
|
|
|
|
choice = raw_input(helpers.color("\n[>] Exit? [y/N] ", "red"))
|
|
|
|
if choice.lower() != "" and choice.lower()[0] == "y":
|
|
|
|
self.shutdown()
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
continue
|
|
|
|
except KeyboardInterrupt as e:
|
|
|
|
continue
|
|
|
|
|
|
|
|
# exception used to signal jumping to "Main" menu
|
|
|
|
except NavMain as e:
|
|
|
|
self.menu_state = "Main"
|
|
|
|
|
|
|
|
# exception used to signal jumping to "Agents" menu
|
|
|
|
except NavAgents as e:
|
|
|
|
self.menu_state = "Agents"
|
|
|
|
|
|
|
|
# exception used to signal jumping to "Listeners" menu
|
|
|
|
except NavListeners as e:
|
|
|
|
self.menu_state = "Listeners"
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-03-24 20:03:31 +00:00
|
|
|
except Exception as e:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("[!] Exception: %s" % (e))
|
2016-03-24 20:03:31 +00:00
|
|
|
time.sleep(5)
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# print a nicely formatted help menu
|
|
|
|
# stolen/adapted from recon-ng
|
2016-07-21 01:28:27 +00:00
|
|
|
def print_topics(self, header, commands, cmdlen, maxcol):
|
|
|
|
if commands:
|
|
|
|
self.stdout.write("%s\n" % str(header))
|
2015-08-05 18:36:39 +00:00
|
|
|
if self.ruler:
|
2016-07-21 01:28:27 +00:00
|
|
|
self.stdout.write("%s\n" % str(self.ruler * len(header)))
|
|
|
|
for command in commands:
|
|
|
|
self.stdout.write("%s %s\n" % (command.ljust(17), getattr(self, 'do_' + command).__doc__))
|
2015-08-05 18:36:39 +00:00
|
|
|
self.stdout.write("\n")
|
|
|
|
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
def emptyline(self):
|
|
|
|
pass
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def handle_event(self, signal, sender):
|
|
|
|
"""
|
|
|
|
Default event handler.
|
|
|
|
|
|
|
|
Signal Senders:
|
|
|
|
Empire - the main Empire controller (this file)
|
|
|
|
Agents - the Agents handler
|
|
|
|
Listeners - the Listeners handler
|
|
|
|
HttpHandler - the HTTP handler
|
|
|
|
EmpireServer - the Empire HTTP server
|
|
|
|
"""
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2016-02-18 01:06:33 +00:00
|
|
|
# if --debug X is passed, log out all dispatcher signals
|
2015-08-05 18:36:39 +00:00
|
|
|
if self.args.debug:
|
2016-02-18 01:06:33 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
debug_file = open("empire.debug", 'a')
|
|
|
|
debug_file.write(helpers.get_datetime() + " " + sender + " : " + signal + "\n")
|
|
|
|
debug_file.close()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-02-18 01:06:33 +00:00
|
|
|
if self.args.debug == '2':
|
|
|
|
# if --debug 2, also print the output to the screen
|
|
|
|
print " " + sender + " : " + signal
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# display specific signals from the agents.
|
|
|
|
if sender == "Agents":
|
|
|
|
if "[+] Initial agent" in signal:
|
|
|
|
print helpers.color(signal)
|
|
|
|
|
|
|
|
elif "[!] Agent" in signal and "exiting" in signal:
|
|
|
|
print helpers.color(signal)
|
|
|
|
|
2015-09-22 02:32:46 +00:00
|
|
|
elif "WARNING" in signal or "attempted overwrite" in signal:
|
|
|
|
print helpers.color(signal)
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
elif "on the blacklist" in signal:
|
|
|
|
print helpers.color(signal)
|
|
|
|
|
|
|
|
elif sender == "EmpireServer":
|
|
|
|
if "[!] Error starting listener" in signal:
|
|
|
|
print helpers.color(signal)
|
|
|
|
|
|
|
|
elif sender == "Listeners":
|
|
|
|
print helpers.color(signal)
|
|
|
|
|
|
|
|
|
|
|
|
###################################################
|
|
|
|
# CMD methods
|
|
|
|
###################################################
|
|
|
|
|
|
|
|
def default(self, line):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def do_exit(self, line):
|
|
|
|
"Exit Empire"
|
2015-11-22 01:03:40 +00:00
|
|
|
raise KeyboardInterrupt
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_agents(self, line):
|
|
|
|
"Jump to the Agents menu."
|
2015-11-24 05:41:16 +00:00
|
|
|
try:
|
2016-07-21 01:28:27 +00:00
|
|
|
agents_menu = AgentsMenu(self)
|
|
|
|
agents_menu.cmdloop()
|
2015-11-24 05:41:16 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise e
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_listeners(self, line):
|
|
|
|
"Interact with active listeners."
|
2015-11-24 05:41:16 +00:00
|
|
|
try:
|
2016-07-21 01:28:27 +00:00
|
|
|
listener_menu = ListenerMenu(self)
|
|
|
|
listener_menu.cmdloop()
|
2015-11-24 05:41:16 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise e
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_usestager(self, line):
|
|
|
|
"Use an Empire stager."
|
|
|
|
|
2015-11-24 05:41:16 +00:00
|
|
|
try:
|
|
|
|
parts = line.split(" ")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-11-24 05:41:16 +00:00
|
|
|
if parts[0] not in self.stagers.stagers:
|
|
|
|
print helpers.color("[!] Error: invalid stager module")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-11-24 05:41:16 +00:00
|
|
|
elif len(parts) == 1:
|
2016-07-21 01:28:27 +00:00
|
|
|
stager_menu = StagerMenu(self, parts[0])
|
|
|
|
stager_menu.cmdloop()
|
2015-11-24 05:41:16 +00:00
|
|
|
elif len(parts) == 2:
|
|
|
|
listener = parts[1]
|
|
|
|
if not self.listeners.is_listener_valid(listener):
|
|
|
|
print helpers.color("[!] Please enter a valid listener name or ID")
|
|
|
|
else:
|
|
|
|
self.stagers.set_stager_option('Listener', listener)
|
2016-07-21 01:28:27 +00:00
|
|
|
stager_menu = StagerMenu(self, parts[0])
|
|
|
|
stager_menu.cmdloop()
|
2015-11-24 05:41:16 +00:00
|
|
|
else:
|
|
|
|
print helpers.color("[!] Error in MainMenu's do_userstager()")
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-11-24 05:41:16 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise e
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-03-22 18:32:47 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_usemodule(self, line):
|
|
|
|
"Use an Empire module."
|
|
|
|
if line not in self.modules.modules:
|
|
|
|
print helpers.color("[!] Error: invalid module")
|
|
|
|
else:
|
2015-11-24 05:41:16 +00:00
|
|
|
try:
|
2016-07-21 01:28:27 +00:00
|
|
|
module_menu = ModuleMenu(self, line)
|
|
|
|
module_menu.cmdloop()
|
2015-11-24 05:41:16 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise e
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-03-22 18:32:47 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_searchmodule(self, line):
|
|
|
|
"Search Empire module names/descriptions."
|
2016-02-16 05:35:32 +00:00
|
|
|
self.modules.search_modules(line.strip())
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_creds(self, line):
|
|
|
|
"Add/display credentials to/from the database."
|
|
|
|
|
|
|
|
filterTerm = line.strip()
|
|
|
|
|
|
|
|
if filterTerm == "":
|
|
|
|
creds = self.credentials.get_credentials()
|
|
|
|
|
|
|
|
elif filterTerm.split()[0].lower() == "add":
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# add format: "domain username password <notes> <credType> <sid>
|
|
|
|
args = filterTerm.split()[1:]
|
|
|
|
|
|
|
|
if len(args) == 3:
|
|
|
|
domain, username, password = args
|
|
|
|
if helpers.validate_ntlm(password):
|
|
|
|
# credtype, domain, username, password, host, sid="", notes=""):
|
|
|
|
self.credentials.add_credential("hash", domain, username, password, "")
|
|
|
|
else:
|
|
|
|
self.credentials.add_credential("plaintext", domain, username, password, "")
|
|
|
|
|
|
|
|
elif len(args) == 4:
|
|
|
|
domain, username, password, notes = args
|
|
|
|
if helpers.validate_ntlm(password):
|
|
|
|
self.credentials.add_credential("hash", domain, username, password, "", notes=notes)
|
|
|
|
else:
|
|
|
|
self.credentials.add_credential("plaintext", domain, username, password, "", notes=notes)
|
|
|
|
|
|
|
|
elif len(args) == 5:
|
|
|
|
domain, username, password, notes, credType = args
|
|
|
|
self.credentials.add_credential(credType, domain, username, password, "", notes=notes)
|
|
|
|
|
|
|
|
elif len(args) == 6:
|
|
|
|
domain, username, password, notes, credType, sid = args
|
|
|
|
self.credentials.add_credential(credType, domain, username, password, "", sid=sid, notes=notes)
|
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Format is 'add domain username password <notes> <credType> <sid>")
|
|
|
|
return
|
|
|
|
|
|
|
|
creds = self.credentials.get_credentials()
|
|
|
|
|
|
|
|
elif filterTerm.split()[0].lower() == "remove":
|
|
|
|
|
|
|
|
try:
|
|
|
|
args = filterTerm.split()[1:]
|
2016-07-21 01:28:27 +00:00
|
|
|
if len(args) != 1:
|
2015-08-05 18:36:39 +00:00
|
|
|
print helpers.color("[!] Format is 'remove <credID>/<credID-credID>/all'")
|
|
|
|
else:
|
|
|
|
if args[0].lower() == "all":
|
|
|
|
choice = raw_input(helpers.color("[>] Remove all credentials from the database? [y/N] ", "red"))
|
|
|
|
if choice.lower() != "" and choice.lower()[0] == "y":
|
|
|
|
self.credentials.remove_all_credentials()
|
|
|
|
else:
|
|
|
|
if "," in args[0]:
|
|
|
|
credIDs = args[0].split(",")
|
|
|
|
self.credentials.remove_credentials(credIDs)
|
|
|
|
elif "-" in args[0]:
|
|
|
|
parts = args[0].split("-")
|
2016-07-21 01:28:27 +00:00
|
|
|
credIDs = [x for x in xrange(int(parts[0]), int(parts[1]) + 1)]
|
2015-08-05 18:36:39 +00:00
|
|
|
self.credentials.remove_credentials(credIDs)
|
|
|
|
else:
|
|
|
|
self.credentials.remove_credentials(args)
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
except Exception:
|
2015-08-05 18:36:39 +00:00
|
|
|
print helpers.color("[!] Error in remove command parsing.")
|
|
|
|
print helpers.color("[!] Format is 'remove <credID>/<credID-credID>/all'")
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
elif filterTerm.split()[0].lower() == "export":
|
|
|
|
args = filterTerm.split()[1:]
|
|
|
|
|
|
|
|
if len(args) != 1:
|
|
|
|
print helpers.color("[!] Please supply an output filename/filepath.")
|
|
|
|
return
|
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
self.credentials.export_credentials(args[0])
|
2015-08-05 18:36:39 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
elif filterTerm.split()[0].lower() == "plaintext":
|
|
|
|
creds = self.credentials.get_credentials(credtype="plaintext")
|
|
|
|
|
|
|
|
elif filterTerm.split()[0].lower() == "hash":
|
|
|
|
creds = self.credentials.get_credentials(credtype="hash")
|
|
|
|
|
|
|
|
elif filterTerm.split()[0].lower() == "krbtgt":
|
|
|
|
creds = self.credentials.get_krbtgt()
|
|
|
|
|
|
|
|
else:
|
|
|
|
creds = self.credentials.get_credentials(filterTerm=filterTerm)
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
messages.display_credentials(creds)
|
|
|
|
|
|
|
|
|
|
|
|
def do_set(self, line):
|
|
|
|
"Set a global option (e.g. IP whitelists)."
|
|
|
|
|
|
|
|
parts = line.split(" ")
|
|
|
|
if len(parts) == 1:
|
|
|
|
print helpers.color("[!] Please enter 'IP,IP-IP,IP/CIDR' or a file path.")
|
|
|
|
else:
|
|
|
|
if parts[0].lower() == "ip_whitelist":
|
|
|
|
if parts[1] != "" and os.path.exists(parts[1]):
|
2015-12-29 20:57:01 +00:00
|
|
|
try:
|
2016-07-21 01:28:27 +00:00
|
|
|
open_file = open(parts[1], 'r')
|
|
|
|
ipData = open_file.read()
|
|
|
|
open_file.close()
|
2015-12-29 20:57:01 +00:00
|
|
|
self.agents.ipWhiteList = helpers.generate_ip_list(ipData)
|
2016-07-21 01:28:27 +00:00
|
|
|
except Exception:
|
|
|
|
print helpers.color("[!] Error opening ip file %s" % (parts[1]))
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
self.agents.ipWhiteList = helpers.generate_ip_list(",".join(parts[1:]))
|
|
|
|
elif parts[0].lower() == "ip_blacklist":
|
|
|
|
if parts[1] != "" and os.path.exists(parts[1]):
|
2015-12-29 20:57:01 +00:00
|
|
|
try:
|
2016-07-21 01:28:27 +00:00
|
|
|
open_file = open(parts[1], 'r')
|
|
|
|
ipData = open_file.read()
|
|
|
|
open_file.close()
|
2015-12-29 20:57:01 +00:00
|
|
|
self.agents.ipBlackList = helpers.generate_ip_list(ipData)
|
2016-07-21 01:28:27 +00:00
|
|
|
except Exception:
|
|
|
|
print helpers.color("[!] Error opening ip file %s" % (parts[1]))
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
self.agents.ipBlackList = helpers.generate_ip_list(",".join(parts[1:]))
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please choose 'ip_whitelist' or 'ip_blacklist'")
|
|
|
|
|
|
|
|
|
|
|
|
def do_reset(self, line):
|
|
|
|
"Reset a global option (e.g. IP whitelists)."
|
|
|
|
|
|
|
|
if line.strip().lower() == "ip_whitelist":
|
|
|
|
self.agents.ipWhiteList = None
|
|
|
|
if line.strip().lower() == "ip_blacklist":
|
|
|
|
self.agents.ipBlackList = None
|
|
|
|
|
|
|
|
|
|
|
|
def do_show(self, line):
|
|
|
|
"Show a global option (e.g. IP whitelists)."
|
|
|
|
|
|
|
|
if line.strip().lower() == "ip_whitelist":
|
|
|
|
print self.agents.ipWhiteList
|
|
|
|
if line.strip().lower() == "ip_blacklist":
|
|
|
|
print self.agents.ipBlackList
|
|
|
|
|
|
|
|
|
2016-03-31 03:03:02 +00:00
|
|
|
def do_load(self, line):
|
|
|
|
"Loads Empire modules from a non-standard folder."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2016-03-31 03:03:02 +00:00
|
|
|
if line.strip() == '' or not os.path.isdir(line.strip()):
|
|
|
|
print "\n" + helpers.color("[!] Please specify a valid folder to load modules from.") + "\n"
|
|
|
|
else:
|
|
|
|
self.modules.load_modules(rootPath=line.strip())
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_reload(self, line):
|
|
|
|
"Reload one (or all) Empire modules."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
if line.strip().lower() == "all":
|
|
|
|
# reload all modules
|
|
|
|
print "\n" + helpers.color("[*] Reloading all modules.") + "\n"
|
|
|
|
self.modules.load_modules()
|
2016-03-31 03:03:02 +00:00
|
|
|
elif os.path.isdir(line.strip()):
|
|
|
|
# if we're loading an external directory
|
|
|
|
self.modules.load_modules(rootPath=line.strip())
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
if line.strip() not in self.modules.modules:
|
|
|
|
print helpers.color("[!] Error: invalid module")
|
|
|
|
else:
|
|
|
|
print "\n" + helpers.color("[*] Reloading module: " + line) + "\n"
|
|
|
|
self.modules.reload_module(line)
|
|
|
|
|
|
|
|
|
2015-08-20 23:08:40 +00:00
|
|
|
def do_list(self, line):
|
|
|
|
"Lists active agents or listeners."
|
|
|
|
|
|
|
|
parts = line.split(" ")
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
if parts[0].lower() == "agents":
|
2015-08-20 23:08:40 +00:00
|
|
|
|
|
|
|
line = " ".join(parts[1:])
|
2016-07-21 01:28:27 +00:00
|
|
|
all_agents = self.agents.get_agents()
|
2015-08-20 23:08:40 +00:00
|
|
|
|
|
|
|
if line.strip().lower() == "stale":
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
agents_to_display = []
|
2015-08-20 23:08:40 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
for agent in all_agents:
|
2015-08-20 23:08:40 +00:00
|
|
|
|
|
|
|
# max check in -> delay + delay*jitter
|
2016-07-21 01:28:27 +00:00
|
|
|
intervalMax = (agent[4] + agent[4] * agent[5]) + 30
|
2015-08-20 23:08:40 +00:00
|
|
|
|
|
|
|
# get the agent last check in time
|
2016-07-21 01:28:27 +00:00
|
|
|
agent_time = time.mktime(time.strptime(agent[16], "%Y-%m-%d %H:%M:%S"))
|
|
|
|
if agent_time < time.mktime(time.localtime()) - intervalMax:
|
2015-08-20 23:08:40 +00:00
|
|
|
# if the last checkin time exceeds the limit, remove it
|
2016-07-21 01:28:27 +00:00
|
|
|
agents_to_display.append(agent)
|
2015-08-20 23:08:40 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
messages.display_staleagents(agents_to_display)
|
2015-08-20 23:08:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
elif line.strip() != "":
|
|
|
|
# if we're listing an agents active in the last X minutes
|
|
|
|
try:
|
|
|
|
minutes = int(line.strip())
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-20 23:08:40 +00:00
|
|
|
# grab just the agents active within the specified window (in minutes)
|
2016-07-21 01:28:27 +00:00
|
|
|
agents_to_display = []
|
|
|
|
for agent in all_agents:
|
|
|
|
agent_time = time.mktime(time.strptime(agent[16], "%Y-%m-%d %H:%M:%S"))
|
|
|
|
|
|
|
|
if agent_time > time.mktime(time.localtime()) - (int(minutes) * 60):
|
|
|
|
agents_to_display.append(agent)
|
2015-08-20 23:08:40 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
messages.display_agents(agents_to_display)
|
2015-08-20 23:08:40 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
except Exception:
|
2015-08-20 23:08:40 +00:00
|
|
|
print helpers.color("[!] Please enter the minute window for agent checkin.")
|
|
|
|
|
|
|
|
else:
|
|
|
|
messages.display_agents(agents)
|
|
|
|
|
|
|
|
|
|
|
|
elif parts[0].lower() == "listeners":
|
|
|
|
|
|
|
|
messages.display_listeners(self.listeners.get_listeners())
|
|
|
|
|
|
|
|
|
2016-07-15 22:56:38 +00:00
|
|
|
def do_interact(self, line):
|
|
|
|
"Interact with a particular agent."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2016-07-15 22:56:38 +00:00
|
|
|
name = line.strip()
|
|
|
|
|
|
|
|
if name != "" and self.agents.is_agent_present(name):
|
|
|
|
# resolve the passed name to a sessionID
|
|
|
|
sessionID = self.agents.get_agent_id(name)
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
agent_menu = AgentMenu(self, sessionID)
|
|
|
|
agent_menu.cmdloop()
|
2016-07-15 22:56:38 +00:00
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid agent name")
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def complete_usemodule(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an Empire PowerShell module path."
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
module_names = self.modules.modules.keys()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
2016-07-21 01:28:27 +00:00
|
|
|
return [s[offs:] for s in module_names if s.startswith(mline)]
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def complete_reload(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an Empire PowerShell module path."
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
module_names = self.modules.modules.keys() + ["all"]
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
2016-07-21 01:28:27 +00:00
|
|
|
return [s[offs:] for s in module_names if s.startswith(mline)]
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def complete_usestager(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an Empire stager module path."
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
stager_names = self.stagers.stagers.keys()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
if (line.split(" ")[1].lower() in stager_names) and line.endswith(" "):
|
2015-08-05 18:36:39 +00:00
|
|
|
# if we already have a stager name, tab-complete listener names
|
2016-07-21 01:28:27 +00:00
|
|
|
listener_names = self.listeners.get_listener_names()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
end_line = " ".join(line.split(" ")[1:])
|
|
|
|
mline = end_line.partition(' ')[2]
|
2015-08-05 18:36:39 +00:00
|
|
|
offs = len(mline) - len(text)
|
2016-07-21 01:28:27 +00:00
|
|
|
return [s[offs:] for s in listener_names if s.startswith(mline)]
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
# otherwise tab-complate the stager names
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
2016-07-21 01:28:27 +00:00
|
|
|
return [s[offs:] for s in stager_names if s.startswith(mline)]
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def complete_set(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a global option."
|
|
|
|
|
|
|
|
options = ["ip_whitelist", "ip_blacklist"]
|
|
|
|
|
|
|
|
if line.split(" ")[1].lower() in options:
|
2016-07-21 01:28:27 +00:00
|
|
|
return helpers.complete_path(text, line, arg=True)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in options if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
2016-03-31 03:03:02 +00:00
|
|
|
def complete_load(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a module load path."
|
2016-07-21 01:28:27 +00:00
|
|
|
return helpers.complete_path(text, line)
|
2016-03-31 03:03:02 +00:00
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def complete_reset(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a global option."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
return self.complete_set(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_show(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a global option."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
return self.complete_set(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_creds(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete 'creds' commands."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
|
|
|
commands = ["add", "remove", "export", "hash", "plaintext", "krbtgt"]
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in commands if s.startswith(mline)]
|
|
|
|
|
2016-07-15 22:56:38 +00:00
|
|
|
def complete_interact(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an interact command"
|
|
|
|
|
|
|
|
names = self.agents.get_agent_names()
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in names if s.startswith(mline)]
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
class AgentsMenu(cmd.Cmd):
|
2016-07-21 01:28:27 +00:00
|
|
|
"""
|
|
|
|
The main class used by Empire to drive the 'agents' menu.
|
|
|
|
"""
|
2015-08-05 18:36:39 +00:00
|
|
|
def __init__(self, mainMenu):
|
|
|
|
cmd.Cmd.__init__(self)
|
|
|
|
|
|
|
|
self.mainMenu = mainMenu
|
|
|
|
|
|
|
|
self.doc_header = 'Commands'
|
|
|
|
|
|
|
|
# set the prompt text
|
2016-07-21 01:28:27 +00:00
|
|
|
self.prompt = '(Empire: ' + helpers.color("agents", color="blue") + ') > '
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
messages.display_agents(self.mainMenu.agents.get_agents())
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-11-22 01:03:40 +00:00
|
|
|
# def preloop(self):
|
|
|
|
# traceback.print_stack()
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# print a nicely formatted help menu
|
2016-03-22 00:20:03 +00:00
|
|
|
# stolen/adapted from recon-ng
|
2016-07-21 01:28:27 +00:00
|
|
|
def print_topics(self, header, commands, cmdlen, maxcol):
|
|
|
|
if commands:
|
|
|
|
self.stdout.write("%s\n" % str(header))
|
2015-08-05 18:36:39 +00:00
|
|
|
if self.ruler:
|
2016-07-21 01:28:27 +00:00
|
|
|
self.stdout.write("%s\n" % str(self.ruler * len(header)))
|
|
|
|
for command in commands:
|
|
|
|
self.stdout.write("%s %s\n" % (command.ljust(17), getattr(self, 'do_' + command).__doc__))
|
2015-08-05 18:36:39 +00:00
|
|
|
self.stdout.write("\n")
|
|
|
|
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
def emptyline(self):
|
|
|
|
pass
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_back(self, line):
|
2016-03-22 18:32:47 +00:00
|
|
|
"Go back to the main menu."
|
|
|
|
raise NavMain()
|
|
|
|
|
|
|
|
|
|
|
|
def do_listeners(self, line):
|
|
|
|
"Jump to the listeners menu."
|
|
|
|
raise NavListeners()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_main(self, line):
|
|
|
|
"Go back to the main menu."
|
2015-11-22 01:03:40 +00:00
|
|
|
raise NavMain()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_exit(self, line):
|
|
|
|
"Exit Empire."
|
2015-11-22 01:03:40 +00:00
|
|
|
raise KeyboardInterrupt
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_list(self, line):
|
2015-08-20 23:08:40 +00:00
|
|
|
"Lists all active agents (or listeners)."
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-08-20 23:08:40 +00:00
|
|
|
if line.lower().startswith("listeners"):
|
|
|
|
self.mainMenu.do_list("listeners " + str(" ".join(line.split(" ")[1:])))
|
|
|
|
elif line.lower().startswith("agents"):
|
|
|
|
self.mainMenu.do_list("agents " + str(" ".join(line.split(" ")[1:])))
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
2015-08-20 23:08:40 +00:00
|
|
|
self.mainMenu.do_list("agents " + str(line))
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_rename(self, line):
|
|
|
|
"Rename a particular agent."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
parts = line.strip().split(" ")
|
|
|
|
|
|
|
|
# name sure we get an old name and new name for the agent
|
|
|
|
if len(parts) == 2:
|
|
|
|
# replace the old name with the new name
|
|
|
|
self.mainMenu.agents.rename_agent(parts[0], parts[1])
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter an agent name and new name")
|
|
|
|
|
|
|
|
|
|
|
|
def do_interact(self, line):
|
|
|
|
"Interact with a particular agent."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
name = line.strip()
|
|
|
|
|
|
|
|
if name != "" and self.mainMenu.agents.is_agent_present(name):
|
|
|
|
# resolve the passed name to a sessionID
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(name)
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
agent_menu = AgentMenu(self.mainMenu, sessionID)
|
|
|
|
agent_menu.cmdloop()
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid agent name")
|
|
|
|
|
|
|
|
|
|
|
|
def do_kill(self, line):
|
|
|
|
"Task one or more agents to exit."
|
|
|
|
|
|
|
|
name = line.strip()
|
|
|
|
|
|
|
|
if name.lower() == "all":
|
|
|
|
try:
|
|
|
|
choice = raw_input(helpers.color("[>] Kill all agents? [y/N] ", "red"))
|
|
|
|
if choice.lower() != "" and choice.lower()[0] == "y":
|
2016-07-21 01:28:27 +00:00
|
|
|
all_agents = self.mainMenu.agents.get_agents()
|
|
|
|
for agent in all_agents:
|
2015-08-05 18:36:39 +00:00
|
|
|
sessionID = agent[1]
|
|
|
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_EXIT")
|
2016-07-21 01:28:27 +00:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
print ""
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
else:
|
|
|
|
# extract the sessionID and clear the agent tasking
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(name)
|
|
|
|
|
|
|
|
if sessionID and len(sessionID) != 0:
|
|
|
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_EXIT")
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Invalid agent name")
|
|
|
|
|
|
|
|
|
|
|
|
def do_creds(self, line):
|
|
|
|
"Display/return credentials from the database."
|
|
|
|
self.mainMenu.do_creds(line)
|
|
|
|
|
|
|
|
|
|
|
|
def do_clear(self, line):
|
|
|
|
"Clear one or more agent's taskings."
|
|
|
|
|
|
|
|
name = line.strip()
|
|
|
|
|
|
|
|
if name.lower() == "all":
|
|
|
|
self.mainMenu.agents.clear_agent_tasks("all")
|
2015-11-22 22:25:28 +00:00
|
|
|
elif name.lower() == "autorun":
|
|
|
|
self.mainMenu.agents.clear_autoruns()
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
# extract the sessionID and clear the agent tasking
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(name)
|
|
|
|
|
|
|
|
if sessionID and len(sessionID) != 0:
|
|
|
|
self.mainMenu.agents.clear_agent_tasks(sessionID)
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Invalid agent name")
|
|
|
|
|
|
|
|
|
|
|
|
def do_sleep(self, line):
|
|
|
|
"Task one or more agents to 'sleep [agent/all] interval [jitter]'"
|
|
|
|
|
|
|
|
parts = line.strip().split(" ")
|
|
|
|
|
|
|
|
if len(parts) == 1:
|
|
|
|
print helpers.color("[!] Please enter 'interval [jitter]'")
|
|
|
|
|
|
|
|
elif parts[0].lower() == "all":
|
|
|
|
delay = parts[1]
|
|
|
|
jitter = 0.0
|
|
|
|
if len(parts) == 3:
|
|
|
|
jitter = parts[2]
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
all_agents = self.mainMenu.agents.get_agents()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
for agent in all_agents:
|
2015-08-05 18:36:39 +00:00
|
|
|
sessionID = agent[1]
|
|
|
|
# update this agent info in the database
|
|
|
|
self.mainMenu.agents.set_agent_field("delay", delay, sessionID)
|
|
|
|
self.mainMenu.agents.set_agent_field("jitter", jitter, sessionID)
|
|
|
|
# task the agent
|
|
|
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_SHELL", "Set-Delay " + str(delay) + " " + str(jitter))
|
|
|
|
# update the agent log
|
|
|
|
msg = "Tasked agent to delay sleep/jitter " + str(delay) + "/" + str(jitter)
|
|
|
|
self.mainMenu.agents.save_agent_log(sessionID, msg)
|
|
|
|
|
|
|
|
else:
|
|
|
|
# extract the sessionID and clear the agent tasking
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(parts[0])
|
|
|
|
|
|
|
|
delay = parts[1]
|
|
|
|
jitter = 0.0
|
|
|
|
if len(parts) == 3:
|
|
|
|
jitter = parts[2]
|
|
|
|
|
|
|
|
if sessionID and len(sessionID) != 0:
|
|
|
|
# update this agent's information in the database
|
|
|
|
self.mainMenu.agents.set_agent_field("delay", delay, sessionID)
|
|
|
|
self.mainMenu.agents.set_agent_field("jitter", jitter, sessionID)
|
|
|
|
|
|
|
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_SHELL", "Set-Delay " + str(delay) + " " + str(jitter))
|
|
|
|
# update the agent log
|
|
|
|
msg = "Tasked agent to delay sleep/jitter " + str(delay) + "/" + str(jitter)
|
|
|
|
self.mainMenu.agents.save_agent_log(sessionID, msg)
|
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Invalid agent name")
|
|
|
|
|
2015-08-12 01:48:21 +00:00
|
|
|
|
2015-08-10 22:50:18 +00:00
|
|
|
def do_lostlimit(self, line):
|
|
|
|
"Task one or more agents to 'lostlimit [agent/all] <#ofCBs> '"
|
2015-08-10 02:18:02 +00:00
|
|
|
|
|
|
|
parts = line.strip().split(" ")
|
|
|
|
|
|
|
|
if len(parts) == 1:
|
|
|
|
print helpers.color("[!] Please enter a valid '#ofCBs'")
|
|
|
|
|
|
|
|
elif parts[0].lower() == "all":
|
2016-07-21 01:28:27 +00:00
|
|
|
lost_limit = parts[1]
|
|
|
|
all_agents = self.mainMenu.agents.get_agents()
|
2015-08-10 02:18:02 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
for agent in all_agents:
|
2015-08-10 02:18:02 +00:00
|
|
|
sessionID = agent[1]
|
|
|
|
# update this agent info in the database
|
2016-07-21 01:28:27 +00:00
|
|
|
self.mainMenu.agents.set_agent_field("lost_limit", lost_limit, sessionID)
|
2015-08-10 02:18:02 +00:00
|
|
|
# task the agent
|
2016-07-21 01:28:27 +00:00
|
|
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_SHELL", "Set-LostLimit " + str(lost_limit))
|
2015-08-10 02:18:02 +00:00
|
|
|
# update the agent log
|
2016-07-21 01:28:27 +00:00
|
|
|
msg = "Tasked agent to change lost limit %s" % (lost_limit)
|
2015-08-10 02:18:02 +00:00
|
|
|
self.mainMenu.agents.save_agent_log(sessionID, msg)
|
|
|
|
|
|
|
|
else:
|
|
|
|
# extract the sessionID and clear the agent tasking
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(parts[0])
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
lost_limit = parts[1]
|
2015-08-10 02:18:02 +00:00
|
|
|
|
|
|
|
if sessionID and len(sessionID) != 0:
|
|
|
|
# update this agent's information in the database
|
2016-07-21 01:28:27 +00:00
|
|
|
self.mainMenu.agents.set_agent_field("lost_limit", lost_limit, sessionID)
|
2015-08-10 02:18:02 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_SHELL", "Set-LostLimit " + str(lost_limit))
|
2015-08-10 02:18:02 +00:00
|
|
|
# update the agent log
|
2016-07-21 01:28:27 +00:00
|
|
|
msg = "Tasked agent to change lost limit %s" % (lost_limit)
|
2015-08-10 02:18:02 +00:00
|
|
|
self.mainMenu.agents.save_agent_log(sessionID, msg)
|
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Invalid agent name")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-08-12 01:48:21 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_killdate(self, line):
|
|
|
|
"Set the killdate for one or more agents (killdate [agent/all] 01/01/2016)."
|
|
|
|
|
|
|
|
parts = line.strip().split(" ")
|
|
|
|
|
|
|
|
if len(parts) == 1:
|
|
|
|
print helpers.color("[!] Please enter date in form 01/01/2016")
|
|
|
|
|
|
|
|
elif parts[0].lower() == "all":
|
|
|
|
date = parts[1]
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
all_agents = self.mainMenu.agents.get_agents()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
for agent in all_agents:
|
2015-08-05 18:36:39 +00:00
|
|
|
sessionID = agent[1]
|
|
|
|
# update this agent's field in the database
|
|
|
|
self.mainMenu.agents.set_agent_field("kill_date", date, sessionID)
|
|
|
|
# task the agent
|
|
|
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_SHELL", "Set-KillDate " + str(date))
|
|
|
|
msg = "Tasked agent to set killdate to " + str(date)
|
|
|
|
self.mainMenu.agents.save_agent_log(sessionID, msg)
|
|
|
|
|
|
|
|
else:
|
|
|
|
# extract the sessionID and clear the agent tasking
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(parts[0])
|
|
|
|
|
|
|
|
date = parts[1]
|
|
|
|
|
|
|
|
if sessionID and len(sessionID) != 0:
|
|
|
|
# update this agent's field in the database
|
|
|
|
self.mainMenu.agents.set_agent_field("kill_date", date, sessionID)
|
|
|
|
# task the agent
|
|
|
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_SHELL", "Set-KillDate " + str(date))
|
|
|
|
# update the agent log
|
|
|
|
msg = "Tasked agent to set killdate to " + str(date)
|
|
|
|
self.mainMenu.agents.save_agent_log(sessionID, msg)
|
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Invalid agent name")
|
|
|
|
|
|
|
|
|
|
|
|
def do_workinghours(self, line):
|
|
|
|
"Set the workinghours for one or more agents (workinghours [agent/all] 9:00-17:00)."
|
|
|
|
|
|
|
|
parts = line.strip().split(" ")
|
|
|
|
|
|
|
|
if len(parts) == 1:
|
|
|
|
print helpers.color("[!] Please enter hours in the form '9:00-17:00'")
|
|
|
|
|
|
|
|
elif parts[0].lower() == "all":
|
|
|
|
hours = parts[1]
|
2016-07-21 01:28:27 +00:00
|
|
|
hours = hours.replace(",", "-")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
all_agents = self.mainMenu.agents.get_agents()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
for agent in all_agents:
|
2015-08-05 18:36:39 +00:00
|
|
|
sessionID = agent[1]
|
|
|
|
# update this agent's field in the database
|
|
|
|
self.mainMenu.agents.set_agent_field("working_hours", hours, sessionID)
|
|
|
|
# task the agent
|
|
|
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_SHELL", "Set-WorkingHours " + str(hours))
|
2016-07-21 01:28:27 +00:00
|
|
|
msg = "Tasked agent to set working hours to %s" % (hours)
|
2015-08-05 18:36:39 +00:00
|
|
|
self.mainMenu.agents.save_agent_log(sessionID, msg)
|
|
|
|
|
|
|
|
else:
|
|
|
|
# extract the sessionID and clear the agent tasking
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(parts[0])
|
|
|
|
|
|
|
|
hours = parts[1]
|
2016-07-21 01:28:27 +00:00
|
|
|
hours = hours.replace(",", "-")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
if sessionID and len(sessionID) != 0:
|
2016-07-21 01:28:27 +00:00
|
|
|
# update this agent's field in the database
|
2015-08-05 18:36:39 +00:00
|
|
|
self.mainMenu.agents.set_agent_field("working_hours", hours, sessionID)
|
|
|
|
# task the agent
|
|
|
|
self.mainMenu.agents.add_agent_task(sessionID, "TASK_SHELL", "Set-WorkingHours " + str(hours))
|
|
|
|
|
|
|
|
# update the agent log
|
|
|
|
msg = "Tasked agent to set working hours to " + str(hours)
|
|
|
|
self.mainMenu.agents.save_agent_log(sessionID, msg)
|
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Invalid agent name")
|
|
|
|
|
|
|
|
|
|
|
|
def do_remove(self, line):
|
|
|
|
"Remove one or more agents from the database."
|
|
|
|
|
|
|
|
name = line.strip()
|
|
|
|
|
|
|
|
if name.lower() == "all":
|
|
|
|
try:
|
|
|
|
choice = raw_input(helpers.color("[>] Remove all agents from the database? [y/N] ", "red"))
|
|
|
|
if choice.lower() != "" and choice.lower()[0] == "y":
|
|
|
|
self.mainMenu.agents.remove_agent('%')
|
2016-07-21 01:28:27 +00:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
print ""
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-08-12 01:59:19 +00:00
|
|
|
elif name.lower() == "stale":
|
|
|
|
# remove 'stale' agents that have missed their checkin intervals
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
all_agents = self.mainMenu.agents.get_agents()
|
|
|
|
|
|
|
|
for agent in all_agents:
|
2015-08-12 01:59:19 +00:00
|
|
|
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(agent[3])
|
|
|
|
|
|
|
|
# max check in -> delay + delay*jitter
|
2016-07-21 01:28:27 +00:00
|
|
|
interval_max = (agent[4] + agent[4] * agent[5]) + 30
|
2015-08-12 01:59:19 +00:00
|
|
|
|
|
|
|
# get the agent last check in time
|
2016-07-21 01:28:27 +00:00
|
|
|
agent_time = time.mktime(time.strptime(agent[16], "%Y-%m-%d %H:%M:%S"))
|
2015-08-12 01:59:19 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
if agent_time < time.mktime(time.localtime()) - interval_max:
|
2015-08-12 01:59:19 +00:00
|
|
|
# if the last checkin time exceeds the limit, remove it
|
2016-07-21 01:28:27 +00:00
|
|
|
self.mainMenu.agents.remove_agent(sessionID)
|
2015-08-12 01:59:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
elif name.isdigit():
|
2015-08-12 01:48:21 +00:00
|
|
|
# if we're removing agents that checked in longer than X minutes ago
|
2016-07-21 01:28:27 +00:00
|
|
|
all_agents = self.mainMenu.agents.get_agents()
|
2015-08-12 01:48:21 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
minutes = int(line.strip())
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-12 01:48:21 +00:00
|
|
|
# grab just the agents active within the specified window (in minutes)
|
2016-07-21 01:28:27 +00:00
|
|
|
for agent in all_agents:
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-08-12 01:48:21 +00:00
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(agent[3])
|
|
|
|
|
|
|
|
# get the agent last check in time
|
2016-07-21 01:28:27 +00:00
|
|
|
agentTime = time.mktime(time.strptime(agent[16], "%Y-%m-%d %H:%M:%S"))
|
2015-08-12 01:48:21 +00:00
|
|
|
|
|
|
|
if agentTime < time.mktime(time.localtime()) - (int(minutes) * 60):
|
|
|
|
# if the last checkin time exceeds the limit, remove it
|
|
|
|
self.mainMenu.agents.remove_agent(sessionID)
|
|
|
|
|
|
|
|
except:
|
|
|
|
print helpers.color("[!] Please enter the minute window for agent checkin.")
|
|
|
|
|
|
|
|
else:
|
2015-08-05 18:36:39 +00:00
|
|
|
# extract the sessionID and clear the agent tasking
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(name)
|
|
|
|
|
|
|
|
if sessionID and len(sessionID) != 0:
|
|
|
|
self.mainMenu.agents.remove_agent(sessionID)
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Invalid agent name")
|
|
|
|
|
|
|
|
|
|
|
|
def do_usestager(self, line):
|
|
|
|
"Use an Empire stager."
|
|
|
|
|
|
|
|
parts = line.split(" ")
|
|
|
|
|
|
|
|
if parts[0] not in self.mainMenu.stagers.stagers:
|
|
|
|
print helpers.color("[!] Error: invalid stager module")
|
|
|
|
|
|
|
|
elif len(parts) == 1:
|
2016-07-21 01:28:27 +00:00
|
|
|
stager_menu = StagerMenu(self.mainMenu, parts[0])
|
|
|
|
stager_menu.cmdloop()
|
2015-08-05 18:36:39 +00:00
|
|
|
elif len(parts) == 2:
|
|
|
|
listener = parts[1]
|
|
|
|
if not self.mainMenu.listeners.is_listener_valid(listener):
|
|
|
|
print helpers.color("[!] Please enter a valid listener name or ID")
|
|
|
|
else:
|
|
|
|
self.mainMenu.stagers.set_stager_option('Listener', listener)
|
2016-07-21 01:28:27 +00:00
|
|
|
stager_menu = StagerMenu(self.mainMenu, parts[0])
|
|
|
|
stager_menu.cmdloop()
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
print helpers.color("[!] Error in AgentsMenu's do_userstager()")
|
|
|
|
|
|
|
|
|
|
|
|
def do_usemodule(self, line):
|
|
|
|
"Use an Empire PowerShell module."
|
|
|
|
|
|
|
|
module = line.strip()
|
|
|
|
|
|
|
|
if module not in self.mainMenu.modules.modules:
|
|
|
|
print helpers.color("[!] Error: invalid module")
|
|
|
|
else:
|
|
|
|
# set agent to "all"
|
2016-07-21 01:28:27 +00:00
|
|
|
module_menu = ModuleMenu(self.mainMenu, line, agent="all")
|
|
|
|
module_menu.cmdloop()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_searchmodule(self, line):
|
|
|
|
"Search Empire module names/descriptions."
|
|
|
|
|
|
|
|
searchTerm = line.strip()
|
|
|
|
|
|
|
|
if searchTerm.strip() == "":
|
|
|
|
print helpers.color("[!] Please enter a search term.")
|
|
|
|
else:
|
|
|
|
self.mainMenu.modules.search_modules(searchTerm)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_interact(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an interact command"
|
|
|
|
|
|
|
|
names = self.mainMenu.agents.get_agent_names()
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in names if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_rename(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a rename command"
|
|
|
|
|
|
|
|
return self.complete_interact(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_clear(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a clear command"
|
|
|
|
|
2015-11-22 22:25:28 +00:00
|
|
|
names = self.mainMenu.agents.get_agent_names() + ["all", "autorun"]
|
2015-08-05 18:36:39 +00:00
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in names if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_remove(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a remove command"
|
|
|
|
|
2015-08-15 21:58:44 +00:00
|
|
|
names = self.mainMenu.agents.get_agent_names() + ["all", "stale"]
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in names if s.startswith(mline)]
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2016-04-15 18:42:12 +00:00
|
|
|
def complete_list(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a list command"
|
|
|
|
|
|
|
|
options = ["stale"]
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in options if s.startswith(mline)]
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def complete_kill(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a kill command"
|
|
|
|
|
|
|
|
return self.complete_clear(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_sleep(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a sleep command"
|
|
|
|
|
|
|
|
return self.complete_clear(text, line, begidx, endidx)
|
|
|
|
|
2015-08-15 21:58:44 +00:00
|
|
|
|
2015-08-10 22:50:18 +00:00
|
|
|
def complete_lostlimit(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a lostlimit command"
|
2015-08-10 02:18:02 +00:00
|
|
|
|
|
|
|
return self.complete_clear(text, line, begidx, endidx)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-08-15 21:58:44 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def complete_killdate(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a killdate command"
|
|
|
|
|
|
|
|
return self.complete_clear(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_workinghours(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a workinghours command"
|
|
|
|
|
|
|
|
return self.complete_clear(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_usemodule(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an Empire PowerShell module path"
|
|
|
|
return self.mainMenu.complete_usemodule(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_usestager(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an Empire stager module path."
|
|
|
|
return self.mainMenu.complete_usestager(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_creds(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete 'creds' commands."
|
|
|
|
return self.mainMenu.complete_creds(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
2015-08-12 01:48:21 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
class AgentMenu(cmd.Cmd):
|
2016-07-21 01:28:27 +00:00
|
|
|
"""
|
|
|
|
The main class used by Empire to drive an individual 'agent' menu.
|
|
|
|
"""
|
2015-08-05 18:36:39 +00:00
|
|
|
def __init__(self, mainMenu, sessionID):
|
|
|
|
|
|
|
|
cmd.Cmd.__init__(self)
|
|
|
|
|
|
|
|
self.mainMenu = mainMenu
|
|
|
|
|
|
|
|
self.sessionID = sessionID
|
|
|
|
|
|
|
|
self.doc_header = 'Agent Commands'
|
|
|
|
|
|
|
|
# try to resolve the sessionID to a name
|
|
|
|
name = self.mainMenu.agents.get_agent_name(sessionID)
|
|
|
|
|
|
|
|
# set the text prompt
|
2016-07-21 01:28:27 +00:00
|
|
|
self.prompt = '(Empire: ' + helpers.color(name, 'red') + ') > '
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-08-20 18:35:42 +00:00
|
|
|
# agent commands that have opsec-safe alises in the agent code
|
2016-07-21 01:28:27 +00:00
|
|
|
self.agentCommands = ["ls", "dir", "rm", "del", "cp", "copy", "pwd", "cat", "cd", "mkdir", "rmdir", "mv", "move", "ipconfig", "ifconfig", "route", "reboot", "restart", "shutdown", "ps", "tasklist", "getpid", "whoami", "getuid", "hostname"]
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# listen for messages from this specific agent
|
2016-07-21 01:28:27 +00:00
|
|
|
dispatcher.connect(self.handle_agent_event, sender=dispatcher.Any)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# display any results from the database that were stored
|
|
|
|
# while we weren't interacting with the agent
|
|
|
|
results = self.mainMenu.agents.get_agent_results(self.sessionID)
|
|
|
|
if results:
|
|
|
|
print "\n" + results.rstrip('\r\n')
|
|
|
|
|
2015-11-22 01:03:40 +00:00
|
|
|
# def preloop(self):
|
|
|
|
# traceback.print_stack()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
def handle_agent_event(self, signal, sender):
|
|
|
|
"""
|
|
|
|
Handle agent event signals.
|
|
|
|
"""
|
2016-07-21 01:28:27 +00:00
|
|
|
|
|
|
|
if "[!] Agent" in signal and "exiting" in signal:
|
|
|
|
pass
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
name = self.mainMenu.agents.get_agent_name(self.sessionID)
|
|
|
|
|
|
|
|
if (str(self.sessionID) + " returned results" in signal) or (str(name) + " returned results" in signal):
|
|
|
|
# display any results returned by this agent that are returned
|
|
|
|
# while we are interacting with it
|
|
|
|
results = self.mainMenu.agents.get_agent_results(self.sessionID)
|
|
|
|
if results:
|
|
|
|
print "\n" + results
|
|
|
|
|
|
|
|
elif "[+] Part of file" in signal and "saved" in signal:
|
|
|
|
if (str(self.sessionID) in signal) or (str(name) in signal):
|
|
|
|
print helpers.color(signal)
|
|
|
|
|
|
|
|
|
|
|
|
# print a nicely formatted help menu
|
|
|
|
# stolen/adapted from recon-ng
|
2016-07-21 01:28:27 +00:00
|
|
|
def print_topics(self, header, commands, cmdlen, maxcol):
|
|
|
|
if commands:
|
|
|
|
self.stdout.write("%s\n" % str(header))
|
2015-08-05 18:36:39 +00:00
|
|
|
if self.ruler:
|
2016-07-21 01:28:27 +00:00
|
|
|
self.stdout.write("%s\n" % str(self.ruler * len(header)))
|
|
|
|
for command in commands:
|
|
|
|
self.stdout.write("%s %s\n" % (command.ljust(17), getattr(self, 'do_' + command).__doc__))
|
2015-08-05 18:36:39 +00:00
|
|
|
self.stdout.write("\n")
|
|
|
|
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
def emptyline(self):
|
|
|
|
pass
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def default(self, line):
|
|
|
|
"Default handler"
|
|
|
|
|
|
|
|
line = line.strip()
|
|
|
|
parts = line.split(" ")
|
|
|
|
|
|
|
|
if len(parts) > 0:
|
2015-08-20 18:35:42 +00:00
|
|
|
# check if we got an agent command
|
|
|
|
if parts[0] in self.agentCommands:
|
2015-08-05 18:36:39 +00:00
|
|
|
shellcmd = " ".join(parts)
|
|
|
|
# task the agent with this shell command
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SHELL", shellcmd)
|
|
|
|
# update the agent log
|
2015-08-20 18:35:42 +00:00
|
|
|
msg = "Tasked agent to run command " + line
|
2015-08-05 18:36:39 +00:00
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
2015-08-20 18:35:42 +00:00
|
|
|
else:
|
|
|
|
print helpers.color("[!] Command not recognized.")
|
|
|
|
print helpers.color("[*] Use 'help' or 'help agentcmds' to see available commands.")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_back(self, line):
|
|
|
|
"Go back a menu."
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2016-03-22 18:32:47 +00:00
|
|
|
def do_agents(self, line):
|
|
|
|
"Jump to the Agents menu."
|
|
|
|
raise NavAgents()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
2015-11-24 05:41:16 +00:00
|
|
|
def do_listeners(self, line):
|
|
|
|
"Jump to the listeners menu."
|
|
|
|
raise NavListeners()
|
|
|
|
|
|
|
|
|
2016-03-22 18:32:47 +00:00
|
|
|
def do_main(self, line):
|
|
|
|
"Go back to the main menu."
|
|
|
|
raise NavMain()
|
2015-11-24 05:41:16 +00:00
|
|
|
|
|
|
|
|
2015-08-20 18:35:42 +00:00
|
|
|
def do_help(self, *args):
|
|
|
|
"Displays the help menu or syntax for particular commands."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-20 18:35:42 +00:00
|
|
|
if args[0].lower() == "agentcmds":
|
|
|
|
print "\n" + helpers.color("[*] Available opsec-safe agent commands:\n")
|
|
|
|
print " " + messages.wrap_columns(", ".join(self.agentCommands), " ", width1=50, width2=10, indent=5) + "\n"
|
|
|
|
else:
|
|
|
|
cmd.Cmd.do_help(self, *args)
|
|
|
|
|
|
|
|
|
2015-08-20 23:08:40 +00:00
|
|
|
def do_list(self, line):
|
|
|
|
"Lists all active agents (or listeners)."
|
|
|
|
|
|
|
|
if line.lower().startswith("listeners"):
|
|
|
|
self.mainMenu.do_list("listeners " + str(" ".join(line.split(" ")[1:])))
|
|
|
|
elif line.lower().startswith("agents"):
|
|
|
|
self.mainMenu.do_list("agents " + str(" ".join(line.split(" ")[1:])))
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please use 'list [agents/listeners] <modifier>'.")
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_rename(self, line):
|
|
|
|
"Rename the agent."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
parts = line.strip().split(" ")
|
|
|
|
oldname = self.mainMenu.agents.get_agent_name(self.sessionID)
|
|
|
|
|
|
|
|
# name sure we get a new name to rename this agent
|
|
|
|
if len(parts) == 1:
|
|
|
|
# replace the old name with the new name
|
|
|
|
result = self.mainMenu.agents.rename_agent(oldname, parts[0])
|
|
|
|
if result:
|
2016-07-21 01:28:27 +00:00
|
|
|
self.prompt = "(Empire: " + helpers.color(parts[0], 'red') + ") > "
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a new name for the agent")
|
|
|
|
|
|
|
|
|
|
|
|
def do_info(self, line):
|
|
|
|
"Display information about this agent"
|
|
|
|
|
|
|
|
# get the agent name, if applicable
|
|
|
|
agent = self.mainMenu.agents.get_agent(self.sessionID)
|
|
|
|
messages.display_agent(agent)
|
|
|
|
|
|
|
|
|
|
|
|
def do_exit(self, line):
|
|
|
|
"Task agent to exit."
|
|
|
|
|
|
|
|
try:
|
|
|
|
choice = raw_input(helpers.color("[>] Task agent to exit? [y/N] ", "red"))
|
|
|
|
if choice.lower() != "" and choice.lower()[0] == "y":
|
|
|
|
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_EXIT")
|
|
|
|
# update the agent log
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, "Tasked agent to exit")
|
2015-08-19 19:51:36 +00:00
|
|
|
return True
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
print ""
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_clear(self, line):
|
2016-07-21 01:28:27 +00:00
|
|
|
"Clear out agent tasking."
|
2015-08-05 18:36:39 +00:00
|
|
|
self.mainMenu.agents.clear_agent_tasks(self.sessionID)
|
|
|
|
|
|
|
|
|
|
|
|
def do_jobs(self, line):
|
|
|
|
"Return jobs or kill a running job."
|
|
|
|
|
|
|
|
parts = line.split(" ")
|
|
|
|
|
|
|
|
if len(parts) == 1:
|
|
|
|
if parts[0] == '':
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_GETJOBS")
|
|
|
|
# update the agent log
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, "Tasked agent to get running jobs")
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please use form 'jobs kill JOB_ID'")
|
|
|
|
elif len(parts) == 2:
|
|
|
|
jobID = parts[1].strip()
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_STOPJOB", jobID)
|
|
|
|
# update the agent log
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, "Tasked agent to stop job " + str(jobID))
|
|
|
|
|
|
|
|
|
|
|
|
def do_sleep(self, line):
|
|
|
|
"Task an agent to 'sleep interval [jitter]'"
|
|
|
|
|
|
|
|
parts = line.strip().split(" ")
|
|
|
|
|
|
|
|
if len(parts) > 0 and parts[0] != "":
|
|
|
|
delay = parts[0]
|
|
|
|
jitter = 0.0
|
|
|
|
if len(parts) == 2:
|
|
|
|
jitter = parts[1]
|
|
|
|
|
|
|
|
# update this agent's information in the database
|
|
|
|
self.mainMenu.agents.set_agent_field("delay", delay, self.sessionID)
|
|
|
|
self.mainMenu.agents.set_agent_field("jitter", jitter, self.sessionID)
|
|
|
|
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SHELL", "Set-Delay " + str(delay) + " " + str(jitter))
|
|
|
|
# update the agent log
|
|
|
|
msg = "Tasked agent to delay sleep/jitter " + str(delay) + "/" + str(jitter)
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
|
|
|
|
2015-11-24 05:41:16 +00:00
|
|
|
|
2015-08-10 22:50:18 +00:00
|
|
|
def do_lostlimit(self, line):
|
|
|
|
"Task an agent to change the limit on lost agent detection"
|
2015-08-10 02:18:02 +00:00
|
|
|
|
|
|
|
parts = line.strip().split(" ")
|
|
|
|
if len(parts) > 0 and parts[0] != "":
|
2015-08-10 22:50:18 +00:00
|
|
|
lostLimit = parts[0]
|
2015-08-10 02:18:02 +00:00
|
|
|
|
|
|
|
# update this agent's information in the database
|
2015-08-10 22:50:18 +00:00
|
|
|
self.mainMenu.agents.set_agent_field("lost_limit", lostLimit, self.sessionID)
|
2016-07-21 01:28:27 +00:00
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SHELL", "Set-LostLimit " + str(lostLimit))
|
2015-08-10 02:18:02 +00:00
|
|
|
# update the agent log
|
2015-08-10 22:50:18 +00:00
|
|
|
msg = "Tasked agent to change lost limit " + str(lostLimit)
|
2015-08-10 02:18:02 +00:00
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
def do_kill(self, line):
|
|
|
|
"Task an agent to kill a particular process name or ID."
|
|
|
|
|
|
|
|
parts = line.strip().split(" ")
|
|
|
|
process = parts[0]
|
|
|
|
|
|
|
|
if process == "":
|
|
|
|
print helpers.color("[!] Please enter a process name or ID.")
|
|
|
|
else:
|
|
|
|
# if we were passed a process ID
|
|
|
|
if process.isdigit():
|
|
|
|
command = "Stop-Process " + str(process) + " -Force"
|
|
|
|
else:
|
|
|
|
# otherwise assume we were passed a process name
|
|
|
|
# so grab all processes by this name and kill them
|
|
|
|
command = "Get-Process " + str(process) + " | %{Stop-Process $_.Id -Force}"
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SHELL", command)
|
|
|
|
|
|
|
|
# update the agent log
|
|
|
|
msg = "Tasked agent to kill process: " + str(process)
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
|
|
|
|
|
|
|
|
|
|
|
def do_killdate(self, line):
|
|
|
|
"Get or set an agent's killdate (01/01/2016)."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
parts = line.strip().split(" ")
|
|
|
|
date = parts[0]
|
|
|
|
|
|
|
|
if date == "":
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SHELL", "Get-KillDate")
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, "Tasked agent to get KillDate")
|
|
|
|
|
|
|
|
else:
|
|
|
|
# update this agent's information in the database
|
|
|
|
self.mainMenu.agents.set_agent_field("kill_date", date, self.sessionID)
|
|
|
|
|
|
|
|
# task the agent
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SHELL", "Set-KillDate " + str(date))
|
|
|
|
|
|
|
|
# update the agent log
|
|
|
|
msg = "Tasked agent to set killdate to " + str(date)
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
|
|
|
|
|
|
|
|
|
|
|
def do_workinghours(self, line):
|
|
|
|
"Get or set an agent's working hours (9:00-17:00)."
|
|
|
|
|
|
|
|
parts = line.strip().split(" ")
|
|
|
|
hours = parts[0]
|
|
|
|
|
|
|
|
if hours == "":
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SHELL", "Get-WorkingHours")
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, "Tasked agent to get working hours")
|
|
|
|
|
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
hours = hours.replace(",", "-")
|
2015-08-05 18:36:39 +00:00
|
|
|
# update this agent's information in the database
|
|
|
|
self.mainMenu.agents.set_agent_field("working_hours", hours, self.sessionID)
|
|
|
|
|
|
|
|
# task the agent
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SHELL", "Set-WorkingHours " + str(hours))
|
|
|
|
|
|
|
|
# update the agent log
|
|
|
|
msg = "Tasked agent to set working hours to " + str(hours)
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
|
|
|
|
|
|
|
|
|
|
|
def do_shell(self, line):
|
|
|
|
"Task an agent to use a shell command."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
line = line.strip()
|
|
|
|
|
|
|
|
if line != "":
|
|
|
|
# task the agent with this shell command
|
2015-08-20 18:35:42 +00:00
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SHELL", "shell " + str(line))
|
2015-08-05 18:36:39 +00:00
|
|
|
# update the agent log
|
|
|
|
msg = "Tasked agent to run shell command " + line
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
def do_sysinfo(self, line):
|
|
|
|
"Task an agent to get system information."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# task the agent with this shell command
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SYSINFO")
|
|
|
|
# update the agent log
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, "Tasked agent to get system information")
|
|
|
|
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
def do_download(self, line):
|
2015-08-05 18:36:39 +00:00
|
|
|
"Task an agent to download a file."
|
|
|
|
|
|
|
|
line = line.strip()
|
|
|
|
|
|
|
|
if line != "":
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_DOWNLOAD", line)
|
|
|
|
# update the agent log
|
|
|
|
msg = "Tasked agent to download " + line
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
|
|
|
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
def do_upload(self, line):
|
2015-08-05 18:36:39 +00:00
|
|
|
"Task an agent to upload a file."
|
|
|
|
|
|
|
|
# "upload /path/file.ext" or "upload /path/file/file.ext newfile.ext"
|
|
|
|
# absolute paths accepted
|
|
|
|
parts = line.strip().split(" ")
|
|
|
|
uploadname = ""
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
if len(parts) > 0 and parts[0] != "":
|
|
|
|
if len(parts) == 1:
|
|
|
|
# if we're uploading the file with its original name
|
|
|
|
uploadname = os.path.basename(parts[0])
|
|
|
|
else:
|
|
|
|
# if we're uploading the file as a different name
|
|
|
|
uploadname = parts[1].strip()
|
|
|
|
|
|
|
|
if parts[0] != "" and os.path.exists(parts[0]):
|
|
|
|
# read in the file and base64 encode it for transport
|
2016-07-21 01:28:27 +00:00
|
|
|
open_file = open(parts[0], 'r')
|
|
|
|
file_data = open_file.read()
|
|
|
|
open_file.close()
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# update the agent log with the filename and MD5
|
2016-07-21 01:28:27 +00:00
|
|
|
msg = "Tasked agent to upload %s : %s" % (parts[0], hashlib.md5(file_data).hexdigest())
|
2015-08-05 18:36:39 +00:00
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
|
|
|
|
|
|
|
# upload packets -> "filename | script data"
|
2016-07-21 01:28:27 +00:00
|
|
|
file_data = helpers.encode_base64(file_data)
|
|
|
|
data = uploadname + "|" + file_data
|
2015-08-05 18:36:39 +00:00
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_UPLOAD", data)
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid file path to upload")
|
|
|
|
|
|
|
|
|
|
|
|
def do_scriptimport(self, line):
|
|
|
|
"Imports a PowerShell script and keeps it in memory in the agent."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
path = line.strip()
|
|
|
|
|
|
|
|
if path != "" and os.path.exists(path):
|
2016-07-21 01:28:27 +00:00
|
|
|
open_file = open(path, 'r')
|
|
|
|
script_data = open_file.read()
|
|
|
|
open_file.close()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# strip out comments and blank lines from the imported script
|
2016-07-21 01:28:27 +00:00
|
|
|
script_data = helpers.strip_powershell_comments(script_data)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# task the agent to important the script
|
2016-07-21 01:28:27 +00:00
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SCRIPT_IMPORT", script_data)
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# update the agent log with the filename and MD5
|
2016-07-21 01:28:27 +00:00
|
|
|
msg = "Tasked agent to import %s : %s" % (path, hashlib.md5(script_data).hexdigest())
|
2015-08-05 18:36:39 +00:00
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
|
|
|
|
|
|
|
# extract the functions from the script so we can tab-complete them
|
2016-07-21 01:28:27 +00:00
|
|
|
functions = helpers.parse_powershell_script(script_data)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# set this agent's tab-completable functions
|
2016-07-21 01:28:27 +00:00
|
|
|
self.mainMenu.agents.set_agent_functions(self.sessionID, functions)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid script path")
|
|
|
|
|
|
|
|
|
|
|
|
def do_scriptcmd(self, line):
|
|
|
|
"Execute a function in the currently imported PowerShell script."
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
command = line.strip()
|
|
|
|
|
|
|
|
if command != "":
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_SCRIPT_COMMAND", command)
|
|
|
|
msg = "[*] Tasked agent %s to run %s" % (self.sessionID, command)
|
2015-08-05 18:36:39 +00:00
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
|
|
|
|
|
|
|
|
|
|
|
def do_usemodule(self, line):
|
|
|
|
"Use an Empire PowerShell module."
|
|
|
|
|
|
|
|
module = line.strip()
|
|
|
|
|
|
|
|
if module not in self.mainMenu.modules.modules:
|
|
|
|
print helpers.color("[!] Error: invalid module")
|
2016-07-21 01:28:27 +00:00
|
|
|
else:
|
|
|
|
module_menu = ModuleMenu(self.mainMenu, line, agent=self.sessionID)
|
|
|
|
module_menu.cmdloop()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_searchmodule(self, line):
|
|
|
|
"Search Empire module names/descriptions."
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
search_term = line.strip()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
if search_term.strip() == "":
|
2015-08-05 18:36:39 +00:00
|
|
|
print helpers.color("[!] Please enter a search term.")
|
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
self.mainMenu.modules.search_modules(search_term)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_updateprofile(self, line):
|
|
|
|
"Update an agent connection profile."
|
|
|
|
|
|
|
|
# profile format:
|
|
|
|
# TaskURI1,TaskURI2,...|UserAgent|OptionalHeader1,OptionalHeader2...
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
profile = line.strip().strip()
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
if profile != "":
|
2015-08-05 18:36:39 +00:00
|
|
|
# load up a profile from a file if a path was passed
|
|
|
|
if os.path.exists(profile):
|
2016-07-21 01:28:27 +00:00
|
|
|
open_file = open(profile, 'r')
|
|
|
|
profile = open_file.readlines()
|
|
|
|
open_file.close()
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# strip out profile comments and blank lines
|
2016-07-21 01:28:27 +00:00
|
|
|
profile = [l for l in profile if not l.startswith("#" and l.strip() != "")]
|
2015-08-05 18:36:39 +00:00
|
|
|
profile = profile[0]
|
2015-12-29 20:57:01 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
if not profile.strip().startswith("\"/"):
|
|
|
|
print helpers.color("[!] Task URIs in profiles must start with / and be enclosed in quotes!")
|
|
|
|
else:
|
|
|
|
updatecmd = "Update-Profile " + profile
|
|
|
|
|
|
|
|
# task the agent to update their profile
|
|
|
|
self.mainMenu.agents.add_agent_task(self.sessionID, "TASK_CMD_WAIT", updatecmd)
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# update the agent's profile in the database
|
|
|
|
self.mainMenu.agents.update_agent_profile(self.sessionID, profile)
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# print helpers.color("[*] Tasked agent "+self.sessionID+" to run " + updatecmd)
|
|
|
|
# update the agent log
|
|
|
|
msg = "Tasked agent to update profile " + profile
|
|
|
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[*] Profile format is \"TaskURI1,TaskURI2,...|UserAgent|OptionalHeader2:Val1|OptionalHeader2:Val2...\"")
|
|
|
|
|
|
|
|
|
|
|
|
def do_psinject(self, line):
|
|
|
|
"Inject a launcher into a remote process. Ex. psinject <listener> <pid>"
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# get the info for the psinject module
|
|
|
|
if line:
|
|
|
|
listenerID = line.split(" ")[0].strip()
|
2016-07-21 01:28:27 +00:00
|
|
|
pid = ''
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
if len(line.split(" ")) == 2:
|
2015-08-05 18:36:39 +00:00
|
|
|
pid = line.split(" ")[1].strip()
|
|
|
|
|
|
|
|
if self.mainMenu.modules.modules["management/psinject"]:
|
|
|
|
|
|
|
|
if listenerID != "" and self.mainMenu.listeners.is_listener_valid(listenerID):
|
|
|
|
|
|
|
|
module = self.mainMenu.modules.modules["management/psinject"]
|
|
|
|
module.options['Listener']['Value'] = listenerID
|
2016-07-21 01:28:27 +00:00
|
|
|
module.options['Agent']['Value'] = self.mainMenu.agents.get_agent_name(self.sessionID)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
if pid != '':
|
|
|
|
module.options['ProcId']['Value'] = pid
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
module_menu = ModuleMenu(self.mainMenu, "management/psinject")
|
|
|
|
module_menu.cmdloop()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter <listenerName> <pid>")
|
|
|
|
|
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("[!] management/psinject module not loaded")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Injection requires you to specify listener")
|
|
|
|
|
|
|
|
|
|
|
|
def do_injectshellcode(self, line):
|
|
|
|
"Inject listener shellcode into a remote process. Ex. injectshellcode <meter_listener> <pid>"
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# get the info for the inject module
|
|
|
|
if line:
|
|
|
|
listenerID = line.split(" ")[0].strip()
|
2016-07-21 01:28:27 +00:00
|
|
|
pid = ''
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
if len(line.split(" ")) == 2:
|
2015-08-05 18:36:39 +00:00
|
|
|
pid = line.split(" ")[1].strip()
|
|
|
|
|
|
|
|
if self.mainMenu.modules.modules["code_execution/invoke_shellcode"]:
|
|
|
|
|
|
|
|
if listenerID != "" and self.mainMenu.listeners.is_listener_valid(listenerID):
|
|
|
|
|
|
|
|
module = self.mainMenu.modules.modules["code_execution/invoke_shellcode"]
|
|
|
|
module.options['Listener']['Value'] = listenerID
|
2016-07-21 01:28:27 +00:00
|
|
|
module.options['Agent']['Value'] = self.mainMenu.agents.get_agent_name(self.sessionID)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
if pid != '':
|
|
|
|
module.options['ProcessID']['Value'] = pid
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
module_menu = ModuleMenu(self.mainMenu, "code_execution/invoke_shellcode")
|
|
|
|
module_menu.cmdloop()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter <listenerName> <pid>")
|
|
|
|
|
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("[!] code_execution/invoke_shellcode module not loaded")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Injection requires you to specify listener")
|
|
|
|
|
2016-03-31 21:27:15 +00:00
|
|
|
def do_sc(self, line):
|
|
|
|
"Takes a screenshot, default is PNG. Giving a ratio means using JPEG. Ex. sc [1-100]"
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2016-03-31 21:27:15 +00:00
|
|
|
# get the info for the psinject module
|
2016-07-21 01:28:27 +00:00
|
|
|
if len(line.strip()) > 0:
|
2016-03-31 21:27:15 +00:00
|
|
|
# JPEG compression ratio
|
|
|
|
try:
|
2016-07-21 01:28:27 +00:00
|
|
|
screenshot_ratio = str(int(line.strip()))
|
|
|
|
except Exception:
|
2016-03-31 21:27:15 +00:00
|
|
|
print helpers.color("[*] JPEG Ratio incorrect. Has been set to 80.")
|
2016-07-21 01:28:27 +00:00
|
|
|
screenshot_ratio = "80"
|
2016-03-31 21:27:15 +00:00
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
screenshot_ratio = ""
|
|
|
|
|
2016-03-31 21:27:15 +00:00
|
|
|
if self.mainMenu.modules.modules["collection/screenshot"]:
|
|
|
|
module = self.mainMenu.modules.modules["collection/screenshot"]
|
|
|
|
module.options['Agent']['Value'] = self.mainMenu.agents.get_agent_name(self.sessionID)
|
2016-07-21 01:28:27 +00:00
|
|
|
module.options['Ratio']['Value'] = screenshot_ratio
|
|
|
|
|
2016-03-31 21:27:15 +00:00
|
|
|
# execute the screenshot module
|
2016-07-21 01:28:27 +00:00
|
|
|
module_menu = ModuleMenu(self.mainMenu, "collection/screenshot")
|
|
|
|
module_menu.do_execute("")
|
|
|
|
|
2016-03-31 21:27:15 +00:00
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("[!] collection/screenshot module not loaded")
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_spawn(self, line):
|
|
|
|
"Spawns a new Empire agent for the given listener name. Ex. spawn <listener>"
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# get the info for the spawn module
|
|
|
|
if line:
|
|
|
|
listenerID = line.split(" ")[0].strip()
|
|
|
|
|
|
|
|
if listenerID != "" and self.mainMenu.listeners.is_listener_valid(listenerID):
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
# ensure the inject module is loaded
|
2015-08-05 18:36:39 +00:00
|
|
|
if self.mainMenu.modules.modules["management/spawn"]:
|
|
|
|
module = self.mainMenu.modules.modules["management/spawn"]
|
|
|
|
|
|
|
|
module.options['Listener']['Value'] = listenerID
|
2016-07-21 01:28:27 +00:00
|
|
|
module.options['Agent']['Value'] = self.mainMenu.agents.get_agent_name(self.sessionID)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# jump to the spawn module
|
2016-07-21 01:28:27 +00:00
|
|
|
module_menu = ModuleMenu(self.mainMenu, "management/spawn")
|
|
|
|
module_menu.cmdloop()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("[!] management/spawn module not loaded")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid listener name or ID.")
|
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please specify a listener name or ID.")
|
|
|
|
|
|
|
|
|
|
|
|
def do_bypassuac(self, line):
|
|
|
|
"Runs BypassUAC, spawning a new high-integrity agent for a listener. Ex. spawn <listener>"
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# get the info for the bypassuac module
|
|
|
|
if line:
|
|
|
|
listenerID = line.split(" ")[0].strip()
|
|
|
|
|
|
|
|
if listenerID != "" and self.mainMenu.listeners.is_listener_valid(listenerID):
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
# ensure the inject module is loaded
|
2015-08-05 18:36:39 +00:00
|
|
|
if self.mainMenu.modules.modules["privesc/bypassuac"]:
|
|
|
|
module = self.mainMenu.modules.modules["privesc/bypassuac"]
|
|
|
|
|
|
|
|
module.options['Listener']['Value'] = listenerID
|
2016-07-21 01:28:27 +00:00
|
|
|
module.options['Agent']['Value'] = self.mainMenu.agents.get_agent_name(self.sessionID)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# jump to the spawn module
|
2016-07-21 01:28:27 +00:00
|
|
|
module_menu = ModuleMenu(self.mainMenu, "privesc/bypassuac")
|
|
|
|
module_menu.do_execute("")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("[!] privesc/bypassuac module not loaded")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid listener name or ID.")
|
|
|
|
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please specify a listener name or ID.")
|
|
|
|
|
|
|
|
|
|
|
|
def do_mimikatz(self, line):
|
|
|
|
"Runs Invoke-Mimikatz on the client."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
|
|
|
# ensure the credentials/mimiktaz/logonpasswords module is loaded
|
2015-08-05 18:36:39 +00:00
|
|
|
if self.mainMenu.modules.modules["credentials/mimikatz/logonpasswords"]:
|
|
|
|
module = self.mainMenu.modules.modules["credentials/mimikatz/logonpasswords"]
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
module.options['Agent']['Value'] = self.mainMenu.agents.get_agent_name(self.sessionID)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# execute the Mimikatz module
|
2016-07-21 01:28:27 +00:00
|
|
|
module_menu = ModuleMenu(self.mainMenu, "credentials/mimikatz/logonpasswords")
|
|
|
|
module_menu.do_execute("")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_pth(self, line):
|
|
|
|
"Executes PTH for a CredID through Mimikatz."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
credID = line.strip()
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
if credID == "":
|
|
|
|
print helpers.color("[!] Please specify a <CredID>.")
|
|
|
|
return
|
|
|
|
|
|
|
|
if self.mainMenu.modules.modules["credentials/mimikatz/pth"]:
|
|
|
|
# reload the module to reset the default values
|
|
|
|
module = self.mainMenu.modules.reload_module("credentials/mimikatz/pth")
|
|
|
|
|
|
|
|
module = self.mainMenu.modules.modules["credentials/mimikatz/pth"]
|
|
|
|
|
|
|
|
# set mimikt/pth to use the given CredID
|
|
|
|
module.options['CredID']['Value'] = credID
|
|
|
|
|
|
|
|
# set the agent ID
|
|
|
|
module.options['Agent']['Value'] = self.mainMenu.agents.get_agent_name(self.sessionID)
|
|
|
|
|
|
|
|
# execute the mimikatz/pth module
|
2016-07-21 01:28:27 +00:00
|
|
|
module_menu = ModuleMenu(self.mainMenu, "credentials/mimikatz/pth")
|
|
|
|
module_menu.do_execute("")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_steal_token(self, line):
|
|
|
|
"Uses credentials/tokens to impersonate a token for a given process ID."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
processID = line.strip()
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
if processID == "":
|
|
|
|
print helpers.color("[!] Please specify a process ID.")
|
|
|
|
return
|
|
|
|
|
|
|
|
if self.mainMenu.modules.modules["credentials/tokens"]:
|
|
|
|
# reload the module to reset the default values
|
|
|
|
module = self.mainMenu.modules.reload_module("credentials/tokens")
|
|
|
|
|
|
|
|
module = self.mainMenu.modules.modules["credentials/tokens"]
|
|
|
|
|
|
|
|
# set credentials/token to impersonate the given process ID token
|
|
|
|
module.options['ImpersonateUser']['Value'] = "True"
|
|
|
|
module.options['ProcessID']['Value'] = processID
|
|
|
|
|
|
|
|
# set the agent ID
|
|
|
|
module.options['Agent']['Value'] = self.mainMenu.agents.get_agent_name(self.sessionID)
|
|
|
|
|
|
|
|
# execute the token module
|
2016-07-21 01:28:27 +00:00
|
|
|
module_menu = ModuleMenu(self.mainMenu, "credentials/tokens")
|
|
|
|
module_menu.do_execute("")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-15 23:14:43 +00:00
|
|
|
# run a sysinfo to update
|
|
|
|
self.do_sysinfo(line)
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
def do_revtoself(self, line):
|
|
|
|
"Uses credentials/tokens to revert token privileges."
|
|
|
|
|
|
|
|
if self.mainMenu.modules.modules["credentials/tokens"]:
|
|
|
|
# reload the module to reset the default values
|
|
|
|
module = self.mainMenu.modules.reload_module("credentials/tokens")
|
|
|
|
|
|
|
|
module = self.mainMenu.modules.modules["credentials/tokens"]
|
|
|
|
|
|
|
|
# set credentials/token to revert to self
|
|
|
|
module.options['RevToSelf']['Value'] = "True"
|
|
|
|
|
|
|
|
# set the agent ID
|
|
|
|
module.options['Agent']['Value'] = self.mainMenu.agents.get_agent_name(self.sessionID)
|
|
|
|
|
|
|
|
# execute the token module
|
2016-07-21 01:28:27 +00:00
|
|
|
module_menu = ModuleMenu(self.mainMenu, "credentials/tokens")
|
|
|
|
module_menu.do_execute("")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-15 23:14:43 +00:00
|
|
|
# run a sysinfo to update
|
|
|
|
self.do_sysinfo(line)
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
def do_creds(self, line):
|
|
|
|
"Display/return credentials from the database."
|
|
|
|
self.mainMenu.do_creds(line)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_psinject(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete psinject option values."
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in self.mainMenu.listeners.get_listener_names() if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_injectshellcode(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete injectshellcode option values."
|
|
|
|
|
|
|
|
return self.complete_psinject(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_spawn(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete spawn option values."
|
|
|
|
|
|
|
|
return self.complete_psinject(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_bypassuac(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete bypassuac option values."
|
|
|
|
|
|
|
|
return self.complete_psinject(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_jobs(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete jobs management options."
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in ["kill"] if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_scriptimport(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a PowerShell script path"
|
2016-07-21 01:28:27 +00:00
|
|
|
|
|
|
|
return helpers.complete_path(text, line)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def complete_scriptcmd(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a script cmd set."
|
|
|
|
|
|
|
|
functions = self.mainMenu.agents.get_agent_functions(self.sessionID)
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in functions if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_usemodule(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an Empire PowerShell module path"
|
|
|
|
return self.mainMenu.complete_usemodule(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_upload(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an upload file path"
|
2016-07-21 01:28:27 +00:00
|
|
|
return helpers.complete_path(text, line)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def complete_updateprofile(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an updateprofile path"
|
2016-07-21 01:28:27 +00:00
|
|
|
return helpers.complete_path(text, line)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def complete_creds(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete 'creds' commands."
|
|
|
|
return self.mainMenu.complete_creds(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ListenerMenu(cmd.Cmd):
|
2016-07-21 01:28:27 +00:00
|
|
|
"""
|
|
|
|
The main class used by Empire to drive the 'listener' menu.
|
|
|
|
"""
|
2015-08-05 18:36:39 +00:00
|
|
|
def __init__(self, mainMenu):
|
|
|
|
cmd.Cmd.__init__(self)
|
|
|
|
self.doc_header = 'Listener Commands'
|
|
|
|
|
|
|
|
self.mainMenu = mainMenu
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# get all the the stock listener options
|
|
|
|
self.options = self.mainMenu.listeners.get_listener_options()
|
|
|
|
|
|
|
|
# set the prompt text
|
2016-07-21 01:28:27 +00:00
|
|
|
self.prompt = '(Empire: ' + helpers.color("listeners", color="blue") + ') > '
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# display all active listeners on menu startup
|
|
|
|
messages.display_listeners(self.mainMenu.listeners.get_listeners())
|
|
|
|
|
2015-11-22 01:03:40 +00:00
|
|
|
# def preloop(self):
|
|
|
|
# traceback.print_stack()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# print a nicely formatted help menu
|
|
|
|
# stolen/adapted from recon-ng
|
2016-07-21 01:28:27 +00:00
|
|
|
def print_topics(self, header, commands, cmdlen, maxcol):
|
|
|
|
if commands:
|
|
|
|
self.stdout.write("%s\n" % str(header))
|
2015-08-05 18:36:39 +00:00
|
|
|
if self.ruler:
|
2016-07-21 01:28:27 +00:00
|
|
|
self.stdout.write("%s\n" % str(self.ruler * len(header)))
|
|
|
|
for command in commands:
|
|
|
|
self.stdout.write("%s %s\n" % (command.ljust(17), getattr(self, 'do_' + command).__doc__))
|
2015-08-05 18:36:39 +00:00
|
|
|
self.stdout.write("\n")
|
|
|
|
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
def emptyline(self):
|
|
|
|
pass
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_list(self, line):
|
2015-08-20 23:08:40 +00:00
|
|
|
"List all active listeners (or agents)."
|
|
|
|
|
|
|
|
if line.lower().startswith("agents"):
|
|
|
|
self.mainMenu.do_list("agents " + str(" ".join(line.split(" ")[1:])))
|
|
|
|
elif line.lower().startswith("listeners"):
|
|
|
|
self.mainMenu.do_list("listeners " + str(" ".join(line.split(" ")[1:])))
|
|
|
|
else:
|
|
|
|
self.mainMenu.do_list("listeners " + str(line))
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_back(self, line):
|
2016-03-22 18:32:47 +00:00
|
|
|
"Go back to the main menu."
|
|
|
|
raise NavMain()
|
|
|
|
|
|
|
|
|
|
|
|
def do_agents(self, line):
|
|
|
|
"Jump to the Agents menu."
|
|
|
|
raise NavAgents()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_main(self, line):
|
|
|
|
"Go back to the main menu."
|
2015-11-22 01:03:40 +00:00
|
|
|
raise NavMain()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
2016-03-22 18:32:47 +00:00
|
|
|
def do_exit(self, line):
|
|
|
|
"Exit Empire."
|
|
|
|
raise KeyboardInterrupt
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_set(self, line):
|
|
|
|
"Set a listener option."
|
|
|
|
parts = line.split(" ")
|
|
|
|
if len(parts) > 1:
|
2015-12-29 20:57:01 +00:00
|
|
|
|
|
|
|
if parts[0].lower() == "defaultprofile" and os.path.exists(parts[1]):
|
|
|
|
try:
|
2016-07-21 01:28:27 +00:00
|
|
|
open_file = open(parts[1], 'r')
|
|
|
|
profile_data_raw = open_file.readlines()
|
|
|
|
open_file.close()
|
2015-12-29 20:57:01 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
profile_data = [l for l in profile_data_raw if not l.startswith("#" and l.strip() != "")]
|
|
|
|
profile_data = profile_data[0].strip("\"")
|
2015-12-29 20:57:01 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
self.mainMenu.listeners.set_listener_option(parts[0], profile_data)
|
|
|
|
|
|
|
|
except Exception:
|
|
|
|
print helpers.color("[!] Error opening profile file %s" % (parts[1]))
|
2015-12-29 20:57:01 +00:00
|
|
|
else:
|
|
|
|
self.mainMenu.listeners.set_listener_option(parts[0], " ".join(parts[1:]))
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a value to set for the option")
|
|
|
|
|
|
|
|
|
|
|
|
def do_unset(self, line):
|
|
|
|
"Unset a listener option."
|
|
|
|
option = line.strip()
|
|
|
|
self.mainMenu.listeners.set_listener_option(option, '')
|
|
|
|
|
|
|
|
|
|
|
|
def do_info(self, line):
|
|
|
|
"Display listener options."
|
|
|
|
|
|
|
|
parts = line.split(" ")
|
|
|
|
|
|
|
|
if parts[0] != '':
|
|
|
|
if self.mainMenu.listeners.is_listener_valid(parts[0]):
|
|
|
|
listener = self.mainMenu.listeners.get_listener(parts[0])
|
|
|
|
messages.display_listener_database(listener)
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid listener name or ID")
|
|
|
|
else:
|
|
|
|
messages.display_listener(self.mainMenu.listeners.options)
|
|
|
|
|
|
|
|
|
|
|
|
def do_options(self, line):
|
|
|
|
"Display listener options."
|
|
|
|
|
|
|
|
parts = line.split(" ")
|
|
|
|
|
|
|
|
if parts[0] != '':
|
|
|
|
if self.mainMenu.listeners.is_listener_valid(parts[0]):
|
|
|
|
listener = self.mainMenu.listeners.get_listener(parts[0])
|
|
|
|
messages.display_listener_database(listener)
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid listener name or ID")
|
|
|
|
else:
|
|
|
|
messages.display_listener(self.mainMenu.listeners.options)
|
|
|
|
|
|
|
|
|
|
|
|
def do_kill(self, line):
|
|
|
|
"Kill one or all active listeners."
|
|
|
|
|
|
|
|
listenerID = line.strip()
|
|
|
|
|
|
|
|
if listenerID.lower() == "all":
|
|
|
|
try:
|
|
|
|
choice = raw_input(helpers.color("[>] Kill all listeners? [y/N] ", "red"))
|
|
|
|
if choice.lower() != "" and choice.lower()[0] == "y":
|
|
|
|
self.mainMenu.listeners.killall()
|
2016-07-21 01:28:27 +00:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
print ""
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
else:
|
|
|
|
if listenerID != "" and self.mainMenu.listeners.is_listener_valid(listenerID):
|
|
|
|
self.mainMenu.listeners.shutdown_listener(listenerID)
|
|
|
|
self.mainMenu.listeners.delete_listener(listenerID)
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Invalid listener name or ID.")
|
|
|
|
|
|
|
|
|
|
|
|
def do_execute(self, line):
|
|
|
|
"Execute a listener with the currently specified options."
|
2016-04-01 21:06:21 +00:00
|
|
|
(success, message) = self.mainMenu.listeners.add_listener_from_config()
|
|
|
|
if success:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("[*] Listener '%s' successfully started." % (message))
|
2016-04-01 21:06:21 +00:00
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("[!] %s" % (message))
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
2015-08-20 23:08:40 +00:00
|
|
|
def do_run(self, line):
|
|
|
|
"Execute a listener with the currently specified options."
|
|
|
|
self.do_execute(line)
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_usestager(self, line):
|
|
|
|
"Use an Empire stager."
|
|
|
|
|
|
|
|
parts = line.split(" ")
|
|
|
|
|
|
|
|
if parts[0] not in self.mainMenu.stagers.stagers:
|
|
|
|
print helpers.color("[!] Error: invalid stager module")
|
|
|
|
|
|
|
|
elif len(parts) == 1:
|
2016-07-21 01:28:27 +00:00
|
|
|
stager_menu = StagerMenu(self.mainMenu, parts[0])
|
|
|
|
stager_menu.cmdloop()
|
2015-08-05 18:36:39 +00:00
|
|
|
elif len(parts) == 2:
|
|
|
|
listener = parts[1]
|
|
|
|
if not self.mainMenu.listeners.is_listener_valid(listener):
|
|
|
|
print helpers.color("[!] Please enter a valid listener name or ID")
|
|
|
|
else:
|
|
|
|
self.mainMenu.stagers.set_stager_option('Listener', listener)
|
2016-07-21 01:28:27 +00:00
|
|
|
stager_menu = StagerMenu(self.mainMenu, parts[0])
|
|
|
|
stager_menu.cmdloop()
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
print helpers.color("[!] Error in ListenerMenu's do_userstager()")
|
|
|
|
|
|
|
|
|
|
|
|
def do_launcher(self, line):
|
|
|
|
"Generate an initial launcher for a listener."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
nameid = self.mainMenu.listeners.get_listener_id(line.strip())
|
2016-07-21 01:28:27 +00:00
|
|
|
if nameid:
|
2015-08-05 18:36:39 +00:00
|
|
|
listenerID = nameid
|
|
|
|
else:
|
2016-07-21 01:28:27 +00:00
|
|
|
listenerID = line.strip()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
if listenerID != "" and self.mainMenu.listeners.is_listener_valid(listenerID):
|
|
|
|
# set the listener value for the launcher
|
|
|
|
stager = self.mainMenu.stagers.stagers["launcher"]
|
|
|
|
stager.options['Listener']['Value'] = listenerID
|
|
|
|
stager.options['Base64']['Value'] = "True"
|
|
|
|
|
|
|
|
# and generate the code
|
|
|
|
print stager.generate()
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid listenerID")
|
|
|
|
|
|
|
|
|
2016-07-15 22:56:38 +00:00
|
|
|
def do_interact(self, line):
|
|
|
|
"Interact with a particular agent."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2016-07-15 22:56:38 +00:00
|
|
|
name = line.strip()
|
|
|
|
|
|
|
|
if name != "" and self.mainMenu.agents.is_agent_present(name):
|
|
|
|
# resolve the passed name to a sessionID
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(name)
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
agent_menu = AgentMenu(self.mainMenu, sessionID)
|
|
|
|
agent_menu.cmdloop()
|
2016-07-15 22:56:38 +00:00
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid agent name")
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def complete_set(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete listener option values."
|
|
|
|
|
|
|
|
if line.split(" ")[1].lower() == "host":
|
|
|
|
return ["http://" + helpers.lhost()]
|
|
|
|
|
|
|
|
elif line.split(" ")[1].lower() == "redirecttarget":
|
|
|
|
# if we're tab-completing a listener name, return all the names
|
|
|
|
listenerNames = self.mainMenu.listeners.get_listener_names()
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
end_line = " ".join(line.split(" ")[1:])
|
|
|
|
mline = end_line.partition(' ')[2]
|
2015-08-05 18:36:39 +00:00
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in listenerNames if s.startswith(mline)]
|
|
|
|
|
|
|
|
elif line.split(" ")[1].lower() == "type":
|
|
|
|
# if we're tab-completing the listener type
|
2015-08-11 17:33:26 +00:00
|
|
|
listenerTypes = ["native", "pivot", "hop", "foreign", "meter"]
|
2016-07-21 01:28:27 +00:00
|
|
|
end_line = " ".join(line.split(" ")[1:])
|
|
|
|
mline = end_line.partition(' ')[2]
|
2015-08-05 18:36:39 +00:00
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in listenerTypes if s.startswith(mline)]
|
|
|
|
|
|
|
|
elif line.split(" ")[1].lower() == "certpath":
|
2016-07-21 01:28:27 +00:00
|
|
|
return helpers.complete_path(text, line, arg=True)
|
|
|
|
|
2015-12-29 20:57:01 +00:00
|
|
|
elif line.split(" ")[1].lower() == "defaultprofile":
|
2016-07-21 01:28:27 +00:00
|
|
|
return helpers.complete_path(text, line, arg=True)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in self.options if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_unset(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete listener option values."
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in self.options if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_usestager(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an Empire stager module path."
|
|
|
|
return self.mainMenu.complete_usestager(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_kill(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete listener names"
|
|
|
|
|
|
|
|
# get all the listener names
|
|
|
|
names = self.mainMenu.listeners.get_listener_names() + ["all"]
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in names if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_launcher(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete listener names/IDs"
|
|
|
|
|
|
|
|
# get all the listener names
|
|
|
|
names = self.mainMenu.listeners.get_listener_names()
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in names if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_info(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete listener names/IDs"
|
|
|
|
return self.complete_launcher(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_options(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete listener names/IDs"
|
|
|
|
return self.complete_launcher(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
2016-07-15 22:56:38 +00:00
|
|
|
def complete_interact(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an interact command"
|
|
|
|
|
|
|
|
names = self.mainMenu.agents.get_agent_names()
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in names if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
class ModuleMenu(cmd.Cmd):
|
2016-07-21 01:28:27 +00:00
|
|
|
"""
|
|
|
|
The main class used by Empire to drive the 'module' menu.
|
|
|
|
"""
|
2015-08-05 18:36:39 +00:00
|
|
|
def __init__(self, mainMenu, moduleName, agent=None):
|
|
|
|
cmd.Cmd.__init__(self)
|
|
|
|
self.doc_header = 'Module Commands'
|
|
|
|
|
|
|
|
self.mainMenu = mainMenu
|
|
|
|
|
|
|
|
# get the current module/name
|
|
|
|
self.moduleName = moduleName
|
|
|
|
self.module = self.mainMenu.modules.modules[moduleName]
|
|
|
|
|
|
|
|
# set the prompt text
|
2016-07-21 01:28:27 +00:00
|
|
|
self.prompt = '(Empire: ' + helpers.color(self.moduleName, color="blue") + ') > '
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# if this menu is being called from an agent menu
|
|
|
|
if agent:
|
|
|
|
# resolve the agent sessionID to a name, if applicable
|
|
|
|
agent = self.mainMenu.agents.get_agent_name(agent)
|
|
|
|
self.module.options['Agent']['Value'] = agent
|
|
|
|
|
2015-11-22 01:03:40 +00:00
|
|
|
# def preloop(self):
|
|
|
|
# traceback.print_stack()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
def validate_options(self):
|
|
|
|
"Make sure all required module options are completed."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
sessionID = self.module.options['Agent']['Value']
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
for option, values in self.module.options.iteritems():
|
2015-08-05 18:36:39 +00:00
|
|
|
if values['Required'] and ((not values['Value']) or (values['Value'] == '')):
|
|
|
|
print helpers.color("[!] Error: Required module option missing.")
|
|
|
|
return False
|
|
|
|
|
|
|
|
try:
|
|
|
|
# if we're running this module for all agents, skip this validation
|
2016-07-21 01:28:27 +00:00
|
|
|
if sessionID.lower() != "all" and sessionID.lower() != "autorun":
|
2015-08-05 18:36:39 +00:00
|
|
|
modulePSVersion = int(self.module.info['MinPSVersion'])
|
|
|
|
agentPSVersion = int(self.mainMenu.agents.get_ps_version(sessionID))
|
|
|
|
# check if the agent/module PowerShell versions are compatible
|
|
|
|
if modulePSVersion > agentPSVersion:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("[!] Error: module requires PS version %s but agent running PS version %s" % (modulePSVersion, agentPSVersion))
|
2015-08-05 18:36:39 +00:00
|
|
|
return False
|
2016-07-21 01:28:27 +00:00
|
|
|
except Exception:
|
2015-08-05 18:36:39 +00:00
|
|
|
print helpers.color("[!] Invalid module or agent PS version!")
|
|
|
|
return False
|
|
|
|
|
|
|
|
# check if the module needs admin privs
|
|
|
|
if self.module.info['NeedsAdmin']:
|
|
|
|
# if we're running this module for all agents, skip this validation
|
2015-11-22 22:25:28 +00:00
|
|
|
if sessionID.lower() != "all" and sessionID.lower() != "autorun":
|
2015-08-05 18:36:39 +00:00
|
|
|
if not self.mainMenu.agents.is_agent_elevated(sessionID):
|
|
|
|
print helpers.color("[!] Error: module needs to run in an elevated context.")
|
|
|
|
return False
|
|
|
|
|
|
|
|
# if the module isn't opsec safe, prompt before running
|
|
|
|
if not self.module.info['OpsecSafe']:
|
|
|
|
try:
|
|
|
|
choice = raw_input(helpers.color("[>] Module is not opsec safe, run? [y/N] ", "red"))
|
|
|
|
if not (choice.lower() != "" and choice.lower()[0] == "y"):
|
|
|
|
return False
|
2016-07-21 01:28:27 +00:00
|
|
|
except KeyboardInterrupt:
|
2015-08-05 18:36:39 +00:00
|
|
|
print ""
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
def emptyline(self):
|
|
|
|
pass
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
# print a nicely formatted help menu
|
|
|
|
# stolen/adapted from recon-ng
|
2016-07-21 01:28:27 +00:00
|
|
|
def print_topics(self, header, commands, cmdlen, maxcol):
|
|
|
|
if commands:
|
|
|
|
self.stdout.write("%s\n" % str(header))
|
2015-08-05 18:36:39 +00:00
|
|
|
if self.ruler:
|
2016-07-21 01:28:27 +00:00
|
|
|
self.stdout.write("%s\n" % str(self.ruler * len(header)))
|
|
|
|
for command in commands:
|
|
|
|
self.stdout.write("%s %s\n" % (command.ljust(17), getattr(self, 'do_' + command).__doc__))
|
2015-08-05 18:36:39 +00:00
|
|
|
self.stdout.write("\n")
|
|
|
|
|
|
|
|
|
2016-03-22 18:32:47 +00:00
|
|
|
def do_back(self, line):
|
|
|
|
"Go back a menu."
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_agents(self, line):
|
|
|
|
"Jump to the Agents menu."
|
2015-11-22 01:03:40 +00:00
|
|
|
raise NavAgents()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_listeners(self, line):
|
|
|
|
"Jump to the listeners menu."
|
2015-11-22 01:03:40 +00:00
|
|
|
raise NavListeners()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
2016-03-22 18:32:47 +00:00
|
|
|
def do_main(self, line):
|
|
|
|
"Go back to the main menu."
|
|
|
|
raise NavMain()
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_exit(self, line):
|
|
|
|
"Exit Empire."
|
2015-11-22 01:03:40 +00:00
|
|
|
raise KeyboardInterrupt
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
2015-08-20 23:08:40 +00:00
|
|
|
def do_list(self, line):
|
|
|
|
"Lists all active agents (or listeners)."
|
|
|
|
|
|
|
|
if line.lower().startswith("listeners"):
|
|
|
|
self.mainMenu.do_list("listeners " + str(" ".join(line.split(" ")[1:])))
|
|
|
|
elif line.lower().startswith("agents"):
|
|
|
|
self.mainMenu.do_list("agents " + str(" ".join(line.split(" ")[1:])))
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please use 'list [agents/listeners] <modifier>'.")
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_reload(self, line):
|
|
|
|
"Reload the current module."
|
|
|
|
|
|
|
|
print "\n" + helpers.color("[*] Reloading module") + "\n"
|
|
|
|
|
|
|
|
# reload the specific module
|
|
|
|
self.mainMenu.modules.reload_module(self.moduleName)
|
|
|
|
# regrab the reference
|
|
|
|
self.module = self.mainMenu.modules.modules[self.moduleName]
|
|
|
|
|
|
|
|
|
|
|
|
def do_info(self, line):
|
|
|
|
"Display module options."
|
|
|
|
messages.display_module(self.moduleName, self.module)
|
|
|
|
|
|
|
|
|
|
|
|
def do_options(self, line):
|
|
|
|
"Display module options."
|
|
|
|
messages.display_module(self.moduleName, self.module)
|
|
|
|
|
|
|
|
|
|
|
|
def do_set(self, line):
|
|
|
|
"Set a module option."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
parts = line.split()
|
|
|
|
|
|
|
|
try:
|
|
|
|
option = parts[0]
|
|
|
|
if option not in self.module.options:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("[!] Invalid option specified.")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
elif len(parts) == 1:
|
2015-08-05 18:36:39 +00:00
|
|
|
# "set OPTION"
|
|
|
|
# check if we're setting a switch
|
|
|
|
if self.module.options[option]['Description'].startswith("Switch."):
|
|
|
|
self.module.options[option]['Value'] = "True"
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please specify an option value.")
|
|
|
|
else:
|
|
|
|
# otherwise "set OPTION VALUE"
|
|
|
|
option = parts[0]
|
|
|
|
value = " ".join(parts[1:])
|
2016-07-21 01:28:27 +00:00
|
|
|
|
|
|
|
if value == '""' or value == "''":
|
|
|
|
value = ""
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
self.module.options[option]['Value'] = value
|
|
|
|
except:
|
|
|
|
print helpers.color("[!] Error in setting option, likely invalid option name.")
|
|
|
|
|
|
|
|
|
|
|
|
def do_unset(self, line):
|
|
|
|
"Unset a module option."
|
|
|
|
|
|
|
|
option = line.split()[0]
|
|
|
|
|
|
|
|
if line.lower() == "all":
|
|
|
|
for option in self.module.options:
|
|
|
|
self.module.options[option]['Value'] = ''
|
|
|
|
if option not in self.module.options:
|
|
|
|
print helpers.color("[!] Invalid option specified.")
|
|
|
|
else:
|
|
|
|
self.module.options[option]['Value'] = ''
|
|
|
|
|
|
|
|
|
|
|
|
def do_usemodule(self, line):
|
|
|
|
"Use an Empire PowerShell module."
|
|
|
|
|
|
|
|
module = line.strip()
|
|
|
|
|
|
|
|
if module not in self.mainMenu.modules.modules:
|
|
|
|
print helpers.color("[!] Error: invalid module")
|
2016-07-21 01:28:27 +00:00
|
|
|
else:
|
|
|
|
module_menu = ModuleMenu(self.mainMenu, line, agent=self.module.options['Agent']['Value'])
|
|
|
|
module_menu.cmdloop()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_creds(self, line):
|
|
|
|
"Display/return credentials from the database."
|
|
|
|
self.mainMenu.do_creds(line)
|
|
|
|
|
|
|
|
|
|
|
|
def do_execute(self, line):
|
|
|
|
"Execute the given Empire module."
|
|
|
|
|
|
|
|
if not self.validate_options():
|
|
|
|
return
|
|
|
|
|
|
|
|
agentName = self.module.options['Agent']['Value']
|
|
|
|
moduleData = self.module.generate()
|
|
|
|
|
|
|
|
if not moduleData or moduleData == "":
|
|
|
|
print helpers.color("[!] Error: module produced an empty script")
|
|
|
|
dispatcher.send("[!] Error: module produced an empty script", sender="Empire")
|
|
|
|
return
|
|
|
|
|
2015-11-29 01:24:45 +00:00
|
|
|
try:
|
|
|
|
moduleData.decode('ascii')
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
print helpers.color("[!] Error: module source contains non-ascii characters")
|
|
|
|
return
|
|
|
|
|
2015-11-21 23:07:57 +00:00
|
|
|
# strip all comments from the module
|
|
|
|
moduleData = helpers.strip_powershell_comments(moduleData)
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
taskCommand = ""
|
|
|
|
|
|
|
|
# build the appropriate task command and module data blob
|
|
|
|
if str(self.module.info['Background']).lower() == "true":
|
|
|
|
# if this module should be run in the background
|
|
|
|
extention = self.module.info['OutputExtension']
|
|
|
|
if extention and extention != "":
|
|
|
|
# if this module needs to save its file output to the server
|
|
|
|
# format- [15 chars of prefix][5 chars extension][data]
|
|
|
|
saveFilePrefix = self.moduleName.split("/")[-1]
|
|
|
|
moduleData = saveFilePrefix.rjust(15) + extention.rjust(5) + moduleData
|
|
|
|
taskCommand = "TASK_CMD_JOB_SAVE"
|
|
|
|
else:
|
|
|
|
taskCommand = "TASK_CMD_JOB"
|
|
|
|
else:
|
|
|
|
# if this module is run in the foreground
|
|
|
|
extention = self.module.info['OutputExtension']
|
|
|
|
if self.module.info['OutputExtension'] and self.module.info['OutputExtension'] != "":
|
|
|
|
# if this module needs to save its file output to the server
|
|
|
|
# format- [15 chars of prefix][5 chars extension][data]
|
|
|
|
saveFilePrefix = self.moduleName.split("/")[-1][:15]
|
|
|
|
moduleData = saveFilePrefix.rjust(15) + extention.rjust(5) + moduleData
|
|
|
|
taskCommand = "TASK_CMD_WAIT_SAVE"
|
|
|
|
else:
|
|
|
|
taskCommand = "TASK_CMD_WAIT"
|
|
|
|
|
|
|
|
# if we're running the module on all modules
|
|
|
|
if agentName.lower() == "all":
|
|
|
|
try:
|
|
|
|
choice = raw_input(helpers.color("[>] Run module on all agents? [y/N] ", "red"))
|
|
|
|
if choice.lower() != "" and choice.lower()[0] == "y":
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
# signal everyone with what we're doing
|
|
|
|
print helpers.color("[*] Tasking all agents to run " + self.moduleName)
|
|
|
|
dispatcher.send("[*] Tasking all agents to run " + self.moduleName, sender="Empire")
|
|
|
|
|
|
|
|
# actually task the agents
|
|
|
|
for agent in self.mainMenu.agents.get_agents():
|
|
|
|
|
|
|
|
sessionID = agent[1]
|
|
|
|
|
|
|
|
# set the agent's tasking in the cache
|
|
|
|
self.mainMenu.agents.add_agent_task(sessionID, taskCommand, moduleData)
|
|
|
|
|
|
|
|
# update the agent log
|
2016-07-21 01:28:27 +00:00
|
|
|
# dispatcher.send("[*] Tasked agent "+sessionID+" to run module " + self.moduleName, sender="Empire")
|
|
|
|
dispatcher.send("[*] Tasked agent %s to run module %s" % (sessionID, self.moduleName), sender="Empire")
|
|
|
|
msg = "Tasked agent to run module %s" % (self.moduleName)
|
2015-08-05 18:36:39 +00:00
|
|
|
self.mainMenu.agents.save_agent_log(sessionID, msg)
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
print ""
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2015-11-22 22:25:28 +00:00
|
|
|
# set the script to be the global autorun
|
|
|
|
elif agentName.lower() == "autorun":
|
|
|
|
|
|
|
|
self.mainMenu.agents.set_autoruns(taskCommand, moduleData)
|
2016-07-21 01:28:27 +00:00
|
|
|
dispatcher.send("[*] Set module %s to be global script autorun." % (self.moduleName), sender="Empire")
|
2015-11-22 22:25:28 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
if not self.mainMenu.agents.is_agent_present(agentName):
|
|
|
|
print helpers.color("[!] Invalid agent name.")
|
|
|
|
else:
|
|
|
|
# set the agent's tasking in the cache
|
|
|
|
self.mainMenu.agents.add_agent_task(agentName, taskCommand, moduleData)
|
|
|
|
|
|
|
|
# update the agent log
|
2016-07-21 01:28:27 +00:00
|
|
|
dispatcher.send("[*] Tasked agent %s to run module %s" % (agentName, self.moduleName), sender="Empire")
|
|
|
|
msg = "Tasked agent to run module %s" % (self.moduleName)
|
2015-08-05 18:36:39 +00:00
|
|
|
self.mainMenu.agents.save_agent_log(agentName, msg)
|
|
|
|
|
|
|
|
|
2015-08-20 22:49:23 +00:00
|
|
|
def do_run(self, line):
|
|
|
|
"Execute the given Empire module."
|
|
|
|
self.do_execute(line)
|
|
|
|
|
|
|
|
|
2016-07-15 22:56:38 +00:00
|
|
|
def do_interact(self, line):
|
|
|
|
"Interact with a particular agent."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2016-07-15 22:56:38 +00:00
|
|
|
name = line.strip()
|
|
|
|
|
|
|
|
if name != "" and self.mainMenu.agents.is_agent_present(name):
|
|
|
|
# resolve the passed name to a sessionID
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(name)
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
agent_menu = AgentMenu(self.mainMenu, sessionID)
|
|
|
|
agent_menu.cmdloop()
|
2016-07-15 22:56:38 +00:00
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid agent name")
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def complete_set(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a module option to set."
|
|
|
|
|
|
|
|
options = self.module.options.keys()
|
|
|
|
|
|
|
|
if line.split(" ")[1].lower() == "agent":
|
|
|
|
# if we're tab-completing "agent", return the agent names
|
2015-11-22 22:25:28 +00:00
|
|
|
agentNames = self.mainMenu.agents.get_agent_names() + ["all", "autorun"]
|
2016-07-21 01:28:27 +00:00
|
|
|
end_line = " ".join(line.split(" ")[1:])
|
|
|
|
|
|
|
|
mline = end_line.partition(' ')[2]
|
2015-08-05 18:36:39 +00:00
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in agentNames if s.startswith(mline)]
|
|
|
|
|
|
|
|
elif line.split(" ")[1].lower() == "listener":
|
|
|
|
# if we're tab-completing a listener name, return all the names
|
|
|
|
listenerNames = self.mainMenu.listeners.get_listener_names()
|
2016-07-21 01:28:27 +00:00
|
|
|
end_line = " ".join(line.split(" ")[1:])
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
mline = end_line.partition(' ')[2]
|
2015-08-05 18:36:39 +00:00
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in listenerNames if s.startswith(mline)]
|
|
|
|
|
|
|
|
elif line.split(" ")[1].lower().endswith("path"):
|
2016-07-21 01:28:27 +00:00
|
|
|
return helpers.complete_path(text, line, arg=True)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
elif line.split(" ")[1].lower().endswith("file"):
|
2016-07-21 01:28:27 +00:00
|
|
|
return helpers.complete_path(text, line, arg=True)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
elif line.split(" ")[1].lower().endswith("host"):
|
|
|
|
return [helpers.lhost()]
|
|
|
|
|
|
|
|
# otherwise we're tab-completing an option name
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in options if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_unset(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a module option to unset."
|
|
|
|
|
|
|
|
options = self.module.options.keys() + ["all"]
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in options if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_usemodule(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an Empire PowerShell module path."
|
|
|
|
return self.mainMenu.complete_usemodule(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
|
|
|
def complete_creds(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete 'creds' commands."
|
|
|
|
return self.mainMenu.complete_creds(text, line, begidx, endidx)
|
|
|
|
|
|
|
|
|
2016-07-15 22:56:38 +00:00
|
|
|
def complete_interact(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an interact command"
|
|
|
|
|
|
|
|
names = self.mainMenu.agents.get_agent_names()
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in names if s.startswith(mline)]
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
class StagerMenu(cmd.Cmd):
|
2016-07-21 01:28:27 +00:00
|
|
|
"""
|
|
|
|
The main class used by Empire to drive the 'stager' menu.
|
|
|
|
"""
|
2015-08-05 18:36:39 +00:00
|
|
|
def __init__(self, mainMenu, stagerName, listener=None):
|
|
|
|
cmd.Cmd.__init__(self)
|
|
|
|
self.doc_header = 'Stager Menu'
|
|
|
|
|
|
|
|
self.mainMenu = mainMenu
|
|
|
|
|
|
|
|
# get the current stager name
|
|
|
|
self.stagerName = stagerName
|
|
|
|
self.stager = self.mainMenu.stagers.stagers[stagerName]
|
|
|
|
|
|
|
|
# set the prompt text
|
2016-07-21 01:28:27 +00:00
|
|
|
self.prompt = '(Empire: ' + helpers.color("stager/" + self.stagerName, color="blue") + ') > '
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# if this menu is being called from an listener menu
|
|
|
|
if listener:
|
|
|
|
# resolve the listener ID to a name, if applicable
|
|
|
|
listener = self.mainMenu.listeners.get_listener(listener)
|
|
|
|
self.stager.options['Listener']['Value'] = listener
|
|
|
|
|
|
|
|
|
|
|
|
def validate_options(self):
|
|
|
|
"Make sure all required stager options are completed."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
|
|
|
for option, values in self.stager.options.iteritems():
|
2015-08-05 18:36:39 +00:00
|
|
|
if values['Required'] and ((not values['Value']) or (values['Value'] == '')):
|
|
|
|
print helpers.color("[!] Error: Required stager option missing.")
|
|
|
|
return False
|
|
|
|
|
|
|
|
listenerName = self.stager.options['Listener']['Value']
|
|
|
|
|
2016-03-22 01:50:19 +00:00
|
|
|
if not self.mainMenu.listeners.is_listener_valid(listenerName):
|
2015-08-05 18:36:39 +00:00
|
|
|
print helpers.color("[!] Invalid listener ID or name.")
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
def emptyline(self):
|
|
|
|
pass
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
# print a nicely formatted help menu
|
|
|
|
# stolen/adapted from recon-ng
|
2016-07-21 01:28:27 +00:00
|
|
|
def print_topics(self, header, commands, cmdlen, maxcol):
|
|
|
|
if commands:
|
|
|
|
self.stdout.write("%s\n" % str(header))
|
2015-08-05 18:36:39 +00:00
|
|
|
if self.ruler:
|
2016-07-21 01:28:27 +00:00
|
|
|
self.stdout.write("%s\n" % str(self.ruler * len(header)))
|
|
|
|
for command in commands:
|
|
|
|
self.stdout.write("%s %s\n" % (command.ljust(17), getattr(self, 'do_' + command).__doc__))
|
2015-08-05 18:36:39 +00:00
|
|
|
self.stdout.write("\n")
|
|
|
|
|
|
|
|
|
2016-03-22 18:32:47 +00:00
|
|
|
def do_back(self, line):
|
|
|
|
"Go back a menu."
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def do_agents(self, line):
|
|
|
|
"Jump to the Agents menu."
|
|
|
|
raise NavAgents()
|
|
|
|
|
|
|
|
|
|
|
|
def do_listeners(self, line):
|
|
|
|
"Jump to the listeners menu."
|
|
|
|
raise NavListeners()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def do_main(self, line):
|
2016-03-22 18:32:47 +00:00
|
|
|
"Go back to the main menu."
|
|
|
|
raise NavMain()
|
|
|
|
|
|
|
|
|
|
|
|
def do_exit(self, line):
|
|
|
|
"Exit Empire."
|
|
|
|
raise KeyboardInterrupt
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
2015-08-20 23:08:40 +00:00
|
|
|
def do_list(self, line):
|
|
|
|
"Lists all active agents (or listeners)."
|
|
|
|
|
|
|
|
if line.lower().startswith("listeners"):
|
|
|
|
self.mainMenu.do_list("listeners " + str(" ".join(line.split(" ")[1:])))
|
|
|
|
elif line.lower().startswith("agents"):
|
|
|
|
self.mainMenu.do_list("agents " + str(" ".join(line.split(" ")[1:])))
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please use 'list [agents/listeners] <modifier>'.")
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def do_info(self, line):
|
|
|
|
"Display stager options."
|
|
|
|
messages.display_stager(self.stagerName, self.stager)
|
|
|
|
|
|
|
|
|
|
|
|
def do_options(self, line):
|
|
|
|
"Display stager options."
|
|
|
|
messages.display_stager(self.stagerName, self.stager)
|
|
|
|
|
|
|
|
|
|
|
|
def do_set(self, line):
|
|
|
|
"Set a stager option."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
parts = line.split()
|
|
|
|
|
|
|
|
try:
|
|
|
|
option = parts[0]
|
|
|
|
if option not in self.stager.options:
|
2016-07-21 01:28:27 +00:00
|
|
|
print helpers.color("[!] Invalid option specified.")
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
elif len(parts) == 1:
|
2015-08-05 18:36:39 +00:00
|
|
|
# "set OPTION"
|
|
|
|
# check if we're setting a switch
|
|
|
|
if self.stager.options[option]['Description'].startswith("Switch."):
|
|
|
|
self.stager.options[option]['Value'] = "True"
|
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please specify an option value.")
|
|
|
|
else:
|
|
|
|
# otherwise "set OPTION VALUE"
|
|
|
|
option = parts[0]
|
|
|
|
value = " ".join(parts[1:])
|
2016-07-21 01:28:27 +00:00
|
|
|
|
|
|
|
if value == '""' or value == "''":
|
|
|
|
value = ""
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
self.stager.options[option]['Value'] = value
|
|
|
|
except:
|
|
|
|
print helpers.color("[!] Error in setting option, likely invalid option name.")
|
|
|
|
|
|
|
|
|
|
|
|
def do_unset(self, line):
|
|
|
|
"Unset a stager option."
|
|
|
|
|
|
|
|
option = line.split()[0]
|
|
|
|
|
|
|
|
if line.lower() == "all":
|
|
|
|
for option in self.stager.options:
|
|
|
|
self.stager.options[option]['Value'] = ''
|
|
|
|
if option not in self.stager.options:
|
|
|
|
print helpers.color("[!] Invalid option specified.")
|
|
|
|
else:
|
|
|
|
self.stager.options[option]['Value'] = ''
|
|
|
|
|
|
|
|
|
|
|
|
def do_generate(self, line):
|
|
|
|
"Generate/execute the given Empire stager."
|
|
|
|
|
|
|
|
if not self.validate_options():
|
|
|
|
return
|
|
|
|
|
|
|
|
stagerOutput = self.stager.generate()
|
|
|
|
|
|
|
|
savePath = ''
|
|
|
|
if 'OutFile' in self.stager.options:
|
|
|
|
savePath = self.stager.options['OutFile']['Value']
|
|
|
|
|
|
|
|
if savePath != '':
|
|
|
|
# make the base directory if it doesn't exist
|
|
|
|
if not os.path.exists(os.path.dirname(savePath)) and os.path.dirname(savePath) != '':
|
|
|
|
os.makedirs(os.path.dirname(savePath))
|
|
|
|
|
|
|
|
# if we need to write binary output for a .dll
|
|
|
|
if ".dll" in savePath:
|
2016-07-21 01:28:27 +00:00
|
|
|
out_file = open(savePath, 'wb')
|
|
|
|
out_file.write(bytearray(stagerOutput))
|
|
|
|
out_file.close()
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
# otherwise normal output
|
2016-07-21 01:28:27 +00:00
|
|
|
out_file = open(savePath, 'w')
|
|
|
|
out_file.write(stagerOutput)
|
|
|
|
out_file.close()
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# if this is a bash script, make it executable
|
|
|
|
if ".sh" in savePath:
|
|
|
|
os.chmod(savePath, 777)
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
print "\n" + helpers.color("[*] Stager output written out to: %s\n" % (savePath))
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
else:
|
|
|
|
print stagerOutput
|
|
|
|
|
|
|
|
|
|
|
|
def do_execute(self, line):
|
|
|
|
"Generate/execute the given Empire stager."
|
|
|
|
self.do_generate(line)
|
|
|
|
|
|
|
|
|
2016-07-15 22:56:38 +00:00
|
|
|
def do_interact(self, line):
|
|
|
|
"Interact with a particular agent."
|
2016-07-21 01:28:27 +00:00
|
|
|
|
2016-07-15 22:56:38 +00:00
|
|
|
name = line.strip()
|
|
|
|
|
|
|
|
if name != "" and self.mainMenu.agents.is_agent_present(name):
|
|
|
|
# resolve the passed name to a sessionID
|
|
|
|
sessionID = self.mainMenu.agents.get_agent_id(name)
|
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
agent_menu = AgentMenu(self.mainMenu, sessionID)
|
|
|
|
agent_menu.cmdloop()
|
2016-07-15 22:56:38 +00:00
|
|
|
else:
|
|
|
|
print helpers.color("[!] Please enter a valid agent name")
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def complete_set(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a stager option to set."
|
|
|
|
|
|
|
|
options = self.stager.options.keys()
|
|
|
|
|
|
|
|
if line.split(" ")[1].lower() == "listener":
|
|
|
|
# if we're tab-completing a listener name, return all the names
|
|
|
|
listenerNames = self.mainMenu.listeners.get_listener_names()
|
2016-07-21 01:28:27 +00:00
|
|
|
end_line = " ".join(line.split(" ")[1:])
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-07-21 01:28:27 +00:00
|
|
|
mline = end_line.partition(' ')[2]
|
2015-08-05 18:36:39 +00:00
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in listenerNames if s.startswith(mline)]
|
|
|
|
|
|
|
|
elif line.split(" ")[1].lower().endswith("path"):
|
|
|
|
# tab-complete any stager option that ends with 'path'
|
2016-07-21 01:28:27 +00:00
|
|
|
return helpers.complete_path(text, line, arg=True)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
# otherwise we're tab-completing an option name
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in options if s.startswith(mline)]
|
|
|
|
|
|
|
|
|
|
|
|
def complete_unset(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete a stager option to unset."
|
|
|
|
|
|
|
|
options = self.stager.options.keys() + ["all"]
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
|
|
|
return [s[offs:] for s in options if s.startswith(mline)]
|
2016-07-15 22:56:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
def complete_interact(self, text, line, begidx, endidx):
|
|
|
|
"Tab-complete an interact command"
|
|
|
|
|
|
|
|
names = self.mainMenu.agents.get_agent_names()
|
|
|
|
|
|
|
|
mline = line.partition(' ')[2]
|
|
|
|
offs = len(mline) - len(text)
|
2016-07-21 01:28:27 +00:00
|
|
|
return [s[offs:] for s in names if s.startswith(mline)]
|