Skip to content

Commit

Permalink
Merge branch 'main' into zerologon-Shot
Browse files Browse the repository at this point in the history
  • Loading branch information
XiaoliChan authored Sep 17, 2023
2 parents 2fd4cca + 04a6ba7 commit e7af722
Show file tree
Hide file tree
Showing 19 changed files with 87 additions and 135 deletions.
6 changes: 6 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
##########################################
# code ownership
##########################################

# default ownership:
* @zblurx @Marshall-Hallenbeck @NeffIsBack
7 changes: 2 additions & 5 deletions .github/workflows/crackmapexec-test.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
name: CrackMapExec Tests

on:
workflow_dispatch:
push:
branches: [ master ]
pull_request:
branches: [ master ]
pull_request_review:
types: [submitted]

jobs:
build:
Expand Down
7 changes: 1 addition & 6 deletions .github/workflows/crackmapexec.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
43 changes: 11 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)**

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:
All the hard work and development over the years from everyone in the CrackMapExec project.

- 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~~
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
6 changes: 6 additions & 0 deletions cme/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,12 @@ def parse_credentials(self):
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):
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_filename = None
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_filename = "\\Windows\\Temp\\" + gen_random_string(6)
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_filename} 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_filename} 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_filename), "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_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)
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_filename}")
smbConnection.deleteFile(self.__share, self.__output_filename)

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: 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
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: 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
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: 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)
Expand Down
66 changes: 16 additions & 50 deletions cme/protocols/winrm.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,31 +231,14 @@ def plaintext_login(self, domain, username, password):
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)
Expand Down Expand Up @@ -308,31 +291,14 @@ def hash_login(self, domain, username, ntlm_hash):
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)
Expand Down
Loading

0 comments on commit e7af722

Please sign in to comment.