techPowerUp! Forums

Go Back   techPowerUp! Forums > Software > Programming & Webmastering

Reply
 
Thread Tools
Old Jun 8, 2008, 11:16 AM   #1
Oliver_FF
200 Posts
 
Oliver_FF's Avatar
 
Join Date: Oct 2006
Posts: 478 (0.20/day)
Thanks: 23
Thanked 66 Times in 53 Posts

System Specs

C/C++/C# Console Redirection with Sockets - Win32

Here's another interesting thing that you can do with sockets in C or C++. If any of you are familiar with the concepts of SSH or Telnet you'll get this straight away. Every console application has three IO paths...

1. stdIn is the standard input - aka when you type something into the console and it goes to your program.
2. stdOut is the standard output - aka when your program outputs feedback the data is written to stdOut, then its contents are written to the console you are working in.
3. stdErr is the standard error - aka if your program crashes and burns you can tell the OS roughly what happened (in an ideal world...)

Well with C or C++ in Windows you can redirect stdIn and stdOut of any console application to go through a network socket. To write to stdIn you simply send data over the socket. To read from stdOut you simply read data off of the socket. Pretty cool, eh? The most obvious use of something like this is for remote access to your computer - create a host program that sits around waiting for you to connect to it and redirect output to, say, cmd.exe so you have "complete" control over your PC remotely. "Complete" because cmd.exe sucks


Code:
#using <windows.h> //sorry not entirely sure where inside there the specific headers are :(

//The socket to use
Socket thisSocket;
//Information about the process we are redirecting.
PROCESS_INFORMATION pi;
//Information about where the IO goes ;)
STARTUPINFO si;

/* Initialise the socket somewhere here */

//cb is the size of the STARTUPINFO structure
si.cb = sizeof( si );
//Tell it we do not want to see the application we are redirecting to/from
si.wShowWindow = SW_HIDE;
//Tell it we want to be able to use .wShowWinwow, .hStdInput, .hstdOutput, .hstdError members.
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
        
//Tell it we want the standard input to come from thisSocket
si.hStdInput = (HANDLE)thisSocket;
//Tell it we want the standard output to go to thisSocket
si.hStdOutput = (HANDLE)thisSocket;
//Tell it we want the stardard error to appear on thisSocket
si.hStdError = (HANDLE)thisSocket;
        
//Spawn the process we want to redirect using the information we just declared.
CreateProcess( NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi );
        

/* From now everything is set up and ticking over. */


//Wait until the process we started ends - then we can quit.
WaitForSingleObject( pi.hProcess, INFINITE );
        
//Close the process handles before exiting.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
MSDN on PROCESS_INFORMATION - http://msdn.microsoft.com/en-us/libr...73(VS.85).aspx
MSDN on STARTUPINFO - http://msdn.microsoft.com/en-us/libr...31(VS.85).aspx

The same effect can be done using C#. The code is easier to read and follow in C# but also it's trickier because you have to transfer the data between the socket yourself... At least that's what i'm assuming when i attempted it...

Code:
using System.Diagnostics;

process = new Process();
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = "cmd.exe";
process.Start();

//use process.StandardInput.WriteLine(); to write to the applications stdIn

//use process.StandardOutput.ReadLine(); to read from the applications stdOut
Oliver_FF is offline  
Reply With Quote
The Following User Says Thank You to Oliver_FF For This Useful Post:
Old Jun 8, 2008, 12:15 PM   #2
DanTheBanjoman
Seņor Moderator
 
DanTheBanjoman's Avatar
 
Join Date: May 2004
Location: Utrecht, Utrecht, The kingdom of the Netherlands
Posts: 8,498 (2.58/day)
Thanks: 41
Thanked 1,453 Times in 1,077 Posts
Send a message via ICQ to DanTheBanjoman Send a message via MSN to DanTheBanjoman

System Specs

I've been looking for simple code to send data over a network to build upon. This seems relatively simple. The examples I found were huge and didn't even work out of the box.

The downside is that I don't use C, I'll be looking into this though.
DanTheBanjoman is offline  
Reply With Quote
Old Jun 8, 2008, 02:32 PM   #3
Oliver_FF
200 Posts
 
Oliver_FF's Avatar
 
Join Date: Oct 2006
Posts: 478 (0.20/day)
Thanks: 23
Thanked 66 Times in 53 Posts

System Specs

If you just want to send data over the network you might want to check my basic sockets tutorial thing here:
http://forums.techpowerup.com/showthread.php?t=56901

