/********************************************************/ /* ntapi: Native API core library */ /* Copyright (C) 2013--2016 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ /********************************************************/ #include #include #include #include #include #include #include #include #include "ntapi_impl.h" static int32_t __tt_create_process_cancel(nt_create_process_params * params, 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); return status; } int32_t __stdcall __ntapi_tt_create_native_process_v2( __in_out nt_create_process_params * params) { int32_t status; nt_object_attributes oa_process; nt_object_attributes oa_thread; nt_unicode_string nt_image; nt_unicode_string nt_cmd_line; wchar16_t * cmd_line_runtime_buffer; size_t cmd_line_runtime_buffer_size; nt_create_process_info nt_process_info; int fresume_thread; struct { size_t size_in_bytes; nt_create_process_ext_param file_info; } ext_params; #if (__SIZEOF_POINTER__ == 4) wchar16_t runtime_arg[12] = { ' ','-','r',' ', 'i','n','t','e','g','r','a','l'}; #elif (__SIZEOF_POINTER__ == 8) wchar16_t runtime_arg[20] = { ' ','-','r',' ', 'i','n','t','e','g','r','a','l', '-','r','u','n','t','i','m','e'}; #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; /* 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; } /* process_params */ if (!params->process_params) { /* cmd_line */ if (!params->cmd_line) { params->cmd_line = params->image_name; } __ntapi->rtl_init_unicode_string( &nt_cmd_line, params->cmd_line); /* rtdata (alternative to cmd_line) */ if (params->rtblock) { cmd_line_runtime_buffer = (wchar16_t *)0; cmd_line_runtime_buffer_size = nt_cmd_line.maxlen + sizeof(runtime_arg); if ((status = __ntapi->zw_allocate_virtual_memory( NT_CURRENT_PROCESS_HANDLE, (void **)&cmd_line_runtime_buffer, 0,&cmd_line_runtime_buffer_size, NT_MEM_RESERVE | NT_MEM_COMMIT, NT_PAGE_READWRITE))) return status; __ntapi->tt_memcpy_utf16( (wchar16_t *)cmd_line_runtime_buffer, (wchar16_t *)nt_cmd_line.buffer, nt_cmd_line.strlen); __ntapi->tt_memcpy_utf16( (wchar16_t *)pe_va_from_rva( cmd_line_runtime_buffer, nt_cmd_line.strlen), (wchar16_t *)runtime_arg, sizeof(runtime_arg)); nt_cmd_line.strlen += sizeof(runtime_arg); nt_cmd_line.maxlen += sizeof(runtime_arg); nt_cmd_line.buffer = cmd_line_runtime_buffer; } /* environment */ if (!params->environment) params->environment = __ntapi->tt_get_peb_env_block_utf16(); if ((status = __ntapi->rtl_create_process_parameters( ¶ms->process_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 status; __ntapi->rtl_normalize_process_params(params->process_params); } /* create_process_info */ if (!params->create_process_info) { __ntapi->tt_aligned_block_memset( &nt_process_info,0,sizeof(nt_process_info)); nt_process_info.size = sizeof(nt_create_process_info); nt_process_info.state = NT_PROCESS_CREATE_INITIAL_STATE; nt_process_info.init_state.init_flags = NT_PROCESS_CREATE_INFO_OBTAIN_OUTPUT; nt_process_info.init_state.file_access_ext = NT_FILE_READ_ATTRIBUTES|NT_FILE_READ_ACCESS; params->create_process_info = &nt_process_info; } /* create_process_ext_params */ if (!params->create_process_ext_params) { __ntapi->tt_aligned_block_memset( &ext_params,0,sizeof(ext_params)); ext_params.size_in_bytes = sizeof(ext_params); /* file_info */ ext_params.file_info.ext_param_type = NT_CREATE_PROCESS_EXT_PARAM_SET_FILE_NAME; ext_params.file_info.ext_param_size = nt_image.strlen; ext_params.file_info.ext_param_addr = nt_image.buffer; params->create_process_ext_params = (nt_create_process_ext_params *)&ext_params; } params->hprocess = 0; params->hthread = 0; fresume_thread = 0; if (params->rtblock) { fresume_thread = (params->creation_flags_thread ^ 0x01) & 0x01; params->creation_flags_thread |= 0x01; } if (!params->desired_access_process) params->desired_access_process = NT_PROCESS_ALL_ACCESS; if (!params->desired_access_thread) params->desired_access_thread = NT_THREAD_ALL_ACCESS; if ((status = __ntapi->zw_create_user_process( ¶ms->hprocess, ¶ms->hthread, params->desired_access_process, params->desired_access_thread, params->obj_attr_process, params->obj_attr_thread, params->creation_flags_process, params->creation_flags_thread, params->process_params, params->create_process_info, params->create_process_ext_params))) return 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,status); /* tidy up */ __ntapi->zw_close(params->create_process_info->success_state.hfile); __ntapi->zw_close(params->create_process_info->success_state.hsection); if ((status = __ntapi->zw_query_information_process( params->hprocess, NT_PROCESS_BASIC_INFORMATION, ¶ms->pbi,sizeof(params->pbi), 0))) return __tt_create_process_cancel(params,status); if (!params->rtblock) return NT_STATUS_SUCCESS; /* rtdata */ if ((status = __ntapi_tt_create_remote_runtime_data(params->hprocess,params->rtblock))) return __tt_create_process_cancel(params,status); /* conditional resume */ if (fresume_thread && (status = __ntapi->zw_resume_thread(params->hthread,0))) return __tt_create_process_cancel(params,status); return NT_STATUS_SUCCESS; }