Skip to content

Commit 1779e84

Browse files
authored
Merge branch 'main' into module_ggp_privs
2 parents 4693d21 + 5da5bf1 commit 1779e84

151 files changed

Lines changed: 8063 additions & 3855 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
11
## Description
22

33
Please include a summary of the change and which issue is fixed, or what the enhancement does.
4-
Please also include relevant motivation and context.
54
List any dependencies that are required for this change.
65

76
## Type of change
8-
Please delete options that are not relevant.
97
- [ ] Bug fix (non-breaking change which fixes an issue)
108
- [ ] New feature (non-breaking change which adds functionality)
119
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
1210
- [ ] This change requires a documentation update
1311
- [ ] This requires a third party update (such as Impacket, Dploot, lsassy, etc)
1412

15-
## How Has This Been Tested?
16-
Please describe the tests that you ran to verify your changes (e2e, single commands, etc)
17-
Please also list any relevant details for your test configuration, such as your locally running machine Python version & OS, as well as the target(s) you tested against, including software versions
18-
19-
If you are using poetry, you can easily run tests via:
20-
`poetry run python tests/e2e_tests.py -t $TARGET -u $USER -p $PASSWORD`
21-
There are additional options like `--errors` to display ALL errors (some may not be failures), `--poetry` (output will include the poetry run prepended), `--line-num $START-$END $SINGLE` for only running a subset
13+
## Setup guide for the review
14+
Please provide guidance on what setup is needed to test the introduced changes, such as your locally running machine Python version & OS, as well as the target(s) you tested against, including software versions.
15+
In particular:
16+
- Bug Fix: Please provide a short description on how to trigger the bug, to make the bug reproducable for the reviewer.
17+
- Added Feature/Enhancement: Please specify what setup is needed in order to test the changes. E.g. is additional software needed? GPO changes required? Specific registry settings that need to be changed?
2218

2319
## Screenshots (if appropriate):
2420
Screenshots are always nice to have and can give a visual representation of the change.
@@ -29,8 +25,7 @@ If appropriate include before and after screenshot(s) to show which results are
2925
- [ ] I have ran Ruff against my changes (via poetry: `poetry run python -m ruff check . --preview`, use `--fix` to automatically fix what it can)
3026
- [ ] I have added or updated the tests/e2e_commands.txt file if necessary
3127
- [ ] New and existing e2e tests pass locally with my changes
32-
- [ ] My code follows the style guidelines of this project (should be covered by Ruff above)
33-
- [ ] If reliant on third party dependencies, such as Impacket, dploot, lsassy, etc, I have linked the relevant PRs in those projects
28+
- [ ] If reliant on changes of third party dependencies, such as Impacket, dploot, lsassy, etc, I have linked the relevant PRs in those projects
3429
- [ ] I have performed a self-review of my own code
3530
- [ ] I have commented my code, particularly in hard-to-understand areas
3631
- [ ] I have made corresponding changes to the documentation (PR here: https://github.com/Pennyw0rth/NetExec-Wiki)

.github/workflows/build-binaries.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
strategy:
1111
matrix:
1212
os: [ubuntu-latest, macOS-latest, windows-latest]
13-
python-version: ["3.12"]
13+
python-version: ["3.13"]
1414
#python-version: ["3.8", "3.9", "3.10", "3.11"] # for binary builds we only need one version
1515
steps:
1616
- uses: actions/checkout@v4
@@ -20,7 +20,7 @@ jobs:
2020
python-version: ${{ matrix.python-version }}
2121
- name: Build Native Binary
2222
run: |
23-
pip install pyinstaller
23+
pip install pyinstaller pillow
2424
pip install .
2525
pyinstaller netexec.spec
2626
- name: Upload Windows Binary

.github/workflows/build-zipapps.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
strategy:
1111
matrix:
1212
os: [ubuntu-latest, macOS-latest, windows-latest]
13-
python-version: ["3.10", "3.11", "3.12"]
13+
python-version: ["3.10", "3.11", "3.12", "3.13"]
1414
steps:
1515
- uses: actions/checkout@v4
1616
- name: NetExec set up python on ${{ matrix.os }}

.github/workflows/lint.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ name: Lint Python code with ruff
44
on:
55
push:
66
workflow_dispatch:
7+
pull_request_review:
8+
types: [submitted]
79

810
jobs:
911
lint:
1012
runs-on: ubuntu-latest
1113
if:
12-
github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
14+
github.event_name == 'push' || github.event.review.state == 'APPROVED' || github.event_name == 'workflow_dispatch'
1315

1416
steps:
1517
- uses: actions/checkout@v4
@@ -19,7 +21,7 @@ jobs:
1921
- name: Set up Python
2022
uses: actions/setup-python@v5
2123
with:
22-
python-version: 3.12
24+
python-version: 3.13
2325
cache: poetry
2426
cache-dependency-path: poetry.lock
2527
- name: Install dependencies with dev group

.github/workflows/test.yml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,20 @@ on:
88
jobs:
99
build:
1010
name: Test for Py${{ matrix.python-version }}
11-
if: github.event.review.state == 'APPROVED'
11+
if: github.event.review.state == 'APPROVED' || github.event_name == 'workflow_dispatch'
1212
runs-on: ${{ matrix.os }}
1313
strategy:
1414
max-parallel: 5
1515
matrix:
1616
os: [ubuntu-latest]
17-
python-version: ["3.10", "3.11", "3.12"]
17+
python-version: ["3.10", "3.11", "3.12", "3.13"]
1818
steps:
1919
- uses: actions/checkout@v4
2020
- name: Install poetry
2121
run: |
2222
pipx install poetry
23+
poetry --version
24+
poetry env info
2325
- name: NetExec set up python ${{ matrix.python-version }} on ${{ matrix.os }}
2426
uses: actions/setup-python@v5
2527
with:
@@ -29,11 +31,6 @@ jobs:
2931
- name: Install with pipx
3032
run: |
3133
pipx install . --python python${{ matrix.python-version }}
32-
- name: Install poetry
33-
run: |
34-
pipx install poetry --python python${{ matrix.python-version }}
35-
poetry --version
36-
poetry env info
3734
- name: Install libraries with dev group
3835
run: |
3936
poetry install --with dev
@@ -48,4 +45,4 @@ jobs:
4845
poetry run netexec mssql 127.0.0.1
4946
poetry run netexec ssh 127.0.0.1
5047
poetry run netexec ftp 127.0.0.1
51-
poetry run netexec smb 127.0.0.1 -M veeam
48+
poetry run netexec smb 127.0.0.1 -L

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2023, Marshall-Hallenbeck, NeffIsBack, zblurx, mpgn_x64
1+
Copyright (c) 2025, Marshall-Hallenbeck, NeffIsBack, zblurx, mpgn_x64
22
Copyright (c) 2022, byt3bl33d3r
33
All rights reserved.
44

netexec.spec

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,20 @@ a = Analysis(
2020
'aardwolf.commons.target',
2121
'aardwolf.protocol.x224.constants',
2222
'impacket.examples.secretsdump',
23+
'impacket.examples.regsecrets',
2324
'impacket.dcerpc.v5.lsat',
2425
'impacket.dcerpc.v5.transport',
2526
'impacket.dcerpc.v5.lsad',
2627
'impacket.dcerpc.v5.gkdi',
2728
'impacket.dcerpc.v5.rprn',
2829
'impacket.dcerpc.v5.even',
30+
'impacket.dcerpc.v5.even6',
2931
'impacket.dpapi_ng',
3032
'impacket.tds',
3133
'impacket.version',
3234
'impacket.ldap.ldap',
35+
'jwt',
3336
'nxc.connection',
34-
'nxc.servers.smb',
3537
'nxc.protocols.smb.wmiexec',
3638
'nxc.protocols.smb.atexec',
3739
'nxc.protocols.smb.smbexec',
@@ -42,11 +44,11 @@ a = Analysis(
4244
'nxc.parsers.ldap_results',
4345
'nxc.helpers.bash',
4446
'nxc.helpers.bloodhound',
47+
'nxc.helpers.even6_parser',
4548
'nxc.helpers.msada_guids',
4649
'nxc.helpers.ntlm_parser',
4750
'paramiko',
4851
'pypsrp.client',
49-
'pywerview.cli.helpers',
5052
'pylnk3',
5153
'pypykatz',
5254
'pyNfsClient',
@@ -71,6 +73,7 @@ a = Analysis(
7173
'dploot.triage.masterkeys',
7274
'dploot.triage.mobaxterm',
7375
'dploot.triage.backupkey',
76+
'dploot.triage.wam',
7477
'dploot.triage.wifi',
7578
'dploot.triage.sccm',
7679
'dploot.lib.target',

nxc/cli.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,46 +16,47 @@
1616

1717
def gen_cli_args():
1818
setup_debug_logging()
19-
19+
2020
try:
2121
VERSION, COMMIT = importlib.metadata.version("netexec").split("+")
22+
DISTANCE, COMMIT = COMMIT.split(".")
2223
except ValueError:
2324
VERSION = importlib.metadata.version("netexec")
2425
COMMIT = ""
25-
CODENAME = "NeedForSpeed"
26-
nxc_logger.debug(f"NXC VERSION: {VERSION} - {CODENAME} - {COMMIT}")
27-
26+
DISTANCE = ""
27+
CODENAME = "SmoothOperator"
28+
2829
generic_parser = argparse.ArgumentParser(add_help=False, formatter_class=DisplayDefaultsNotNone)
2930
generic_group = generic_parser.add_argument_group("Generic", "Generic options for nxc across protocols")
3031
generic_group.add_argument("--version", action="store_true", help="Display nxc version")
3132
generic_group.add_argument("-t", "--threads", type=int, dest="threads", default=256, help="set how many concurrent threads to use")
3233
generic_group.add_argument("--timeout", default=None, type=int, help="max timeout in seconds of each thread")
3334
generic_group.add_argument("--jitter", metavar="INTERVAL", type=str, help="sets a random delay between each authentication")
34-
35+
3536
output_parser = argparse.ArgumentParser(add_help=False, formatter_class=DisplayDefaultsNotNone)
3637
output_group = output_parser.add_argument_group("Output", "Options to set verbosity levels and control output")
3738
output_group.add_argument("--verbose", action="store_true", help="enable verbose output")
3839
output_group.add_argument("--debug", action="store_true", help="enable debug level information")
3940
output_group.add_argument("--no-progress", action="store_true", help="do not displaying progress bar during scan")
4041
output_group.add_argument("--log", metavar="LOG", help="export result into a custom file")
41-
42+
4243
dns_parser = argparse.ArgumentParser(add_help=False, formatter_class=DisplayDefaultsNotNone)
4344
dns_group = dns_parser.add_argument_group("DNS")
4445
dns_group.add_argument("-6", dest="force_ipv6", action="store_true", help="Enable force IPv6")
4546
dns_group.add_argument("--dns-server", action="store", help="Specify DNS server (default: Use hosts file & System DNS)")
4647
dns_group.add_argument("--dns-tcp", action="store_true", help="Use TCP instead of UDP for DNS queries")
4748
dns_group.add_argument("--dns-timeout", action="store", type=int, default=3, help="DNS query timeout in seconds")
48-
49+
4950
parser = argparse.ArgumentParser(
5051
description=rf"""
5152
. .
5253
.| |. _ _ _ _____
5354
|| || | \ | | ___ | |_ | ____| __ __ ___ ___
5455
\\( )// | \| | / _ \ | __| | _| \ \/ / / _ \ / __|
5556
.=[ ]=. | |\ | | __/ | |_ | |___ > < | __/ | (__
56-
/ /ॱ-ॱ\ \ |_| \_| \___| \__| |_____| /_/\_\ \___| \___|
57-
\ /
58-
57+
/ /˙-˙\ \ |_| \_| \___| \__| |_____| /_/\_\ \___| \___|
58+
˙ \ / ˙
59+
˙ ˙
5960
6061
The network execution tool
6162
Maintained as an open source project by @NeffIsBack, @MJHallenbeck, @_zblurx
@@ -98,12 +99,13 @@ def gen_cli_args():
9899
kerberos_group.add_argument("--use-kcache", action="store_true", help="Use Kerberos authentication from ccache file (KRB5CCNAME)")
99100
kerberos_group.add_argument("--aesKey", metavar="AESKEY", nargs="+", help="AES key to use for Kerberos Authentication (128 or 256 bits)")
100101
kerberos_group.add_argument("--kdcHost", metavar="KDCHOST", help="FQDN of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter")
101-
102-
server_group = std_parser.add_argument_group("Servers", "Options for nxc servers")
103-
server_group.add_argument("--server", choices={"http", "https"}, default="https", help="use the selected server")
104-
server_group.add_argument("--server-host", type=str, default="0.0.0.0", metavar="HOST", help="IP to bind the server to")
105-
server_group.add_argument("--server-port", metavar="PORT", type=int, help="start the server on the specified port")
106-
server_group.add_argument("--connectback-host", type=str, metavar="CHOST", help="IP for the remote system to connect back to")
102+
103+
certificate_group = std_parser.add_argument_group("Certificate", "Options for certificate authentication")
104+
certificate_group.add_argument("--pfx-cert", metavar="PFXCERT", help="Use certificate authentication from pfx file .pfx")
105+
certificate_group.add_argument("--pfx-base64", metavar="PFXB64", help="Use certificate authentication from pfx file encoded in base64")
106+
certificate_group.add_argument("--pfx-pass", metavar="PFXPASS", help="Password of the pfx certificate")
107+
certificate_group.add_argument("--pem-cert", metavar="PEMCERT", help="Use certificate authentication from PEM file")
108+
certificate_group.add_argument("--pem-key", metavar="PEMKEY", help="Private key for the PEM format")
107109

108110
p_loader = ProtocolLoader()
109111
protocols = p_loader.get_protocols()
@@ -115,22 +117,22 @@ def gen_cli_args():
115117
except Exception as e:
116118
nxc_logger.exception(f"Error loading proto_args from proto_args.py file in protocol folder: {protocol} - {e}")
117119

118-
argcomplete.autocomplete(parser)
120+
argcomplete.autocomplete(parser, always_complete_options=False)
119121
args = parser.parse_args()
120122

121123
if len(sys.argv) == 1:
122124
parser.print_help()
123125
sys.exit(1)
124126

125127
if args.version:
126-
print(f"{VERSION} - {CODENAME} - {COMMIT}")
128+
print(f"{VERSION} - {CODENAME} - {COMMIT} - {DISTANCE}")
127129
sys.exit(1)
128130

129131
# Multiply output_tries by 10 to enable more fine granural control, see exec methods
130132
if hasattr(args, "get_output_tries"):
131133
args.get_output_tries = args.get_output_tries * 10
132134

133-
return args
135+
return args, [CODENAME, VERSION, COMMIT, DISTANCE]
134136

135137

136138
def get_module_names():

nxc/config.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import os
21
from os.path import join as path_join
32
import configparser
4-
from nxc.paths import NXC_PATH, DATA_PATH
3+
from nxc.paths import DATA_PATH, CONFIG_PATH
54
from nxc.first_run import first_run_setup
65
from nxc.logger import nxc_logger
76
from ast import literal_eval
@@ -10,20 +9,25 @@
109
nxc_default_config.read(path_join(DATA_PATH, "nxc.conf"))
1110

1211
nxc_config = configparser.ConfigParser()
13-
nxc_config.read(os.path.join(NXC_PATH, "nxc.conf"))
12+
nxc_config.read(CONFIG_PATH)
1413

1514
if "nxc" not in nxc_config.sections():
1615
first_run_setup()
17-
nxc_config.read(os.path.join(NXC_PATH, "nxc.conf"))
16+
nxc_config.read(CONFIG_PATH)
1817

1918
# Check if there are any missing options in the config file
2019
for section in nxc_default_config.sections():
20+
if not nxc_config.has_section(section):
21+
nxc_logger.display(f"Adding missing section '{section}' to nxc.conf")
22+
nxc_config.add_section(section)
23+
with open(CONFIG_PATH, "w") as config_file:
24+
nxc_config.write(config_file)
2125
for option in nxc_default_config.options(section):
2226
if not nxc_config.has_option(section, option):
2327
nxc_logger.display(f"Adding missing option '{option}' in config section '{section}' to nxc.conf")
2428
nxc_config.set(section, option, nxc_default_config.get(section, option))
2529

26-
with open(path_join(NXC_PATH, "nxc.conf"), "w") as config_file:
30+
with open(CONFIG_PATH, "w") as config_file:
2731
nxc_config.write(config_file)
2832

2933
# THESE OPTIONS HAVE TO EXIST IN THE DEFAULT CONFIG FILE

0 commit comments

Comments
 (0)