Logging keystrokes OSX from kernelspace

Questions and Answers about all things *OS (macOS, iOS, tvOS, watchOS)

Logging keystrokes OSX from kernelspace

Postby vivami » Tue Jun 07, 2016 5:28 pm


I was wondering wether it is possible to log keystrokes from the kernel using hooked syscalls. I have hooked SYS_read, but it appears to be only passing keys typed in a ttys (Terminal) session. So, no "global" logging. I am aware of logKext (https://github.com/SlEePlEs5/logKext), but I wanted to prevent going the IOKit kext way, as it is more effort to develop (rebooting enforced before loading).

I contacted Jonathan on Twitter, and he answers are below:
Keystrokes/taps in iOS/OS X are IOKit HID events, not syscalls. Snoop windowserver/backboardd and their connected Mach ports.

There *Is* no alternative in OS X or iOS. The reason syscalls work is because a tty is a classic UN*X device, so it abides by the classic POSIX syscalls. The iOS and OS X input stack is event driven over Mach, so It has to be via IOKit. But I'll give you more detail there.
Posts: 1
Joined: Tue Jun 07, 2016 5:19 pm

Re: Logging keystrokes OSX from kernelspace

Postby morpheus » Tue Jun 07, 2016 7:55 pm

SO, Now Jonathan is explaining over here. This is a bit long, and may rehash things you already know, but this way you get the full picture:

- TTYs don't see nor care where the keyboard is. As far they are concerned, they are character devices which may be read from and written to. This is why SYS_read works well, because irrespective of where the keyboard really is - remote or local, the terminal creator (Terminal.app, or sshd, etc) will feed the characters into it.

- Terminal.App itself - as the rest of the OS X GUI - gets the keystrokes as IOKit Events. But not directly - rather, via WindowServer - which is the one to get all the IOHID events in user mode, then dispatch them to the "focused window" (similar to what backboard does in *OS). Try the following experiment: Open a terminal sudo to root and type

bash-3.2# killall -STOP WindowServer; sleep 5; killall -CONT WindowServer

BE VERY CAREFUL TO TYPE ALL THESE ON ONE LINE, WITH NO TYPOS - since this WILL freeze your GUI (for five seconds).

In the span, type characters. Nothing will seemingly happen, but as soon as the CONT is received, you'll see your characters.

Using ProcExp, observe and see that WindowServer is connected to your app via Mach Ports. In the example below, 243 is my Terminal.app:

bash-3.2# procexp 243 | grep Window
Terminal:243:0x3a0f ->WindowServer:134:0xe30f
Terminal:243:0x3d1f ->WindowServer:134:0x1c03
Terminal:243:0x4117 <-WindowServer:134:0xe417
Terminal:243:0x5f03 ->WindowServer:134:0xb823
Terminal:243:0x6003 <-WindowServer:134:0xb50b
Terminal:243:0x6313 ->WindowServer:134:0xbc1b
Terminal:243:0x640f <-WindowServer:134:0xb90b
Terminal:243:0x6c0f ->WindowServer:134:0x1b03

Once again, with ProcExp, observe Terminal.app's threads:

4 31/63 Policy:1 CPU:1 com.apple.terminal.tty-io
0xae1 0x7fff88b644de mach_msg_trap + 0xa 0xffffff8000318800
0x7fff8e07beb4 __CFRunLoopServiceMachPort + 0xd4
0x7fff8e07b37b __CFRunLoopRun + 0x55b
0x7fff8e07abd8 CFRunLoopRunSpecific + 0x128
0x7fff8e532268 _pthread_body + 0x83
0x7fff8e5321e5 _pthread_body + 0x0
0x7fff8e53041d thread_start + 0xd

And that's how Terminal.app gets the keystrokes.

If you want to otherwise sniff keystrokes, your options are:

- Do what LogKExt does - be in the kernel - you don't want that.
- Hijack from WindowServer by sniffing on it (via mach_task APIs, etc) - complicated
- Register yourself with IOHID by opening a user client (to see WindowServer, try ioreg -l -w 0 -f - and you will see that it registers a user client) - and do it the way WindowServer does. That way you're still in user mode (which I assume you want, and NOT kernelspace, otherwise you'd have gone with option 1, logKext). NOTE - As of 10.11 (and for sure 10.12) you will need an IOHID Entitlement for this.

I'm covering this in MOXiI 2nd Ed, btw. Though in Volume II (Kernel/Advanced) which won't be out for a while. I do have sample code for intercepting the touchpad. I'll work on modifying it so it works with the keyboard, though.

Hope this helps - let me know if you have any questions.

Site Admin
Posts: 530
Joined: Thu Apr 11, 2013 6:24 pm

Return to Questions and Answers

Who is online

Users browsing this forum: No registered users and 1 guest