From 9d2de519b2d2781f3a2bddb54cb4a2bfdbb969a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George=20Bi=C8=99oc?= Date: Sun, 19 Jun 2022 12:39:23 +0200 Subject: [PATCH] [NTOS:SE] NtQueryInformationToken: implement TokenGroupsAndPrivileges TokenGroupsAndPrivileges is the younger sister of two TokenGroups and TokenPrivileges classes. In its purpose there's no huge substantial differences apart that this class comes with its own structure, TOKEN_GROUPS_AND_PRIVILEGES, and that this structure comes with extra information. --- ntoskrnl/se/tokencls.c | 78 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/ntoskrnl/se/tokencls.c b/ntoskrnl/se/tokencls.c index 24adad4f61c..8bb5598ce9e 100644 --- a/ntoskrnl/se/tokencls.c +++ b/ntoskrnl/se/tokencls.c @@ -905,9 +905,83 @@ NtQueryInformationToken( } case TokenGroupsAndPrivileges: - DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; + { + PSID Sid, RestrictedSid; + ULONG SidLen, RestrictedSidLen; + ULONG UserGroupLength, RestrictedSidLength, PrivilegeLength; + PTOKEN_GROUPS_AND_PRIVILEGES GroupsAndPrivs = (PTOKEN_GROUPS_AND_PRIVILEGES)TokenInformation; + + DPRINT("NtQueryInformationToken(TokenGroupsAndPrivileges)\n"); + UserGroupLength = RtlLengthSidAndAttributes(Token->UserAndGroupCount, Token->UserAndGroups); + RestrictedSidLength = RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids); + PrivilegeLength = Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES); + + RequiredLength = sizeof(TOKEN_GROUPS_AND_PRIVILEGES) + + UserGroupLength + RestrictedSidLength + PrivilegeLength; + + _SEH2_TRY + { + if (TokenInformationLength >= RequiredLength) + { + GroupsAndPrivs->SidCount = Token->UserAndGroupCount; + GroupsAndPrivs->SidLength = UserGroupLength; + GroupsAndPrivs->Sids = (PSID_AND_ATTRIBUTES)(GroupsAndPrivs + 1); + + Sid = (PSID)((ULONG_PTR)GroupsAndPrivs->Sids + (Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES))); + SidLen = UserGroupLength - (Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES)); + Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount, + Token->UserAndGroups, + SidLen, + GroupsAndPrivs->Sids, + Sid, + &Unused.PSid, + &Unused.Ulong); + NT_ASSERT(NT_SUCCESS(Status)); + + GroupsAndPrivs->RestrictedSidCount = Token->RestrictedSidCount; + GroupsAndPrivs->RestrictedSidLength = RestrictedSidLength; + GroupsAndPrivs->RestrictedSids = NULL; + if (SeTokenIsRestricted(Token)) + { + GroupsAndPrivs->RestrictedSids = (PSID_AND_ATTRIBUTES)((ULONG_PTR)GroupsAndPrivs->Sids + UserGroupLength); + + RestrictedSid = (PSID)((ULONG_PTR)GroupsAndPrivs->RestrictedSids + (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES))); + RestrictedSidLen = RestrictedSidLength - (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)); + Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount, + Token->RestrictedSids, + RestrictedSidLen, + GroupsAndPrivs->RestrictedSids, + RestrictedSid, + &Unused.PSid, + &Unused.Ulong); + NT_ASSERT(NT_SUCCESS(Status)); + } + + GroupsAndPrivs->PrivilegeCount = Token->PrivilegeCount; + GroupsAndPrivs->PrivilegeLength = PrivilegeLength; + GroupsAndPrivs->Privileges = (PLUID_AND_ATTRIBUTES)((ULONG_PTR)(GroupsAndPrivs + 1) + + UserGroupLength + RestrictedSidLength); + RtlCopyLuidAndAttributesArray(Token->PrivilegeCount, + Token->Privileges, + GroupsAndPrivs->Privileges); + + GroupsAndPrivs->AuthenticationId = Token->AuthenticationId; + } + else + { + Status = STATUS_BUFFER_TOO_SMALL; + } + + *ReturnLength = RequiredLength; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + break; + } case TokenRestrictedSids: {