File Minifilter part 2: How to get SID and User name for I/O requests in File minifilter

Getting user name associated with the current I/O request can be obtained as shown below.

First of all we need a TOKEN_USER object from the PFLT_CALLBACK_DATA object.
There are two methods to achieve this.

A) From current thread(if impersonation is used) or process token

TOKEN_USER* TokenUser;
use ZwOpenThreadTokenEx() to get token handle.
HANDLE token;
if ((status=ZwOpenThreadTokenEx(NtCurrentThread(), GENERIC_READ, TRUE,OBJ_KERNEL_HANDLE , &token)) != STATUS_SUCCESS)
status=ZwOpenProcessTokenEx(NtCurrentProcess(), GENERIC_READ, OBJ_KERNEL_HANDLE,&token);

Get TokenUser from this token handle

ZwQueryInformationToken(token, TokenUser, NULL, 0, &len); //to get required length
if (!(*ppUser=ExAllocatePoolWithTag(NonPagedPool, len, 'ofni'))) //tagged memory allocation
if ((status=ZwQueryInformationToken(token, TokenUser, *ppUser, len, &len)) != STATUS_SUCCESS)
ExFreePoolWithTag(*ppUser, 'nacS');

B) From subject context present in the callback object

PFLT_CALLBACK_DATA Data; //passed from file filter module as parameter to callbacks
TOKEN_USER **ppUser; // token user to be used to extract SID
PACCESS_TOKEN pToken = SeQuerySubjectContextToken(&(Data->Iopb->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext));
*ppUser = NULL;
status = SeQueryInformationToken(pToken,TokenUser,ppUser);

Once TOKEN_USER structure is filled; following code can be used to generate a valid SID

TOKEN _USER* pUser; //it is the TOKEN_USER filled from one of the above mentioned methods

unsigned long dwStrSidSize=0;
SID* sid = (SID*)pUser->User.Sid;
dwStrSidSize = sprintf(strSID,"S-%u-",sid->Revision);
IdAuth = (sid->IdentifierAuthority.Value[5]) + (sid->IdentifierAuthority.Value[4] << 8 ) + (sid->IdentifierAuthority.Value[3] << 16) + (sid->IdentifierAuthority.Value[2] << 24);
dwStrSidSize += sprintf(strSID+strlen(strSID),"%u",IdAuth);
if (sid->SubAuthorityCount)
for (index = 0; index < sid->SubAuthorityCount;index++)
dwStrSidSize += sprintf(strSID+dwStrSidSize,"-%u",sid->SubAuthority[index]);

At the end free the allocated TOKEN USER as follows

ExFreePoolWithTag(pUser, 'ofni');

This way SID string can be achieved for current I/O request. This string can be cached (using SCANNER_STREAM_HANDLE_CONTEXT; will write about it in some other post) to be used in all the callbacks related to current I/O request.

This SID string can be passed to user mode code where user name, domain name, domain groups and other associated information can be retrieved.
For example:
use ConvertStringSidToSid to get SID structure.
LookupAccountSid can be used to retrieve account name of the user from this SID structure.

Explore posts in the same categories: Programming

Tags: ,

You can comment below, or link to this permanent URL from your own site.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: