diff options
| author | Quentin LADEVIE <qladevie@wanadev.fr> | 2024-09-09 08:28:11 +0200 |
|---|---|---|
| committer | Quentin LADEVIE <qladevie@wanadev.fr> | 2024-09-09 08:28:11 +0200 |
| commit | 09d761b30a579b0282185c1db9e91e981f2f3a27 (patch) | |
| tree | 6050453c03502e0eee84c8d90b8e7da92d63d61e | |
| parent | e61b27e6c699ae175d7704ddaaee0d39b6d14382 (diff) | |
Load public symbols for dll
Initial code for pdb loading
| -rw-r--r-- | src/events.c | 166 | ||||
| -rw-r--r-- | src/main.c | 1 | ||||
| -rw-r--r-- | src/pdb.c | 96 |
3 files changed, 224 insertions, 39 deletions
diff --git a/src/events.c b/src/events.c index ea80e58..8870571 100644 --- a/src/events.c +++ b/src/events.c @@ -1,5 +1,130 @@ +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\n", "Loading DLL : error reading dll name"); + return; + } + + wchar_t name_uni[1024U] = { 0U }; + if (!read_memory((const void*)addr, name_uni, sizeof(name_uni))) { + print("Cannot read dll name from proc memory\n"); + 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, const char* name) { + IMAGE_DOS_HEADER dos_header = { 0U }; + if (!read_memory(base_addr, (void*)&dos_header, sizeof(dos_header))) { + print("Cannot read DOS header for module %s at address %x\n", (char*)name, base_addr); + return; + } + + IMAGE_NT_HEADERS64 nt_header = { 0U }; + if (!read_memory((const void*)((u64)base_addr + dos_header.e_lfanew), (void*)&nt_header, sizeof(nt_header))) { + print("Cannot read NT header for module %s at address %x\n", (char*)name, base_addr); + return; + } + + // Export table + IMAGE_DATA_DIRECTORY export_table = 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); + + 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*)name, base_addr); + return; + } + + u16 name_ordinals[8192]; + if (!read_memory((const void*)((u64)base_addr + (u64)export_dir.AddressOfNameOrdinals), (void*)&name_ordinals, export_dir.NumberOfNames * sizeof(name_ordinals[0]))) { + print("Cannot read name ordinals from export directory for module %s at address %x\n", (char*)name, base_addr); + return; + } + + u32 names[8192]; + if (!read_memory((const void*)((u64)base_addr + (u64)export_dir.AddressOfNames), (void*)&names, export_dir.NumberOfNames * sizeof(names[0]))) { + print("Cannot read names from export directory for module %s at address %x\n", (char*)name, base_addr); + return; + } + + print("Found %u functions\n", export_dir.NumberOfNames); + for (u32 i = 0U; i < export_dir.NumberOfNames; i++) { + const char* func_name = (const char*)((u64)base_addr + names[name_ordinals[i]]); + if (export_dir_end < (void*)func_name || (void*)func_name < export_dir_start) { + print("%u : Fowarded function\n", i); + } else { + print("%u : Function name : %s\n", i, func_name); + } + } + } + + + // Private symbols + IMAGE_DATA_DIRECTORY debug_table = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]; + IMAGE_DEBUG_DIRECTORY debug_entries[20U] = { 0U }; + + 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", name, base_addr); + return; + } + + struct codeview_header { + u32 signature; + u32 guid[4U]; + u32 age; + char path; + }; + + 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 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*)name, base_addr); + } + + print("PDB path : %s\n", &header.path); + open_pdb(&header.path); + } +} + void handle_create_process() { print("%s\n", "CreateProcessDebugEvent"); + + CREATE_PROCESS_DEBUG_INFO proc_dbg_info = dbg_event.u.CreateProcessInfo; + u8 proc_name[1024U] = { 0U }; + read_name_uni(proc_dbg_info.lpImageName, (const char*)proc_name, sizeof(proc_name)); + print("%s%s\n", "Loading Process : ", (char*)proc_name); + + load_symbols((const void*)proc_dbg_info.lpBaseOfImage, (const char*)proc_name); } void handle_create_thread() { @@ -39,49 +164,12 @@ void handle_load_dll() { 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"); - } + read_name_uni(dll_name_addr, (const char*)dll_name, sizeof(dll_name)); - 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); - } + load_symbols(dll_base_addr, (const char*)dll_name); } void handle_unload_dll() { @@ -46,6 +46,7 @@ u8 read_memory(const void* addr, void* buffer, size_t size) { } #include "parser.c" +#include "pdb.c" #include "events.c" void dbg_loop() { diff --git a/src/pdb.c b/src/pdb.c new file mode 100644 index 0000000..dfa4c74 --- /dev/null +++ b/src/pdb.c @@ -0,0 +1,96 @@ +void open_pdb(const char* pdb_path) { + HANDLE pdb_file = CreateFileA(pdb_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (pdb_file == INVALID_HANDLE_VALUE) { + print("Cannot open pdb file at path %s due to error %u\n", pdb_path, GetLastError()); + } + + // MSF superblock + struct msf_superblock { + u8 magic[32U]; + u32 block_size; + u32 free_block_map_block; + u32 num_blocks; + u32 num_directory_bytes; + u32 unknown; + u32 block_map_addr; + }; + struct msf_superblock superblock = { 0U }; + u8 block[4096U] = { 0U }; + u32 b_read = 0U; + ReadFile(pdb_file, (void*)&superblock, sizeof(superblock), (LPDWORD)&b_read, NULL); + + // Stream directory + u32 dir_addr = (superblock.block_map_addr - 1U) * sizeof(block); + SetFilePointer(pdb_file, dir_addr, NULL, FILE_BEGIN); + ReadFile(pdb_file, (void*)block, superblock.num_directory_bytes, (LPDWORD)&b_read, NULL); + u32 num_streams = ((u32*)block)[0U]; + u32* stream_sizes = &((u32*)block)[1U]; + u32* stream_blocks = stream_sizes + num_streams; + u32* pdb_info_stream_blocks = NULL; + u32* pdb_DBI_stream_blocks = NULL; + + u32 block_index = 0U; + for(u32 stream_id = 0u; stream_id < num_streams; stream_id++) { + print("PDB stream size : %u\n", stream_sizes[stream_id]); + if (stream_id == 1U) { + pdb_info_stream_blocks = &stream_blocks[block_index]; + } + if (stream_id == 3U) { + pdb_DBI_stream_blocks = &stream_blocks[block_index]; + } + if (stream_sizes[stream_id] == (u32)-1) { + continue; + } + for(u32 id = 0u; id < (stream_sizes[stream_id] / sizeof(block)) + 1U; id++) { + print("PDB stream blocks : %u\n", stream_blocks[block_index]); + block_index++; + } + } + + // PDB Info Stream + struct pdb_info_stream { + u32 version; + u32 signature; + u32 age; + u32 guid[4u]; + }; + + struct pdb_info_stream pdb_info_stream = { 0U }; + SetFilePointer(pdb_file, pdb_info_stream_blocks[0U] * sizeof(block), NULL, FILE_BEGIN); + ReadFile(pdb_file, (void*)&pdb_info_stream, sizeof(pdb_info_stream), (LPDWORD)&b_read, NULL); + pdb_info_stream; + + // DBI Stream + struct pdb_DBI_stream { + i32 version_signature; + u32 version_header; + u32 age; + u16 global_stream_index; + u16 build_number; + u16 public_stream_index; + u16 pdb_dll_version; + u16 sym_record_stream; + u16 pdb_dll_rbld; + i32 mod_info_size; + i32 section_contribution_size; + i32 section_map_size; + i32 source_info_size; + i32 type_server_map_size; + u32 mfc_type_server_index; + i32 optional_dbg_header_size; + i32 ec_substream_size; + u16 flags; + u16 machine; + u32 padding; + }; + struct pdb_DBI_stream pdb_DBI_stream = { 0U }; + SetFilePointer(pdb_file, pdb_DBI_stream_blocks[0U] * sizeof(block), NULL, FILE_BEGIN); + ReadFile(pdb_file, (void*)&pdb_DBI_stream, sizeof(pdb_DBI_stream), (LPDWORD)&b_read, NULL); + print(""); + pdb_DBI_stream; + + // Global Symbol Stream + SetFilePointer(pdb_file, pdb_DBI_stream.global_stream_index * sizeof(block), NULL, FILE_BEGIN); + ReadFile(pdb_file, (void*)&pdb_DBI_stream, sizeof(pdb_DBI_stream), (LPDWORD)&b_read, NULL); +} |
