Show Notes

PwnKit, a Win32k Type Confusion, and Binary Ninja 3.0

This was an interesting data based attack all because it was assumed there would be arguments in argv. A for-loop starts with n=1 looping until n < argv. Then after processing the arguments, accessing argv[n] outside of the loop. Normally this would be pointing to the last argument but when argc is zero, and the loop never runs and argv[n] points out of bounds.

This particular issue was actually reported on back in 2013 though it was not exploited at the time. It was noted that they could get as far as having the first environment variable treated as the executable to be started, but without being able to authenticate as root or pass arguments they couldn’t weaponize it.

Which is where PwnKit picks back up, rather than looking at this as just another way of controlling the program that will be executed, they looked at abusing that write-back into argv[n] as a way of introducing environment variables that would have been stripped by (which removes things like LD_PRELOAD when running setuid binaries so a low-privileged user cannot cause any issues). What Qualys found was that a cleverly named folder and binary name could be used to have it write back a proper environment variable.

Having a folder like name=. in their PATH environment, and inside the name=. folder having a binary named value would result in the g_find_program_in_path call returning the string name=./value which ends up being written into argv[n] aka envp[0].

Using this they could reintroduce sensitive environment values and compromise a privileged setuid binary.

Once again, the use of user-mode callbacks in the Windows kernel enabled an attacker to change out the type of an object unexpectedly leading to a type confusion.

The post indicates that several families of kernel calls (xxxMenuWindowProc, xxxSBWndProc, xxxSwitchWndProc, xxxTooltipWndProc) could be used to trigger the xxxClientAllocWindowClassExtraBytes callbacks. The callback could then use NtUserConsoleControl method to set theConsoleWindow flag of the tagWND object. Once the callback returned, the tagWND object will be accessed, but it will be unaware of the type change that occurred, leading to a type confusion where a user_mode pointer is treated as the offset to the desktop heap, which can be used for more out-of-bound accesses.

There is a bit of a race condition in some areas of kernel code a file that has been closed by userspace will still be accessed by the kernel.

The issue is whenfd_install(fd, file) is called, which exposes the file to the userland and then any further work on fd or file is attempted. The problem is that as it has been exposed to the userspace, it can be closed by userspace immediately leading to a use-after-free.

} }