Getting wrong SID in the driver

Hi All,

We have a driver that passively sits and listens to file traffic, we send details about the file activity if that interests us. During file detail capturing process, we also get the SID of the thread/process.

For some reason in one our client sites we are getting wrong SIDs, I am not sure why that happens but interestingly we were not able to capture the process information for those events ( PsGetCurrentProcessId() fails). We capture the SID information during the PreRead Callback and finalize the file information during PostRead Callback.

Here is the code that we use, please help!

//-----------------------------------------------------------------------------
// Get the current SID
//-----------------------------------------------------------------------------
NTSTATUS KernelUtil_GetSID(
PSID & sid, // Returned SID
ULONG callerAllocTag // Tag for memory allocation
)
{
sid = NULL;

//
// Try and open the thread token. If that fails, open the process token
// (which always works) and then use the token handle (in either
// case) to query the SID information for the token.
//
HANDLE handle;
NTSTATUS status = ZwOpenThreadToken(NtCurrentThread(), TOKEN_READ, TRUE,
&handle);

if (status == STATUS_NO_TOKEN)
{
//
// Since we don’t have a thread level token we’ll use the process
// level token. This is the common case (in fact) since the only
// time a thread has a token is when it is impersonating.
//

DoTraceMessage(TRACELEVEL_WARNING,“KernelUtil_GetSID() : ZwOpenThreadToken failed” );

status = ZwOpenProcessToken(NtCurrentProcess(), TOKEN_READ, &handle);
}

if (status != STATUS_SUCCESS)
{
DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() : ZwOpenProcessToken failed” );
return status;
}

//
// Retrieve the user information from the token.
//
ULONG length;
PTOKEN_USER pToken = NULL;

status = ZwQueryInformationToken(handle, TokenUser, NULL, 0, &length);

if (status == STATUS_BUFFER_TOO_SMALL)
{
pToken = (PTOKEN_USER)KernelUtil_Alloc(length, AllocTag);

if (pToken == NULL)
{
DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : pToken is NULL” );
ZwClose(handle);
return STATUS_NO_MEMORY;
}

DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : Token Length Needed : %d”, length );

status = ZwQueryInformationToken(handle, TokenUser, pToken, length,
&length);

if ( status != STATUS_SUCCESS )
{
DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() : ZwQueryInformationToken failed to get the SID” );
}
}
else
{
DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() : ZwQueryInformationToken failed to get the length needed” );
}

ZwClose(handle);

if (status != STATUS_SUCCESS || pToken == NULL)
{
if (pToken != NULL)
{
KernelUtil_Free(pToken, AllocTag);
}
return status;
}

if (!RtlValidSid(pToken->User.Sid))
{
DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : SID is not a valid one”);
KernelUtil_Free(pToken, AllocTag);
return STATUS_INVALID_SID;
}

ULONG sidLength = RtlLengthSid(pToken->User.Sid);

DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : SID Length Needed : %d”, sidLength);

sid = KernelUtil_Alloc(sidLength, callerAllocTag);

if (sid == NULL)
{
DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() : not able to allocate memory for SID” );
KernelUtil_Free(pToken, AllocTag);
return STATUS_NO_MEMORY;
}

RtlCopyMemory(sid, pToken->User.Sid, sidLength);

PUCHAR temp = (PUCHAR)KernelUtil_Alloc(sidLength, AllocTag);

if (temp == NULL)
{
DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() : not able to allocate memory for temp” );
}
else
{
// Temporary: Printing the SID info to make sure there is no corruption during the buffer transfer to UserMode
RtlCopyMemory(temp, pToken->User.Sid, sidLength);

for( ULONG i = 0 ; i < sidLength; ++i )
{
DoTraceMessage( TRACELEVEL_VERBOSE, “KernelUtil_GetSID(): SID %d: %02x”, i, temp[i] );
}

KernelUtil_Free(temp, AllocTag);
}

KernelUtil_Free(pToken, AllocTag);
return STATUS_SUCCESS;
}

You cannot do this in the read path. The read can come in on an arbitrary
thread context so the SID you get can be totally bogus. Capture this data
on the file open that is the only safe way to do this.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

