summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--]420
-rw-r--r--build.bat8
-rw-r--r--compile_flags.txt12
-rw-r--r--include/events.h19
-rw-r--r--include/hashmap.h26
-rw-r--r--include/module.h41
-rw-r--r--include/parser.h4
-rw-r--r--include/pdb.h5
-rw-r--r--include/stack_walk.h3
-rw-r--r--include/types.h2
-rw-r--r--include/utils.h23
-rw-r--r--src/events.c12
-rw-r--r--src/hashmap.c15
-rw-r--r--src/main.c34
-rw-r--r--src/module.c23
-rw-r--r--src/parser.c16
-rw-r--r--src/pdb.c8
-rw-r--r--src/stack_walk.c15
-rw-r--r--src/utils.c20
19 files changed, 217 insertions, 489 deletions
diff --git a/] b/]
deleted file mode 100644
index 1254912..0000000
--- a/]
+++ /dev/null
@@ -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");
-}
diff --git a/build.bat b/build.bat
index 1d48f79..14d0588 100644
--- a/build.bat
+++ b/build.bat
@@ -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;
diff --git a/src/main.c b/src/main.c
index ea94bc9..fbefb1d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);
diff --git a/src/pdb.c b/src/pdb.c
index 7f37c34..0d6617a 100644
--- a/src/pdb.c
+++ b/src/pdb.c
@@ -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;
+}