Fix pipe ACL: switch from named pipe to TCP loopback
Named pipe created by SYSTEM service denied connection from user process. TCP loopback socket (127.0.0.1:random) has no cross-session ACL issues. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipes;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
@@ -82,71 +83,77 @@ public class RtcService
|
||||
|
||||
private async Task CapturePipeLoopAsync(ClientWebSocket ws, CancellationToken ct)
|
||||
{
|
||||
var pipeName = $"it-nexus-rdp-{Guid.NewGuid():N}";
|
||||
var exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule!.FileName;
|
||||
|
||||
using var pipeServer = new NamedPipeServerStream(
|
||||
pipeName, PipeDirection.In, 1,
|
||||
PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
|
||||
// TCP Loopback: kein ACL-Problem zwischen SYSTEM-Service und User-Prozess
|
||||
var listener = new TcpListener(IPAddress.Loopback, 0);
|
||||
listener.Start();
|
||||
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
||||
|
||||
// Helper via schtasks in User-Session starten
|
||||
if (!SpawnCaptureHelper(exePath, pipeName))
|
||||
if (!SpawnCaptureHelper(exePath, port.ToString()))
|
||||
{
|
||||
listener.Stop();
|
||||
AgentWorker.Log("RDP: Helper-Start fehlgeschlagen");
|
||||
return;
|
||||
}
|
||||
|
||||
TcpClient? tcp = null;
|
||||
try
|
||||
{
|
||||
using var connectCts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
|
||||
using var connectCts = new CancellationTokenSource(TimeSpan.FromSeconds(15));
|
||||
using var linked = CancellationTokenSource.CreateLinkedTokenSource(ct, connectCts.Token);
|
||||
await pipeServer.WaitForConnectionAsync(linked.Token);
|
||||
tcp = await listener.AcceptTcpClientAsync(linked.Token);
|
||||
}
|
||||
catch
|
||||
{
|
||||
listener.Stop();
|
||||
AgentWorker.Log("RDP: Helper hat sich nicht verbunden");
|
||||
return;
|
||||
}
|
||||
finally { listener.Stop(); }
|
||||
|
||||
AgentWorker.Log("RDP: Helper verbunden, sende Frames...");
|
||||
AgentWorker.Log($"RDP: Helper verbunden (Port {port}), sende Frames...");
|
||||
|
||||
var lenBuf = new byte[4];
|
||||
while (!ct.IsCancellationRequested && pipeServer.IsConnected && ws.State == WebSocketState.Open)
|
||||
using (tcp)
|
||||
{
|
||||
try
|
||||
var stream = tcp.GetStream();
|
||||
var lenBuf = new byte[4];
|
||||
|
||||
while (!ct.IsCancellationRequested && tcp.Connected && ws.State == WebSocketState.Open)
|
||||
{
|
||||
// 4-Byte Länge lesen
|
||||
var read = 0;
|
||||
while (read < 4)
|
||||
try
|
||||
{
|
||||
var n = await pipeServer.ReadAsync(lenBuf.AsMemory(read, 4 - read), ct);
|
||||
if (n == 0) goto done;
|
||||
read += n;
|
||||
var read = 0;
|
||||
while (read < 4)
|
||||
{
|
||||
var n = await stream.ReadAsync(lenBuf.AsMemory(read, 4 - read), ct);
|
||||
if (n == 0) goto done;
|
||||
read += n;
|
||||
}
|
||||
var jpegLen = BitConverter.ToInt32(lenBuf);
|
||||
if (jpegLen <= 0 || jpegLen > 5_000_000) continue;
|
||||
|
||||
var jpeg = new byte[jpegLen];
|
||||
read = 0;
|
||||
while (read < jpegLen)
|
||||
{
|
||||
var n = await stream.ReadAsync(jpeg.AsMemory(read, jpegLen - read), ct);
|
||||
if (n == 0) goto done;
|
||||
read += n;
|
||||
}
|
||||
|
||||
var payload = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new
|
||||
{
|
||||
type = "rdp_frame",
|
||||
data = Convert.ToBase64String(jpeg)
|
||||
}));
|
||||
|
||||
if (ws.State == WebSocketState.Open)
|
||||
await ws.SendAsync(new ArraySegment<byte>(payload), WebSocketMessageType.Text, true, CancellationToken.None);
|
||||
}
|
||||
var jpegLen = BitConverter.ToInt32(lenBuf);
|
||||
if (jpegLen <= 0 || jpegLen > 5_000_000) continue;
|
||||
|
||||
// JPEG-Daten lesen
|
||||
var jpeg = new byte[jpegLen];
|
||||
read = 0;
|
||||
while (read < jpegLen)
|
||||
{
|
||||
var n = await pipeServer.ReadAsync(jpeg.AsMemory(read, jpegLen - read), ct);
|
||||
if (n == 0) goto done;
|
||||
read += n;
|
||||
}
|
||||
|
||||
var payload = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new
|
||||
{
|
||||
type = "rdp_frame",
|
||||
data = Convert.ToBase64String(jpeg)
|
||||
}));
|
||||
|
||||
if (ws.State == WebSocketState.Open)
|
||||
await ws.SendAsync(new ArraySegment<byte>(payload), WebSocketMessageType.Text, true, CancellationToken.None);
|
||||
catch (OperationCanceledException) { break; }
|
||||
catch (Exception ex) { AgentWorker.Log($"RDP: TCP-Fehler: {ex.Message}"); break; }
|
||||
}
|
||||
catch (OperationCanceledException) { break; }
|
||||
catch (Exception ex) { AgentWorker.Log($"RDP: Pipe-Fehler: {ex.Message}"); break; }
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
Reference in New Issue
Block a user