Skip to content

Commit 981ad11

Browse files
authored
Merge branch 'main' into dc-list
Signed-off-by: termanix <50464194+termanix@users.noreply.github.com>
2 parents e993fbd + c34c581 commit 981ad11

11 files changed

Lines changed: 135 additions & 47 deletions

File tree

.github/workflows/build-binaries.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

nxc/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def gen_cli_args():
2424
VERSION = importlib.metadata.version("netexec")
2525
COMMIT = ""
2626
DISTANCE = ""
27-
CODENAME = "NeedForSpeed"
27+
CODENAME = "SmoothOperator"
2828
nxc_logger.debug(f"NXC VERSION: {VERSION} - {CODENAME} - {COMMIT} - {DISTANCE}")
2929

3030
generic_parser = argparse.ArgumentParser(add_help=False, formatter_class=DisplayDefaultsNotNone)
@@ -124,7 +124,7 @@ def gen_cli_args():
124124
except Exception as e:
125125
nxc_logger.exception(f"Error loading proto_args from proto_args.py file in protocol folder: {protocol} - {e}")
126126

127-
argcomplete.autocomplete(parser)
127+
argcomplete.autocomplete(parser, always_complete_options=False)
128128
args = parser.parse_args()
129129

130130
if len(sys.argv) == 1:

nxc/first_run.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ def first_run_setup(logger=nxc_logger):
2929
logger.display(f"Creating missing folder {folder}")
3030
mkdir(path_join(NXC_PATH, folder))
3131

32+
log_subfolders = (
33+
"sam",
34+
"lsa",
35+
"ntds",
36+
"dpapi",
37+
)
38+
for subfolder in log_subfolders:
39+
if not exists(path_join(NXC_PATH, f"logs/{subfolder}")):
40+
logger.display(f"Creating missing folder logs/{subfolder}")
41+
mkdir(path_join(NXC_PATH, f"logs/{subfolder}"))
42+
3243
initialize_db()
3344

3445
if not exists(CONFIG_PATH):

