[NTOS:SE] Fixes for NT tokens.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 25 Sep 2018 22:51:38 +0000 (00:51 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 27 Sep 2018 22:45:01 +0000 (00:45 +0200)
- 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.

ntoskrnl/include/internal/se.h
ntoskrnl/se/token.c

index 993c6ce..6095bd9 100644 (file)
@@ -314,6 +314,13 @@ SeIsTokenChild(
     OUT PBOOLEAN IsChild
 );
 
+NTSTATUS
+NTAPI
+SeIsTokenSibling(
+    IN PTOKEN Token,
+    OUT PBOOLEAN IsSibling
+);
+
 NTSTATUS
 NTAPI
 SepCreateImpersonationTokenDacl(
index 0b20030..f41ef93 100644 (file)
@@ -717,25 +717,67 @@ SeIsTokenChild(IN PTOKEN Token,
                OUT PBOOLEAN IsChild)
 {
     PTOKEN ProcessToken;
-    LUID ProcessLuid, CallerLuid;
+    LUID ProcessTokenId, CallerParentId;
 
     /* Assume failure */
     *IsChild = FALSE;
 
     /* Reference the process token */
     ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
+    if (!ProcessToken)
+        return STATUS_UNSUCCESSFUL;
 
-    /* Get the ID */
-    ProcessLuid = ProcessToken->AuthenticationId;
+    /* Get its token ID */
+    ProcessTokenId = ProcessToken->TokenId;
 
     /* Dereference the token */
     ObFastDereferenceObject(&PsGetCurrentProcess()->Token, ProcessToken);
 
-    /* Get our LUID */
-    CallerLuid = Token->AuthenticationId;
+    /* Get our parent token ID */
+    CallerParentId = Token->ParentTokenId;
 
-    /* Compare the LUIDs */
-    if (RtlEqualLuid(&CallerLuid, &ProcessLuid)) *IsChild = TRUE;
+    /* Compare the token IDs */
+    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 STATUS_SUCCESS;