From dd89bb8ad4fe184a34b5dbdda237e640fc82121b Mon Sep 17 00:00:00 2001 From: midipix Date: Mon, 27 Jul 2015 04:01:18 -0400 Subject: entered advanced internal development stage. --- src/process/nt32/tt_fork_v1.s | 60 ++++ src/process/nt32/tt_fork_v1_i386.c | 66 ++++ src/process/nt64/tt_fork_v1.s | 134 +++++++++ src/process/nt64/tt_fork_v1_x86_64.asm | 136 +++++++++ src/process/nt64/tt_fork_v2_x86_64.asm | 50 ++++ src/process/ntapi_tt_create_native_process_v1.c | 258 ++++++++++++++++ src/process/ntapi_tt_create_native_process_v2.c | 233 +++++++++++++++ .../ntapi_tt_create_remote_process_params.c | 331 +++++++++++++++++++++ src/process/ntapi_tt_create_remote_runtime_data.c | 178 +++++++++++ src/process/ntapi_tt_fork_v1.c | 218 ++++++++++++++ src/process/ntapi_tt_fork_v2.c | 183 ++++++++++++ src/process/ntapi_tt_get_runtime_data.c | 83 ++++++ src/process/ntapi_tt_init_runtime_data.c | 82 +++++ src/process/ntapi_tt_map_image_as_data.c | 120 ++++++++ src/process/tt_fork_v1.c | 0 15 files changed, 2132 insertions(+) create mode 100644 src/process/nt32/tt_fork_v1.s create mode 100644 src/process/nt32/tt_fork_v1_i386.c create mode 100644 src/process/nt64/tt_fork_v1.s create mode 100644 src/process/nt64/tt_fork_v1_x86_64.asm create mode 100644 src/process/nt64/tt_fork_v2_x86_64.asm create mode 100644 src/process/ntapi_tt_create_native_process_v1.c create mode 100644 src/process/ntapi_tt_create_native_process_v2.c create mode 100644 src/process/ntapi_tt_create_remote_process_params.c create mode 100644 src/process/ntapi_tt_create_remote_runtime_data.c create mode 100644 src/process/ntapi_tt_fork_v1.c create mode 100644 src/process/ntapi_tt_fork_v2.c create mode 100644 src/process/ntapi_tt_get_runtime_data.c create mode 100644 src/process/ntapi_tt_init_runtime_data.c create mode 100644 src/process/ntapi_tt_map_image_as_data.c create mode 100644 src/process/tt_fork_v1.c (limited to 'src/process') diff --git a/src/process/nt32/tt_fork_v1.s b/src/process/nt32/tt_fork_v1.s new file mode 100644 index 0000000..2e2f01d --- /dev/null +++ b/src/process/nt32/tt_fork_v1.s @@ -0,0 +1,60 @@ +########################################################## +## ntapi: Native API core library ## +## Copyright (C) 2013,2014,2015 Z. Gilboa ## +## Released under GPLv2 and GPLv3; see COPYING.NTAPI. ## +########################################################## + +.section .text + +.global ___tt_fork +.global ___tt_fork_child_entry_point +.global @__tt_fork_child_entry_point@4 +.global ___tt_fork_child_entry_point_adj +.global @__tt_fork_child_entry_point_adj@4 + +___tt_fork: +___tt_fork_prolog: + push %ebp + mov %esp, %ebp + +___tt_fork_save_regs: + push %ecx + push %edx + push %ebx + push %esi + push %edi + +___tt_fork_impl_call: + mov %esp, %ecx + mov $0, %edx + call @__tt_fork_impl@8 + +___tt_fork_restore_regs: + pop %edi + pop %esi + pop %ebx + pop %edx + pop %ecx + +___tt_fork_epilog: + mov %ebp, %esp + pop %ebp + ret + +___tt_fork_child_entry_point: +@__tt_fork_child_entry_point@4: +___tt_fork_child_entry_point_adj: +@__tt_fork_child_entry_point_adj@4: + xor %eax, %eax + mov %ecx, %esp + +___tt_fork_child_restore_regs: + pop %edi + pop %esi + pop %ebx + pop %edx + pop %ecx + +___tt_fork_child_epilog: + pop %ebp + ret diff --git a/src/process/nt32/tt_fork_v1_i386.c b/src/process/nt32/tt_fork_v1_i386.c new file mode 100644 index 0000000..34b813e --- /dev/null +++ b/src/process/nt32/tt_fork_v1_i386.c @@ -0,0 +1,66 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#include + +#if (__COMPILER__ == __MSVC__) && defined(__X86_MODEL) + +intptr_t __fastcall __tt_fork_impl( + __in uintptr_t saved_regs_stack_pointer, + __in uintptr_t stack_adjustment); + +int32_t __declspec(naked) __cdecl __tt_fork(void) +{ + __asm { + push ebp + mov ebp, esp + + push ecx + push edx + push ebx + push esi + push edi + + mov ecx, esp + call __tt_fork_impl + + pop edi + pop esi + pop ebx + pop edx + pop ecx + + mov esp, ebp + pop ebp + ret + }; +} + +void __declspec(naked) __fastcall __tt_fork_child_entry_point(uintptr_t esp_saved) +{ + __asm { + xor eax, eax + mov esp, ecx + + pop edi + pop esi + pop ebx + pop edx + pop ecx + + pop ebp + ret + }; +} + +void __declspec(naked) __fastcall __tt_fork_child_entry_point_adj(uintptr_t esp_saved) +{ + __asm { + jmp __tt_fork_child_entry_point + }; +} + +#endif diff --git a/src/process/nt64/tt_fork_v1.s b/src/process/nt64/tt_fork_v1.s new file mode 100644 index 0000000..5f09463 --- /dev/null +++ b/src/process/nt64/tt_fork_v1.s @@ -0,0 +1,134 @@ +########################################################## +## ntapi: Native API core library ## +## Copyright (C) 2013,2014,2015 Z. Gilboa ## +## Released under GPLv2 and GPLv3; see COPYING.NTAPI. ## +########################################################## + +.section .text + +.global __tt_fork_v1 +.global __tt_fork_child_entry_point +.global __tt_fork_child_entry_point_adj + +__tt_fork_v1: +__tt_fork_save_regs: + push %rbp + push %rcx + push %rdx + push %rbx + push %rsi + push %rdi + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 + + sub 0x40,%rsp + + mov %rsp, %rdx + and $0xf, %rdx + test %rdx, %rdx + jne __tt_fork_impl_adj_call + +__tt_fork_impl_call: + mov %rsp, %rcx + call __tt_fork_impl_v1 + + add 0x40,%rsp + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rdi + pop %rsi + pop %rbx + pop %rdx + pop %rcx + pop %rbp + + ret + +__tt_fork_impl_adj_call: + push %rdi + + mov %rsp, %rcx + call __tt_fork_impl_v1 + + pop %rdi + + add 0x40,%rsp + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rdi + pop %rsi + pop %rbx + pop %rdx + pop %rcx + pop %rbp + + ret + + +__tt_fork_child_entry_point: + xor %rax, %rax + mov %rcx, %rsp + + add 0x40,%rsp + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rdi + pop %rsi + pop %rbx + pop %rdx + pop %rcx + pop %rbp + + ret + +__tt_fork_child_entry_point_adj: + xor %rax, %rax + mov %rcx, %rsp + + pop %rdi + + add 0x40,%rsp + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rdi + pop %rsi + pop %rbx + pop %rdx + pop %rcx + pop %rbp + + ret diff --git a/src/process/nt64/tt_fork_v1_x86_64.asm b/src/process/nt64/tt_fork_v1_x86_64.asm new file mode 100644 index 0000000..f79131e --- /dev/null +++ b/src/process/nt64/tt_fork_v1_x86_64.asm @@ -0,0 +1,136 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +TITLE tt_fork_x86_64 + +.data +__tt_fork_impl_v1 PROTO C + +.code +__tt_fork_v1 PROC + push rbp + push rcx + push rdx + push rbx + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + + sub rsp, 40h + + mov rdx, rsp + and rdx, 15 + test rdx, rdx + jne __tt_fork_impl_adj_call + + mov rcx, rsp + call __tt_fork_impl_v1 + + add rsp, 40h + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rbx + pop rdx + pop rcx + pop rbp + ret +__tt_fork_v1 ENDP + +__tt_fork_impl_adj_call PROC + push rdi + + mov rcx, rsp + mov rdx, 1 + call __tt_fork_impl_v1 + + pop rdi + + add rsp, 40h + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rbx + pop rdx + pop rcx + pop rbp + ret +__tt_fork_impl_adj_call ENDP + + +__tt_fork_child_entry_point PROC + xor rax, rax + mov rsp, rcx + + add rsp, 40h + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rbx + pop rdx + pop rcx + pop rbp + ret +__tt_fork_child_entry_point ENDP + + +__tt_fork_child_entry_point_adj PROC + xor rax, rax + mov rsp, rcx + + pop rdi + + add rsp, 40h + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rbx + pop rdx + pop rcx + pop rbp + ret +__tt_fork_child_entry_point_adj ENDP + +END diff --git a/src/process/nt64/tt_fork_v2_x86_64.asm b/src/process/nt64/tt_fork_v2_x86_64.asm new file mode 100644 index 0000000..cc6e353 --- /dev/null +++ b/src/process/nt64/tt_fork_v2_x86_64.asm @@ -0,0 +1,50 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +TITLE tt_fork_x86_64 + +.data +__tt_fork_impl_v2 PROTO C + +.code +__tt_fork_v2 PROC + push rbp + push rcx + push rdx + push rbx + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + + sub rsp, 40h + call __tt_fork_impl_v2 + add rsp, 40h + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rbx + pop rdx + pop rcx + pop rbp + ret +__tt_fork_v2 ENDP + +END diff --git a/src/process/ntapi_tt_create_native_process_v1.c b/src/process/ntapi_tt_create_native_process_v1.c new file mode 100644 index 0000000..b2572cc --- /dev/null +++ b/src/process/ntapi_tt_create_native_process_v1.c @@ -0,0 +1,258 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 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, 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; + + wchar16_t * cmd_line_runtime_buffer; + size_t cmd_line_runtime_buffer_size; + int fresume_thread; + + #if defined (__NT32) + wchar16_t runtime_arg[12] = { + ' ','-','r',' ', + 'i','n','t','e','g','r','a','l'}; + #elif defined (__NT64) + 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; + + /* 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) { + /* cmd_line */ + if (!params->cmd_line) { + params->cmd_line = params->image_name; + } + + __ntapi->rtl_init_unicode_string( + &nt_cmd_line, + params->cmd_line); + + /* rtblock */ + 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 __tt_create_process_cancel(params,hsection,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(); + } + } + + 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); + + /* 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.thread_id; + + return status; +} diff --git a/src/process/ntapi_tt_create_native_process_v2.c b/src/process/ntapi_tt_create_native_process_v2.c new file mode 100644 index 0000000..49fbaf7 --- /dev/null +++ b/src/process/ntapi_tt_create_native_process_v2.c @@ -0,0 +1,233 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 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 defined (__NT32) + wchar16_t runtime_arg[12] = { + ' ','-','r',' ', + 'i','n','t','e','g','r','a','l'}; + #elif defined (__NT64) + 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; + + 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; +} diff --git a/src/process/ntapi_tt_create_remote_process_params.c b/src/process/ntapi_tt_create_remote_process_params.c new file mode 100644 index 0000000..3ff8711 --- /dev/null +++ b/src/process/ntapi_tt_create_remote_process_params.c @@ -0,0 +1,331 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ntapi_impl.h" + +int32_t __stdcall __ntapi_tt_create_remote_process_params( + __in void * hprocess, + __out nt_process_parameters ** rprocess_params, + __in nt_unicode_string * image_file, + __in nt_unicode_string * dll_path __optional, + __in nt_unicode_string * current_directory __optional, + __in nt_unicode_string * command_line __optional, + __in wchar16_t * environment __optional, + __in nt_unicode_string * window_title __optional, + __in nt_unicode_string * desktop_info __optional, + __in nt_unicode_string * shell_info __optional, + __in nt_unicode_string * runtime_data __optional) +{ + #define __ALIGN_ALLOC_SIZE \ + process_params.alloc_size += sizeof(uintptr_t) - 1; \ + process_params.alloc_size /= sizeof(uintptr_t); \ + process_params.alloc_size *= sizeof(uintptr_t); + + int32_t status; + + ptrdiff_t d_image; + ptrdiff_t d_dll_path; + ptrdiff_t d_cwd; + ptrdiff_t d_cmd_line; + ptrdiff_t d_environment; + ptrdiff_t d_runtime; + /* + ptrdiff_t d_wnd_title; + ptrdiff_t d_desktop; + ptrdiff_t d_shell; + */ + + wchar16_t * wch; + size_t env_block_size; + size_t params_block_size; + size_t bytes_written; + + nt_process_parameters process_params; + nt_process_parameters * params_block; + nt_process_parameters * rparams_block; + nt_process_parameters * params_default; + + /* make the compiler happy */ + d_image = 0; + d_dll_path = 0; + d_cwd = 0; + d_cmd_line = 0; + d_environment = 0; + d_runtime = 0; + env_block_size = 0; + + /* initialize */ + __ntapi->tt_aligned_block_memset( + &process_params, + 0,sizeof(nt_process_parameters)); + + /* allow for extended structures (newer OS versions) */ + process_params.alloc_size = sizeof(nt_process_parameters) + + 8 * sizeof(uintptr_t); + + params_default = ((nt_peb *)pe_get_peb_address())->process_params; + + /* image_file */ + if (image_file) { + /* check alignment and sanity */ + if ((uintptr_t)image_file->buffer % sizeof(uintptr_t)) + return NT_STATUS_INVALID_PARAMETER_2; + else if (image_file->maxlen < image_file->strlen) + return NT_STATUS_INVALID_PARAMETER_2; + + process_params.image_file_name.strlen = image_file->strlen; + process_params.image_file_name.maxlen = image_file->maxlen; + + /* store offset and update alloc_size */ + d_image = process_params.alloc_size; + process_params.alloc_size += image_file->maxlen; + __ALIGN_ALLOC_SIZE; + } + + /* dll_path */ + if (!dll_path) + dll_path = &(params_default->dll_path); + + if (dll_path) { + /* check alignment and sanity */ + if ((uintptr_t)dll_path->buffer % sizeof(uintptr_t)) + return NT_STATUS_INVALID_PARAMETER_3; + else if (dll_path->maxlen < dll_path->strlen) + return NT_STATUS_INVALID_PARAMETER_3; + + process_params.dll_path.strlen = dll_path->strlen; + process_params.dll_path.maxlen = dll_path->maxlen; + + /* store offset and update alloc_size */ + d_dll_path = process_params.alloc_size; + process_params.alloc_size += dll_path->maxlen; + __ALIGN_ALLOC_SIZE; + } + + /* current_directory */ + if (!current_directory) + current_directory = &(params_default->cwd_name); + + if (current_directory) { + /* check alignment and sanity */ + if ((uintptr_t)current_directory->buffer % sizeof(uintptr_t)) + return NT_STATUS_INVALID_PARAMETER_4; + else if (current_directory->maxlen < current_directory->strlen) + return NT_STATUS_INVALID_PARAMETER_4; + + process_params.cwd_name.strlen = current_directory->strlen; + process_params.cwd_name.maxlen = current_directory->maxlen; + + /* store offset and update alloc_size */ + d_cwd = process_params.alloc_size; + process_params.alloc_size += current_directory->maxlen; + __ALIGN_ALLOC_SIZE; + } + + /* command_line */ + if (command_line) { + /* check alignment and sanity */ + if ((uintptr_t)command_line->buffer % sizeof(uintptr_t)) + return NT_STATUS_INVALID_PARAMETER_5; + else if (command_line->maxlen < command_line->strlen) + return NT_STATUS_INVALID_PARAMETER_5; + + process_params.command_line.strlen = command_line->strlen; + process_params.command_line.maxlen = command_line->maxlen; + + /* store offset and update alloc_size */ + d_cmd_line = process_params.alloc_size; + process_params.alloc_size += command_line->maxlen; + __ALIGN_ALLOC_SIZE; + } + + /* environment */ + if (environment) { + /* check alignment */ + if ((uintptr_t)environment % sizeof(uintptr_t)) + return NT_STATUS_INVALID_PARAMETER_6; + + /* obtain size of environment block */ + wch = environment; + + while (*wch) { + /* reach the end of the current variable */ + while (*wch++) + /* proceed to the next variable */ + wch++; + } + + env_block_size = (uintptr_t)wch - (uintptr_t)environment; + + /* store offset and update alloc_size */ + d_environment = process_params.alloc_size; + process_params.alloc_size += (uint32_t)env_block_size + 0x1000; + __ALIGN_ALLOC_SIZE; + } + + /* runtime_data */ + if (runtime_data) { + /* check alignment and sanity */ + if ((uintptr_t)runtime_data->buffer % sizeof(uintptr_t)) + return NT_STATUS_INVALID_PARAMETER_5; + else if (runtime_data->maxlen < runtime_data->strlen) + return NT_STATUS_INVALID_PARAMETER_5; + + process_params.runtime_data.strlen = runtime_data->strlen; + process_params.runtime_data.maxlen = runtime_data->maxlen; + + /* store offset and update alloc_size */ + d_runtime = process_params.alloc_size; + process_params.alloc_size += runtime_data->maxlen; + __ALIGN_ALLOC_SIZE; + } + + /* allocate local and remote process parameters blocks */ + params_block = (nt_process_parameters *)0; + rparams_block = (nt_process_parameters *)0; + + process_params.used_size = process_params.alloc_size; + params_block_size = process_params.alloc_size; + + /* local block */ + status = __ntapi->zw_allocate_virtual_memory( + NT_CURRENT_PROCESS_HANDLE, + (void **)¶ms_block, + 0, + ¶ms_block_size, + NT_MEM_COMMIT, + NT_PAGE_READWRITE); + + if (status != NT_STATUS_SUCCESS) + return status; + + process_params.alloc_size = (uint32_t)params_block_size; + __ntapi->tt_aligned_block_memset(params_block,0,params_block_size); + + /* remote block */ + status = __ntapi->zw_allocate_virtual_memory( + hprocess, + (void **)&rparams_block, + 0, + ¶ms_block_size, + NT_MEM_RESERVE | NT_MEM_COMMIT, + NT_PAGE_READWRITE); + + if (status != NT_STATUS_SUCCESS) { + __ntapi->zw_free_virtual_memory( + NT_CURRENT_PROCESS_HANDLE, + (void **)¶ms_block, + (size_t *)&process_params.alloc_size, + NT_MEM_RELEASE); + + return status; + } + + /* copy the process_params structure */ + __ntapi->tt_aligned_memcpy_utf16( + (uintptr_t *)params_block, + (uintptr_t *)&process_params, + sizeof(nt_process_parameters)); + + /* image_file */ + if (image_file) { + params_block->image_file_name.buffer = + (uint16_t *)pe_va_from_rva(rparams_block,d_image); + + __ntapi->tt_aligned_memcpy_utf16( + (uintptr_t *)pe_va_from_rva(params_block,d_image), + (uintptr_t *)image_file->buffer, + image_file->strlen); + } + + /* dll_path */ + if (dll_path) { + params_block->dll_path.buffer = + (uint16_t *)pe_va_from_rva(rparams_block,d_dll_path); + + __ntapi->tt_aligned_memcpy_utf16( + (uintptr_t *)pe_va_from_rva(params_block,d_dll_path), + (uintptr_t *)dll_path->buffer, + dll_path->strlen); + } + + /* current_directory */ + if (current_directory) { + params_block->cwd_name.buffer = + (uint16_t *)pe_va_from_rva(rparams_block,d_cwd); + + __ntapi->tt_aligned_memcpy_utf16( + (uintptr_t *)pe_va_from_rva(params_block,d_cwd), + (uintptr_t *)current_directory->buffer, + current_directory->strlen); + } + + /* command_line */ + if (command_line) { + params_block->command_line.buffer = + (uint16_t *)pe_va_from_rva(rparams_block,d_cmd_line); + + __ntapi->tt_aligned_memcpy_utf16( + (uintptr_t *)pe_va_from_rva(params_block,d_cmd_line), + (uintptr_t *)command_line->buffer, + command_line->strlen); + } + + /* environment */ + if (environment) { + params_block->environment = + (wchar16_t *)pe_va_from_rva(rparams_block,d_environment); + + __ntapi->tt_aligned_memcpy_utf16( + (uintptr_t *)pe_va_from_rva(params_block,d_environment), + (uintptr_t *)environment, + env_block_size); + } + + /* runtime_data */ + if (runtime_data) { + params_block->runtime_data.buffer = + (uint16_t *)pe_va_from_rva(rparams_block,d_runtime); + + __ntapi->tt_aligned_memcpy_utf16( + (uintptr_t *)pe_va_from_rva(params_block,d_runtime), + (uintptr_t *)runtime_data->buffer, + runtime_data->strlen); + } + + params_block->flags = 1; /* normalized */ + + /* copy the local params block to the remote process */ + status = __ntapi->zw_write_virtual_memory( + hprocess, + rparams_block, + (char *)params_block, + process_params.alloc_size, + &bytes_written); + + if (status != NT_STATUS_SUCCESS) + return status; + + /* free the local params block */ + __ntapi->zw_free_virtual_memory( + NT_CURRENT_PROCESS_HANDLE, + (void **)¶ms_block, + (size_t *)&process_params.alloc_size, + NT_MEM_RELEASE); + + /* all done */ + *rprocess_params = rparams_block; + + return NT_STATUS_SUCCESS; +} diff --git a/src/process/ntapi_tt_create_remote_runtime_data.c b/src/process/ntapi_tt_create_remote_runtime_data.c new file mode 100644 index 0000000..d3cf9ca --- /dev/null +++ b/src/process/ntapi_tt_create_remote_runtime_data.c @@ -0,0 +1,178 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#include +#include +#include +#include +#include "ntapi_impl.h" + +typedef struct _nt_process_basic_information nt_pbi; + +int32_t __stdcall __ntapi_tt_create_remote_runtime_data( + __in void * hprocess, + __in_out nt_runtime_data_block * rtblock) +{ + int32_t status; + + size_t bytes_written; + nt_pbi rpbi; + nt_process_parameters * rprocess_params; + nt_unicode_string rcmd_line; + uint32_t runtime_arg_hash; + nt_runtime_data * rtdata; + void * srv_ready; + + #if defined (__NT32) + wchar16_t runtime_arg[8] = { + 'i','n','t','e','g','r','a','l'}; + #elif defined (__NT64) + wchar16_t runtime_arg[16] = { + 'i','n','t','e','g','r','a','l', + '-','r','u','n','t','i','m','e'}; + #endif + + /* validation */ + if (!hprocess) + return NT_STATUS_INVALID_PARAMETER_1; + else if (!rtblock) + return NT_STATUS_INVALID_PARAMETER_2; + else if (!rtblock->addr) + return NT_STATUS_INVALID_PARAMETER_2; + else if (!rtblock->size) + return NT_STATUS_INVALID_PARAMETER_2; + + runtime_arg_hash = __ntapi->tt_buffer_crc32( + 0, + (char *)runtime_arg, + sizeof(runtime_arg)); + + /* obtain process information */ + status = __ntapi->zw_query_information_process( + hprocess, + NT_PROCESS_BASIC_INFORMATION, + (void *)&rpbi, + sizeof(nt_process_basic_information), + 0); + + if (status != NT_STATUS_SUCCESS) + return status; + + status = __ntapi->zw_read_virtual_memory( + hprocess, + pe_va_from_rva( + rpbi.peb_base_address, + (uintptr_t)&(((nt_peb *)0)->process_params)), + (char *)&rprocess_params, + sizeof(uintptr_t), + &bytes_written); + + if (status != NT_STATUS_SUCCESS) + return status; + + status = __ntapi->zw_read_virtual_memory( + hprocess, + &rprocess_params->command_line, + (char *)&rcmd_line, + sizeof(nt_unicode_string), + &bytes_written); + + if (status != NT_STATUS_SUCCESS) + return status; + + if (rcmd_line.buffer == 0) + return NT_STATUS_BUFFER_TOO_SMALL; + else if (rcmd_line.strlen < sizeof(runtime_arg) + 4*sizeof(wchar16_t)) + return NT_STATUS_INVALID_USER_BUFFER; + + status = __ntapi->zw_read_virtual_memory( + hprocess, + pe_va_from_rva( + rcmd_line.buffer, + rcmd_line.strlen - sizeof(runtime_arg)), + (char *)&runtime_arg, + sizeof(runtime_arg), + &bytes_written); + + if (status != NT_STATUS_SUCCESS) + return status; + + /* verify remote process compatibility */ + runtime_arg_hash ^= __ntapi->tt_buffer_crc32( + 0, + (char *)runtime_arg, + sizeof(runtime_arg)); + + if (runtime_arg_hash) + return NT_STATUS_INVALID_SIGNATURE; + + /* remote block */ + rtblock->remote_size = rtblock->size; + status = __ntapi->zw_allocate_virtual_memory( + hprocess, + &rtblock->remote_addr, + 0, + &rtblock->remote_size, + NT_MEM_RESERVE | NT_MEM_COMMIT, + NT_PAGE_READWRITE); + + if (status != NT_STATUS_SUCCESS) + return status; + + /* session handles */ + if (rtblock->flags & NT_RUNTIME_DATA_DUPLICATE_SESSION_HANDLES) { + rtdata = (nt_runtime_data *)rtblock->addr; + srv_ready = rtdata->srv_ready; + + status = __ntapi->zw_duplicate_object( + NT_CURRENT_PROCESS_HANDLE, + srv_ready, + hprocess, + &rtdata->srv_ready, + 0,0,NT_DUPLICATE_SAME_ATTRIBUTES | NT_DUPLICATE_SAME_ACCESS); + if (status) return status; + } else + srv_ready = 0; + + /* copy local block to remote process */ + status = __ntapi->zw_write_virtual_memory( + hprocess, + rtblock->remote_addr, + (char *)rtblock->addr, + rtblock->size, + &bytes_written); + + /* restore rtdata */ + if (srv_ready) + rtdata->srv_ready = srv_ready; + + if (status != NT_STATUS_SUCCESS) + return status; + + /* runtime_arg */ + __ntapi->tt_uintptr_to_hex_utf16( + (uintptr_t)rtblock->remote_addr, + runtime_arg); + + /* update remote runtime arg */ + status = __ntapi->zw_write_virtual_memory( + hprocess, + pe_va_from_rva( + rcmd_line.buffer, + rcmd_line.strlen - sizeof(runtime_arg)), + (char *)&runtime_arg, + sizeof(runtime_arg), + &bytes_written); + + if (status) + __ntapi->zw_free_virtual_memory( + hprocess, + &rtblock->remote_addr, + &rtblock->remote_size, + NT_MEM_RELEASE); + + return status; +} diff --git a/src/process/ntapi_tt_fork_v1.c b/src/process/ntapi_tt_fork_v1.c new file mode 100644 index 0000000..de917ef --- /dev/null +++ b/src/process/ntapi_tt_fork_v1.c @@ -0,0 +1,218 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ntapi_impl.h" + +intptr_t __cdecl __attr_hidden__ __tt_fork_v1(void); +uint32_t __fastcall __attr_hidden__ __tt_fork_child_entry_point(uintptr_t saved_regs_stack_pointer); +uint32_t __fastcall __attr_hidden__ __tt_fork_child_entry_point_adj(uintptr_t saved_regs_stack_pointer); + +/** legacy fork chronology: + * + * parent: + * __ntapi_tt_fork -> + * __tt_fork -> + * __tt_fork_impl -> + * return to __tt_fork --> + * __ntapi_tt_fork + * -> return to caller + * + * child: + * __tt_fork_child_entry_point[_adj] -> + * __ntapi_tt_fork (internal return) -> + * -> return to caller +**/ + + +static intptr_t __tt_fork_cancel(void * hprocess,int32_t status) +{ + __ntapi->zw_terminate_process(hprocess, status); + __ntapi->zw_close(hprocess); + return (intptr_t)(-1); +} + +intptr_t __fastcall __tt_fork_impl_v1( + uintptr_t saved_regs_stack_pointer, + uintptr_t stack_adjustment) +{ + int32_t status; + void * hprocess; + void * hthread; + void ** hport_session; + ntapi_internals * __internals; + + nt_object_attributes oa; + nt_process_basic_information pbi; + nt_thread_context context; + nt_user_stack stack; + nt_memory_basic_information mbi; + nt_client_id cid; + nt_large_integer timeout; + + hprocess = hthread = (void *)0; + + oa.len = sizeof(nt_object_attributes); + oa.root_dir = 0; + oa.obj_name = 0; + oa.obj_attr = 0; + oa.sec_desc = 0; + oa.sec_qos = 0; + + if ((status = __ntapi->zw_create_process( + &hprocess, + NT_PROCESS_ALL_ACCESS, + &oa, + NT_CURRENT_PROCESS_HANDLE, + 1,0,0,0))) + return (intptr_t)(-1); + + if ((status = __ntapi->zw_query_information_process( + hprocess, + NT_PROCESS_BASIC_INFORMATION, + (void *)&pbi, + sizeof(nt_process_basic_information), + 0))) + return __tt_fork_cancel(hprocess,status); + + + + __ntapi->tt_aligned_block_memset( + &context,0,sizeof(nt_thread_context)); + + __INIT_CONTEXT(context); + context.STACK_POINTER_REGISTER = saved_regs_stack_pointer; + context.FAST_CALL_ARG0 = saved_regs_stack_pointer; + + context.INSTRUCTION_POINTER_REGISTER = stack_adjustment + ? (uintptr_t)__tt_fork_child_entry_point_adj + : (uintptr_t)__tt_fork_child_entry_point; + + + + if ((status = __ntapi->zw_query_virtual_memory( + NT_CURRENT_PROCESS_HANDLE, + (void *)context.STACK_POINTER_REGISTER, + NT_MEMORY_BASIC_INFORMATION, + &mbi,sizeof(nt_memory_basic_information),0))) + return __tt_fork_cancel(hprocess,status); + + stack.fixed_stack_base = (void *)0; + stack.fixed_stack_limit = (void *)0; + stack.expandable_stack_base = (void *)((uintptr_t)mbi.base_address + mbi.region_size); + stack.expandable_stack_limit = (void *)mbi.base_address; + stack.expandable_stack_bottom = (void *)mbi.allocation_base; + + + + __internals = __ntapi_internals(); + hport_session = &__internals->hport_tty_session; + timeout.quad = (-1) * 10 * 1000 * __NT_FORK_CHILD_WAIT_MILLISEC; + + if (hport_session && *hport_session) + if ((status = __ntapi->tty_client_process_register( + *hport_session, + pbi.unique_process_id, + 0, 0, &timeout))) + return __tt_fork_cancel(hprocess,status); + + + if ((status = __ntapi->zw_create_thread( + &hthread, + NT_THREAD_ALL_ACCESS, + &oa,hprocess,&cid, + &context,&stack,0))) + return __tt_fork_cancel(hprocess,status); + + + if (cid.process_id > 0) { + __internals->hany[0] = hprocess; + __internals->hany[1] = hthread; + } else { + __internals->hany[0] = 0; + __internals->hany[1] = 0; + } + + /* hoppla */ + return (int32_t)cid.process_id; +} + +intptr_t __fastcall __ntapi_tt_fork_v1( + __out void ** hprocess, + __out void ** hthread) +{ + int32_t status; + intptr_t pid; + nt_large_integer timeout; + void ** hport_session; + void * hevent_tty_connected; + ntapi_internals * __internals; + + __internals = __ntapi_internals(); + hport_session = &__internals->hport_tty_session; + timeout.quad = (-1) * 10 * 1000 * __NT_FORK_CHILD_WAIT_MILLISEC; + + if (at_locked_cas(&__internals->hlock,0,1)) + return (intptr_t)(-1); + + if (hport_session && *hport_session) + if (__ntapi_tt_create_inheritable_event( + &hevent_tty_connected, + NT_NOTIFICATION_EVENT, + NT_EVENT_NOT_SIGNALED)) + return (intptr_t)(-1); + + pid = __tt_fork_v1(); + + *hprocess = __internals->hany[0]; + *hthread = __internals->hany[1]; + + at_store(&__internals->hlock,0); + + if (hport_session && *hport_session) { + if (pid == 0) { + if ((status = __ntapi->tty_connect( + hport_session, + __internals->subsystem->base_named_objects, + NT_SECURITY_IMPERSONATION))) + return __tt_fork_cancel(NT_CURRENT_PROCESS_HANDLE,status); + + __internals->hdev_mount_point_mgr = 0; + + if (__internals->rtdata) + __internals->rtdata->hsession = *hport_session; + + __ntapi->zw_set_event( + hevent_tty_connected, + 0); + + } else if (pid > 0) { + status = __ntapi->zw_wait_for_single_object( + hevent_tty_connected, + NT_SYNC_NON_ALERTABLE, + &timeout); + + if (status && __PSX_DEBUG) + if ((status = __ntapi->zw_wait_for_single_object( + hevent_tty_connected, + NT_SYNC_NON_ALERTABLE, + 0))) + pid = __tt_fork_cancel(*hprocess,status); + } + + __ntapi->zw_close(hevent_tty_connected); + } + + return pid; +} diff --git a/src/process/ntapi_tt_fork_v2.c b/src/process/ntapi_tt_fork_v2.c new file mode 100644 index 0000000..e483554 --- /dev/null +++ b/src/process/ntapi_tt_fork_v2.c @@ -0,0 +1,183 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ntapi_impl.h" + +static intptr_t __tt_fork_cancel(void * hprocess,int32_t status) +{ + __ntapi->zw_terminate_process(hprocess, status); + __ntapi->zw_close(hprocess); + return (intptr_t)(-1); +} + +intptr_t __fastcall __tt_fork_impl_v2( + __out void ** hprocess, + __out void ** hthread) +{ + int32_t status; + void ** hport_session; + nt_object_attributes oa_process; + nt_object_attributes oa_thread; + nt_create_process_info process_info; + nt_cid cid; + nt_sec_img_inf sec_img_inf; + nt_timeout timeout; + ntapi_internals * __internals; + + struct { + size_t size_in_bytes; + nt_create_process_ext_param process_info; + nt_create_process_ext_param section_info; + } ext_params; + + + oa_process.len = sizeof(nt_object_attributes); + oa_process.root_dir = 0; + oa_process.obj_name = 0; + oa_process.obj_attr = 0; + oa_process.sec_desc = 0; + oa_process.sec_qos = 0; + + oa_thread.len = sizeof(nt_object_attributes); + oa_thread.root_dir = 0; + oa_thread.obj_name = 0; + oa_thread.obj_attr = 0; + oa_thread.sec_desc = 0; + oa_thread.sec_qos = 0; + + + __ntapi->tt_aligned_block_memset( + &process_info,0,sizeof(process_info)); + + process_info.size = sizeof(process_info); + process_info.state = NT_PROCESS_CREATE_INITIAL_STATE; + process_info.init_state.init_flags = NT_PROCESS_CREATE_FLAGS_NO_OBJECT_SYNC; + + __ntapi->tt_aligned_block_memset(&ext_params,0,sizeof(ext_params)); + __ntapi->tt_aligned_block_memset(&cid,0,sizeof(cid)); + __ntapi->tt_aligned_block_memset(&sec_img_inf,0,sizeof(sec_img_inf)); + ext_params.size_in_bytes = sizeof(ext_params); + + ext_params.process_info.ext_param_type = NT_CREATE_PROCESS_EXT_PARAM_GET_CLIENT_ID; + ext_params.process_info.ext_param_size = sizeof(cid); + ext_params.process_info.ext_param_addr = &cid; + + ext_params.section_info.ext_param_type = NT_CREATE_PROCESS_EXT_PARAM_GET_SECTION_IMAGE_INFO; + ext_params.section_info.ext_param_size = sizeof(sec_img_inf); + ext_params.section_info.ext_param_addr = &sec_img_inf; + + + /* [thou shalt remember the single step paradox] */ + status = __ntapi->zw_create_user_process( + hprocess, + hthread, + NT_PROCESS_ALL_ACCESS, + NT_THREAD_ALL_ACCESS, + &oa_process, + &oa_thread, + NT_PROCESS_CREATE_FLAGS_INHERIT_HANDLES, + NT_PROCESS_CREATE_FLAGS_CREATE_THREAD_SUSPENDED, + (nt_process_parameters *)0, + &process_info, + (nt_create_process_ext_params *)&ext_params); + + if (status == NT_STATUS_PROCESS_CLONED) + return 0; + else if (status) + return (intptr_t)(-1); + + __internals = __ntapi_internals(); + hport_session = &__internals->hport_tty_session; + timeout.quad = (-1) * 10 * 1000 * __NT_FORK_CHILD_WAIT_MILLISEC; + + if (hport_session && *hport_session) + if ((status = __ntapi->tty_client_process_register( + *hport_session, + cid.process_id, + 0,0,&timeout))) + return __tt_fork_cancel(*hprocess,status); + + /* [thou shalt remember the single step paradox] */ + if ((status = __ntapi->zw_resume_thread( + *hthread,0))) + return __tt_fork_cancel(*hprocess,status); + + /* hoppla */ + return (int32_t)cid.process_id; +} + +intptr_t __fastcall __ntapi_tt_fork_v2( + __out void ** hprocess, + __out void ** hthread) +{ + int32_t status; + intptr_t pid; + nt_large_integer timeout; + void ** hport_session; + void * hevent_tty_connected; + ntapi_internals * __internals; + + __internals = __ntapi_internals(); + hport_session = &__internals->hport_tty_session; + timeout.quad = (-1) * 10 * 1000 * __NT_FORK_CHILD_WAIT_MILLISEC; + + if (hport_session && *hport_session) + if (__ntapi_tt_create_inheritable_event( + &hevent_tty_connected, + NT_NOTIFICATION_EVENT, + NT_EVENT_NOT_SIGNALED)) + return (intptr_t)(-1); + + pid = __tt_fork_impl_v2(hprocess,hthread); + + if (!hport_session || !*hport_session) + return pid; + else if (pid < 0) + return pid; + + if (pid == 0) { + if ((status = __ntapi->tty_connect( + hport_session, + __internals->subsystem->base_named_objects, + NT_SECURITY_IMPERSONATION))) + return __tt_fork_cancel(NT_CURRENT_PROCESS_HANDLE,status); + + __internals->hdev_mount_point_mgr = 0; + + if (__internals->rtdata) + __internals->rtdata->hsession = *hport_session; + + __ntapi->zw_set_event( + hevent_tty_connected, + 0); + } else { + status = __ntapi->zw_wait_for_single_object( + hevent_tty_connected, + NT_SYNC_NON_ALERTABLE, + &timeout); + + if (status && __PSX_DEBUG) + if ((status = __ntapi->zw_wait_for_single_object( + hevent_tty_connected, + NT_SYNC_NON_ALERTABLE, + 0))) + pid = __tt_fork_cancel(*hprocess,status); + } + + + __ntapi->zw_close(hevent_tty_connected); + + return pid; +} diff --git a/src/process/ntapi_tt_get_runtime_data.c b/src/process/ntapi_tt_get_runtime_data.c new file mode 100644 index 0000000..92b4b2b --- /dev/null +++ b/src/process/ntapi_tt_get_runtime_data.c @@ -0,0 +1,83 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#include +#include +#include +#include +#include "ntapi_impl.h" + +#if defined (__NT32) +static wchar16_t runtime_arg[12] = { + ' ','-','r',' ', + 'i','n','t','e','g','r','a','l'}; +#elif defined (__NT64) +static wchar16_t runtime_arg[20] = { + ' ','-','r',' ', + 'i','n','t','e','g','r','a','l', + '-','r','u','n','t','i','m','e'}; +#endif + +int32_t __stdcall __ntapi_tt_get_runtime_data( + __out nt_runtime_data ** rtdata, + __in wchar16_t ** argv) +{ + int32_t status; + nt_process_parameters * process_params; + nt_cmd_option_meta_utf16 cmd_opt_meta; + nt_runtime_data buffer; + nt_runtime_data * prtdata; + ntapi_internals * __internals; + + /* init */ + __internals = __ntapi_internals(); + + /* once? */ + if (__internals->rtdata) { + *rtdata = __internals->rtdata; + return NT_STATUS_SUCCESS; + } + + if (!(argv = argv ? argv : __internals->ntapi_img_sec_bss->argv_envp_array)) + return NT_STATUS_INVALID_PARAMETER_2; + + /* integral process? */ + if ((status = __ntapi->tt_get_short_option_meta_utf16( + __ntapi->tt_crc32_table(), + 'r', + argv, + &cmd_opt_meta))) + return status; + + else if (argv[3]) + status = NT_STATUS_INVALID_PARAMETER_MIX; + + if ((status = __ntapi->tt_hex_utf16_to_uintptr( + cmd_opt_meta.value, + (uintptr_t *)&prtdata))) + return status; + + if ((status = __ntapi->zw_read_virtual_memory( + NT_CURRENT_PROCESS_HANDLE, + prtdata, + (char *)&buffer, + sizeof(buffer),0))) + return status; + + /* avoid confusion :-) */ + process_params = ((nt_peb *)pe_get_peb_address())->process_params; + + __ntapi->tt_memcpy_utf16( + (wchar16_t *)pe_va_from_rva( + process_params->command_line.buffer, + process_params->command_line.strlen - sizeof(runtime_arg)), + runtime_arg, + sizeof(runtime_arg)); + + *rtdata = prtdata; + + return NT_STATUS_SUCCESS; +} diff --git a/src/process/ntapi_tt_init_runtime_data.c b/src/process/ntapi_tt_init_runtime_data.c new file mode 100644 index 0000000..c7c2603 --- /dev/null +++ b/src/process/ntapi_tt_init_runtime_data.c @@ -0,0 +1,82 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#include +#include +#include +#include +#include "ntapi_impl.h" + +int32_t __stdcall __ntapi_tt_update_runtime_data(nt_runtime_data * rtdata) +{ + int32_t status; + nt_process_basic_information pbi; + uint32_t ret; + nt_oa oa = {sizeof(oa)}; + + /* process (self) */ + rtdata->cid_self.process_id = pe_get_current_process_id(); + rtdata->cid_self.thread_id = 0; + + if ((status = __ntapi->zw_open_process( + &rtdata->hprocess_self, + NT_PROCESS_ALL_ACCESS, + &oa,&rtdata->cid_self))) + return status; + + if (rtdata->cid_parent.process_id) + return NT_STATUS_SUCCESS; + + /* process (parent) */ + if ((status = __ntapi->zw_query_information_process( + rtdata->hprocess_self, + NT_PROCESS_BASIC_INFORMATION, + &pbi,sizeof(pbi),&ret))) + return status; + + rtdata->cid_parent.process_id = pbi.inherited_from_unique_process_id; + rtdata->cid_parent.thread_id = 0; + rtdata->hprocess_parent = 0; + + return NT_STATUS_SUCCESS; +} + +int32_t __stdcall __ntapi_tt_init_runtime_data(nt_runtime_data * rtdata) +{ + int32_t status; + nt_peb * peb; + nt_oa oa = {sizeof(oa)}; + + /* init */ + __ntapi->tt_aligned_block_memset(rtdata,0,sizeof(*rtdata)); + peb = (nt_peb *)(pe_get_peb_address()); + + /* pid (self,parent) */ + if ((status = __ntapi_tt_update_runtime_data(rtdata))) + return status; + + /* std handles */ + rtdata->hstdin = peb->process_params->hstdin; + rtdata->hstdout = peb->process_params->hstdout; + rtdata->hstderr = peb->process_params->hstderr; + + if (__ntapi->tt_get_file_handle_type(rtdata->hstdin,&rtdata->stdin_type)) { + rtdata->hstdin = NT_INVALID_HANDLE_VALUE; + rtdata->stdin_type = 0; + } + + if (__ntapi->tt_get_file_handle_type(rtdata->hstdout,&rtdata->stdout_type)) { + rtdata->hstdout = NT_INVALID_HANDLE_VALUE; + rtdata->stdout_type = 0; + } + + if (__ntapi->tt_get_file_handle_type(rtdata->hstderr,&rtdata->stderr_type)) { + rtdata->hstderr = NT_INVALID_HANDLE_VALUE; + rtdata->stderr_type = 0; + } + + return 0; +} diff --git a/src/process/ntapi_tt_map_image_as_data.c b/src/process/ntapi_tt_map_image_as_data.c new file mode 100644 index 0000000..864f9cc --- /dev/null +++ b/src/process/ntapi_tt_map_image_as_data.c @@ -0,0 +1,120 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#include +#include +#include +#include +#include +#include "ntapi_impl.h" + +static nt_sqos const sqos = { + sizeof(sqos), + NT_SECURITY_IMPERSONATION, + NT_SECURITY_TRACKING_DYNAMIC, + 1}; + +static int32_t __tt_exec_unmap_image(nt_executable_image * image, void * base, int32_t status) +{ + int32_t ret; + + if (base) + if ((ret = __ntapi->zw_unmap_view_of_section( + NT_CURRENT_PROCESS_HANDLE, + base))) + return ret; + + if (image->hsection) + if ((ret = __ntapi->zw_close(image->hsection))) + return ret; + + return status; +} + +int32_t __stdcall __ntapi_tt_exec_unmap_image(nt_executable_image * image) +{ + return __tt_exec_unmap_image(image,image->addr,0); +} + + +int32_t __stdcall __ntapi_tt_exec_map_image_as_data(nt_executable_image * image) +{ + int32_t status; + uint16_t * pi16; + uint32_t * pi32; + nt_sec_size sec_size; + size_t view_size; + void * base; + void * hsection; + + struct pe_image_dos_hdr * dos; + struct pe_coff_file_hdr * coff; + union pe_opt_hdr * opt; + struct pe_sec_hdr * sec; + + nt_oa oa = {sizeof(oa), + 0,0,0,0,(nt_sqos *)&sqos}; + + base = 0; + sec_size.quad = 0; + view_size = image->size; + + if ((status = __ntapi->zw_create_section( + &hsection, + NT_SECTION_MAP_READ, + &oa, + &sec_size, + NT_PAGE_READONLY, + NT_SEC_RESERVE,image->hfile))) + return status; + + if ((status = __ntapi->zw_map_view_of_section( + hsection, + NT_CURRENT_PROCESS_HANDLE, + &base, + 0,0,0, + &view_size, + NT_VIEW_UNMAP,0, + NT_PAGE_READONLY))) + return __tt_exec_unmap_image( + image,base,status); + + if (!(dos = pe_get_image_dos_hdr_addr(base))) + return 0; + + pi32 = (uint32_t *)dos->dos_lfanew; + if ((*pi32 + sizeof(*coff)) > view_size) + return __tt_exec_unmap_image( + image,base,NT_STATUS_INVALID_IMAGE_FORMAT); + + if (!(coff = pe_get_image_coff_hdr_addr(base))) + return 0; + + if (!(opt = pe_get_image_opt_hdr_addr(base))) + return 0; + + sec = pe_get_image_section_tbl_addr(base); + pi16 = (uint16_t *)coff->num_of_sections; + if (((size_t)sec-(size_t)base + *pi16 * sizeof(*sec)) > view_size) + return __tt_exec_unmap_image( + image,base,NT_STATUS_INVALID_IMAGE_FORMAT); + + /* subsystem: same offset (pe32, pe32+) */ + pi16 = (uint16_t *)opt; + image->magic = *pi16; + + pi16 = (uint16_t *)opt->opt_hdr_32.subsystem; + image->subsystem = *pi16; + + pi16 = (uint16_t *)coff->characteristics; + image->characteristics = *pi16; + + image->hsection = hsection; + image->addr = base; + image->size = view_size; + + return status; +} diff --git a/src/process/tt_fork_v1.c b/src/process/tt_fork_v1.c new file mode 100644 index 0000000..e69de29 -- cgit v1.2.3