Advanced Frida Usage Part 3 – Inspecting XPC Calls

					<div>
				<div>
		<div>
							<div>
			<div>
						<h2>Introduction</h2><p>In the last two blogs, we have discussed briefly how we can use Frida with applications, today we will cover briefly how to do that with the system binaries.</p><p>Before we can proceed with the binaries, we first need to discuss <em><b>XPC</b></em> which is used as a means of communication between processes. XPC is a type of IPC (InterProcess Communication) used on <b>*OS</b>.</p><p>According to the <a href="https://developer.apple.com/documentation/xpc?language=objc" rel="noreferrer" target="_blank">documentation</a>:</p><blockquote><p><b>XPC provides a lightweight mechanism for basic interprocess communication. </b></p></blockquote><h2>Operation modes and usage</h2><p>There exist two modes of operation:</p><ul><li><p>server</p></li><li><p>client</p></li></ul><p>In the <em>server _mode, binary creates a specific _mach service</em> and registers it with <em>launchd</em>, while in the <em>client</em> mode connects to that specific <em>mach service</em> and sends a specific message to the server.</p><p>The first function that gets called from the server and client is <code>xpc_connection_create_mach_service</code> which returns <code>xpc_connection_t</code>.</p><p>This function accepts three parameters:</p><ul><li><p>name of the service</p></li><li><p>dispatch queue (can be <em>NULL</em>)</p></li><li><p>mode (1 for the listener/server mode or 0 for the client mode)</p></li></ul><p>Once we have done this, we need to configure the handler which is actually ObjC block by calling <code>xpc_connection_set_event_handler</code>.</p><p>Parameters are:</p><ul><li><p>connection of <code>xpc_connection_t</code></p></li><li><p>handler of <code>xpc_handler_t</code></p></li></ul><p><code>xpc_handler_t</code> is a block, defined as <code>void (^xpc_handler_t)(xpc_object_t object)</code></p>						</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
						<h2>Sending message</h2><p>To send the message, we first need to define from what does the message consists of. Message consists for <code>xpc_object_t</code> types where the main one being <code>xpc_dictionary</code>. </p><p><code>xpc_dictionary</code> consists of values mapped to distinct key.</p><p>The main function to create <em>xpc_dictionary</em> is <code>xpc_dictionary_create(const char *const  _Nonnull *keys,  xpc_object_t _Nullable const *values, size_t count)</code></p><p>Once we have created the dictionary, we can use one of the following to send the actual message:</p><ul><li><p><code>xpc_session_send_message</code> – send a message</p></li><li><p><code>xpc_session_send_message_with_reply</code> – send a message while blocking to get the reply</p></li><li><p><code>xpc_session_send_message_with_reply_async</code> – send a message with reply handler asynchronously</p></li></ul><p>Since we want over the basics of XPC, the steps for server and client are the following:</p><p><em>Server:</em></p><ol start=""><li><p>Call <code>xpc_connection_create_mach_service</code> with some specific name, while setting <code>flags</code> parameter to 1</p></li><li><p>Call <code>xpc_connection_set_event_handler</code> to setup the handler for the connections</p></li><li><p>Call <code>xpc_connection_resume</code> to resume the connection (start listening)</p></li></ol><p><em>Client:</em></p><ol start=""><li><p>Call <code>xpc_connection_create_mach_service</code> with the name used for server and setting <code>flags</code> parameter to 0</p></li><li><p>Call <code>xpc_connection_set_event_handler</code> to setup the handler for the connection</p></li><li><p>Call <code>xpc_connection_resume</code> to actually connect to the server</p></li><li><p>Craft the message </p></li><li><p>Call one of <code>xpc_session_send_message*</code> variants to send the message</p></li></ol><p>Now that we have covered that, let’s create a simple server and client using C.</p><p><strong>server.c:</strong></p>						</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
				<div>
		<pre>
			<code>
				#include &lt;stdio.h&gt;

