An array of KSE_HOOK structures provides the third level in the description of a driver shim. The second level of the description is an array of KSE_COLLECTION structures. The top top level is a KSE_SHIM structure.

Microsoft’s name for this structure is known from symbol files for a driver (NDIS.SYS) that registers a shim and uses C++ for instantiating its KSE_HOOK array as statically allocated data: the C++ decoration names the type. Microsoft’s names and types are not known for members, there being no type information in the symbol file.

The KSE_HOOK is 0x10 and 0x20 bytes in 32-bit and 64-bit Windows 10, respectively.

Offset (x86) Offset (x64) Size Description
0x00 0x00 dword type of collection:
0 to hook function in shimmed driver’s Import Address Table;
1 to hook shimmed driver’s receipt of I/O requests and related notifications;
2 for last KSE_HOOK in array
0x04 0x08 pointer for type 0 only: address of name of exported function to hook, as null-terminated ANSI string
dword for type 1 only: I/O callback code
0x08 0x10 pointer address of hook routine
0x0C 0x18 pointer initially NULL;
for type 0 only: receives forwarding address

For the last hook in the array, i.e., for type 2, all other members are ignored.

Each KSE_HOOK must specify a hook routine to which a shimmed driver’s execution is to be diverted. If instead the pointer is NULL, then the shim that contains this KSE_HOOK cannot be registered.

When a registered shim is applied to some driver, the Kernel Shim Engine (KSE) edits each KSE_HOOK.

The type 0 hooks are applied after the driver is loaded, of course, but before it executes any of its code, even for initialisation. This ensures that all the driver’s code is subject to the redirection of functions that the driver imports. The type 1 hooks are applied later, because it is only during the driver’s initialisation that the driver sets into various members of the given DRIVER_OBJECT the addresses at which it wants to be called for such things as I/O requests. The codes for these I/O callbacks are:

Code Interpretation
1 to hook what the driver puts in the DriverInit member
2 to hook what the driver puts in the DriverStartIo member
3 to hook what the driver puts in the DriverUnload member
4 to hook what the driver puts in the AddDevice member (of the DRIVER_EXTENSION)
100 + mj to hook what the driver puts in the MajorFunction member for the IRP major function mj

It is not clear what Microsoft intends by changing the DriverInit member. Having a loaded a driver and expecting to initialise it, the kernel sets DriverInit to the driver’s entry point for initialisation and then calls that entry point. To hook the member after the initialisation is too late if the goal is to affect the driver’s initialisation. More study is evidently needed.