|
|
482851 |
/*****************************************************************************/
|
|
|
482851 |
/* pemagination: a (virtual) tour into portable bits and executable bytes */
|
|
|
482851 |
/* Copyright (C) 2013--2017 Z. Gilboa */
|
|
|
482851 |
/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
|
|
|
482851 |
/*****************************************************************************/
|
|
|
482851 |
|
|
|
482851 |
#include <psxtypes/psxtypes.h>
|
|
|
482851 |
#include <pemagine/pemagine.h>
|
|
|
482851 |
#include "pe_os.h"
|
|
|
482851 |
|
|
|
482851 |
static int32_t pe_get_device_dos_drive_letter(
|
|
|
482851 |
void * hntdll,
|
|
|
482851 |
os_zw_query_object * zw_query_object,
|
|
|
482851 |
uintptr_t * dbuffer,
|
|
|
482851 |
uint32_t dbufsize,
|
|
|
482851 |
wchar16_t * devname,
|
|
|
482851 |
size_t devnamelen,
|
|
|
482851 |
wchar16_t * letter)
|
|
|
482851 |
{
|
|
|
482851 |
int32_t status;
|
|
|
482851 |
void * hdevice;
|
|
|
482851 |
int sigh;
|
|
|
482851 |
size_t idx;
|
|
|
482851 |
size_t cap;
|
|
|
482851 |
uint32_t len;
|
|
|
482851 |
struct os_oa oa;
|
|
|
482851 |
struct os_iosb iosb;
|
|
|
482851 |
wchar16_t * src;
|
|
|
482851 |
wchar16_t * dst;
|
|
|
482851 |
struct pe_unicode_str path;
|
|
|
482851 |
struct pe_unicode_str * dpath;
|
|
|
482851 |
os_zw_open_file * zw_open_file;
|
|
|
482851 |
os_zw_close * zw_close;
|
|
|
482851 |
|
|
|
482851 |
wchar16_t namebuf[8] = {
|
|
|
482851 |
'\\','?','?','\\',
|
|
|
482851 |
'X',':','\\',0};
|
|
|
482851 |
|
|
|
482851 |
unsigned char letters[26] = {
|
|
|
482851 |
'C','Z','Y','X','W','V',
|
|
|
482851 |
'E','H','F','G','D','I',
|
|
|
482851 |
'P','Q','R','S','T','U',
|
|
|
482851 |
'J','K','L','M','N','O',
|
|
|
482851 |
'A','B'};
|
|
|
482851 |
|
|
|
482851 |
/* init */
|
|
|
482851 |
if (!(zw_open_file = (os_zw_open_file *)pe_get_procedure_address(
|
|
|
482851 |
hntdll,"ZwOpenFile")))
|
|
|
482851 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
482851 |
|
|
|
482851 |
if (!(zw_close = (os_zw_close *)pe_get_procedure_address(
|
|
|
482851 |
hntdll,"ZwClose")))
|
|
|
482851 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
482851 |
|
|
|
482851 |
/* path */
|
|
|
482851 |
path.buffer = namebuf;
|
|
|
482851 |
path.strlen = 7 * sizeof(wchar16_t);
|
|
|
482851 |
path.maxlen = 0;
|
|
|
482851 |
|
|
|
482851 |
/* oa */
|
|
|
482851 |
oa.len = sizeof(struct os_oa);
|
|
|
482851 |
oa.root_dir = 0;
|
|
|
482851 |
oa.obj_name = &pat;;
|
|
|
482851 |
oa.obj_attr = 0;
|
|
|
482851 |
oa.sec_desc = 0;
|
|
|
482851 |
oa.sec_qos = 0;
|
|
|
482851 |
|
|
|
482851 |
/* just a few rounds of submissiveness */
|
|
|
482851 |
for (sigh=0; sigh<26; sigh++) {
|
|
|
482851 |
namebuf[4] = letters[sigh];
|
|
|
482851 |
|
|
|
482851 |
status = zw_open_file(
|
|
|
482851 |
&hdevice,
|
|
|
482851 |
OS_SEC_SYNCHRONIZE
|
|
|
482851 |
| OS_FILE_READ_ATTRIBUTES
|
|
|
482851 |
| OS_FILE_READ_ACCESS,
|
|
|
482851 |
&oa,&iosb,
|
|
|
482851 |
OS_FILE_SHARE_READ
|
|
|
482851 |
| OS_FILE_SHARE_WRITE
|
|
|
482851 |
| OS_FILE_SHARE_DELETE,
|
|
|
482851 |
OS_FILE_DIRECTORY_FILE);
|
|
|
482851 |
|
|
|
482851 |
if (status == OS_STATUS_SUCCESS) {
|
|
|
482851 |
status = zw_query_object(
|
|
|
482851 |
hdevice,
|
|
|
482851 |
OS_OBJECT_NAME_INFORMATION,
|
|
|
482851 |
dbuffer,dbufsize,&len;;
|
|
|
482851 |
|
|
|
482851 |
if (status == OS_STATUS_SUCCESS) {
|
|
|
482851 |
dpath = (struct pe_unicode_str *)dbuffer;
|
|
|
482851 |
|
|
|
482851 |
src = devname;
|
|
|
482851 |
dst = dpath->buffer;
|
|
|
482851 |
|
|
|
482851 |
idx = 0;
|
|
|
482851 |
cap = devnamelen / sizeof(wchar16_t);
|
|
|
482851 |
|
|
|
482851 |
for (; idx
|
|
|
482851 |
idx++;
|
|
|
482851 |
|
|
|
482851 |
if (idx==cap && dst[idx]=='\\') {
|
|
|
482851 |
zw_close(hdevice);
|
|
|
482851 |
*letter = letters[sigh];
|
|
|
482851 |
|
|
|
482851 |
return OS_STATUS_SUCCESS;
|
|
|
482851 |
}
|
|
|
482851 |
}
|
|
|
482851 |
|
|
|
482851 |
zw_close(hdevice);
|
|
|
482851 |
}
|
|
|
482851 |
}
|
|
|
482851 |
|
|
|
482851 |
return OS_STATUS_NOT_SUPPORTED;
|
|
|
482851 |
}
|
|
|
482851 |
|
|
|
482851 |
|
|
|
aa2c17 |
static int32_t pe_load_library_impl(
|
|
|
aa2c17 |
void ** baseaddr,
|
|
|
aa2c17 |
void * hdsolib,
|
|
|
aa2c17 |
uintptr_t * buffer,
|
|
|
aa2c17 |
uint32_t bufsize,
|
|
|
aa2c17 |
uint32_t * flags)
|
|
|
482851 |
{
|
|
|
482851 |
int32_t status;
|
|
|
482851 |
struct pe_unicode_str path;
|
|
|
482851 |
struct pe_unicode_str * npath;
|
|
|
482851 |
uintptr_t addr;
|
|
|
482851 |
uintptr_t * dbuffer;
|
|
|
482851 |
uint32_t dbufsize;
|
|
|
482851 |
wchar16_t * ldrdir;
|
|
|
482851 |
wchar16_t * slash;
|
|
|
482851 |
wchar16_t * wch;
|
|
|
482851 |
wchar16_t * cap;
|
|
|
482851 |
wchar16_t letter;
|
|
|
482851 |
uint32_t len;
|
|
|
482851 |
int mup;
|
|
|
482851 |
void * hntdll;
|
|
|
482851 |
os_zw_query_object * zw_query_object;
|
|
|
482851 |
os_ldr_load_dll * ldr_load_dll;
|
|
|
482851 |
|
|
|
482851 |
/* init */
|
|
|
482851 |
if (!(hntdll = pe_get_ntdll_module_handle()))
|
|
|
482851 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
482851 |
|
|
|
482851 |
if (!(zw_query_object = (os_zw_query_object *)pe_get_procedure_address(
|
|
|
482851 |
hntdll,"ZwQueryObject")))
|
|
|
482851 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
482851 |
|
|
|
482851 |
if (!(ldr_load_dll = (os_ldr_load_dll *)pe_get_procedure_address(
|
|
|
482851 |
hntdll,"LdrLoadDll")))
|
|
|
482851 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
482851 |
|
|
|
482851 |
/* loader native path */
|
|
|
482851 |
if ((status = zw_query_object(
|
|
|
aa2c17 |
hdsolib,
|
|
|
482851 |
OS_OBJECT_NAME_INFORMATION,
|
|
|
482851 |
buffer,bufsize,&len)))
|
|
|
482851 |
return status;
|
|
|
482851 |
|
|
|
482851 |
/* integrity */
|
|
|
482851 |
if (len == sizeof(struct pe_unicode_str))
|
|
|
482851 |
return OS_STATUS_BAD_FILE_TYPE;
|
|
|
482851 |
|
|
|
482851 |
/* first sigh */
|
|
|
482851 |
npath = (struct pe_unicode_str *)buffer;
|
|
|
482851 |
|
|
|
482851 |
wch = npath->buffer;
|
|
|
482851 |
cap = npath->buffer + (npath->strlen / sizeof(wchar16_t));
|
|
|
482851 |
|
|
|
482851 |
if ((cap < &wch[8])
|
|
|
482851 |
|| (wch[0] != '\\')
|
|
|
482851 |
|| (wch[1] != 'D')
|
|
|
482851 |
|| (wch[2] != 'e')
|
|
|
482851 |
|| (wch[3] != 'v')
|
|
|
482851 |
|| (wch[4] != 'i')
|
|
|
482851 |
|| (wch[5] != 'c')
|
|
|
482851 |
|| (wch[6] != 'e')
|
|
|
482851 |
|| (wch[7] != '\\'))
|
|
|
482851 |
return OS_STATUS_NOT_SUPPORTED;
|
|
|
482851 |
|
|
|
482851 |
mup = (cap > &wch[11])
|
|
|
482851 |
&& (wch[8]=='M')
|
|
|
482851 |
&& (wch[9]=='u')
|
|
|
482851 |
&& (wch[10]=='p')
|
|
|
482851 |
&& (wch[11]=='\\');
|
|
|
482851 |
|
|
|
482851 |
slash = mup ? &wch[12] : &wch[8];
|
|
|
482851 |
|
|
|
482851 |
for (; (*slash != '\\') && (slash < cap); )
|
|
|
482851 |
slash++;
|
|
|
482851 |
|
|
|
482851 |
if (slash == cap)
|
|
|
482851 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
482851 |
|
|
|
482851 |
if (mup)
|
|
|
482851 |
for (++slash; (*slash != '\\') && (slash < cap); )
|
|
|
482851 |
slash++;
|
|
|
482851 |
|
|
|
482851 |
if (slash == cap)
|
|
|
482851 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
482851 |
|
|
|
482851 |
/* second sigh */
|
|
|
482851 |
addr = (uintptr_t)cap;
|
|
|
482851 |
addr += sizeof(uintptr_t) - 1;
|
|
|
482851 |
addr /= sizeof(uintptr_t);
|
|
|
482851 |
addr *= sizeof(uintptr_t);
|
|
|
482851 |
|
|
|
482851 |
dbuffer = (uintptr_t *)addr;
|
|
|
482851 |
dbufsize = bufsize;
|
|
|
482851 |
dbufsize -= (dbuffer - buffer) * sizeof(uintptr_t);
|
|
|
482851 |
|
|
|
482851 |
if ((status = pe_get_device_dos_drive_letter(
|
|
|
482851 |
hntdll,
|
|
|
482851 |
zw_query_object,
|
|
|
482851 |
dbuffer,dbufsize,
|
|
|
482851 |
npath->buffer,
|
|
|
482851 |
(slash - npath->buffer) * sizeof(wchar16_t),
|
|
|
482851 |
&letter)))
|
|
|
482851 |
return status;
|
|
|
482851 |
|
|
|
482851 |
slash = &slash[-2];
|
|
|
482851 |
slash[0] = letter;
|
|
|
482851 |
slash[1] = ':';
|
|
|
482851 |
|
|
|
482851 |
path.buffer = slash;
|
|
|
482851 |
path.strlen = (cap - slash) * sizeof(wchar16_t);
|
|
|
482851 |
|
|
|
482851 |
/* third sigh */
|
|
|
482851 |
for (slash=cap; (slash > path.buffer) && (*slash != '\\'); )
|
|
|
482851 |
slash--;
|
|
|
482851 |
|
|
|
482851 |
if (slash == path.buffer)
|
|
|
482851 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
482851 |
|
|
|
482851 |
ldrdir = path.buffer;
|
|
|
482851 |
*slash = 0;
|
|
|
482851 |
|
|
|
482851 |
path.strlen -= (++slash - ldrdir) * sizeof(wchar16_t);
|
|
|
482851 |
path.maxlen = path.strlen;
|
|
|
482851 |
path.buffer = slash;
|
|
|
482851 |
|
|
|
482851 |
/* hoppla */
|
|
|
482851 |
return ldr_load_dll(
|
|
|
482851 |
ldrdir,flags,
|
|
|
482851 |
&path,baseaddr);
|
|
|
482851 |
}
|
|
|
aa2c17 |
|
|
|
aa2c17 |
|
|
|
aa2c17 |
int32_t pe_load_framework_loader(
|
|
|
aa2c17 |
void ** baseaddr,
|
|
|
aa2c17 |
struct pe_framework_runtime_data * rtdata,
|
|
|
aa2c17 |
uintptr_t * buffer,
|
|
|
aa2c17 |
uint32_t bufsize,
|
|
|
aa2c17 |
uint32_t * sysflags)
|
|
|
aa2c17 |
{
|
|
|
aa2c17 |
return pe_load_library_impl(
|
|
|
aa2c17 |
baseaddr,
|
|
|
aa2c17 |
rtdata->hloader,
|
|
|
aa2c17 |
buffer,bufsize,
|
|
|
aa2c17 |
sysflags);
|
|
|
aa2c17 |
}
|
|
|
224f38 |
|
|
|
224f38 |
|
|
|
224f38 |
int32_t pe_load_framework_library(
|
|
|
224f38 |
void ** baseaddr,
|
|
|
224f38 |
void * hat,
|
|
|
224f38 |
const wchar16_t * atrelname,
|
|
|
224f38 |
uintptr_t * buffer,
|
|
|
224f38 |
uint32_t bufsize,
|
|
|
224f38 |
uint32_t * sysflags)
|
|
|
224f38 |
{
|
|
|
224f38 |
int32_t status;
|
|
|
224f38 |
struct pe_unicode_str path;
|
|
|
224f38 |
struct os_oa oa;
|
|
|
224f38 |
struct os_iosb iosb;
|
|
|
224f38 |
const wchar16_t * wch;
|
|
|
224f38 |
const wchar16_t * wch_cap;
|
|
|
224f38 |
void * hdsolib;
|
|
|
224f38 |
void * hntdll;
|
|
|
224f38 |
os_zw_close * zw_close;
|
|
|
224f38 |
os_zw_open_file * zw_open_file;
|
|
|
224f38 |
|
|
|
224f38 |
/* init */
|
|
|
224f38 |
if (!(hntdll = pe_get_ntdll_module_handle()))
|
|
|
224f38 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
224f38 |
|
|
|
224f38 |
if (!(zw_close = (os_zw_close *)pe_get_procedure_address(
|
|
|
224f38 |
hntdll,"ZwClose")))
|
|
|
224f38 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
224f38 |
|
|
|
224f38 |
if (!(zw_open_file = (os_zw_open_file *)pe_get_procedure_address(
|
|
|
224f38 |
hntdll,"ZwOpenFile")))
|
|
|
224f38 |
return OS_STATUS_INTERNAL_ERROR;
|
|
|
224f38 |
|
|
|
224f38 |
/* oa */
|
|
|
224f38 |
oa.len = sizeof(struct os_oa);
|
|
|
224f38 |
oa.root_dir = hat;
|
|
|
224f38 |
oa.obj_name = &pat;;
|
|
|
224f38 |
oa.obj_attr = 0;
|
|
|
224f38 |
oa.sec_desc = 0;
|
|
|
224f38 |
oa.sec_qos = 0;
|
|
|
224f38 |
|
|
|
224f38 |
/* at-relative path */
|
|
|
224f38 |
wch = atrelname;
|
|
|
224f38 |
wch_cap = atrelname + 512;
|
|
|
224f38 |
|
|
|
224f38 |
for (; *wch && wch
|
|
|
224f38 |
wch++;
|
|
|
224f38 |
|
|
|
224f38 |
if (*wch)
|
|
|
224f38 |
return OS_STATUS_NAME_TOO_LONG;
|
|
|
224f38 |
|
|
|
224f38 |
path.buffer = (wchar16_t *)atrelname;
|
|
|
224f38 |
path.strlen = sizeof(wchar16_t) * (wch - atrelname);
|
|
|
224f38 |
path.maxlen = 0;
|
|
|
224f38 |
|
|
|
224f38 |
/* open at */
|
|
|
224f38 |
if ((status = zw_open_file(
|
|
|
224f38 |
&hdsolib,
|
|
|
224f38 |
OS_SEC_SYNCHRONIZE
|
|
|
224f38 |
| OS_FILE_READ_ACCESS
|
|
|
224f38 |
| OS_FILE_READ_ATTRIBUTES,
|
|
|
224f38 |
&oa,&iosb,
|
|
|
224f38 |
OS_FILE_SHARE_READ
|
|
|
224f38 |
| OS_FILE_SHARE_WRITE
|
|
|
224f38 |
| OS_FILE_SHARE_DELETE,
|
|
|
224f38 |
OS_FILE_NON_DIRECTORY_FILE)))
|
|
|
224f38 |
return status;
|
|
|
224f38 |
|
|
|
224f38 |
/* hoppla */
|
|
|
224f38 |
status = pe_load_library_impl(
|
|
|
224f38 |
baseaddr,hdsolib,
|
|
|
224f38 |
buffer,bufsize,
|
|
|
224f38 |
sysflags);
|
|
|
224f38 |
|
|
|
224f38 |
/* all done */
|
|
|
224f38 |
zw_close(hdsolib);
|
|
|
224f38 |
|
|
|
224f38 |
return status;
|
|
|
224f38 |
}
|