Question about SIDs and PSIDs

In our quest to get the user’s sid from an IRP we used the following:

  1. Accessed the structure directly:
    pIrpStack->Parameters.Create.SecurityContext->AccessState->SubjectSecurityCo
    ntext
  2. Used SeQuerySubjectContextToken() on the SubjectSecurityContext to obtain
    the Token.
  3. Used SeQueryInformationToken() on the token to get the TOKEN_USER;
  4. Since there are no functions to manipulate this structure, we accessed it
    directly: tokenUser.User, which is a SID_AND_ATTRIBUTES struct, and finally,
    tokenUser.User.Sid which is a PSID.

Then we used RtlValidSid() to verify the sid, and, guess what, it’s INVALID!

However, while trying to figure out what we had done wrong (and completly by
accident) we tried to dereference the PSID twice in the debugger, and it
worked. In c, this would be:

PSID p;
(…)
p=tokenUser.User.Sid;

// Instead of using RtlValidSid(p), we used
RtlValidSid( (PSID)*(unsigned long *)p ) // and it worked!

What is the meaning of this? Is the tokenUser.User.Sid in fact a PSID*
instead of a PSID?
Are we doing something wrong? This is a VERY irregular way to use a PSID.

Has anyone managed to use a PSID in kernel mode as it was intended (without
having to derreference it twice)?
ANY thoughts are welcome.


You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com

You didn’t post the code that called ZwQueryInformationToken. In any
case you have to set the User.Sid to valid buffer pointer and length
parameter has to indicate sufficient length for SID. You have to check
for NTSTATUS also. If it says STATUS_BUFFER_TOO_SMALL try again.
Try this

len = 512;
buf = alloc(len);
user = (PTOKEN_USER)buf;
buf += sizeof (SID_AND_ATTRIBUTES);
len -= sizeof (SID_AND_ATTRIBUTES);
user->User.Sid = buf;
stat = ZwQueryInformationToken(token_handle, TokenUser, user, len,
&nbytes);

— “Paulo Valerio, Ricardo Ramalho” wrote:
> In our quest to get the user’s sid from an IRP we used the following:
>
> 1. Accessed the structure directly:
>
pIrpStack->Parameters.Create.SecurityContext->AccessState->SubjectSecurityCo
> ntext
> 2. Used SeQuerySubjectContextToken() on the SubjectSecurityContext to
> obtain
> the Token.
> 3. Used SeQueryInformationToken() on the token to get the TOKEN_USER;
> 4. Since there are no functions to manipulate this structure, we
> accessed it
> directly: tokenUser.User, which is a SID_AND_ATTRIBUTES struct, and
> finally,
> tokenUser.User.Sid which is a PSID.
>
> Then we used RtlValidSid() to verify the sid, and, guess what, it’s
> INVALID!
>
> However, while trying to figure out what we had done wrong (and
> completly by
> accident) we tried to dereference the PSID twice in the debugger, and
> it
> worked. In c, this would be:
>
> PSID p;
> (…)
> p=tokenUser.User.Sid;
>
> // Instead of using RtlValidSid(p), we used
> RtlValidSid( (PSID)*(unsigned long )p ) // and it worked!
>
> What is the meaning of this? Is the tokenUser.User.Sid in fact a
> PSID

> instead of a PSID?
> Are we doing something wrong? This is a VERY irregular way to use a
> PSID.
>
> Has anyone managed to use a PSID in kernel mode as it was intended
> (without
> having to derreference it twice)?
> ANY thoughts are welcome.
>
>
> —
> You are currently subscribed to ntfsd as: xxxxx@yahoo.com
> To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com

__________________________________________________
Do You Yahoo!?
Get email at your own domain with Yahoo! Mail.
http://personal.mail.yahoo.com/


You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com

> You didn’t post the code that called ZwQueryInformationToken. In any
(…)

That function is not documented on the DDK or on the IFS kit. That’s why i
used SeQueryInformationToken() - i didn’t know ZwQueryInformationToken even
existed;
Here’s the code i used:

