From a664e3b49192e012df48730e723a22c5a148ba96 Mon Sep 17 00:00:00 2001 From: Alexander Neff Date: Fri, 8 Sep 2023 21:53:39 +0200 Subject: [PATCH 01/16] Fix for allowing to test multiple users with one password --- cme/connection.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cme/connection.py b/cme/connection.py index 09aa0ef3..05ede773 100755 --- a/cme/connection.py +++ b/cme/connection.py @@ -341,6 +341,12 @@ class connection(object): secret.append(aesKey) cred_type.append('aesKey') + # Allow trying multiple users with a single password + if len(username) > 1 and len(secret) == 1: + secret = secret * len(username) + cred_type = cred_type * len(username) + self.args.no_bruteforce = True + return domain, username, owned, secret, cred_type, [None] * len(secret) def try_credentials(self, domain, username, owned, secret, cred_type, data=None): From 0e528ae8f0eaa436d0a4fb315541c140763f98f7 Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Sat, 9 Sep 2023 19:19:41 +0200 Subject: [PATCH 02/16] Add us to cli output --- cme/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cme/cli.py b/cme/cli.py index 623ff288..a8f7e407 100755 --- a/cme/cli.py +++ b/cme/cli.py @@ -24,7 +24,8 @@ def gen_cli_args(): \______|| _| `._____|/__/ \__\ \______||__|\__\ |__| |__| /__/ \__\ | _| |_______|/__/ \__\ |_______| \______| A swiss army knife for pentesting networks - Forged by @byt3bl33d3r and @mpgn_x64 using the powah of dank memes + Forged by @byt3bl33d3r and @mpgn_x64 using the powah of dank memes. + Maintained as an open source project by @NeffIsBack, @MJHallenbeck, @_zblurx {highlight('Version', 'red')} : {highlight(VERSION)} {highlight('Codename', 'red')}: {highlight(CODENAME)} From 2400bc6c200963a273463d160fab52836fa8cb8c Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Sat, 9 Sep 2023 19:20:46 +0200 Subject: [PATCH 03/16] Make exec fail messages more precise --- cme/protocols/smb/atexec.py | 2 +- cme/protocols/smb/mmcexec.py | 2 +- cme/protocols/smb/proto_args.py | 2 +- cme/protocols/smb/smbexec.py | 2 +- cme/protocols/smb/wmiexec.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cme/protocols/smb/atexec.py b/cme/protocols/smb/atexec.py index 1e4d02bd..049b84ed 100755 --- a/cme/protocols/smb/atexec.py +++ b/cme/protocols/smb/atexec.py @@ -203,7 +203,7 @@ class TSCH_EXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f'ATEXEC: Get output file error, maybe got detected by AV software, please increase the number of tries with the option "--get-output-tries". If it\'s still failing maybe something is blocking the schedule job, try another exec method') + self.logger.fail(f'ATEXEC: Couldn\'t retrieve output file, maybe got detected by AV. Please increase the number of tries with the option "--get-output-tries". If it\'s still failing, try the wmi protocol or another exec method') break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : self.logger.fail(f'ATEXEC: Get ouput failed, target has blocked ADMIN$ access (maybe command executed!)') diff --git a/cme/protocols/smb/mmcexec.py b/cme/protocols/smb/mmcexec.py index 4ab99c76..3b320a59 100644 --- a/cme/protocols/smb/mmcexec.py +++ b/cme/protocols/smb/mmcexec.py @@ -252,7 +252,7 @@ class MMCEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f'MMCEXEC: Get output file error, maybe got detected by AV software, please increase the number of tries with the option "--get-output-tries". If it\'s still failing maybe something is blocking the schedule job, try another exec method') + self.logger.fail(f'MMCEXEC: Couldn\'t retrieve output file, maybe got detected by AV. Please increase the number of tries with the option "--get-output-tries". If it\'s still failing, try the wmi protocol or another exec method') break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : self.logger.fail(f'MMCEXEC: Get ouput failed, target has blocked {self.__share} access (maybe command executed!)') diff --git a/cme/protocols/smb/proto_args.py b/cme/protocols/smb/proto_args.py index 9dac1c8b..eb083226 100644 --- a/cme/protocols/smb/proto_args.py +++ b/cme/protocols/smb/proto_args.py @@ -91,7 +91,7 @@ def proto_args(parser, std_parser, module_parser): help="force the PowerShell command to run in a 32-bit process") cgroup.add_argument("--no-output", action="store_true", help="do not retrieve command output") cegroup = cgroup.add_mutually_exclusive_group() - cegroup.add_argument("-x", metavar="COMMAND", dest="execute", help="execute the specified command") + cegroup.add_argument("-x", metavar="COMMAND", dest="execute", help="execute the specified CMD command") cegroup.add_argument("-X", metavar="PS_COMMAND", dest="ps_execute", help="execute the specified PowerShell command") psgroup = smb_parser.add_argument_group("Powershell Obfuscation", "Options for PowerShell script obfuscation") psgroup.add_argument("--obfs", action="store_true", help="Obfuscate PowerShell scripts") diff --git a/cme/protocols/smb/smbexec.py b/cme/protocols/smb/smbexec.py index 1f51acd2..a54275ed 100755 --- a/cme/protocols/smb/smbexec.py +++ b/cme/protocols/smb/smbexec.py @@ -170,7 +170,7 @@ class SMBEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f'SMBEXEC: Get output file error, maybe got detected by AV software, please increase the number of tries with the option "--get-output-tries". If it\'s still failing maybe something is blocking the schedule job, try another exec method') + self.logger.fail(f'SMBEXEC: Couldn\'t retrieve output file, maybe got detected by AV. Please increase the number of tries with the option "--get-output-tries". If it\'s still failing, try the wmi protocol or another exec method') break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : self.logger.fail(f'SMBEXEC: Get ouput failed, target has blocked {self.__share} access (maybe command executed!)') diff --git a/cme/protocols/smb/wmiexec.py b/cme/protocols/smb/wmiexec.py index 419ed4fb..13693c90 100755 --- a/cme/protocols/smb/wmiexec.py +++ b/cme/protocols/smb/wmiexec.py @@ -166,7 +166,7 @@ class WMIEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f'WMIEXEC: Get output file error, maybe got detected by AV software, please increase the number of tries with the option "--get-output-tries". If it\'s still failing maybe something is blocking the schedule job, try another exec method') + self.logger.fail(f'WMIEXEC: Couldn\'t retrieve output-file, maybe got detected by AV. Try the wmi protocol or another exec method') break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : self.logger.fail(f'SMB connection: target has blocked {self.__share} access (maybe command executed!)') From 4a739a0f323026bcc08e9390e11a1c1675fdffa0 Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Sat, 9 Sep 2023 19:21:57 +0200 Subject: [PATCH 04/16] Change wmi --interval-time to --exec-timeout to more accuratly represent the effect --- cme/protocols/wmi.py | 6 +++--- cme/protocols/wmi/proto_args.py | 2 +- cme/protocols/wmi/wmiexec.py | 10 +++++----- cme/protocols/wmi/wmiexec_event.py | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cme/protocols/wmi.py b/cme/protocols/wmi.py index c5eb8fb9..a2ac6ae4 100644 --- a/cme/protocols/wmi.py +++ b/cme/protocols/wmi.py @@ -432,7 +432,7 @@ class wmi(connection): if not self.args.no_output: get_output = True - if "systeminfo" in command and self.args.interval_time < 10: + if "systeminfo" in command and self.args.exec_timeout < 10: self.logger.fail("Execute 'systeminfo' must set the interval time higher than 10 seconds") return False @@ -441,11 +441,11 @@ class wmi(connection): return False if self.args.exec_method == "wmiexec": - exec_method = wmiexec.WMIEXEC(self.conn.getRemoteName(), self.username, self.password, self.domain, self.lmhash, self.nthash, self.doKerberos, self.kdcHost, self.aesKey, self.logger, self.args.interval_time, self.args.codec) + exec_method = wmiexec.WMIEXEC(self.conn.getRemoteName(), self.username, self.password, self.domain, self.lmhash, self.nthash, self.doKerberos, self.kdcHost, self.aesKey, self.logger, self.args.exec_timeout, self.args.codec) output = exec_method.execute(command, get_output) elif self.args.exec_method == "wmiexec-event": - exec_method = wmiexec_event.WMIEXEC_EVENT(self.conn.getRemoteName(), self.username, self.password, self.domain, self.lmhash, self.nthash, self.doKerberos, self.kdcHost, self.aesKey, self.logger, self.args.interval_time, self.args.codec) + exec_method = wmiexec_event.WMIEXEC_EVENT(self.conn.getRemoteName(), self.username, self.password, self.domain, self.lmhash, self.nthash, self.doKerberos, self.kdcHost, self.aesKey, self.logger, self.args.exec_timeout, self.args.codec) output = exec_method.execute(command, get_output) self.conn.disconnect() diff --git a/cme/protocols/wmi/proto_args.py b/cme/protocols/wmi/proto_args.py index 6bb1605e..53d37f68 100644 --- a/cme/protocols/wmi/proto_args.py +++ b/cme/protocols/wmi/proto_args.py @@ -23,7 +23,7 @@ def proto_args(parser, std_parser, module_parser): "[wmiexec (win32_process + StdRegProv)]: get command results over registry instead of using smb connection. " "[wmiexec-event (T1546.003)]: this method is not very stable, highly recommend use this method in single host, " "using on multiple hosts may crash (just try again if it crashed).") - cgroup.add_argument("--interval-time", default=5 ,metavar='INTERVAL_TIME', dest='interval_time', type=int, help='Set interval time(seconds) when executing command, unrecommend set it lower than 5') + cgroup.add_argument("--exec-timeout", default=5, metavar='exec_timeout', dest='exec_timeout', type=int, help='Set timeout (in seconds) when executing a command, minimum 5 seconds is recommended. Default: %(default)s') cgroup.add_argument("--codec", default="utf-8", help="Set encoding used (codec) from the target's output (default " "\"utf-8\"). If errors are detected, run chcp.com at the target, " diff --git a/cme/protocols/wmi/wmiexec.py b/cme/protocols/wmi/wmiexec.py index 70b027af..59d167fe 100644 --- a/cme/protocols/wmi/wmiexec.py +++ b/cme/protocols/wmi/wmiexec.py @@ -34,7 +34,7 @@ from impacket.dcerpc.v5.dcomrt import DCOMConnection from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, WBEM_FLAG_FORWARD_ONLY, IWbemLevel1Login class WMIEXEC: - def __init__(self, host, username, password, domain, lmhash, nthash, doKerberos, kdcHost, aesKey, logger, interval_time, codec): + def __init__(self, host, username, password, domain, lmhash, nthash, doKerberos, kdcHost, aesKey, logger, exec_timeout, codec): self.__host = host self.__username = username self.__password = password @@ -45,7 +45,7 @@ class WMIEXEC: self.__kdcHost = kdcHost self.__aesKey = aesKey self.logger = logger - self.__interval_time = interval_time + self.__exec_timeout = exec_timeout self.__registry_Path = "" self.__outputBuffer = "" self.__retOutput = True @@ -91,8 +91,8 @@ class WMIEXEC: command = fr'''{self.__shell} {command} 1> {result_output} 2>&1 && certutil -encodehex -f {result_output} {result_output_b64} 0x40000001 && for /F "usebackq" %G in ("{result_output_b64}") do reg add HKLM\{self.__registry_Path} /v {keyName} /t REG_SZ /d "%G" /f && del /q /f /s {result_output} {result_output_b64}''' self.execute_remote(command) - self.logger.info("Waiting {}s for command completely executed.".format(self.__interval_time)) - time.sleep(self.__interval_time) + self.logger.info("Waiting {}s for command completely executed.".format(self.__exec_timeout)) + time.sleep(self.__exec_timeout) self.queryRegistry(keyName) @@ -104,7 +104,7 @@ class WMIEXEC: retVal = descriptor.GetStringValue(2147483650, self.__registry_Path, keyName) self.__outputBuffer = base64.b64decode(retVal.sValue).decode(self.__codec, errors='replace').rstrip('\r\n') except Exception as e: - self.logger.fail(f'WMIEXEC: Get output file error, maybe command not executed successfully or got detected by AV software, please increase the interval time of command execution with "--interval-time" option. If it\'s still failing maybe something is blocking the schedule job in vbscript, try another exec method') + self.logger.fail(f'WMIEXEC: Couldn\'t retrieve output-file. Either command timed out or got detected by AV. Try increasing the timeout with "--exec-timeout" option. If it\'s still failing, try the smb protocol or another exec method') try: self.logger.debug(f"Removing temporary registry path: HKLM\\{self.__registry_Path}") diff --git a/cme/protocols/wmi/wmiexec_event.py b/cme/protocols/wmi/wmiexec_event.py index e1ada22c..8e1c6dcd 100644 --- a/cme/protocols/wmi/wmiexec_event.py +++ b/cme/protocols/wmi/wmiexec_event.py @@ -37,7 +37,7 @@ from impacket.dcerpc.v5.dcom.wmi import WBEMSTATUS from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, WBEM_FLAG_FORWARD_ONLY, IWbemLevel1Login, WBEMSTATUS class WMIEXEC_EVENT: - def __init__(self, host, username, password, domain, lmhash, nthash, doKerberos, kdcHost, aesKey, logger, interval_time, codec): + def __init__(self, host, username, password, domain, lmhash, nthash, doKerberos, kdcHost, aesKey, logger, exec_timeout, codec): self.__host = host self.__username = username self.__password = password @@ -51,7 +51,7 @@ class WMIEXEC_EVENT: self.__retOutput = True self.logger = logger - self.__interval_time = interval_time + self.__exec_timeout = exec_timeout self.__codec = codec self.__instanceID = f"windows-object-{str(uuid.uuid4())}" self.__instanceID_StoreResult = f"windows-object-{str(uuid.uuid4())}" @@ -84,8 +84,8 @@ class WMIEXEC_EVENT: self.execute_remote(command) # Get command results - self.logger.info("Waiting {}s for command completely executed.".format(self.__interval_time)) - time.sleep(self.__interval_time) + self.logger.info("Waiting {}s for command completely executed.".format(self.__exec_timeout)) + time.sleep(self.__exec_timeout) if self.__retOutput: self.get_CommandResult() @@ -190,7 +190,7 @@ class WMIEXEC_EVENT: record = dict(command_ResultObject.getProperties()) self.__outputBuffer = base64.b64decode(record['ScriptText']['value']).decode(self.__codec, errors='replace') except Exception as e: - self.logger.fail(f'WMIEXEC-EVENT: Get output file error, maybe command not executed successfully or got detected by AV software, please increase the interval time of command execution with "--interval-time" option. If it\'s still failing maybe something is blocking the schedule job in vbscript, try another exec method') + self.logger.fail(f'WMIEXEC-EVENT: Couldn\'t retrieve output-file. Either command timed out or got detected by AV. Try increasing the timeout with "--exec-timeout" option. If it\'s still failing, try the smb protocol or another exec method') def remove_Instance(self): if self.__retOutput: From 2119d37e528051dbd6b2ef556f5dad0fb48ef328 Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Sat, 9 Sep 2023 19:40:13 +0200 Subject: [PATCH 05/16] Typo --- cme/protocols/smb/wmiexec.py | 2 +- cme/protocols/wmi/wmiexec.py | 2 +- cme/protocols/wmi/wmiexec_event.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cme/protocols/smb/wmiexec.py b/cme/protocols/smb/wmiexec.py index 13693c90..21f6c313 100755 --- a/cme/protocols/smb/wmiexec.py +++ b/cme/protocols/smb/wmiexec.py @@ -166,7 +166,7 @@ class WMIEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f'WMIEXEC: Couldn\'t retrieve output-file, maybe got detected by AV. Try the wmi protocol or another exec method') + self.logger.fail(f'WMIEXEC: Couldn\'t retrieve output file, maybe got detected by AV. Try the wmi protocol or another exec method') break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : self.logger.fail(f'SMB connection: target has blocked {self.__share} access (maybe command executed!)') diff --git a/cme/protocols/wmi/wmiexec.py b/cme/protocols/wmi/wmiexec.py index 59d167fe..38b79274 100644 --- a/cme/protocols/wmi/wmiexec.py +++ b/cme/protocols/wmi/wmiexec.py @@ -104,7 +104,7 @@ class WMIEXEC: retVal = descriptor.GetStringValue(2147483650, self.__registry_Path, keyName) self.__outputBuffer = base64.b64decode(retVal.sValue).decode(self.__codec, errors='replace').rstrip('\r\n') except Exception as e: - self.logger.fail(f'WMIEXEC: Couldn\'t retrieve output-file. Either command timed out or got detected by AV. Try increasing the timeout with "--exec-timeout" option. If it\'s still failing, try the smb protocol or another exec method') + self.logger.fail(f'WMIEXEC: Couldn\'t retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with "--exec-timeout" option. If it\'s still failing, try the smb protocol or another exec method') try: self.logger.debug(f"Removing temporary registry path: HKLM\\{self.__registry_Path}") diff --git a/cme/protocols/wmi/wmiexec_event.py b/cme/protocols/wmi/wmiexec_event.py index 8e1c6dcd..e5619ae5 100644 --- a/cme/protocols/wmi/wmiexec_event.py +++ b/cme/protocols/wmi/wmiexec_event.py @@ -190,7 +190,7 @@ class WMIEXEC_EVENT: record = dict(command_ResultObject.getProperties()) self.__outputBuffer = base64.b64decode(record['ScriptText']['value']).decode(self.__codec, errors='replace') except Exception as e: - self.logger.fail(f'WMIEXEC-EVENT: Couldn\'t retrieve output-file. Either command timed out or got detected by AV. Try increasing the timeout with "--exec-timeout" option. If it\'s still failing, try the smb protocol or another exec method') + self.logger.fail(f'WMIEXEC-EVENT: Couldn\'t retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with "--exec-timeout" option. If it\'s still failing, try the smb protocol or another exec method') def remove_Instance(self): if self.__retOutput: From 95ac793b2aa401d57644bdf53c539f95188e5566 Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Sat, 9 Sep 2023 23:13:06 +0200 Subject: [PATCH 06/16] Replacing single quotes with double quotes in strings --- cme/protocols/smb/atexec.py | 4 ++-- cme/protocols/smb/mmcexec.py | 4 ++-- cme/protocols/smb/smbexec.py | 4 ++-- cme/protocols/smb/wmiexec.py | 4 ++-- cme/protocols/wmi/wmiexec.py | 2 +- cme/protocols/wmi/wmiexec_event.py | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cme/protocols/smb/atexec.py b/cme/protocols/smb/atexec.py index 049b84ed..0f539455 100755 --- a/cme/protocols/smb/atexec.py +++ b/cme/protocols/smb/atexec.py @@ -203,10 +203,10 @@ class TSCH_EXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f'ATEXEC: Couldn\'t retrieve output file, maybe got detected by AV. Please increase the number of tries with the option "--get-output-tries". If it\'s still failing, try the wmi protocol or another exec method') + self.logger.fail(f"ATEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option \"--get-output-tries\". If it's still failing, try the wmi protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : - self.logger.fail(f'ATEXEC: Get ouput failed, target has blocked ADMIN$ access (maybe command executed!)') + self.logger.fail(f"ATEXEC: Get ouput failed, target has blocked ADMIN$ access (maybe command executed!)") break if str(e).find("SHARING") > 0 or str(e).find("STATUS_OBJECT_NAME_NOT_FOUND") >= 0: sleep(3) diff --git a/cme/protocols/smb/mmcexec.py b/cme/protocols/smb/mmcexec.py index 3b320a59..0cc5637a 100644 --- a/cme/protocols/smb/mmcexec.py +++ b/cme/protocols/smb/mmcexec.py @@ -252,10 +252,10 @@ class MMCEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f'MMCEXEC: Couldn\'t retrieve output file, maybe got detected by AV. Please increase the number of tries with the option "--get-output-tries". If it\'s still failing, try the wmi protocol or another exec method') + self.logger.fail(f"MMCEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option \"--get-output-tries\". If it's still failing, try the wmi protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : - self.logger.fail(f'MMCEXEC: Get ouput failed, target has blocked {self.__share} access (maybe command executed!)') + self.logger.fail(f"MMCEXEC: Get ouput failed, target has blocked {self.__share} access (maybe command executed!)") break if str(e).find("STATUS_SHARING_VIOLATION") >= 0 or str(e).find("STATUS_OBJECT_NAME_NOT_FOUND") >= 0: # Output not finished, let's wait diff --git a/cme/protocols/smb/smbexec.py b/cme/protocols/smb/smbexec.py index a54275ed..b58a4f84 100755 --- a/cme/protocols/smb/smbexec.py +++ b/cme/protocols/smb/smbexec.py @@ -170,10 +170,10 @@ class SMBEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f'SMBEXEC: Couldn\'t retrieve output file, maybe got detected by AV. Please increase the number of tries with the option "--get-output-tries". If it\'s still failing, try the wmi protocol or another exec method') + self.logger.fail(f"SMBEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option \"--get-output-tries\". If it's still failing, try the wmi protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : - self.logger.fail(f'SMBEXEC: Get ouput failed, target has blocked {self.__share} access (maybe command executed!)') + self.logger.fail(f"SMBEXEC: Get ouput failed, target has blocked {self.__share} access (maybe command executed!)") break if str(e).find("STATUS_SHARING_VIOLATION") >= 0 or str(e).find("STATUS_OBJECT_NAME_NOT_FOUND") >= 0: # Output not finished, let's wait diff --git a/cme/protocols/smb/wmiexec.py b/cme/protocols/smb/wmiexec.py index 21f6c313..45e65495 100755 --- a/cme/protocols/smb/wmiexec.py +++ b/cme/protocols/smb/wmiexec.py @@ -166,10 +166,10 @@ class WMIEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f'WMIEXEC: Couldn\'t retrieve output file, maybe got detected by AV. Try the wmi protocol or another exec method') + self.logger.fail(f"WMIEXEC: Couldn't retrieve output file, maybe got detected by AV. Try the wmi protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : - self.logger.fail(f'SMB connection: target has blocked {self.__share} access (maybe command executed!)') + self.logger.fail(f"SMB connection: target has blocked {self.__share} access (maybe command executed!)") break if str(e).find("STATUS_SHARING_VIOLATION") >= 0 or str(e).find("STATUS_OBJECT_NAME_NOT_FOUND") >= 0: sleep(2) diff --git a/cme/protocols/wmi/wmiexec.py b/cme/protocols/wmi/wmiexec.py index 38b79274..cf9cd0de 100644 --- a/cme/protocols/wmi/wmiexec.py +++ b/cme/protocols/wmi/wmiexec.py @@ -104,7 +104,7 @@ class WMIEXEC: retVal = descriptor.GetStringValue(2147483650, self.__registry_Path, keyName) self.__outputBuffer = base64.b64decode(retVal.sValue).decode(self.__codec, errors='replace').rstrip('\r\n') except Exception as e: - self.logger.fail(f'WMIEXEC: Couldn\'t retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with "--exec-timeout" option. If it\'s still failing, try the smb protocol or another exec method') + self.logger.fail(f"WMIEXEC: Couldn't retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with \"--exec-timeout\" option. If it's still failing, try the smb protocol or another exec method") try: self.logger.debug(f"Removing temporary registry path: HKLM\\{self.__registry_Path}") diff --git a/cme/protocols/wmi/wmiexec_event.py b/cme/protocols/wmi/wmiexec_event.py index e5619ae5..5a0421e6 100644 --- a/cme/protocols/wmi/wmiexec_event.py +++ b/cme/protocols/wmi/wmiexec_event.py @@ -190,7 +190,7 @@ class WMIEXEC_EVENT: record = dict(command_ResultObject.getProperties()) self.__outputBuffer = base64.b64decode(record['ScriptText']['value']).decode(self.__codec, errors='replace') except Exception as e: - self.logger.fail(f'WMIEXEC-EVENT: Couldn\'t retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with "--exec-timeout" option. If it\'s still failing, try the smb protocol or another exec method') + self.logger.fail(f"WMIEXEC-EVENT: Couldn't retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with \"--exec-timeout\" option. If it's still failing, try the smb protocol or another exec method") def remove_Instance(self): if self.__retOutput: From fe517be3e6e3b5d7d578a10f4bdfad96016c9781 Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Sat, 9 Sep 2023 23:54:08 +0200 Subject: [PATCH 07/16] Fix spelling mistakes and formatting --- cme/modules/veeam_dump.py | 2 +- cme/protocols/smb/atexec.py | 4 ++-- cme/protocols/smb/mmcexec.py | 4 ++-- cme/protocols/smb/smbexec.py | 2 +- cme/protocols/wmi/wmiexec.py | 2 +- cme/protocols/wmi/wmiexec_event.py | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cme/modules/veeam_dump.py b/cme/modules/veeam_dump.py index e2092a79..c43a678b 100644 --- a/cme/modules/veeam_dump.py +++ b/cme/modules/veeam_dump.py @@ -144,7 +144,7 @@ class CMEModule: return connection.execute("powershell.exe -e {} -OutputFormat Text".format(psScipt_b64), True) def printCreds(self, context, output): - # Format ouput if returned in some XML Format + # Format output if returned in some XML Format if "CLIXML" in output: output = self.stripXmlOutput(context, output) diff --git a/cme/protocols/smb/atexec.py b/cme/protocols/smb/atexec.py index 0f539455..bd2e9139 100755 --- a/cme/protocols/smb/atexec.py +++ b/cme/protocols/smb/atexec.py @@ -203,10 +203,10 @@ class TSCH_EXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f"ATEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option \"--get-output-tries\". If it's still failing, try the wmi protocol or another exec method") + self.logger.fail(f"ATEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it's still failing, try the wmi protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : - self.logger.fail(f"ATEXEC: Get ouput failed, target has blocked ADMIN$ access (maybe command executed!)") + self.logger.fail(f"ATEXEC: Get output failed, target has blocked ADMIN$ access (maybe command executed!)") break if str(e).find("SHARING") > 0 or str(e).find("STATUS_OBJECT_NAME_NOT_FOUND") >= 0: sleep(3) diff --git a/cme/protocols/smb/mmcexec.py b/cme/protocols/smb/mmcexec.py index 0cc5637a..c6784564 100644 --- a/cme/protocols/smb/mmcexec.py +++ b/cme/protocols/smb/mmcexec.py @@ -252,10 +252,10 @@ class MMCEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f"MMCEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option \"--get-output-tries\". If it's still failing, try the wmi protocol or another exec method") + self.logger.fail(f"MMCEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it's still failing, try the wmi protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : - self.logger.fail(f"MMCEXEC: Get ouput failed, target has blocked {self.__share} access (maybe command executed!)") + self.logger.fail(f"MMCEXEC: Get output failed, target has blocked {self.__share} access (maybe command executed!)") break if str(e).find("STATUS_SHARING_VIOLATION") >= 0 or str(e).find("STATUS_OBJECT_NAME_NOT_FOUND") >= 0: # Output not finished, let's wait diff --git a/cme/protocols/smb/smbexec.py b/cme/protocols/smb/smbexec.py index b58a4f84..0816f837 100755 --- a/cme/protocols/smb/smbexec.py +++ b/cme/protocols/smb/smbexec.py @@ -173,7 +173,7 @@ class SMBEXEC: self.logger.fail(f"SMBEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option \"--get-output-tries\". If it's still failing, try the wmi protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : - self.logger.fail(f"SMBEXEC: Get ouput failed, target has blocked {self.__share} access (maybe command executed!)") + self.logger.fail(f"SMBEXEC: Get output failed, target has blocked {self.__share} access (maybe command executed!)") break if str(e).find("STATUS_SHARING_VIOLATION") >= 0 or str(e).find("STATUS_OBJECT_NAME_NOT_FOUND") >= 0: # Output not finished, let's wait diff --git a/cme/protocols/wmi/wmiexec.py b/cme/protocols/wmi/wmiexec.py index cf9cd0de..db5d74e2 100644 --- a/cme/protocols/wmi/wmiexec.py +++ b/cme/protocols/wmi/wmiexec.py @@ -104,7 +104,7 @@ class WMIEXEC: retVal = descriptor.GetStringValue(2147483650, self.__registry_Path, keyName) self.__outputBuffer = base64.b64decode(retVal.sValue).decode(self.__codec, errors='replace').rstrip('\r\n') except Exception as e: - self.logger.fail(f"WMIEXEC: Couldn't retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with \"--exec-timeout\" option. If it's still failing, try the smb protocol or another exec method") + self.logger.fail(f"WMIEXEC: Couldn't retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with '--exec-timeout' option. If it's still failing, try the smb protocol or another exec method") try: self.logger.debug(f"Removing temporary registry path: HKLM\\{self.__registry_Path}") diff --git a/cme/protocols/wmi/wmiexec_event.py b/cme/protocols/wmi/wmiexec_event.py index 5a0421e6..5519c84e 100644 --- a/cme/protocols/wmi/wmiexec_event.py +++ b/cme/protocols/wmi/wmiexec_event.py @@ -190,7 +190,7 @@ class WMIEXEC_EVENT: record = dict(command_ResultObject.getProperties()) self.__outputBuffer = base64.b64decode(record['ScriptText']['value']).decode(self.__codec, errors='replace') except Exception as e: - self.logger.fail(f"WMIEXEC-EVENT: Couldn't retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with \"--exec-timeout\" option. If it's still failing, try the smb protocol or another exec method") + self.logger.fail(f"WMIEXEC-EVENT: Couldn't retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with '--exec-timeout' option. If it's still failing, try the smb protocol or another exec method") def remove_Instance(self): if self.__retOutput: From ba51e3036c048daab83190325a481fb36d688936 Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Sun, 10 Sep 2023 12:18:55 +0200 Subject: [PATCH 08/16] Replace double quote with single quote --- cme/protocols/smb/smbexec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cme/protocols/smb/smbexec.py b/cme/protocols/smb/smbexec.py index 0816f837..260baf36 100755 --- a/cme/protocols/smb/smbexec.py +++ b/cme/protocols/smb/smbexec.py @@ -170,7 +170,7 @@ class SMBEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f"SMBEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option \"--get-output-tries\". If it's still failing, try the wmi protocol or another exec method") + self.logger.fail(f"SMBEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it's still failing, try the wmi protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : self.logger.fail(f"SMBEXEC: Get output failed, target has blocked {self.__share} access (maybe command executed!)") From 47199d6d79e8c7ea73be2075524171d7672c8a9b Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Sun, 10 Sep 2023 12:33:05 +0200 Subject: [PATCH 09/16] Enable using any share with atexec --- cme/protocols/smb.py | 5 +++-- cme/protocols/smb/atexec.py | 24 +++++++++++++----------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/cme/protocols/smb.py b/cme/protocols/smb.py index a9cc2265..c1cfd162 100755 --- a/cme/protocols/smb.py +++ b/cme/protocols/smb.py @@ -734,8 +734,9 @@ class smb(connection): self.kdcHost, self.hash, self.logger, - self.args.get_output_tries - ) # self.args.share) + self.args.get_output_tries, + self.args.share + ) self.logger.info("Executed command via atexec") break except: diff --git a/cme/protocols/smb/atexec.py b/cme/protocols/smb/atexec.py index bd2e9139..cc783675 100755 --- a/cme/protocols/smb/atexec.py +++ b/cme/protocols/smb/atexec.py @@ -38,6 +38,8 @@ class TSCH_EXEC: self.__doKerberos = doKerberos self.__kdcHost = kdcHost self.__tries = tries + self.__output = None + self.__share = share self.logger = logger if hashes is not None: @@ -73,7 +75,7 @@ class TSCH_EXEC: def output_callback(self, data): self.__outputBuffer = data - def gen_xml(self, command, tmpFileName, fileless=False): + def gen_xml(self, command, fileless=False): xml = """ @@ -114,11 +116,12 @@ class TSCH_EXEC: cmd.exe """ if self.__retOutput: + self.__output = "\\Windows\\Temp\\" + gen_random_string(6) if fileless: local_ip = self.__rpctransport.get_socket().getsockname()[0] - argument_xml = f" /C {command} > \\\\{local_ip}\\{self.__share_name}\\{tmpFileName} 2>&1" + argument_xml = f" /C {command} > \\\\{local_ip}\\{self.__share_name}\\{self.__output} 2>&1" else: - argument_xml = f" /C {command} > %windir%\\Temp\\{tmpFileName} 2>&1" + argument_xml = f" /C {command} > {self.__output} 2>&1" elif self.__retOutput is False: argument_xml = f" /C {command}" @@ -143,9 +146,8 @@ class TSCH_EXEC: # dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY) tmpName = gen_random_string(8) - tmpFileName = tmpName + ".tmp" - xml = self.gen_xml(command, tmpFileName, fileless) + xml = self.gen_xml(command, fileless) self.logger.info(f"Task XML: {xml}") taskCreated = False @@ -187,7 +189,7 @@ class TSCH_EXEC: if fileless: while True: try: - with open(os.path.join("/tmp", "cme_hosted", tmpFileName), "r") as output: + with open(os.path.join("/tmp", "cme_hosted", self.__output), "r") as output: self.output_callback(output.read()) break except IOError: @@ -198,15 +200,15 @@ class TSCH_EXEC: tries = 1 while True: try: - self.logger.info(f"Attempting to read ADMIN$\\Temp\\{tmpFileName}") - smbConnection.getFile("ADMIN$", f"Temp\\{tmpFileName}", self.output_callback) + self.logger.info(f"Attempting to read {self.__share}\\{self.__output}") + smbConnection.getFile(self.__share, self.__output, self.output_callback) break except Exception as e: if tries >= self.__tries: self.logger.fail(f"ATEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it's still failing, try the wmi protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : - self.logger.fail(f"ATEXEC: Get output failed, target has blocked ADMIN$ access (maybe command executed!)") + self.logger.fail(f"ATEXEC: Get output failed, target has blocked {self.__share} access (maybe command executed!)") break if str(e).find("SHARING") > 0 or str(e).find("STATUS_OBJECT_NAME_NOT_FOUND") >= 0: sleep(3) @@ -215,7 +217,7 @@ class TSCH_EXEC: self.logger.debug(str(e)) if self.__outputBuffer: - self.logger.debug(f"Deleting file ADMIN$\\Temp\\{tmpFileName}") - smbConnection.deleteFile("ADMIN$", f"Temp\\{tmpFileName}") + self.logger.debug(f"Deleting file {self.__share}\\{self.__output}") + smbConnection.deleteFile(self.__share, self.__output) dce.disconnect() From 604099f1b0e2dc8dcbceafe654b253f59021e81f Mon Sep 17 00:00:00 2001 From: XiaoliChan <2209553467@qq.com> Date: Mon, 11 Sep 2023 15:46:38 +0800 Subject: [PATCH 10/16] [winrm] less ugly if condition Signed-off-by: XiaoliChan <2209553467@qq.com> --- cme/protocols/winrm.py | 66 ++++++++++-------------------------------- 1 file changed, 16 insertions(+), 50 deletions(-) diff --git a/cme/protocols/winrm.py b/cme/protocols/winrm.py index 1c460bc3..5fea95e3 100644 --- a/cme/protocols/winrm.py +++ b/cme/protocols/winrm.py @@ -231,31 +231,14 @@ class winrm(connection): self.password = password self.username = username self.domain = domain - if self.args.ssl and self.args.ignore_ssl_cert: - self.conn = Client( - self.host, - auth="ntlm", - username=f"{domain}\\{self.username}", - password=self.password, - ssl=True, - cert_validation=False, - ) - elif self.args.ssl: - self.conn = Client( - self.host, - auth="ntlm", - username=f"{domain}\\{self.username}", - password=self.password, - ssl=True, - ) - else: - self.conn = Client( - self.host, - auth="ntlm", - username=f"{domain}\\{self.username}", - password=self.password, - ssl=False, - ) + self.conn = Client( + self.host, + auth="ntlm", + username=f"{domain}\\{self.username}", + password=self.password, + ssl=True if self.args.ssl else False, + cert_validation=False if self.args.ignore_ssl_cert else True, + ) # TO DO: right now we're just running the hostname command to make the winrm library auth to the server # we could just authenticate without running a command :) (probably) @@ -308,31 +291,14 @@ class winrm(connection): nthash = self.hash self.domain = domain - if self.args.ssl and self.args.ignore_ssl_cert: - self.conn = Client( - self.host, - auth="ntlm", - username=f"{self.domain}\\{self.username}", - password=lmhash + nthash, - ssl=True, - cert_validation=False, - ) - elif self.args.ssl: - self.conn = Client( - self.host, - auth="ntlm", - username=f"{self.domain}\\{self.username}", - password=lmhash + nthash, - ssl=True, - ) - else: - self.conn = Client( - self.host, - auth="ntlm", - username=f"{self.domain}\\{self.username}", - password=lmhash + nthash, - ssl=False, - ) + self.conn = Client( + self.host, + auth="ntlm", + username=f"{self.domain}\\{self.username}", + password=lmhash + nthash, + ssl=True if self.args.ssl else False, + cert_validation=False if self.args.ignore_ssl_cert else True, + ) # TO DO: right now we're just running the hostname command to make the winrm library auth to the server # we could just authenticate without running a command :) (probably) From 9805fe968e297bffc29465ce9a875eb2076c7eae Mon Sep 17 00:00:00 2001 From: Marshall Hallenbeck Date: Tue, 12 Sep 2023 16:19:53 -0400 Subject: [PATCH 11/16] Update README.md Initial README changes for NetExec/nxc rebrand Signed-off-by: Marshall Hallenbeck --- README.md | 43 +++++++++++-------------------------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index becafb58..a009a1fe 100755 --- a/README.md +++ b/README.md @@ -1,58 +1,37 @@ ![Supported Python versions](https://img.shields.io/badge/python-3.7+-blue.svg) -[![Twitter](https://img.shields.io/twitter/follow/byt3bl33d3r?label=byt3bl33d3r&style=social)](https://twitter.com/intent/follow?screen_name=byt3bl33d3r) [![Twitter](https://img.shields.io/twitter/follow/mpgn_x64?label=mpgn_x64&style=social)](https://twitter.com/intent/follow?screen_name=mpgn_x64) [![Twitter](https://img.shields.io/twitter/follow/al3xn3ff?label=al3x_n3ff&style=social)](https://twitter.com/intent/follow?screen_name=al3x_n3ff) [![Twitter](https://img.shields.io/twitter/follow/_zblurx?label=_zblurx&style=social)](https://twitter.com/intent/follow?screen_name=_zblurx) [![Twitter](https://img.shields.io/twitter/follow/MJHallenbeck?label=MJHallenbeck&style=social)](https://twitter.com/intent/follow?screen_name=MJHallenbeck) -🚩 This is the open source repository of CrackMapExec maintained by a community of passionate people -# CrackMapExec +🚩 This is the open source repository of NetExec maintained by a community of passionate people +# NetExec

