Blame src/process/ntapi_tt_create_remote_process_params.c

dd89bb
/********************************************************/
dd89bb
/*  ntapi: Native API core library                      */
64e606
/*  Copyright (C) 2013--2021  SysDeer Technologies, LLC */
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
int32_t	__stdcall __ntapi_tt_create_remote_process_params(
dd89bb
	__in	void *				hprocess,
dd89bb
	__out 	nt_process_parameters **	rprocess_params,
dd89bb
	__in	nt_unicode_string *		image_file,
dd89bb
	__in	nt_unicode_string *		dll_path		__optional,
dd89bb
	__in	nt_unicode_string *		current_directory	__optional,
dd89bb
	__in	nt_unicode_string *		command_line		__optional,
dd89bb
	__in	wchar16_t *			environment 		__optional,
dd89bb
	__in	nt_unicode_string *		window_title		__optional,
dd89bb
	__in	nt_unicode_string *		desktop_info		__optional,
dd89bb
	__in	nt_unicode_string *		shell_info		__optional,
dd89bb
	__in	nt_unicode_string *		runtime_data		__optional)
dd89bb
{
dd89bb
	#define __ALIGN_ALLOC_SIZE \
dd89bb
		process_params.alloc_size += sizeof(uintptr_t) - 1; \
dd89bb
		process_params.alloc_size /= sizeof(uintptr_t); \
dd89bb
		process_params.alloc_size *= sizeof(uintptr_t);
dd89bb
dd89bb
	int32_t		status;
dd89bb
dd89bb
	ptrdiff_t	d_image;
dd89bb
	ptrdiff_t	d_dll_path;
dd89bb
	ptrdiff_t	d_cwd;
dd89bb
	ptrdiff_t	d_cmd_line;
dd89bb
	ptrdiff_t	d_environment;
dd89bb
	ptrdiff_t	d_runtime;
dd89bb
	/*
dd89bb
	ptrdiff_t	d_wnd_title;
dd89bb
	ptrdiff_t	d_desktop;
dd89bb
	ptrdiff_t	d_shell;
dd89bb
	*/
dd89bb
dd89bb
	wchar16_t *	wch;
dd89bb
	size_t		env_block_size;
dd89bb
	size_t		params_block_size;
dd89bb
	size_t		bytes_written;
dd89bb
dd89bb
	nt_process_parameters	process_params;
dd89bb
	nt_process_parameters *	params_block;
dd89bb
	nt_process_parameters *	rparams_block;
dd89bb
	nt_process_parameters *	params_default;
dd89bb
c713d8
	/* unused params */
c713d8
	(void)window_title;
c713d8
	(void)desktop_info;
c713d8
	(void)shell_info;
c713d8
dd89bb
	/* make the compiler happy */
dd89bb
	d_image		= 0;
dd89bb
	d_dll_path	= 0;
dd89bb
	d_cwd		= 0;
dd89bb
	d_cmd_line	= 0;
dd89bb
	d_environment	= 0;
dd89bb
	d_runtime	= 0;
dd89bb
	env_block_size	= 0;
dd89bb
dd89bb
	/* initialize */
dd89bb
	__ntapi->tt_aligned_block_memset(
dd89bb
		&process_params,
dd89bb
		0,sizeof(nt_process_parameters));
dd89bb
dd89bb
	/* allow for extended structures (newer OS versions) */
dd89bb
	process_params.alloc_size = sizeof(nt_process_parameters)
dd89bb
					+ 8 * sizeof(uintptr_t);
dd89bb
dd89bb
	params_default = ((nt_peb *)pe_get_peb_address())->process_params;
dd89bb
dd89bb
	/* image_file */
dd89bb
	if (image_file) {
dd89bb
		/* check alignment and sanity */
dd89bb
		if ((uintptr_t)image_file->buffer % sizeof(uintptr_t))
dd89bb
			return NT_STATUS_INVALID_PARAMETER_2;
dd89bb
		else if (image_file->maxlen < image_file->strlen)
dd89bb
			return NT_STATUS_INVALID_PARAMETER_2;
dd89bb
dd89bb
		process_params.image_file_name.strlen = image_file->strlen;
dd89bb
		process_params.image_file_name.maxlen = image_file->maxlen;
dd89bb
dd89bb
		/* store offset and update alloc_size */
dd89bb
		d_image = process_params.alloc_size;
dd89bb
		process_params.alloc_size += image_file->maxlen;
dd89bb
		__ALIGN_ALLOC_SIZE;
dd89bb
	}
dd89bb
dd89bb
	/* dll_path */
dd89bb
	if (!dll_path)
dd89bb
		dll_path = &(params_default->dll_path);
dd89bb
dd89bb
	if (dll_path) {
dd89bb
		/* check alignment and sanity */
dd89bb
		if ((uintptr_t)dll_path->buffer % sizeof(uintptr_t))
dd89bb
			return NT_STATUS_INVALID_PARAMETER_3;
dd89bb
		else if (dll_path->maxlen < dll_path->strlen)
dd89bb
			return NT_STATUS_INVALID_PARAMETER_3;
dd89bb
dd89bb
		process_params.dll_path.strlen = dll_path->strlen;
dd89bb
		process_params.dll_path.maxlen = dll_path->maxlen;
dd89bb
dd89bb
		/* store offset and update alloc_size */
dd89bb
		d_dll_path = process_params.alloc_size;
dd89bb
		process_params.alloc_size += dll_path->maxlen;
dd89bb
		__ALIGN_ALLOC_SIZE;
dd89bb
	}
dd89bb
dd89bb
	/* current_directory */
dd89bb
	if (!current_directory)
dd89bb
		current_directory = &(params_default->cwd_name);
dd89bb
dd89bb
	if (current_directory) {
dd89bb
		/* check alignment and sanity */
dd89bb
		if ((uintptr_t)current_directory->buffer % sizeof(uintptr_t))
dd89bb
			return NT_STATUS_INVALID_PARAMETER_4;
dd89bb
		else if (current_directory->maxlen < current_directory->strlen)
dd89bb
			return NT_STATUS_INVALID_PARAMETER_4;
dd89bb
dd89bb
		process_params.cwd_name.strlen = current_directory->strlen;
dd89bb
		process_params.cwd_name.maxlen = current_directory->maxlen;
dd89bb
dd89bb
		/* store offset and update alloc_size */
dd89bb
		d_cwd = process_params.alloc_size;
dd89bb
		process_params.alloc_size += current_directory->maxlen;
dd89bb
		__ALIGN_ALLOC_SIZE;
dd89bb
	}
dd89bb
dd89bb
	/* command_line */
dd89bb
	if (command_line) {
dd89bb
		/* check alignment and sanity */
dd89bb
		if ((uintptr_t)command_line->buffer % sizeof(uintptr_t))
dd89bb
			return NT_STATUS_INVALID_PARAMETER_5;
dd89bb
		else if (command_line->maxlen < command_line->strlen)
dd89bb
			return NT_STATUS_INVALID_PARAMETER_5;
dd89bb
dd89bb
		process_params.command_line.strlen = command_line->strlen;
dd89bb
		process_params.command_line.maxlen = command_line->maxlen;
dd89bb
dd89bb
		/* store offset and update alloc_size */
dd89bb
		d_cmd_line = process_params.alloc_size;
dd89bb
		process_params.alloc_size += command_line->maxlen;
dd89bb
		__ALIGN_ALLOC_SIZE;
dd89bb
	}
dd89bb
dd89bb
	/* environment */
dd89bb
	if (environment) {
dd89bb
		/* check alignment */
dd89bb
		if ((uintptr_t)environment % sizeof(uintptr_t))
dd89bb
			return NT_STATUS_INVALID_PARAMETER_6;
dd89bb
dd89bb
		/* obtain size of environment block */
dd89bb
		wch = environment;
dd89bb
dd89bb
		while (*wch) {
dd89bb
			/* reach the end of the current variable */
dd89bb
			while (*wch++)
dd89bb
			/* proceed to the next variable */
dd89bb
			wch++;
dd89bb
		}
dd89bb
dd89bb
		env_block_size = (uintptr_t)wch - (uintptr_t)environment;
dd89bb
dd89bb
		/* store offset and update alloc_size */
dd89bb
		d_environment = process_params.alloc_size;
dd89bb
		process_params.alloc_size += (uint32_t)env_block_size + 0x1000;
dd89bb
		__ALIGN_ALLOC_SIZE;
dd89bb
	}
dd89bb
dd89bb
	/* runtime_data */
dd89bb
	if (runtime_data) {
dd89bb
		/* check alignment and sanity */
dd89bb
		if ((uintptr_t)runtime_data->buffer % sizeof(uintptr_t))
dd89bb
			return NT_STATUS_INVALID_PARAMETER_5;
dd89bb
		else if (runtime_data->maxlen < runtime_data->strlen)
dd89bb
			return NT_STATUS_INVALID_PARAMETER_5;
dd89bb
dd89bb
		process_params.runtime_data.strlen = runtime_data->strlen;
dd89bb
		process_params.runtime_data.maxlen = runtime_data->maxlen;
dd89bb
dd89bb
		/* store offset and update alloc_size */
dd89bb
		d_runtime = process_params.alloc_size;
dd89bb
		process_params.alloc_size += runtime_data->maxlen;
dd89bb
		__ALIGN_ALLOC_SIZE;
dd89bb
	}
dd89bb
dd89bb
	/* allocate local and remote process parameters blocks */
dd89bb
	params_block = (nt_process_parameters *)0;
dd89bb
	rparams_block = (nt_process_parameters *)0;
dd89bb
dd89bb
	process_params.used_size = process_params.alloc_size;
dd89bb
	params_block_size = process_params.alloc_size;
dd89bb
dd89bb
	/* local block */
dd89bb
	status = __ntapi->zw_allocate_virtual_memory(
dd89bb
		NT_CURRENT_PROCESS_HANDLE,
dd89bb
		(void **)&params_block,
dd89bb
		0,
dd89bb
		&params_block_size,
dd89bb
		NT_MEM_COMMIT,
dd89bb
		NT_PAGE_READWRITE);
dd89bb
dd89bb
	if (status != NT_STATUS_SUCCESS)
dd89bb
		return status;
dd89bb
dd89bb
	process_params.alloc_size = (uint32_t)params_block_size;
dd89bb
	__ntapi->tt_aligned_block_memset(params_block,0,params_block_size);
dd89bb
dd89bb
	/* remote block */
dd89bb
	status = __ntapi->zw_allocate_virtual_memory(
dd89bb
		hprocess,
dd89bb
		(void **)&rparams_block,
dd89bb
		0,
dd89bb
		&params_block_size,
dd89bb
		NT_MEM_RESERVE | NT_MEM_COMMIT,
dd89bb
		NT_PAGE_READWRITE);
dd89bb
dd89bb
	if (status != NT_STATUS_SUCCESS) {
dd89bb
		__ntapi->zw_free_virtual_memory(
dd89bb
			NT_CURRENT_PROCESS_HANDLE,
dd89bb
			(void **)&params_block,
dd89bb
			(size_t *)&process_params.alloc_size,
dd89bb
			NT_MEM_RELEASE);
dd89bb
dd89bb
		return status;
dd89bb
	}
dd89bb
dd89bb
	/* copy the process_params structure */
dd89bb
	__ntapi->tt_aligned_memcpy_utf16(
dd89bb
		(uintptr_t *)params_block,
dd89bb
		(uintptr_t *)&process_params,
dd89bb
		sizeof(nt_process_parameters));
dd89bb
dd89bb
	/* image_file */
dd89bb
	if (image_file) {
dd89bb
		params_block->image_file_name.buffer =
dd89bb
			(uint16_t *)pe_va_from_rva(rparams_block,d_image);
dd89bb
dd89bb
		__ntapi->tt_aligned_memcpy_utf16(
dd89bb
			(uintptr_t *)pe_va_from_rva(params_block,d_image),
dd89bb
			(uintptr_t *)image_file->buffer,
dd89bb
			image_file->strlen);
dd89bb
	}
dd89bb
dd89bb
	/* dll_path */
dd89bb
	if (dll_path) {
dd89bb
		params_block->dll_path.buffer =
dd89bb
			(uint16_t *)pe_va_from_rva(rparams_block,d_dll_path);
dd89bb
dd89bb
		__ntapi->tt_aligned_memcpy_utf16(
dd89bb
			(uintptr_t *)pe_va_from_rva(params_block,d_dll_path),
dd89bb
			(uintptr_t *)dll_path->buffer,
dd89bb
			dll_path->strlen);
dd89bb
	}
dd89bb
dd89bb
	/* current_directory */
dd89bb
	if (current_directory) {
dd89bb
		params_block->cwd_name.buffer =
dd89bb
			(uint16_t *)pe_va_from_rva(rparams_block,d_cwd);
dd89bb
dd89bb
		__ntapi->tt_aligned_memcpy_utf16(
dd89bb
			(uintptr_t *)pe_va_from_rva(params_block,d_cwd),
dd89bb
			(uintptr_t *)current_directory->buffer,
dd89bb
			current_directory->strlen);
dd89bb
	}
dd89bb
dd89bb
	/* command_line */
dd89bb
	if (command_line) {
dd89bb
		params_block->command_line.buffer =
dd89bb
			(uint16_t *)pe_va_from_rva(rparams_block,d_cmd_line);
dd89bb
dd89bb
		__ntapi->tt_aligned_memcpy_utf16(
dd89bb
			(uintptr_t *)pe_va_from_rva(params_block,d_cmd_line),
dd89bb
			(uintptr_t *)command_line->buffer,
dd89bb
			command_line->strlen);
dd89bb
	}
dd89bb
dd89bb
	/* environment */
dd89bb
	if (environment) {
dd89bb
		params_block->environment =
dd89bb
			(wchar16_t *)pe_va_from_rva(rparams_block,d_environment);
dd89bb
dd89bb
		__ntapi->tt_aligned_memcpy_utf16(
dd89bb
			(uintptr_t *)pe_va_from_rva(params_block,d_environment),
dd89bb
			(uintptr_t *)environment,
dd89bb
			env_block_size);
dd89bb
	}
dd89bb
dd89bb
	/* runtime_data */
dd89bb
	if (runtime_data) {
dd89bb
		params_block->runtime_data.buffer =
dd89bb
			(uint16_t *)pe_va_from_rva(rparams_block,d_runtime);
dd89bb
dd89bb
		__ntapi->tt_aligned_memcpy_utf16(
dd89bb
			(uintptr_t *)pe_va_from_rva(params_block,d_runtime),
dd89bb
			(uintptr_t *)runtime_data->buffer,
dd89bb
			runtime_data->strlen);
dd89bb
	}
dd89bb
dd89bb
	params_block->flags = 1; /* normalized */
dd89bb
dd89bb
	/* copy the local params block to the remote process */
dd89bb
	status = __ntapi->zw_write_virtual_memory(
dd89bb
		hprocess,
dd89bb
		rparams_block,
dd89bb
		(char *)params_block,
dd89bb
		process_params.alloc_size,
dd89bb
		&bytes_written);
dd89bb
dd89bb
	if (status != NT_STATUS_SUCCESS)
dd89bb
		return status;
dd89bb
dd89bb
	/* free the local params block */
dd89bb
	__ntapi->zw_free_virtual_memory(
dd89bb
		NT_CURRENT_PROCESS_HANDLE,
dd89bb
		(void **)&params_block,
dd89bb
		(size_t *)&process_params.alloc_size,
dd89bb
		NT_MEM_RELEASE);
dd89bb
dd89bb
	/* all done */
dd89bb
	*rprocess_params = rparams_block;
dd89bb
dd89bb
	return NT_STATUS_SUCCESS;
dd89bb
}