Quality of life improvements using command line arguments

This commit is contained in:
toneillcodes
2026-06-15 17:56:00 -04:00
parent f4ea3e9091
commit fbea61b4be
2 changed files with 89 additions and 35 deletions
@@ -1,47 +1,88 @@
import argparse
import json
import sys
# Paths to your data files
MASTER_EXPORTS_FILE = "c:\\payloads\\uxtheme-modules.txt"
ACTIVE_TELEMETRY_FILE = "active_telemetry.jsonl"
OUTPUT_DORMANT_FILE = "uxtheme_dormant_targets.txt"
def isolate_dormant_code():
def isolate_dormant_code(
master_file, telemetry_file, output_file, target_dll
):
# 1. Load the comprehensive master export list
with open(MASTER_EXPORTS_FILE, "r", encoding="utf-8") as f:
master_exports = set(line.strip() for line in f if line.strip())
try:
with open(master_file, "r", encoding="utf-8") as f:
master_exports = set(line.strip() for line in f if line.strip())
except FileNotFoundError:
print(f"[-] Master exports file '{master_file}' not found.")
sys.exit(1)
print(f"[*] Loaded {len(master_exports)} total exports from master list.")
# 2. Parse the active telemetry log to find what actually fired
active_functions = set()
try:
# Inside your post-testing analysis script:
active_functions = set()
TARGET_DLL = "uxtheme.dll" # Filter for your specific analysis target
with open(ACTIVE_TELEMETRY_FILE, "r", encoding="utf-8") as f:
with open(telemetry_file, "r", encoding="utf-8") as f:
for line in f:
if line.strip():
entry = json.loads(line)
# Only match active functions that belong to the current target DLL
if entry["module"].lower() == TARGET_DLL.lower():
active_functions.add(entry["function"])
if entry.get("module", "").lower() == target_dll.lower():
active_functions.add(entry.get("function"))
except FileNotFoundError:
print(f"[-] Telemetry file {ACTIVE_TELEMETRY_FILE} not found.")
return
print(f"[-] Telemetry file '{telemetry_file}' not found.")
sys.exit(1)
print(f"[*] Identified {len(active_functions)} unique functions called during profiling.")
print(
f"[*] Identified {len(active_functions)} unique functions called during profiling."
)
# 3. Perform the set subtraction (Master Set - Active Set = Dormant Set)
dormant_targets = master_exports - active_functions
print(f"[+] Successfully isolated {len(dormant_targets)} completely dormant functions!")
print(
f"[+] Successfully isolated {len(dormant_targets)} completely dormant functions!"
)
# 4. Save the clean targets to a file for blast-radius calculation
with open(OUTPUT_DORMANT_FILE, "w", encoding="utf-8") as f:
for func in sorted(dormant_targets):
f.write(func + "\n")
print(f"[+] Dormant targets written to: {OUTPUT_DORMANT_FILE}")
try:
with open(output_file, "w", encoding="utf-8") as f:
for func in sorted(dormant_targets):
f.write(func + "\n")
except Exception as e:
print(f"[-] Failed to write output file: {e}")
sys.exit(1)
print(f"[+] Dormant targets written to: {output_file}")
if __name__ == "__main__":
isolate_dormant_code()
parser = argparse.ArgumentParser(
description="Isolate dormant exported functions by comparing a master list against active telemetry."
)
parser.add_argument(
"-m",
"--master",
required=True,
help="Path to the master exports text file (e.g., uxtheme-modules.txt).",
)
parser.add_argument(
"-t",
"--telemetry",
required=True,
help="Path to the active telemetry log JSONL file.",
)
parser.add_argument(
"-o",
"--output",
required=True,
help="Path where the output dormant functions file should be saved.",
)
parser.add_argument(
"-d",
"--dll",
required=True,
help="Target DLL name to filter within telemetry (e.g., uxtheme.dll).",
)
args = parser.parse_args()
# Run the isolation logic with the required parameters
isolate_dormant_code(args.master, args.telemetry, args.output, args.dll)
@@ -3,10 +3,10 @@ import csv
import json
import sys
STOMP_PATH = "C:\\Users\\Administrator\\Desktop\\git\\windows-process-injection\\module-stomping\\remote-stomp.exe"
TIMEOUT = 60
# Default fallback value for optional parameters
DEFAULT_TIMEOUT = 60
def transform_data(csv_file_path, json_file_path):
def transform_data(csv_file_path, json_file_path, stomp_path, timeout_seconds):
transformed_data = []
try:
@@ -23,9 +23,9 @@ def transform_data(csv_file_path, json_file_path):
json_entry = {
"target_executable": targetProcess,
"trigger_dll": targetModule,
"secondary_tool": STOMP_PATH,
"secondary_tool": stomp_path,
"tool_arguments": ["-p", "{pid}", "-d", targetModule, "-n", "-s", targetSectionSize],
"timeout_seconds": TIMEOUT,
"timeout_seconds": timeout_seconds,
}
transformed_data.append(json_entry)
@@ -34,8 +34,8 @@ def transform_data(csv_file_path, json_file_path):
json.dump(transformed_data, json_file, indent=2)
print(f"Success! Processed {len(transformed_data)} rows.")
print(f"Input: {csv_file_path}")
print(f"Output: {json_file_path}")
print(f"Input: {csv_file_path}")
print(f"Output: {json_file_path}")
except FileNotFoundError:
print(f"Error: The file '{csv_file_path}' was not found.")
@@ -55,7 +55,7 @@ if __name__ == "__main__":
"-i",
"--input",
required=True,
help="Path to the input CSV file (must contain field2 and field3 headers).",
help="Path to the input CSV file.",
)
parser.add_argument(
"-o",
@@ -63,9 +63,22 @@ if __name__ == "__main__":
required=True,
help="Path where the output JSON file should be saved.",
)
parser.add_argument(
"-s",
"--stomp-path",
required=True,
help="Path to the stomp executable.",
)
parser.add_argument(
"-t",
"--timeout",
type=int,
default=DEFAULT_TIMEOUT,
help=f"Timeout value in seconds (default: {DEFAULT_TIMEOUT}).",
)
# Parse the arguments from the command line
args = parser.parse_args()
# Run the transformation logic
transform_data(args.input, args.output)
# Run the transformation logic with the mandatory parameters
transform_data(args.input, args.output, args.stomp_path, args.timeout)