当需要登录界面截图,和模拟键盘,或其它特殊操作,需要提权到SYSTEM
如果此时程序需要操作注册表,就无法使用HKEY_CURRENT_USER来设置当前用户的配置,此时就需要使用HKEY_USERS来设置当前系统登录用户的配置
又因为用的是SYSTEM用户运行程序,所以需要用winapi来获取sid,而无法直接获取
定义一些内容
C#
[DllImport("kernel32.dll")]public static extern uint WTSGetActiveConsoleSessionId();[DllImport("Wtsapi32.dll")]public static extern bool WTSQueryUserToken(int sessionId, out IntPtr token);[DllImport("advapi32.dll", SetLastError = true)]public static extern bool GetTokenInformation( nint TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, nint TokenInformation, int TokenInformationLength, out int ReturnLength);[DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true), SuppressUnmanagedCodeSecurity]public static extern bool ConvertSidToStringSid(IntPtr sid, out string stringSid);public enum TOKEN_INFORMATION_CLASS{ TokenUser = 1, TokenGroups, TokenPrivileges, TokenOwner, TokenPrimaryGroup, TokenDefaultDacl, TokenSource, TokenType, TokenImpersonationLevel, TokenStatistics, TokenRestrictedSids, TokenSessionId, TokenGroupsAndPrivileges, TokenSessionReference, TokenSandBoxInert, TokenAuditPolicy, TokenOrigin, TokenElevationType, TokenLinkedToken, TokenElevation, TokenHasRestrictions, TokenAccessInformation, TokenVirtualizationAllowed, TokenVirtualizationEnabled, TokenIntegrityLevel, TokenUIAccess, TokenMandatoryPolicy, TokenLogonSid, MaxTokenInfoClass}[StructLayout(LayoutKind.Sequential)]public struct TOKEN_USER{ public SID_AND_ATTRIBUTES User;}[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]public struct USER_INFO_0{ public string usri0_name;}[DllImport("Netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]public static extern int NetUserEnum(StringBuilder servername,int level,int filter,out IntPtr bufptr,int prefmaxlen,out int entriesread,out int totalentries,ref int resume_handle);[DllImport("Netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]public static extern int NetApiBufferFree(IntPtr Buffer);[DllImport("Advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]public static extern bool LookupAccountName( string lpSystemName, string lpAccountName, IntPtr Sid, ref int cbSid, StringBuilder ReferencedDomainName, ref int cchReferencedDomainName, out int peUse);获取当前登录用户的sid
C#
private static string currentUsername = string.Empty;public static string GetCurrentUserSid() { if (OperatingSystem.IsWindows() == false) { return string.Empty; } if (OperatingSystem.IsWindows()) { WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent(); currentUsername = currentIdentity.Name; //不是SYSTEM用户,直接获取当前用户sid if (IsSystemUser() == false) { return currentIdentity.User.Value; } } //获取系统登录用户sid IntPtr hToken; int sessionId = (int)Kernel32.WTSGetActiveConsoleSessionId(); if (WTSAPI32.WTSQueryUserToken(sessionId, out hToken)) { try { IntPtr tokenInformation; int returnLength; if (GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenUser, IntPtr.Zero, 0, out returnLength) || returnLength == 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } tokenInformation = Marshal.AllocHGlobal(returnLength); try { if (!GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenUser, tokenInformation, returnLength, out returnLength)) { return string.Empty; } var user = (TOKEN_USER)Marshal.PtrToStructure(tokenInformation, typeof(TOKEN_USER)); string stringSid; if (ConvertSidToStringSid(user.User.Sid, out stringSid)) { return stringSid; } } finally { Marshal.FreeHGlobal(tokenInformation); } } finally { if (hToken != IntPtr.Zero) { Marshal.FreeHGlobal(hToken); } } } return string.Empty;}public static bool IsSystemUser(){ return currentUsername == "NT AUTHORITY\\SYSTEM";}未登录系统,获取默认用户sid
当系统只有一个登录用户时,可以作为默认sid,以操作注册表
C#
public static string GetDefaultUserSid(){ if (OperatingSystem.IsWindows() == false) { return string.Empty; } List<string> registrySids = Registry.Users.GetSubKeyNames().ToList(); List<string> sids = new List<string>(); int resumeHandle = 0; int result = NetApi32.NetUserEnum(null, 0, 2, out IntPtr bufPtr, -1, out int entriesRead, out int totalEntries, ref resumeHandle); if (result == 0) { try { for (int i = 0; i < entriesRead; i++) { USER_INFO_0 userInfo = (USER_INFO_0)Marshal.PtrToStructure(bufPtr+(Marshal.SizeOf(typeof(USER_INFO_0))*i), typeof(USER_INFO_0)); int cbSid = 0; int cchReferencedDomainName = 0; int peUse; StringBuilder referencedDomainName = new StringBuilder(); IntPtr pSid = IntPtr.Zero; bool bSuccess = LookupAccountName(null, userInfo.usri0_name, pSid, ref cbSid, referencedDomainName, ref cchReferencedDomainName, out peUse); if (!bSuccess && cbSid > 0) { pSid = Marshal.AllocHGlobal(cbSid); referencedDomainName.EnsureCapacity(cchReferencedDomainName); bSuccess = LookupAccountName(null, userInfo.usri0_name, pSid, ref cbSid, referencedDomainName, ref cchReferencedDomainName, out peUse); } if (bSuccess) { if (ConvertSidToStringSid(pSid, out string stringSid)) { if (registrySids.Contains(stringSid)) { sids.Add(stringSid); } } } if (pSid != IntPtr.Zero) { Marshal.FreeHGlobal(pSid); } } } catch (Exception) { } finally { NetApi32.NetApiBufferFree(bufPtr); } } if(sids.Count == 1) { return sids[0]; } return string.Empty;}可以配置注册表了
C#
HKEY_USERS\{sid}\xxx
支付宝微信扫一扫,打赏作者吧~
