diff options
| author | Quentin LADEVIE <qladevie@wanadev.fr> | 2024-09-03 11:15:10 +0200 |
|---|---|---|
| committer | Quentin LADEVIE <qladevie@wanadev.fr> | 2024-09-03 11:15:10 +0200 |
| commit | e61b27e6c699ae175d7704ddaaee0d39b6d14382 (patch) | |
| tree | 1b227cafa0f86681afddeb8e25d4d072318bb9fc | |
| parent | 41d163a8a9be2f6d94e42157ad695fbe2cd000ae (diff) | |
Log dll name on loading
Print output debug string
Refactored code
Improved print
Add a function to read memory from the deubgged process
Fixed a read out of bounds
| -rw-r--r-- | src/events.c | 121 | ||||
| -rw-r--r-- | src/main.c | 392 | ||||
| -rw-r--r-- | src/parser.c | 249 | ||||
| -rw-r--r-- | src/test.c | 2 | ||||
| -rw-r--r-- | src/utils.c | 54 |
5 files changed, 486 insertions, 332 deletions
diff --git a/src/events.c b/src/events.c new file mode 100644 index 0000000..ea80e58 --- /dev/null +++ b/src/events.c @@ -0,0 +1,121 @@ +void handle_create_process() { + print("%s\n", "CreateProcessDebugEvent"); +} + +void handle_create_thread() { + print("%s\n", "CreateThreadDebugEvent"); +} + +void handle_exception() { + print("%s : ", "ExceptionDebugEvent"); + + if (dbg_event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP && expect_single_step) { + print("%s\n", "Single Step"); + continue_status = DBG_CONTINUE; + expect_single_step = FALSE; + } else if (dbg_event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { + print("%s\n", "Breakpoint"); + continue_status = DBG_CONTINUE; + } else { + print("%u\n", dbg_event.u.Exception.ExceptionRecord.ExceptionCode); + } +} + +void handle_exit_process() { + print("%s\n", "ExitProcessDebugEvent"); + TerminateProcess(NULL, 0U); +} + +void handle_exit_thread() { + print("%s\n", "ExitThreadDebugEvent"); +} + +void handle_load_dll() { + LOAD_DLL_DEBUG_INFO dll_info = dbg_event.u.LoadDll; + const void* dll_name_addr = dll_info.lpImageName; + const void* dll_base_addr = dll_info.lpBaseOfDll; + if (dll_name_addr == NULL) { + print("%s\n", "Loading DLL : error read dll name"); + return; + } + + u8* addr = NULL; + if (!read_memory(dll_name_addr, (void*)&addr, 8U)) { + print("%s\n", "Loading DLL : error reading dll name"); + return; + } + + u8 dll_name[1024U] = { 0U }; + if (!read_memory((const void*)addr, dll_name, sizeof(dll_name))) { + print("Cannot read dll name from proc memory\n"); + } + + if (dll_info.fUnicode) { + u8 dll_name_ansi[1024U] = { 0U }; + WideCharToMultiByte( + CP_ACP, + 0, + (wchar_t*)dll_name, + -1, + (char*)dll_name_ansi, + sizeof(dll_name_ansi), + NULL, + NULL + ); + StringCchCopyA((char*)dll_name, sizeof(dll_name), (const char*)dll_name_ansi); + } + print("%s%s\n", "Loading DLL : ", (char*)dll_name); + + IMAGE_DOS_HEADER dos_header = { 0U }; + if (!read_memory(dll_base_addr, (void*)&dos_header, sizeof(dos_header))) { + print("Cannot read DOS header for module %s at address %x\n", dll_name, dll_base_addr); + } + + IMAGE_NT_HEADERS64 nt_header = { 0U }; + if (!read_memory((const void*)((u64)dll_base_addr + dos_header.e_lfanew), (void*)&nt_header, sizeof(nt_header))) { + print("Cannot read NT header for module %s at address %x\n", dll_name, dll_base_addr); + } + + IMAGE_DATA_DIRECTORY export_table = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + IMAGE_EXPORT_DIRECTORY export_dir = { 0U }; + + if (!read_memory((const void*)((u64)dll_base_addr + (u64)export_table.VirtualAddress), (void*)&export_dir, export_table.Size)) { + print("Cannot read export table for module at address %x\n", dll_base_addr); + } +} + +void handle_unload_dll() { + print("%s\n", "UnloadDLLDebugEvent"); +} + +void handle_output_debug_string() { + OUTPUT_DEBUG_STRING_INFO dbg_str_event = dbg_event.u.DebugString; + char* str_addr = dbg_str_event.lpDebugStringData; + size_t str_size = (size_t)dbg_str_event.nDebugStringLength; + // assert(str_size > 1024U); + u8 dbg_str[1024U] = { 0U }; + if (read_memory(str_addr, dbg_str, str_size)) { + print("%s\n", "OutputDebugStringDebugEvent : error read debug string"); + return; + } + if (dbg_str_event.fUnicode) { + u8 ansi_str[1024U] = { 0U }; + WideCharToMultiByte( + CP_ACP, + 0, + (wchar_t*)dbg_str, + -1, + (char*)ansi_str, + sizeof(ansi_str), + NULL, + NULL + ); + print("%s%s\n", "OutputDebugStringDebugEvent : ", ansi_str); + } else { + print("%s%s\n", "OutputDebugStringDebugEvent : ", dbg_str); + } +} + +void handle_rip() { + print("%s\n", "RIPEvent"); +} @@ -1,4 +1,5 @@ #include <Windows.h> +#include <intrin.h> #include <strsafe.h> #include "types.h" @@ -6,288 +7,101 @@ #include "utils.c" static HANDLE h_input = NULL; +static HANDLE h_output = NULL; static u8 is_open = TRUE; static u8 process_commands = TRUE; static u8 expect_single_step = FALSE; static DWORD continue_status = DBG_EXCEPTION_NOT_HANDLED; static DEBUG_EVENT dbg_event; -static PROCESS_INFORMATION proc_info; +static PROCESS_INFORMATION proc_info = { 0 }; -enum TOKEN_TYPE { - // Commands - TOKEN_CONTINUE, - TOKEN_PRINT_REG, - TOKEN_STEP_INTO, - TOKEN_DUMP_MEMORY, - TOKEN_QUIT, - - // Primaries - TOKEN_DECIMAL_NUMBER, - TOKEN_HEXADECIMAL_NUMBER, - - TOKEN_UNKNOWN, +struct module { + u8 fix_compilation; }; -struct token { - enum TOKEN_TYPE type; - const char* lexeme; - u8 size; -}; +static struct module mods[64U] = { 0U }; +static u64 mods_list = 0U; -struct command { - const char* start; - u8 size; -}; +u8 add_mod() { + u64 free_mods = ~mods_list; + assert(!free_mods); + u8 mod_index = (u8)(free_mods >> (_lzcnt_u64(free_mods) + 1U)); + // struct module* mod = &mods[mod_index]; -struct ast_node { - struct token* token; - struct ast_node* left; - struct ast_node* right; -}; -static struct command commands[] = { - { .start = "g", .size = 1 }, - { .start = "r", .size = 1 }, - { .start = "t", .size = 1 }, - { .start = "db", .size = 2 }, - { .start = "q", .size = 1 }, -}; -_Static_assert((sizeof(commands) / sizeof(commands[0])) == TOKEN_QUIT + 1, "Missing commands"); + return mod_index; +}; -u8 is_end(char c) { - return c == '\0'; +void remove_mod(u8 mod_index) { + mods_list ^= (u64)(0x1 << (((i8)mod_index) - 1U)); } -u8 is_alpha(char c) { - return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); -} +/* Read debugged process memory at address */ +u8 read_memory(const void* addr, void* buffer, size_t size) { + size_t b_read = 0U; + HRESULT hr = ReadProcessMemory(proc_info.hProcess, addr, buffer, size, &b_read); -u8 is_decimal_digit(char c) { - return '0' <= c && c <= '9'; + return hr > 0 && b_read == size; } -u8 is_hexadecimal_digit(char c) { - return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); -} - -void lexer(const char* str_cmd, size_t str_cmd_len, struct token* tokens) { - const char* cur = str_cmd; - struct token* cur_token = tokens; - str_cmd_len = 0; - - while(*cur != '\0') { - cur_token->type = TOKEN_UNKNOWN; - if(*cur == '0' && cur[1] == 'x') { - const char* start = cur; - cur += 2; +#include "parser.c" +#include "events.c" - while(is_hexadecimal_digit(*cur) && !is_end(*cur)) { - cur++; - } - - cur_token->lexeme = start; - cur_token->type = TOKEN_HEXADECIMAL_NUMBER; - cur_token->size = (u8)(cur - start); - cur_token++; - } else if(is_decimal_digit(*cur)) { - const char* start = cur; - cur++; - - while(is_decimal_digit(*cur) && !is_end(*cur)) { - cur++; - } - - cur_token->lexeme = start; - cur_token->type = TOKEN_DECIMAL_NUMBER; - cur_token->size = (u8)(cur - start); - cur_token++; - } else if(is_alpha(*cur)) { - const char* start = cur; - cur++; - while(is_alpha(*cur) && !is_end(*cur)) { - cur++; - } +void dbg_loop() { + while(is_open) { + WaitForDebugEventEx(&dbg_event, INFINITE); - cur_token->lexeme = start; - cur_token->size = (u8)(cur - start); + continue_status = DBG_EXCEPTION_NOT_HANDLED; - for(int i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) { - struct command cur_cmd = commands[i]; - if (CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, cur_cmd.start, cur_cmd.size, cur_token->lexeme, cur_token->size) == CSTR_EQUAL) { - cur_token->type = i; - cur_token++; - break; - } - } - } else { - cur++; + 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; } - } -} - -struct ast_node* parse_primary(struct token* tokens, struct ast_node* nodes) { - struct ast_node* cur_node = &nodes[0]; - struct token* cur_token = &tokens[0]; - if (cur_token->type == TOKEN_HEXADECIMAL_NUMBER || - cur_token->type == TOKEN_DECIMAL_NUMBER) { - cur_node->token = cur_token; - cur_node->left = NULL; - cur_node->right = NULL; - return cur_node; - } else { - print("Expecting a primary token\n"); - return NULL; - } -} - -struct ast_node* parse_command(struct token* tokens, struct ast_node* nodes) { - struct ast_node* cur_node = &nodes[0]; - struct token* cur_token = &tokens[0]; - switch(cur_token->type) { - case TOKEN_CONTINUE: - tokens++; - print("TOKEN_CONTINUE\n"); - cur_node->token = cur_token; - cur_node->left = NULL; - cur_node->right = NULL; - return cur_node; - case TOKEN_PRINT_REG: - tokens++; - print("TOKEN_PRINT_REG\n"); - cur_node->token = cur_token; - cur_node->left = NULL; - cur_node->right = NULL; - return cur_node; - case TOKEN_STEP_INTO: - tokens++; - print("TOKEN_STEP_INTO\n"); - cur_node->token = cur_token; - cur_node->left = NULL; - cur_node->right = NULL; - return cur_node; - case TOKEN_DUMP_MEMORY: - tokens++; - print("TOKEN_DUMP_MEMORY\n"); - cur_node->token = cur_token; - cur_node->left = NULL; - cur_node->right = parse_primary(tokens, ++nodes); - return cur_node; - case TOKEN_QUIT: - tokens++; - print("TOKEN_QUIT\n"); - cur_node->token = cur_token; - cur_node->left = NULL; - cur_node->right = NULL; - return cur_node; - default: - print("%s must be a command\n", cur_token->lexeme); - return NULL; - } -} - -u64 eval_number(const struct ast_node* node) { - if (node->token->type == TOKEN_DECIMAL_NUMBER || - node->token->type == TOKEN_HEXADECIMAL_NUMBER) { - return atou64(node->token->lexeme, node->token->size); - } - return ~0U; -} -void run(struct ast_node* root) { - struct ast_node cur_node = root[0]; - CONTEXT ctx = { - .ContextFlags = CONTEXT_ALL, - }; - HANDLE h_thread = OpenThread( - THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, - FALSE, - dbg_event.dwThreadId - ); - GetThreadContext(h_thread, &ctx); - - if (cur_node.token->type == TOKEN_CONTINUE) { - ContinueDebugEvent( - dbg_event.dwProcessId, - dbg_event.dwThreadId, - continue_status - ); - process_commands = FALSE; - } else if (cur_node.token->type == TOKEN_PRINT_REG) { - print("RIP : %x\n", ctx.Rip); - print("RAX : %x\n", ctx.Rax); - print("RCX : %x\n", ctx.Rcx); - print("RDX : %x\n", ctx.Rdx); - print("RBX : %x\n", ctx.Rbx); - print("RSP : %x\n", ctx.Rsp); - print("RBP : %x\n", ctx.Rbp); - print("RSI : %x\n", ctx.Rsi); - print("RDI : %x\n", ctx.Rdi); process_commands = TRUE; - } else if (cur_node.token->type == TOKEN_STEP_INTO) { - ctx.EFlags |= 0x100; // TRAP_FLAG - if(SetThreadContext(h_thread, &ctx) == 0) { - __debugbreak(); - } - ContinueDebugEvent( - dbg_event.dwProcessId, - dbg_event.dwThreadId, - continue_status - ); - expect_single_step = TRUE; - process_commands = FALSE; - } else if (cur_node.token->type == TOKEN_QUIT) { - is_open = FALSE; - process_commands = FALSE; - } else if (cur_node.token->type == TOKEN_DUMP_MEMORY) { - u64 addr = eval_number(cur_node.right); - u8 buf[16U] = { 0 }; - size_t b_read = 0U; - - HRESULT hr = ReadProcessMemory( - proc_info.hProcess, - (void*)addr, - buf, - sizeof(buf), - &b_read - ); + while(process_commands) { + const char write_buffer[] = "> "; + DWORD c_written = 0U; + WriteConsole(h_output, write_buffer, sizeof(write_buffer), &c_written, NULL); + char input_buffer[64] = { 0 }; + DWORD input_size = 0U; + ReadConsole(h_input, input_buffer, sizeof(input_buffer), &input_size, NULL); - if (hr > 0) { - print("%b %b %b %b %b %b %b %b %b %b %b %b %b %b %b %b\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); - } else { - print("Unable to read memory at this address\n"); + interpreter(input_buffer, input_size); } - - } else { - print("Command unknown\n"); - process_commands = TRUE; - } - - CloseHandle(h_thread); -} - -u8 interpreter(const char* str_cmd, size_t str_cmd_len) { - struct token tokens[64U]; - struct ast_node nodes[64U]; - - lexer(str_cmd, str_cmd_len, tokens); - - struct ast_node* root = parse_command(tokens, nodes); - - if(root == NULL) { - print("Ill formed command\n"); - return FALSE; } - - run(root); - return TRUE; } int mainCRTStartup() { - STARTUPINFOW startup_info = { - .cb = sizeof(startup_info), - }; + STARTUPINFOW startup_info = { 0 }; + startup_info.cb = sizeof(startup_info); BOOL ret = CreateProcessW( NULL, @@ -307,6 +121,12 @@ int mainCRTStartup() { 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); @@ -315,75 +135,7 @@ int mainCRTStartup() { DWORD console_mode = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; SetConsoleMode(h_input, console_mode); - while(is_open) { - WaitForDebugEventEx(&dbg_event, INFINITE); - - continue_status = DBG_EXCEPTION_NOT_HANDLED; - - switch (dbg_event.dwDebugEventCode) { - case CREATE_PROCESS_DEBUG_EVENT: { - OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, FALSE, dbg_event.dwThreadId); - print("%s\n", "CreateProcessDebugEvent"); - break; - } - case CREATE_THREAD_DEBUG_EVENT: { - print("%s\n", "CreateThreadDebugEvent"); - break; - } - case EXCEPTION_DEBUG_EVENT: { - print("%s : ", "ExceptionDebugEvent"); - - if (dbg_event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP && expect_single_step) { - print("%s\n", "Single Step"); - continue_status = DBG_CONTINUE; - expect_single_step = FALSE; - } else if (dbg_event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { - print("%s\n", "Breakpoint"); - continue_status = DBG_CONTINUE; - } else { - print("%u\n", dbg_event.u.Exception.ExceptionRecord.ExceptionCode); - } - - break; - } - case EXIT_PROCESS_DEBUG_EVENT: { - print("%s\n", "ExitProcessDebugEvent"); - TerminateProcess(NULL, 0U); - return 0; - break; - } - case EXIT_THREAD_DEBUG_EVENT: { - print("%s\n", "ExitThreadDebugEvent"); - break; - } - case LOAD_DLL_DEBUG_EVENT: { - // print("%s%s\n", "Loading DLL : ", (char*)dbg_event.u.LoadDll.lpImageName); - print("%s%s\n", "Loading DLL : ", NULL); - break; - } - case OUTPUT_DEBUG_STRING_EVENT: { - print("%s\n", "OutputDebugStringDebugEvent"); - break; - } - case RIP_EVENT: { - print("%s\n", "RIPEvent"); - break; - } - case UNLOAD_DLL_DEBUG_EVENT: { - print("%s\n", "UnloadDLLDebugEvent"); - break; - } - } - - process_commands = TRUE; - while(process_commands) { - char input_buffer[16]; - DWORD input_size = 0U; - ReadConsole(h_input, input_buffer, sizeof(input_buffer), &input_size, NULL); - - interpreter(input_buffer, input_size); - } - } + dbg_loop(); TerminateProcess(proc_info.hProcess, 0U); return 0; diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..c42c2cc --- /dev/null +++ b/src/parser.c @@ -0,0 +1,249 @@ +enum TOKEN_TYPE { + // Commands + TOKEN_CONTINUE, + TOKEN_PRINT_REG, + TOKEN_STEP_INTO, + TOKEN_DUMP_MEMORY, + TOKEN_QUIT, + + // Primaries + TOKEN_DECIMAL_NUMBER, + TOKEN_HEXADECIMAL_NUMBER, + + TOKEN_UNKNOWN, +}; + +struct token { + enum TOKEN_TYPE type; + const char* lexeme; + u8 size; +}; + +struct command { + const char* start; + u8 size; +}; + +struct ast_node { + struct token* token; + struct ast_node* left; + struct ast_node* right; +}; + +static struct command commands[] = { + { .start = "g", .size = 1 }, + { .start = "r", .size = 1 }, + { .start = "t", .size = 1 }, + { .start = "db", .size = 2 }, + { .start = "q", .size = 1 }, +}; + +_Static_assert((sizeof(commands) / sizeof(commands[0])) == TOKEN_QUIT + 1, "Missing commands"); + +void lexer(const char* str_cmd, size_t str_cmd_len, struct token* tokens) { + const char* cur = str_cmd; + const char* end = str_cmd + str_cmd_len; + struct token* cur_token = tokens; + str_cmd_len = 0; + + while(cur < end) { + cur_token->type = TOKEN_UNKNOWN; + if(*cur == '0' && cur[1] == 'x') { + const char* start = cur; + cur += 2; + + while(is_hexadecimal_digit(*cur) && cur < end) { + cur++; + } + + cur_token->lexeme = start; + cur_token->type = TOKEN_HEXADECIMAL_NUMBER; + cur_token->size = (u8)(cur - start); + cur_token++; + } else if(is_decimal_digit(*cur)) { + const char* start = cur; + cur++; + + while(is_decimal_digit(*cur) && cur < end) { + cur++; + } + + cur_token->lexeme = start; + cur_token->type = TOKEN_DECIMAL_NUMBER; + cur_token->size = (u8)(cur - start); + cur_token++; + } else if(is_alpha(*cur)) { + const char* start = cur; + cur++; + while(is_alpha(*cur) && cur < end) { + cur++; + } + + cur_token->lexeme = start; + cur_token->size = (u8)(cur - start); + + for(int i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) { + struct command cur_cmd = commands[i]; + if (CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, cur_cmd.start, cur_cmd.size, cur_token->lexeme, cur_token->size) == CSTR_EQUAL) { + cur_token->type = i; + cur_token++; + break; + } + } + } else { + cur++; + } + } +} + +struct ast_node* parse_primary(struct token* tokens, struct ast_node* nodes) { + struct ast_node* cur_node = &nodes[0]; + struct token* cur_token = &tokens[0]; + if (cur_token->type == TOKEN_HEXADECIMAL_NUMBER || + cur_token->type == TOKEN_DECIMAL_NUMBER) { + cur_node->token = cur_token; + cur_node->left = NULL; + cur_node->right = NULL; + return cur_node; + } else { + print("Expecting a primary token\n"); + return NULL; + } +} + +struct ast_node* parse_command(struct token* tokens, struct ast_node* nodes) { + struct ast_node* cur_node = &nodes[0]; + struct token* cur_token = &tokens[0]; + switch(cur_token->type) { + case TOKEN_CONTINUE: + tokens++; + print("TOKEN_CONTINUE\n"); + cur_node->token = cur_token; + cur_node->left = NULL; + cur_node->right = NULL; + return cur_node; + case TOKEN_PRINT_REG: + tokens++; + print("TOKEN_PRINT_REG\n"); + cur_node->token = cur_token; + cur_node->left = NULL; + cur_node->right = NULL; + return cur_node; + case TOKEN_STEP_INTO: + tokens++; + print("TOKEN_STEP_INTO\n"); + cur_node->token = cur_token; + cur_node->left = NULL; + cur_node->right = NULL; + return cur_node; + case TOKEN_DUMP_MEMORY: + tokens++; + print("TOKEN_DUMP_MEMORY\n"); + cur_node->token = cur_token; + cur_node->left = NULL; + cur_node->right = parse_primary(tokens, ++nodes); + return cur_node; + case TOKEN_QUIT: + tokens++; + print("TOKEN_QUIT\n"); + cur_node->token = cur_token; + cur_node->left = NULL; + cur_node->right = NULL; + return cur_node; + default: + print("%s must be a command\n", cur_token->lexeme); + return NULL; + } +} + +u64 eval_number(const struct ast_node* node) { + if (node->token->type == TOKEN_DECIMAL_NUMBER || + node->token->type == TOKEN_HEXADECIMAL_NUMBER) { + return atou64(node->token->lexeme, node->token->size); + } + return ~0U; +} + +void run(struct ast_node* root) { + struct ast_node cur_node = root[0]; + CONTEXT ctx = { + .ContextFlags = CONTEXT_ALL, + }; + HANDLE h_thread = OpenThread( + THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, + FALSE, + dbg_event.dwThreadId + ); + GetThreadContext(h_thread, &ctx); + + if (cur_node.token->type == TOKEN_CONTINUE) { + ContinueDebugEvent( + dbg_event.dwProcessId, + dbg_event.dwThreadId, + continue_status + ); + process_commands = FALSE; + } else if (cur_node.token->type == TOKEN_PRINT_REG) { + print("RIP : %x\n", ctx.Rip); + print("RAX : %x\n", ctx.Rax); + print("RCX : %x\n", ctx.Rcx); + print("RDX : %x\n", ctx.Rdx); + print("RBX : %x\n", ctx.Rbx); + print("RSP : %x\n", ctx.Rsp); + print("RBP : %x\n", ctx.Rbp); + print("RSI : %x\n", ctx.Rsi); + print("RDI : %x\n", ctx.Rdi); + process_commands = TRUE; + } else if (cur_node.token->type == TOKEN_STEP_INTO) { + ctx.EFlags |= 0x100; // TRAP_FLAG + if(SetThreadContext(h_thread, &ctx) == 0) { + __debugbreak(); + } + ContinueDebugEvent( + dbg_event.dwProcessId, + dbg_event.dwThreadId, + continue_status + ); + expect_single_step = TRUE; + process_commands = FALSE; + } else if (cur_node.token->type == TOKEN_QUIT) { + is_open = FALSE; + process_commands = FALSE; + } else if (cur_node.token->type == TOKEN_DUMP_MEMORY) { + u64 addr = eval_number(cur_node.right); + u8 buf[16U] = { 0 }; + + if(read_memory((const void*)addr, (void*)buf, sizeof(buf))) { + for (u32 index = 0U; index < sizeof(buf); index++) { + print("%b ", buf[index]); + } + print("\n"); + } else { + + print("Unable to read memory at this address, error %u\n", GetLastError()); + } + + } else { + print("Command unknown\n"); + process_commands = TRUE; + } + + CloseHandle(h_thread); +} + +u8 interpreter(const char* str_cmd, size_t str_cmd_len) { + struct token tokens[64U]; + struct ast_node nodes[64U]; + + lexer(str_cmd, str_cmd_len, tokens); + + struct ast_node* root = parse_command(tokens, nodes); + + if(root == NULL) { + print("Ill formed command\n"); + return FALSE; + } + + run(root); + return TRUE; +} @@ -1,7 +1,9 @@ +#include <Windows.h> int mainCRTStartup() { unsigned long long int i = 0; while (1) { + OutputDebugStringA("Hello World !"); i++; } diff --git a/src/utils.c b/src/utils.c index f7994f9..de719e9 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,3 +1,22 @@ +#if defined (_DEBUG) +#define assert(x) if (!(x)) __debugbreak(); +#else +#define assert(x) (x) +#endif +void print(const char* format, ...); + +u8 is_alpha(char c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); +} + +u8 is_decimal_digit(char c) { + return '0' <= c && c <= '9'; +} + +u8 is_hexadecimal_digit(char c) { + return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); +} + void u64toa(u64 number, char* str, u32 base) { static char codes[16U] = { '0', @@ -89,25 +108,36 @@ void print(const char* format, ...) { char c = va_arg(args, char); StringCchCatA(cur_char, 1U, &c); cur_char += 1U; + } else if (*cur_fmt == 'x' && is_alpha(cur_fmt[1])) { + u32 base = 16U; + *cur_char = '0'; + cur_char++; + *cur_char = 'x'; + cur_char++; + cur_fmt++; + + if(*cur_fmt == 'b') { + u8 number = va_arg(args, u8); + u64toa((u64)number, cur_char, base); + size_t length = 0U; + StringCchLengthA(formatted_str, sizeof(formatted_str), &length); + cur_char = formatted_str + length; + } else if(*cur_fmt == 'u') { + u64 number = va_arg(args, u64); + u64toa(number, cur_char, base); + size_t length = 0U; + StringCchLengthA(formatted_str, sizeof(formatted_str), &length); + cur_char = formatted_str + length; + } } else if(*cur_fmt == 'b') { u8 number = va_arg(args, u8); - u64toa((u64)number, cur_char, 10); + u64toa((u64)number, cur_char, 10U); size_t length = 0U; StringCchLengthA(formatted_str, sizeof(formatted_str), &length); cur_char = formatted_str + length; } else if(*cur_fmt == 'u') { u64 number = va_arg(args, u64); - u64toa(number, cur_char, 10); - size_t length = 0U; - StringCchLengthA(formatted_str, sizeof(formatted_str), &length); - cur_char = formatted_str + length; - } else if(*cur_fmt == 'x') { - u64 number = va_arg(args, u64); - *cur_char = '0'; - cur_char++; - *cur_char = 'x'; - *cur_char++; - u64toa(number, cur_char, 16); + u64toa(number, cur_char, 10U); size_t length = 0U; StringCchLengthA(formatted_str, sizeof(formatted_str), &length); cur_char = formatted_str + length; |
