Search code examples
c++winsock

Winsock, command line on a remote server


I'm new with winsock, i work in linux enviroment, I am trying to write a program where the client will connect on a shell server, I am having trouble sending output to client, I have not develope the full client yet, I'm using netcat for testing, but do not get the data in the output... someone can give help to improve this code?

what should I do so that the client receives the output of cmd command ?

int Socket_Manip::SHELL() {

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    memset((void *)&si, 0, sizeof(si));
    memset((void *)&pi, 0, sizeof(pi));

    si.wShowWindow = SW_HIDE;
    si.hStdInput = (HANDLE)ClientSocket;
    si.hStdOutput = (HANDLE)ClientSocket;
    si.hStdError = (HANDLE)ClientSocket;
    CreateProcess(NULL,"cmd", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);

    return 0;
}

Solution

  • You cannot use a socket to redirect CreateProcess() I/O. Use pipes from CreatePipe() instead. Refer to MSND for an example:

    Creating a Child Process with Redirected Input and Output

    You will have to write some monitoring code that passes data back and forth between the pipes and socket as needed. Try something like this:

    struct sThreadInfo
    {
        SOCKET Socket;
        HANDLE hStdIn;
        HANDLE hStdOut;
        bool Stop;
    };
    
    DWORD WINAPI ClientSocketToShell(LPVOID lpParameter)
    {
        sThreadInfo *ti = (sThreadInfo*) lpParameter;
    
        BYTE buffer[1024];
        DWORD BytesWritten;
        fd_set rds;
    
        while (!ti->Stop)
        {
            FD_ZERO(&rds);
            FD_SET(ti->Socket, &rds);
    
            timeval timeout;
            timeout.tv_sec = 1;
            timeout.tv_usec = 0;
    
            int ret = select(0, &rds, NULL, NULL, &timeout);
            if (ret < 0)
                break;
    
            if (ret > 0)
            {
                ret = recv(ti->Socket, buffer, sizeof(buffer), 0);
                if (ret <= 0)
                    break;
    
                if (!WriteFile(ti->hStdIn, buffer, ret, &BytesWritten, NULL))
                    break;
            }
        }
    
        return 0;
    }
    
    DWORD WINAPI ShellToClientSocket(LPVOID lpParameter)
    {
        sThreadInfo *ti = (sThreadInfo*) lpParameter;
    
        BYTE buffer[1024];
        DWORD BytesAvailable, BytesRead;
    
        while (!ti->Stop)
        {
            if (!PeekNamedPipe(ti->hStdOut, NULL, 0, NULL, &BytesAvailable, NULL))
                break;
    
            if (BytesAvailable != 0)
            {
                if (!ReadFile(ti->hStdOut, buffer, min(sizeof(buffer), BytesAvailable), &BytesRead, NULL))
                    break;
    
                ret = send(ti->Socket, buffer, BytesRead, 0);
                if (ret <= 0)
                    break;
            }
            else
                Sleep(1000);
        }
    
        return 0;
    }
    
    int Socket_Manip::SHELL()
    {
        SECURITY_ATTRIBUTES saAttr; 
        saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
        saAttr.bInheritHandle = TRUE; 
        saAttr.lpSecurityDescriptor = NULL; 
    
        HANDLE hStdIn_Rd = NULL;
        HANDLE hStdIn_Wr = NULL;
        HANDLE hStdOut_Rd = NULL;
        HANDLE hStdOut_Wr = NULL;
    
        if (!CreatePipe(&hStdOut_Rd, &hStdOut_Wr, &saAttr, 0))
            return 0;
        SetHandleInformation(hStdOut_Rd, HANDLE_FLAG_INHERIT, 0);
    
        if (!CreatePipe(&hStdIn_Rd, &hStdIn_Wr, &saAttr, 0))
        {
            CloseHandle(hStdOut_Rd);
            CloseHandle(hStdOut_Wr);
            return 0;
        }
        SetHandleInformation(hStdIn_Wr, HANDLE_FLAG_INHERIT, 0);
    
        STARTUPINFO si;
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
        si.hStdError = hStdOut_Wr;
        si.hStdOutput = hStdOut_Wr;
        si.hStdInput = hStdIn_Rd;
        si.wShowWindow = SW_HIDE;
    
        PROCESS_INFORMATION pi;
        ZeroMemory(&pi, sizeof(pi));
    
        TCHAR cmd[] = TEXT("cmd");
        if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
        {
            CloseHandle(pi.hThread);
    
            sThreadInfo ti;
            ZeroMemory(&ti, sizeof(ti));
            ti.Socket = ClientSocket;
            ti.hStdIn = hStdIn_Wr;
            ti.hStdOut = hStdOut_Rd;
            ti.Stop - false;
    
            HANDLE Handles[3];
            DWORD dwThreadID;
    
            ZeroMemory(Handles, sizeof(Handles));
            Handles[0] = pi.hProcess;
            Handles[1] = CreateThread(NULL, 0, &ClientSocketToShell, &ti, 0, &dwThreadID);
            Handles[2] = CreateThread(NULL, 0, &ShellToClientSocket, &ti, 0, &dwThreadID);
    
            DWORD ret = WaitForMultipleObjects(3, Handles, FALSE, INFINITE);
    
            ti.Stop = true;
            if (ret != WAIT_OBJECT_0)
                TerminateProcess(pi.hProcess, 0);
    
            WaitForMultipleObjects(2, &Handles[1], TRUE, INFINITE);
    
            CloseHandle(pi.hProcess);
            CloseHandle(Handles[1]);
            CloseHandle(Handles[2]);
       }
    
        CloseHandle(hStdIn_Rd);
        CloseHandle(hStdIn_Wr);
        CloseHandle(hStdOut_Rd);
        CloseHandle(hStdOut_Wr);
    
        return 0;
    }