/// <summary> /// Trigger the Type Confusion Vulnerability /// </summary> /// <param name="pTypeConfusionUserObject">The pointer to TYPE_CONFUSION_USER_OBJECT object</param> /// <returns>NTSTATUS</returns> NTSTATUS TriggerTypeConfusion(IN PTYPE_CONFUSION_USER_OBJECT pTypeConfusionUserObject) { NTSTATUS status = STATUS_UNSUCCESSFUL; PTYPE_CONFUSION_KERNEL_OBJECT pTypeConfusionKernelObject = NULL; PAGED_CODE(); __try { // Verify if the buffer resides in User Mode ProbeForRead(pTypeConfusionUserObject, sizeof(TYPE_CONFUSION_USER_OBJECT), (ULONG)__alignof(TYPE_CONFUSION_USER_OBJECT)); // Allocate Pool Memory pTypeConfusionKernelObject = (PTYPE_CONFUSION_KERNEL_OBJECT) ExAllocatePoolWithTag(NonPagedPool, sizeof(TYPE_CONFUSION_KERNEL_OBJECT), (ULONG)POOL_TAG); if (!pTypeConfusionKernelObject) { // Unable to allocate Pool Memory with Tag DbgPrint("[-] Unable To Allocate Pool Memory\n"); status = STATUS_NO_MEMORY; return status; } else { DbgPrint("[+] Pool Address: 0x%p\n", pTypeConfusionKernelObject); DbgPrint("[+] Pool Type: %s\n", STRINGIFY(NonPagedPool)); DbgPrint("[+] Pool Size: 0x%X\n", sizeof(TYPE_CONFUSION_KERNEL_OBJECT)); DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG)); } DbgPrint("[+] pTypeConfusionUserObject: 0x%p\n", pTypeConfusionUserObject); DbgPrint("[+] pTypeConfusionKernelObject: 0x%p\n", pTypeConfusionKernelObject); DbgPrint("[+] pTypeConfusionKernelObject Size: 0x%X\n", sizeof(TYPE_CONFUSION_KERNEL_OBJECT)); pTypeConfusionKernelObject->objectID = pTypeConfusionUserObject->objectID; DbgPrint("[+] pTypeConfusionKernelObject->objectID: 0x%p\n", pTypeConfusionKernelObject->objectID); pTypeConfusionKernelObject->objectType = pTypeConfusionUserObject->objectType; DbgPrint("[+] pTypeConfusionKernelObject->objectType: 0x%p\n", pTypeConfusionKernelObject->objectType); #ifdef SECURE // Secure Note: This is secure because the developer is properly setting 'pCallback' // member of the TYPE_CONFUSION_KERNEL_OBJECT structure before passing the pointer to // itself to TypeConfusionObjectInitializer() function as parameter pTypeConfusionKernelObject->pCallback = &TypeConfusionObjectCallback; status = TypeConfusionObjectInitializer(pTypeConfusionKernelObject); #else DbgPrint("[+] Triggering Type Confusion\n"); // Vulnerability Note: This is a vanilla Type Confusion vulnerability due to improper // use of the UNION construct. The developer has not set the 'pCallback' member of the // TYPE_CONFUSION_KERNEL_OBJECT structure before passing the pointer to itself to // TypeConfusionObjectInitializer() function as parameter status = TypeConfusionObjectInitializer(pTypeConfusionKernelObject); #endif DbgPrint("[+] Freeing pTypeConfusionKernelObject Object\n"); DbgPrint("[+] Pool Address: 0x%p\n", pTypeConfusionKernelObject); DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG)); // Free the allocated Pool Memory ExFreePoolWithTag((PVOID)pTypeConfusionKernelObject, (ULONG)POOL_TAG); pTypeConfusionKernelObject = NULL; } __except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); DbgPrint("[-] Exception Code: 0x%X\n", status); } return status; }
/// <summary> /// Trigger the Type Confusion Vulnerability /// </summary> /// <param name="UserTypeConfusionObject">The pointer to USER_TYPE_CONFUSION_OBJECT object</param> /// <returns>NTSTATUS</returns> NTSTATUS TriggerTypeConfusion(IN PUSER_TYPE_CONFUSION_OBJECT UserTypeConfusionObject) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PKERNEL_TYPE_CONFUSION_OBJECT KernelTypeConfusionObject = NULL; PAGED_CODE(); __try { // Verify if the buffer resides in user mode ProbeForRead(UserTypeConfusionObject, sizeof(USER_TYPE_CONFUSION_OBJECT), (ULONG)__alignof(USER_TYPE_CONFUSION_OBJECT)); // Allocate Pool chunk KernelTypeConfusionObject = (PKERNEL_TYPE_CONFUSION_OBJECT) ExAllocatePoolWithTag(NonPagedPool, sizeof(KERNEL_TYPE_CONFUSION_OBJECT), (ULONG)POOL_TAG); if (!KernelTypeConfusionObject) { // Unable to allocate Pool chunk DbgPrint("[-] Unable to allocate Pool chunk\n"); Status = STATUS_NO_MEMORY; return Status; } else { DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG)); DbgPrint("[+] Pool Type: %s\n", STRINGIFY(NonPagedPool)); DbgPrint("[+] Pool Size: 0x%X\n", sizeof(KERNEL_TYPE_CONFUSION_OBJECT)); DbgPrint("[+] Pool Chunk: 0x%p\n", KernelTypeConfusionObject); } DbgPrint("[+] UserTypeConfusionObject: 0x%p\n", UserTypeConfusionObject); DbgPrint("[+] KernelTypeConfusionObject: 0x%p\n", KernelTypeConfusionObject); DbgPrint("[+] KernelTypeConfusionObject Size: 0x%X\n", sizeof(KERNEL_TYPE_CONFUSION_OBJECT)); KernelTypeConfusionObject->ObjectID = UserTypeConfusionObject->ObjectID; KernelTypeConfusionObject->ObjectType = UserTypeConfusionObject->ObjectType; DbgPrint("[+] KernelTypeConfusionObject->ObjectID: 0x%p\n", KernelTypeConfusionObject->ObjectID); DbgPrint("[+] KernelTypeConfusionObject->ObjectType: 0x%p\n", KernelTypeConfusionObject->ObjectType); #ifdef SECURE // Secure Note: This is secure because the developer is properly setting 'Callback' // member of the 'KERNEL_TYPE_CONFUSION_OBJECT' structure before passing the pointer // of 'KernelTypeConfusionObject' to 'TypeConfusionObjectInitializer()' function as // parameter KernelTypeConfusionObject->Callback = &TypeConfusionObjectCallback; Status = TypeConfusionObjectInitializer(KernelTypeConfusionObject); #else DbgPrint("[+] Triggering Type Confusion\n"); // Vulnerability Note: This is a vanilla Type Confusion vulnerability due to improper // use of the 'UNION' construct. The developer has not set the 'Callback' member of // the 'KERNEL_TYPE_CONFUSION_OBJECT' structure before passing the pointer of // 'KernelTypeConfusionObject' to 'TypeConfusionObjectInitializer()' function as // parameter Status = TypeConfusionObjectInitializer(KernelTypeConfusionObject); #endif DbgPrint("[+] Freeing KernelTypeConfusionObject Object\n"); DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG)); DbgPrint("[+] Pool Chunk: 0x%p\n", KernelTypeConfusionObject); // Free the allocated Pool chunk ExFreePoolWithTag((PVOID)KernelTypeConfusionObject, (ULONG)POOL_TAG); KernelTypeConfusionObject = NULL; } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); DbgPrint("[-] Exception Code: 0x%X\n", Status); } return Status; }