@ChiChou wrote:
XPC 是 macOS / iOS 上很常见的进程间通信机制。分析 XPC 通信很容易想到在 lldb 里对
xpc_*
系列函数下断点。不过调试的时候发现一些进程处理 XPC 队列被阻塞之后,会导致整个桌面被挂起无法操作。作为 frida 脑残粉,果断转到脚本上实现。作为 XPC 的发送方有两个关键的函数调用:
void xpc_connection_send_message_with_reply(xpc_connection_t connection, xpc_object_t message, dispatch_queue_t targetq, xpc_handler_t handler); xpc_object_t xpc_connection_send_message_with_reply_sync(xpc_connection_t connection, xpc_object_t message);
其中
xpc_object_t
实际上是一个NSObject<OS_xpc_object>
的指针:
typedef NSObject<OS_xpc_object> *xpc_object_t;
因此完全可以使用 ObjectiveC 的 description 方法打印其内容。
const xpc_connection_get_name = new NativeFunction( Module.findExportByName(null, 'xpc_connection_get_name'), 'pointer', ['pointer']) function logger(tag) { return { onEnter: function(args) { const conn = ptr(args[0]) const name = Memory.readUtf8String(xpc_connection_get_name(conn)) console.log(tag, name) console.log(new ObjC.Object(args[1]) + '') }, onLeave: function() {} } } Interceptor.attach(Module.findExportByName(null, 'xpc_connection_send_message_with_reply'), logger('async')) Interceptor.attach(Module.findExportByName(null, 'xpc_connection_send_message_with_reply_sync'), logger('sync'))
比如在 Apple Script 编辑器里测试如下脚本
do shell script "sudo touch /1" user name "root" password "xxxx" with administrator privileges
可以看到 Script Editor 向 authd 服务发送了如下消息
sync com.apple.authd <OS_xpc_dictionary: <dictionary: 0x6040003600c0> { count = 4, transaction: 0, voucher = 0x0, contents = "_rights" => <array: 0x60400085b720> { count = 1, capacity = 8, contents = 0: <dictionary: 0x60400017ee40> { count = 3, transaction: 0, voucher = 0x0, contents = "_item_name" => <string: 0x604000859b90> { length = 22, contents = "system.privilege.admin" } "_item_flags" => <uint64: 0x604000421600>: 0 "_item_value" => <data: 0x604000c69380>: { length = 7 bytes, contents = 0x2f62696e2f7368 } } } "_type" => <uint64: 0x60400023e560>: 1 "_flags" => <uint64: 0x6040004217c0>: 18 "_environment" => <array: 0x60400084a4a0> { count = 3, capacity = 8, contents = 0: <dictionary: 0x60400017c8c0> { count = 3, transaction: 0, voucher = 0x0, contents = "_item_name" => <string: 0x60400085e900> { length = 8, contents = "username" } "_item_flags" => <uint64: 0x6040006220c0>: 0 "_item_value" => <data: 0x604000c647c0>: { length = 4 bytes, contents = 0x726f6f74 } } 1: <dictionary: 0x604000361d40> { count = 3, transaction: 0, voucher = 0x0, contents = "_item_name" => <string: 0x604000a460c0> { length = 8, contents = "password" } "_item_flags" => <uint64: 0x6040004262e0>: 0 "_item_value" => <data: 0x604000e60000>: { length = 0 bytes, contents = 0x } } 2: <dictionary: 0x6040001759c0> { count = 3, transaction: 0, voucher = 0x0, contents = "_item_name" => <string: 0x6040008580c0> { length = 6, contents = "prompt" } "_item_flags" => <uint64: 0x6040004218a0>: 0 "_item_value" => <data: 0x604000c77d80>: { length = 0 bytes, contents = 0x } } } }>
Posts: 1
Participants: 1