#include "types.h" #include "utils.h" #include "events.h" #include "parser.h" // ======================= // ====== windows.h ====== // ======================= #define STATUS_WAIT_0 ((u32 )0x00000000L) #define STATUS_ABANDONED_WAIT_0 ((u32 )0x00000080L) #define STATUS_USER_APC ((u32 )0x000000C0L) #define STATUS_TIMEOUT ((u32 )0x00000102L) #define STATUS_PENDING ((u32 )0x00000103L) #define DBG_EXCEPTION_HANDLED ((u32 )0x00010001L) #define DBG_CONTINUE ((u32 )0x00010002L) #define STATUS_SEGMENT_NOTIFICATION ((u32 )0x40000005L) #define STATUS_FATAL_APP_EXIT ((u32 )0x40000015L) #define DBG_REPLY_LATER ((u32 )0x40010001L) #define DBG_TERMINATE_THREAD ((u32 )0x40010003L) #define DBG_TERMINATE_PROCESS ((u32 )0x40010004L) #define DBG_CONTROL_C ((u32 )0x40010005L) #define DBG_PRINTEXCEPTION_C ((u32 )0x40010006L) #define DBG_RIPEXCEPTION ((u32 )0x40010007L) #define DBG_CONTROL_BREAK ((u32 )0x40010008L) #define DBG_COMMAND_EXCEPTION ((u32 )0x40010009L) #define DBG_PRINTEXCEPTION_WIDE_C ((u32 )0x4001000AL) #define STATUS_GUARD_PAGE_VIOLATION ((u32 )0x80000001L) #define STATUS_DATATYPE_MISALIGNMENT ((u32 )0x80000002L) #define STATUS_BREAKPOINT ((u32 )0x80000003L) #define STATUS_SINGLE_STEP ((u32 )0x80000004L) #define STATUS_LONGJUMP ((u32 )0x80000026L) #define STATUS_UNWIND_CONSOLIDATE ((u32 )0x80000029L) #define DBG_EXCEPTION_NOT_HANDLED ((u32 )0x80010001L) #define STATUS_ACCESS_VIOLATION ((u32 )0xC0000005L) #define STATUS_IN_PAGE_ERROR ((u32 )0xC0000006L) #define STATUS_INVALID_HANDLE ((u32 )0xC0000008L) #define STATUS_INVALID_PARAMETER ((u32 )0xC000000DL) #define STATUS_NO_MEMORY ((u32 )0xC0000017L) #define STATUS_ILLEGAL_INSTRUCTION ((u32 )0xC000001DL) #define STATUS_NONCONTINUABLE_EXCEPTION ((u32 )0xC0000025L) #define STATUS_INVALID_DISPOSITION ((u32 )0xC0000026L) #define STATUS_ARRAY_BOUNDS_EXCEEDED ((u32 )0xC000008CL) #define STATUS_FLOAT_DENORMAL_OPERAND ((u32 )0xC000008DL) #define STATUS_FLOAT_DIVIDE_BY_ZERO ((u32 )0xC000008EL) #define STATUS_FLOAT_INEXACT_RESULT ((u32 )0xC000008FL) #define STATUS_FLOAT_INVALID_OPERATION ((u32 )0xC0000090L) #define STATUS_FLOAT_OVERFLOW ((u32 )0xC0000091L) #define STATUS_FLOAT_STACK_CHECK ((u32 )0xC0000092L) #define STATUS_FLOAT_UNDERFLOW ((u32 )0xC0000093L) #define STATUS_INTEGER_DIVIDE_BY_ZERO ((u32 )0xC0000094L) #define STATUS_INTEGER_OVERFLOW ((u32 )0xC0000095L) #define STATUS_PRIVILEGED_INSTRUCTION ((u32 )0xC0000096L) #define STATUS_STACK_OVERFLOW ((u32 )0xC00000FDL) #define STATUS_DLL_NOT_FOUND ((u32 )0xC0000135L) #define STATUS_ORDINAL_NOT_FOUND ((u32 )0xC0000138L) #define STATUS_ENTRYPOINT_NOT_FOUND ((u32 )0xC0000139L) #define STATUS_CONTROL_C_EXIT ((u32 )0xC000013AL) #define STATUS_DLL_INIT_FAILED ((u32 )0xC0000142L) #define STATUS_CONTROL_STACK_VIOLATION ((u32 )0xC00001B2L) #define STATUS_FLOAT_MULTIPLE_FAULTS ((u32 )0xC00002B4L) #define STATUS_FLOAT_MULTIPLE_TRAPS ((u32 )0xC00002B5L) #define STATUS_REG_NAT_CONSUMPTION ((u32 )0xC00002C9L) #define STATUS_HEAP_CORRUPTION ((u32 )0xC0000374L) #define STATUS_STACK_BUFFER_OVERRUN ((u32 )0xC0000409L) #define STATUS_INVALID_CRUNTIME_PARAMETER ((u32 )0xC0000417L) #define STATUS_ASSERTION_FAILURE ((u32 )0xC0000420L) #define STATUS_ENCLAVE_VIOLATION ((u32 )0xC00004A2L) #define STATUS_INTERRUPTED ((u32 )0xC0000515L) #define STATUS_THREAD_NOT_RUNNING ((u32 )0xC0000516L) #define STATUS_ALREADY_REGISTERED ((u32 )0xC0000718L) /* compatibility macros */ #define STILL_ACTIVE STATUS_PENDING #define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION #define EXCEPTION_DATATYPE_MISALIGNMENT STATUS_DATATYPE_MISALIGNMENT #define EXCEPTION_BREAKPOINT STATUS_BREAKPOINT #define EXCEPTION_SINGLE_STEP STATUS_SINGLE_STEP #define EXCEPTION_ARRAY_BOUNDS_EXCEEDED STATUS_ARRAY_BOUNDS_EXCEEDED #define EXCEPTION_FLT_DENORMAL_OPERAND STATUS_FLOAT_DENORMAL_OPERAND #define EXCEPTION_FLT_DIVIDE_BY_ZERO STATUS_FLOAT_DIVIDE_BY_ZERO #define EXCEPTION_FLT_INEXACT_RESULT STATUS_FLOAT_INEXACT_RESULT #define EXCEPTION_FLT_INVALID_OPERATION STATUS_FLOAT_INVALID_OPERATION #define EXCEPTION_FLT_OVERFLOW STATUS_FLOAT_OVERFLOW #define EXCEPTION_FLT_STACK_CHECK STATUS_FLOAT_STACK_CHECK #define EXCEPTION_FLT_UNDERFLOW STATUS_FLOAT_UNDERFLOW #define EXCEPTION_INT_DIVIDE_BY_ZERO STATUS_INTEGER_DIVIDE_BY_ZERO #define EXCEPTION_INT_OVERFLOW STATUS_INTEGER_OVERFLOW #define EXCEPTION_PRIV_INSTRUCTION STATUS_PRIVILEGED_INSTRUCTION #define EXCEPTION_IN_PAGE_ERROR STATUS_IN_PAGE_ERROR #define EXCEPTION_ILLEGAL_INSTRUCTION STATUS_ILLEGAL_INSTRUCTION #define EXCEPTION_NONCONTINUABLE_EXCEPTION STATUS_NONCONTINUABLE_EXCEPTION #define EXCEPTION_STACK_OVERFLOW STATUS_STACK_OVERFLOW #define EXCEPTION_INVALID_DISPOSITION STATUS_INVALID_DISPOSITION #define EXCEPTION_GUARD_PAGE STATUS_GUARD_PAGE_VIOLATION #define EXCEPTION_INVALID_HANDLE STATUS_INVALID_HANDLE #define EXCEPTION_POSSIBLE_DEADLOCK STATUS_POSSIBLE_DEADLOCK #define CONTROL_C_EXIT STATUS_CONTROL_C_EXIT // // Debug APIs // #define EXCEPTION_DEBUG_EVENT 1 #define CREATE_THREAD_DEBUG_EVENT 2 #define CREATE_PROCESS_DEBUG_EVENT 3 #define EXIT_THREAD_DEBUG_EVENT 4 #define EXIT_PROCESS_DEBUG_EVENT 5 #define LOAD_DLL_DEBUG_EVENT 6 #define UNLOAD_DLL_DEBUG_EVENT 7 #define OUTPUT_DEBUG_STRING_EVENT 8 #define RIP_EVENT 9 typedef u32 (*PTHREAD_START_ROUTINE)(void* lpThreadParameter); typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE; #define EXCEPTION_MAXIMUM_PARAMETERS 15 // maximum number of exception parameters // // Exception record definition. // typedef struct _EXCEPTION_RECORD { u32 ExceptionCode; u32 ExceptionFlags; struct _EXCEPTION_RECORD *ExceptionRecord; void* ExceptionAddress; u32 NumberParameters; u64* ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; } EXCEPTION_RECORD; typedef EXCEPTION_RECORD *PEXCEPTION_RECORD; typedef struct _EXCEPTION_DEBUG_INFO { EXCEPTION_RECORD ExceptionRecord; u32 dwFirstChance; } EXCEPTION_DEBUG_INFO, *LPEXCEPTION_DEBUG_INFO; typedef struct _CREATE_THREAD_DEBUG_INFO { void* hThread; void* lpThreadLocalBase; LPTHREAD_START_ROUTINE lpStartAddress; } CREATE_THREAD_DEBUG_INFO, *LPCREATE_THREAD_DEBUG_INFO; typedef struct _CREATE_PROCESS_DEBUG_INFO { void* hFile; void* hProcess; void* hThread; void* lpBaseOfImage; u32 dwDebugInfoFileOffset; u32 nDebugInfoSize; void* lpThreadLocalBase; LPTHREAD_START_ROUTINE lpStartAddress; void* lpImageName; u16 fUnicode; } CREATE_PROCESS_DEBUG_INFO, *LPCREATE_PROCESS_DEBUG_INFO; typedef struct _EXIT_THREAD_DEBUG_INFO { u32 dwExitCode; } EXIT_THREAD_DEBUG_INFO, *LPEXIT_THREAD_DEBUG_INFO; typedef struct _EXIT_PROCESS_DEBUG_INFO { u32 dwExitCode; } EXIT_PROCESS_DEBUG_INFO, *LPEXIT_PROCESS_DEBUG_INFO; typedef struct _LOAD_DLL_DEBUG_INFO { void* hFile; void* lpBaseOfDll; u32 dwDebugInfoFileOffset; u32 nDebugInfoSize; void* lpImageName; u16 fUnicode; } LOAD_DLL_DEBUG_INFO, *LPLOAD_DLL_DEBUG_INFO; typedef struct _UNLOAD_DLL_DEBUG_INFO { void* lpBaseOfDll; } UNLOAD_DLL_DEBUG_INFO, *LPUNLOAD_DLL_DEBUG_INFO; typedef struct _OUTPUT_DEBUG_STRING_INFO { char* lpDebugStringData; u16 fUnicode; u16 nDebugStringLength; } OUTPUT_DEBUG_STRING_INFO, *LPOUTPUT_DEBUG_STRING_INFO; typedef struct _RIP_INFO { u32 dwError; u32 dwType; } RIP_INFO, *LPRIP_INFO; typedef struct _DEBUG_EVENT { u32 dwDebugEventCode; u32 dwProcessId; u32 dwThreadId; union { EXCEPTION_DEBUG_INFO Exception; CREATE_THREAD_DEBUG_INFO CreateThread; CREATE_PROCESS_DEBUG_INFO CreateProcessInfo; EXIT_THREAD_DEBUG_INFO ExitThread; EXIT_PROCESS_DEBUG_INFO ExitProcess; LOAD_DLL_DEBUG_INFO LoadDll; UNLOAD_DLL_DEBUG_INFO UnloadDll; OUTPUT_DEBUG_STRING_INFO DebugString; RIP_INFO RipInfo; } u; } DEBUG_EVENT, *LPDEBUG_EVENT; extern i32 WaitForDebugEventEx(LPDEBUG_EVENT lpDebugEvent, u32 dwMilliseconds); typedef struct _PROCESS_INFORMATION { void* hProcess; void* hThread; u32 dwProcessId; u32 dwThreadId; } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION; #define PAGE_NOACCESS 0x01 #define PAGE_READONLY 0x02 #define PAGE_READWRITE 0x04 #define PAGE_WRITECOPY 0x08 #define PAGE_EXECUTE 0x10 #define PAGE_EXECUTE_READ 0x20 #define PAGE_EXECUTE_READWRITE 0x40 #define PAGE_EXECUTE_WRITECOPY 0x80 #define PAGE_GUARD 0x100 #define PAGE_NOCACHE 0x200 #define PAGE_WRITECOMBINE 0x400 #define PAGE_GRAPHICS_NOACCESS 0x0800 #define PAGE_GRAPHICS_READONLY 0x1000 #define PAGE_GRAPHICS_READWRITE 0x2000 #define PAGE_GRAPHICS_EXECUTE 0x4000 #define PAGE_GRAPHICS_EXECUTE_READ 0x8000 #define PAGE_GRAPHICS_EXECUTE_READWRITE 0x10000 #define PAGE_GRAPHICS_COHERENT 0x20000 #define PAGE_GRAPHICS_NOCACHE 0x40000 #define PAGE_ENCLAVE_THREAD_CONTROL 0x80000000 #define PAGE_REVERT_TO_FILE_MAP 0x80000000 #define PAGE_TARGETS_NO_UPDATE 0x40000000 #define PAGE_TARGETS_INVALID 0x40000000 #define PAGE_ENCLAVE_UNVALIDATED 0x20000000 #define PAGE_ENCLAVE_MASK 0x10000000 #define PAGE_ENCLAVE_DECOMMIT (PAGE_ENCLAVE_MASK | 0) #define PAGE_ENCLAVE_SS_FIRST (PAGE_ENCLAVE_MASK | 1) #define PAGE_ENCLAVE_SS_REST (PAGE_ENCLAVE_MASK | 2) #define MEM_COMMIT 0x00001000 #define MEM_RESERVE 0x00002000 #define MEM_REPLACE_PLACEHOLDER 0x00004000 #define MEM_RESERVE_PLACEHOLDER 0x00040000 #define MEM_RESET 0x00080000 #define MEM_TOP_DOWN 0x00100000 #define MEM_WRITE_WATCH 0x00200000 #define MEM_PHYSICAL 0x00400000 #define MEM_ROTATE 0x00800000 #define MEM_DIFFERENT_IMAGE_BASE_OK 0x00800000 #define MEM_RESET_UNDO 0x01000000 #define MEM_LARGE_PAGES 0x20000000 #define MEM_4MB_PAGES 0x80000000 #define MEM_64K_PAGES (MEM_LARGE_PAGES | MEM_PHYSICAL) #define MEM_UNMAP_WITH_TRANSIENT_BOOST 0x00000001 #define MEM_COALESCE_PLACEHOLDERS 0x00000001 #define MEM_PRESERVE_PLACEHOLDER 0x00000002 #define MEM_DECOMMIT 0x00004000 #define MEM_RELEASE 0x00008000 #define MEM_FREE 0x00010000 #define MEM_EXTENDED_PARAMETER_GRAPHICS 0x00000001 #define MEM_EXTENDED_PARAMETER_NONPAGED 0x00000002 #define MEM_EXTENDED_PARAMETER_ZERO_PAGES_OPTIONAL 0x00000004 #define MEM_EXTENDED_PARAMETER_NONPAGED_LARGE 0x00000008 #define MEM_EXTENDED_PARAMETER_NONPAGED_HUGE 0x00000010 #define MEM_EXTENDED_PARAMETER_SOFT_FAULT_PAGES 0x00000020 #define MEM_EXTENDED_PARAMETER_EC_CODE 0x00000040 #define MEM_EXTENDED_PARAMETER_NUMA_NODE_MANDATORY MINLONG64 extern void* VirtualAlloc(void* lpAddress, size_t dwSize, u32 flAllocationType, u32 flProtect); extern i32 VirtualFree(void* lpAddress, size_t dwSize, u32 dwFreeType); #define STD_INPUT_HANDLE ((u32)-10) #define STD_OUTPUT_HANDLE ((u32)-11) #define STD_ERROR_HANDLE ((u32)-12) extern void* GetStdHandle(u32 nStdHandle); typedef struct _STARTUPINFOA { u32 cb; i8* lpReserved; i8* lpDesktop; i8* lpTitle; u32 dwX; u32 dwY; u32 dwXSize; u32 dwYSize; u32 dwXCountChars; u32 dwYCountChars; u32 dwFillAttribute; u32 dwFlags; u16 wShowWindow; u16 cbReserved2; u8* lpReserved2; void* hStdInput; void* hStdOutput; void* hStdError; } STARTUPINFOA, *LPSTARTUPINFOA; typedef struct _SECURITY_ATTRIBUTES { u32 nLength; void* lpSecurityDescriptor; i32 bInheritHandle; } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; // // Process dwCreationFlag values // #define DEBUG_PROCESS 0x00000001 #define DEBUG_ONLY_THIS_PROCESS 0x00000002 #define CREATE_SUSPENDED 0x00000004 #define DETACHED_PROCESS 0x00000008 #define CREATE_NEW_CONSOLE 0x00000010 #define NORMAL_PRIORITY_CLASS 0x00000020 #define IDLE_PRIORITY_CLASS 0x00000040 #define HIGH_PRIORITY_CLASS 0x00000080 #define REALTIME_PRIORITY_CLASS 0x00000100 #define CREATE_NEW_PROCESS_GROUP 0x00000200 #define CREATE_UNICODE_ENVIRONMENT 0x00000400 #define CREATE_SEPARATE_WOW_VDM 0x00000800 #define CREATE_SHARED_WOW_VDM 0x00001000 #define CREATE_FORCEDOS 0x00002000 #define BELOW_NORMAL_PRIORITY_CLASS 0x00004000 #define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000 #define INHERIT_PARENT_AFFINITY 0x00010000 #define INHERIT_CALLER_PRIORITY 0x00020000 // Deprecated #define CREATE_PROTECTED_PROCESS 0x00040000 #define EXTENDED_STARTUPINFO_PRESENT 0x00080000 #define PROCESS_MODE_BACKGROUND_BEGIN 0x00100000 #define PROCESS_MODE_BACKGROUND_END 0x00200000 #define CREATE_SECURE_PROCESS 0x00400000 #define CREATE_BREAKAWAY_FROM_JOB 0x01000000 #define CREATE_PRESERVE_CODE_AUTHZ_LEVEL 0x02000000 #define CREATE_DEFAULT_ERROR_MODE 0x04000000 #define CREATE_NO_WINDOW 0x08000000 #define PROFILE_USER 0x10000000 #define PROFILE_KERNEL 0x20000000 #define PROFILE_SERVER 0x40000000 #define CREATE_IGNORE_SYSTEM_DEFAULT 0x80000000 // // Thread dwCreationFlag values // //#define CREATE_SUSPENDED 0x00000004 extern i32 CreateProcessA( const i8* lpApplicationName, i8* lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, i32 bInheritHandles, u32 dwCreationFlags, void* lpEnvironment, const i8* lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ); extern i32 TerminateProcess(void* hProcess, u32 uExitCode); // // Input Mode flags: // #define ENABLE_PROCESSED_INPUT 0x0001 #define ENABLE_LINE_INPUT 0x0002 #define ENABLE_ECHO_INPUT 0x0004 #define ENABLE_WINDOW_INPUT 0x0008 #define ENABLE_MOUSE_INPUT 0x0010 #define ENABLE_INSERT_MODE 0x0020 #define ENABLE_QUICK_EDIT_MODE 0x0040 #define ENABLE_EXTENDED_FLAGS 0x0080 #define ENABLE_AUTO_POSITION 0x0100 #define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200 // // Output Mode flags: // #define ENABLE_PROCESSED_OUTPUT 0x0001 #define ENABLE_WRAP_AT_EOL_OUTPUT 0x0002 #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 #define DISABLE_NEWLINE_AUTO_RETURN 0x0008 #define ENABLE_LVB_GRID_WORLDWIDE 0x0010 extern i32 SetConsoleMode(void* hConsoleHandle, u32 dwMode); typedef struct _CONSOLE_READCONSOLE_CONTROL { u32 nLength; u32 nInitialChars; u32 dwCtrlWakeupMask; u32 dwControlKeyState; } CONSOLE_READCONSOLE_CONTROL, *PCONSOLE_READCONSOLE_CONTROL; extern i32 ReadConsoleA( void* hConsoleInput, void* lpBuffer, u32 nNumberOfCharsToRead, u32* lpNumberOfCharsRead, PCONSOLE_READCONSOLE_CONTROL pInputControl ); extern i32 WriteConsoleA( void* hConsoleOutput, const void* lpBuffer, u32 nNumberOfCharsToWrite, u32* lpNumberOfCharsWritten, void* lpReserved ); // ======================== // ====== !windows.h ====== // ======================== extern u32 _fltused = TRUE; u8 is_open = TRUE; u8 process_commands = TRUE; void* h_input = NULL; void* h_output = NULL; DEBUG_EVENT dbg_event; PROCESS_INFORMATION proc_info = { 0 }; u32 continue_status = DBG_EXCEPTION_NOT_HANDLED; // TODO: Perfect hashing table ? u8* string_stack_base = NULL; u8* string_stack_current = NULL; void dbg_loop() { while(is_open) { WaitForDebugEventEx(&dbg_event, INFINITE); continue_status = DBG_EXCEPTION_NOT_HANDLED; switch (dbg_event.dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: handle_create_process(); break; case CREATE_THREAD_DEBUG_EVENT: handle_create_thread(); break; case EXCEPTION_DEBUG_EVENT: handle_exception(); break; case EXIT_PROCESS_DEBUG_EVENT: handle_exit_process(); break; case EXIT_THREAD_DEBUG_EVENT: handle_exit_thread(); break; case LOAD_DLL_DEBUG_EVENT: handle_load_dll(); break; case OUTPUT_DEBUG_STRING_EVENT: handle_output_debug_string(); break; case RIP_EVENT: handle_rip(); break; case UNLOAD_DLL_DEBUG_EVENT: handle_unload_dll(); break; } process_commands = TRUE; while(process_commands) { const char write_buffer[] = "> "; u32 c_written = 0U; WriteConsoleA(h_output, write_buffer, sizeof(write_buffer), &c_written, NULL); char input_buffer[64] = { 0 }; u32 input_size = 0U; ReadConsoleA(h_input, input_buffer, sizeof(input_buffer), &input_size, NULL); interpreter(input_buffer, input_size); } } } int mainCRTStartup() { string_stack_current = string_stack_base = VirtualAlloc(NULL, 4096U * 64U, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); STARTUPINFOA startup_info = { 0 }; startup_info.cb = sizeof(startup_info); i32 ret = CreateProcessA( NULL, (i8*)"./test.exe", NULL, NULL, FALSE, DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &startup_info, &proc_info ); if (ret == 0) { print("%s\n", "Failed to create process"); return 0; } h_output = GetStdHandle(STD_OUTPUT_HANDLE); if (h_output == NULL) { TerminateProcess(proc_info.hProcess, 1U); return 1U; } h_input = GetStdHandle(STD_INPUT_HANDLE); if (h_input == NULL) { TerminateProcess(proc_info.hProcess, 1U); return 1U; } u32 console_mode = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; SetConsoleMode(h_input, console_mode); dbg_loop(); TerminateProcess(proc_info.hProcess, 0U); return 0; }