📄 token.c
字号:
GENERIC_MAPPING GenericMapping =
{
STANDARD_RIGHTS_READ,
STANDARD_RIGHTS_WRITE,
STANDARD_RIGHTS_EXECUTE,
STANDARD_RIGHTS_ALL
};
PACL Dacl;
ULONG SidLen;
HANDLE hToken = NULL;
NTSTATUS Status, AccessStatus;
/* doesn't return gracefully if IsMember is NULL! */
*IsMember = FALSE;
SidLen = RtlLengthSid(SidToCheck);
if (ExistingTokenHandle == NULL)
{
Status = NtOpenThreadToken(NtCurrentThread(),
TOKEN_QUERY,
FALSE,
&hToken);
if (Status == STATUS_NO_TOKEN)
{
/* we're not impersonating, open the primary token */
Status = NtOpenProcessToken(NtCurrentProcess(),
TOKEN_QUERY | TOKEN_DUPLICATE,
&hToken);
if (NT_SUCCESS(Status))
{
HANDLE hNewToken = FALSE;
BOOL DupRet;
/* duplicate the primary token to create an impersonation token */
DupRet = DuplicateTokenEx(hToken,
TOKEN_QUERY | TOKEN_IMPERSONATE,
NULL,
SecurityImpersonation,
TokenImpersonation,
&hNewToken);
NtClose(hToken);
if (!DupRet)
{
DPRINT1("Failed to duplicate the primary token!\n");
return FALSE;
}
hToken = hNewToken;
}
}
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
}
else
{
hToken = ExistingTokenHandle;
}
/* create a security descriptor */
SecurityDescriptor = RtlAllocateHeap(RtlGetProcessHeap(),
0,
sizeof(SECURITY_DESCRIPTOR) +
sizeof(ACL) + SidLen +
sizeof(ACCESS_ALLOWED_ACE));
if (SecurityDescriptor == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
/* set the owner and group */
Status = RtlSetOwnerSecurityDescriptor(SecurityDescriptor,
SidToCheck,
FALSE);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
Status = RtlSetGroupSecurityDescriptor(SecurityDescriptor,
SidToCheck,
FALSE);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
/* create the DACL */
Dacl = (PACL)(SecurityDescriptor + 1);
Status = RtlCreateAcl(Dacl,
sizeof(ACL) + SidLen + sizeof(ACCESS_ALLOWED_ACE),
ACL_REVISION);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
Status = RtlAddAccessAllowedAce(Dacl,
ACL_REVISION,
0x1,
SidToCheck);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
/* assign the DACL to the security descriptor */
Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
TRUE,
Dacl,
FALSE);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
/* it's time to perform the access check. Just use _some_ desired access right
(same as for the ACE) and see if we're getting it granted. This indicates
our SID is a member of the token. We however can't use a generic access
right as those aren't mapped and return an error (STATUS_GENERIC_NOT_MAPPED). */
Status = NtAccessCheck(SecurityDescriptor,
hToken,
0x1,
&GenericMapping,
&PrivBuffer.PrivilegeSet,
&PrivBufferSize,
&GrantedAccess,
&AccessStatus);
if (NT_SUCCESS(Status) && NT_SUCCESS(AccessStatus) && (GrantedAccess == 0x1))
{
*IsMember = TRUE;
}
Cleanup:
if (hToken != NULL && hToken != ExistingTokenHandle)
{
NtClose(hToken);
}
if (SecurityDescriptor != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(),
0,
SecurityDescriptor);
}
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
BOOL STDCALL
IsTokenRestricted(HANDLE TokenHandle)
{
ULONG RetLength;
PTOKEN_GROUPS lpGroups;
NTSTATUS Status;
BOOL Ret = FALSE;
/* determine the required buffer size and allocate enough memory to read the
list of restricted SIDs */
Status = NtQueryInformationToken(TokenHandle,
TokenRestrictedSids,
NULL,
0,
&RetLength);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
AllocAndReadRestrictedSids:
lpGroups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),
0,
RetLength);
if (lpGroups == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
/* actually read the list of the restricted SIDs */
Status = NtQueryInformationToken(TokenHandle,
TokenRestrictedSids,
lpGroups,
RetLength,
&RetLength);
if (NT_SUCCESS(Status))
{
Ret = (lpGroups->GroupCount != 0);
}
else if (Status == STATUS_BUFFER_TOO_SMALL)
{
/* looks like the token was modified in the meanwhile, let's just try again */
HeapFree(GetProcessHeap(),
0,
lpGroups);
goto AllocAndReadRestrictedSids;
}
else
{
SetLastError(RtlNtStatusToDosError(Status));
}
/* free allocated memory */
HeapFree(GetProcessHeap(),
0,
lpGroups);
return Ret;
}
BOOL STDCALL
CreateRestrictedToken(
HANDLE TokenHandle,
DWORD Flags,
DWORD DisableSidCount,
PSID_AND_ATTRIBUTES pSidAndAttributes,
DWORD DeletePrivilegeCount,
PLUID_AND_ATTRIBUTES pLUIDAndAttributes,
DWORD RestrictedSidCount,
PSID_AND_ATTRIBUTES pSIDAndAttributes,
PHANDLE NewTokenHandle
)
{
FIXME("unimplemented!\n", __FUNCTION__);
return FALSE;
}
/*
* @unimplemented
*/
PSID
WINAPI
GetSiteSidFromToken(IN HANDLE TokenHandle)
{
PTOKEN_GROUPS RestrictedSids;
ULONG RetLen;
UINT i;
NTSTATUS Status;
PSID PSiteSid = NULL;
SID_IDENTIFIER_AUTHORITY InternetSiteAuthority = {SECURITY_INTERNETSITE_AUTHORITY};
Status = NtQueryInformationToken(TokenHandle,
TokenRestrictedSids,
NULL,
0,
&RetLen);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
SetLastError(RtlNtStatusToDosError(Status));
return NULL;
}
RestrictedSids = (PTOKEN_GROUPS)RtlAllocateHeap(RtlGetProcessHeap(),
0,
RetLen);
if (RestrictedSids == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
Status = NtQueryInformationToken(TokenHandle,
TokenRestrictedSids,
RestrictedSids,
RetLen,
&RetLen);
if (NT_SUCCESS(Status))
{
for (i = 0; i < RestrictedSids->GroupCount; i++)
{
SID* RSSid = RestrictedSids->Groups[i].Sid;
if (RtlCompareMemory(&(RSSid->IdentifierAuthority),
&InternetSiteAuthority,
sizeof(SID_IDENTIFIER_AUTHORITY)) ==
sizeof(SID_IDENTIFIER_AUTHORITY))
{
PSiteSid = RtlAllocateHeap(RtlGetProcessHeap(),
0,
RtlLengthSid((RestrictedSids->
Groups[i]).Sid));
if (PSiteSid == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
}
else
{
RtlCopySid(RtlLengthSid(RestrictedSids->Groups[i].Sid),
PSiteSid,
RestrictedSids->Groups[i].Sid);
}
break;
}
}
}
else
{
SetLastError(RtlNtStatusToDosError(Status));
}
RtlFreeHeap(RtlGetProcessHeap(), 0, RestrictedSids);
return PSiteSid;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -