diff options
author | midipix <writeonce@midipix.org> | 2017-01-28 05:15:30 +0000 |
---|---|---|
committer | midipix <writeonce@midipix.org> | 2017-01-28 00:26:01 -0500 |
commit | 77cbd46254c491fb56d863494b9102217f297252 (patch) | |
tree | 532a057079f66403057d49c6ed29519f4baf10b7 /src | |
parent | 7cd4117bbe6a97ca13ff81c2ff2a165268bdeb55 (diff) | |
download | pemagine-77cbd46254c491fb56d863494b9102217f297252.tar.bz2 pemagine-77cbd46254c491fb56d863494b9102217f297252.tar.xz |
ldso: added pe_find_framework_loader().
Diffstat (limited to 'src')
-rw-r--r-- | src/internal/pe_os.h | 10 | ||||
-rw-r--r-- | src/ldso/pe_find_framework_loader.c | 271 |
2 files changed, 281 insertions, 0 deletions
diff --git a/src/internal/pe_os.h b/src/internal/pe_os.h index d0dc903..ad26de4 100644 --- a/src/internal/pe_os.h +++ b/src/internal/pe_os.h @@ -9,11 +9,17 @@ #define OS_STATUS_NO_MATCH 0xC0000272 #define OS_STATUS_INVALID_ADDRESS 0xC0000141 #define OS_STATUS_CONTEXT_MISMATCH 0xC0000719 +#define OS_STATUS_COULD_NOT_INTERPRET 0xC00000B9 +#define OS_STATUS_NAME_TOO_LONG 0xC0000106 #define OS_STATUS_INTERNAL_ERROR 0xC00000E5 #define OS_STATUS_BAD_FILE_TYPE 0xC0000903 #define OS_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034 +#define OS_STATUS_OBJECT_PATH_NOT_FOUND 0xC000003A #define OS_STATUS_MORE_PROCESSING_REQUIRED 0xC0000016 +#define OS_OBJ_INHERIT 0x00000002 +#define OS_OBJ_CASE_INSENSITIVE 0x00000040 + #define OS_SEC_SYNCHRONIZE 0x00100000 #define OS_FILE_READ_ACCESS 0x00000001 #define OS_FILE_READ_ATTRIBUTES 0x00000080 @@ -113,6 +119,10 @@ struct os_peb { }; +typedef int32_t __stdcall os_zw_close( + __in void * handle); + + typedef int32_t __stdcall os_zw_query_object( __in void * handle, __in int obj_info_class, 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 <psxtypes/psxtypes.h> +#include <pemagine/pemagine.h> +#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 && wch<wch_cap; wch++) + if ((*wch == '\\') != (*wch == '/')) + return OS_STATUS_INVALID_PARAMETER; + + if (*wch) + return OS_STATUS_NAME_TOO_LONG; + + path.buffer = (wchar16_t *)basename; + path.strlen = sizeof(wchar16_t) * (wch - basename); + path.maxlen = 0; + + 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( + &hdsodir,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; + + oa.root_dir = hdsodir; + + 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 = hdsodir; + rtdata->hloader = hloader; + rtdata->himage = himage; + + return OS_STATUS_SUCCESS; + } + + /* root-relative loader path */ + wch = rrelname; + wch_cap = rrelname + 512; + + for (; *wch && wch<wch_cap; ) + wch++; + + if (*wch) + return OS_STATUS_NAME_TOO_LONG; + + path.buffer = (wchar16_t *)rrelname; + path.strlen = sizeof(wchar16_t) * (wch - rrelname); + path.maxlen = 0; + + /* inherited root directory? */ + if (rtdata->hroot) { + 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; +} |