From 77cbd46254c491fb56d863494b9102217f297252 Mon Sep 17 00:00:00 2001 From: midipix Date: Sat, 28 Jan 2017 05:15:30 +0000 Subject: ldso: added pe_find_framework_loader(). --- src/ldso/pe_find_framework_loader.c | 271 ++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 src/ldso/pe_find_framework_loader.c (limited to 'src/ldso') diff --git a/src/ldso/pe_find_framework_loader.c b/src/ldso/pe_find_framework_loader.c new file mode 100644 index 0000000..df18655 --- /dev/null +++ b/src/ldso/pe_find_framework_loader.c @@ -0,0 +1,271 @@ +/*****************************************************************************/ +/* 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 "pe_os.h" + +int32_t pe_find_framework_loader( + struct pe_framework_runtime_data * rtdata, + const wchar16_t * basename, + const wchar16_t * rrelname, + void * refaddr, + uintptr_t * buffer, + uint32_t bufsize, + uint32_t flags) +{ + int32_t status; + struct pe_unicode_str path; + struct os_oa oa; + struct os_iosb iosb; + void * himage; + void * himgdir; + void * hdsodir; + void * hloader; + void * hparent; + void * hprevious; + const wchar16_t * wch; + const wchar16_t * wch_cap; + void * hntdll; + os_zw_close * zw_close; + os_zw_open_file * zw_open_file; + + /* init */ + if (!(hntdll = pe_get_ntdll_module_handle())) + return OS_STATUS_INTERNAL_ERROR; + + if (!(zw_close = (os_zw_close *)pe_get_procedure_address( + hntdll,"ZwClose"))) + return OS_STATUS_INTERNAL_ERROR; + + if (!(zw_open_file = (os_zw_open_file *)pe_get_procedure_address( + hntdll,"ZwOpenFile"))) + return OS_STATUS_INTERNAL_ERROR; + + /* flags */ + if (flags == PE_LDSO_INTEGRAL_ONLY) + (void)0; + else if (flags == PE_LDSO_DEFAULT_EXECUTABLE) + (void)0; + else if (flags == PE_LDSO_STANDALONE_EXECUTABLE) + (void)0; + else + return OS_STATUS_INVALID_PARAMETER; + + /* oa */ + oa.len = sizeof(struct os_oa); + oa.root_dir = 0; + oa.obj_name = &path; + oa.obj_attr = OS_OBJ_CASE_INSENSITIVE; + oa.sec_desc = 0; + oa.sec_qos = 0; + + /* standalone executable? */ + if (flags == PE_LDSO_STANDALONE_EXECUTABLE) { + wch = basename; + wch_cap = basename + 512; + + for (; *wch && wchhdsodir = hdsodir; + rtdata->hloader = hloader; + rtdata->himage = himage; + + return OS_STATUS_SUCCESS; + } + + /* root-relative loader path */ + wch = rrelname; + wch_cap = rrelname + 512; + + for (; *wch && wchhroot) { + oa.root_dir = rtdata->hroot; + + if ((status = zw_open_file( + &hloader, + OS_SEC_SYNCHRONIZE + | OS_FILE_READ_ACCESS + | OS_FILE_READ_ATTRIBUTES, + &oa,&iosb, + OS_FILE_SHARE_READ + | OS_FILE_SHARE_WRITE + | OS_FILE_SHARE_DELETE, + OS_FILE_NON_DIRECTORY_FILE))) + return status; + + rtdata->hdsodir = 0; + rtdata->hloader = hloader; + rtdata->himage = himage; + + return OS_STATUS_SUCCESS; + } + + /* integral only and no inherited root directory? */ + if (flags == PE_LDSO_INTEGRAL_ONLY) + return OS_STATUS_COULD_NOT_INTERPRET; + + /* finde Pluto / find Waldo */ + if ((status = pe_open_image_from_addr( + &himage,refaddr, + buffer,bufsize, + 0, + OS_SEC_SYNCHRONIZE + | OS_FILE_READ_ACCESS + | OS_FILE_READ_ATTRIBUTES, + OS_FILE_SHARE_READ + | OS_FILE_SHARE_WRITE + | OS_FILE_SHARE_DELETE, + 0))) + return status; + + if ((status = pe_open_physical_parent_directory( + &himgdir,himage, + buffer,bufsize, + 0, + OS_SEC_SYNCHRONIZE + | OS_FILE_READ_ACCESS + | OS_FILE_READ_ATTRIBUTES, + OS_FILE_SHARE_READ + | OS_FILE_SHARE_WRITE + | OS_FILE_SHARE_DELETE, + 0))) + return status; + + if ((status = pe_open_physical_parent_directory( + &hparent,himgdir, + buffer,bufsize, + OS_OBJ_INHERIT, + OS_SEC_SYNCHRONIZE + | OS_FILE_READ_ACCESS + | OS_FILE_READ_ATTRIBUTES, + OS_FILE_SHARE_READ + | OS_FILE_SHARE_WRITE + | OS_FILE_SHARE_DELETE, + 0))) + return status; + + zw_close(himgdir); + + hloader = 0; + oa.root_dir = hparent; + + status = zw_open_file( + &hloader, + OS_SEC_SYNCHRONIZE + | OS_FILE_READ_ACCESS + | OS_FILE_READ_ATTRIBUTES, + &oa,&iosb, + OS_FILE_SHARE_READ + | OS_FILE_SHARE_WRITE + | OS_FILE_SHARE_DELETE, + OS_FILE_NON_DIRECTORY_FILE); + + while (!hloader) { + if (status == (int32_t)OS_STATUS_OBJECT_NAME_NOT_FOUND) + (void)0; + else if (status == (int32_t)OS_STATUS_OBJECT_PATH_NOT_FOUND) + (void)0; + else + return status; + + hprevious = hparent; + + if ((status = pe_open_physical_parent_directory( + &hparent,hprevious, + buffer,bufsize, + OS_OBJ_INHERIT, + OS_SEC_SYNCHRONIZE + | OS_FILE_READ_ACCESS + | OS_FILE_READ_ATTRIBUTES, + OS_FILE_SHARE_READ + | OS_FILE_SHARE_WRITE + | OS_FILE_SHARE_DELETE, + 0))) + return status; + + oa.root_dir = hparent; + + status = zw_open_file( + &hloader, + OS_SEC_SYNCHRONIZE + | OS_FILE_READ_ACCESS + | OS_FILE_READ_ATTRIBUTES, + &oa,&iosb, + OS_FILE_SHARE_READ + | OS_FILE_SHARE_WRITE + | OS_FILE_SHARE_DELETE, + OS_FILE_NON_DIRECTORY_FILE); + + zw_close(hprevious); + } + + rtdata->hdsodir = 0; + rtdata->hloader = hloader; + rtdata->himage = himage; + rtdata->hroot = hparent; + + return OS_STATUS_SUCCESS; +} -- cgit v1.2.3