From 393c205aed99a73cb8ff984858f288f8cb901688 Mon Sep 17 00:00:00 2001 From: midipix Date: Tue, 17 Jan 2017 19:40:32 +0000 Subject: ldso: added pe_open_physical_parent_directory(). --- include/pemagine/pemagine.h | 9 +++ project/common.mk | 3 +- project/headers.mk | 3 +- project/tree.mk | 1 + src/internal/pe_os.h | 67 +++++++++++++++++ src/ldso/pe_open_physical_parent_directory.c | 105 +++++++++++++++++++++++++++ 6 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 src/internal/pe_os.h create mode 100644 src/ldso/pe_open_physical_parent_directory.c diff --git a/include/pemagine/pemagine.h b/include/pemagine/pemagine.h index ac84a97..c222406 100644 --- a/include/pemagine/pemagine.h +++ b/include/pemagine/pemagine.h @@ -196,6 +196,15 @@ pe_api void * pe_get_ntdll_module_handle (void); pe_api void * pe_get_kernel32_module_handle (void); +/* ldso */ +pe_api int32_t pe_open_physical_parent_directory( + void ** hparent, + void * href, + uintptr_t * buffer, + uint32_t buffer_size, + uint32_t desired_access, + uint32_t open_options); + #ifdef __cplusplus } #endif diff --git a/project/common.mk b/project/common.mk index f8a5ce1..60c71f8 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_physical_parent_directory.c \ src/meta/pe_get_image_stack_heap_info.c \ src/meta/pe_get_symbol_module_info.c \ src/meta/pe_get_symbol_name.c \ @@ -21,4 +22,4 @@ API_SRCS = \ INTERNAL_SRCS = \ src/internal/pe_entry_point.c \ -COMMON_SRCS = $(API_SRCS) $(INTERNAL_SRCS) \ No newline at end of file +COMMON_SRCS = $(API_SRCS) $(INTERNAL_SRCS) diff --git a/project/headers.mk b/project/headers.mk index 0863c1b..f9ee61d 100644 --- a/project/headers.mk +++ b/project/headers.mk @@ -14,6 +14,7 @@ API_HEADERS_NT64 = \ $(PROJECT_DIR)/include/$(PACKAGE)/bits/nt64/pe_inline_asm__msvc.h \ INTERNAL_HEADERS = \ - $(PROJECT_DIR)/src/internal/pe_impl.h + $(PROJECT_DIR)/src/internal/pe_impl.h \ + $(PROJECT_DIR)/src/internal/pe_os.h \ ALL_HEADERS = $(API_HEADERS) $(INTERNAL_HEADERS) $(API_HEADERS_NT32) $(API_HEADERS_NT64) diff --git a/project/tree.mk b/project/tree.mk index 08c47de..1811851 100644 --- a/project/tree.mk +++ b/project/tree.mk @@ -4,6 +4,7 @@ tree.tag: mkdir -p src/headers mkdir -p src/imports mkdir -p src/internal + mkdir -p src/ldso mkdir -p src/meta mkdir -p src/modules touch tree.tag diff --git a/src/internal/pe_os.h b/src/internal/pe_os.h new file mode 100644 index 0000000..f68a462 --- /dev/null +++ b/src/internal/pe_os.h @@ -0,0 +1,67 @@ +#ifndef PE_OS_H +#define PE_OS_H + +#include + +#define OS_STATUS_INTERNAL_ERROR 0xC00000E5 +#define OS_STATUS_BAD_FILE_TYPE 0xC0000903 +#define OS_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034 +#define OS_STATUS_MORE_PROCESSING_REQUIRED 0xC0000016 + +#define OS_SEC_SYNCHRONIZE 0x00100000 +#define OS_FILE_READ_ACCESS 0x00000001 +#define OS_FILE_READ_ATTRIBUTES 0x00000080 + +#define OS_FILE_DIRECTORY_FILE 0x00000001 +#define OS_FILE_NON_DIRECTORY_FILE 0x00000040 + +#define OS_FILE_SHARE_READ 0x00000001 +#define OS_FILE_SHARE_WRITE 0x00000002 +#define OS_FILE_SHARE_DELETE 0x00000004 + + +enum os_object_info_class { + OS_OBJECT_BASIC_INFORMATION = 0, + OS_OBJECT_NAME_INFORMATION = 1, + OS_OBJECT_TYPE_INFORMATION = 2, + OS_OBJECT_ALL_TYPES_INFORMATION = 3, + OS_OBJECT_HANDLE_INFORMATION = 4 +}; + + +struct os_oa { + uint32_t len; + void * root_dir; + struct pe_unicode_str * obj_name; + uint32_t obj_attr; + void * sec_desc; + void * sec_qos; +}; + + +struct os_iosb { + union { + int32_t status; + void * pointer; + }; + intptr_t info; +}; + + +typedef int32_t __stdcall os_zw_query_object( + __in void * handle, + __in int obj_info_class, + __out void * obj_info, + __in size_t obj_info_length, + __out uint32_t * returned_length __optional); + + +typedef int32_t __stdcall os_zw_open_file( + __out void ** hfile, + __in uint32_t desired_access, + __in struct os_oa * obj_attr, + __out struct os_iosb * io_status_block, + __in uint32_t share_access, + __in uint32_t open_options); + +#endif diff --git a/src/ldso/pe_open_physical_parent_directory.c b/src/ldso/pe_open_physical_parent_directory.c new file mode 100644 index 0000000..7166df5 --- /dev/null +++ b/src/ldso/pe_open_physical_parent_directory.c @@ -0,0 +1,105 @@ +/*****************************************************************************/ +/* 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" + +int32_t pe_open_physical_parent_directory( + __out void ** hparent, + __in void * href, + __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; + wchar16_t * wch; + wchar16_t * root; + struct pe_unicode_str * path; + uint32_t len; + void * hntdll; + os_zw_query_object * zw_query_object; + os_zw_open_file * zw_open_file; + + + /* init */ + path = (struct pe_unicode_str *)buffer; + + if (!(hntdll = pe_get_ntdll_module_handle())) + return OS_STATUS_INTERNAL_ERROR; + + if (!(zw_query_object = (os_zw_query_object *)pe_get_procedure_address( + hntdll,"ZwQueryObject"))) + 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 base directory */ + if ((status = zw_query_object( + href, + OS_OBJECT_NAME_INFORMATION, + path, + buffer_size, + &len))) + return status; + + /* integrity */ + if (len == sizeof(struct pe_unicode_str)) + return OS_STATUS_BAD_FILE_TYPE; + + /* device root directory */ + root = path->buffer; + wch = path->buffer + (path->strlen / sizeof(uint16_t)); + + + if ((root[0] != '\\') + || (root[1] != 'D') || (root[2] != 'e') + || (root[3] != 'v') || (root[4] != 'i') + || (root[5] != 'c') || (root[6] != 'e') + || (root[7] != '\\')) + return OS_STATUS_INTERNAL_ERROR; + + for (root=&root[8]; (rootbuffer) * sizeof(uint16_t)) == path->strlen) + return OS_STATUS_MORE_PROCESSING_REQUIRED; + + /* physical parent directory path */ + for (; (wch>root) && (wch[-1]!='\\'); ) + wch--; + + path->strlen = sizeof(uint16_t) * (uint16_t)(wch-path->buffer); + path->maxlen = 0; + + /* oa */ + oa.len = sizeof(struct os_oa); + oa.root_dir = 0; + oa.obj_name = path; + 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 parent directory */ + return zw_open_file( + hparent, + desired_access, + &oa, + &iosb, + OS_FILE_SHARE_READ | OS_FILE_SHARE_WRITE, + open_options | OS_FILE_DIRECTORY_FILE); +} -- cgit v1.2.3