/********************************************************/
/* ntapi: Native API core library */
/* Copyright (C) 2013--2021 SysDeer Technologies, LLC */
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
/********************************************************/
#include <psxtypes/psxtypes.h>
#include <pemagine/pemagine.h>
#include <ntapi/nt_status.h>
#include <ntapi/nt_object.h>
#include <ntapi/nt_thread.h>
#include <ntapi/nt_process.h>
#include <ntapi/nt_string.h>
#include <ntapi/ntapi.h>
#include "ntapi_impl.h"
struct __integral_cmdline {
struct pe_guid_str_utf16 guid;
wchar16_t space1;
wchar16_t rarg[2];
wchar16_t space2;
wchar16_t addr[2*__SIZEOF_POINTER__];
wchar16_t null;
};
static int32_t __tt_create_process_cancel(nt_create_process_params * params, void * hsection, int32_t status)
{
if (params->hprocess) {
__ntapi->zw_terminate_process(params->hprocess,NT_STATUS_INTERNAL_ERROR);
__ntapi->zw_close(params->hprocess);
}
if (params->hthread)
__ntapi->zw_close(params->hthread);
if (hsection)
__ntapi->zw_close(hsection);
return status;
}
int32_t __stdcall __ntapi_tt_create_native_process_v1(nt_create_process_params * params)
{
int32_t status;
void * hfile;
void * hsection;
nt_object_attributes oa_file;
nt_object_attributes oa_process;
nt_object_attributes oa_thread;
nt_unicode_string nt_image;
nt_unicode_string nt_cmd_line;
nt_process_parameters * rprocess_params;
nt_thread_params tparams;
nt_io_status_block iosb;
nt_section_image_information sii;
int fresume_thread;
struct __integral_cmdline fcmdline = {
{
'{',{'3','e','4','3','e','c','8','4'},
'-',{'1','a','f','1'},
'-',{'4','e','d','e'},
'-',{'a','c','d','8'},
'-',{'c','3','d','9','2','0','a','f','c','8','6','8'},
'}'
},
#if (__SIZEOF_POINTER__ == 4)
' ',{'-','r'},' ',
{'i','n','t','e','g','r','a','l'},0};
#elif (__SIZEOF_POINTER__ == 8)
' ',{'-','r'},' ',
{'i','n','t','e','g','r','a','l',
'-','r','u','n','t','i','m','e'},0};
#endif
/* validation */
if (params->cmd_line && params->process_params)
return NT_STATUS_INVALID_PARAMETER_MIX;
else if (params->cmd_line && params->rtblock)
return NT_STATUS_INVALID_PARAMETER_MIX;
else if (params->environment && params->process_params)
return NT_STATUS_INVALID_PARAMETER_MIX;
/* tparams */
__ntapi->tt_aligned_block_memset(
&tparams, 0, sizeof(tparams));
/* image_name */
__ntapi->rtl_init_unicode_string(
&nt_image,
params->image_name);
/* oa_process */
if (!params->obj_attr_process) {
__ntapi->tt_aligned_block_memset(
&oa_process,0,sizeof(oa_process));
oa_process.len = sizeof(oa_process);
params->obj_attr_process = &oa_process;
}
/* oa_thread */
if (!params->obj_attr_thread) {
__ntapi->tt_aligned_block_memset(
&oa_thread,0,sizeof(oa_thread));
oa_thread.len = sizeof(oa_thread);
params->obj_attr_thread = &oa_thread;
}
/* legacy tasks */
/* init the oa_file structure */
oa_file.len = sizeof(nt_object_attributes);
oa_file.root_dir = (void *)0;
oa_file.obj_name = &nt_image;
oa_file.obj_attr = 0;
oa_file.sec_desc = (nt_security_descriptor *)0;
oa_file.sec_qos = (nt_sqos *)0;
/* open the file */
if ((status = __ntapi->zw_open_file(
&hfile,
NT_FILE_EXECUTE | NT_PROCESS_SYNCHRONIZE,
&oa_file,
&iosb,
NT_FILE_SHARE_READ,
NT_FILE_SYNCHRONOUS_IO_NONALERT)))
return status;
/* create the executable section */
hsection = 0;
oa_file.obj_name = 0;
status = __ntapi->zw_create_section(
&hsection,
NT_SECTION_ALL_ACCESS,
&oa_file,0,
NT_PAGE_EXECUTE,
NT_SEC_IMAGE,
hfile);
__ntapi->zw_close(hfile);
if (status) return status;
/* create the process */
if ((status = __ntapi->zw_create_process(
¶ms->hprocess,
NT_PROCESS_ALL_ACCESS,
&oa_process,
NT_CURRENT_PROCESS_HANDLE,
1,hsection,0,0)))
return __tt_create_process_cancel(params,hsection,status);
/* obtain stack/heap and entry point information */
if ((status = __ntapi->zw_query_section(
hsection,
NT_SECTION_IMAGE_INFORMATION,
&sii,sizeof(sii),0)))
return __tt_create_process_cancel(params,hsection,status);
/* obtain process information */
if ((status = __ntapi->zw_query_information_process(
tparams.hprocess,
NT_PROCESS_BASIC_INFORMATION,
¶ms->pbi,sizeof(params->pbi),
0)))
return __tt_create_process_cancel(params,hsection,status);
/* create remote process parameters block */
if (!params->process_params) {
/* environment */
if (!params->environment)
params->environment = __ntapi->tt_get_peb_env_block_utf16();
/* cmd_line */
if (params->rtblock) {
nt_cmd_line.strlen = sizeof(fcmdline) - sizeof(fcmdline.null);
nt_cmd_line.maxlen = sizeof(fcmdline);
nt_cmd_line.buffer = &fcmdline.guid.lbrace;
params->cmd_line = &fcmdline.guid.lbrace;
} else {
if (!params->cmd_line)
params->cmd_line = params->image_name;
__ntapi->rtl_init_unicode_string(
&nt_cmd_line,
params->cmd_line);
}
}
fresume_thread = (params->creation_flags_thread ^ 0x01) & 0x01;
/* create target thread */
tparams.hprocess = params->hprocess;
tparams.start = (nt_thread_start_routine *)sii.entry_point;
tparams.obj_attr = &oa_thread;
tparams.creation_flags = NT_CREATE_SUSPENDED | NT_CREATE_FIRST_THREAD_OF_PROCESS;
tparams.stack_size_commit = sii.stack_commit;
tparams.stack_size_reserve = sii.stack_reserve;
if ((status = __ntapi->tt_create_remote_thread(&tparams)))
return __tt_create_process_cancel(params,hsection,status);
/* remote process params */
if ((status = __ntapi->tt_create_remote_process_params(
tparams.hprocess,
&rprocess_params,
&nt_image,
(nt_unicode_string *)0,
(nt_unicode_string *)0,
&nt_cmd_line,
params->environment,
(nt_unicode_string *)0,
(nt_unicode_string *)0,
(nt_unicode_string *)0,
(nt_unicode_string *)0)))
return __tt_create_process_cancel(params,hsection,status);
/* session registration */
if (params->hsession && (params->hsession != NT_INVALID_HANDLE_VALUE))
if ((status = __ntapi->tty_client_process_register(
params->hsession,
params->pbi.unique_process_id,
0,0,0)))
return __tt_create_process_cancel(params,hsection,status);
/* update the target process environment block: */
/* make process_params point to rparams_block */
if ((status = __ntapi->zw_write_virtual_memory(
tparams.hprocess,
(char *)((uintptr_t)params->pbi.peb_base_address
+ (uintptr_t)&(((nt_peb *)0)->process_params)),
(char *)&rprocess_params,
sizeof(uintptr_t),0)))
return __tt_create_process_cancel(params,hsection,status);
/* rtdata */
if (params->rtblock) {
struct _nt_runtime_data * rtdata;
rtdata = (struct _nt_runtime_data *)params->rtblock->addr;
rtdata->flags &= ~NT_RUNTIME_DATA_ARGV_ENVP_RELOCATED;
}
if (params->rtblock && (status = __ntapi_tt_create_remote_runtime_data(tparams.hprocess,params->rtblock)))
return __tt_create_process_cancel(params,hsection,status);
if (fresume_thread && (status = __ntapi->zw_resume_thread(tparams.hthread,0)))
return __tt_create_process_cancel(params,hsection,status);
/* all done */
params->hthread = tparams.hthread;
params->cid.process_id = params->pbi.unique_process_id;
params->cid.thread_id = tparams.cid.thread_id;
return status;
}