Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Make some text more precise #7

Merged
merged 9 commits into from
Sep 14, 2023
3 changes: 2 additions & 1 deletion cme/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)}
Expand Down
2 changes: 1 addition & 1 deletion cme/modules/veeam_dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def executePsPostgreSql(self, context, connection, PostgreSqlExec, PostgresUserF
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)

Expand Down
5 changes: 3 additions & 2 deletions cme/protocols/smb.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,8 +734,9 @@ def execute(self, payload=None, get_output=False, methods=None):
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:
Expand Down
26 changes: 14 additions & 12 deletions cme/protocols/smb/atexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def __init__(
self.__doKerberos = doKerberos
self.__kdcHost = kdcHost
self.__tries = tries
self.__output = None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably rename this "__output_filename"

self.__share = share
self.logger = logger

if hashes is not None:
Expand Down Expand Up @@ -73,7 +75,7 @@ def execute(self, command, output=False):
def output_callback(self, data):
self.__outputBuffer = data

def gen_xml(self, command, tmpFileName, fileless=False):
def gen_xml(self, command, fileless=False):
xml = """<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<Triggers>
Expand Down Expand Up @@ -114,11 +116,12 @@ def gen_xml(self, command, tmpFileName, fileless=False):
<Command>cmd.exe</Command>
"""
if self.__retOutput:
self.__output = "\\Windows\\Temp\\" + gen_random_string(6)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we want the folder to be a variable, so users can pass in their own temp location?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be another feature. Probably great to add but should be done seperatly imo

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we want the folder to be a variable, so users can pass in their own temp location?

Yes, as @NeffIsBack said, this is another feature

if fileless:
local_ip = self.__rpctransport.get_socket().getsockname()[0]
argument_xml = f" <Arguments>/C {command} &gt; \\\\{local_ip}\\{self.__share_name}\\{tmpFileName} 2&gt;&amp;1</Arguments>"
argument_xml = f" <Arguments>/C {command} &gt; \\\\{local_ip}\\{self.__share_name}\\{self.__output} 2&gt;&amp;1</Arguments>"
else:
argument_xml = f" <Arguments>/C {command} &gt; %windir%\\Temp\\{tmpFileName} 2&gt;&amp;1</Arguments>"
argument_xml = f" <Arguments>/C {command} &gt; {self.__output} 2&gt;&amp;1</Arguments>"

elif self.__retOutput is False:
argument_xml = f" <Arguments>/C {command}</Arguments>"
Expand All @@ -143,9 +146,8 @@ def execute_handler(self, command, fileless=False):
# 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
Expand Down Expand Up @@ -187,7 +189,7 @@ def execute_handler(self, command, fileless=False):
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:
Expand All @@ -198,15 +200,15 @@ def execute_handler(self, command, fileless=False):
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: 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")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ouput 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!)")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Expand All @@ -215,7 +217,7 @@ def execute_handler(self, command, fileless=False):
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()
4 changes: 2 additions & 2 deletions cme/protocols/smb/mmcexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,10 @@ def get_output_remote(self):
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")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 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!)")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Expand Down
2 changes: 1 addition & 1 deletion cme/protocols/smb/proto_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
4 changes: 2 additions & 2 deletions cme/protocols/smb/smbexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,10 @@ def get_output_remote(self):
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")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 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!)")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Expand Down
4 changes: 2 additions & 2 deletions cme/protocols/smb/wmiexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ def get_output_remote(self):
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!)')
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)
Expand Down
6 changes: 3 additions & 3 deletions cme/protocols/wmi.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ def execute(self, command=None, get_output=False):
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

Expand All @@ -441,11 +441,11 @@ def execute(self, command=None, get_output=False):
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()
Expand Down
2 changes: 1 addition & 1 deletion cme/protocols/wmi/proto_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, "
Expand Down
10 changes: 5 additions & 5 deletions cme/protocols/wmi/wmiexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
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
Expand All @@ -45,7 +45,7 @@ def __init__(self, host, username, password, domain, lmhash, nthash, doKerberos,
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
Expand Down Expand Up @@ -91,8 +91,8 @@ def execute_WithOutput(self, command):
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)

Expand All @@ -104,7 +104,7 @@ def queryRegistry(self, keyName):
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}")
Expand Down
10 changes: 5 additions & 5 deletions cme/protocols/wmi/wmiexec_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
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
Expand All @@ -51,7 +51,7 @@ def __init__(self, host, username, password, domain, lmhash, nthash, doKerberos,
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())}"
Expand Down Expand Up @@ -84,8 +84,8 @@ def execute_handler(self, command):
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()
Expand Down Expand Up @@ -190,7 +190,7 @@ def get_CommandResult(self):
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:
Expand Down