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(). --- src/internal/pe_os.h | 67 +++++++++++++++++ src/ldso/pe_open_physical_parent_directory.c | 105 +++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 src/internal/pe_os.h create mode 100644 src/ldso/pe_open_physical_parent_directory.c (limited to 'src') 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