文章目录
  1. 1. 原理:
  2. 2. 实现:
  3. 3. 效果
有时我们需要写一个Shell来完成一些比较猥琐的事(比如远程Shell),怎么办?完全自己写一个shell吗?可行,但是工作量太大;有一个比较好的方案能帮助我们快速的完成工作--管道.

原理:

这方面资料网上其实挺多的,简单说下吧,程序一般都有输入句柄和输出句柄,什么叫输入呢,就是你向它发送数据,输出肯定就是它向你发送数据了,简单来说,printf算是输出,scanf算是输入.一般来说,打开cmd.exe如果不进行设置的话它的输入输出句柄就被设置成默认的了,也就是GetStdHandle的返回值,那如果把输入输出句柄设置成我们自己设定的会怎么样呢?没错,就可以使用ReadFile读取它的输出,使用WriteFile向它输入!

实现:

废话不说,直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

#include <stdio.h>
#include <Windows.h>

#define BUFFER_SIZE 1024

HANDLE hProcess=0;
HANDLE hRead1,hRead2;
HANDLE hWrite1,hWrite2;

BOOL WINAPI HandlerRoutine(DWORD dwType)
{

if(hProcess)
{
TerminateProcess(hProcess,0);
CloseHandle(hRead1);
CloseHandle(hRead2);
CloseHandle(hWrite1);
CloseHandle(hWrite2);
hProcess=0;
}
}

DWORD __stdcall ReadThread(void * pData)
{

char buffer[BUFFER_SIZE];
DWORD len;
HANDLE hRead=(HANDLE)pData;
while(1)
{
ReadFile(hRead,buffer,BUFFER_SIZE,&len,0);
buffer[len]=0;
printf("%s",buffer);
}
return 1;
}

void main(int argc,char * argv[])
{


SECURITY_ATTRIBUTES sa;
PROCESS_INFORMATION pi;
STARTUPINFO si;
DWORD len;
char buffer[BUFFER_SIZE];

if(argc<2)
{
printf("输入程序路径!\r\n");
return ;
}
SetConsoleCtrlHandler(HandlerRoutine,1);
sa.bInheritHandle=1; //设置继承
sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=0;

if((!CreatePipe(&hRead1,&hWrite1,&sa,0))||(!CreatePipe(&hRead2,&hWrite2,&sa,0)))
{
printf("CreatePipe failed!\r\n");
return ;
}
memset(&si,0,sizeof(si));
memset(&pi,0,sizeof(pi));

GetStartupInfo(&si);
si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
si.hStdError=hWrite1;
si.hStdInput=hRead2;
si.hStdOutput=hWrite1;
si.wShowWindow=SW_HIDE;

if(!CreateProcess(argv[1],0,0,0,1,0,0,0,&si,&pi))
{
printf("CreateProcess failed!\r\n");
return ;
}
hProcess=pi.hProcess;
Sleep(300); //等待程序执行
PeekNamedPipe(hRead1,buffer,1,&len,0,0);
while(len)
{
ReadFile(hRead1,buffer,BUFFER_SIZE,&len,0);
buffer[len]=0;
printf("%s",buffer);
PeekNamedPipe(hRead1,buffer,1,&len,0,0);
}
CloseHandle(CreateThread(0,0,ReadThread,(void *)hRead1,0,0));
while(1)
{
gets(buffer);
len=strlen(buffer);
if(len>BUFFER_SIZE-2)
{
printf("防溢出!\r\n");
continue;
}
WriteFile(hWrite2,buffer,len,&len,0);
WriteFile(hWrite2,"\r\n",2,&len,0); //执行
}
}

效果



文章目录
  1. 1. 原理:
  2. 2. 实现:
  3. 3. 效果