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;
}