diff options
| -rw-r--r-- | ] | 420 | ||||
| -rw-r--r-- | build.bat | 8 | ||||
| -rw-r--r-- | compile_flags.txt | 12 | ||||
| -rw-r--r-- | include/events.h | 19 | ||||
| -rw-r--r-- | include/hashmap.h | 26 | ||||
| -rw-r--r-- | include/module.h | 41 | ||||
| -rw-r--r-- | include/parser.h | 4 | ||||
| -rw-r--r-- | include/pdb.h | 5 | ||||
| -rw-r--r-- | include/stack_walk.h | 3 | ||||
| -rw-r--r-- | include/types.h | 2 | ||||
| -rw-r--r-- | include/utils.h | 23 | ||||
| -rw-r--r-- | src/events.c | 12 | ||||
| -rw-r--r-- | src/hashmap.c | 15 | ||||
| -rw-r--r-- | src/main.c | 34 | ||||
| -rw-r--r-- | src/module.c | 23 | ||||
| -rw-r--r-- | src/parser.c | 16 | ||||
| -rw-r--r-- | src/pdb.c | 8 | ||||
| -rw-r--r-- | src/stack_walk.c | 15 | ||||
| -rw-r--r-- | src/utils.c | 20 |
19 files changed, 217 insertions, 489 deletions
@@ -1,420 +0,0 @@ -const char* dummy_name = "Function_dummy_name"; - -void read_name_uni(const void* name_addr, const char* name, size_t name_size) { - u8* addr = NULL; - if (!read_memory(name_addr, (void*)&addr, 8U)) { - print("%s %u\n", "Loading DLL : error reading dll name : ", GetLastError()); - return; - } - - wchar_t name_uni[256U] = { 0U }; - if (!read_memory((const void*)addr, name_uni, sizeof(name_uni))) { - print("Cannot read dll name from proc memory %u\n", GetLastError()); - return; - } - - WideCharToMultiByte( - CP_ACP, - 0, - name_uni, - -1, - (char*)name, - (int)name_size, - NULL, - NULL - ); -} -void read_name_ansi(const void* name_addr, const char* name, size_t name_size) { - u8* addr = NULL; - if (!read_memory(name_addr, (void*)&addr, 8U)) { - print("%s\n", "Loading DLL : error reading dll name"); - return; - } - - if (!read_memory((const void*)addr, (char*)name, name_size)) { - print("Cannot read dll name from proc memory\n"); - return; - } -} - -void load_symbols(const void* base_addr, struct module* module) { - if (!read_memory(base_addr, (void*)&module->dos_header, sizeof(module->dos_header))) { - print("Cannot read DOS header for module %s at address %x\n", (char*)module->name, base_addr); - return; - } - - if (!read_memory((const void*)((u64)base_addr + module->dos_header.e_lfanew), (void*)&module->nt_header, sizeof(module->nt_header))) { - print("Cannot read NT header for module %s at address %x\n", (char*)module->name, base_addr); - return; - } - - print("Module Base Address %xu\n", base_addr); - print("Module Size %xu\n", module->nt_header.OptionalHeader.SizeOfImage); - - // Export table - IMAGE_DATA_DIRECTORY export_table = module->nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; - IMAGE_EXPORT_DIRECTORY export_dir = { 0U }; - const void* export_dir_start = (const void*)((u64)base_addr + (u64)export_table.VirtualAddress); - const void* export_dir_end = (const void*)((u64)export_dir_start + export_table.Size); - -#ifndef HASHMAP - u8** public_names = NULL; - u32* public_addresses = NULL; -#endif - if (export_table.Size != 0U) { - if (!read_memory((const void*)((u64)base_addr + (u64)export_table.VirtualAddress), (void*)&export_dir, sizeof(export_dir))) { - print("Cannot read export dir for module %s at address %x\n", (char*)module->name, base_addr); - return; - } - - size_t ordinals_size = export_dir.NumberOfNames * sizeof(u16); - u16* ordinals = VirtualAlloc(NULL, ordinals_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - if (!read_memory((const void*)((u64)base_addr + (u64)export_dir.AddressOfNameOrdinals), (void*)ordinals, ordinals_size)) { - print("Cannot read name ordinals from export directory for module %s at address %x\n", (char*)module->name, base_addr); - return; - } - - size_t names_size = export_dir.NumberOfNames * sizeof(u32); - u32* names_address = VirtualAlloc(NULL, names_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); -#ifndef HASHMAP - external_names = VirtualAlloc(NULL, export_dir.NumberOfNames * sizeof(external_names[0U]), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); -#endif - if (!read_memory((const void*)((u64)base_addr + (u64)export_dir.AddressOfNames), (void*)names_address, names_size)) { - print("Cannot read names from export directory for module %s at address %x\n", (char*)module->name, base_addr); - return; - } - - size_t addresses_size = export_dir.NumberOfFunctions * sizeof(u32); - u32* addresses = VirtualAlloc(NULL, addresses_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); -#ifndef HASHMAP - external_addresses = addresses; -#endif - if (!read_memory((const void*)((u64)base_addr + (u64)export_dir.AddressOfFunctions), (void*)addresses, addresses_size)) { - print("Cannot read functions addresses from export directory for module %s at address %x\n", (char*)module->name, base_addr); - return; - } - -#ifndef HASHMAP - for (u32 i = 0U; i < export_dir.NumberOfFunctions; i++) { - for (u32 name_index = 0U; name_index < export_dir.NumberOfNames; name_index++) { - if (ordinals[name_index] == i) { - // TODO: Add string management code - assert(string_stack_current - 16U * 4096U < string_stack_base); - size_t length = 0U; - void* name_address = (void*)((u64)module->base_addr + names_address[name_index]); - read_memory(name_address, string_stack_current, 256U); - StringCchLengthA((PCNZCH)string_stack_current, STRSAFE_MAX_CCH, &length); - string_stack_current[length] = '\0'; - external_names[i] = string_stack_current; - string_stack_current += length + 1U; - break; - } - } - } - - init_module_functions(module, external_names, external_addresses, NULL, NULL, export_dir.NumberOfFunctions); -#endif - - print("Found %u functions\n", export_dir.NumberOfFunctions); - for (u32 i = 0U; i < export_dir.NumberOfFunctions; i++) { - char func_name[256U] = { 0 }; - u64 func_address = (u64)base_addr + addresses[i]; - u32 name_index = 0U; - for (; name_index < export_dir.NumberOfNames; name_index++) { - if (ordinals[name_index] == i) { - break; - } - } - - u64 name_address = (u64)base_addr + names_address[name_index]; - read_memory((void*)name_address, func_name, sizeof(func_name)); - - if (export_dir_start < (void*)func_address && (void*)func_address < export_dir_end) { - print("%u : Fowarded function : %s\n", i, func_name); - } else if (name_index && name_index < export_dir.NumberOfNames) { - print("%u : Function name : %s, function address %xu\n", i, func_name, addresses[i]); -#ifdef HASHMAP - insert_elem(&module->symbols, addresses[i], 0U, name_address); -#endif - } else { - print("%u : Function has no name, function address %xu\n", i, addresses[i]); -#ifdef HASHMAP - insert_elem(&module->symbols, addresses[i], 0U, (u64)dummy_name); -#endif - } - } - - VirtualFree(names_address, names_size, MEM_RELEASE); - VirtualFree(ordinals, ordinals_size, MEM_RELEASE); -#ifdef HASHMAP - VirtualFree(addresses, addresses_size, MEM_RELEASE); -#endif - } - - // Private symbols - IMAGE_DATA_DIRECTORY debug_table = module->nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]; - IMAGE_DEBUG_DIRECTORY debug_entries[20U] = { 0U }; - - u8** private_names = NULL; - u32* private_starts = NULL; - u32* private_ends = NULL; - if (debug_table.VirtualAddress && !read_memory((const void*)((u64)base_addr + (u64)debug_table.VirtualAddress), debug_entries, debug_table.Size)) { - print("Cannot read image debug infos for module %s at address %x\n", module->name, base_addr); - return; - } - - for (u32 i = 0U; i < debug_table.Size / sizeof(debug_entries[0U]); i++) { - if (debug_entries[i].Type != IMAGE_DEBUG_TYPE_CODEVIEW) { - print("Image debug type different from CodeView\n"); - continue; - } - - struct codeview_header { - u32 signature; - u32 guid[4U]; - u32 age; - char path; - } header = { 0U }; - if (!read_memory((const void*)((u64)base_addr + (u64)debug_entries[i].AddressOfRawData), (void*)&header, debug_entries[i].SizeOfData)) { - print("Cannot read code view header for module %s at address %x\n", (char*)module->name, base_addr); - } - - print("PDB path : %s\n", &header.path); - open_pdb(&header.path, module); - } - - - // Exception directory - IMAGE_DATA_DIRECTORY exception_entry = module->nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; - - if (exception_entry.Size == 0U) { - print("Exception directory is empty in module %s\n", module->name); - } - - RUNTIME_FUNCTION* exception_table = VirtualAlloc(NULL, exception_entry.Size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - if (!read_memory((const void*)((u64)base_addr + (u64)exception_entry.VirtualAddress), (void*)exception_table, exception_entry.Size)) { - print("Cannot read exception table for module %s at address %x\n", (char*)module->name, base_addr); - return; - } - - // TODO: Merge private and public symbols - - u32 pdata_entries = exception_entry.Size / sizeof(exception_table[0U]); - u32* unwind_offsets = VirtualAlloc(NULL, pdata_entries * sizeof(unwind_offsets[0U]), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - // Find unwind info offset - for (u32 index = 0U; index < pdata_entries; index++) { - RUNTIME_FUNCTION cur_entry = exception_table[index]; - -#ifdef HASHMAP - struct element* elem = find_elem(&module->symbols, cur_entry.BeginAddress); - if (elem == NULL) { - elem = insert_elem(&module->symbols, cur_entry.BeginAddress, cur_entry.EndAddress, 0ULL); - } else { - if (elem->name == 0U) { - print("function name %s\n", elem->name); - } - - elem->end = cur_entry.EndAddress; - } - - elem->unwind_offset = cur_entry.UnwindData; -#else - if (module->functions_start == cur_entry.BeginAddress) { - pdata_entries[i] = cur_entry.UnwindData; - } - // u32 sym_index = find_function(module, cur_entry.BeginAddress); - // if (sym_index == (u32)-1) { - // // TODO: Add element - // add_functions(module, NULL, (u32*)&cur_entry.BeginAddress, (u32*)&cur_entry.EndAddress, (u32*)&cur_entry.UnwindData, 1U); - // assert(FALSE); - // } else { - // module->functions_unwind[sym_index] = cur_entry.UnwindData; - // } -#endif - - // if (!read_memory((const void*)((u64)base_addr + (u64)cur_entry.UnwindData), (void*)u_info, 4096U)) { - // print("Cannot read unwind info in for function %s\n", elem->name); - // continue; - // } - - // size_t total_size = sizeof(*u_info) + (u_info->count_of_unwind_codes - 1U) * sizeof(struct UNWIND_CODE); - // assert(total_size < 4096U); - - // for (u32 code_index = 0U; code_index < u_info->count_of_unwind_codes; code_index++) { - // struct UNWIND_CODE* cur_code = &u_info->unwind_code[code_index]; - // switch (cur_code->unwind_operation_code) { - // case UWOP_PUSH_NONVOL: - // print("push non volatile\n"); - // print("push "); - // print_reg(cur_code->op_info); - // break; - // case UWOP_ALLOC_LARGE: - // print("alloc large\n"); - // if (cur_code->op_info == 0U) { - // u16 size = *(u16*)&u_info->unwind_code[code_index + 1U]; - // if (u_info->frame_register) { - // print("sub rbp %xu\n", size); - // } else { - // print("sub rsp %xu\n", size); - // } - // code_index++; - // } else { - // u32 size = *(u32*)&u_info->unwind_code[code_index + 1U]; - // if (u_info->frame_register) { - // print("sub rbp %xu\n", size); - // } else { - // print("sub rsp %xu\n", size); - // } - // code_index += 2U; - // } - // break; - // case UWOP_ALLOC_SMALL: - // print("alloc small\n"); - // u32 size = cur_code->op_info * 8U + 8U; - // if (u_info->frame_register) { - // print("sub rbp %xu\n", size); - // } else { - // print("sub rsp %xu\n", size); - // } - // break; - // case UWOP_SET_FPREG: - // print("set frame point reg\n"); - // print("mov rbp rsp - %xu\n", u_info->frame_register_offset * 16U); - // break; - // case UWOP_SAVE_NONVOL: - // print("save non volatile\n"); - // if (u_info->frame_register) { - // print("mov rbp "); - // } else { - // print("mov rsp "); - // } - // print_reg(cur_code->op_info); - // code_index++; - // break; - // case UWOP_SAVE_NONVOL_FAR: - // print("save non volatile far\n"); - // code_index += 2U; - // break; - // case UWOP_SAVE_XMM128: - // print("save xmm128\n"); - // code_index++; - // break; - // case UWOP_SAVE_XMM128_FAR: - // print("save xmm128 far\n"); - // code_index += 2U; - // break; - // case UWOP_PUSH_MACHFRAME: - // print("push mach frame\n"); - // break; - // default: - // print("bad operation code\n"); - // } - // } - } - - // VirtualFree(u_info, 4096U, MEM_RELEASE); - VirtualFree(exception_table, exception_entry.Size, MEM_RELEASE); -} - -void handle_create_process() { - print("%s\n", "CreateProcessDebugEvent"); - - CREATE_PROCESS_DEBUG_INFO proc_dbg_info = dbg_event.u.CreateProcessInfo; - - HANDLE hproc = OpenProcess(PROCESS_VM_READ, FALSE, dbg_event.dwProcessId); - hproc; - - struct module* module = &modules[add_module()]; - // https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-create_process_debug_info - // Debuggers must be prepared to handle the case where lpImageName is NULL or *lpImageName (in the address space of the process being debugged) is NULL. - // Specifically, the system does not provide an image name for a create process event - // module->base_addr = proc_dbg_info.lpBaseOfImage; - // read_name_uni(proc_dbg_info.lpImageName, (const char*)module->name, sizeof(module->name)); - module->base_addr = proc_dbg_info.lpBaseOfImage; - GetFinalPathNameByHandleA(proc_dbg_info.hFile, (LPSTR)module->name, sizeof(module->name), FILE_NAME_NORMALIZED); - print("%s%s\n", "Loading Process : ", (char*)module->name); - - load_symbols((const void*)proc_dbg_info.lpBaseOfImage, module); -} - -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; - void* dll_base_addr = dll_info.lpBaseOfDll; - if (dll_name_addr == NULL) { - print("%s\n", "Loading DLL : error reading dll name"); - return; - } - - struct module* module = &modules[add_module()]; - module->base_addr = dll_base_addr; - read_name_uni(dll_name_addr, (const char*)module->name, sizeof(module->name)); - - print("%s%s\n", "Loading DLL : ", (char*)module->name); - - load_symbols(dll_base_addr, module); -} - -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 %u\n", "OutputDebugStringDebugEvent : error reading debug string : ", GetLastError()); - 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"); -} @@ -34,13 +34,17 @@ if "%release%"=="0" ( set L_FLAGS=/DEBUG %L_FLAGS% ) +set src=main utils events module parser pdb hashmap stack_walk :: DBG :: Compile -cl /Fd:%BUILD_DIR%\main.pdb %C_FLAGS% src\main.c +(for %%s in (%src%) do ( + call set OBJS=%%OBJS%% %BUILD_DIR%\%%s.obj + cl /Fd:%BUILD_DIR%\%%s.pdb %C_FLAGS% src\%%s.c +)) :: Link -link %L_FLAGS% /OUT:%BUILD_DIR%\main.exe %BUILD_DIR%\main.obj kernel32.lib +link %L_FLAGS% /OUT:%BUILD_DIR%\main.exe %OBJS% kernel32.lib :: Test program set SRC_FILE=test diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..b5976a9 --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,12 @@ +-W4 +-WX +-GS- +-GR- +-Gs1000000000 +-Fo:%BUILD_DIR%\ +-I +include/ +-I +src/ +-c +-TC diff --git a/include/events.h b/include/events.h new file mode 100644 index 0000000..65131c6 --- /dev/null +++ b/include/events.h @@ -0,0 +1,19 @@ +#pragma once + +extern void handle_create_process(); + +extern void handle_create_thread(); + +extern void handle_exception(); + +extern void handle_exit_process(); + +extern void handle_exit_thread(); + +extern void handle_load_dll(); + +extern void handle_unload_dll(); + +extern void handle_output_debug_string(); + +extern void handle_rip(); diff --git a/include/hashmap.h b/include/hashmap.h new file mode 100644 index 0000000..88490e7 --- /dev/null +++ b/include/hashmap.h @@ -0,0 +1,26 @@ +#pragma once + +#include "types.h" + +struct element { + u64 name; + u32 start; + u32 end; + u32 unwind_offset; + u32 psl; +}; + +struct hashmap { + u32 capacity; + u32 size; + + struct element* arr; +}; + +extern struct hashmap create_unordered_flat(); + +extern struct element* insert_elem(struct hashmap* map, u32 start, u32 end, u64 name); + +extern struct element* find_elem(struct hashmap* map, u32 start); + +extern void iterate(struct hashmap* map); diff --git a/include/module.h b/include/module.h new file mode 100644 index 0000000..e94e156 --- /dev/null +++ b/include/module.h @@ -0,0 +1,41 @@ +#pragma once + +#include <Windows.h> + +#include "types.h" +#include "hashmap.h" + +struct module { + void* base_addr; + u8** functions_name; + u32* functions_start; + u32* functions_end; + u32* functions_unwind; + u32 functions_count; + u32 functions_capacity; + // u32 functions_name_capacity; + // u32 function_start_capacity; + // u32 function_end_capacity; + // u32 function_unwind_capacity; + + IMAGE_DOS_HEADER dos_header; + IMAGE_NT_HEADERS64 nt_header; +#ifdef HASHMAP + struct hashmap symbols; +#endif + u8 name[256U]; +}; + + +extern struct module modules[64U]; +extern u64 modules_list; + +extern u8 add_module(); + +extern void remove_module(u8 index); + +#ifdef HASHMAP +extern struct element* find_function(struct module* module, u32 rip_offset); +#else +extern u32 find_function(struct module* module, u64 rip_offset); +#endif // HASHMAP diff --git a/include/parser.h b/include/parser.h new file mode 100644 index 0000000..1f93aac --- /dev/null +++ b/include/parser.h @@ -0,0 +1,4 @@ +#pragma once + +#include "types.h" +extern u8 interpreter(const char* str_cmd, size_t str_cmd_len); diff --git a/include/pdb.h b/include/pdb.h new file mode 100644 index 0000000..965ccc3 --- /dev/null +++ b/include/pdb.h @@ -0,0 +1,5 @@ +#pragma once + +#include "module.h" + +extern void open_pdb(const char* pdb_path, struct module* module); diff --git a/include/stack_walk.h b/include/stack_walk.h new file mode 100644 index 0000000..783cbb9 --- /dev/null +++ b/include/stack_walk.h @@ -0,0 +1,3 @@ +#pragma once + +extern void walk_stack(void* ctx); diff --git a/include/types.h b/include/types.h index a3b0942..463b73f 100644 --- a/include/types.h +++ b/include/types.h @@ -1,3 +1,5 @@ +#pragma once + #include <stdint.h> typedef uint8_t u8; diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..738ba9f --- /dev/null +++ b/include/utils.h @@ -0,0 +1,23 @@ +#pragma once + +#include "types.h" + +#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); + +u8 is_decimal_digit(char c); + +u8 is_hexadecimal_digit(char c); + +void u64toa(u64 number, char* str, u32 base); + +u64 atou64(const char* str, u32 len); + +u8 read_memory(const void* addr, void* buffer, size_t size); diff --git a/src/events.c b/src/events.c index 4f2115a..7492597 100644 --- a/src/events.c +++ b/src/events.c @@ -1,3 +1,12 @@ +#include <Windows.h> + +#include "utils.h" +#include "pdb.h" + +u8 expect_single_step = FALSE; + +extern DEBUG_EVENT dbg_event; + const char* dummy_name = "Function_dummy_name"; void read_name_uni(const void* name_addr, const char* name, size_t name_size) { @@ -24,6 +33,7 @@ void read_name_uni(const void* name_addr, const char* name, size_t name_size) { NULL ); } + void read_name_ansi(const void* name_addr, const char* name, size_t name_size) { u8* addr = NULL; if (!read_memory(name_addr, (void*)&addr, 8U)) { @@ -362,6 +372,8 @@ void handle_create_thread() { } void handle_exception() { + extern DWORD continue_status; + print("%s : ", "ExceptionDebugEvent"); if (dbg_event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP && expect_single_step) { diff --git a/src/hashmap.c b/src/hashmap.c index 5b2d5a0..4a59e15 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -1,17 +1,8 @@ -struct element { - u64 name; - u32 start; - u32 end; - u32 unwind_offset; - u32 psl; -}; +#include "hashmap.h" -struct hashmap { - u32 capacity; - u32 size; +#include <Windows.h> - struct element* arr; -}; +#include "utils.h" static const u32 initial_size = 4096U * 100U; static const u32 empty_psl = (u32)-1; @@ -4,38 +4,24 @@ #include "types.h" -#include "utils.c" -#include "hashmap.c" +#include "utils.h" +#include "events.h" +#include "parser.h" extern u32 _fltused = TRUE; -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 = { 0 }; +u8 is_open = TRUE; +u8 process_commands = TRUE; +HANDLE h_input = NULL; +HANDLE h_output = NULL; +DEBUG_EVENT dbg_event; +PROCESS_INFORMATION proc_info = { 0 }; +DWORD continue_status = DBG_EXCEPTION_NOT_HANDLED; // TODO: Perfect hashing table ? u8* string_stack_base = NULL; u8* string_stack_current = NULL; -/* 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); - - return hr > 0 && b_read == size; -} - -#include "module.c" -#include "stack_walk.c" -#include "parser.c" -#include "pdb.c" -#include "events.c" - void dbg_loop() { while(is_open) { WaitForDebugEventEx(&dbg_event, INFINITE); diff --git a/src/module.c b/src/module.c index 9148aa8..ad50d7a 100644 --- a/src/module.c +++ b/src/module.c @@ -1,23 +1,6 @@ -struct module { - void* base_addr; - u8** functions_name; - u32* functions_start; - u32* functions_end; - u32* functions_unwind; - u32 functions_count; - u32 functions_capacity; - // u32 functions_name_capacity; - // u32 function_start_capacity; - // u32 function_end_capacity; - // u32 function_unwind_capacity; - - IMAGE_DOS_HEADER dos_header; - IMAGE_NT_HEADERS64 nt_header; -#ifdef HASHMAP - struct hashmap symbols; -#endif - u8 name[256U]; -}; +#include "module.h" + +#include "utils.h" struct module modules[64U] = { 0U }; u64 modules_list = ~0ULL; diff --git a/src/parser.c b/src/parser.c index ab9bde1..1731c70 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,3 +1,14 @@ +#include "parser.h" + +#include <Windows.h> + +#include "utils.h" +#include "module.h" +#include "stack_walk.h" + +extern u8 expect_single_step; +extern DWORD continue_status; + enum TOKEN_TYPE { // Commands TOKEN_CONTINUE, @@ -194,6 +205,10 @@ u64 eval_number(const struct ast_node* node) { } void run(struct ast_node* root) { + extern DEBUG_EVENT dbg_event; + extern u8 process_commands; + extern u8 is_open; + struct ast_node cur_node = root[0]; CONTEXT ctx = { .ContextFlags = CONTEXT_ALL, @@ -225,7 +240,6 @@ void run(struct ast_node* root) { } } else if (cur_node.token->type == TOKEN_PRINT_REG) { print("RIP : %xu\n", ctx.Rip); - print("RAX : %xu\n", ctx.Rax); print("RCX : %xu\n", ctx.Rcx); print("RDX : %xu\n", ctx.Rdx); print("RBX : %xu\n", ctx.Rbx); @@ -1,5 +1,10 @@ +#include "pdb.h" + +#include <strsafe.h> #include "cvinfo.h" +#include "utils.h" + enum STREAM_INDEX { OLD_DIRECTORY, PDB, @@ -8,6 +13,9 @@ enum STREAM_INDEX { IPI, }; +extern u8* string_stack_base; +extern u8* string_stack_current; + void open_pdb(const char* pdb_path, struct module* module) { HANDLE pdb_file = CreateFileA(pdb_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); diff --git a/src/stack_walk.c b/src/stack_walk.c index bb4f4be..88a21db 100644 --- a/src/stack_walk.c +++ b/src/stack_walk.c @@ -1,3 +1,10 @@ +#include "stack_walk.h" + +#include <Windows.h> + +#include "module.h" +#include "utils.h" + // enum UNWIND_INFO_FLAGS { // UNW_FLAG_EHANDLER, // UNW_FLAG_UHANDLER, @@ -130,10 +137,10 @@ void print_reg(enum UNWIND_OP_INFO_TYPE op_info) { } } -void walk_stack(CONTEXT* ctx) { - u64 addr = ctx->Rip; - u64 rsp = ctx->Rsp; - u64 rbp = ctx->Rbp; +void walk_stack(void* ctx) { + u64 addr = ((CONTEXT*)ctx)->Rip; + u64 rsp = ((CONTEXT*)ctx)->Rsp; + u64 rbp = ((CONTEXT*)ctx)->Rbp; struct module* module = NULL; struct UNWIND_INFO* u_info = VirtualAlloc(NULL, 4096U, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); while (addr) { diff --git a/src/utils.c b/src/utils.c index de719e9..440b9fb 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,9 +1,7 @@ -#if defined (_DEBUG) -#define assert(x) if (!(x)) __debugbreak(); -#else -#define assert(x) (x) -#endif -void print(const char* format, ...); +#include "utils.h" + +#include <Windows.h> +#include <strsafe.h> u8 is_alpha(char c) { return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); @@ -155,3 +153,13 @@ void print(const char* format, ...) { StringCchLengthA(formatted_str, sizeof(formatted_str), &length); SUCCEEDED(WriteFile(standard_err, formatted_str, (DWORD)length, NULL, NULL)); } + +/* Read debugged process memory at address */ +u8 read_memory(const void* addr, void* buffer, size_t size) { + extern PROCESS_INFORMATION proc_info; + + size_t b_read = 0U; + HRESULT hr = ReadProcessMemory(proc_info.hProcess, addr, buffer, size, &b_read); + + return hr > 0 && b_read == size; +} |
