A Light on Windows 10's “OBJECT_HEADER->TypeIndex”

In Windows OS, the system resources (e.g. processes, files, devices) that need to be named, shared, protected, or exposed to user mode, are managed by the OS as objects. User applications can’t access these objects/resources directly but through the Object Manager (Ob), the subsystem that manages the access to the system objects/resources. Windows 10 (build 16299), for example, has 64 different object types.

But what’s the Windows object?…

  1. Object header (OBJECT_HEADER): the first 0x30 bytes. The object manager owns and manages this part of the structure (Figure 1).
  2. The body: the part that represents the actual system resource (e.g. EPROCESS for processes, FILE_OBJECT for files, DEVICE_OBJECT for devices).
Figure 1. OBJECT_HEADER Data Structure

In this post together we will shed a light on TypeIndex element of the object header and the change that has taken place in Windows 10. But before that let’s recall what we knew about TypeIndex from the Windows releases prior to Windows 10.

TypeIndex in Windows 7/8/8.1

Figure 2. nt!ObTypeIndexTable
Figure 3. OBJECT_TYPE Data Structure

Now let’s take an exmple from a Windows 8.1 system where I picked an object of type process located at the memory address 0xffffe0007fa6a8d0 in this case (Figure 4). As you can see below, the TypeIndex value for this object is “7”. Okay! now let’s check the seventh pointer in nt!ObTypeIndexTable. As you can see below, the seventh pionter points to the OBJECT_TYPE that its name value is “Process”.

Figure 4. Example for TypeIndex in Windows 8.1

TypeIndex in Windows 10

In Windows 10, TypeIndex is no longer a valid index into nt!ObTypeIndexTable. The objects of the same type have different TypeIndex values, which is enough to confirm the statement above. Moreover, the TypeIndex value is either an index to the wrong pointer that points to the wrong object type or sometimes an out of the range index (remember that Windows 10 has 64 object types).

Figure 5 shows the TypeIndex values for two Windows 10 objects of the type process. They are different and out of range indexes.

Figure 5. Example of TypeIndex (Windows 10)

The question then is how these values are used to get the right index to the pointer to the right object type?. One of the way to answer this is looking at code pieces that deal with this data strucutre. I searched the object manager functions looking for the ones that could be dealing with the OBJECT_HEADER and more specifically TypeIndex. The search revealed an interesting function that couldn’t be overlooked in this context because of its name, nt!ObGetObjectType! (Figure 6).

Figure 6. ObGetObjectType function

Let’s have a look at what nt!ObGetObjectType does…

Figure 7. Assembly code of nt!ObGetObjectType

The function ObGetObjectType takes the address to the object as an argument and does the following:

  1. The code calculates the OBJECT_HEADER address for the object by substracting 0x30 from the object memory address passed as an argument. Remember! the size of the object header is 0x30 bytes.
  2. The code XORs the TypeIndex value with the second least significant byte of the address of OBJECT_HEADER calculated in the previous step.
  3. The code then XORs the result from step 2 with the byte at the address nt!ObHeaderCookie.
  4. Finally, the result of the XOR operations is used as an index into nt!ObTypeIndexTable and returns the pointer to the OBJECT_TYPE at this index.

So the equation to caluclate the index from the TypeIndex as the following:

Index = TypeIndex ^ 2nd least significate byte of OBJECT_HEADER address ^ nt!ObHeaderCookie

Let’s validate this equation on an object of the type process (at the memory address ffffae04744e0500) in this case. As you can see in Figure 8, the 2nd least significant byte of object header address is 0x04. The TypeIndex value for the object is 0xf2. The cookie value is 0xf1. Using above equation, the index value would be 7 (highlighted in red).

Figure 8. example for Index value caluculation from TypeIndex

Checking the OBJECT_TYPE, at the location that the 7th pointer in nt!ObTypeIndexTable points to, confirms it’s of the type “Process” (Figure 9).

Figure 9. OBJECT_TYPE struct that ObTypeIndexTable’s 7th pointer points to

This shows how “OBJECT_HEADER->TypeIndex” value is used, in Windows 10 , to reference the object type and confirms the equation above.

Hope you liked the post… 👋🏽

Ashraf Abdalhalim

We —humans— who connect the real and cyber spaces. https://twitter.com/AshAbdalhalim