一个管道有读端和写端,当你把这个管道和一个进程搭接起来的时候,可以用这个管道当作输入,也可以用这个管道当作输出,如果是要向管道输入,则数据输入端是写端,另一端是读端,如果是由管道输出,则由进程写入管道,是写端,另一端是读端,也就是接收进程的输出数据的一端,因此如果要重定向进程的输入和输出,则需要2根管道.
以下代码演示了创建CMD.EXE进程,并用2根管道重定向他的输入输出,并读取CMD产生的结果数据.
千万不要忘记设置SECURITY_ATTRIBUTES里的bInheritHandle,比如创建管道的时候要把bInheritHandle设置为TRUE
同样不一定要用管道,比如文件,SOCKET等都可以重定向.
如果是用SOCKET,根据网上的名词,可以创建一个"零管道后门"程序.比如在服务器端上的后门程序监听某个端口,一旦有连接请求,接受后创建SOCKET,就在这个时候开启CMD.EXE,并重定向输入输出到服务器上的这个SOCKET,这样便为远程的这个连接请求开了一个服务器上的后门,从而远程连接可以执行服务器并返回结果.
演示代码如下:
//
// File: Main.cpp
// Purpose: Creates a process( cmd.exe for example ), and redirect its standard input
// by using creating a pipe, then writes some bytes as commands to pipe.
//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
// Error report
void Error( const char *szErrMsg );
int main( int argc, char **argv )
{
// Create pipe
BOOL bRet;
HANDLE hPipeRead, hPipeWrite;
HANDLE hPipeReadII, hPipeWriteII;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof( SECURITY_ATTRIBUTES );
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
bRet = ::CreatePipe( &hPipeRead, &hPipeWrite, &sa, 512 );
bRet &= ::CreatePipe( &hPipeReadII, &hPipeWriteII, &sa, 512 );
if ( !bRet )
{
Error( "Can't create pipe!" );
return -1;
}
// Spawn a process
STARTUPINFO StartInfo;
PROCESS_INFORMATION ProcessInfo;
// memset( &StartInfo, 0, sizeof(StartInfo) );
// memset( &ProcessInfo, 0, sizeof(ProcessInfo) );
::GetStartupInfo( &StartInfo );
StartInfo.cb = sizeof(StartInfo);
StartInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
StartInfo.wShowWindow = SW_HIDE;
StartInfo.hStdInput = hPipeRead;
StartInfo.hStdOutput = hPipeWriteII; //::GetStdHandle( STD_OUTPUT_HANDLE );
StartInfo.hStdError = hPipeWriteII; //::GetStdHandle( STD_OUTPUT_HANDLE );
bRet = ::CreateProcess( TEXT("c:\\windows\\system32\\cmd.exe"), NULL, NULL, NULL, TRUE, 0, NULL, NULL, &StartInfo, &ProcessInfo );
::Sleep(1000);
printf("wake up...\n");
if ( !bRet )
{
Error( "Can't create process!" );
return -1;
}
// Write commands to pipe
char *szCmd = "netstat\r\n";
DWORD dwDummy;
::WriteFile( hPipeWrite, szCmd, 10, &dwDummy, NULL );
::Sleep(2000);
printf("had written...\n");
// Read from pipe
char szBuf[1024];
memset(szBuf, 0, sizeof(szBuf));
::ReadFile( hPipeReadII, szBuf, sizeof(szBuf), &dwDummy, NULL );
// Don't leave till the spawned process goes end
// ::Sleep(2000);
printf("had read...\n");
// ::WaitForSingleObject( ProcessInfo.hProcess, INFINITE );
printf("%s\n", szBuf);
return 0;
}
void Error( const char *szErrMsg )
{
printf( "Error: %s\n", szErrMsg );
}
在WinXP SP2 + VS 2005 Express Edition上编译并运行通过
这个版本的VS需要下载并设置Platform SDK,并另外找一个MSVCRT80D.DLL如果是DEBUG版本的DLL,并设置
包含和链接目录和链接器命令行(user32,kernel32,libcmt)