如果给定用户有SeInteractiveLogonRight和SeRemoteInteractiveLogonRight to find out,我会尝试user rights。最初我认为我使用了GetTokenInformation函数,提供了TokenPrivileges的TOKEN_INFORMATION_CLASS。不幸的是,它没有成功,因为只返回了特权,没有用户权限,如SeInteractiveLogonRight和SeRemoteInteractiveLogonRight。
This page最后有一句相当神秘的句子:
GetTokenInformation函数将获取有关帐户的信息 权限,如果TokenGroups,而不是TokenPrivileges,被指定为 TokenInformationClass参数的值。
我不明白这一点,因为如果我调用此函数传递TokenGroups,我得到的只是组sids - 本地和域。没有返回类似登录权限的内容。你能解释一下吗?
现在,如果有其他方式获取我想要的信息,请告诉我。我尝试调用LsaEnumerateAccountRights,但这不起作用,因为如果帐户直接持有特权,而不是作为组成员资格的一部分,则返回特权。我需要找到有效的权限,即使它是通过多级组成员身份获得的。
与上述GetTokenInformation相反,确实返回了有效权限,但我似乎无法找到返回登录权限的方法。
因为在stackoverflow上习惯显示一些代码,所以这是我的。对不起它的powershell,因为这个问题更适合c ++开发者,但这就是我推动它的方式。
这不是一个PowerShell问题,如果你能提供任何与c ++相关的指针,他们也会提供帮助,我只需要在概念上解决这个问题。语言并不重要。
GetTokenInformation代码基于some code from github,位于以下位置:
#Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/
Function Get-DelegateType
{
Param
(
[OutputType([Type])]
[Parameter( Position = 0)]
[Type[]]
$Parameters = (New-Object Type[](0)),
[Parameter( Position = 1 )]
[Type]
$ReturnType = [Void]
)
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
Write-Output $TypeBuilder.CreateType()
}
#Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/
Function Get-ProcAddress
{
Param
(
[OutputType([IntPtr])]
[Parameter( Position = 0, Mandatory = $True )]
[String]
$Module,
[Parameter( Position = 1, Mandatory = $True )]
[String]
$Procedure
)
# Get a reference to System.dll in the GAC
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
# Get a reference to the GetModuleHandle and GetProcAddress methods
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
# Get a handle to the module specified
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
# Return the address of the function
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}
$Domain = [AppDomain]::CurrentDomain
$DynamicAssembly = New-Object System.Reflection.AssemblyName('DynamicAssembly')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynamicAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('DynamicModule', $false)
$ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]
#ENUMs
$TypeBuilder = $ModuleBuilder.DefineEnum('TOKEN_INFORMATION_CLASS', 'Public', [UInt32])
$TypeBuilder.DefineLiteral('TokenUser', [UInt32] 1) | Out-Null
$TypeBuilder.DefineLiteral('TokenGroups', [UInt32] 2) | Out-Null
$TypeBuilder.DefineLiteral('TokenPrivileges', [UInt32] 3) | Out-Null
$TypeBuilder.DefineLiteral('TokenOwner', [UInt32] 4) | Out-Null
$TypeBuilder.DefineLiteral('TokenPrimaryGroup', [UInt32] 5) | Out-Null
$TypeBuilder.DefineLiteral('TokenDefaultDacl', [UInt32] 6) | Out-Null
$TypeBuilder.DefineLiteral('TokenSource', [UInt32] 7) | Out-Null
$TypeBuilder.DefineLiteral('TokenType', [UInt32] 8) | Out-Null
$TypeBuilder.DefineLiteral('TokenImpersonationLevel', [UInt32] 9) | Out-Null
$TypeBuilder.DefineLiteral('TokenStatistics', [UInt32] 10) | Out-Null
$TypeBuilder.DefineLiteral('TokenRestrictedSids', [UInt32] 11) | Out-Null
$TypeBuilder.DefineLiteral('TokenSessionId', [UInt32] 12) | Out-Null
$TypeBuilder.DefineLiteral('TokenGroupsAndPrivileges', [UInt32] 13) | Out-Null
$TypeBuilder.DefineLiteral('TokenSessionReference', [UInt32] 14) | Out-Null
$TypeBuilder.DefineLiteral('TokenSandBoxInert', [UInt32] 15) | Out-Null
$TypeBuilder.DefineLiteral('TokenAuditPolicy', [UInt32] 16) | Out-Null
$TypeBuilder.DefineLiteral('TokenOrigin', [UInt32] 17) | Out-Null
$TypeBuilder.DefineLiteral('TokenElevationType', [UInt32] 18) | Out-Null
$TypeBuilder.DefineLiteral('TokenLinkedToken', [UInt32] 19) | Out-Null
$TypeBuilder.DefineLiteral('TokenElevation', [UInt32] 20) | Out-Null
$TypeBuilder.DefineLiteral('TokenHasRestrictions', [UInt32] 21) | Out-Null
$TypeBuilder.DefineLiteral('TokenAccessInformation', [UInt32] 22) | Out-Null
$TypeBuilder.DefineLiteral('TokenVirtualizationAllowed', [UInt32] 23) | Out-Null
$TypeBuilder.DefineLiteral('TokenVirtualizationEnabled', [UInt32] 24) | Out-Null
$TypeBuilder.DefineLiteral('TokenIntegrityLevel', [UInt32] 25) | Out-Null
$TypeBuilder.DefineLiteral('TokenUIAccess', [UInt32] 26) | Out-Null
$TypeBuilder.DefineLiteral('TokenMandatoryPolicy', [UInt32] 27) | Out-Null
$TypeBuilder.DefineLiteral('TokenLogonSid', [UInt32] 28) | Out-Null
$TypeBuilder.DefineLiteral('TokenIsAppContainer', [UInt32] 29) | Out-Null
$TypeBuilder.DefineLiteral('TokenCapabilities', [UInt32] 30) | Out-Null
$TypeBuilder.DefineLiteral('TokenAppContainerSid', [UInt32] 31) | Out-Null
$TypeBuilder.DefineLiteral('TokenAppContainerNumber', [UInt32] 32) | Out-Null
$TypeBuilder.DefineLiteral('TokenUserClaimAttributes', [UInt32] 33) | Out-Null
$TypeBuilder.DefineLiteral('TokenDeviceClaimAttributes', [UInt32] 34) | Out-Null
$TypeBuilder.DefineLiteral('TokenRestrictedUserClaimAttributes', [UInt32] 35) | Out-Null
$TypeBuilder.DefineLiteral('TokenRestrictedDeviceClaimAttributes', [UInt32] 36) | Out-Null
$TypeBuilder.DefineLiteral('TokenDeviceGroups', [UInt32] 37) | Out-Null
$TypeBuilder.DefineLiteral('TokenRestrictedDeviceGroups', [UInt32] 38) | Out-Null
$TypeBuilder.DefineLiteral('TokenSecurityAttributes', [UInt32] 39) | Out-Null
$TypeBuilder.DefineLiteral('TokenIsRestricted', [UInt32] 40) | Out-Null
$TypeBuilder.DefineLiteral('MaxTokenInfoClass', [UInt32] 41) | Out-Null
$TOKEN_INFORMATION_CLASS = $TypeBuilder.CreateType()
$GetTokenInformationAddr = Get-ProcAddress advapi32.dll GetTokenInformation
$GetTokenInformationDelegate = Get-DelegateType @([IntPtr], $TOKEN_INFORMATION_CLASS, [IntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool])
$GetTokenInformation = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetTokenInformationAddr, $GetTokenInformationDelegate)
$LookupPrivilegeNameWAddr = Get-ProcAddress advapi32.dll LookupPrivilegeNameW
$LookupPrivilegeNameWDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UInt32].MakeByRefType()) ([Bool])
$LookupPrivilegeNameW = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupPrivilegeNameWAddr, $LookupPrivilegeNameWDelegate)
$LookupAccountSidWAddr = Get-ProcAddress advapi32.dll LookupAccountSidW
$LookupAccountSidWDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UInt32].MakeByRefType(), [IntPtr], [UInt32].MakeByRefType(), [UInt32].MakeByRefType()) ([Bool])
$LookupAccountSidW = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupAccountSidWAddr, $LookupAccountSidWDelegate)
#Struct LUID
$Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
$TypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType], 8)
$TypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null
$TypeBuilder.DefineField('HighPart', [Int32], 'Public') | Out-Null
$LUID = $TypeBuilder.CreateType()
#Struct LUID_AND_ATTRIBUTES
$Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
$TypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType], 12)
$TypeBuilder.DefineField('Luid', $LUID, 'Public') | Out-Null
$TypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null
$LUID_AND_ATTRIBUTES = $TypeBuilder.CreateType()
#Struct SID_AND_ATTRIBUTES
$Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
$TypeBuilder = $ModuleBuilder.DefineType('SID_AND_ATTRIBUTES', $Attributes, [System.ValueType], 16)
$TypeBuilder.DefineField('Sid', [IntPtr], 'Public') | Out-Null
$TypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null
$SID_AND_ATTRIBUTES = $TypeBuilder.CreateType()
#Struct TOKEN_PRIVILEGES
$Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
$TypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType], 16)
$TypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null
$TypeBuilder.DefineField('Privileges', $LUID_AND_ATTRIBUTES, 'Public') | Out-Null
$TOKEN_PRIVILEGES = $TypeBuilder.CreateType()
#Struct TOKEN_GROUPS
$Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
$TypeBuilder = $ModuleBuilder.DefineType('TOKEN_GROUPS', $Attributes, [System.ValueType], 16)
$TypeBuilder.DefineField('GroupCount', [UInt32], 'Public') | Out-Null
$TypeBuilder.DefineField('Groups', $SID_AND_ATTRIBUTES, 'Public') | Out-Null
$TOKEN_GROUPS = $TypeBuilder.CreateType()
#Used to add 64bit memory addresses
Function Add-SignedIntAsUnsigned
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[Int64]
$Value1,
[Parameter(Position = 1, Mandatory = $true)]
[Int64]
$Value2
)
[Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1)
[Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2)
[Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0)
if ($Value1Bytes.Count -eq $Value2Bytes.Count)
{
$CarryOver = 0
for ($i = 0; $i -lt $Value1Bytes.Count; $i++)
{
#Add bytes
[UInt16]$Sum = $Value1Bytes[$i] + $Value2Bytes[$i] + $CarryOver
$FinalBytes[$i] = $Sum -band 0x00FF
if (($Sum -band 0xFF00) -eq 0x100)
{
$CarryOver = 1
}
else
{
$CarryOver = 0
}
}
}
else
{
Throw "Cannot add bytearrays of different sizes"
}
return [BitConverter]::ToInt64($FinalBytes, 0)
}
#this is the account
$accountName = 'mydomain\myaccount'
#this cruft here is so that we get UPN for the WindowsIdentity conscturctor
add-type -AssemblyName System.DirectoryServices.AccountManagement
$pc = new-object System.DirectoryServices.AccountManagement.PrincipalContext Domain,$env:USERDOMAIN
$p = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($pc,$accountName)
#and finally
$wi = new-object System.Security.Principal.WindowsIdentity $p.UserPrincipalName
[UInt32]$TokenPrivilegesSize = 10000
[IntPtr]$TokenPrivilegesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenPrivilegesSize)
[UInt32]$RealSize = 0
$Success = $GetTokenInformation.Invoke($wi.Token, $TOKEN_INFORMATION_CLASS::TokenPrivileges, $TokenPrivilegesPtr, $TokenPrivilegesSize, [Ref]$RealSize)
if (-not $Success)
{
$ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
Write-Warning "GetTokenInformation failed to retrieve Token SessionId. ErrorCode: $ErrorCode"
}
else
{
$TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesPtr, [Type]$TOKEN_PRIVILEGES)
#Loop through each privilege
[IntPtr]$PrivilegesBasePtr = [IntPtr](Add-SignedIntAsUnsigned $TokenPrivilegesPtr ([System.Runtime.InteropServices.Marshal]::OffsetOf([Type]$TOKEN_PRIVILEGES, "Privileges")))
$LuidAndAttributeSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$LUID_AND_ATTRIBUTES)
for ($i = 0; $i -lt $TokenPrivileges.PrivilegeCount; $i++)
{
$LuidAndAttributePtr = [IntPtr](Add-SignedIntAsUnsigned $PrivilegesBasePtr ($LuidAndAttributeSize * $i))
$LuidAndAttribute = [System.Runtime.InteropServices.Marshal]::PtrToStructure($LuidAndAttributePtr, [Type]$LUID_AND_ATTRIBUTES)
#Lookup privilege name
[UInt32]$PrivilegeNameSize = 60
$PrivilegeNamePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PrivilegeNameSize)
$PLuid = $LuidAndAttributePtr #The Luid structure is the first object in the LuidAndAttributes structure, so a ptr to LuidAndAttributes also points to Luid
$Success = $LookupPrivilegeNameW.Invoke([IntPtr]::Zero, $PLuid, $PrivilegeNamePtr, [Ref]$PrivilegeNameSize)
if (-not $Success)
{
$ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
Write-Warning "Call to LookupPrivilegeNameW failed. Error code: $ErrorCode. RealSize: $PrivilegeNameSize"
}
$PrivilegeName = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($PrivilegeNamePtr)
#Get the privilege attributes
$PrivilegeStatus = ""
$Enabled = $false
if ($LuidAndAttribute.Attributes -eq 0)
{
$Enabled = $false
}
if (($LuidAndAttribute.Attributes -band $Win32Constants.SE_PRIVILEGE_ENABLED_BY_DEFAULT) -eq $Win32Constants.SE_PRIVILEGE_ENABLED_BY_DEFAULT) #enabled by default
{
$Enabled = $true
}
if (($LuidAndAttribute.Attributes -band $Win32Constants.SE_PRIVILEGE_ENABLED) -eq $Win32Constants.SE_PRIVILEGE_ENABLED) #enabled
{
$Enabled = $true
}
if (($LuidAndAttribute.Attributes -band $Win32Constants.SE_PRIVILEGE_REMOVED) -eq $Win32Constants.SE_PRIVILEGE_REMOVED) #SE_PRIVILEGE_REMOVED. This should never exist. Write a warning if it is found so I can investigate why/how it was found.
{
Write-Warning "Unexpected behavior: Found a token with SE_PRIVILEGE_REMOVED. Please report this as a bug. "
}
if ($Enabled)
{
$PrivilegeName + "(Enabled)" | Write-Host
}
else
{
$PrivilegeName + "(Available)" | Write-Host
}
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($PrivilegeNamePtr)
}
}
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenPrivilegesPtr)
[UInt32]$TokenGroupsSize = 10000
[IntPtr]$TokenGroupsPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenGroupsSize)
[UInt32]$RealSize = 0
$Success = $GetTokenInformation.Invoke($wi.Token, $TOKEN_INFORMATION_CLASS::TokenGroups, $TokenGroupsPtr, $TokenGroupsSize, [Ref]$RealSize)
if (-not $Success)
{
$ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
Write-Warning "GetTokenInformation failed to retrieve Token SessionId. ErrorCode: $ErrorCode"
}
else
{
$TokenGroups = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenGroupsPtr, [Type]$TOKEN_GROUPS)
#Loop through each privilege
[IntPtr]$GroupsBasePtr = [IntPtr](Add-SignedIntAsUnsigned $TokenGroupsPtr ([System.Runtime.InteropServices.Marshal]::OffsetOf([Type]$TOKEN_GROUPS, "Groups")))
$SidAndAttributeSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$SID_AND_ATTRIBUTES)
for ($i = 0; $i -lt $TokenGroups.GroupCount; $i++)
{
$SidAndAttributePtr = [IntPtr](Add-SignedIntAsUnsigned $GroupsBasePtr ($SidAndAttributeSize * $i))
$SidAndAttribute = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SidAndAttributePtr, [Type]$SID_AND_ATTRIBUTES)
$Sid = $SidAndAttribute.Sid
[UInt32]$Size = 100
[UInt32]$NumUsernameChar = $Size / 2
[UInt32]$NumDomainChar = $Size / 2
[UInt32]$SidNameUse = 0
$UsernameBuffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($Size)
$DomainBuffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($Size)
$Success = $LookupAccountSidW.Invoke([IntPtr]::Zero, $Sid, $UsernameBuffer, [Ref]$NumUsernameChar, $DomainBuffer, [Ref]$NumDomainChar, [Ref]$SidNameUse)
if ($Success)
{
$Username = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($UsernameBuffer)
$Domain = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($DomainBuffer)
}
else
{
$ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
Write-Warning "Error calling LookupAccountSidW. Error code: $ErrorCode"
}
$Domain + "/" + $Username | Write-Host
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($UsernameBuffer)
$UsernameBuffer = [IntPtr]::Zero
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($DomainBuffer)
$DomainBuffer = [IntPtr]::Zero
}
}
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenGroupsPtr)
修改
根据评论我还尝试使用TokenGroupsAndPrivileges令牌信息类,但它似乎列出了没有登录权限的相同权限列表。
答案 0 :(得分:0)
尽管MSDN说的是,令牌不会携带权利信息。为GetTokenInformation
调用TokenGroups
会为您提供帐户所在群组的传递列表。您可以通过在每个群组上调用LsaEnumerateAccountRights来获取权限。
这将有效,因为您拥有所有组。如果您查询的用户的TokenGroups不是直接在您的本地管理员组中,而是在属于您的本地管理员组的组中,您将从GetTokenInformation
调用中收到本地管理员组SID。现在,如果您的本地管理员组拥有本地LSA数据库中的本地登录权限,则会LsaEnumerateAccountRights
返回该权限。
此答案基于评论中链接的Harry Johnston's answer。