ObOpenObjectByPointer causing crash while extracting WTS ID(Session ID) from process ID

I am extracting the WTS ID from process ID but sometimes getting crash due to ObOpenObjectByPointer API

Code :

BOOLEAN GetSessionIdOfProcess(UINT64 dwPid, UINT32* sessionId)
{
	HANDLE hprocess, htoken;
	NTSTATUS status;
	OBJECT_ATTRIBUTES objectAttributes;
	CLIENT_ID myCid;
	PEPROCESS eProcess;
	InitializeObjectAttributes(&objectAttributes, 0, 0, 0, 0);

	myCid.UniqueProcess = (HANDLE)dwPid;
	myCid.UniqueThread = 0;
	BOOLEAN result = FALSE;
	//Open the process and get the handle
	status = ZwOpenProcess(&hprocess, PROCESS_ALL_ACCESS, &objectAttributes, &myCid);
	if (!NT_SUCCESS(status))
	{
		DbgPrintEx(DPFLTR_NDE_MASK, DPFLTR_NDE_ERROR_LEVEL, "Error occured while accessing the process handle for PID : %llu , error code : %x\r\n", dwPid, status);
		goto Exit;
	}

	//Get EPROCESS from the process handle
	status = ObReferenceObjectByHandle(hprocess, FILE_READ_DATA, 0, KernelMode, &eProcess, 0);
	if (!NT_SUCCESS(status) || eProcess == NULL)
	{
		DbgPrintEx(DPFLTR_NDE_MASK, DPFLTR_NDE_ERROR_LEVEL, "Error occured while accessing the EPROCESS structure for PID : %llu , error code : %x\r\n", dwPid, status);
	}
	else
	{
		// Get Process token from the EPROCESS
		PVOID token = PsReferencePrimaryToken(eProcess);

		if (token)
		{
			// Now that we have a token reference, get a handle to it
			// so that we can query it.
			status = ObOpenObjectByPointer(token, 0, NULL, TOKEN_QUERY, NULL, KernelMode, &htoken);
			if (!NT_SUCCESS(status))
			{
				DbgPrintEx(DPFLTR_NDE_MASK, DPFLTR_NDE_ERROR_LEVEL, "Error occured while accessing the token handle for PID : %llu , error code : %x\r\n", dwPid, status);
			}
			else
			{
				ULONG retLen = 0;
				ZwQueryInformationToken(htoken, TokenSessionId, sessionId, sizeof(UINT32), &retLen);
				DbgPrintEx(DPFLTR_NDE_MASK, DPFLTR_NDE_DEBUG_LEVEL, "Extracted information, PID : %llu WTS ID : %d\r\n", dwPid, *sessionId);
				result = TRUE;
				ZwClose(htoken);
			}
			ObDereferenceObject(token);
		}
		else
		{
			DbgPrintEx(DPFLTR_NDE_MASK, DPFLTR_NDE_ERROR_LEVEL, "Token value for PID : %llu is NULL\r\n", dwPid);
		}
		ObDereferenceObject(eProcess);
	}	
	ZwClose(hprocess);

Exit:
	return result;
}

Error Data :-

fffffb88706ce4c8 fffff8072d409b69 : 000000000000000a ffffad841e8ff018 0000000000000002 0000000000000000 : nt+0x3f6b90
fffffb88706ce4d0 fffff8072d405e69 : fffffb88706ceaf0 fffffb88706ce8a8 0000000000000000 0000000000000000 : nt+0x408b69
fffffb88706ce610 fffff8072d5f765b : 0000000000000000 fffffb8800000000 0000000000000000 ffffad8413e59030 : nt+0x404e69
fffffb88706ce7a0 fffff8072d6d5189 : ffffad8413e59060 0000000000000000 fffff287fc5607bb 002e006700000008 : nt+0x5f665b
fffffb88706ce990 fffff80732316635 : 01d7590566503ed7 fffffb88706cf9d0 fffffb88706cf010 0000000000000000 : nt+0x6d4189
fffffb88706cec10 fffff80732317385 : 0000000000000490 fffffb88706ced00 fffff80732316910 fffffb88706cf638 : GetSessionIdOfProcess+0x175