nxc/modules/enum_av.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,14 @@ def LsarLookupNames(self, dce, policyHandle, service):
289289
{"name": "exploitProtectionIPC", "processes": ["AVKWCtlx64.exe"]}
290290
]
291291
},
292+
{
293+
"name": "Ivanti Security",
294+
"services": [
295+
{"name": "STAgent$Shavlik Protect", "description": "Ivanti Security Controls Agent"},
296+
{"name": "STDispatch$Shavlik Protect", "description": "Ivanti Security Controls Agent Dispatcher"}
297+
],
298+
"pipes": []
299+
},
292300
{
293301
"name": "Kaspersky Security for Windows Server",
294302
"services": [
@@ -335,6 +343,11 @@ def LsarLookupNames(self, dce, policyHandle, service):
335343
],
336344
"pipes": []
337345
},
346+
{
347+
"name": "Rapid7",
348+
"services": [{"name": "ir_agent", "description": "Rapid7 Insight Agent"}],
349+
"pipes": []
350+
},
338351
{
339352
"name": "Sophos Intercept X",
340353
"services": [
@@ -384,7 +397,10 @@ def LsarLookupNames(self, dce, policyHandle, service):
384397
{"name": "Trend Micro Web Service Communicator", "description": "Trend Micro Web Service Communicator"},
385398
{"name": "TMiACAgentSvc", "description": "Trend Micro Application Control Service (Agent)"},
386399
{"name": "CETASvc", "description": "Trend Micro Cloud Endpoint Telemetry Service"},
387-
{"name": "iVPAgent", "description": "Trend Micro Vulnerability Protection Service (Agent)"}
400+
{"name": "iVPAgent", "description": "Trend Micro Vulnerability Protection Service (Agent)"},
401+
{"name": "ds_agent", "description": "Trend Micro Deep Security Agent"},
402+
{"name": "ds_monitor", "description": "Trend Micro Deep Security Monitor"},
403+
{"name": "ds_notifier", "description": "Trend Micro Deep Security Notifier"}
388404
],
389405
"pipes": [
390406
{"name": "IPC_XBC_XBC_AGENT_PIPE_*", "processes": ["EndpointBasecamp.exe"]},

nxc/modules/get-desc-users.py

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from impacket.ldap import ldapasn1 as ldapasn1_impacket
21
from impacket.ldap import ldap as ldap_impacket
32
import re
43
from nxc.logger import nxc_logger
4+
from nxc.parsers.ldap_results import parse_result_attributes
55

66

77
class NXCModule:
@@ -55,24 +55,10 @@ def on_login(self, context, connection):
5555
nxc_logger.debug(e)
5656
return False
5757

58-
answers = []
5958
context.log.debug(f"Total of records returned {len(resp)}")
60-
for item in resp:
61-
if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True:
62-
continue
63-
sAMAccountName = ""
64-
description = ""
65-
try:
66-
for attribute in item["attributes"]:
67-
if str(attribute["type"]) == "sAMAccountName":
68-
sAMAccountName = str(attribute["vals"][0])
69-
elif str(attribute["type"]) == "description":
70-
description = attribute["vals"][0]
71-
if sAMAccountName != "" and description != "":
72-
answers.append([sAMAccountName, description])
73-
except Exception as e:
74-
context.log.debug("Exception:", exc_info=True)
75-
context.log.debug(f"Skipping item, cannot process due to error {e!s}")
59+
resp_parsed = parse_result_attributes(resp)
60+
answers = [[x["sAMAccountName"], x.get("description")] for x in resp_parsed if x.get("description")]
61+
7662
answers = self.filter_answer(context, answers)
7763
if len(answers) > 0:
7864
context.log.success("Found following users: ")
@@ -108,5 +94,5 @@ def filter_answer(self, context, answers):
10894
answersFiltered.append([answer[0], description])
10995
elif (self.FILTER != "" and conditionFilter) and (conditionPasswordPolicy == self.PASSWORDPOLICY):
11096
context.log.highlight(f"'{self.FILTER}' found in user: '{answer[0]}' description: '{description}'")
111-
97+
11298
return answersFiltered

nxc/netexec.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# PYTHON_ARGCOMPLETE_OK
12
import sys
23
from nxc.helpers.logger import highlight
34
from nxc.helpers.misc import identify_target_file

nxc/parsers/ldap_results.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from impacket.ldap import ldapasn1 as ldapasn1_impacket
2+
from uuid import UUID
23

34

45
def parse_result_attributes(ldap_response):
@@ -11,16 +12,43 @@ def parse_result_attributes(ldap_response):
1112
for attribute in entry["attributes"]:
1213
val_list = []
1314
for val in attribute["vals"].components:
14-
try:
15-
encoding = val.encoding
16-
val_decoded = str(val).encode(encoding).decode("utf-8")
17-
except UnicodeDecodeError:
18-
# If we can't decode the value, we'll just return the bytes
19-
val_decoded = val.__bytes__()
15+
# Typical Byte objects we know how to decode
16+
if str(attribute["type"]) == "objectGUID":
17+
val_decoded = UUID(bytes=val.__bytes__())
18+
elif str(attribute["type"]) == "objectSid":
19+
val_decoded = sid_to_str(val.__bytes__())
20+
else:
21+
# For the rest we try to decode the value with its encoding
22+
try:
23+
encoding = val.encoding
24+
val_decoded = str(val).encode(encoding).decode("utf-8")
25+
except UnicodeDecodeError:
26+
# If we can't decode the value, we'll just return the bytes
27+
val_decoded = val.__bytes__()
2028
val_list.append(val_decoded)
2129
if len(val_list) == 1:
2230
attribute_map[str(attribute["type"])] = val_list[0]
2331
else:
2432
attribute_map[str(attribute["type"])] = val_list
2533
parsed_response.append(attribute_map)
2634
return parsed_response
35+
36+
37+
def sid_to_str(sid):
38+
try:
39+
# revision
40+
revision = int(sid[0])
41+
# count of sub authorities
42+
sub_authorities = int(sid[1])
43+
# big endian
44+
identifier_authority = int.from_bytes(sid[2:8], byteorder="big")
45+
# If true then it is represented in hex
46+
if identifier_authority >= 2**32:
47+
identifier_authority = hex(identifier_authority)
48+
49+
# loop over the count of small endians
50+
sub_authority = "-" + "-".join([str(int.from_bytes(sid[8 + (i * 4): 12 + (i * 4)], byteorder="little")) for i in range(sub_authorities)])
51+
return "S-" + str(revision) + "-" + str(identifier_authority) + sub_authority
52+
except Exception:
53+
pass
54+
return sid

nxc/protocols/ldap/proto_args.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def proto_args(parser, parents):
2020
vgroup.add_argument("--find-delegation", action="store_true", help="Finds delegation relationships within an Active Directory domain. (Enabled Accounts only)")
2121
vgroup.add_argument("--trusted-for-delegation", action="store_true", help="Get the list of users and computers with flag TRUSTED_FOR_DELEGATION")
2222
vgroup.add_argument("--password-not-required", action="store_true", help="Get the list of users with flag PASSWD_NOTREQD")
23-
vgroup.add_argument("--admin-count", action="store_true", help="Get objets that had the value adminCount=1")
23+
vgroup.add_argument("--admin-count", action="store_true", help="Get user that had the value adminCount=1")
2424
vgroup.add_argument("--users", nargs="*", help="Enumerate domain users")
2525
vgroup.add_argument("--users-export", help="Enumerate domain users and export them to the specified file")
2626
vgroup.add_argument("--groups", nargs="?", const="", help="Enumerate domain groups, if a group is specified than its members are enumerated")

nxc/protocols/nfs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def shares(self):
262262

263263
read_perm, write_perm, exec_perm = self.get_permissions(file_handle)
264264
self.mount.umnt(self.auth)
265-
self.logger.highlight(f"{self.auth['uid']:<11}{'r' if read_perm else '-'}{'w' if write_perm else '-'}{('x' if exec_perm else '-'):<7}{convert_size(used_space) + "/" + convert_size(total_space):<16} {share:<30} {', '.join(network) if network else 'No network':<15}")
265+
self.logger.highlight(f"{self.auth['uid']:<11}{'r' if read_perm else '-'}{'w' if write_perm else '-'}{('x' if exec_perm else '-'):<7}{convert_size(used_space) + '/' + convert_size(total_space):<16} {share:<30} {', '.join(network) if network else 'No network':<15}")
266266
except Exception as e:
267267
self.logger.fail(f"Failed to list share: {share} - {e}")
268268

0 commit comments

Comments
 (0)