利用匿名管道实现远程CMD

本文介绍了如何利用匿名管道在Windows环境中实现远程CMD通信。详细讲解了命名管道和匿名管道的基本概念、使用方法,包括创建、连接和通信过程。同时,给出了一个使用汇编语言实现的远程CMD动态链接库的示例代码,涉及CreatePipe、CreateProcess等API函数的应用。
摘要由CSDN通过智能技术生成
一.基本的理论知识
1.什么是管道以及分类
管道是两个头的东西,每个头各连接一个进程或者同一个进程的不同代码,按照管道的类别分有两种管道,匿名的和命名的;按照管道的传输方向分也可以分成两种,单向的双向的。根据管道的特点,命名管道通常用在网络环境下不同计算机上运行的进程之间的通信(当然也可以用在同一台机的不同进程中)它可以是单向或双向的;而匿名管道只能用在同一台计算机中,它只能是单向的。匿名管道其实是通过用给了一个指定名字的有名管道来实现的。
使用管道的好处在于:读写它使用的是对文件操作的 api,结果操作管道就和操作文件一样。即使你在不同的计算机之间用命名管道来通信,你也不必了解和自己去实现网络间通信的具体细节。
2.管道的使用
A.命名管道
命名管道是由服务器端的进程建立的,管道的命名必须遵循特定的命名方法,就是 "//./pipe/管道名",当作为客户端的进程要使用时,使用"//计算机名//pipe/管道名" 来打开使用,具体步骤如下:
服务端通过函数 CreateNamedPipe 创建一个命名管道的实例并返回用于今后操作的句柄,或为已存在的管道创建新的实例。 服务端侦听来自客户端的连接请求,该功能通过 ConnectNamedPipe 函数实现。 
    客户端通过函数 WaitNamedPipe 来等待管道的出现,如果在超时值变为零以前,有一个管道可以使用,则 WaitNamedPipe 将返回 True,并通过调用 CreateFile 或 CallNamedPipe 来呼叫对服务端的连接。 
    此时服务端将接受客户端的连接请求,成功建立连接,服务端 ConnectNamedPipe 返回 True 建立连接之后,客户端与服务器端即可通过 ReadFile 和 WriteFile,利用得到的管道文件句柄,彼此间进行信息交换。 当客户端与服务端的通信结束,客户端调用 CloseFile,服务端接着调用 DisconnectNamedPipe。最后调用函数CloseHandle来关闭该管道。 
B.匿名管道
    由于命名管道使用时作为客户端的程序必须知道管道的名称,所以更多的用在同一“作者”编写的服务器/工作站程序中,你不可能随便找出一个程序来要求它和你写的程序来通过命名管道通信。而匿名管道的使用则完全不同,它允许你和完全不相干的进程通信,条件是这个进程通过控制台“console”来输入输出,典型的例子是老的 Dos 应用程序,它们在运行时 Windows 为它们开了个 Dos 窗口,它们的输入输出就是 console 方式的。还有一些标准的 Win32 程序也使用控制台输入输出,如果在 Win32 编程中不想使用图形界面,你照样可以使用 AllocConsole 得到一个控制台,然后通过 GetStdHandle 得到输入或输出句柄,再通过 WriteConsole 或 WriteFile 把结果输出到控制台(通常是一个象 Dos 窗口)的屏幕上。虽然这些程序看起来象 Dos 程序,但它们是不折不扣的 Win32 程序,如果你在纯 Dos 下使用,就会显示“The program must run under Windows!”。
一个控制台有三个句柄:
在Windows操作系统中,可以使用匿名管道重定向实现输出cmd命令执行结果。具体步骤如下: 1. 创建一个匿名管道,使用CreatePipe函数实现。 2. 创建一个子进程,使用CreateProcess函数实现。在子进程中,将管道的输出重定向到标准输出。 3. 在父进程中,使用ReadFile函数读取管道中的数据,即子进程输出的结果。 下面是一个示例代码: ``` #include <windows.h> #include <stdio.h> int main() { HANDLE hReadPipe, hWritePipe; SECURITY_ATTRIBUTES saAttr; PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; BOOL bSuccess; DWORD dwRead; // 创建匿名管道 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; if(!CreatePipe(&hReadPipe, &hWritePipe, &saAttr, 0)) { printf("CreatePipe failed\n"); return 1; } // 创建子进程 ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdError = hWritePipe; siStartInfo.hStdOutput = hWritePipe; siStartInfo.dwFlags |= STARTF_USESTDHANDLES; bSuccess = CreateProcess(NULL, "ipconfig", NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo); if(!bSuccess) { printf("CreateProcess failed\n"); return 1; } // 读取子进程输出的结果 CHAR chBuf[1024]; ZeroMemory(chBuf, sizeof(chBuf)); for (;;) { bSuccess = ReadFile(hReadPipe, chBuf, sizeof(chBuf), &dwRead, NULL); if(!bSuccess || dwRead == 0) break; printf("%s", chBuf); ZeroMemory(chBuf, sizeof(chBuf)); } // 关闭句柄 CloseHandle(hReadPipe); CloseHandle(hWritePipe); CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); return 0; } ``` 上述代码中,使用了ipconfig命令作为示例,可以根据实际需求替换为其他命令。运行程序后,会输出ipconfig命令的执行结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值