PSID GetUserSID(PIO_STACK_LOCATION pIrpStack){

NTSTATUS stat;
PSID pSid;
TOKEN_USER t;
PACCESS_TOKEN pToken;

pToken =
SeQuerySubjectContextToken(&(pIrpStack->Parameters.Create.SecurityContext->A
ccessState->SubjectSecurityContext));

if(pToken == NULL){
DbgPrint(“(GetUserSid) No Access Token\n”);
return NULL;
}

stat=SeQueryInformationToken(pToken,TokenUser, (void *)&t);

pSid = (PSID)*(unsigned long *) t.User.Sid; // Unless i do this, the
t.User.Sid doesn’t work.

if (NT_SUCCESS(stat)) {
DbgPrint(“(GetUserSid) Got Sid\n”);
return pSid;
}

DbgPrint(“(GetUserSid) No Sid?\n”);
return NULL;
};

And it works fine, if i do the double pointer derreference thing - which i
shouldn’t.

case you have to set the User.Sid to valid buffer pointer and length
parameter has to indicate sufficient length for SID. You have to check
for NTSTATUS also. If it says STATUS_BUFFER_TOO_SMALL try again.
Try this

len = 512;
buf = alloc(len);
user = (PTOKEN_USER)buf;
buf += sizeof (SID_AND_ATTRIBUTES);
len -= sizeof (SID_AND_ATTRIBUTES);
user->User.Sid = buf;
stat = ZwQueryInformationToken(token_handle, TokenUser, user, len,
&nbytes);

— “Paulo Valerio, Ricardo Ramalho” wrote:
> > In our quest to get the user’s sid from an IRP we used the following:
> >
> > 1. Accessed the structure directly:
> >
>
pIrpStack->Parameters.Create.SecurityContext->AccessState->SubjectSecurityCo
> > ntext
> > 2. Used SeQuerySubjectContextToken() on the SubjectSecurityContext to
> > obtain
> > the Token.
> > 3. Used SeQueryInformationToken() on the token to get the TOKEN_USER;
> > 4. Since there are no functions to manipulate this structure, we
> > accessed it
> > directly: tokenUser.User, which is a SID_AND_ATTRIBUTES struct, and
> > finally,
> > tokenUser.User.Sid which is a PSID.
> >
> > Then we used RtlValidSid() to verify the sid, and, guess what, it’s
> > INVALID!
> >
> > However, while trying to figure out what we had done wrong (and
> > completly by
> > accident) we tried to dereference the PSID twice in the debugger, and
> > it
> > worked. In c, this would be:
> >
> > PSID p;
> > (…)
> > p=tokenUser.User.Sid;
> >
> > // Instead of using RtlValidSid(p), we used
> > RtlValidSid( (PSID)*(unsigned long )p ) // and it worked!
> >
> > What is the meaning of this? Is the tokenUser.User.Sid in fact a
> > PSID

> > instead of a PSID?
> > Are we doing something wrong? This is a VERY irregular way to use a
> > PSID.
> >
> > Has anyone managed to use a PSID in kernel mode as it was intended
> > (without
> > having to derreference it twice)?
> > ANY thoughts are welcome.


You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com

> stat=SeQueryInformationToken(pToken,TokenUser, (void *)&t);

pSid = (PSID)*(unsigned long *) t.User.Sid; // Unless i do this, the
t.User.Sid doesn’t work.

if (NT_SUCCESS(stat)) {
DbgPrint(“(GetUserSid) Got Sid\n”);
return pSid;
}

DbgPrint(“(GetUserSid) No Sid?\n”);
return NULL;
};

And it works fine, if i do the double pointer derreference
thing - which i shouldn’t.

Yes, you should because it returns the void pointer. (See the function
prototype in ntifs.h or the IFS kit doc.) What is not documented in the IFS
kit is that you must call ExFreePool() after you are done with the token.
Otherwise, it causes the memory leak.
So, in your case, you should be doing:

PTOKEN_USER t_p;
:
:
stat=SeQueryInformationToken(pToken,TokenUser, (void *)&t_p);
// And check the returned status, here!!!
:
:
ExFreePool(t_p);

— Seiichi


You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com