![]() ![]() This is where the event queue and cursor data reside, and this makes up 99% of the shared memory. Typedef volatile struct _evOffsets EvOffsets This structs holds information about where the other parts of the shared memory are located in respect to the beginning of the shared memory (so they’re given as offsets). This memory is split into three parts packed after each other in this order: IOHIDSystem/ IOHIDUserClient offer some shared memory for an event queue and certain cursor-related data that WindowServer can map into its address space via clientMemoryForType. For now we’re gonna look at what it actually uses that UserClient for. ![]() So snatching that is not straightforward, but we’ll get to that later. This variable is checked in IOHIDSystem::evOpen, which in turn is called from IOHIDSystem::newUserClientGated (so we can’t even race it).īottom line, there can only be one IOHIDUserClient at any given moment, and chances are that when your code runs, WindowServer will be long up and running with its UserClient already. This is specifically enforced by the evOpenCalled class variable, which is set to true when an IOHIDUserClient is spawned and to false again when it is closed. This is an important point because as it turns out, IOHIDSystem restricts the number of IOHIDUserClients that can exist at any given time to exactly one. IOHIDUserClient(IOHIDUserClient): (os/kern) successful (0x0) IOHIDParamUserClient can actually be spawned by any unprivileged process, but of interest to us is IOHIDUserClient, arguably the most powerful of the three, which during normal system operation is held by WindowServer: (There used to be a fourth, IOHIDStackShotUserClient, but that has been commented out for a while now.) Like almost all UserClients in IOHIDFamily these days, IOHIDEventSystemUserClient requires an entitlement to be spawned ( .user-access-service), however the other two do not. It starts with the IOHIDSystem class and the UserClients it offers. ![]() In order to understand the attack surface as well as the vulnerability, you need to know about the involved parts of IOHIDFamily. I’m also using my hsp4 kext along with kern-utils to inspect kernel memory.įor any kind of questions or feedback, feel free to hit me up on Twitter Mastodon or via mail ( where * = siguza). Note: The ioprint and ioscan utilities I’m using in this write-up are available from my iokit-utils repository. Targets Sierra and High Sierra (up to 10.13.1, see README), achieves full kernel r/w and disables SIP to prove that the vulnerability can be exploited by any unprivileged user on all recent versions of macOS. Targets High Sierra, just to prove that no separate KASLR leak is needed. Targets all macOS versions, crashes the kernel to prove the existence of a memory corruption. The exploit accompanying this write-up consists of three parts: I was originally looking through its source in the hope of finding a low-hanging fruit that would let me compromise an iOS kernel, but what I didn’t know then is that some parts of IOHIDFamily exist only on macOS - specifically IOHIDSystem, which contains the vulnerability discussed herein. ![]() IOHIDFamily has been notorious in the past for the many race conditions it contained, which ultimately led to large parts of it being rewritten to make use of command gates, as well as large parts being locked down by means of entitlements. This is the tale of a macOS-only vulnerability in IOHIDFamily that yields kernel r/w and can be exploited by any unprivileged user. ![]()
0 Comments
Leave a Reply. |