mirror of
https://github.com/toneillcodes/windows-process-injection
synced 2026-06-21 14:11:25 +00:00
Stability fuzzing PoC
This commit is contained in:
@@ -6,10 +6,13 @@ LOG_FILE = "active_telemetry.jsonl"
|
||||
# TOGGLE FLAG: Set to True for Chrome/Browsers, False for Notepad++/Single apps
|
||||
ENABLE_CHILD_GATING = False
|
||||
|
||||
# CONNECTION MODE: Set to a running PID (e.g., 1234) to attach, or None to spawn fresh
|
||||
TARGET_PID = 10032
|
||||
|
||||
# The JavaScript instrumentation payload to inject
|
||||
JS_CODE = """
|
||||
const seenFunctions = new Set();
|
||||
const moduleName = "wininet.dll";
|
||||
const moduleName = "uxtheme.dll";
|
||||
|
||||
function instrumentModule() {
|
||||
try {
|
||||
@@ -81,35 +84,46 @@ def on_child_added(child):
|
||||
# Initialize device manager
|
||||
device = frida.get_local_device()
|
||||
|
||||
# Configure target binary path and flags
|
||||
# TARGET_PATH = r"C:\Program Files\Google\Chrome\Application\chrome.exe"
|
||||
# Configure fallback spawn target path and flags
|
||||
TARGET_PATH = r"C:\Program Files\Notepad++\notepad++.exe"
|
||||
TARGET_FLAGS = [TARGET_PATH]
|
||||
|
||||
try:
|
||||
print(f"[*] Bootstrapping instrumentation loop for {TARGET_PATH}...")
|
||||
print(f"[*] Child Gating Status: {'ENABLED' if ENABLE_CHILD_GATING else 'DISABLED'}")
|
||||
|
||||
# 1. Conditionally register the device-level callback
|
||||
# 1. Conditionally register child gating callbacks if enabled
|
||||
if ENABLE_CHILD_GATING:
|
||||
device.on('child-added', on_child_added)
|
||||
|
||||
# 2. Spawn the process with the configured gating flag
|
||||
pid = device.spawn(TARGET_FLAGS, child_gating=ENABLE_CHILD_GATING)
|
||||
session = device.attach(pid)
|
||||
# 2. Establish Session based on connection mode (Attach vs Spawn)
|
||||
if TARGET_PID is not None:
|
||||
print(f"[*] Attaching to existing process PID: {TARGET_PID}...")
|
||||
session = device.attach(TARGET_PID)
|
||||
pid = TARGET_PID
|
||||
should_resume = False
|
||||
else:
|
||||
print(f"[*] Bootstrapping fresh instance for {TARGET_PATH}...")
|
||||
pid = device.spawn(TARGET_FLAGS, child_gating=ENABLE_CHILD_GATING)
|
||||
session = device.attach(pid)
|
||||
should_resume = True
|
||||
|
||||
print(f"[*] Child Gating Status: {'ENABLED' if ENABLE_CHILD_GATING else 'DISABLED'}")
|
||||
|
||||
# 3. Conditionally enable session-level child tracking
|
||||
if ENABLE_CHILD_GATING:
|
||||
session.enable_child_gating()
|
||||
|
||||
# Load script into the primary parent process
|
||||
# Load script into the target process session
|
||||
script = session.create_script(JS_CODE)
|
||||
script.on('message', on_message)
|
||||
script.load()
|
||||
|
||||
device.resume(pid)
|
||||
print(f"[+] Root process running at PID {pid}. Press Ctrl+C to stop tracking.\n" + "="*80)
|
||||
|
||||
# 4. Only resume if we spawned it suspended
|
||||
if should_resume:
|
||||
device.resume(pid)
|
||||
print(f"[+] Root process spawned and running at PID {pid}.")
|
||||
else:
|
||||
print(f"[+] Successfully attached to running PID {pid}.")
|
||||
|
||||
print("[*] Telemetry active. Press Ctrl+C to stop tracking.\n" + "="*80)
|
||||
sys.stdin.read()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
## Module Testing Table
|
||||
| Process | Version Tested | Target Module | Target Function | Payload Size | Beacon Result | Notes |
|
||||
|----|----|----|----|----|----|----|
|
||||
| notepad++.exe | 8.9.3 | wininet.dll | InternetSetOptionW | 287930 | execution | Crashed on 'Open File' operation |
|
||||
| Code.exe | 1.105.1 | wininet.dll | ShowCertificate | 287930 | success | Stable during typical usage |
|
||||
| notepad++.exe | 8.9.3 | wininet.dll | InternetSetOptionW | 287930 | execution, unstable | Crashed on 'Open File' operation |
|
||||
| notepad++.exe | 8.9.3 | wininet.dll | ShowCertificate | 287930 | success | Stable during normal browsing |
|
||||
| sublime_text.exe | Build 4200 | wininet.dll | InternetSetOptionW | 287930 | success | Stable during typical usage |
|
||||
| sublime_text.exe | Build 4200 | wininet.dll | ShowCertificate | 287930 | success | Stable during typical usage |
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
[
|
||||
{
|
||||
"target_executable": "C:\\Program Files\\Sublime Text\\sublime_text.exe",
|
||||
"trigger_dll": "comctl32.dll",
|
||||
"secondary_tool": "C:\\Users\\Administrator\\Desktop\\git\\windows-process-injection\\module-stomping\\remote-stomp.exe",
|
||||
"tool_arguments": ["-p", "{pid}", "-d", "wininet.dll", "-f", "InternetSetOptionW"],
|
||||
"timeout_seconds": 60
|
||||
},
|
||||
{
|
||||
"target_executable": "C:\\Program Files\\Sublime Text\\sublime_text.exe",
|
||||
"trigger_dll": "comctl32.dll",
|
||||
"secondary_tool": "C:\\Users\\Administrator\\Desktop\\git\\windows-process-injection\\module-stomping\\remote-stomp.exe",
|
||||
"tool_arguments": ["-p", "{pid}", "-d", "wininet.dll", "-f", "DeleteUrlCacheEntry"],
|
||||
"timeout_seconds": 60
|
||||
},
|
||||
{
|
||||
"target_executable": "C:\\Program Files\\Sublime Text\\sublime_text.exe",
|
||||
"trigger_dll": "comctl32.dll",
|
||||
"secondary_tool": "C:\\Users\\Administrator\\Desktop\\git\\windows-process-injection\\module-stomping\\remote-stomp.exe",
|
||||
"tool_arguments": ["-p", "{pid}", "-d", "wininet.dll", "-f", "DeleteUrlCacheEntryA"],
|
||||
"timeout_seconds": 60
|
||||
},
|
||||
{
|
||||
"target_executable": "C:\\Program Files\\Sublime Text\\sublime_text.exe",
|
||||
"trigger_dll": "comctl32.dll",
|
||||
"secondary_tool": "C:\\Users\\Administrator\\Desktop\\git\\windows-process-injection\\module-stomping\\remote-stomp.exe",
|
||||
"tool_arguments": ["-p", "{pid}", "-d", "wininet.dll", "-f", "IsHostInProxyBypassList"],
|
||||
"timeout_seconds": 60
|
||||
},
|
||||
{
|
||||
"target_executable": "C:\\Program Files\\Sublime Text\\sublime_text.exe",
|
||||
"trigger_dll": "comctl32.dll",
|
||||
"secondary_tool": "C:\\Users\\Administrator\\Desktop\\git\\windows-process-injection\\module-stomping\\remote-stomp.exe",
|
||||
"tool_arguments": ["-p", "{pid}", "-d", "wininet.dll", "-f", "InternetInitializeAutoProxyDll"],
|
||||
"timeout_seconds": 60
|
||||
},
|
||||
{
|
||||
"target_executable": "C:\\Program Files\\Sublime Text\\sublime_text.exe",
|
||||
"trigger_dll": "comctl32.dll",
|
||||
"secondary_tool": "C:\\Users\\Administrator\\Desktop\\git\\windows-process-injection\\module-stomping\\remote-stomp.exe",
|
||||
"tool_arguments": ["-p", "{pid}", "-d", "wininet.dll", "-f", "ShowCertificate"],
|
||||
"timeout_seconds": 60
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,102 @@
|
||||
import json
|
||||
import subprocess
|
||||
import time
|
||||
import os
|
||||
|
||||
def is_module_loaded(pid, module_name):
|
||||
"""Checks if a specific DLL is loaded by the target PID via tasklist."""
|
||||
try:
|
||||
cmd = ["tasklist", "/FI", f"PID eq {pid}", "/M", module_name]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, creationflags=subprocess.CREATE_NO_WINDOW)
|
||||
return module_name.lower() in result.stdout.lower()
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def run_configured_test(config_path):
|
||||
if not os.path.exists(config_path):
|
||||
print(f"[-] Configuration file not found: {config_path}")
|
||||
return
|
||||
|
||||
# 1. Parse configuration parameters safely
|
||||
try:
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
config = json.load(f)
|
||||
|
||||
target = config["target_executable"]
|
||||
trigger_dll = config["trigger_dll"]
|
||||
tool = config["secondary_tool"]
|
||||
tool_args = config.get("tool_arguments", [])
|
||||
timeout_sec = config.get("timeout_seconds", 60)
|
||||
except Exception as e:
|
||||
print(f"[-] Failed to parse JSON configuration: {e}")
|
||||
return
|
||||
|
||||
print(f"[*] Loaded profile for: {os.path.basename(target)}")
|
||||
|
||||
# 2. Start the primary process
|
||||
process = subprocess.Popen([target])
|
||||
pid = process.pid
|
||||
print(f"[+] Started primary process {pid} normally.")
|
||||
|
||||
# 3. Poll until the dependency module settles
|
||||
print(f"[*] Waiting for {trigger_dll} to stabilize in memory...")
|
||||
start_time = time.time()
|
||||
module_found = False
|
||||
|
||||
while time.time() - start_time < 10: # 10s initialization boundary
|
||||
if is_module_loaded(pid, trigger_dll):
|
||||
module_found = True
|
||||
print(f"[+] Verified {trigger_dll} mapping established.")
|
||||
break
|
||||
time.sleep(0.2)
|
||||
|
||||
if process.poll() is not None:
|
||||
print("[-] Primary process terminated during initialization.")
|
||||
return
|
||||
|
||||
if not module_found:
|
||||
print(f"[-] Warning: {trigger_dll} not explicitly verified. Proceeding...")
|
||||
|
||||
# 4. Resolve arguments and launch secondary tool
|
||||
cmd_line = [tool] + [arg.replace("{pid}", str(pid)) if isinstance(arg, str) else str(arg) for arg in tool_args]
|
||||
print(f"[+] Launching companion process: {' '.join(cmd_line)}")
|
||||
secondary_process = subprocess.Popen(cmd_line)
|
||||
|
||||
# 5. Monitor execution life cycle up to the timeout threshold
|
||||
print(f"[*] Monitoring execution stability window ({timeout_sec}s)...")
|
||||
try:
|
||||
exit_code = process.wait(timeout=timeout_sec)
|
||||
|
||||
# Interpret termination exit codes
|
||||
STATUS_ACCESS_VIOLATION = -1073741819 # 0xC0000005
|
||||
STATUS_INVALID_CRUNTIME = -1073740777 # 0xC0000417
|
||||
STATUS_INVALID_CRUNTIME_ALT = 3221225622
|
||||
|
||||
if exit_code in [STATUS_ACCESS_VIOLATION, 0xC0000005]:
|
||||
print("[!] Stability Fault: Process crashed due to an Access Violation (0xC0000005).")
|
||||
elif exit_code in [STATUS_INVALID_CRUNTIME, STATUS_INVALID_CRUNTIME_ALT]:
|
||||
print("[!] Stability Fault: Process forced closure via Invalid CRT Parameter (0xC0000417).")
|
||||
elif exit_code != 0:
|
||||
print(f"[!] Process stopped prematurely with exit code: {exit_code}")
|
||||
else:
|
||||
print(f"[+] Process completed run cleanly with exit code: {exit_code}")
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
print(f"[+] Stability Window Met: Process handled workload successfully for {timeout_sec}s.")
|
||||
except KeyboardInterrupt:
|
||||
print("[-] Execution stopped by user.")
|
||||
finally:
|
||||
print("[+] Performing environmental cleanup...")
|
||||
if process.poll() is None:
|
||||
process.kill()
|
||||
process.wait()
|
||||
if secondary_process.poll() is None:
|
||||
try:
|
||||
secondary_process.kill()
|
||||
secondary_process.wait()
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
CONFIG_FILE = "stability-harness-config.json"
|
||||
run_configured_test(CONFIG_FILE)
|
||||
Reference in New Issue
Block a user