#include <stdlib.h>
#include <dispatch/dispatch.h>
#include <xpc/xpc.h>

#define NAME “io.8ksec.xpc”

int main(void)
{
xpc_connection_t conn;

conn = xpc_connection_create_mach_service(NAME, NULL,
    XPC_CONNECTION_MACH_SERVICE_LISTENER);

xpc_connection_set_event_handler(conn, ^(xpc_object_t peer) {
	xpc_connection_set_event_handler(peer, ^(xpc_object_t event) {
	    	if (event == XPC_ERROR_CONNECTION_INVALID) {
			return;
		}

	    	if (xpc_get_type(event) != XPC_TYPE_DICTIONARY) {
			return;
		}

		xpc_object_t resp = xpc_dictionary_create(NULL, NULL, 0);
		xpc_dictionary_set_string(resp, "hello", "8ksec");
        xpc_dictionary_set_int64(resp, "blogCount", 3);
		xpc_connection_send_message(peer, resp);
	});
	xpc_connection_resume(peer);
});

xpc_connection_resume(conn);
dispatch_main();

}







					<div>
				<div>
		<div>
							<div>
			<div>
						<ul><li><p>server creates new mach service called <em>io.8ksec.xpc</em></p></li><li><p>sets up event_handler for the new connection</p></li><li><p>for each connection, sets up event handler</p></li><li><p>this event handler checks whether the type is XPC_TYPE_DICTIONARY; it is new dictionary is created</p></li><li><p>dictionary contains string <em>8ksec</em> under key <em>hello</em> and int64_t 3 under key <em>blogCount</em></p></li><li><p>sends the message to this connection</p></li><li><p>in the outside handler connection is resumed for the peer(client)</p></li><li><p>finally, connection is resumed for the entire xpc connection</p></li></ul>						</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
				<div>
		<pre>
			<code>
				#include &lt;stdio.h&gt;

#include <stdlib.h>
#include <xpc/xpc.h>

#define NAME “io.8ksec.xpc”

int main(void)
{
xpc_connection_t conn;
xpc_object_t msg;

msg = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_string(msg, "Hello", "world");

conn = xpc_connection_create_mach_service(NAME, NULL, 0);
if (conn == NULL) {
	perror("xpc_connection_create_mach_service");
	return (1);
}

xpc_connection_set_event_handler(conn, ^(xpc_object_t obj) {
    const char * hello_value = xpc_dictionary_get_string(obj, "hello");
    int64_t count_value = xpc_dictionary_get_int64(obj, "blogCount");
    printf("hello=%s\n", hello_value);
    printf("blogCount=%lld\n", count_value);
});

xpc_connection_resume(conn);
xpc_connection_send_message(conn, msg);

dispatch_main();

}







					<div>
				<div>
		<div>
							<div>
			<div>
						<ul><li><p>client creates a new dictionary with key <em>Hello</em> and value <em>world</em></p></li><li><p>connects to the mach service which is exposed by the server (<em>io.8ksec.xpc</em>)</p></li><li><p>sets up event handler for the connection where it extracts the values for the keys defined in the servers dictionary</p></li><li><p>resumes the connection</p></li><li><p>and sends the dummy message so that event handler inside the server is triggered which sends the message</p></li></ul><p>We also need to create <em>Info.plist</em> file the server which looks like this:</p>						</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
				<div>
		<pre>
			<code>
				&lt;?xml version="1.0" encoding="UTF-8"?&gt;

