Skip to content

Commit

Permalink
XPC: Add sending XPC message to Darwin client.
Browse files Browse the repository at this point in the history
  • Loading branch information
matan1008 committed Feb 28, 2022
1 parent abeeb13 commit 01e12d4
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/rpcclient/rpcclient/darwin/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from rpcclient.darwin.processes import DarwinProcesses
from rpcclient.darwin.structs import utsname
from rpcclient.darwin.symbol import DarwinSymbol
from rpcclient.darwin.xpc import Xpc
from rpcclient.exceptions import RpcClientException, MissingLibraryError
from rpcclient.structs.consts import RTLD_NOW

Expand Down Expand Up @@ -62,6 +63,7 @@ def __init__(self, sock, sysname: str, hostname: str, port: int = None):
self.network = DarwinNetwork(self)
self.ioregistry = IORegistry(self)
self.location = Location(self)
self.xpc = Xpc(self)

@property
def modules(self) -> typing.List[str]:
Expand Down
43 changes: 43 additions & 0 deletions src/rpcclient/rpcclient/darwin/xpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from functools import lru_cache


class Xpc:
def __init__(self, client):
"""
:param rpcclient.darwin.client.DarwinClient client:
"""
self._client = client

def send_message(self, service_name, message):
"""
Send message to a service and return result.
"""
message_raw = self.to_xpc_object(message)
assert message_raw != 0
response = self.send_message_raw(service_name, message_raw)
assert response != 0
return self.from_xpc_object(response)

def from_xpc_object(self, address):
"""
Convert XPC object to python object.
"""
return self._client.symbols._CFXPCCreateCFObjectFromXPCObject(address).py

def to_xpc_object(self, obj):
"""
Convert python object to XPC object.
"""
return self._client.symbols._CFXPCCreateXPCObjectFromCFObject(self._client.cf(obj))

def send_message_raw(self, service_name, message_raw):
conn = self._connect_to_mach_service(service_name)
return self._client.symbols.xpc_connection_send_message_with_reply_sync(conn, message_raw)

@lru_cache(maxsize=None)
def _connect_to_mach_service(self, service_name):
conn = self._client.symbols.xpc_connection_create_mach_service(service_name, 0, 0)
assert conn != 0, 'failed to create xpc connection'
self._client.symbols.xpc_connection_set_event_handler(conn, self._client.get_dummy_block())
self._client.symbols.xpc_connection_resume(conn)
return conn
13 changes: 13 additions & 0 deletions src/rpcclient/tests/test_xpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pytest


@pytest.mark.darwin
def test_from_xpc_object(client):
"""
:param rpcclient.darwin.client.DarwinClient client:
"""
criteria = client.symbols.xpc_dictionary_create(0, 0, 0)
client.symbols.xpc_dictionary_set_int64(criteria, 'Delay', 5)
client.symbols.xpc_dictionary_set_int64(criteria, 'GracePeriod', 1)
client.symbols.xpc_dictionary_set_string(criteria, 'Priority', 'Utility')
assert client.xpc.from_xpc_object(criteria) == {'Delay': 5, 'Priority': 'Utility', 'GracePeriod': 1}

0 comments on commit 01e12d4

Please sign in to comment.