diff --git a/include/pemagine/pemagine.h b/include/pemagine/pemagine.h index c222406..d5d0e66 100644 --- a/include/pemagine/pemagine.h +++ b/include/pemagine/pemagine.h @@ -197,6 +197,15 @@ pe_api void * pe_get_kernel32_module_handle (void); /* ldso */ +pe_api int32_t pe_open_image_from_addr( + void ** himage, + void * addr, + uintptr_t * buffer, + uint32_t buffer_size, + uint32_t desired_access, + uint32_t open_options); + + pe_api int32_t pe_open_physical_parent_directory( void ** hparent, void * href, @@ -205,6 +214,7 @@ pe_api int32_t pe_open_physical_parent_directory( uint32_t desired_access, uint32_t open_options); + #ifdef __cplusplus } #endif diff --git a/project/common.mk b/project/common.mk index 60c71f8..38b0a37 100644 --- a/project/common.mk +++ b/project/common.mk @@ -10,6 +10,7 @@ API_SRCS = \ src/headers/pe_get_image_section_tbl_addr.c \ src/headers/pe_get_image_special_hdr_addr.c \ src/imports/pe_enum_image_import_hdrs.c \ + src/ldso/pe_open_image_from_addr.c \ src/ldso/pe_open_physical_parent_directory.c \ src/meta/pe_get_image_stack_heap_info.c \ src/meta/pe_get_symbol_module_info.c \ diff --git a/src/internal/pe_os.h b/src/internal/pe_os.h index f68a462..54275e3 100644 --- a/src/internal/pe_os.h +++ b/src/internal/pe_os.h @@ -19,6 +19,9 @@ #define OS_FILE_SHARE_WRITE 0x00000002 #define OS_FILE_SHARE_DELETE 0x00000004 +#define OS_CURRENT_PROCESS_HANDLE (void *)(uintptr_t)(-1) +#define OS_CURRENT_THREAD_HANDLE (void *)(uintptr_t)(-2) + enum os_object_info_class { OS_OBJECT_BASIC_INFORMATION = 0, @@ -29,6 +32,14 @@ enum os_object_info_class { }; +enum os_memory_info_class { + OS_MEMORY_BASIC_INFORMATION, + OS_MEMORY_WORKING_SET_LIST, + OS_MEMORY_SECTION_NAME, + OS_MEMORY_BASIC_VLM_INFORMATION +}; + + struct os_oa { uint32_t len; void * root_dir; @@ -56,6 +67,15 @@ typedef int32_t __stdcall os_zw_query_object( __out uint32_t * returned_length __optional); +typedef int32_t __stdcall os_zw_query_virtual_memory( + __in void * hprocess, + __in void * base_address, + __in int mem_info_class, + __out void * mem_info, + __in uint32_t mem_info_length, + __out uint32_t * returned_length __optional); + + typedef int32_t __stdcall os_zw_open_file( __out void ** hfile, __in uint32_t desired_access, diff --git a/src/ldso/pe_open_image_from_addr.c b/src/ldso/pe_open_image_from_addr.c new file mode 100644 index 0000000..2729a18 --- /dev/null +++ b/src/ldso/pe_open_image_from_addr.c @@ -0,0 +1,83 @@ +/*****************************************************************************/ +/* pemagination: a (virtual) tour into portable bits and executable bytes */ +/* Copyright (C) 2013--2017 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */ +/*****************************************************************************/ + +#include +#include +#include +#include "pe_os.h" + +struct os_memory_section_name { + struct pe_unicode_str section_name; + wchar16_t section_name_buffer[]; +}; + +pe_api int32_t pe_open_image_from_addr( + __out void ** himage, + __in void * addr, + __out uintptr_t * buffer, + __in uint32_t buffer_size, + __in uint32_t desired_access, + __in uint32_t open_options) +{ + int32_t status; + struct os_oa oa; + struct os_iosb iosb; + struct os_memory_section_name * path; + uint32_t len; + void * hntdll; + os_zw_query_virtual_memory * zw_query_virtual_memory; + os_zw_open_file * zw_open_file; + + + /* init */ + path = (struct os_memory_section_name *)buffer; + path->section_name.strlen = 0; + path->section_name.maxlen = (uint16_t)(buffer_size - sizeof(struct pe_unicode_str)); + path->section_name.buffer = path->section_name_buffer; + + if (!(hntdll = pe_get_ntdll_module_handle())) + return OS_STATUS_INTERNAL_ERROR; + + if (!(zw_query_virtual_memory = (os_zw_query_virtual_memory *)pe_get_procedure_address( + hntdll,"ZwQueryVirtualMemory"))) + return OS_STATUS_INTERNAL_ERROR; + + if (!(zw_open_file = (os_zw_open_file *)pe_get_procedure_address( + hntdll,"ZwOpenFile"))) + return OS_STATUS_INTERNAL_ERROR; + + /* native path of image containing addr */ + if ((status = zw_query_virtual_memory( + OS_CURRENT_PROCESS_HANDLE, + addr, + OS_MEMORY_SECTION_NAME, + buffer, + buffer_size, + &len))) + return status; + + /* oa */ + oa.len = sizeof(struct os_oa); + oa.root_dir = 0; + oa.obj_name = &path->section_name; + oa.obj_attr = 0; + oa.sec_desc = 0; + oa.sec_qos = 0; + + /* default access */ + desired_access = desired_access + ? desired_access + : OS_SEC_SYNCHRONIZE | OS_FILE_READ_ATTRIBUTES | OS_FILE_READ_ACCESS; + + /* open image */ + return zw_open_file( + himage, + desired_access, + &oa, + &iosb, + OS_FILE_SHARE_READ | OS_FILE_SHARE_WRITE, + open_options | OS_FILE_NON_DIRECTORY_FILE); +}