[NTOS:SE] Fixes for NT tokens.

- SeIsTokenChild(): Correctly check whether a caller-provided token
  is a child from the current process' primary token by looking at
  its ParentTokenId member.

- Add a SeIsTokenSibling() helper to determine whether a caller-provided
  token and the current process' primary token are siblings, by comparing
  their ParentTokenId's and AuthenticationId's.

NOTE: Children tokens are created through CreateRestrictedToken();
sibling tokens are created through DuplicateToken() (amongst others).

See slide 49 of https://www.slideshare.net/Shakacon/social-engineering-the-windows-kernel-by-james-forshaw
or https://googleprojectzero.blogspot.com/2016/01/raising-dead.html
for some details.
This commit is contained in:
Hermès Bélusca-Maïto 2018-09-26 00:51:38 +02:00
parent 3caab66e22
commit 7f9282927b
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
2 changed files with 56 additions and 7 deletions

View file

@ -314,6 +314,13 @@ SeIsTokenChild(
OUT PBOOLEAN IsChild OUT PBOOLEAN IsChild
); );
NTSTATUS
NTAPI
SeIsTokenSibling(
IN PTOKEN Token,
OUT PBOOLEAN IsSibling
);
NTSTATUS NTSTATUS
NTAPI NTAPI
SepCreateImpersonationTokenDacl( SepCreateImpersonationTokenDacl(

View file

@ -717,25 +717,67 @@ SeIsTokenChild(IN PTOKEN Token,
OUT PBOOLEAN IsChild) OUT PBOOLEAN IsChild)
{ {
PTOKEN ProcessToken; PTOKEN ProcessToken;
LUID ProcessLuid, CallerLuid; LUID ProcessTokenId, CallerParentId;
/* Assume failure */ /* Assume failure */
*IsChild = FALSE; *IsChild = FALSE;
/* Reference the process token */ /* Reference the process token */
ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess()); ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
if (!ProcessToken)
return STATUS_UNSUCCESSFUL;
/* Get the ID */ /* Get its token ID */
ProcessLuid = ProcessToken->AuthenticationId; ProcessTokenId = ProcessToken->TokenId;
/* Dereference the token */ /* Dereference the token */
ObFastDereferenceObject(&PsGetCurrentProcess()->Token, ProcessToken); ObFastDereferenceObject(&PsGetCurrentProcess()->Token, ProcessToken);
/* Get our LUID */ /* Get our parent token ID */
CallerLuid = Token->AuthenticationId; CallerParentId = Token->ParentTokenId;
/* Compare the LUIDs */ /* Compare the token IDs */
if (RtlEqualLuid(&CallerLuid, &ProcessLuid)) *IsChild = TRUE; if (RtlEqualLuid(&CallerParentId, &ProcessTokenId))
*IsChild = TRUE;
/* Return success */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
SeIsTokenSibling(IN PTOKEN Token,
OUT PBOOLEAN IsSibling)
{
PTOKEN ProcessToken;
LUID ProcessParentId, ProcessAuthId;
LUID CallerParentId, CallerAuthId;
/* Assume failure */
*IsSibling = FALSE;
/* Reference the process token */
ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
if (!ProcessToken)
return STATUS_UNSUCCESSFUL;
/* Get its parent and authentication IDs */
ProcessParentId = ProcessToken->ParentTokenId;
ProcessAuthId = ProcessToken->AuthenticationId;
/* Dereference the token */
ObFastDereferenceObject(&PsGetCurrentProcess()->Token, ProcessToken);
/* Get our parent and authentication IDs */
CallerParentId = Token->ParentTokenId;
CallerAuthId = Token->AuthenticationId;
/* Compare the token IDs */
if (RtlEqualLuid(&CallerParentId, &ProcessParentId) &&
RtlEqualLuid(&CallerAuthId, &ProcessAuthId))
{
*IsSibling = TRUE;
}
/* Return success */ /* Return success */
return STATUS_SUCCESS; return STATUS_SUCCESS;