Last active
April 17, 2024 16:09
-
-
Save mistymntncop/f6853ffe9492a049e03f2ee3c53d1d26 to your computer and use it in GitHub Desktop.
NtWaitForDebugEvent + WaitForMultipleObjects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <windows.h> | |
#include "nt_crap.h" | |
#define ArrayCount(arr) (sizeof(arr)/sizeof(arr[0])) | |
#define assert(expr) if(!(expr)) { *(char*)0 = 0; } | |
bool dbg_create_process(char *exe_path, HANDLE *debug_handle_out) { | |
NTSTATUS status = 0; | |
*debug_handle_out = INVALID_HANDLE_VALUE; | |
OBJECT_ATTRIBUTES obj_attr = {0}; | |
InitializeObjectAttributes(&obj_attr, 0, 0, 0, 0); | |
HANDLE debug_event_handle = 0; | |
status = NtCreateDebugObject(&debug_event_handle, DEBUG_ALL_ACCESS, &obj_attr, DBGK_KILL_PROCESS_ON_EXIT); | |
assert(NT_SUCCESS(status)); | |
UNICODE_STRING nt_path = {0}; //LEAK | |
wchar_t wide_path[MAX_PATH] = {0}; | |
size_t exe_path_size = strlen(exe_path); | |
assert(exe_path_size < MAX_PATH); | |
if(!MultiByteToWideChar(CP_ACP, 0, exe_path, exe_path_size, wide_path, MAX_PATH)) { | |
assert(0); | |
} | |
RtlDosPathNameToNtPathName_U_(wide_path, &nt_path, 0, 0); | |
RTL_USER_PROCESS_PARAMETERS *proc_params = 0; | |
status = RtlCreateProcessParametersEx(&proc_params, &nt_path, 0, 0, 0, 0, | |
&nt_path, 0, 0, 0, RTL_USER_PROCESS_PARAMETERS_NORMALIZED); | |
assert(NT_SUCCESS(status)); | |
size_t attr_count = 3; | |
size_t attr_size = sizeof(PS_ATTRIBUTE_LIST) + (attr_count * sizeof(PS_ATTRIBUTE)); | |
PS_ATTRIBUTE_LIST *attr_list = (PS_ATTRIBUTE_LIST*) calloc(1, attr_size); | |
attr_list->TotalLength = attr_size; | |
int n = 0; | |
attr_list->Attributes[n].Attribute = PsAttributeValue(PsAttributeImageName, FALSE, TRUE, FALSE); | |
attr_list->Attributes[n].Size = nt_path.Length; | |
attr_list->Attributes[n].Value = (ULONG_PTR) nt_path.Buffer; | |
n++; | |
attr_list->Attributes[n].Attribute = PsAttributeValue(PsAttributeDebugPort, FALSE, TRUE, TRUE); | |
attr_list->Attributes[n].Size = sizeof(debug_event_handle); | |
attr_list->Attributes[n].Value = (ULONG_PTR) debug_event_handle; | |
n++; | |
CLIENT_ID client_id = {0}; //proc id and thread id in here | |
attr_list->Attributes[n].Attribute = PsAttributeValue(PsAttributeClientId, TRUE, FALSE, FALSE); | |
attr_list->Attributes[n].Size = sizeof(client_id); | |
attr_list->Attributes[n].Value = (ULONG_PTR) &client_id; | |
n++; | |
assert(n == attr_count); | |
PS_CREATE_INFO proc_create_info = {0}; | |
proc_create_info.Size = sizeof(proc_create_info); | |
HANDLE process_handle = 0; | |
HANDLE thread_handle = 0; | |
status = NtCreateUserProcess( | |
&process_handle, &thread_handle, | |
PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS, | |
0, 0, | |
PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT, | |
THREAD_CREATE_FLAGS_CREATE_SUSPENDED, | |
proc_params, &proc_create_info, | |
attr_list | |
); | |
int err = GetLastError(); | |
assert(NT_SUCCESS(status)); | |
RtlDestroyProcessParameters(proc_params); | |
free(attr_list); | |
ResumeThread(thread_handle); | |
//CloseHandle(process_handle); | |
//CloseHandle(thread_handle); | |
*debug_handle_out = debug_event_handle; | |
return true;// NT_SUCCESS(status); | |
} | |
bool wait_for_dbg_event(HANDLE debug_event_handle, DEBUG_EVENT *debug_event, DWORD wait_mili) { | |
LARGE_INTEGER timeout = {0}; | |
LARGE_INTEGER *timeout_ptr = 0; | |
if(wait_mili != INFINITE) { | |
BaseFormatTimeOut(&timeout, wait_mili); | |
timeout_ptr = &timeout; | |
} | |
DBGUI_WAIT_STATE_CHANGE wait_change = {0}; | |
NTSTATUS event_status = NtWaitForDebugEvent( | |
debug_event_handle, FALSE, timeout_ptr, &wait_change); | |
if(event_status == STATUS_TIMEOUT) { | |
return false; | |
} | |
assert(NT_SUCCESS(event_status)); | |
NTSTATUS convert_status = DbgUiConvertStateChangeStructure(&wait_change, debug_event); | |
assert(NT_SUCCESS(convert_status)); | |
return true; | |
} | |
void continue_dbg_event(HANDLE debug_event_handle, DWORD proc_id, DWORD thread_id, DWORD dbg_status) { | |
CLIENT_ID client_id = { | |
(HANDLE)(UINT_PTR)proc_id, | |
(HANDLE)(UINT_PTR)thread_id | |
}; | |
NTSTATUS status = NtDebugContinue( | |
debug_event_handle, &client_id, dbg_status); | |
assert(NT_SUCCESS(status)); | |
} | |
int main(int argc, char **argv) { | |
load_native_funcs(); | |
HANDLE std_input = GetStdHandle(STD_INPUT_HANDLE); | |
DWORD console_mode = 0; | |
GetConsoleMode(std_input, &console_mode); | |
console_mode &= ~(ENABLE_LINE_INPUT); | |
FlushConsoleInputBuffer(std_input); | |
char current_dir[MAX_PATH+1] = {0}; | |
DWORD path_len = GetCurrentDirectory(sizeof(current_dir), current_dir); | |
assert(path_len < sizeof(current_dir)); | |
HANDLE handles[MAXIMUM_WAIT_OBJECTS] = {0}; | |
for(uint32_t i = 0; i < ArrayCount(handles); i++) { | |
handles[i] = INVALID_HANDLE_VALUE; | |
} | |
DWORD waiting_count = 0; | |
handles[waiting_count++] = std_input; | |
while(true) { | |
assert(waiting_count < ArrayCount(handles)); | |
//any input on STD_INPUT_HANDLE will signal WaitForMultipleObjects | |
DWORD wait_obj = WaitForMultipleObjects(waiting_count, handles, FALSE, INFINITE); | |
//first slot is reserved for stdin | |
if(wait_obj == WAIT_OBJECT_0) { | |
INPUT_RECORD inputs = {0}; | |
DWORD bytes_read = 0; | |
//We can't use ReadConsole with WFMO because WFMO will return | |
//on the first key event not when received an entired line. | |
ReadConsoleInput(std_input, &inputs, sizeof(inputs), &bytes_read); | |
//FlushConsoleInputBuffer(std_input); | |
if(inputs.EventType == KEY_EVENT) { | |
if(inputs.Event.KeyEvent.uChar.AsciiChar == 'n') { | |
char exe_path[MAX_PATH+1] = {0}; | |
sprintf(exe_path, "%s\\%s", current_dir, "prog.exe"); | |
HANDLE new_debug_handle = 0; | |
if(dbg_create_process(exe_path, &new_debug_handle)) { | |
assert(waiting_count < ArrayCount(handles)); | |
handles[waiting_count++] = new_debug_handle; | |
} else { | |
assert(!"bad beans!!!!"); | |
} | |
} | |
} | |
} else if(wait_obj >= (WAIT_OBJECT_0+1) && wait_obj < (WAIT_OBJECT_0+waiting_count)) { | |
DWORD event = wait_obj - WAIT_OBJECT_0; | |
assert(event < waiting_count); | |
HANDLE debug_event_handle = handles[event]; | |
DEBUG_EVENT debug_event = {0}; | |
//we need to call NtWaitForDebugEvent a second time and let it timeout | |
//otherwise it will never be reset and WaitForMultipleObjects | |
//will hang forever... | |
DWORD timeout = INFINITE; | |
while(wait_for_dbg_event(debug_event_handle, &debug_event, timeout)) { | |
DWORD dbg_status = DBG_CONTINUE; | |
switch(debug_event.dwDebugEventCode) { | |
case OUTPUT_DEBUG_STRING_EVENT: { | |
VOID *string_addr = debug_event.u.DebugString.lpDebugStringData; | |
char *string = (char*) malloc(debug_event.u.DebugString.nDebugStringLength); | |
HANDLE proc_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, debug_event.dwProcessId); | |
SIZE_T bytes_read = 0; | |
ReadProcessMemory(proc_handle, string_addr, string, debug_event.u.DebugString.nDebugStringLength, &bytes_read); | |
assert(bytes_read == debug_event.u.DebugString.nDebugStringLength); | |
printf("%u - %s\n", debug_event.dwProcessId, string); | |
CloseHandle(proc_handle); | |
free(string); | |
} break; | |
} | |
continue_dbg_event(debug_event_handle, | |
debug_event.dwProcessId, debug_event.dwThreadId, dbg_status); | |
timeout = 0; | |
} | |
} | |
} | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define WIN32_LEAN_AND_MEAN | |
#include <winternl.h> | |
typedef struct { | |
EXCEPTION_RECORD ExceptionRecord; | |
ULONG FirstChance; | |
} DBGKM_EXCEPTION; | |
typedef struct { | |
ULONG SubSystemKey; | |
PVOID StartAddress; | |
} DBGKM_CREATE_THREAD; | |
typedef struct { | |
ULONG SubSystemKey; | |
HANDLE FileHandle; | |
PVOID BaseOfImage; | |
ULONG DebugInfoFileOffset; | |
ULONG DebugInfoSize; | |
DBGKM_CREATE_THREAD InitialThread; | |
} DBGKM_CREATE_PROCESS; | |
typedef struct { | |
NTSTATUS ExitStatus; | |
} DBGKM_EXIT_THREAD; | |
typedef struct { | |
NTSTATUS ExitStatus; | |
} DBGKM_EXIT_PROCESS; | |
typedef struct { | |
HANDLE FileHandle; | |
PVOID BaseOfDll; | |
ULONG DebugInfoFileOffset; | |
ULONG DebugInfoSize; | |
PVOID NamePointer; | |
} DBGKM_LOAD_DLL; | |
typedef struct { | |
PVOID BaseAddress; | |
} DBGKM_UNLOAD_DLL; | |
typedef struct { | |
HANDLE HandleToThread; | |
DBGKM_CREATE_THREAD NewThread; | |
} DBGUI_CREATE_THREAD; | |
typedef struct { | |
HANDLE HandleToProcess; | |
HANDLE HandleToThread; | |
DBGKM_CREATE_PROCESS NewProcess; | |
} DBGUI_CREATE_PROCESS; | |
typedef enum { | |
DbgIdle, | |
DbgReplyPending, | |
DbgCreateThreadStateChange, | |
DbgCreateProcessStateChange, | |
DbgExitThreadStateChange, | |
DbgExitProcessStateChange, | |
DbgExceptionStateChange, | |
DbgBreakpointStateChange, | |
DbgSingleStepStateChange, | |
DbgLoadDllStateChange, | |
DbgUnloadDllStateChange | |
} DBG_STATE; | |
//TODO: CHECK THIS STRUCTURE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
typedef struct { | |
DBG_STATE NewState; | |
CLIENT_ID AppClientId; | |
union { | |
DBGKM_EXCEPTION Exception; | |
DBGUI_CREATE_THREAD CreateThread; | |
DBGUI_CREATE_PROCESS CreateProcessInfo; | |
DBGKM_EXIT_THREAD ExitThread; | |
DBGKM_EXIT_PROCESS ExitProcess; | |
DBGKM_LOAD_DLL LoadDll; | |
DBGKM_UNLOAD_DLL UnloadDll; | |
} StateInfo; | |
} DBGUI_WAIT_STATE_CHANGE; | |
typedef enum { | |
SectionBasicInformation, | |
SectionImageInformation, | |
} SECTION_INFORMATION_CLASS; | |
typedef struct { | |
PVOID EntryPoint; | |
ULONG ZeroBits; | |
ULONGLONG StackReserved; //VOID* | |
ULONGLONG StackCommit; | |
ULONG SubSystemType; | |
union { | |
struct { | |
USHORT SubSystemMinorVersion; | |
USHORT SubSystemMajorVersion; | |
}; | |
ULONG SubSystemVersion; | |
}; | |
ULONG GpValue; | |
USHORT ImageCharacteristics; | |
USHORT DllCharacteristics; | |
USHORT Machine; | |
UCHAR ImageContainsCode; | |
union { | |
UCHAR ImageFlags; | |
struct { | |
UCHAR ComPlusNativeReady:1; | |
UCHAR ComPlusILOnly:1; | |
UCHAR ImageDynamicallyRelocated:1; | |
UCHAR ImageMappedFlat:1; | |
UCHAR Reserved:4; | |
}; | |
}; | |
ULONG LoaderFlags; | |
ULONG ImageFileSize; | |
ULONG CheckSum; | |
} SECTION_IMAGE_INFORMATION; | |
typedef struct { | |
ULONG Size; | |
HANDLE ProcessHandle; | |
HANDLE ThreadHandle; | |
CLIENT_ID ClientId; | |
SECTION_IMAGE_INFORMATION ImageInformation; | |
} RTL_USER_PROCESS_INFORMATION; | |
typedef NTSTATUS (NTAPI nt_create_debug_object_t)( | |
HANDLE *DebugObjectHandle, | |
ACCESS_MASK DesiredAccess, | |
OBJECT_ATTRIBUTES *ObjectAttributes, | |
ULONG Flags | |
); | |
typedef NTSTATUS (NTAPI nt_debug_active_process_t)(HANDLE ProcessHandle, HANDLE DebugObjectHandle); | |
typedef NTSTATUS (NTAPI nt_remove_process_debug_t)(HANDLE ProcessHandle, HANDLE DebugObjectHandle); | |
typedef NTSTATUS (NTAPI nt_wait_for_debug_event_t)(HANDLE, BOOLEAN, LARGE_INTEGER *, DBGUI_WAIT_STATE_CHANGE *); | |
typedef NTSTATUS (NTAPI nt_debug_continue_t)(HANDLE, CLIENT_ID *, NTSTATUS); | |
typedef NTSTATUS (NTAPI nt_set_information_process_t)( | |
IN HANDLE ProcessHandle, | |
IN PROCESS_INFORMATION_CLASS ProcessInformationClass, | |
IN PVOID ProcessInformation, | |
IN ULONG ProcessInformationLength | |
); | |
#define DEBUG_PROCESS_DETACH_ON_EXIT 0x00000001 | |
#define DEBUG_PROCESS_ONLY_THIS_PROCESS 0x00000002 | |
#define ProcessDebugFlags (PROCESS_INFORMATION_CLASS)31 | |
#define DEBUG_READ_EVENT 0x0001 | |
#define DEBUG_PROCESS_ASSIGN 0x0002 | |
#define DEBUG_SET_INFORMATION 0x0004 | |
#define DEBUG_QUERY_INFORMATION 0x0008 | |
#define DEBUG_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \ | |
DEBUG_READ_EVENT | DEBUG_PROCESS_ASSIGN | DEBUG_SET_INFORMATION | \ | |
DEBUG_QUERY_INFORMATION) | |
#define DBGK_KILL_PROCESS_ON_EXIT (0x1) | |
typedef NTSTATUS (NTAPI dbg_ui_convert_state_change_structure_t)( | |
DBGUI_WAIT_STATE_CHANGE *wait_change, | |
DEBUG_EVENT *debug_event | |
); | |
typedef NTSTATUS (NTAPI rtl_create_process_parameters_t)( | |
OUT RTL_USER_PROCESS_PARAMETERS **pProcessParameters, | |
IN UNICODE_STRING *ImagePathName, | |
IN UNICODE_STRING *DllPath OPTIONAL, | |
IN UNICODE_STRING *CurrentDirectory OPTIONAL, | |
IN UNICODE_STRING *CommandLine OPTIONAL, | |
IN VOID *Environment OPTIONAL, | |
IN UNICODE_STRING *WindowTitle OPTIONAL, | |
IN UNICODE_STRING *DesktopInfo OPTIONAL, | |
IN UNICODE_STRING *ShellInfo OPTIONAL, | |
IN UNICODE_STRING *RuntimeData OPTIONAL | |
); | |
typedef NTSTATUS (NTAPI rtl_destroy_process_parameters_t)( | |
IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters | |
); | |
typedef NTSTATUS (NTAPI rtl_create_user_process_t)( | |
IN UNICODE_STRING *ImagePath, | |
IN ULONG ObjectAttributes, | |
IN OUT RTL_USER_PROCESS_PARAMETERS *ProcessParameters, | |
IN SECURITY_DESCRIPTOR *ProcessSecurityDescriptor OPTIONAL, | |
IN SECURITY_DESCRIPTOR *ThreadSecurityDescriptor OPTIONAL, | |
IN HANDLE ParentProcess, | |
IN BOOLEAN InheritHandles, | |
IN HANDLE DebugPort OPTIONAL, | |
IN HANDLE ExceptionPort OPTIONAL, | |
OUT RTL_USER_PROCESS_INFORMATION *ProcessInformation | |
); | |
//////////////////////////////////////////// | |
typedef enum _PS_PROTECTED_TYPE { | |
PsProtectedTypeNone, | |
PsProtectedTypeProtectedLight, | |
PsProtectedTypeProtected, | |
PsProtectedTypeMax | |
} PS_PROTECTED_TYPE; | |
typedef enum _PS_PROTECTED_SIGNER { | |
PsProtectedSignerNone, | |
PsProtectedSignerAuthenticode, | |
PsProtectedSignerCodeGen, | |
PsProtectedSignerAntimalware, | |
PsProtectedSignerLsa, | |
PsProtectedSignerWindows, | |
PsProtectedSignerWinTcb, | |
PsProtectedSignerMax | |
} PS_PROTECTED_SIGNER; | |
typedef struct _PS_PROTECTION { | |
union { | |
UCHAR Level; | |
struct { | |
UCHAR Type : 3; | |
UCHAR Audit : 1; | |
UCHAR Signer : 4; | |
}; | |
}; | |
} PS_PROTECTION, *PPS_PROTECTION; | |
// begin_rev | |
#define PS_ATTRIBUTE_NUMBER_MASK 0x0000ffff | |
#define PS_ATTRIBUTE_THREAD 0x00010000 // can be used with threads | |
#define PS_ATTRIBUTE_INPUT 0x00020000 // input only | |
#define PS_ATTRIBUTE_ADDITIVE 0x00040000 /// Is an additional option (see ProcThreadAttributeValue in WinBase.h) | |
// end_rev | |
typedef enum _PS_ATTRIBUTE_NUM { | |
PsAttributeParentProcess, // in HANDLE | |
PsAttributeDebugPort, // in HANDLE | |
PsAttributeToken, // in HANDLE | |
PsAttributeClientId, // out PCLIENT_ID | |
PsAttributeTebAddress, // out PTEB | |
PsAttributeImageName, // in PWSTR | |
PsAttributeImageInfo, // out PSECTION_IMAGE_INFORMATION | |
PsAttributeMemoryReserve, // in PPS_MEMORY_RESERVE | |
PsAttributePriorityClass, // in UCHAR | |
PsAttributeErrorMode, // in ULONG | |
PsAttributeStdHandleInfo, // 10, in PPS_STD_HANDLE_INFO | |
PsAttributeHandleList, // in PHANDLE | |
PsAttributeGroupAffinity, // in PGROUP_AFFINITY | |
PsAttributePreferredNode, // in PUSHORT | |
PsAttributeIdealProcessor, // in PPROCESSOR_NUMBER | |
PsAttributeUmsThread, // see UpdateProceThreadAttributeList in msdn (CreateProcessA/W...) in PUMS_CREATE_THREAD_ATTRIBUTES | |
PsAttributeMitigationOptions, // in UCHAR | |
PsAttributeProtectionLevel, | |
PsAttributeSecureProcess, // since THRESHOLD (Virtual Secure Mode, Device Guard) | |
PsAttributeJobList, | |
PsAttributeMax | |
} PS_ATTRIBUTE_NUM; | |
#define PsAttributeValue(Number, Thread, Input, Additive) \ | |
(((Number) & PS_ATTRIBUTE_NUMBER_MASK) | \ | |
((Thread) ? PS_ATTRIBUTE_THREAD : 0) | \ | |
((Input) ? PS_ATTRIBUTE_INPUT : 0) | \ | |
((Additive) ? PS_ATTRIBUTE_ADDITIVE : 0)) | |
typedef struct _PS_ATTRIBUTE { | |
ULONGLONG Attribute; /// PROC_THREAD_ATTRIBUTE_XXX | PROC_THREAD_ATTRIBUTE_XXX modifiers, see ProcThreadAttributeValue macro and Windows Internals 6 (372) | |
SIZE_T Size; /// Size of Value or *ValuePtr | |
union { | |
ULONG_PTR Value; /// Reserve 8 bytes for data (such as a Handle or a data pointer) | |
PVOID ValuePtr; /// data pointer | |
}; | |
PSIZE_T ReturnLength; /// Either 0 or specifies size of data returned to caller via "ValuePtr" | |
} PS_ATTRIBUTE, *PPS_ATTRIBUTE; | |
typedef struct _PS_ATTRIBUTE_LIST { | |
SIZE_T TotalLength; /// sizeof(PS_ATTRIBUTE_LIST) | |
PS_ATTRIBUTE Attributes[0]; /// Depends on how many attribute entries should be supplied to NtCreateUserProcess | |
} PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST; | |
typedef struct _PS_MEMORY_RESERVE { | |
PVOID ReserveAddress; | |
SIZE_T ReserveSize; | |
} PS_MEMORY_RESERVE, *PPS_MEMORY_RESERVE; | |
typedef enum _PS_STD_HANDLE_STATE { | |
PsNeverDuplicate, | |
PsRequestDuplicate, // duplicate standard handles specified by PseudoHandleMask, and only if StdHandleSubsystemType matches the image subsystem | |
PsAlwaysDuplicate, // always duplicate standard handles | |
PsMaxStdHandleStates | |
} PS_STD_HANDLE_STATE; | |
// begin_rev | |
#define PS_STD_INPUT_HANDLE 0x1 | |
#define PS_STD_OUTPUT_HANDLE 0x2 | |
#define PS_STD_ERROR_HANDLE 0x4 | |
// end_rev | |
typedef struct _PS_STD_HANDLE_INFO { | |
union { | |
ULONG Flags; | |
struct { | |
ULONG StdHandleState : 2; // PS_STD_HANDLE_STATE | |
ULONG PseudoHandleMask : 3; // PS_STD_* | |
}; | |
}; | |
ULONG StdHandleSubsystemType; | |
} PS_STD_HANDLE_INFO, *PPS_STD_HANDLE_INFO; | |
// windows-internals-book:"Chapter 5" | |
typedef enum _PS_CREATE_STATE { | |
PsCreateInitialState, | |
PsCreateFailOnFileOpen, | |
PsCreateFailOnSectionCreate, | |
PsCreateFailExeFormat, | |
PsCreateFailMachineMismatch, | |
PsCreateFailExeName, // Debugger specified | |
PsCreateSuccess, | |
PsCreateMaximumStates | |
} PS_CREATE_STATE; | |
typedef struct _PS_CREATE_INFO { | |
SIZE_T Size; | |
PS_CREATE_STATE State; | |
union { | |
// PsCreateInitialState | |
struct { | |
union { | |
ULONG InitFlags; | |
struct { | |
UCHAR WriteOutputOnExit : 1; | |
UCHAR DetectManifest : 1; | |
UCHAR IFEOSkipDebugger : 1; | |
UCHAR IFEODoNotPropagateKeyState : 1; | |
UCHAR SpareBits1 : 4; | |
UCHAR SpareBits2 : 8; | |
USHORT ProhibitedImageCharacteristics : 16; | |
}; | |
}; | |
ACCESS_MASK AdditionalFileAccess; | |
} InitState; | |
// PsCreateFailOnSectionCreate | |
struct { | |
HANDLE FileHandle; | |
} FailSection; | |
// PsCreateFailExeFormat | |
struct { | |
USHORT DllCharacteristics; | |
} ExeFormat; | |
// PsCreateFailExeName | |
struct { | |
HANDLE IFEOKey; | |
} ExeName; | |
// PsCreateSuccess | |
struct { | |
union { | |
ULONG OutputFlags; | |
struct { | |
UCHAR ProtectedProcess : 1; | |
UCHAR AddressSpaceOverride : 1; | |
UCHAR DevOverrideEnabled : 1; // from Image File Execution Options | |
UCHAR ManifestDetected : 1; | |
UCHAR ProtectedProcessLight : 1; | |
UCHAR SpareBits1 : 3; | |
UCHAR SpareBits2 : 8; | |
USHORT SpareBits3 : 16; | |
}; | |
}; | |
HANDLE FileHandle; | |
HANDLE SectionHandle; | |
ULONGLONG UserProcessParametersNative; | |
ULONG UserProcessParametersWow64; | |
ULONG CurrentParameterFlags; | |
ULONGLONG PebAddressNative; | |
ULONG PebAddressWow64; | |
ULONGLONG ManifestAddress; | |
ULONG ManifestSize; | |
} SuccessState; | |
}; | |
} PS_CREATE_INFO, *PPS_CREATE_INFO; | |
// end_private | |
// Extended PROCESS_CREATE_FLAGS_* | |
// begin_rev | |
#define PROCESS_CREATE_FLAGS_LARGE_PAGE_SYSTEM_DLL 0x00000020 | |
#define PROCESS_CREATE_FLAGS_PROTECTED_PROCESS 0x00000040 | |
#define PROCESS_CREATE_FLAGS_CREATE_SESSION 0x00000080 // ? | |
#define PROCESS_CREATE_FLAGS_INHERIT_FROM_PARENT 0x00000100 | |
#define PROCESS_CREATE_FLAGS_INHERIT_HANDLES 0x00000004 | |
// end_rev | |
// begin_rev | |
#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001 | |
#define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002 // ? | |
#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004 | |
#define THREAD_CREATE_FLAGS_HAS_SECURITY_DESCRIPTOR 0x00000010 // ? | |
#define THREAD_CREATE_FLAGS_ACCESS_CHECK_IN_TARGET 0x00000020 // ? | |
#define THREAD_CREATE_FLAGS_INITIAL_THREAD 0x00000080 | |
// end_rev | |
#define RTL_USER_PROCESS_PARAMETERS_NORMALIZED 0x01 | |
#define PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT 0x00000002 | |
//////////////////////// | |
typedef NTSTATUS (NTAPI nt_create_user_process_t)( | |
HANDLE *ProcessHandle, | |
HANDLE *ThreadHandle, | |
ACCESS_MASK ProcessDesiredAccess, | |
ACCESS_MASK ThreadDesiredAccess, | |
OBJECT_ATTRIBUTES *ProcessObjectAttributes, | |
OBJECT_ATTRIBUTES *ThreadObjectAttributes, | |
ULONG ProcessFlags, | |
ULONG ThreadFlags, | |
RTL_USER_PROCESS_PARAMETERS *ProcessParameters, | |
PS_CREATE_INFO *CreateInfo, | |
PS_ATTRIBUTE_LIST *AttributeList | |
); | |
typedef LARGE_INTEGER *(WINAPI base_format_timeout_t)( | |
LARGE_INTEGER *pLITimeout, | |
DWORD dwMillis | |
); | |
typedef NTSTATUS (NTAPI nt_resume_thread)( | |
IN HANDLE ThreadHandle, | |
OUT PULONG SuspendCount OPTIONAL | |
); | |
//RtlDosPathNameToNtPathName_U | |
typedef BOOLEAN (NTAPI rtl_dos_path_name_to_nt_path_name_u)( | |
IN PCWSTR DosName, | |
OUT UNICODE_STRING *NtName, | |
OUT PCWSTR *PartName, | |
OUT VOID **RelativeName | |
//OUT PRTL_RELATIVE_NAME_U RelativeName | |
); | |
typedef void (rtl_free_unicode_string)(UNICODE_STRING *UnicodeString); | |
typedef NTSTATUS (NTAPI rtl_create_process_parameters_ex_t)( | |
_Out_ RTL_USER_PROCESS_PARAMETERS **pProcessParameters, | |
_In_ PUNICODE_STRING ImagePathName, | |
_In_opt_ PUNICODE_STRING DllPath, | |
_In_opt_ PUNICODE_STRING CurrentDirectory, | |
_In_opt_ PUNICODE_STRING CommandLine, | |
_In_opt_ PVOID Environment, | |
_In_opt_ PUNICODE_STRING WindowTitle, | |
_In_opt_ PUNICODE_STRING DesktopInfo, | |
_In_opt_ PUNICODE_STRING ShellInfo, | |
_In_opt_ PUNICODE_STRING RuntimeData, | |
_In_ ULONG Flags | |
); | |
nt_resume_thread *NtResumeThread = 0; | |
nt_create_debug_object_t *NtCreateDebugObject = 0; | |
nt_debug_active_process_t *NtDebugActiveProcess = 0; | |
nt_remove_process_debug_t *NtRemoveProcessDebug = 0; | |
nt_wait_for_debug_event_t *NtWaitForDebugEvent = 0; | |
nt_debug_continue_t *NtDebugContinue = 0; | |
nt_set_information_process_t *NtSetInformationProcess_ = 0; | |
nt_create_user_process_t *NtCreateUserProcess = 0; | |
dbg_ui_convert_state_change_structure_t *DbgUiConvertStateChangeStructure = 0; | |
rtl_create_process_parameters_t *RtlCreateProcessParameters = 0; | |
rtl_create_process_parameters_ex_t *RtlCreateProcessParametersEx = 0; | |
rtl_destroy_process_parameters_t *RtlDestroyProcessParameters = 0; | |
rtl_create_user_process_t *RtlCreateUserProcess = 0; | |
//rtl_free_unicode_string *RtlFreeUnicodeString = 0; | |
base_format_timeout_t *BaseFormatTimeOut = 0; | |
rtl_dos_path_name_to_nt_path_name_u *RtlDosPathNameToNtPathName_U_ = 0; | |
bool nt_funcs_loaded = false; | |
void load_native_funcs() { | |
if(nt_funcs_loaded) return; | |
nt_funcs_loaded = true; | |
HMODULE nt_dll = GetModuleHandle("ntdll.dll"); | |
NtResumeThread = (nt_resume_thread *) | |
GetProcAddress(nt_dll, "NtResumeThread"); | |
NtCreateDebugObject = (nt_create_debug_object_t *) | |
GetProcAddress(nt_dll, "NtCreateDebugObject"); | |
NtDebugActiveProcess = (nt_debug_active_process_t *) | |
GetProcAddress(nt_dll, "NtDebugActiveProcess"); | |
NtRemoveProcessDebug = (nt_remove_process_debug_t *) | |
GetProcAddress(nt_dll, "NtRemoveProcessDebug"); | |
NtWaitForDebugEvent = (nt_wait_for_debug_event_t *) | |
GetProcAddress(nt_dll, "NtWaitForDebugEvent"); | |
NtDebugContinue = (nt_debug_continue_t *) | |
GetProcAddress(nt_dll, "NtDebugContinue"); | |
NtSetInformationProcess_ = (nt_set_information_process_t *) | |
GetProcAddress(nt_dll, "NtSetInformationProcess"); | |
NtCreateUserProcess = (nt_create_user_process_t *) | |
GetProcAddress(nt_dll, "NtCreateUserProcess"); | |
DbgUiConvertStateChangeStructure = (dbg_ui_convert_state_change_structure_t *) | |
GetProcAddress(nt_dll, "DbgUiConvertStateChangeStructure"); | |
RtlCreateProcessParameters = (rtl_create_process_parameters_t *) | |
GetProcAddress(nt_dll, "RtlCreateProcessParameters"); | |
RtlCreateProcessParametersEx = (rtl_create_process_parameters_ex_t *) | |
GetProcAddress(nt_dll, "RtlCreateProcessParametersEx"); | |
RtlDestroyProcessParameters = (rtl_destroy_process_parameters_t *) | |
GetProcAddress(nt_dll, "RtlDestroyProcessParameters"); | |
RtlCreateUserProcess = (rtl_create_user_process_t *) | |
GetProcAddress(nt_dll, "RtlCreateUserProcess"); | |
RtlDosPathNameToNtPathName_U_ = (rtl_dos_path_name_to_nt_path_name_u *) | |
GetProcAddress(nt_dll, "RtlDosPathNameToNtPathName_U"); | |
//RtlFreeUnicodeString = (rtl_free_unicode_string *) | |
// GetProcAddress(nt_dll, "RtlFreeUnicodeString"); | |
HMODULE kernel32_dll = GetModuleHandle("kernel32.dll"); | |
BaseFormatTimeOut = (base_format_timeout_t *) | |
GetProcAddress(kernel32_dll, "BaseFormatTimeOut"); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <windows.h> | |
int main(int argc, char **argv) { | |
while(true) { | |
printf("hello world\n"); | |
OutputDebugStringA("hello world\n"); | |
Sleep(2 * 1000); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment