summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/pemagine/pemagine.h9
-rw-r--r--project/common.mk3
-rw-r--r--project/headers.mk3
-rw-r--r--project/tree.mk1
-rw-r--r--src/internal/pe_os.h67
-rw-r--r--src/ldso/pe_open_physical_parent_directory.c105
6 files changed, 186 insertions, 2 deletions
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 <pemagine/pe_structs.h>
+
+#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 <psxtypes/psxtypes.h>
+#include <pemagine/pemagine.h>
+#include <pemagine/pe_structs.h>
+#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]; (root<wch) && (*root!='\\'); )
+ root++;
+
+ if ((uint16_t)((++root - path->buffer) * 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);
+}