|
|
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 |
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 |
|
|
|
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 **)¶ms_block,
|
|
|
dd89bb |
0,
|
|
|
dd89bb |
¶ms_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 |
¶ms_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 **)¶ms_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 **)¶ms_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 |
}
|