FAULTING_SOURCE_LINE_NUMBER:  677

FAULTING_SOURCE_CODE:  
   673: 		if (token)
   674: 		{
   675: 			// Now that we have a token reference, get a handle to it
   676: 			// so that we can query it.
   677: 			status = ObOpenObjectByPointer(token, 0, NULL, TOKEN_QUERY, NULL, KernelMode, &htoken);
   678: 			if (!NT_SUCCESS(status))
   679: 			{
   680: 				DbgPrintEx(DPFLTR_NDE_MASK, DPFLTR_NDE_ERROR_LEVEL, "Error occured while accessing the token handle for PID : %llu , error code : %x\r\n", dwPid, status);
   681: 			}
   682: 			else

IRQL_NOT_LESS_OR_EQUAL (a)
An attempt was made to access a pageable (or completely invalid) address at an interrupt request level (IRQL) that is too high. This is usually caused by drivers using improper addresses.
If a kernel debugger is available get the stack backtrace.
Arguments:
Arg1: ffffad841e8ff018, memory referenced
Arg2: 0000000000000002, IRQL
Arg3: 0000000000000000, bitfield :
bit 0 : value 0 = read operation, 1 = write operation
bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status)
Arg4: fffff8072d5f765b, address which referenced memory

Please let me know how I can extract the WTS ID from process ID

Did you try to debug it yourself before posting the question here? It seems like this function runs at DISPATCH_LEVEL which causes a crash - this is pretty clear from the error… Can you send a callstack with resolved symbols?

Also there’s no need to call ObOpenObjectByPointer you can just use SeQueryInformationToken on the token object

Thanks Ori,

This issue is not occurring frequently so it is quite difficult to get the issue in debugging.

STACK_TEXT:

fffffb88`706ce4c8 fffff807`2d409b69 : 00000000`0000000a ffffad84`1e8ff018 00000000`00000002 00000000`00000000 : nt+0x3f6b90
fffffb88`706ce4d0 fffff807`2d405e69 : fffffb88`706ceaf0 fffffb88`706ce8a8 00000000`00000000 00000000`00000000 : nt+0x408b69
fffffb88`706ce610 fffff807`2d5f765b : 00000000`00000000 fffffb88`00000000 00000000`00000000 ffffad84`13e59030 : nt+0x404e69
fffffb88`706ce7a0 fffff807`2d6d5189 : ffffad84`13e59060 00000000`00000000 fffff287`fc5607bb 002e0067`00000008 : nt+0x5f665b
fffffb88`706ce990 fffff807`32316635 : 01d75905`66503ed7 fffffb88`706cf9d0 fffffb88`706cf010 00000000`00000000 : nt+0x6d4189
fffffb88`706cec10 fffff807`32317385 : 00000000`00000490 fffffb88`706ced00 fffff807`32316910 fffffb88`706cf638 : uacnde!GetSessionIdOfProcess+0x175 [D:\Projects\wfp-network_extractor\NetworkDataExtraction\WindowFilterCallback.c @ 677] 
fffffb88`706cecd0 fffff807`32316977 : fffffb88`706cf9d0 fffffb88`706cf720 fffffb88`706cf638 fffffb88`706cf2d0 : uacnde!UpdateSourceIP+0x105 [D:\Projects\wfp-network_extractor\NetworkDataExtraction\WindowFilterCallback.c @ 550] 
fffffb88`706cee80 fffff807`2f4c0d2b : fffffb88`706cf638 fffffb88`706cf9d0 fffffb88`706cf720 fffffb88`706cf2d0 : uacnde!TLInspectALEConnectClassify+0x67 [D:\Projects\wfp-network_extractor\NetworkDataExtraction\WindowFilterCallback.c @ 446] 
fffffb88`706ceec0 fffff807`2f2dfafd : ffffd386`fa22ae60 fffffb88`706cf9d0 00000000`0000012e 00000000`000000c0 : tcpip+0x130d2b
fffffb88`706cef10 fffff807`2f2b95eb : 00000000`00000042 fffffb88`706cf638 fffffb88`706cf9d0 fffffb88`706cf720 : NETIO+0x2fafd
fffffb88`706cf090 fffff807`2f2b818a : ffffd386`ff5f8fb0 fffffb88`706cf638 00000000`00000000 fffffb88`706cf390 : NETIO+0x95eb
fffffb88`706cf1f0 fffff807`2f437f50 : fffffb88`706cff00 fffffb88`706cf6e0 fffffb88`706d0338 ffffd387`0398dc90 : NETIO+0x818a
fffffb88`706cf5e0 fffff807`2f4b3bbe : 00000000`0000d7fe 00000000`00000000 00000000`00000000 fffffb88`706d0390 : tcpip+0xa7f50
fffffb88`706cfe60 fffff807`2f43ad12 : 00000000`00000000 fffffb88`706d0180 00000000`00000002 00000000`00000000 : tcpip+0x123bbe
fffffb88`706d0050 fffff807`2f3c245b : ffffd386`fa4c4440 fffff807`2f701010 ffffd387`01230a40 fffff807`30de4f06 : tcpip+0xaad12
fffffb88`706d0220 fffff807`2f3c51ed : 00000000`00000026 fffffb88`706d1128 00000000`00000001 fffffb88`706d0c60 : tcpip+0x3245b
fffffb88`706d0550 fffff807`2f3c426b : ffffd386`fa2af988 ffffd386`0080308a fffffb88`706d0920 fffff807`2f3b2a01 : tcpip+0x351ed
fffffb88`706d0820 fffff807`2f3c3e30 : fffffb88`706d1100 00000000`00000000 fffff807`2f589230 ffffd387`0398dc90 : tcpip+0x3426b
fffffb88`706d09a0 fffff807`2f3b23de : 00000000`00003500 ffffd386`fa4dd4b0 ffffd386`fa4d3500 ffffd386`fa4dd4b0 : tcpip+0x33e30
fffffb88`706d09e0 fffff807`2f3b15ac : 00000000`00000000 00000000`00000000 fffff807`3051ea40 ffffd387`040da8a0 : tcpip+0x223de
fffffb88`706d0e80 fffff807`2f3b12f5 : ffffd387`020e4d01 fffff807`2f3b12e0 fffffb88`706d1300 fffffb88`706d1300 : tcpip+0x215ac
fffffb88`706d11f0 fffff807`2d299b98 : fffffb88`706d1450 ffffd386`ff6302b0 00000000`00000000 00000000`00000000 : tcpip+0x212f5
fffffb88`706d1220 fffff807`2d299b0d : fffff807`2f3b12e0 fffffb88`706d1300 00000000`00000000 fffff807`2f2c010b : nt+0x298b98
fffffb88`706d1290 fffff807`2f4038fb : ffffd386`fab3a000 fffff807`2f2c6ede 00000000`00000013 fffff807`30504b30 : nt+0x298b0d
fffffb88`706d12d0 fffff807`30520899 : fffffb88`706d1640 fffffb88`706d1b80 ffffd387`020e4d80 fffffb88`706d1b80 : tcpip+0x738fb
fffffb88`706d1350 fffff807`30504a25 : ffffd386`ff6302b0 fffffb88`706d1968 0000007a`8537dce0 ffffd387`04f94020 : afd+0x50899
fffffb88`706d1540 fffff807`2d6e2db2 : 00000000`00000000 00000000`000120d3 fffffb88`706d1b80 ffffd387`04f93d70 : afd+0x34a25
fffffb88`706d18e0 fffff807`2d6e2a16 : 00000000`00000001 00000000`00000fa0 00000000`00000000 00000000`00000000 : nt+0x6e1db2
fffffb88`706d1a20 fffff807`2d4095b5 : 00000000`00000000 ffffd387`03698040 0000007a`00000000 ffffd387`037c55e0 : nt+0x6e1a16
fffffb88`706d1a90 00007ffe`46a6cf04 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt+0x4085b5
0000007a`8537dc38 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007ffe`46a6cf04

I will check the SeQueryInformationToken API.

As 0xrepnz stated, your GetSessionIdOfProcess(…) function runs at DISPATCH_LEVEL at some point in your driver, while ObOpenObjectByPointer(…) is supposed to be called at <= APC_LEVEL.

For the note: DISPATCH_LEVEL = 2, APC_LEVEL = 1, so you need to lower your IRQL.