Blame src/process/ntapi_tt_create_native_process_v1.c

dd89bb
/********************************************************/
dd89bb
/*  ntapi: Native API core library                      */
4256e2
/*  Copyright (C) 2013--2016  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
7f8d50
	#if (__SIZEOF_POINTER__ == 4)
dd89bb
	wchar16_t		runtime_arg[12] = {
dd89bb
		' ','-','r',' ',
dd89bb
		'i','n','t','e','g','r','a','l'};
7f8d50
	#elif (__SIZEOF_POINTER__ == 8)
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
			&params->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
			&params->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
f154f6
	/* session registration */
f154f6
	if (params->hsession && (params->hsession != NT_INVALID_HANDLE_VALUE))
f154f6
		if ((status = __ntapi->tty_client_process_register(
f154f6
				params->hsession,
f154f6
				params->pbi.unique_process_id,
f154f6
				0,0,0)))
f154f6
			return __tt_create_process_cancel(params,hsection,status);
f154f6
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
}