diff --git a/module-stomping/api-monitoring/find-dormant-exports.py b/module-stomping/api-monitoring/find-dormant-exports.py index 9397df0..dcbbf6c 100644 --- a/module-stomping/api-monitoring/find-dormant-exports.py +++ b/module-stomping/api-monitoring/find-dormant-exports.py @@ -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() \ No newline at end of file + 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) \ No newline at end of file diff --git a/module-stomping/stability-harness/make-stability-plan.py b/module-stomping/stability-harness/make-stability-plan.py index a600885..cd5d819 100644 --- a/module-stomping/stability-harness/make-stability-plan.py +++ b/module-stomping/stability-harness/make-stability-plan.py @@ -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) \ No newline at end of file + # Run the transformation logic with the mandatory parameters + transform_data(args.input, args.output, args.stomp_path, args.timeout) \ No newline at end of file