- cme +

+You are on the **latest up-to-date** repository of the project NetExec (nxc) ! 🎉 -This project was initially created in 2015 by **@byt3bl33d3r**. In 2019 **@mpgn_x64** started maintaining the project. Five years and a lot of additions later, he retired from maintaining the project. Like many other contributer we (NeffIsBack, Marshall-Hallenbeck and zblurx) started working on new features, bugfixes and helped maintaining CME. With the end of mpgn's maintainer role, we decided to maintain the project together as an full open source project. - -You are on the **latest up-to-date** repository of the project CrackMapExec ! 🎉 - -- 🚧 If you want to report a problem, open un [Issue](https://github.com/Pennyw0rth/CrackMapExec/issues) -- 🔀 If you want to contribute, open a [Pull Request](https://github.com/Pennyw0rth/CrackMapExec/pulls) -- 💬 If you want to discuss, open a [Discussion](https://github.com/Pennyw0rth/CrackMapExec/discussions) +- 🚧 If you want to report a problem, open un [Issue](https://github.com/Pennyw0rth/NetExec/issues) +- 🔀 If you want to contribute, open a [Pull Request](https://github.com/Pennyw0rth/NetExec/pulls) +- 💬 If you want to discuss, open a [Discussion](https://github.com/Pennyw0rth/NetExec/discussions) # Acknowledgments -**(These are the people who did the hard stuff)** +All the hard work and development over the years from everyone in the CrackMapExec project. -This project was originally inspired by: -- [CredCrack](https://github.com/gojhonny/CredCrack) -- [smbexec](https://github.com/pentestgeek/smbexec) -- [smbmap](https://github.com/ShawnDEvans/smbmap) - -Unintentional contributors: - -- The [Empire](https://github.com/PowerShellEmpire/Empire) project -- @T-S-A's [smbspider](https://github.com/T-S-A/smbspider) script -- @ConsciousHacker's partial Python port of Invoke-obfuscation from the [GreatSCT](https://github.com/GreatSCT/GreatSCT) project # Documentation, Tutorials, Examples -See the project's [wiki](https://www.crackmapexec.wiki/) for documentation and usage examples +See the project's wiki (in development) for documentation and usage examples # Installation -Please see the installation instructions on the [official wiki](https://www.crackmapexec.wiki/getting-started/installation) +Please see the installation instructions on the wiki (in development) # Code Contributors +Awesome code contributors of NetExec: -Awesome code contributors of CME: - -[![](https://github.com/mpgn.png?size=50)](https://github.com/mpgn) [![](https://github.com/Marshall-Hallenbeck.png?size=50)](https://github.com/Marshall-Hallenbeck) [![](https://github.com/zblurx.png?size=50)](https://github.com/zblurx) [![](https://github.com/NeffIsBack.png?size=50)](https://github.com/NeffIsBack) [![](https://github.com/Hackndo.png?size=50)](https://github.com/Hackndo) -[![](https://github.com/nurfed1?size=50)](https://github.com/nurfed1) - - -# To do -- ~~0wn everything~~ From ef552ac97a9dcec470387d839b586d4243278ece Mon Sep 17 00:00:00 2001 From: Marshall Hallenbeck Date: Tue, 12 Sep 2023 16:26:37 -0400 Subject: [PATCH 12/16] Fix links/shoutout Signed-off-by: Marshall Hallenbeck --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a009a1fe..811d0f76 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ ![Supported Python versions](https://img.shields.io/badge/python-3.7+-blue.svg) -[![Twitter](https://img.shields.io/twitter/follow/mpgn_x64?label=mpgn_x64&style=social)](https://twitter.com/intent/follow?screen_name=mpgn_x64) [![Twitter](https://img.shields.io/twitter/follow/al3xn3ff?label=al3x_n3ff&style=social)](https://twitter.com/intent/follow?screen_name=al3x_n3ff) [![Twitter](https://img.shields.io/twitter/follow/_zblurx?label=_zblurx&style=social)](https://twitter.com/intent/follow?screen_name=_zblurx) [![Twitter](https://img.shields.io/twitter/follow/MJHallenbeck?label=MJHallenbeck&style=social)](https://twitter.com/intent/follow?screen_name=MJHallenbeck) @@ -31,6 +30,7 @@ Please see the installation instructions on the wiki (in development) # Code Contributors Awesome code contributors of NetExec: +[![](https://github.com/mpgn.png?size=50)](https://github.com/mpgn) [![](https://github.com/Marshall-Hallenbeck.png?size=50)](https://github.com/Marshall-Hallenbeck) [![](https://github.com/zblurx.png?size=50)](https://github.com/zblurx) [![](https://github.com/NeffIsBack.png?size=50)](https://github.com/NeffIsBack) From 287525fef31e0bde9f11712b04fede763a8738ed Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Wed, 13 Sep 2023 00:03:50 +0200 Subject: [PATCH 13/16] Add name description --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 811d0f76..3dacb6e5 100755 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ 🚩 This is the open source repository of NetExec maintained by a community of passionate people -# NetExec +# NetExec - The Network Execution Tool

From 0b4a6ffdc10224fdd0695f0e71819110b25c2f4f Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Wed, 13 Sep 2023 00:24:04 +0200 Subject: [PATCH 14/16] Add CODEOWNERS file for review approval --- .github/CODEOWNERS | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..423f56d5 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +########################################## +# code ownership +########################################## + +# default ownership: +* @zblurx @Marshall-Hallenbeck @NeffIsBack \ No newline at end of file From 78f1dd41362fcf5b69d11dbc2dea797613821ded Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Thu, 14 Sep 2023 00:18:59 +0200 Subject: [PATCH 15/16] Fix cli to only run building binaries manually and test on review submit --- .github/workflows/crackmapexec-test.yml | 7 ++----- .github/workflows/crackmapexec.yml | 7 +------ 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/.github/workflows/crackmapexec-test.yml b/.github/workflows/crackmapexec-test.yml index bc6fcb63..3769e312 100644 --- a/.github/workflows/crackmapexec-test.yml +++ b/.github/workflows/crackmapexec-test.yml @@ -1,11 +1,8 @@ name: CrackMapExec Tests on: - workflow_dispatch: - push: - branches: [ master ] - pull_request: - branches: [ master ] + pull_request_review: + types: [submitted] jobs: build: diff --git a/.github/workflows/crackmapexec.yml b/.github/workflows/crackmapexec.yml index e1ab04d1..c8067330 100644 --- a/.github/workflows/crackmapexec.yml +++ b/.github/workflows/crackmapexec.yml @@ -1,12 +1,7 @@ -name: CrackMapExec Tests & Build +name: CrackMapExec Build Binaries on: workflow_dispatch: - branches: [ main ] - push: - branches: [ main ] - pull_request: - branches: [ main ] jobs: build: From 473c4b1952a4f1dcf66d00946e34055c6c79e426 Mon Sep 17 00:00:00 2001 From: Alex <61382599+NeffIsBack@users.noreply.github.com> Date: Thu, 14 Sep 2023 00:29:55 +0200 Subject: [PATCH 16/16] Improve feedback text for the user --- cme/protocols/smb/atexec.py | 22 +++++++++++----------- cme/protocols/smb/mmcexec.py | 4 ++-- cme/protocols/smb/smbexec.py | 4 ++-- cme/protocols/smb/wmiexec.py | 2 +- cme/protocols/wmi/wmiexec.py | 2 +- cme/protocols/wmi/wmiexec_event.py | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/cme/protocols/smb/atexec.py b/cme/protocols/smb/atexec.py index cc783675..ae8273d2 100755 --- a/cme/protocols/smb/atexec.py +++ b/cme/protocols/smb/atexec.py @@ -38,7 +38,7 @@ class TSCH_EXEC: self.__doKerberos = doKerberos self.__kdcHost = kdcHost self.__tries = tries - self.__output = None + self.__output_filename = None self.__share = share self.logger = logger @@ -116,12 +116,12 @@ class TSCH_EXEC: cmd.exe """ if self.__retOutput: - self.__output = "\\Windows\\Temp\\" + gen_random_string(6) + self.__output_filename = "\\Windows\\Temp\\" + gen_random_string(6) if fileless: local_ip = self.__rpctransport.get_socket().getsockname()[0] - argument_xml = f" /C {command} > \\\\{local_ip}\\{self.__share_name}\\{self.__output} 2>&1" + argument_xml = f" /C {command} > \\\\{local_ip}\\{self.__share_name}\\{self.__output_filename} 2>&1" else: - argument_xml = f" /C {command} > {self.__output} 2>&1" + argument_xml = f" /C {command} > {self.__output_filename} 2>&1" elif self.__retOutput is False: argument_xml = f" /C {command}" @@ -189,7 +189,7 @@ class TSCH_EXEC: if fileless: while True: try: - with open(os.path.join("/tmp", "cme_hosted", self.__output), "r") as output: + with open(os.path.join("/tmp", "cme_hosted", self.__output_filename), "r") as output: self.output_callback(output.read()) break except IOError: @@ -200,15 +200,15 @@ class TSCH_EXEC: tries = 1 while True: try: - self.logger.info(f"Attempting to read {self.__share}\\{self.__output}") - smbConnection.getFile(self.__share, self.__output, self.output_callback) + self.logger.info(f"Attempting to read {self.__share}\\{self.__output_filename}") + smbConnection.getFile(self.__share, self.__output_filename, self.output_callback) break except Exception as e: if tries >= self.__tries: - self.logger.fail(f"ATEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it's still failing, try the wmi protocol or another exec method") + self.logger.fail(f"ATEXEC: Could not retrieve output file, it may have been detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it is still failing, try the 'wmi' protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : - self.logger.fail(f"ATEXEC: Get output failed, target has blocked {self.__share} access (maybe command executed!)") + self.logger.fail(f"ATEXEC: Getting the output file failed - target has blocked access to the share: {self.__share} (but the command may have executed!)") break if str(e).find("SHARING") > 0 or str(e).find("STATUS_OBJECT_NAME_NOT_FOUND") >= 0: sleep(3) @@ -217,7 +217,7 @@ class TSCH_EXEC: self.logger.debug(str(e)) if self.__outputBuffer: - self.logger.debug(f"Deleting file {self.__share}\\{self.__output}") - smbConnection.deleteFile(self.__share, self.__output) + self.logger.debug(f"Deleting file {self.__share}\\{self.__output_filename}") + smbConnection.deleteFile(self.__share, self.__output_filename) dce.disconnect() diff --git a/cme/protocols/smb/mmcexec.py b/cme/protocols/smb/mmcexec.py index c6784564..44dd802f 100644 --- a/cme/protocols/smb/mmcexec.py +++ b/cme/protocols/smb/mmcexec.py @@ -252,10 +252,10 @@ class MMCEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f"MMCEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it's still failing, try the wmi protocol or another exec method") + self.logger.fail(f"MMCEXEC: Could not retrieve output file, it may have been detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it is still failing, try the 'wmi' protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : - self.logger.fail(f"MMCEXEC: Get output failed, target has blocked {self.__share} access (maybe command executed!)") + self.logger.fail(f"MMCEXEC: Getting the output file failed - target has blocked access to the share: {self.__share} (but the command may have executed!)") break if str(e).find("STATUS_SHARING_VIOLATION") >= 0 or str(e).find("STATUS_OBJECT_NAME_NOT_FOUND") >= 0: # Output not finished, let's wait diff --git a/cme/protocols/smb/smbexec.py b/cme/protocols/smb/smbexec.py index 260baf36..73c8a765 100755 --- a/cme/protocols/smb/smbexec.py +++ b/cme/protocols/smb/smbexec.py @@ -170,10 +170,10 @@ class SMBEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f"SMBEXEC: Couldn't retrieve output file, maybe got detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it's still failing, try the wmi protocol or another exec method") + self.logger.fail(f"SMBEXEC: Could not retrieve output file, it may have been detected by AV. Please increase the number of tries with the option '--get-output-tries'. If it is still failing, try the 'wmi' protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : - self.logger.fail(f"SMBEXEC: Get output failed, target has blocked {self.__share} access (maybe command executed!)") + self.logger.fail(f"SMBEXEC: Getting the output file failed - target has blocked access to the share: {self.__share} (but the command may have executed!)") break if str(e).find("STATUS_SHARING_VIOLATION") >= 0 or str(e).find("STATUS_OBJECT_NAME_NOT_FOUND") >= 0: # Output not finished, let's wait diff --git a/cme/protocols/smb/wmiexec.py b/cme/protocols/smb/wmiexec.py index 45e65495..6046df34 100755 --- a/cme/protocols/smb/wmiexec.py +++ b/cme/protocols/smb/wmiexec.py @@ -166,7 +166,7 @@ class WMIEXEC: break except Exception as e: if tries >= self.__tries: - self.logger.fail(f"WMIEXEC: Couldn't retrieve output file, maybe got detected by AV. Try the wmi protocol or another exec method") + self.logger.fail(f"WMIEXEC: Could not retrieve output file, it may have been detected by AV. If it is still failing, try the 'wmi' protocol or another exec method") break if str(e).find("STATUS_BAD_NETWORK_NAME") >0 : self.logger.fail(f"SMB connection: target has blocked {self.__share} access (maybe command executed!)") diff --git a/cme/protocols/wmi/wmiexec.py b/cme/protocols/wmi/wmiexec.py index db5d74e2..e32594dc 100644 --- a/cme/protocols/wmi/wmiexec.py +++ b/cme/protocols/wmi/wmiexec.py @@ -104,7 +104,7 @@ class WMIEXEC: retVal = descriptor.GetStringValue(2147483650, self.__registry_Path, keyName) self.__outputBuffer = base64.b64decode(retVal.sValue).decode(self.__codec, errors='replace').rstrip('\r\n') except Exception as e: - self.logger.fail(f"WMIEXEC: Couldn't retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with '--exec-timeout' option. If it's still failing, try the smb protocol or another exec method") + self.logger.fail(f"WMIEXEC: Could not retrieve output file, it may have been detected by AV. Please try increasing the timeout with the '--exec-timeout' option. If it is still failing, try the 'smb' protocol or another exec method") try: self.logger.debug(f"Removing temporary registry path: HKLM\\{self.__registry_Path}") diff --git a/cme/protocols/wmi/wmiexec_event.py b/cme/protocols/wmi/wmiexec_event.py index 5519c84e..3a7f1e3f 100644 --- a/cme/protocols/wmi/wmiexec_event.py +++ b/cme/protocols/wmi/wmiexec_event.py @@ -190,7 +190,7 @@ class WMIEXEC_EVENT: record = dict(command_ResultObject.getProperties()) self.__outputBuffer = base64.b64decode(record['ScriptText']['value']).decode(self.__codec, errors='replace') except Exception as e: - self.logger.fail(f"WMIEXEC-EVENT: Couldn't retrieve output file. Either command timed out or got detected by AV. Try increasing the timeout with '--exec-timeout' option. If it's still failing, try the smb protocol or another exec method") + self.logger.fail(f"WMIEXEC-EVENT: Could not retrieve output file, it may have been detected by AV. Please try increasing the timeout with the '--exec-timeout' option. If it is still failing, try the 'smb' protocol or another exec method") def remove_Instance(self): if self.__retOutput: