Merge branch 'main' into wmi-improv-admin-check
commit
e3837d986a
|
@ -0,0 +1,6 @@
|
|||
##########################################
|
||||
# code ownership
|
||||
##########################################
|
||||
|
||||
# default ownership:
|
||||
* @zblurx @Marshall-Hallenbeck @NeffIsBack
|
|
@ -1,11 +1,8 @@
|
|||
name: CrackMapExec Tests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
|
@ -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:
|
||||
|
|
43
README.md
43
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 - The Network Execution Tool
|
||||
|
||||
<p align="center">
|
||||
<img src="https://cloud.githubusercontent.com/assets/5151193/17577511/d312ceb4-5f3b-11e6-8de5-8822246289fd.jpg" alt="cme"/>
|
||||
<!-- placeholder for nxc logo-->
|
||||
</p>
|
||||
|
||||
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 CME:
|
||||
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)
|
||||
[![](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~~
|
||||
|
|
|
@ -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)}
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -38,6 +38,8 @@ class TSCH_EXEC:
|
|||
self.__doKerberos = doKerberos
|
||||
self.__kdcHost = kdcHost
|
||||
self.__tries = tries
|
||||
self.__output_filename = 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 = """<?xml version="1.0" encoding="UTF-16"?>
|
||||
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
||||
<Triggers>
|
||||
|
@ -114,11 +116,12 @@ class TSCH_EXEC:
|
|||
<Command>cmd.exe</Command>
|
||||
"""
|
||||
if self.__retOutput:
|
||||
self.__output_filename = "\\Windows\\Temp\\" + gen_random_string(6)
|
||||
if fileless:
|
||||
local_ip = self.__rpctransport.get_socket().getsockname()[0]
|
||||
argument_xml = f" <Arguments>/C {command} > \\\\{local_ip}\\{self.__share_name}\\{tmpFileName} 2>&1</Arguments>"
|
||||
argument_xml = f" <Arguments>/C {command} > \\\\{local_ip}\\{self.__share_name}\\{self.__output_filename} 2>&1</Arguments>"
|
||||
else:
|
||||
argument_xml = f" <Arguments>/C {command} > %windir%\\Temp\\{tmpFileName} 2>&1</Arguments>"
|
||||
argument_xml = f" <Arguments>/C {command} > {self.__output_filename} 2>&1</Arguments>"
|
||||
|
||||
elif self.__retOutput is False:
|
||||
argument_xml = f" <Arguments>/C {command}</Arguments>"
|
||||
|
@ -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_filename), "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_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: 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: 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: 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)
|
||||
|
@ -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_filename}")
|
||||
smbConnection.deleteFile(self.__share, self.__output_filename)
|
||||
|
||||
dce.disconnect()
|
||||
|
|
|
@ -252,10 +252,10 @@ 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: 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: 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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -170,10 +170,10 @@ 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: 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: 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
|
||||
|
|
|
@ -166,10 +166,10 @@ 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: 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!)')
|
||||
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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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, "
|
||||
|
|
|
@ -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: 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}")
|
||||
|
|
|
@ -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: 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:
|
||||
|
|
Loading…
Reference in New Issue