using Newtonsoft.Json;
using System;
using System.IO;
using System.IO.Pipes;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
using System.Threading;
namespace API.PipeServer
{
public class Server
{
private bool running;
private Thread runningThread;
private EventWaitHandle terminateHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
public string PipeName { get; set; }
private void ServerLoop()
{
while (running)
{
ProcessNextClient();
}
terminateHandle.Set();
}
public void Run()
{
running = true;
runningThread = new Thread(ServerLoop);
runningThread.Start();
}
public void Stop()
{
running = false;
terminateHandle.WaitOne();
}
public virtual string ProcessRequest(string message)
{
return "";
}
public void ProcessClientThread(object o)
{
using (NamedPipeServerStream pipeStream = (NamedPipeServerStream)o)
{
StreamReader sr = new StreamReader(pipeStream);
//Receive instruction message
string instructionJson = sr.ReadLine();
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: --- Receiving Instruction ---");
Console.WriteLine(instructionJson);
//Getting instruction message
var instruction = JsonConvert.DeserializeObject<InstructionHandler.Instruction>(instructionJson);
//Get data
var json = API.API.GetAPIJson(instruction);
//Send data back to Python client
try
{
pipeStream.Write(Encoding.UTF8.GetBytes(json));
pipeStream.WaitForPipeDrain();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: --- Closing Stream ---");
pipeStream.Close();
pipeStream.Dispose();
}
}
public void ProcessNextClient()
{
try
{
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: Creating server");
PipeSecurity pipeSecurity = new PipeSecurity();
pipeSecurity.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), PipeAccessRights.ReadWrite, AccessControlType.Allow));
var pipeStream = NamedPipeServerStreamAcl.Create("test_api", PipeDirection.InOut, 254, PipeTransmissionMode.Message, PipeOptions.None, 1024, 1024, pipeSecurity);
pipeStream.WaitForConnection();
//Spawn a new thread for each request and continue waiting
Thread t = new Thread(ProcessClientThread);
t.Start(pipeStream);
}
catch (Exception e)
{
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: Error - {e.Message}");
}
}
}
}
我知道这是一个古老的问题,但是在我自己遇到同一问题之后,我终于奏效了。
没有太深的深入Win32内部设备,在允许服务器端上多个管道实例时要理解的主要内容是,在引擎盖窗户下方会大致执行以下操作:
ACCESS
现有管道并为IT创建一个新实例
internal sealed class Win32NamedPipeServerStreamFactory : INamedPipeServerStreamFactory
{
private static readonly Lock s_lock = new();
private static volatile PipeSecurity? s_pipeSecurity;
public NamedPipeServerStream CreateInstance(string pipeName)
{
PipeOptions options = GetOptions(out PipeSecurity pipeSecurity);
// modify creation options as needed
NamedPipeServerStream pipe = NamedPipeServerStreamAcl.Create
(
pipeName: pipeName,
direction: PipeDirection.InOut,
maxNumberOfServerInstances: NamedPipeServerStream.MaxAllowedServerInstances,
transmissionMode: PipeTransmissionMode.Byte,
options: options,
inBufferSize: 0,
outBufferSize: 0,
pipeSecurity: pipeSecurity,
inheritability: HandleInheritability.None
);
return pipe;
}
private static PipeOptions GetOptions(out PipeSecurity pipeSecurity)
{
PipeSecurity? security = s_pipeSecurity;
if (security is not null)
{
pipeSecurity = security;
return PipeOptions.None;
}
lock (s_lock)
{
security = s_pipeSecurity;
if (security is not null)
{
pipeSecurity = security;
return PipeOptions.None;
}
SecurityIdentifier currentUser = WindowsIdentity.GetCurrent().Owner
?? throw new InvalidOperationException("Could not determine current user");
PipeAccessRule fullControlForCurrentUser = new
(
currentUser,
PipeAccessRights.FullControl,
AccessControlType.Allow
);
SecurityIdentifier otherUsers = new(WellKnownSidType.AuthenticatedUserSid, null);
PipeAccessRule readWriteForOtherUsers = new
(
otherUsers,
// deny access to extended attributes due to security concerns:
// https://googleprojectzero.blogspot.com/2019/09/windows-exploitation-tricks-spoofing.html
rights: PipeAccessRights.ReadData | PipeAccessRights.WriteData | PipeAccessRights.ReadAttributes | PipeAccessRights.WriteAttributes,
AccessControlType.Allow
);
pipeSecurity = new PipeSecurity();
pipeSecurity.AddAccessRule(fullControlForCurrentUser);
pipeSecurity.AddAccessRule(readWriteForOtherUsers);
s_pipeSecurity = pipeSecurity;
return PipeOptions.FirstPipeInstance;
}
}