CLI tool for running Playbooks
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

506 lines
25 KiB

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Win32.SafeHandles;
using TrustedUninstaller.Shared.Actions;
namespace TrustedUninstaller.Shared
{
public class ProcessPrivilege
{
private static Win32.TokensEx.SafeTokenHandle userToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
private static Win32.TokensEx.SafeTokenHandle elevatedUserToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
private static Win32.TokensEx.SafeTokenHandle systemToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
private static Win32.TokensEx.SafeTokenHandle impsersonatedSystemToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
private static Win32.TokensEx.SafeTokenHandle lsassToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
internal static void ResetTokens()
{
elevatedUserToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
lsassToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
systemToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
impsersonatedSystemToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
userToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
}
public static void StartPrivilegedTask(AugmentedProcess.Process process, Privilege privilege)
{
var tcs = StartThread(process, privilege);
tcs.Task.Wait();
for (int i = 0; tcs.Task.Result != null && i <= 3; i++)
{
ErrorLogger.WriteToErrorLog("Error launching privileged process: " + tcs.Task.Result.Message, tcs.Task.Result.StackTrace, "PrivilegedProcess Warning",
Path.GetFileName(process.StartInfo.FileName));
ResetTokens();
Thread.Sleep(500 * i);
tcs = StartThread(process, privilege);
tcs.Task.Wait();
}
if (tcs.Task.Result != null)
throw new SecurityException("Error launching privileged process.", tcs.Task.Result);
}
private static TaskCompletionSource<Exception> StartThread(AugmentedProcess.Process process, Privilege privilege)
{
var tcs = new TaskCompletionSource<Exception>();
var thread = new Thread(() =>
{
try
{
switch (privilege)
{
case (Privilege.System):
GetSystemToken();
process.Start(AugmentedProcess.Process.CreateType.RawToken, ref systemToken);
break;
case (Privilege.CurrentUser):
GetUserToken(true);
process.Start(AugmentedProcess.Process.CreateType.UserToken, ref userToken);
break;
case (Privilege.CurrentUserElevated):
GetElevatedUserToken();
process.Start(AugmentedProcess.Process.CreateType.RawToken, ref elevatedUserToken);
break;
default:
throw new ArgumentException("Unexpected.");
}
}
catch (Exception e)
{
tcs.SetResult(e);
return;
}
tcs.SetResult(null);
});
thread.Start();
return tcs;
}
private static uint GetUserSession()
{
var sessionId = Win32.WTS.WTSGetActiveConsoleSessionId();
if (sessionId != 0xFFFFFFFF) return sessionId;
IntPtr pSessionInfo = IntPtr.Zero;
Int32 count = 0;
if (Win32.WTS.WTSEnumerateSessions((IntPtr)null, 0, 1, ref pSessionInfo, ref count) == 0)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error enumerating user sessions.");
Int32 dataSize = Marshal.SizeOf(typeof(Win32.WTS.WTS_SESSION_INFO));
Int64 current = (Int64)pSessionInfo;
for (int i = 0; i < count; i++)
{
Win32.WTS.WTS_SESSION_INFO si =
(Win32.WTS.WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current,
typeof(Win32.WTS.WTS_SESSION_INFO));
current += dataSize;
if (si.State == Win32.WTS.WTS_CONNECTSTATE_CLASS.WTSActive)
{
sessionId = (uint)si.SessionID;
break;
}
}
Win32.WTS.WTSFreeMemory(pSessionInfo);
return sessionId;
}
private static void GetUserToken(bool getPrivileges)
{
if (getPrivileges)
{
GetSystemToken();
var result = Win32.Tokens.ImpersonateLoggedOnUser(systemToken);
if (!result)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error impersonating system process token.");
Win32.TokensEx.AdjustCurrentPrivilege(Win32.Tokens.SE_ASSIGNPRIMARYTOKEN_NAME);
Win32.TokensEx.AdjustCurrentPrivilege(Win32.Tokens.SE_INCREASE_QUOTA_NAME);
}
if (userToken.DangerousGetHandle() != IntPtr.Zero)
return;
var sessionId = GetUserSession();
if (Win32.WTS.WTSQueryUserToken(sessionId, out Win32.TokensEx.SafeTokenHandle wtsToken))
{
if (!Win32.Tokens.DuplicateTokenEx(wtsToken, Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS,
IntPtr.Zero,
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
Win32.Tokens.TOKEN_TYPE.TokenPrimary, out userToken))
{
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to duplicate process token for lsass.");
}
return;
}
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error fetching active user session token.");
}
private static void GetElevatedUserToken()
{
GetSystemToken();
var result = Win32.Tokens.ImpersonateLoggedOnUser(systemToken);
if (!result)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error impersonating system process token.");
if (lsassToken.DangerousGetHandle() == IntPtr.Zero)
{
var processHandle = Win32.Process.OpenProcess(Win32.Process.ProcessAccessFlags.QueryLimitedInformation, false, Process.GetProcessesByName("lsass").First().Id);
if (!Win32.Tokens.OpenProcessToken(processHandle,
Win32.Tokens.TokenAccessFlags.TOKEN_DUPLICATE |
Win32.Tokens.TokenAccessFlags.TOKEN_ASSIGN_PRIMARY |
Win32.Tokens.TokenAccessFlags.TOKEN_QUERY | Win32.Tokens.TokenAccessFlags.TOKEN_IMPERSONATE,
out var tokenHandle))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to open process token for lsass.");
}
if (!Win32.Tokens.DuplicateTokenEx(tokenHandle, Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS,
IntPtr.Zero,
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
Win32.Tokens.TOKEN_TYPE.TokenImpersonation, out lsassToken))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to duplicate process token for lsass.");
}
Win32.CloseHandle(processHandle);
}
result = Win32.Tokens.ImpersonateLoggedOnUser(lsassToken);
if (!result)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error impersonating lsass process token.");
Win32.TokensEx.AdjustCurrentPrivilege(Win32.Tokens.SE_ASSIGNPRIMARYTOKEN_NAME);
Win32.TokensEx.AdjustCurrentPrivilege(Win32.Tokens.SE_INCREASE_QUOTA_NAME);
if (elevatedUserToken.DangerousGetHandle() != IntPtr.Zero)
return;
var privileges = new[]
{
Win32.Tokens.SE_INCREASE_QUOTA_NAME,
Win32.Tokens.SE_MACHINE_ACCOUNT_NAME, Win32.Tokens.SE_SECURITY_NAME,
Win32.Tokens.SE_TAKE_OWNERSHIP_NAME, Win32.Tokens.SE_LOAD_DRIVER_NAME,
Win32.Tokens.SE_SYSTEM_PROFILE_NAME, Win32.Tokens.SE_SYSTEMTIME_NAME,
Win32.Tokens.SE_PROFILE_SINGLE_PROCESS_NAME, Win32.Tokens.SE_INCREASE_BASE_PRIORITY_NAME,
Win32.Tokens.SE_CREATE_PERMANENT_NAME,
Win32.Tokens.SE_BACKUP_NAME, Win32.Tokens.SE_RESTORE_NAME, Win32.Tokens.SE_SHUTDOWN_NAME,
Win32.Tokens.SE_DEBUG_NAME, Win32.Tokens.SE_AUDIT_NAME, Win32.Tokens.SE_SYSTEM_ENVIRONMENT_NAME,
Win32.Tokens.SE_CHANGE_NOTIFY_NAME,
Win32.Tokens.SE_UNDOCK_NAME, Win32.Tokens.SE_SYNC_AGENT_NAME,
Win32.Tokens.SE_ENABLE_DELEGATION_NAME, Win32.Tokens.SE_MANAGE_VOLUME_NAME,
Win32.Tokens.SE_IMPERSONATE_NAME, Win32.Tokens.SE_CREATE_GLOBAL_NAME,
Win32.Tokens.SE_TRUSTED_CREDMAN_ACCESS_NAME, Win32.Tokens.SE_RELABEL_NAME,
Win32.Tokens.SE_TIME_ZONE_NAME,
Win32.Tokens.SE_CREATE_SYMBOLIC_LINK_NAME, Win32.Tokens.SE_DELEGATE_SESSION_USER_IMPERSONATE_NAME
};
var authId = Win32.Tokens.SYSTEM_LUID;
GetUserToken(false);
Win32.Tokens.DuplicateTokenEx(userToken,
Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS, IntPtr.Zero,
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Win32.Tokens.TOKEN_TYPE.TokenPrimary,
out Win32.TokensEx.SafeTokenHandle dupedUserToken);
Win32.SID.AllocateAndInitializeSid(
ref Win32.SID.SECURITY_MANDATORY_LABEL_AUTHORITY,
1,
(int)Win32.SID.SECURITY_MANDATORY_LABEL.High,
0,
0,
0,
0,
0,
0,
0,
out IntPtr integritySid);
var tokenMandatoryLabel = new Win32.Tokens.TOKEN_MANDATORY_LABEL() {
Label = default(Win32.SID.SID_AND_ATTRIBUTES)
};
tokenMandatoryLabel.Label.Attributes = (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_INTEGRITY;
tokenMandatoryLabel.Label.Sid = integritySid;
var integritySize = Marshal.SizeOf(tokenMandatoryLabel);
var tokenInfo = Marshal.AllocHGlobal(integritySize);
Marshal.StructureToPtr(tokenMandatoryLabel, tokenInfo, false);
Win32.Tokens.SetTokenInformation(
dupedUserToken,
Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenIntegrityLevel,
tokenInfo,
integritySize + Win32.SID.GetLengthSid(integritySid));
var pTokenUser = Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenUser);
var pTokenOwner =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenOwner);
var pTokenPrivileges =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenPrivileges);
var pTokenGroups =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenGroups);
var pTokenPrimaryGroup =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenPrimaryGroup);
var pTokenDefaultDacl =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenDefaultDacl);
var pTokenSource =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenSource);
var tokenUser =
(Win32.Tokens.TOKEN_USER)Marshal.PtrToStructure(pTokenUser, typeof(Win32.Tokens.TOKEN_USER));
if (!Win32.TokensEx.CreateTokenPrivileges(privileges, out var tokenPrivileges))
tokenPrivileges =
(Win32.Tokens.TOKEN_PRIVILEGES)Marshal.PtrToStructure(pTokenPrivileges,
typeof(Win32.Tokens.TOKEN_PRIVILEGES));
var tokenGroups = (Win32.Tokens.TOKEN_GROUPS)Marshal.PtrToStructure(
pTokenGroups, typeof(Win32.Tokens.TOKEN_GROUPS));
var tokenOwner =
(Win32.Tokens.TOKEN_OWNER)Marshal.PtrToStructure(pTokenOwner, typeof(Win32.Tokens.TOKEN_OWNER));
var tokenPrimaryGroup =
(Win32.Tokens.TOKEN_PRIMARY_GROUP)Marshal.PtrToStructure(pTokenPrimaryGroup,
typeof(Win32.Tokens.TOKEN_PRIMARY_GROUP));
var tokenDefaultDacl = (Win32.Tokens.TOKEN_DEFAULT_DACL)Marshal.PtrToStructure(
pTokenDefaultDacl, typeof(Win32.Tokens.TOKEN_DEFAULT_DACL));
var tokenSource = (Win32.Tokens.TOKEN_SOURCE)Marshal.PtrToStructure(
pTokenSource, typeof(Win32.Tokens.TOKEN_SOURCE));
/*
for (var idx = 0; idx < tokenPrivileges.PrivilegeCount - 1; idx++)
{
if ((tokenPrivileges.Privileges[idx].Attributes &
(uint)Win32.Tokens.SE_PRIVILEGE_ATTRIBUTES.SE_PRIVILEGE_ENABLED) != 0)
{
}
if ((tokenPrivileges.Privileges[idx].Attributes &
(uint)Win32.Tokens.SE_PRIVILEGE_ATTRIBUTES.SE_PRIVILEGE_ENABLED_BY_DEFAULT) != 0)
{
}
}
*/
IntPtr adminsSid = IntPtr.Zero;
IntPtr localAndAdminSid = IntPtr.Zero;
bool adminsFound = false;
bool localAndAdminFound = false;
for (var idx = 0; idx < tokenGroups.GroupCount - 1; idx++)
{
Win32.SID.ConvertSidToStringSid(tokenGroups.Groups[idx].Sid, out string strSid);
if (string.Compare(strSid, Win32.SID.DOMAIN_ALIAS_RID_ADMINS, StringComparison.OrdinalIgnoreCase) == 0)
{
adminsFound = true;
tokenGroups.Groups[idx].Attributes = (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED |
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES
.SE_GROUP_ENABLED_BY_DEFAULT | (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_MANDATORY | (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_OWNER;
} else if (string.Compare(strSid, Win32.SID.DOMAIN_ALIAS_RID_LOCAL_AND_ADMIN_GROUP, StringComparison.OrdinalIgnoreCase) == 0)
{
localAndAdminFound = true;
tokenGroups.Groups[idx].Attributes = (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED |
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES
.SE_GROUP_ENABLED_BY_DEFAULT | (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_MANDATORY;
}
}
if (!adminsFound)
{
Win32.SID.ConvertStringSidToSid(Win32.SID.DOMAIN_ALIAS_RID_ADMINS, out adminsSid);
tokenGroups.Groups[tokenGroups.GroupCount].Sid = adminsSid;
tokenGroups.Groups[tokenGroups.GroupCount].Attributes =
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED |
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED_BY_DEFAULT;
tokenGroups.GroupCount++;
}
if (!localAndAdminFound)
{
Win32.SID.ConvertStringSidToSid(Win32.SID.DOMAIN_ALIAS_RID_LOCAL_AND_ADMIN_GROUP, out localAndAdminSid);
tokenGroups.Groups[tokenGroups.GroupCount].Sid = localAndAdminSid;
tokenGroups.Groups[tokenGroups.GroupCount].Attributes =
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED |
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED_BY_DEFAULT;
tokenGroups.GroupCount++;
}
var expirationTime = new Win32.LARGE_INTEGER() { QuadPart = -1L };
var sqos = new Win32.Tokens.SECURITY_QUALITY_OF_SERVICE(
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Win32.Tokens.SECURITY_STATIC_TRACKING,
0);
var oa = new Win32.Tokens.OBJECT_ATTRIBUTES(string.Empty, 0) { };
var pSqos = Marshal.AllocHGlobal(Marshal.SizeOf(sqos));
Marshal.StructureToPtr(sqos, pSqos, true);
oa.SecurityQualityOfService = pSqos;
var status = Win32.Tokens.ZwCreateToken(out elevatedUserToken,
Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS, ref oa, Win32.Tokens.TOKEN_TYPE.TokenPrimary,
ref authId, ref expirationTime, ref tokenUser, ref tokenGroups, ref tokenPrivileges, ref tokenOwner,
ref tokenPrimaryGroup, ref tokenDefaultDacl, ref tokenSource);
Win32.LocalFree(pTokenUser);
Win32.LocalFree(pTokenOwner);
Win32.LocalFree(pTokenGroups);
Win32.LocalFree(pTokenDefaultDacl);
Win32.LocalFree(pTokenPrivileges);
Win32.LocalFree(pTokenPrimaryGroup);
if (adminsSid != IntPtr.Zero)
Win32.SID.FreeSid(adminsSid);
if (localAndAdminSid != IntPtr.Zero)
Win32.SID.FreeSid(localAndAdminSid);
if (integritySid != IntPtr.Zero)
Win32.SID.FreeSid(integritySid);
if (status != 0)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error creating elevated user token: " + status);
}
public static void GetSystemToken()
{
if (systemToken.DangerousGetHandle() != IntPtr.Zero)
return;
try
{
var processHandle = Win32.Process.OpenProcess(Win32.Process.ProcessAccessFlags.QueryLimitedInformation, false, Process.GetProcessesByName("winlogon").First().Id);
if (!Win32.Tokens.OpenProcessToken(processHandle,
Win32.Tokens.TokenAccessFlags.TOKEN_DUPLICATE | Win32.Tokens.TokenAccessFlags.TOKEN_ASSIGN_PRIMARY |
Win32.Tokens.TokenAccessFlags.TOKEN_QUERY | Win32.Tokens.TokenAccessFlags.TOKEN_IMPERSONATE,
out var tokenHandle))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to open process token for winlogon.");
}
if (!Win32.Tokens.DuplicateTokenEx(tokenHandle, Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS, IntPtr.Zero,
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
Win32.Tokens.TOKEN_TYPE.TokenPrimary, out systemToken))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to duplicate process token for winlogon.");
}
Win32.CloseHandle(processHandle);
}
catch (Exception e)
{
var sessionId = GetUserSession();
int dwLsassPID = -1;
int dwWinLogonPID = -1;
Win32.WTS.WTS_PROCESS_INFO[] pProcesses;
IntPtr pProcessInfo = IntPtr.Zero;
int dwProcessCount = 0;
if (Win32.WTS.WTSEnumerateProcesses((IntPtr)null, 0, 1, ref pProcessInfo, ref dwProcessCount))
{
IntPtr pMemory = pProcessInfo;
pProcesses = new Win32.WTS.WTS_PROCESS_INFO[dwProcessCount];
for (int i = 0; i < dwProcessCount; i++)
{
pProcesses[i] =
(Win32.WTS.WTS_PROCESS_INFO)Marshal.PtrToStructure(pProcessInfo,
typeof(Win32.WTS.WTS_PROCESS_INFO));
pProcessInfo = (IntPtr)((long)pProcessInfo + Marshal.SizeOf(pProcesses[i]));
var processName = Marshal.PtrToStringAnsi(pProcesses[i].ProcessName);
Win32.SID.ConvertSidToStringSid(pProcesses[i].UserSid, out string sid);
string strSid;
if (processName == null || pProcesses[i].UserSid == default || sid != "S-1-5-18") continue;
if ((-1 == dwLsassPID) && (0 == pProcesses[i].SessionID) && (processName == "lsass.exe"))
{
dwLsassPID = pProcesses[i].ProcessID;
continue;
}
if ((-1 == dwWinLogonPID) && (sessionId == pProcesses[i].SessionID) &&
(processName == "winlogon.exe"))
{
dwWinLogonPID = pProcesses[i].ProcessID;
continue;
}
}
Win32.WTS.WTSFreeMemory(pMemory);
}
IntPtr systemProcessHandle = IntPtr.Zero;
try
{
systemProcessHandle = Process.GetProcessById(dwLsassPID).Handle;
}
catch
{
systemProcessHandle = Process.GetProcessById(dwWinLogonPID).Handle;
}
if (!Win32.Tokens.OpenProcessToken(systemProcessHandle, Win32.Tokens.TokenAccessFlags.TOKEN_DUPLICATE,
out Win32.TokensEx.SafeTokenHandle token))
{
Win32.CloseHandle(systemProcessHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to open process token.");
}
if (!Win32.Tokens.DuplicateTokenEx(token, Win32.Tokens.TokenAccessFlags.MAXIMUM_ALLOWED, IntPtr.Zero,
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
Win32.Tokens.TOKEN_TYPE.TokenPrimary, out systemToken))
{
Win32.CloseHandle(systemProcessHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to duplicate process token.");
}
Win32.CloseHandle(systemProcessHandle);
}
}
public static Win32.TokensEx.SafeTokenHandle GetCurrentProcessToken()
{
if (!Win32.Tokens.OpenProcessToken(Win32.Process.GetCurrentProcess(),
Win32.Tokens.TokenAccessFlags.TOKEN_READ, out Win32.TokensEx.SafeTokenHandle token))
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error opening token for current process.");
return token;
}
private static Win32.TokensEx.SafeTokenHandle GetProcessTokenByName(string name, bool impersonation)
{
var processHandle = Process.GetProcessesByName(name).First().Handle;
if (!Win32.Tokens.OpenProcessToken(processHandle,
Win32.Tokens.TokenAccessFlags.TOKEN_DUPLICATE | Win32.Tokens.TokenAccessFlags.TOKEN_ASSIGN_PRIMARY |
Win32.Tokens.TokenAccessFlags.TOKEN_QUERY | Win32.Tokens.TokenAccessFlags.TOKEN_IMPERSONATE,
out var tokenHandle))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to open process token for " + name + ".");
}
if (!Win32.Tokens.DuplicateTokenEx(tokenHandle, Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS, IntPtr.Zero,
impersonation ? Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation : Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
impersonation ? Win32.Tokens.TOKEN_TYPE.TokenImpersonation : Win32.Tokens.TOKEN_TYPE.TokenPrimary, out Win32.TokensEx.SafeTokenHandle handle))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to duplicate process token for " + name + ".");
}
Win32.CloseHandle(processHandle);
return handle;
} }
}