一个管道有读端和写端,当你把这个管道和一个进程搭接起来的时候,可以用这个管道当作输入,也可以用这个管道当作输出,如果是要向管道输入,则数据输入端是写端,另一端是读端,如果是由管道输出,则由进程写入管道,是写端,另一端是读端,也就是接收进程的输出数据的一端,因此如果要重定向进程的输入和输出,则需要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)
posted on 2010-05-25 23:07 Reno 阅读(583) 评论(0)  编辑 收藏 引用 所属分类: Windows系统编程

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


统计