Edit Template

Understanding Type Confusion in Kernel Driver

In this blog post, we will explore type confusion vulnerabilities in Windows kernel drivers. Type confusion occurs when a program mistakenly treats a piece of memory as a different object type than it actually is, leading to unexpected behavior or security flaws. To better understand this concept, we will build a custom vulnerable kernel driver that demonstrates how type confusion can arise in real-world scenarios.

What Is Type Confusion?

Type confusion happens when a program incorrectly assumes the type of an object in memory, leading to invalid interpretation, unsafe operations, or security vulnerabilities. In kernel drivers, this can allow attackers to manipulate data structures or execute arbitrary code. To use an analogy, type confusion is like mistaking a box of fragile glassware for a box of metal tools and stacking heavy items on it, causing breakage.

Data Type Confusion

Data type confusion is a vulnerability where a variable of one data type is mistakenly used as another incompatible type, causing unsafe behavior. It often leads to arbitrary memory access or logic flaws. We created a custom Windows kernel driver to demonstrate integer-to-pointer data type confusion, where a user-supplied integer is wrongly treated as a pointer.

The vulnerability occurs because a user-controlled 32-bit integer (SourceAddress) is incorrectly treated as a pointer and directly dereferenced (ULONG val = *(ULONG*)srcAddr;), allowing arbitrary kernel memory reads or triggering a system crash. In simple words, it’s like a mailman mistaking a phone number for a home address and trying to deliver a package there, causing confusion or failure.

Proof-of-Concept (PoC) for Type Confusion Vulnerability in IPv4 Driver

This is simply a PoC to demonstrate the vulnerability, exploitation is not covered in this article. In future posts, we will show full exploitation techniques and development.

This PoC opens a handle to the custom driver and sends a crafted IPV4_HEADER structure via DeviceIoControl. The key user input is the SourceAddress field. Instead of providing a legitimate IPv4 address (an integer), the user directly inputs an arbitrary kernel memory address (interpreted as a pointer by the driver).

The crash occurred when the driver tried to dereference a user-controlled pointerrbx = 0x41414141 (user input). This caused an invalid memory access at mov r8d, dword ptr [rbx], leading to a kernel crash (blue screen of death).

Bonus Tip

When hunting for data type confusion in kernel drivers, look for code paths where user-supplied integers (like ULONG, DWORD, UINT32, SIZE_T, NTSTATUS, BOOLEAN, USHORT) are later reinterpreted as pointers or larger structures. Common risky casts include: (PVOID), (ULONG_PTR), (void*), and pointer dereferences (*ptr, memcpy, RtlCopyMemory).

Scalar-to-Pointer Type Confusion in Windows Kernel

This vulnerability is a scalar-to-pointer type confusion caused by improper handling of a union in a Windows kernel driver. The kernel structure allows a user-controlled scalar value (ObjectType) to be reinterpreted as a function pointer (Callback) due to a shared memory location (union).

This custom Windows kernel driver demonstrates a union-based type confusion vulnerability where a user-controlled integer is mistakenly used as a kernel function pointer.

In the given structure, the USER_PACKET_OBJECT structure represents a user-space packet with fields for an ObjectID, PacketType, and a variable-length payload. The KERNEL_PACKET_OBJECT structure is a kernel-space packet that contains a union with two members: PacketType (an integer) and Callback (a function pointer). A union allows these two members to share the same memory space, meaning both PacketType and Callback will use the same address, but only one can be accessed at a time.

Here, the value of userPacket->PacketType, which is controlled by the user, is directly copied into the PacketType field of the KERNEL_PACKET_OBJECT structure. This is problematic because PacketType is part of a union that also contains a function pointer (Callback). Since both fields share the same memory space, an attacker can manipulate the PacketType field to store a value that will later be interpreted as a function pointer. This results in a type confusion vulnerability where an integer value is misinterpreted as a function pointer. 

For example, it’s like handing someone a letter with an envelope that can either hold a note or a secret code; the person can choose to treat it as a note, but if they mistakenly interpret it as a code, they could unlock and trigger unintended actions.

Root Cause Analysis: Type Confusion in mskssrv.sys

In the vulnerable function FSRendezvousServer::PublishRx, the Windows driver mskssrv.sys handles objects related to media streaming. Internally, it manages two types of objects:

  • FSContextReg object (size: 0x78 bytes)
  • FSStreamReg object (size: 0x1D8 bytes)

Both of these objects are stored inside the FileObject->FsContext2 field, which is meant to point to an object that the driver will later operate on.

Where Is the Bug?

The vulnerability happens because the function FsRendezvousServer::FindObject() is used to locate an object—but it does not verify the type of the object it finds.

The key problem lies in how the driver assumes the type of object it is dealing with. The code expects that the object retrieved from FindObject() is always of type FSStreamReg. However, in reality, the object could also be of type FSContextReg, which is a smaller and fundamentally different structure. Without performing any type verification, the driver blindly treats the object as an FSStreamReg and proceeds to call functions such as PublishRx() and GetStats() on it. These functions are designed to operate only on FSStreamReg objects and expect specific fields and memory layouts that do not exist in FSContextReg as show below.

Real-World Analogy

Imagine a person working in a warehouse is told to pick up a specific type of package in a large box. They’re given a label and assume every package is the same size. However, sometimes the label is attached to a small, fragile package that can’t take the same handling as the usual large box.

If the person picks up the small package the same way they would the large box, they could crush or damage it. This is similar to the vulnerability—the driver assumes every object is the larger, more complex type (FSStreamReg), but sometimes it’s a smaller, simpler object (FSContextReg), leading to system failure.

Conclusion — Hunting and Type Confusion Bugs

Type confusion vulnerabilities occur when the kernel mistakenly treats one data type as another, for example, an integer misused as a function pointer or a struct interpreted incorrectly. These bugs are common in complex components like graphics drivers, network protocols, file systems, and streaming engines where mixed data types and unions are frequently used just like we saw in real-world cases such as mssksrv.sys. When hunting, focus on places where user-controlled input flows into unions, type casts, or function callbacks without validation. Fuzzing, static analysis, and runtime debugging (like WinDbg) are powerful tools for exposing such issues.

References

  1. mskssrv.sys: –  https://winbindex.m417z.com/?file=mskssrv.sys
  2. Root Cause Analysis: –  https://www.ibm.com/think/x-force/critically-close-to-zero-day-exploiting-microsoft-kernel-streaming-service

Edit Template