/********************************************************/ /* ntapi: Native API core library */ /* Copyright (C) 2013--2017 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ /********************************************************/ #include #include #include #include #include #include #include #include #include "ntapi_impl.h" struct __integral_cmdline { struct pe_guid_str_utf16 guid; wchar16_t space1; wchar16_t rarg[2]; wchar16_t space2; wchar16_t addr[2*__SIZEOF_POINTER__]; wchar16_t null; }; static int32_t __tt_create_process_cancel(nt_create_process_params * params, void * hsection, 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); if (hsection) __ntapi->zw_close(hsection); return status; } int32_t __stdcall __ntapi_tt_create_native_process_v1(nt_create_process_params * params) { int32_t status; void * hfile; void * hsection; nt_object_attributes oa_file; nt_object_attributes oa_process; nt_object_attributes oa_thread; nt_unicode_string nt_image; nt_unicode_string nt_cmd_line; nt_process_parameters * rprocess_params; nt_thread_params tparams; nt_io_status_block iosb; nt_section_image_information sii; int fresume_thread; struct __integral_cmdline fcmdline = { { '{',{'3','e','4','3','e','c','8','4'}, '-',{'1','a','f','1'}, '-',{'4','e','d','e'}, '-',{'a','c','d','8'}, '-',{'c','3','d','9','2','0','a','f','c','8','6','8'}, '}' }, #if (__SIZEOF_POINTER__ == 4) ' ',{'-','r'},' ', {'i','n','t','e','g','r','a','l'},0}; #elif (__SIZEOF_POINTER__ == 8) ' ',{'-','r'},' ', {'i','n','t','e','g','r','a','l', '-','r','u','n','t','i','m','e'},0}; #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; /* tparams */ __ntapi->tt_aligned_block_memset( &tparams, 0, sizeof(tparams)); /* 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; } /* legacy tasks */ /* init the oa_file structure */ oa_file.len = sizeof(nt_object_attributes); oa_file.root_dir = (void *)0; oa_file.obj_name = &nt_image; oa_file.obj_attr = 0; oa_file.sec_desc = (nt_security_descriptor *)0; oa_file.sec_qos = (nt_sqos *)0; /* open the file */ if ((status = __ntapi->zw_open_file( &hfile, NT_FILE_EXECUTE | NT_PROCESS_SYNCHRONIZE, &oa_file, &iosb, NT_FILE_SHARE_READ, NT_FILE_SYNCHRONOUS_IO_NONALERT))) return status; /* create the executable section */ hsection = 0; oa_file.obj_name = 0; status = __ntapi->zw_create_section( &hsection, NT_SECTION_ALL_ACCESS, &oa_file,0, NT_PAGE_EXECUTE, NT_SEC_IMAGE, hfile); __ntapi->zw_close(hfile); if (status) return status; /* create the process */ if ((status = __ntapi->zw_create_process( ¶ms->hprocess, NT_PROCESS_ALL_ACCESS, &oa_process, NT_CURRENT_PROCESS_HANDLE, 1,hsection,0,0))) return __tt_create_process_cancel(params,hsection,status); /* obtain stack/heap and entry point information */ if ((status = __ntapi->zw_query_section( hsection, NT_SECTION_IMAGE_INFORMATION, &sii,sizeof(sii),0))) return __tt_create_process_cancel(params,hsection,status); /* obtain process information */ if ((status = __ntapi->zw_query_information_process( tparams.hprocess, NT_PROCESS_BASIC_INFORMATION, ¶ms->pbi,sizeof(params->pbi), 0))) return __tt_create_process_cancel(params,hsection,status); /* create remote process parameters block */ if (!params->process_params) { /* environment */ if (!params->environment) params->environment = __ntapi->tt_get_peb_env_block_utf16(); /* cmd_line */ if (params->rtblock) { nt_cmd_line.strlen = sizeof(fcmdline) - sizeof(fcmdline.null); nt_cmd_line.maxlen = sizeof(fcmdline); nt_cmd_line.buffer = &fcmdline.guid.lbrace; params->cmd_line = &fcmdline.guid.lbrace; } else { if (!params->cmd_line) params->cmd_line = params->image_name; __ntapi->rtl_init_unicode_string( &nt_cmd_line, params->cmd_line); } } fresume_thread = (params->creation_flags_thread ^ 0x01) & 0x01; /* create target thread */ tparams.hprocess = params->hprocess; tparams.start = (nt_thread_start_routine *)sii.entry_point; tparams.obj_attr = &oa_thread; tparams.creation_flags = NT_CREATE_SUSPENDED | NT_CREATE_FIRST_THREAD_OF_PROCESS; tparams.stack_size_commit = sii.stack_commit; tparams.stack_size_reserve = sii.stack_reserve; if ((status = __ntapi->tt_create_remote_thread(&tparams))) return __tt_create_process_cancel(params,hsection,status); /* remote process params */ if ((status = __ntapi->tt_create_remote_process_params( tparams.hprocess, &rprocess_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 __tt_create_process_cancel(params,hsection,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,hsection,status); /* update the target process environment block: */ /* make process_params point to rparams_block */ if ((status = __ntapi->zw_write_virtual_memory( tparams.hprocess, (char *)((uintptr_t)params->pbi.peb_base_address + (uintptr_t)&(((nt_peb *)0)->process_params)), (char *)&rprocess_params, sizeof(uintptr_t),0))) return __tt_create_process_cancel(params,hsection,status); /* rtdata */ if (params->rtblock && (status = __ntapi_tt_create_remote_runtime_data(tparams.hprocess,params->rtblock))) return __tt_create_process_cancel(params,hsection,status); if (fresume_thread && (status = __ntapi->zw_resume_thread(tparams.hthread,0))) return __tt_create_process_cancel(params,hsection,status); /* all done */ params->hthread = tparams.hthread; params->cid.process_id = params->pbi.unique_process_id; params->cid.thread_id = tparams.cid.thread_id; return status; }