Recently I needed to debug an exe started within a sandbox from the entry point, but it was difficult since Sandboxie restarts it after running. So after googling and not finding any easy solutions, I wrote a Python script to start the application in a suspended state, which allowed me to attach the debugger to the real process and debug it from the start. Maybe someone else will find it useful despite how trivial it seems:
Python:
import ctypes
import os
# Define necessary structures for Windows API
class STARTUPINFO(ctypes.Structure):
_fields_ = [
("cb", ctypes.c_ulong),
("lpReserved", ctypes.c_char_p),
("lpDesktop", ctypes.c_char_p),
("lpTitle", ctypes.c_char_p),
("dwX", ctypes.c_ulong),
("dwY", ctypes.c_ulong),
("dwXSize", ctypes.c_ulong),
("dwYSize", ctypes.c_ulong),
("dwXCountChars", ctypes.c_ulong),
("dwYCountChars", ctypes.c_ulong),
("dwFillAttribute", ctypes.c_ulong),
("dwFlags", ctypes.c_ulong),
("wShowWindow", ctypes.c_ushort),
("cbReserved2", ctypes.c_ushort),
("lpReserved2", ctypes.POINTER(ctypes.c_ubyte)),
("hStdInput", ctypes.c_void_p),
("hStdOutput", ctypes.c_void_p),
("hStdError", ctypes.c_void_p),
]
class PROCESS_INFORMATION(ctypes.Structure):
_fields_ = [
("hProcess", ctypes.c_void_p),
("hThread", ctypes.c_void_p),
("dwProcessId", ctypes.c_ulong),
("dwThreadId", ctypes.c_ulong),
]
# Load the Windows API library
kernel32 = ctypes.windll.kernel32
# Constants
CREATE_SUSPENDED = 0x00000004
def run_suspended(path_to_executable):
si = STARTUPINFO()
si.cb = ctypes.sizeof(STARTUPINFO)
pi = PROCESS_INFORMATION()
# Prepare the command line
cmd = path_to_executable.encode('ascii')
# Create the process in a suspended state
if kernel32.CreateProcessA(
None, # lpApplicationName
cmd, # lpCommandLine
None, # lpProcessAttributes
None, # lpThreadAttributes
False, # bInheritHandles
CREATE_SUSPENDED, # dwCreationFlags
None, # lpEnvironment
None, # lpCurrentDirectory
ctypes.byref(si), # lpStartupInfo
ctypes.byref(pi) # lpProcessInformation
):
print(f"Process created with PID: {pi.dwProcessId}")
# Here you can resume the process when you're ready with: kernel32.ResumeThread(pi.hThread)
# Or use Sandboxie process menu -> Resume
kernel32.CloseHandle(pi.hProcess)
kernel32.CloseHandle(pi.hThread)
else:
print("Failed to create process.")
print(ctypes.GetLastError())
# Usage
run_suspended("Calc.exe")