//////////////////////////////////////////////////////////////////////////////// // Lists the groups associated with a token //////////////////////////////////////////////////////////////////////////////// public bool GetTokenGroups() { uint returnLength; advapi32.GetTokenInformation(hWorkingToken, Winnt._TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero, 0, out returnLength); hTokenGroups = Marshal.AllocHGlobal((int)returnLength); try { if (!advapi32.GetTokenInformation(hWorkingToken, Winnt._TOKEN_INFORMATION_CLASS.TokenGroups, hTokenGroups, returnLength, out returnLength)) { Misc.GetWin32Error("GetTokenInformation (TokenGroups) - Pass 2"); return(false); } tokenGroups = (Ntifs._TOKEN_GROUPS)Marshal.PtrToStructure(hTokenGroups, typeof(Ntifs._TOKEN_GROUPS)); Console.WriteLine("[+] Enumerated {0} Groups: ", tokenGroups.GroupCount); for (int i = 0; i < tokenGroups.GroupCount; i++) { string sid, account; sid = account = string.Empty; _ReadSidAndName(tokenGroups.Groups[i].Sid, out sid, out account); Console.WriteLine("{0,-50} {1}", sid, account); } return(true); } catch (Exception ex) { Misc.GetWin32Error("GetTokenInformation (TokenGroups) - Pass 2"); Console.WriteLine(ex.Message); return(false); } }
public static extern Boolean AdjustTokenGroups( IntPtr TokenHandle, Boolean ResetToDefault, ref Ntifs._TOKEN_GROUPS NewState, UInt32 BufferLength, ref Ntifs._TOKEN_GROUPS PreviousState, out UInt32 ReturnLengthInBytes );
public static extern bool AdjustTokenGroups( IntPtr TokenHandle, bool ResetToDefault, ref Ntifs._TOKEN_GROUPS NewState, uint BufferLength, IntPtr PreviousState, out uint ReturnLengthInBytes );
internal static extern bool LogonUserExExW( [MarshalAs(UnmanagedType.LPWStr)] string pszUserName, [MarshalAs(UnmanagedType.LPWStr)] string pszDomain, [MarshalAs(UnmanagedType.LPWStr)] string pszPassword, Winbase.LOGON_TYPE dwLogonType, Winbase.LOGON_PROVIDER dwLogonProvider, ref Ntifs._TOKEN_GROUPS pTokenGroups, out IntPtr phToken, IntPtr ppLogonSid, IntPtr ppProfileBuffer, IntPtr pdwProfileLength, IntPtr QuotaLimits );
public static extern uint NtCreateToken( out IntPtr TokenHandle, uint DesiredAccess, ref wudfwdm._OBJECT_ATTRIBUTES ObjectAttributes, Winnt._TOKEN_TYPE TokenType, ref Winnt._LUID AuthenticationId, //From NtAllocateLocallyUniqueId ref long ExpirationTime, ref Ntifs._TOKEN_USER TokenUser, ref Ntifs._TOKEN_GROUPS TokenGroups, ref Winnt._TOKEN_PRIVILEGES_ARRAY TokenPrivileges, ref Ntifs._TOKEN_OWNER TokenOwner, ref Winnt._TOKEN_PRIMARY_GROUP TokenPrimaryGroup, ref Winnt._TOKEN_DEFAULT_DACL TokenDefaultDacl, ref Winnt._TOKEN_SOURCE TokenSource );
private bool CreateTokenPrivileges(Ntifs._TOKEN_USER tokenUser, Ntifs._TOKEN_GROUPS tokenGroups, out Winnt._TOKEN_PRIVILEGES_ARRAY tokenPrivileges) { Console.WriteLine("[*] _TOKEN_PRIVILEGES"); tokenPrivileges = new Winnt._TOKEN_PRIVILEGES_ARRAY(); //Console.WriteLine(" - LsaOpenPolicy"); ntsecapi._LSA_UNICODE_STRING systemName = new ntsecapi._LSA_UNICODE_STRING(); lsalookup._LSA_OBJECT_ATTRIBUTES lsaobjectAttributes = new lsalookup._LSA_OBJECT_ATTRIBUTES() { Length = (uint)Marshal.SizeOf(typeof(lsalookup._LSA_OBJECT_ATTRIBUTES)), RootDirectory = IntPtr.Zero, ObjectName = new ntsecapi._LSA_UNICODE_STRING(), Attributes = 0, SecurityDescriptor = IntPtr.Zero, SecurityQualityOfService = IntPtr.Zero }; IntPtr hPolicyHandle = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr))); uint ntRetVal = advapi32.LsaOpenPolicy( ref systemName, ref lsaobjectAttributes, (uint)lsalookup.LSA_ACCESS_MASK.POLICY_ALL_ACCESS, out hPolicyHandle ); if (0 != ntRetVal) { Misc.GetNtError("LsaOpenPolicy", ntRetVal); return(false); } if (IntPtr.Zero == hPolicyHandle) { Misc.GetNtError("hPolicyHandle", ntRetVal); return(false); } Dictionary <string, Winnt._LUID> rights = new Dictionary <string, Winnt._LUID>(); _LookupRights(hPolicyHandle, tokenUser.User.Sid, ref rights); for (int i = 0; i < extraGroups + localEntriesRead + globalEntriesRead; i++) { _LookupRights(hPolicyHandle, tokenGroups.Groups[i].Sid, ref rights); } tokenPrivileges = new Winnt._TOKEN_PRIVILEGES_ARRAY() { PrivilegeCount = (uint)rights.Keys.Count, Privileges = new Winnt._LUID_AND_ATTRIBUTES[35] }; int j = 0; foreach (string priv in rights.Keys) { tokenPrivileges.Privileges[j].Luid = rights[priv]; tokenPrivileges.Privileges[j].Attributes = Winnt.SE_PRIVILEGE_ENABLED; j++; } return(true); }
internal bool CreateTokenGroups(string domain, string userName, out Ntifs._TOKEN_GROUPS tokenGroups, out Winnt._TOKEN_PRIMARY_GROUP tokenPrimaryGroup, string[] groups) { uint LG_INCLUDE_INDIRECT = 0x0001; Console.WriteLine("[*] _TOKEN_GROUPS"); tokenGroups = new Ntifs._TOKEN_GROUPS(); tokenGroups.Initialize(); tokenPrimaryGroup = new Winnt._TOKEN_PRIMARY_GROUP(); #region NetUserGetLocalGroups //Console.WriteLine(" - NetUserGetLocalGroups"); lmaccess._LOCALGROUP_USERS_INFO_0[] localgroupUserInfo = new lmaccess._LOCALGROUP_USERS_INFO_0[0]; IntPtr bufPtr; uint ntRetVal = netapi32.NetUserGetLocalGroups( domain, userName.ToLower(), 0, LG_INCLUDE_INDIRECT, out bufPtr, -1, ref localEntriesRead, ref localTotalEntriesRead ); if (0 != ntRetVal) { Misc.GetNtError("NetUserGetLocalGroups", ntRetVal); Misc.GetNtError("[-] {0}", ntRetVal); //return false; } localgroupUserInfo = new lmaccess._LOCALGROUP_USERS_INFO_0[localEntriesRead]; Console.WriteLine("[+] Local Groups: {0}", localEntriesRead); for (int i = 0; i < localEntriesRead; i++) { var itemPtr = new IntPtr(bufPtr.ToInt64() + (Marshal.SizeOf(typeof(lmaccess._LOCALGROUP_USERS_INFO_0)) * i)); localgroupUserInfo[i] = (lmaccess._LOCALGROUP_USERS_INFO_0)Marshal.PtrToStructure(itemPtr, typeof(lmaccess._LOCALGROUP_USERS_INFO_0)); Console.WriteLine(" [+] {0}", localgroupUserInfo[i].lgrui0_name); } #endregion #region NetUserGetGroups //Console.WriteLine(" - NetUserGetGroups"); lmaccess._GROUP_USERS_INFO_0[] globalGroupUserInfo;// = new lmaccess._GROUP_USERS_INFO_0[0]; ntRetVal = netapi32.NetUserGetGroups( domain, userName.ToLower(), 0, out bufPtr, -1, ref globalEntriesRead, ref globalEotalEntriesRead ); if (0 != ntRetVal) { Misc.GetNtError("NetUserGetGroups", ntRetVal); Misc.GetNtError("[-] {0}", ntRetVal); //return false; } globalGroupUserInfo = new lmaccess._GROUP_USERS_INFO_0[globalEntriesRead]; Console.WriteLine("[+] Global Groups: {0}", globalEntriesRead); for (int i = 0; i < localEntriesRead; i++) { var itemPtr = new IntPtr(bufPtr.ToInt64() + (Marshal.SizeOf(typeof(lmaccess._GROUP_USERS_INFO_0)) * i)); globalGroupUserInfo[i] = (lmaccess._GROUP_USERS_INFO_0)Marshal.PtrToStructure(itemPtr, typeof(lmaccess._GROUP_USERS_INFO_0)); Console.WriteLine(" [+] {0}", globalGroupUserInfo[i].grui0_name); } #endregion #region Default Admin Entries uint groupsAttributes = (uint)(Winnt.SE_GROUP_ENABLED | Winnt.SE_GROUP_ENABLED_BY_DEFAULT | Winnt.SE_GROUP_MANDATORY); /* * This works, but don't do it this way * //Everyone * _InitializeSid(Winnt.SECURITY_WORLD_SID_AUTHORITY, new uint[] { 0, 0, 0, 0, 0, 0, 0, 0 }, ref tokenGroups.Groups[0].Sid); * tokenGroups.Groups[0].Attributes = groupsAttributes; */ //Console.WriteLine("[+] Extra Groups"); //Everyone InitializeSid("S-1-1-0", ref tokenGroups.Groups[extraGroups].Sid); tokenGroups.Groups[extraGroups++].Attributes = groupsAttributes; //Administrators - Make this a flag InitializeSid("S-1-5-114", ref tokenGroups.Groups[extraGroups].Sid); tokenGroups.Groups[extraGroups++].Attributes = groupsAttributes; //INTERACTIVE InitializeSid("S-1-5-4", ref tokenGroups.Groups[extraGroups].Sid); tokenGroups.Groups[extraGroups++].Attributes = groupsAttributes; //CONSOLE LOGON InitializeSid("S-1-2-1", ref tokenGroups.Groups[extraGroups].Sid); tokenGroups.Groups[extraGroups++].Attributes = groupsAttributes; //Authenticated Users InitializeSid("S-1-5-11", ref tokenGroups.Groups[extraGroups].Sid); tokenGroups.Groups[extraGroups++].Attributes = groupsAttributes; //This Organization InitializeSid("S-1-5-15", ref tokenGroups.Groups[extraGroups].Sid); tokenGroups.Groups[extraGroups++].Attributes = groupsAttributes; //Local account InitializeSid("S-1-5-113", ref tokenGroups.Groups[extraGroups].Sid); tokenGroups.Groups[extraGroups++].Attributes = groupsAttributes; //LOCAL InitializeSid("S-1-2-0", ref tokenGroups.Groups[extraGroups].Sid); tokenGroups.Groups[extraGroups++].Attributes = groupsAttributes; //NTLM Authentication InitializeSid("S-1-5-64-10", ref tokenGroups.Groups[extraGroups].Sid); tokenGroups.Groups[extraGroups++].Attributes = groupsAttributes; //High Integrity Token InitializeSid("S-1-16-12288", ref tokenGroups.Groups[extraGroups].Sid); tokenGroups.Groups[extraGroups++].Attributes = groupsAttributes; #endregion #region Custom Groups //Custom groups foreach (string group in groups) { string d = Environment.MachineName; string groupname = group; if (group.Contains(@"\")) { string[] split = group.Split('\\'); d = split[0]; groupname = split[1]; } string sid = new NTAccount(d, groupname).Translate(typeof(SecurityIdentifier)).Value; InitializeSid(sid, ref tokenGroups.Groups[extraGroups].Sid); tokenGroups.Groups[extraGroups++].Attributes = groupsAttributes; } #endregion #region Local & Global Entries for (int i = 0; i < localEntriesRead; i++) { int offset = i + extraGroups; //Console.WriteLine("[*] Adding: {0}", localgroupUserInfo[i].lgrui0_name); if (!_LookupSid(string.Empty, localgroupUserInfo[i].lgrui0_name, ref tokenGroups.Groups[offset].Sid)) { return(false); } tokenGroups.Groups[offset].Attributes = groupsAttributes; } for (int i = 0; i < globalEntriesRead; i++) { int offset = i + extraGroups + (int)localEntriesRead; //Console.WriteLine("[*] Adding: {0}", globalGroupUserInfo[i].grui0_name); if (!_LookupSid(string.Empty, globalGroupUserInfo[i].grui0_name, ref tokenGroups.Groups[offset].Sid)) { return(false); } if (0 == i) { tokenPrimaryGroup.PrimaryGroup = tokenGroups.Groups[offset].Sid; } tokenGroups.Groups[offset].Attributes = groupsAttributes; } #endregion tokenGroups.GroupCount = (int)(localEntriesRead + globalEntriesRead + extraGroups); Console.WriteLine("[*] Adding Groups"); for (int i = 0; i < tokenGroups.GroupCount; i++) { string sid, account; TokenInformation._ReadSidAndName(tokenGroups.Groups[i].Sid, out sid, out account); Console.WriteLine(" ({0}) {1,-50} {2}", i, sid, account); } return(true); }
//////////////////////////////////////////////////////////////////////////////// // Can be use to remove groups, adding groups would require a new token // Next Release //https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-adjusttokengroups //////////////////////////////////////////////////////////////////////////////// public void SetTokenGroup(string group, bool isSID) { var tokenGroups = new Ntifs._TOKEN_GROUPS(); tokenGroups.Initialize(); if (!DuplicateToken(Winnt._SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation)) { return; } SetWorkingTokenToNewToken(); TokenInformation ti = new TokenInformation(hWorkingToken); ti.GetTokenGroups(); for (int i = 0; i < ti.tokenGroups.GroupCount; i++) { tokenGroups.Groups[i].Sid = ti.tokenGroups.Groups[i].Sid; tokenGroups.Groups[i].Attributes = ti.tokenGroups.Groups[i].Attributes; Console.WriteLine(tokenGroups.Groups[i].Sid); } tokenGroups.GroupCount = ti.tokenGroups.GroupCount; if (!isSID) { Console.WriteLine("Group: {0}", group); string domain = Environment.MachineName; if (group.Contains(@"\")) { string[] split = group.Split('\\'); domain = split[0]; group = split[1]; } group = new NTAccount(domain, group).Translate(typeof(SecurityIdentifier)).Value; } Console.WriteLine("Group SID: {0}", group); ++tokenGroups.GroupCount; if (!CreateTokens.InitializeSid("S-1-5-21-258464558-1780981397-2849438727-1010", ref tokenGroups.Groups[tokenGroups.GroupCount].Sid)) { return; } tokenGroups.Groups[tokenGroups.GroupCount].Attributes = (uint)Winnt.SE_GROUP_ENABLED; CreateTokens ct = new CreateTokens(hWorkingToken); string userName = WindowsIdentity.GetCurrent().Name; userName = userName.Split('\\')[1]; //ct.CreateTokenGroups(userName, out Ntifs._TOKEN_GROUPS tg, out Winnt._TOKEN_PRIMARY_GROUP tpg); tokenGroups = ti.tokenGroups; uint returnLength; if (!advapi32.AdjustTokenGroups(hWorkingToken, false, ref tokenGroups, (uint)Marshal.SizeOf(tokenGroups), ref ti.tokenGroups, out returnLength)) { Misc.GetWin32Error("AdjustTokenGroups"); return; } ti.GetTokenGroups(); Console.WriteLine(returnLength); }