The syntax may vary between programming languages, but the method of using the Windows API is usually fairly similar. It's all pretty well documented over at MSDN too
Oliver_FF is offline  
Reply With Quote
Old Jun 8, 2008, 04:51 PM   #4
Kreij
Hardcore Monkey Moderator
 
Kreij's Avatar
 
Join Date: Feb 2007
Location: Cheeseland (Wisconsin, USA)
Posts: 12,114 (5.27/day)
Thanks: 591
Thanked 5,492 Times in 2,936 Posts

System Specs

Quote:
Originally Posted by DanTheBanjoman View Post
I've been looking for simple code to send data over a network to build upon. This seems relatively simple. The examples I found were huge and didn't even work out of the box.

The downside is that I don't use C, I'll be looking into this though.
What language are you using Dan?
__________________

Cloud (noun, singular): A dynamic arrangement of multiple potential single points of failure, with a user at one end and their data at the other.


Get more tech news on a wide variety of topics at NextPowerUp
Kreij is offline  
Reply With Quote
Old Jun 8, 2008, 08:55 PM   #5
DanTheBanjoman
Seņor Moderator
 
DanTheBanjoman's Avatar
 
Join Date: May 2004
Location: Utrecht, Utrecht, The kingdom of the Netherlands
Posts: 8,498 (2.58/day)
Thanks: 41
Thanked 1,453 Times in 1,077 Posts
Send a message via ICQ to DanTheBanjoman Send a message via MSN to DanTheBanjoman

System Specs

Quote:
Originally Posted by Kreij View Post
What language are you using Dan?
vb.net
DanTheBanjoman is offline  
Reply With Quote
Old Jun 8, 2008, 09:37 PM   #6
Oliver_FF
200 Posts
 
Oliver_FF's Avatar
 
Join Date: Oct 2006
Posts: 478 (0.20/day)
Thanks: 23
Thanked 66 Times in 53 Posts

System Specs

Well I guess it's lucky for you that the structures and function calls are all in VB

Code:
Dim pInfo As PROCESS_INFORMATION = New PROCESS_INFORMATION()
Dim sInfo As STARTUPINFO = New STARTUPINFO()
...[options here]...

CreateProcess("cmd.exe", Nothing, IntPtr.Zero, IntPtr.Zero, True, 0, IntPtr.Zero, Nothing, sInfo, pInfo)

Last edited by Oliver_FF; Jun 8, 2008 at 10:08 PM.
Oliver_FF is offline  
Reply With Quote
Old Jan 14, 2009, 04:44 AM   #7
lo0ney
5 Posts
 
Join Date: Jan 2009
Posts: 6 (0.00/day)
Thanks: 0
Thanked 0 Times in 0 Posts

Could you please explain how i would use the send and recv functions in order to send commands to cmd.exe and how to retrieve output?

Thanks alot!

Lo0ney
lo0ney is offline  
Reply With Quote
Old Jan 14, 2009, 09:15 AM   #8
FordGT90Concept
"I go fast!1!11!1!"
 
FordGT90Concept's Avatar
 
Join Date: Oct 2008
Location: IA, USA
Posts: 10,575 (6.28/day)
Thanks: 1,755
Thanked 2,596 Times in 1,960 Posts

System Specs

If you want to use cmd on the local machine to do something, you're better off just using System.Diagnostics.ProcessStartInfo, System.Diagnostics.Process, and a System.IO.StreamReader. Simply make ProcessStartInfo point to command.exe on Windows 9x and cmd.exe on Windows NT. In the arguments, do:

/C "your commands > file to save output in"

Use the StreamReader to parse the file.


Also, there is Process.StandardOutput, Process.StandardInput, and Process.StandardError that you could use for redirection.
__________________
Golden Rule of Programming: Never assume.

try { SteamDownload(); }
catch (Steamception ex) { RageQuit(); }
FordGT90Concept is offline  
Crunching for Team TPU
Reply With Quote
Old Jan 14, 2009, 08:43 PM   #9
lo0ney
5 Posts
 
Join Date: Jan 2009
Posts: 6 (0.00/day)
Thanks: 0
Thanked 0 Times in 0 Posts

Well im using C and im trying to send commands to cmd.exe remotely. IE: Client/Server

So i would need the client to send commands to the server which would then pass the cmd to cmd.exe then return output to the client
lo0ney is offline  
Reply With Quote
Old Jan 14, 2009, 08:49 PM   #10
FordGT90Concept
"I go fast!1!11!1!"
 
FordGT90Concept's Avatar
 
Join Date: Oct 2008
Location: IA, USA
Posts: 10,575 (6.28/day)
Thanks: 1,755
Thanked 2,596 Times in 1,960 Posts

System Specs

What kind of commands?
__________________
Golden Rule of Programming: Never assume.

try { SteamDownload(); }
catch (Steamception ex) { RageQuit(); }
FordGT90Concept is offline  
Crunching for Team TPU
Reply With Quote
Old Jan 14, 2009, 09:13 PM   #11
lo0ney
5 Posts
 
Join Date: Jan 2009
Posts: 6 (0.00/day)
Thanks: 0
Thanked 0 Times in 0 Posts

Any command that can be executed in cmd.exe. For example: "dir", "ipconfig", "cd C:\"

I have an edit box on the client where the user will type a command to be executed 'remotely' from the server, which launced cmd.exe, then returns the output of the command back to the client.
lo0ney is offline  
Reply With Quote
Old Jan 14, 2009, 09:20 PM   #12
FordGT90Concept
"I go fast!1!11!1!"
 
FordGT90Concept's Avatar
 
Join Date: Oct 2008
Location: IA, USA
Posts: 10,575 (6.28/day)
Thanks: 1,755
Thanked 2,596 Times in 1,960 Posts

System Specs

I would advise against doing that as there is nothing to stop a user from completely destroying a computer. Additionally, some commands return a massive stack of data so you'd have to use TCP instead of the preferred UDP. Have you already got the network layers sorted because that will take the most work.
__________________
Golden Rule of Programming: Never assume.

try { SteamDownload(); }
catch (Steamception ex) { RageQuit(); }
FordGT90Concept is offline  
Crunching for Team TPU
Reply With Quote
Old Jan 14, 2009, 09:41 PM   #13
lo0ney
5 Posts
 
Join Date: Jan 2009
Posts: 6 (0.00/day)
Thanks: 0
Thanked 0 Times in 0 Posts

I can set cmd restrictions and filters later, but for now its just for testing purposes. And I am using TCP sockets, but could i not just use the source posted by Oliver FF to do this?

I have the source (first post) basically as my server, and then i have a client which connects to the server.
lo0ney is offline  
Reply With Quote
Old Aug 21, 2010, 11:47 PM   #14
portnoid
 
Join Date: Aug 2010
Posts: 1 (0.00/day)
Thanks: 0
Thanked 0 Times in 0 Posts

I had the error 87 problem and it turned out to be not using a protocol that supported
IFS handles. Here is how I created a socket that uses IFS handles:

// Load version 2.2 of Winsock
if (WSAStartup(MAKEWORD(2, 2), &wsda))
{
fprintf(stderr, (char *)"WSAStartup failed error=%d\n", WSAGetLastError());
exit(1);
}
// Find a protocol where socket descriptors returned by the provider
// are operating system Installable File System (IFS) handles.
// First, have WSAEnumProtocols tell you how big a buffer you need.
bool bProtocolFound = false;
LPWSAPROTOCOL_INFO lpProtocolBuf = NULL;
DWORD dwBufLen, dwErr;
int nRet = WSAEnumProtocolsA(NULL, lpProtocolBuf, &dwBufLen);
if (SOCKET_ERROR != nRet)
{
die((char *)"WSAEnumProtocols: should not have succeeded");
}
else if (WSAENOBUFS != (dwErr = WSAGetLastError()))
{
// WSAEnumProtocols failed for some reason not relating to buffer size.
die((char *)"WSAEnumProtocols");
}
else
{
// WSAEnumProtocols failed for the "expected" reason. Therefore,
// you need to allocate a buffer of the appropriate size.
lpProtocolBuf = (WSAPROTOCOL_INFO *)malloc(dwBufLen);
if (lpProtocolBuf)
{
// Now call WSAEnumProtocols again with the expectation
// that it will succeed because you have allocated a big enough
// buffer.
nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
if (SOCKET_ERROR == nRet)
{
die((char *)"WSAEnumProtocols");
}
else
{
// Loop through protocols, looking for the first service
// provider that meets the matching criteria.
for (i = 0; i < nRet; i++)
{
if ((IPPROTO_TCP == lpProtocolBuf[i].iProtocol) &&
(XP1_IFS_HANDLES == (XP1_IFS_HANDLES &
lpProtocolBuf[i].dwServiceFlags1)))
{
bProtocolFound = true;

// Create socket.
sock = WSASocket(
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
&lpProtocolBuf[i],
0,
0);
if (INVALID_SOCKET == sock)
{
die((char *)"WSASocket");
}
break;
}
}
}
}
}
portnoid is offline  
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 11:08 PM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
no new posts