wrote in message news:xxxxx@ntfsd…
> Hi All,
>
> We have a driver that passively sits and listens to file traffic, we send
> details about the file activity if that interests us. During file detail
> capturing process, we also get the SID of the thread/process.
>
> For some reason in one our client sites we are getting wrong SIDs, I am
> not sure why that happens but interestingly we were not able to capture
> the process information for those events ( PsGetCurrentProcessId() fails).
> We capture the SID information during the PreRead Callback and finalize
> the file information during PostRead Callback.
>
> Here is the code that we use, please help!
>
> //-----------------------------------------------------------------------------
> // Get the current SID
> //-----------------------------------------------------------------------------
> NTSTATUS KernelUtil_GetSID(
> PSID & sid, // Returned SID
> ULONG callerAllocTag // Tag for memory allocation
> )
> {
> sid = NULL;
>
> //
> // Try and open the thread token. If that fails, open the process token
> // (which always works) and then use the token handle (in either
> // case) to query the SID information for the token.
> //
> HANDLE handle;
> NTSTATUS status = ZwOpenThreadToken(NtCurrentThread(), TOKEN_READ, TRUE,
> &handle);
>
> if (status == STATUS_NO_TOKEN)
> {
> //
> // Since we don’t have a thread level token we’ll use the process
> // level token. This is the common case (in fact) since the only
> // time a thread has a token is when it is impersonating.
> //
>
> DoTraceMessage(TRACELEVEL_WARNING,“KernelUtil_GetSID() :
> ZwOpenThreadToken failed” );
>
> status = ZwOpenProcessToken(NtCurrentProcess(), TOKEN_READ, &handle);
> }
>
> if (status != STATUS_SUCCESS)
> {
> DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() :
> ZwOpenProcessToken failed” );
> return status;
> }
>
> //
> // Retrieve the user information from the token.
> //
> ULONG length;
> PTOKEN_USER pToken = NULL;
>
> status = ZwQueryInformationToken(handle, TokenUser, NULL, 0, &length);
>
> if (status == STATUS_BUFFER_TOO_SMALL)
> {
> pToken = (PTOKEN_USER)KernelUtil_Alloc(length, AllocTag);
>
> if (pToken == NULL)
> {
> DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : pToken is
> NULL” );
> ZwClose(handle);
> return STATUS_NO_MEMORY;
> }
>
> DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : Token Length
> Needed : %d”, length );
>
> status = ZwQueryInformationToken(handle, TokenUser, pToken, length,
> &length);
>
> if ( status != STATUS_SUCCESS )
> {
> DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() :
> ZwQueryInformationToken failed to get the SID” );
> }
> }
> else
> {
> DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() :
> ZwQueryInformationToken failed to get the length needed” );
> }
>
>
> ZwClose(handle);
>
> if (status != STATUS_SUCCESS || pToken == NULL)
> {
> if (pToken != NULL)
> {
> KernelUtil_Free(pToken, AllocTag);
> }
> return status;
> }
>
> if (!RtlValidSid(pToken->User.Sid))
> {
> DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : SID is not a
> valid one”);
> KernelUtil_Free(pToken, AllocTag);
> return STATUS_INVALID_SID;
> }
>
> ULONG sidLength = RtlLengthSid(pToken->User.Sid);
>
> DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : SID Length
> Needed : %d”, sidLength);
>
> sid = KernelUtil_Alloc(sidLength, callerAllocTag);
>
> if (sid == NULL)
> {
> DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() : not able to
> allocate memory for SID” );
> KernelUtil_Free(pToken, AllocTag);
> return STATUS_NO_MEMORY;
> }
>
> RtlCopyMemory(sid, pToken->User.Sid, sidLength);
>
> PUCHAR temp = (PUCHAR)KernelUtil_Alloc(sidLength, AllocTag);
>
> if (temp == NULL)
> {
> DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() : not able to
> allocate memory for temp” );
> }
> else
> {
> // Temporary: Printing the SID info to make sure there is no corruption
> during the buffer transfer to UserMode
> RtlCopyMemory(temp, pToken->User.Sid, sidLength);
>
> for( ULONG i = 0 ; i < sidLength; ++i )
> {
> DoTraceMessage( TRACELEVEL_VERBOSE, “KernelUtil_GetSID(): SID %d:
> %02x”, i, temp[i] );
> }
>
> KernelUtil_Free(temp, AllocTag);
> }
>
>
> KernelUtil_Free(pToken, AllocTag);
> return STATUS_SUCCESS;
> }
>
>
>
>

You should get the SID in MJ_CREATE only.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntfsd…
> Hi All,
>
> We have a driver that passively sits and listens to file traffic, we send
details about the file activity if that interests us. During file detail
capturing process, we also get the SID of the thread/process.
>
> For some reason in one our client sites we are getting wrong SIDs, I am not
sure why that happens but interestingly we were not able to capture the process
information for those events ( PsGetCurrentProcessId() fails). We capture the
SID information during the PreRead Callback and finalize the file information
during PostRead Callback.
>
> Here is the code that we use, please help!
>
>
//-----------------------------------------------------------------------------
> // Get the current SID
>
//-----------------------------------------------------------------------------
> NTSTATUS KernelUtil_GetSID(
> PSID & sid, // Returned SID
> ULONG callerAllocTag // Tag for memory allocation
> )
> {
> sid = NULL;
>
> //
> // Try and open the thread token. If that fails, open the process token
> // (which always works) and then use the token handle (in either
> // case) to query the SID information for the token.
> //
> HANDLE handle;
> NTSTATUS status = ZwOpenThreadToken(NtCurrentThread(), TOKEN_READ, TRUE,
> &handle);
>
> if (status == STATUS_NO_TOKEN)
> {
> //
> // Since we don’t have a thread level token we’ll use the process
> // level token. This is the common case (in fact) since the only
> // time a thread has a token is when it is impersonating.
> //
>
> DoTraceMessage(TRACELEVEL_WARNING,“KernelUtil_GetSID() : ZwOpenThreadToken
failed” );
>
> status = ZwOpenProcessToken(NtCurrentProcess(), TOKEN_READ, &handle);
> }
>
> if (status != STATUS_SUCCESS)
> {
> DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() : ZwOpenProcessToken
failed” );
> return status;
> }
>
> //
> // Retrieve the user information from the token.
> //
> ULONG length;
> PTOKEN_USER pToken = NULL;
>
> status = ZwQueryInformationToken(handle, TokenUser, NULL, 0, &length);
>
> if (status == STATUS_BUFFER_TOO_SMALL)
> {
> pToken = (PTOKEN_USER)KernelUtil_Alloc(length, AllocTag);
>
> if (pToken == NULL)
> {
> DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : pToken is NULL” );
> ZwClose(handle);
> return STATUS_NO_MEMORY;
> }
>
> DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : Token Length
Needed : %d”, length );
>
> status = ZwQueryInformationToken(handle, TokenUser, pToken, length,
> &length);
>
> if ( status != STATUS_SUCCESS )
> {
> DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() :
ZwQueryInformationToken failed to get the SID” );
> }
> }
> else
> {
> DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() :
ZwQueryInformationToken failed to get the length needed” );
> }
>
>
> ZwClose(handle);
>
> if (status != STATUS_SUCCESS || pToken == NULL)
> {
> if (pToken != NULL)
> {
> KernelUtil_Free(pToken, AllocTag);
> }
> return status;
> }
>
> if (!RtlValidSid(pToken->User.Sid))
> {
> DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : SID is not a valid
one”);
> KernelUtil_Free(pToken, AllocTag);
> return STATUS_INVALID_SID;
> }
>
> ULONG sidLength = RtlLengthSid(pToken->User.Sid);
>
> DoTraceMessage(TRACELEVEL_VERBOSE,“KernelUtil_GetSID() : SID Length Needed
: %d”, sidLength);
>
> sid = KernelUtil_Alloc(sidLength, callerAllocTag);
>
> if (sid == NULL)
> {
> DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() : not able to allocate
memory for SID” );
> KernelUtil_Free(pToken, AllocTag);
> return STATUS_NO_MEMORY;
> }
>
> RtlCopyMemory(sid, pToken->User.Sid, sidLength);
>
> PUCHAR temp = (PUCHAR)KernelUtil_Alloc(sidLength, AllocTag);
>
> if (temp == NULL)
> {
> DoTraceMessage(TRACELEVEL_ERROR,“KernelUtil_GetSID() : not able to allocate
memory for temp” );
> }
> else
> {
> // Temporary: Printing the SID info to make sure there is no corruption
during the buffer transfer to UserMode
> RtlCopyMemory(temp, pToken->User.Sid, sidLength);
>
> for( ULONG i = 0 ; i < sidLength; ++i )
> {
> DoTraceMessage( TRACELEVEL_VERBOSE, “KernelUtil_GetSID(): SID %d: %02x”,
i, temp[i] );
> }
>
> KernelUtil_Free(temp, AllocTag);
> }
>
>
> KernelUtil_Free(pToken, AllocTag);
> return STATUS_SUCCESS;
> }
>
>
>
>