/// <summary> /// Create a new thread in a process. /// </summary> /// <param name="object_attributes">The object attributes for the thread object.</param> /// <param name="desired_acccess">Desired access for the handle.</param> /// <param name="process">Process to create the thread in.</param> /// <param name="start_routine">Address of the start routine.</param> /// <param name="argument">Argument to pass to the thread.</param> /// <param name="create_flags">Creation flags.</param> /// <param name="zero_bits">Zero bits for the stack address.</param> /// <param name="stack_size">Size of the committed stack.</param> /// <param name="maximum_stack_size">Maximum reserved stack size.</param> /// <param name="attribute_list">Optional attribute list.</param> /// <param name="throw_on_error">True to throw on error</param> /// <returns>The created thread object.</returns> /// <remarks>This creates a native thread, not a Win32 thread. This might cause unexpected things to fail as they're not initialized.</remarks> public static NtResult <NtThread> Create( ObjectAttributes object_attributes, ThreadAccessRights desired_acccess, NtProcess process, long start_routine, long argument, ThreadCreateFlags create_flags, long zero_bits, long stack_size, long maximum_stack_size, IEnumerable <ProcessAttribute> attribute_list, bool throw_on_error) { using (ProcessAttributeList attr_list = ProcessAttributeList.Create(attribute_list)) { return(NtSystemCalls.NtCreateThreadEx(out SafeKernelObjectHandle handle, desired_acccess, object_attributes, process.Handle, new IntPtr(start_routine), new IntPtr(argument), create_flags, new IntPtr(zero_bits), new IntPtr(stack_size), new IntPtr(maximum_stack_size), attr_list).CreateResult(throw_on_error, () => new NtThread(handle))); } }
/// <summary> /// Start the new process /// </summary> /// <param name="image_path">The image path to the file to execute</param> /// <returns>The result of the process creation</returns> public CreateUserProcessResult Start(string image_path) { if (image_path == null) { throw new ArgumentNullException("image_path"); } using (var process_params = SafeProcessParametersBuffer.Create(ConfigImagePath ?? image_path, DllPath, CurrentDirectory, CommandLine, Environment, WindowTitle, DesktopInfo, ShellInfo, RuntimeData, CreateProcessParametersFlags.Normalize)) { using (var attrs = new DisposableList <ProcessAttribute>()) { ProcessCreateInfo create_info = new ProcessCreateInfo(); attrs.Add(ProcessAttribute.ImageName(image_path)); SafeStructureInOutBuffer <SectionImageInformation> image_info = new SafeStructureInOutBuffer <SectionImageInformation>(); attrs.Add(ProcessAttribute.ImageInfo(image_info)); SafeStructureInOutBuffer <ClientId> client_id = new SafeStructureInOutBuffer <ClientId>(); attrs.Add(ProcessAttribute.ClientId(client_id)); attrs.AddRange(AdditionalAttributes); if (ParentProcess != null) { attrs.Add(ProcessAttribute.ParentProcess(ParentProcess.Handle)); } if (RestrictChildProcess || OverrideRestrictChildProcess) { attrs.Add(ProcessAttribute.ChildProcess(RestrictChildProcess, OverrideRestrictChildProcess)); } if (Token != null) { attrs.Add(ProcessAttribute.Token(Token.Handle)); } using (ProcessAttributeList attr_list = ProcessAttributeList.Create(attrs)) { create_info.Data.InitFlags = InitFlags | ProcessCreateInitFlag.WriteOutputOnExit; create_info.Data.ProhibitedImageCharacteristics = ProhibitedImageCharacteristics; create_info.Data.AdditionalFileAccess = AdditionalFileAccess; using (ObjectAttributes proc_attr = new ObjectAttributes(null, AttributeFlags.None, SafeKernelObjectHandle.Null, null, ProcessSecurityDescriptor), thread_attr = new ObjectAttributes(null, AttributeFlags.None, SafeKernelObjectHandle.Null, null, ThreadSecurityDescriptor)) { NtStatus status = NtSystemCalls.NtCreateUserProcess( out SafeKernelObjectHandle process_handle, out SafeKernelObjectHandle thread_handle, ProcessDesiredAccess, ThreadDesiredAccess, proc_attr, thread_attr, ProcessFlags, ThreadFlags, process_params.DangerousGetHandle(), create_info, attr_list); if (!status.IsSuccess() && !ReturnOnError) { // Close handles which come from errors switch (create_info.State) { case ProcessCreateState.FailOnSectionCreate: NtSystemCalls.NtClose(create_info.Data.FileHandle); break; case ProcessCreateState.FailExeName: NtSystemCalls.NtClose(create_info.Data.IFEOKey); break; } status.ToNtException(); } if (create_info.State == ProcessCreateState.Success) { return(new CreateUserProcessResult(process_handle, thread_handle, create_info.Data, image_info.Result, client_id.Result, TerminateOnDispose)); } else { return(new CreateUserProcessResult(status, create_info.Data, create_info.State)); } } } } } }