|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
/* ntapi: Native API core library */
|
|
|
dd89bb |
/* Copyright (C) 2013,2014,2015 Z. Gilboa */
|
|
|
dd89bb |
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
|
|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
#include <psxtypes/psxtypes.h>
|
|
|
dd89bb |
#include <pemagine/pemagine.h>
|
|
|
dd89bb |
#include <ntapi/nt_status.h>
|
|
|
dd89bb |
#include <ntapi/nt_object.h>
|
|
|
dd89bb |
#include <ntapi/nt_thread.h>
|
|
|
dd89bb |
#include <ntapi/nt_process.h>
|
|
|
dd89bb |
#include <ntapi/nt_string.h>
|
|
|
dd89bb |
#include <ntapi/ntapi.h>
|
|
|
dd89bb |
#include "ntapi_impl.h"
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __tt_create_process_cancel(nt_create_process_params * params, void * hsection, int32_t status)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
if (params->hprocess) {
|
|
|
dd89bb |
__ntapi->zw_terminate_process(params->hprocess,NT_STATUS_INTERNAL_ERROR);
|
|
|
dd89bb |
__ntapi->zw_close(params->hprocess);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
if (params->hthread)
|
|
|
dd89bb |
__ntapi->zw_close(params->hthread);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (hsection)
|
|
|
dd89bb |
__ntapi->zw_close(hsection);
|
|
|
dd89bb |
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_create_native_process_v1(nt_create_process_params * params)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
void * hfile;
|
|
|
dd89bb |
void * hsection;
|
|
|
dd89bb |
|
|
|
dd89bb |
nt_object_attributes oa_file;
|
|
|
dd89bb |
nt_object_attributes oa_process;
|
|
|
dd89bb |
nt_object_attributes oa_thread;
|
|
|
dd89bb |
|
|
|
dd89bb |
nt_unicode_string nt_image;
|
|
|
dd89bb |
nt_unicode_string nt_cmd_line;
|
|
|
dd89bb |
nt_process_parameters * rprocess_params;
|
|
|
dd89bb |
nt_thread_params tparams;
|
|
|
dd89bb |
|
|
|
dd89bb |
nt_io_status_block iosb;
|
|
|
dd89bb |
nt_section_image_information sii;
|
|
|
dd89bb |
|
|
|
dd89bb |
wchar16_t * cmd_line_runtime_buffer;
|
|
|
dd89bb |
size_t cmd_line_runtime_buffer_size;
|
|
|
dd89bb |
int fresume_thread;
|
|
|
dd89bb |
|
|
|
dd89bb |
#if defined (__NT32)
|
|
|
dd89bb |
wchar16_t runtime_arg[12] = {
|
|
|
dd89bb |
' ','-','r',' ',
|
|
|
dd89bb |
'i','n','t','e','g','r','a','l'};
|
|
|
dd89bb |
#elif defined (__NT64)
|
|
|
dd89bb |
wchar16_t runtime_arg[20] = {
|
|
|
dd89bb |
' ','-','r',' ',
|
|
|
dd89bb |
'i','n','t','e','g','r','a','l',
|
|
|
dd89bb |
'-','r','u','n','t','i','m','e'};
|
|
|
dd89bb |
#endif
|
|
|
dd89bb |
|
|
|
dd89bb |
/* validation */
|
|
|
dd89bb |
if (params->cmd_line && params->process_params)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_MIX;
|
|
|
dd89bb |
else if (params->cmd_line && params->rtblock)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_MIX;
|
|
|
dd89bb |
else if (params->environment && params->process_params)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_MIX;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* tparams */
|
|
|
dd89bb |
__ntapi->tt_aligned_block_memset(
|
|
|
dd89bb |
&tparams, 0, sizeof(tparams));
|
|
|
dd89bb |
|
|
|
dd89bb |
/* image_name */
|
|
|
dd89bb |
__ntapi->rtl_init_unicode_string(
|
|
|
dd89bb |
&nt_image,
|
|
|
dd89bb |
params->image_name);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* oa_process */
|
|
|
dd89bb |
if (!params->obj_attr_process) {
|
|
|
dd89bb |
__ntapi->tt_aligned_block_memset(
|
|
|
dd89bb |
&oa_process,0,sizeof(oa_process));
|
|
|
dd89bb |
|
|
|
dd89bb |
oa_process.len = sizeof(oa_process);
|
|
|
dd89bb |
params->obj_attr_process = &oa_process;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* oa_thread */
|
|
|
dd89bb |
if (!params->obj_attr_thread) {
|
|
|
dd89bb |
__ntapi->tt_aligned_block_memset(
|
|
|
dd89bb |
&oa_thread,0,sizeof(oa_thread));
|
|
|
dd89bb |
|
|
|
dd89bb |
oa_thread.len = sizeof(oa_thread);
|
|
|
dd89bb |
params->obj_attr_thread = &oa_thread;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* legacy tasks */
|
|
|
dd89bb |
/* init the oa_file structure */
|
|
|
dd89bb |
oa_file.len = sizeof(nt_object_attributes);
|
|
|
dd89bb |
oa_file.root_dir = (void *)0;
|
|
|
dd89bb |
oa_file.obj_name = &nt_image;
|
|
|
dd89bb |
oa_file.obj_attr = 0;
|
|
|
dd89bb |
oa_file.sec_desc = (nt_security_descriptor *)0;
|
|
|
dd89bb |
oa_file.sec_qos = (nt_sqos *)0;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* open the file */
|
|
|
dd89bb |
if ((status = __ntapi->zw_open_file(
|
|
|
dd89bb |
&hfile,
|
|
|
dd89bb |
NT_FILE_EXECUTE | NT_PROCESS_SYNCHRONIZE,
|
|
|
dd89bb |
&oa_file,
|
|
|
dd89bb |
&iosb,
|
|
|
dd89bb |
NT_FILE_SHARE_READ,
|
|
|
dd89bb |
NT_FILE_SYNCHRONOUS_IO_NONALERT)))
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* create the executable section */
|
|
|
dd89bb |
hsection = 0;
|
|
|
dd89bb |
oa_file.obj_name = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
status = __ntapi->zw_create_section(
|
|
|
dd89bb |
&hsection,
|
|
|
dd89bb |
NT_SECTION_ALL_ACCESS,
|
|
|
dd89bb |
&oa_file,0,
|
|
|
dd89bb |
NT_PAGE_EXECUTE,
|
|
|
dd89bb |
NT_SEC_IMAGE,
|
|
|
dd89bb |
hfile);
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi->zw_close(hfile);
|
|
|
dd89bb |
if (status) return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* create the process */
|
|
|
dd89bb |
if ((status = __ntapi->zw_create_process(
|
|
|
dd89bb |
¶ms->hprocess,
|
|
|
dd89bb |
NT_PROCESS_ALL_ACCESS,
|
|
|
dd89bb |
&oa_process,
|
|
|
dd89bb |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
dd89bb |
1,hsection,0,0)))
|
|
|
dd89bb |
return __tt_create_process_cancel(params,hsection,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* obtain stack/heap and entry point information */
|
|
|
dd89bb |
if ((status = __ntapi->zw_query_section(
|
|
|
dd89bb |
hsection,
|
|
|
dd89bb |
NT_SECTION_IMAGE_INFORMATION,
|
|
|
dd89bb |
&sii,sizeof(sii),0)))
|
|
|
dd89bb |
return __tt_create_process_cancel(params,hsection,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* obtain process information */
|
|
|
dd89bb |
if ((status = __ntapi->zw_query_information_process(
|
|
|
dd89bb |
tparams.hprocess,
|
|
|
dd89bb |
NT_PROCESS_BASIC_INFORMATION,
|
|
|
dd89bb |
¶ms->pbi,sizeof(params->pbi),
|
|
|
dd89bb |
0)))
|
|
|
dd89bb |
return __tt_create_process_cancel(params,hsection,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* create remote process parameters block */
|
|
|
dd89bb |
if (!params->process_params) {
|
|
|
dd89bb |
/* cmd_line */
|
|
|
dd89bb |
if (!params->cmd_line) {
|
|
|
dd89bb |
params->cmd_line = params->image_name;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi->rtl_init_unicode_string(
|
|
|
dd89bb |
&nt_cmd_line,
|
|
|
dd89bb |
params->cmd_line);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* rtblock */
|
|
|
dd89bb |
if (params->rtblock) {
|
|
|
dd89bb |
cmd_line_runtime_buffer = (wchar16_t *)0;
|
|
|
dd89bb |
cmd_line_runtime_buffer_size = nt_cmd_line.maxlen
|
|
|
dd89bb |
+ sizeof(runtime_arg);
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((status = __ntapi->zw_allocate_virtual_memory(
|
|
|
dd89bb |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
dd89bb |
(void **)&cmd_line_runtime_buffer,
|
|
|
dd89bb |
0,&cmd_line_runtime_buffer_size,
|
|
|
dd89bb |
NT_MEM_RESERVE | NT_MEM_COMMIT,
|
|
|
dd89bb |
NT_PAGE_READWRITE)))
|
|
|
dd89bb |
return __tt_create_process_cancel(params,hsection,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi->tt_memcpy_utf16(
|
|
|
dd89bb |
(wchar16_t *)cmd_line_runtime_buffer,
|
|
|
dd89bb |
(wchar16_t *)nt_cmd_line.buffer,
|
|
|
dd89bb |
nt_cmd_line.strlen);
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi->tt_memcpy_utf16(
|
|
|
dd89bb |
(wchar16_t *)pe_va_from_rva(
|
|
|
dd89bb |
cmd_line_runtime_buffer,
|
|
|
dd89bb |
nt_cmd_line.strlen),
|
|
|
dd89bb |
(wchar16_t *)runtime_arg,
|
|
|
dd89bb |
sizeof(runtime_arg));
|
|
|
dd89bb |
|
|
|
dd89bb |
nt_cmd_line.strlen += sizeof(runtime_arg);
|
|
|
dd89bb |
nt_cmd_line.maxlen += sizeof(runtime_arg);
|
|
|
dd89bb |
nt_cmd_line.buffer = cmd_line_runtime_buffer;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* environment */
|
|
|
dd89bb |
if (!params->environment) {
|
|
|
dd89bb |
params->environment = __ntapi->tt_get_peb_env_block_utf16();
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
fresume_thread = (params->creation_flags_thread ^ 0x01) & 0x01;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* create target thread */
|
|
|
dd89bb |
tparams.hprocess = params->hprocess;
|
|
|
dd89bb |
tparams.start = (nt_thread_start_routine *)sii.entry_point;
|
|
|
dd89bb |
tparams.obj_attr = &oa_thread;
|
|
|
dd89bb |
tparams.creation_flags = NT_CREATE_SUSPENDED | NT_CREATE_FIRST_THREAD_OF_PROCESS;
|
|
|
dd89bb |
tparams.stack_size_commit = sii.stack_commit;
|
|
|
dd89bb |
tparams.stack_size_reserve = sii.stack_reserve;
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((status = __ntapi->tt_create_remote_thread(&tparams)))
|
|
|
dd89bb |
return __tt_create_process_cancel(params,hsection,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* remote process params */
|
|
|
dd89bb |
if ((status = __ntapi->tt_create_remote_process_params(
|
|
|
dd89bb |
tparams.hprocess,
|
|
|
dd89bb |
&rprocess_params,
|
|
|
dd89bb |
&nt_image,
|
|
|
dd89bb |
(nt_unicode_string *)0,
|
|
|
dd89bb |
(nt_unicode_string *)0,
|
|
|
dd89bb |
&nt_cmd_line,
|
|
|
dd89bb |
params->environment,
|
|
|
dd89bb |
(nt_unicode_string *)0,
|
|
|
dd89bb |
(nt_unicode_string *)0,
|
|
|
dd89bb |
(nt_unicode_string *)0,
|
|
|
dd89bb |
(nt_unicode_string *)0)))
|
|
|
dd89bb |
return __tt_create_process_cancel(params,hsection,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* update the target process environment block: */
|
|
|
dd89bb |
/* make process_params point to rparams_block */
|
|
|
dd89bb |
if ((status = __ntapi->zw_write_virtual_memory(
|
|
|
dd89bb |
tparams.hprocess,
|
|
|
dd89bb |
(char *)((uintptr_t)params->pbi.peb_base_address
|
|
|
dd89bb |
+ (uintptr_t)&(((nt_peb *)0)->process_params)),
|
|
|
dd89bb |
(char *)&rprocess_params,
|
|
|
dd89bb |
sizeof(uintptr_t),0)))
|
|
|
dd89bb |
return __tt_create_process_cancel(params,hsection,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* rtdata */
|
|
|
dd89bb |
if (params->rtblock && (status = __ntapi_tt_create_remote_runtime_data(tparams.hprocess,params->rtblock)))
|
|
|
dd89bb |
return __tt_create_process_cancel(params,hsection,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (fresume_thread && (status = __ntapi->zw_resume_thread(tparams.hthread,0)))
|
|
|
dd89bb |
return __tt_create_process_cancel(params,hsection,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* all done */
|
|
|
dd89bb |
params->hthread = tparams.hthread;
|
|
|
dd89bb |
params->cid.process_id = params->pbi.unique_process_id;
|
|
|
dd89bb |
params->cid.thread_id = tparams.thread_id;
|
|
|
dd89bb |
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|