Skip to content

Instantly share code, notes, and snippets.

@mistymntncop
Last active April 17, 2024 16:09
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save mistymntncop/f6853ffe9492a049e03f2ee3c53d1d26 to your computer and use it in GitHub Desktop.
Save mistymntncop/f6853ffe9492a049e03f2ee3c53d1d26 to your computer and use it in GitHub Desktop.
NtWaitForDebugEvent + WaitForMultipleObjects
#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;
}
#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");
}
#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