XPoCe - XPC Snooping utilties for MacOS and iOS (version 2.0)

What is this?

XPC* is the enhanced IPC framework used in *OS. Ever since its introduction in 10.7/iOS 5, its use has exploded, as AAPL is rewriting most of its daemons to use it in place of the venerable raw Mach messages. Mach still provides the medium, but message payloads are now dictionary objects - reducing (but not eliminating) type confusion mistakes, and greatly simplifying parsing. In addition, XPC is closely tied to GCD (offering much better performance) and entitlements (greater security). I talk about that in Volume I of MOXiI (Chapter 14).

The original version of XPoCe, my XPC message tracer, relied on library injection. Now that I've just about perfected my debugger framework, coreruption, it made sense to launch a common test case for it - and have it trace XPC messages, by attaching to any PID on the system (yes, even iTunes, XCode, and launchd :-)


It doesn't get simpler than this. Just pick your target PID. If you're tracing platform binaries you'll need SIP disabled and root. Then it's as simple as:

morpheus@Zephyr (~/Documents/OSXBook/2nd/src/coreruption) % sudo ./XPoCe 1
xpc_dictionary_get_uint64 ( dictionary@0x7fc7535f4cd0,"subsystem") 
 = "<dictionary: 0x7fc7535f4cd0> { count = 3, transaction: 0, voucher = 0x0, contents =
	"subsystem" => <uint64: 0x7fc7554401a0>: 2
	"routine" => <uint64: 0x7fc7552113d0>: 700
	"self" => <bool: 0x7fff8feebb48>: true

xpc_dictionary_get_uint64 ( dictionary@0x7fc7535f4cd0,"subsystem") 
 = "<dictionary: 0x7fc7535f4cd0> { count = 9, transaction: 0, voucher = 0x0, contents =
	"handle" => <uint64: 0x7fc7552113d0>: 0
	"subsystem" => <uint64: 0x7fc7554401a0>: 5
	"instance" => <uuid: 0x7fc755445ad0> 00000000-0000-0000-0000-000000000000
	"flags" => <uint64: 0x7fc7552bd460>: 8
	"routine" => <uint64: 0x7fc75525f6f0>: 207
	"type" => <uint64: 0x7fc755242f50>: 7
	"name" => <string: 0x7fc7552a6050> { length = 36, contents = "com.apple.system.notification_center" }
	"domain-port" => <mach send right: 0x7fc7552ebaf0> { name = 3331, right = send, urefs = 174 }
	"targetpid" => <int64: 0x7fc7552841b0>: 0

# 11/07/2018 - Now with Remote XPC as well..
xpc_remote_connection_activate ( connection@0x7fcee3c4e940) = 0x31dffffaf3118a5 () 
xpc_remote_connection_send_message ( connection@0x7fcee3c4e940,dictionary@0x7fcee3d366e0) 

 = "<remote connection: 0x7fcee3c4e940> { type = rsd, state = not-connected, 
	remote service name = com.apple.powerchime.remote, server mode = 0, 
	protocol version number = 1, protocol feature flags = 0x6, local service version = 0, 
	remote service version = 0, traffic class = 0, (root, reply) 
	helo received = (0, 0), next msg id = 1, first msg id = 0, 
	send in progress = 0, preexisting socket = -1"
 = "<dictionary: 0x7fcee3d366e0> { count = 1, transaction: 0, voucher = 0x0, contents =
	"QUERY_CHIME_PLAYBACK" => <bool: 0x7fffb0f2dbe8>: true

And now with remote XPC support:

V2.5 - SimPLISTic and NSXPC support

Version 2.5 now supports NSXPC parsing - transforming the illegible bplist16 into a human readable, SimPLISTic format (The same I use in jlutil. This makes it easy to dump messages for Objective-C remoting, which loads of applications and daemons use:

Unlike v1, this beta version doesn't do simPLISTic - it uses xpc_copy_description. The commercial version enables more filters and output formats.

Also, note that since this hooks xpc_dictionary_get_* calls, the same dictionary may be shown multiple times. You can easily sift those duplicates out since the address in memory is printed as well. Again, this is something that v1 doesn't do, and neither will the final version of this. - Fixed that now.

v2.75 - Can now launch processes under XPoCE

DUH How did I forget to enable this earlier.


  1. How does it work??? By essentially debugging the target process, breaking at critical junctures, and injecting code on top
  2. Does this work on *OS? Certainly. But not the version I'm releasing here. For the *OS version you HAVE to talk to Technologeeks.
  3. Where's the source? On my laptop. This is based on coreruption, which is closed source and soon to be a commercial product. This version is free (you're welcome), but not everything I do is open source, especially when people plagiarize my sources left and right.
  4. Is it really free to use? Yep - free for non commercial use, AISE. If you want to use this commercially, talk to products @ Tg about licensing.
  5. What's this about the final version? It will be A) for MacOS and iOS both B) will be able to use a variety of formats and filters but C) probably not be free - again - products, Technologeeks, com. You know what to do.
  6. It doesn't work on MacOS for some binaries!!! That's because those binaries are either (A) entitled or (B) __RESTRICTED or (C) Setuid. Disable SIP and run this as root and it will work on everything.
  7. I want to know more about Internals!!! Come join TechnoloGeeks' training - NYC December 11th, 2019. Click here for more info.
  8. Wait, where's the download?!?!?! Right here. Just trying to make sure people read :-). Chmod +x. You have to run this as root, obviously.