<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=“1.0”>
<dict>
<key>CFBundleIdentifier</key>
<string>io.8ksec.xpc</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>XPCService</key>
<dict>
<key>ServiceType</key>
<string>Application</string>
</dict>
</dict>
</plist>







					<div>
				<div>
		<div>
							<div>
			<div>
						<p>Once we did that we will embed this file into the `__info_plist` sections inside `__TEXT` segment during compilation.</p>						</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
														<img alt="" height="184" src="https://i0.wp.com/8ksec.io/wp-content/uploads/2023/07/compiling.png?fit=800%2C184&amp;ssl=1" width="800" />															</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
						<p>Once we did that, we will add our server to the _LaunchDaemons_, to do that we need to create plist file. The plist file looks like this:</p>						</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
														<img alt="" height="373" src="https://i0.wp.com/8ksec.io/wp-content/uploads/2023/07/daemon_plist.png?fit=800%2C373&amp;ssl=1" width="800" />															</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
						<p>After loading this plist, we can try connecting to the server and we can see that we got the correct values.</p>						</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
														<img alt="" height="256" src="https://i0.wp.com/8ksec.io/wp-content/uploads/2023/07/loading_daemon.png?fit=800%2C256&amp;ssl=1" width="800" />															</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
						<p>Now that we have covered basics and showed an example of XPC server/listener and the client, let’s now use Frida to analyse a bit of some daemon on macOS.</p><p>We will create frida script that will intercept a couple of functions:</p><ul><li><p><code>xpc_connection_create_mach_service</code></p></li><li><p><code>xpc_connection_send_message</code></p></li><li><p><code>xpc_dictionary_set_string</code></p></li></ul><p>To examine the <code>xpc_object_t</code> type we can use <code>xpc_copy_description</code> which accepts <code>xpc_object_t</code> and returns the description as <code>char *</code>.</p><p>Since we went over the server/client example, we want to do the following:</p><ul><li><p>for <code>xpc_connection_create_mach_service</code> read first parameter (<code>char*</code>)</p></li><li><p><code>xpc_connection_send_message</code> has <code>xpc_object_t</code> as a second argument and we want to inspect that</p></li><li><p><code>xpc_dictionary_set_string</code> we want to inspect second and third argument as they are key and value</p></li></ul><p>We will use <code>Interceptor.attach</code> on the addresses of the function above, however we will also create <code>NativeFunction</code> using the address of <code>xpc_copy_description</code> so that we can inspect <code>xpc_object_t</code> and another <code>NativeFunction</code> using the address of <code>xpc_connection_get_name</code> to get the name of the connection. We will also create two helper function which will just read that C string (char*) and return it back to us. </p><p>The script looks like this:</p>						</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
				<div>
		<pre>
			<code>
				// Get addresses of the functions that we will intercept

var xpc_connection_create_mach_service = Module.findExportByName(null, “xpc_connection_create_mach_service”);
var xpc_connection_send_message = Module.findExportByName(null, “xpc_connection_send_message”);
var xpc_dictionary_set_string = Module.findExportByName(null, “xpc_dictionary_set_string”);

// Get address of xpc_copy_description and create new NativeFunction
// It accepts xpc_object_t and returns char *
var xpc_copy_description_addr = Module.findExportByName(null, “xpc_copy_description”);
var xpc_copy_description = new NativeFunction(xpc_copy_description_addr, “pointer”, [“pointer”]);

// Get address of xpc_connection_get_name and create new NativeFunction
// It accepts xpc_connection_t and returns char *
var xpc_connection_get_name_addr = Module.findExportByName(null, “xpc_connection_get_name”);
var xpc_connection_get_name = new NativeFunction(xpc_connection_get_name_addr, “pointer”, [“pointer”]);

// Helper function to read char *
function readCString(cstr) {
return Memory.readUtf8String(cstr);
}

/* parameters:
1. name
2. dispatch queue (not interested in this now)
3. flags (listener or client mode)
/
Interceptor.attach(xpc_connection_create_mach_service, {
onEnter(args) {
// first argument is char
name and we want to read it
var serviceName = readCString(args[0]);
console.log([*] xpc_connection_create_mach_service called for service: ${serviceName});
}
});

/* parameters:
1. connection (xpc_connection_t)
2. message (xpc_object_t)
*/
Interceptor.attach(xpc_connection_send_message, {
onEnter(args) {
var conn = args[0];
var connName = readCString(xpc_connection_get_name(conn));
var message = args[1];
var messageDescription = readCString(xpc_copy_description(message));
console.log([*] xpc_connection_send_message(name=${connName}) called for ${conn} with description: ${messageDescription});
}
});

/* parameters:
1. dictionary (xpc_object_t)
2. key (char*)
3. value (char*)
*/
Interceptor.attach(xpc_dictionary_set_string, {
onEnter(args) {
var key = readCString(args[1]);
var value = readCString(args[2]);
console.log([*] xpc_dictionary_set_string called for ${key} = ${value});
}
});







					<div>
				<div>
		<div>
							<div>
			<div>
						<p>We will run this script against Signal macOS application.</p>						</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
														<img alt="" height="732" src="https://i0.wp.com/8ksec.io/wp-content/uploads/2023/07/script_running_first.png?fit=800%2C732&amp;ssl=1" width="800" />															</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
														<img alt="" height="278" src="https://i0.wp.com/8ksec.io/wp-content/uploads/2023/07/script_running_second.png?fit=800%2C278&amp;ssl=1" width="800" />															</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
						<p>We can see that the Signal application is making a bunch of `xpc_connection_create_mach_service` function calls and sending a lot of different messages to these connections. We can go even further with this, just like the tools such as [xpcspy](<a href="https://github.com/hot3eed/xpcspy" rel="noreferrer" target="_blank">https://github.com/hot3eed/xpcspy</a>) did it and cover almost entire applications communication with XPC services.</p>						</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
						<h2>References</h2><ul><li><p><a href="https://developer.apple.com/documentation/xpc?language=objc" rel="noreferrer" target="_blank">https://developer.apple.com/documentation/xpc?language=objc</a></p></li><li><p><a href="https://github.com/hot3eed/xpcspy" rel="noreferrer" target="_blank">https://github.com/hot3eed/xpcspy</a></p></li></ul><p>&nbsp;</p>						</div>
			</div>
				</div>
	</div>
						</div>
	
			
					<div>
				<div>
		<div>
							<div>
			<div>
						<h2><strong>GET IN TOUCH</strong></h2><p>Visit our <a href="https://8ksec.io/ksec7.wpcomstaging.com/training" rel="noreferrer" target="_blank">training</a> page if you’re interested in learning more about these techniques and developing your abilities further. Additionally, you may look through our <a href="https://8ksec.io/ksec7.wpcomstaging.com/event-and-calendar/" rel="noreferrer" target="_blank">Events</a> page and sign up for our upcoming Public trainings.&nbsp;</p><p>Please don’t hesitate to reach out to us through out <a href="https://8ksec.io/ksec7.wpcomstaging.com/contact-us/" rel="noreferrer" target="_blank">Contact Us</a> page or through the Button below if you have any questions or need assistance with Penetration Testing or any other Security-related Services. We will answer in a timely manner within 1 business day.</p><p>We are always looking for talented people to join our team. Visit out <a href="https://8ksec.io/ksec7.wpcomstaging.com/careers/" rel="noreferrer" target="_blank">Careers</a> page to look at the available roles. We would love to hear from you.</p>						</div>
			</div>
				</div>
	</div>
						</div>
	
						</div><p>The post <a href="https://8ksec.io/advanced-frida-usage-part-3-inspecting-ios-xpc-calls/" rel="noreferrer" target="_blank">Advanced Frida Usage Part 3 – Inspecting XPC Calls</a> first appeared on <a href="https://8ksec.io" rel="noreferrer" target="_blank">New</a>.</p>

Article Link: https://8ksec.io/advanced-frida-usage-part-3-inspecting-ios-xpc-calls/?utm_source=rss&utm_medium=rss&utm_campaign=advanced-frida-usage-part-3-inspecting-ios-xpc-calls