Reversing
En este caso partiremos el código ioctl 0x222023
que nos interesa explotar, para ver como llegar hasta aquí se puede consultar la parte de reversing en el post anterior
Siguiendo la flecha verde podemos ver que es el bloque encargado de llamar a una función con el nombre TypeConfusionIoctlHandler
que tiene la vulnerabilidad
Esta función se encarga de llamar a TriggerTypeConfusion
pasandole como argumento una estructura UserTypeConfusionObject
que recibe como entrada
La estructura que recibe como parámetro podemos verla desde WinDbg
, ésta cuenta de solo 2 atributos cada uno de 8
bytes, estos se llaman OnjectID
y ObjectType
0: kd> dt HEVD!_USER_TYPE_CONFUSION_OBJECT
+0x000 ObjectID : Uint8B
+0x008 ObjectType : Uint8B
La función TriggerTypeConfusion
inicia guardando la dirección a la estructura inicial en rbx
, luego llama a la función ProbeForRead
para verificar la accesibilidad y después a ExAllocatePoolWithTag
para poder asignar un chunk
del tamaño de la estructura, 16
bytes en la memoria del tipo NonPagedPool
del kernel, el resultado que es el puntero al bloque lo guarda en r14
que será una estructura de 16
bytes como la anterior
El siguiente bloque llama varias veces a DbgPrintEx
para mostrar información como el tipo de pool
, el tamaño del chunk
y su puntero, además los punteros a la estructura inicial UserTypeConfusionObject
recibida y la KernelTypeConfusionObject
que se creó en el pool anteriormente, tambíen muestra el tamaño de esta estructura
También podemos ver la estructura KernelTypeConfusionObject
en WinDbg
, esta consta de 3
atributos, el primero es ObjectID
que ocupa los primeros 8
bytes y luego ObjectType
y Callback
que comparten el mismo offset y por lo tanto valor
0: kd> dt HEVD!_KERNEL_TYPE_CONFUSION_OBJECT
+0x000 ObjectID : Uint8B
+0x008 ObjectType : Uint8B
+0x008 Callback : Ptr64 void
Más adelante guarda los valores de la estructura inicial en rbx
a la creada en r14
, luego le pasa la estructura en r14
a la función TypeConfusionObjectInitializer
Al iniciar la función en rcx
se almacena el puntero a la estructura, luego muestra con DbgPrintEx
el puntero al Callback
que obtiene de [rcx + 8]
, luego mueve a rbx
el valor de rcx
y llama a [rbx + 8]
donde se encuentra el Callback
que tiene el mismo valor del ObjectType
, por lo que si controlamos su valor también la llamada