diff --git a/src/rpcclient/rpcclient/client.py b/src/rpcclient/rpcclient/client.py index f50f1087..bb4e9769 100644 --- a/src/rpcclient/rpcclient/client.py +++ b/src/rpcclient/rpcclient/client.py @@ -11,7 +11,7 @@ from socket import socket import IPython -from construct import Int64sl, Float64l, Float32l +from construct import Int64sl, Float64l, Float32l, Float16l from traitlets.config import Config from rpcclient.darwin.structs import pid_t, exitcode_t @@ -21,8 +21,9 @@ from rpcclient.lief import Lief from rpcclient.network import Network from rpcclient.processes import Processes -from rpcclient.protocol import protocol_message_t, cmd_type_t, exec_chunk_t, exec_chunk_type_t, UNAME_VERSION_LEN, \ - reply_protocol_message_t, dummy_block_t, SERVER_MAGIC_VERSION, argument_type_t +from rpcclient.protocol import protocol_message_t, cmd_type_t, exec_chunk_t, exec_chunk_type_t, \ + reply_protocol_message_t, dummy_block_t, SERVER_MAGIC_VERSION, argument_type_t, call_response_t, arch_t, \ + protocol_handshake_t, call_response_t_size from rpcclient.symbol import Symbol from rpcclient.symbols_jar import SymbolsJar from rpcclient.sysctl import Sysctl @@ -61,7 +62,8 @@ class Client: DEFAULT_ARGV = ['/bin/sh'] DEFAULT_ENVP = [] - def __init__(self, sock, sysname: str, hostname: str, port: int = None): + def __init__(self, sock, sysname: str, arch: arch_t, hostname: str, port: int = None): + self._arch = arch self._hostname = hostname self._port = port self._sock = sock @@ -99,6 +101,11 @@ def uname(self): """ get the utsname struct from remote """ raise NotImplementedError() + @property + def arch(self): + """ get remote arch """ + return self._arch + def dlopen(self, filename: str, mode: int) -> Symbol: """ call dlopen() at remote and return its handle. see the man page for more details. """ message = protocol_message_t.build({ @@ -131,7 +138,8 @@ def dlsym(self, lib: int, symbol_name: str): err = Int64sl.parse(self._recvall(Int64sl.sizeof())) return err - def call(self, address: int, argv: typing.List[int] = None, return_float64=False, return_float32=False) -> Symbol: + def call(self, address: int, argv: typing.List[int] = None, return_float64=False, return_float32=False, + return_float16=False, return_raw=False) -> Symbol: """ call a remote function and retrieve its return value as Symbol object """ fixed_argv = [] free_list = [] @@ -171,22 +179,33 @@ def call(self, address: int, argv: typing.List[int] = None, return_float64=False 'data': {'address': address, 'argv': fixed_argv}, }) self._sock.sendall(message) - integer_err = Int64sl.parse(self._recvall(Int64sl.sizeof())) - double_buf = self._recvall(Float64l.sizeof()) - float32_err = Float32l.parse(double_buf) - float64_err = Float64l.parse(double_buf) + response = call_response_t.parse(self._recvall(call_response_t_size)) for f in free_list: self.symbols.free(f) - if return_float32: - return float32_err + if self.arch == arch_t.ARCH_ARM64: + double_buf = Float64l.build(response.return_values.arm_registers.d[0]) + float16_err = Float16l.parse(double_buf) + float32_err = Float32l.parse(double_buf) + float64_err = response.return_values.arm_registers.d[0] + + if return_float16: + return float16_err + + if return_float32: + return float32_err + + if return_float64: + return float64_err + + if return_raw: + return response.return_values.arm_registers - if return_float64: - return float64_err + return self.symbol(response.return_values.arm_registers.x[0]) - return self.symbol(integer_err) + return self.symbol(response.return_values.return_value) def peek(self, address: int, size: int) -> bytes: """ peek data at given address """ @@ -399,12 +418,11 @@ def reconnect(self): self.close() self._sock = socket() self._sock.connect((self._hostname, self._port)) - magic = self._recvall(len(SERVER_MAGIC_VERSION)) - if magic != SERVER_MAGIC_VERSION: - raise InvalidServerVersionMagicError(f'got an invalid server magic: {magic.hex()}') + handshake = protocol_handshake_t.parse(self._recvall(protocol_handshake_t.sizeof())) - self._recvall(UNAME_VERSION_LEN) + if handshake.magic != SERVER_MAGIC_VERSION: + raise InvalidServerVersionMagicError() def _execute(self, argv: typing.List[str], envp: typing.List[str], background=False) -> int: message = protocol_message_t.build({ @@ -485,6 +503,6 @@ def _execution_loop(self, stdin: io_or_str = sys.stdin, stdout=sys.stdout): def __repr__(self): buf = f'<{self.__class__.__name__} ' buf += f'PID:{self.symbols.getpid():d} UID:{self.symbols.getuid():d} GID:{self.symbols.getgid():d} ' \ - f'SYSNAME:{self._sysname}' + f'SYSNAME:{self._sysname} ARCH:{self.arch}' buf += '>' return buf diff --git a/src/rpcclient/rpcclient/client_factory.py b/src/rpcclient/rpcclient/client_factory.py index dd1b8afe..5849da47 100644 --- a/src/rpcclient/rpcclient/client_factory.py +++ b/src/rpcclient/rpcclient/client_factory.py @@ -3,11 +3,11 @@ from rpcclient.client import Client from rpcclient.darwin.client import DarwinClient +from rpcclient.exceptions import FailedToConnectError, InvalidServerVersionMagicError from rpcclient.ios.client import IosClient from rpcclient.linux.client import LinuxClient -from rpcclient.exceptions import FailedToConnectError, InvalidServerVersionMagicError from rpcclient.macos.client import MacosClient -from rpcclient.protocol import UNAME_VERSION_LEN, DEFAULT_PORT, SERVER_MAGIC_VERSION +from rpcclient.protocol import DEFAULT_PORT, SERVER_MAGIC_VERSION, protocol_handshake_t def recvall(sock, size: int) -> bytes: @@ -29,21 +29,24 @@ def create_client(hostname: str, port: int = DEFAULT_PORT): # wrap in our own exception raise FailedToConnectError() from e - magic = recvall(sock, len(SERVER_MAGIC_VERSION)) - if magic != SERVER_MAGIC_VERSION: - raise InvalidServerVersionMagicError(f'got an invalid server magic: {magic.hex()}') + handshake = protocol_handshake_t.parse(recvall(sock, protocol_handshake_t.sizeof())) + + if handshake.magic != SERVER_MAGIC_VERSION: + raise InvalidServerVersionMagicError() + + sysname = handshake.sysname.lower() + arch = handshake.arch - sysname = recvall(sock, UNAME_VERSION_LEN).split(b'\x00', 1)[0].decode().lower() - logging.info(f'connection uname.sysname: {sysname}') + logging.info(f'connection uname.sysname: {handshake.sysname}') if sysname == 'darwin': - client = DarwinClient(sock, sysname, hostname, port) + client = DarwinClient(sock, sysname, arch, hostname, port) if client.uname.machine.startswith('iPhone'): - return IosClient(sock, sysname, hostname, port) + return IosClient(sock, sysname, arch, hostname, port) else: - return MacosClient(sock, sysname, hostname, port) + return MacosClient(sock, sysname, arch, hostname, port) elif sysname == 'linux': - return LinuxClient(sock, sysname, hostname, port) + return LinuxClient(sock, sysname, arch, hostname, port) - return Client(sock, sysname, hostname, port) + return Client(sock, sysname, arch, hostname, port) diff --git a/src/rpcclient/rpcclient/darwin/client.py b/src/rpcclient/rpcclient/darwin/client.py index 5c4cab0c..7cdeab1d 100644 --- a/src/rpcclient/rpcclient/darwin/client.py +++ b/src/rpcclient/rpcclient/darwin/client.py @@ -27,6 +27,7 @@ from rpcclient.darwin.time import Time from rpcclient.darwin.xpc import Xpc from rpcclient.exceptions import RpcClientException, MissingLibraryError, CfSerializationError +from rpcclient.protocol import arch_t from rpcclient.structs.consts import RTLD_NOW IsaMagic = namedtuple('IsaMagic', 'mask value') @@ -41,9 +42,8 @@ class DarwinClient(Client): - - def __init__(self, sock, sysname: str, hostname: str, port: int = None): - super().__init__(sock, sysname, hostname, port) + def __init__(self, sock, sysname: str, arch: arch_t, hostname: str, port: int = None): + super().__init__(sock, sysname, arch, hostname, port) self._dlsym_global_handle = -2 # RTLD_GLOBAL if 0 == self.dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_NOW): @@ -163,7 +163,7 @@ def _cf_encode_dict(self, o: object) -> DarwinSymbol: for i in range(len(cfvalues)): values_buf[i] = cfvalues[i] return self.symbols.CFDictionaryCreate( - kCFAllocatorDefault, keys_buf, values_buf, len(cfvalues), 0, 0, 0) + kCFAllocatorDefault, keys_buf, values_buf, len(cfvalues), 0, 0) def cf(self, o: object) -> DarwinSymbol: """ construct a CFObject from a given python object """ diff --git a/src/rpcclient/rpcclient/darwin/crash_reports.py b/src/rpcclient/rpcclient/darwin/crash_reports.py index 487b25e5..a6a01a5d 100644 --- a/src/rpcclient/rpcclient/darwin/crash_reports.py +++ b/src/rpcclient/rpcclient/darwin/crash_reports.py @@ -16,9 +16,7 @@ def set_symbolicated(self, enabled: bool = True): enable/disable crash reports symbolication https://github.com/dlevi309/Symbolicator """ - with self._client.sc.open( - '/var/root/Library/Preferences/com.apple.CrashReporter.plist') as pref: - pref.set_dict({'SymbolicateCrashes': enabled}) + self._client.preferences.cf.set('SymbolicateCrashes', enabled, 'com.apple.CrashReporter', 'root') def list(self, prefixed='') -> List[CrashReport]: """ get a list of all crash reports as CrashReport parsed objects """ diff --git a/src/rpcclient/rpcclient/darwin/symbol.py b/src/rpcclient/rpcclient/darwin/symbol.py index 06d9dd94..14173af8 100644 --- a/src/rpcclient/rpcclient/darwin/symbol.py +++ b/src/rpcclient/rpcclient/darwin/symbol.py @@ -3,13 +3,13 @@ class DarwinSymbol(Symbol): - def objc_call(self, selector, *params): + def objc_call(self, selector, *params, **kwargs): """ call an objc method on a given object """ sel = self._client.symbols.sel_getUid(selector) if not self._client.symbols.objc_msgSend(self, self._client.symbols.sel_getUid("respondsToSelector:"), sel): raise UnrecognizedSelectorError(f"unrecognized selector '{selector}' sent to class") - return self._client.symbols.objc_msgSend(self, sel, *params) + return self._client.symbols.objc_msgSend(self, sel, *params, **kwargs) @property def cfdesc(self): diff --git a/src/rpcclient/rpcclient/ios/client.py b/src/rpcclient/rpcclient/ios/client.py index d7ff9b03..f1039d61 100644 --- a/src/rpcclient/rpcclient/ios/client.py +++ b/src/rpcclient/rpcclient/ios/client.py @@ -5,19 +5,22 @@ from rpcclient.ios.backlight import Backlight from rpcclient.ios.lockdown import Lockdown from rpcclient.ios.mobile_gestalt import MobileGestalt +from rpcclient.ios.screen_capture import ScreenCapture from rpcclient.ios.telephony import Telephony +from rpcclient.protocol import arch_t CRASH_REPORTS_DIR = 'Library/Logs/CrashReporter' class IosClient(DarwinClient): - def __init__(self, sock, sysname: str, hostname: str, port: int = None): - super().__init__(sock, sysname, hostname, port) + def __init__(self, sock, sysname: str, arch: arch_t, hostname: str, port: int = None): + super().__init__(sock, sysname, arch, hostname, port) self.backlight = Backlight(self) self.reports = Reports(self, CRASH_REPORTS_DIR) self.mobile_gestalt = MobileGestalt(self) self.lockdown = Lockdown(self) self.telephony = Telephony(self) + self.screen_capture = ScreenCapture(self) @property def roots(self) -> typing.List[str]: diff --git a/src/rpcclient/rpcclient/ios/screen_capture.py b/src/rpcclient/rpcclient/ios/screen_capture.py new file mode 100644 index 00000000..c96ac5b2 --- /dev/null +++ b/src/rpcclient/rpcclient/ios/screen_capture.py @@ -0,0 +1,25 @@ +from collections import namedtuple + +from rpcclient.darwin.symbol import DarwinSymbol + +CGRect = namedtuple('CGRect', 'x0 y0 x1 y1') + + +class ScreenCapture: + """ monitor screen events """ + + def __init__(self, client): + self._client = client + + @property + def main_display(self) -> DarwinSymbol: + return self._client.symbols.objc_getClass('CADisplay').objc_call('mainDisplay') + + @property + def bounds(self) -> CGRect: + d = self.main_display.objc_call('bounds', return_raw=True).d + return CGRect(x0=d[0], y0=d[1], x1=d[2], y1=d[3]) + + @property + def screenshot(self) -> bytes: + return self._client.symbols.UIImagePNGRepresentation(self._client.symbols._UICreateScreenUIImage()).py diff --git a/src/rpcclient/rpcclient/linux/client.py b/src/rpcclient/rpcclient/linux/client.py index 1cb64cc9..2fe3df61 100644 --- a/src/rpcclient/rpcclient/linux/client.py +++ b/src/rpcclient/rpcclient/linux/client.py @@ -3,11 +3,12 @@ from rpcclient.client import Client from rpcclient.linux.fs import LinuxFs from rpcclient.linux.structs import utsname +from rpcclient.protocol import arch_t class LinuxClient(Client): - def __init__(self, sock, uname_version: str, hostname: str, port: int = None): - super().__init__(sock, uname_version, hostname, port) + def __init__(self, sock, sysname: str, arch: arch_t, hostname: str, port: int = None): + super().__init__(sock, sysname, arch, hostname, port) self.fs = LinuxFs(self) @cached_property diff --git a/src/rpcclient/rpcclient/macos/client.py b/src/rpcclient/rpcclient/macos/client.py index 2c21bc3a..c219049f 100644 --- a/src/rpcclient/rpcclient/macos/client.py +++ b/src/rpcclient/rpcclient/macos/client.py @@ -2,14 +2,15 @@ from rpcclient.darwin.client import DarwinClient from rpcclient.darwin.reports import Reports +from rpcclient.protocol import arch_t CRASH_REPORTS_DIR = 'Library/Logs/DiagnosticReports' class MacosClient(DarwinClient): - def __init__(self, sock, sysname: str, hostname: str, port: int = None): - super().__init__(sock, sysname, hostname, port) + def __init__(self, sock, sysname: str, arch: arch_t, hostname: str, port: int = None): + super().__init__(sock, sysname, arch, hostname, port) self.reports = Reports(self, CRASH_REPORTS_DIR) @property diff --git a/src/rpcclient/rpcclient/protocol.py b/src/rpcclient/rpcclient/protocol.py index c4f11119..61a61149 100644 --- a/src/rpcclient/rpcclient/protocol.py +++ b/src/rpcclient/rpcclient/protocol.py @@ -1,5 +1,5 @@ from construct import Struct, Int32ul, PrefixedArray, Const, Enum, this, PascalString, Switch, PaddedString, Bytes, \ - Int64ul, Int8ul, IfThenElse, Float64l + Int64ul, Int8ul, IfThenElse, Float64l, Array, Union cmd_type_t = Enum(Int32ul, CMD_EXEC=0, @@ -15,11 +15,23 @@ CMD_CLOSE=10, CMD_REPLY_POKE=11, ) + +arch_t = Enum(Int32ul, + ARCH_UNKNOWN=0, + ARCH_ARM64=1, + ) + + DEFAULT_PORT = 5910 -SERVER_MAGIC_VERSION = Int32ul.build(0x88888800) +SERVER_MAGIC_VERSION = 0x88888801 MAGIC = 0x12345678 MAX_PATH_LEN = 1024 -UNAME_VERSION_LEN = 256 + +protocol_handshake_t = Struct( + 'magic' / Int32ul, + 'arch' / arch_t, + 'sysname' / PaddedString(256, 'utf8'), +) cmd_exec_t = Struct( 'background' / Int8ul, @@ -95,4 +107,18 @@ 'size' / Int32ul, ) +return_registers_arm_t = Struct( + 'x' / Array(8, Int64ul), + 'd' / Array(8, Float64l), +) + +call_response_t_size = 128 + +call_response_t = Struct( + 'return_values' / Union(None, + 'arm_registers' / return_registers_arm_t, + 'return_value' / Int64ul, + ), +) + dummy_block_t = Int64ul diff --git a/src/rpcserver/ents.plist b/src/rpcserver/ents.plist index f7a268af..c68543ec 100644 --- a/src/rpcserver/ents.plist +++ b/src/rpcserver/ents.plist @@ -42,6 +42,7 @@ kTCCServiceCamera kTCCServiceLocation kTCCServiceBluetoothPeripheral + kTCCServiceScreenCapture com.apple.private.icfcallserver @@ -63,5 +64,15 @@ voice spi + com.apple.QuartzCore.global-capture + + com.apple.QuartzCore.get-client-port + + com.apple.accessibility.api + + com.apple.security.iokit-user-client-class + + IOSurfaceRootUserClient + diff --git a/src/rpcserver/rpcserver.c b/src/rpcserver/rpcserver.c index 008bac2c..60ecf2c7 100644 --- a/src/rpcserver/rpcserver.c +++ b/src/rpcserver/rpcserver.c @@ -1,7 +1,7 @@ #ifndef __APPLE__ #define _XOPEN_SOURCE (600) #define _GNU_SOURCE (1) -#endif // __APPLE__ +#endif // __APPLE__ #include #include #include @@ -32,6 +32,7 @@ #include "common.h" +#define HANDSHAKE_SYSNAME_LEN (256) #define DEFAULT_PORT ("5910") #define DEFAULT_SHELL ("/bin/sh") #define USAGE ("Usage: %s [-p port] [-o (stdout|syslog|file:filename)] \n\ @@ -40,14 +41,13 @@ \n\ Example usage: \n\ %s -p 5910 -o syslog -o stdout -o file:/tmp/log.txt\n") -#define SERVER_MAGIC_VERSION (0x88888800) +#define SERVER_MAGIC_VERSION (0x88888801) #define MAGIC (0x12345678) #define MAX_CONNECTIONS (1024) #define MAX_PATH_LEN (1024) #define MAX_OPTION_LEN (256) #define BUFFERSIZE (64 * 1024) -#define UNAME_VERSION_LEN (256) #define INVALID_PID (0xffffffff) extern char **environ; @@ -74,6 +74,19 @@ typedef enum CMD_EXEC_CHUNK_TYPE_EXITCODE = 1, } cmd_exec_chunk_type_t; +typedef enum +{ + ARCH_UNKNOWN = 0, + ARCH_ARM64 = 1, +} arch_t; + +typedef struct +{ + u32 magic; + u32 arch; // arch_t + char sysname[HANDSHAKE_SYSNAME_LEN]; +} protocol_handshake_t; + typedef struct { u32 type; @@ -129,6 +142,21 @@ typedef struct u32 cmd_type; } protocol_message_t; +typedef struct +{ + u64 x[8]; + u64 d[8]; +} return_registers_arm_t; + +typedef struct +{ + union + { + return_registers_arm_t arm_registers; + u64 return_value; + } return_values; +} call_response_t; + void *get_in_addr(struct sockaddr *sa) // get sockaddr, IPv4 or IPv6: { return sa->sa_family == AF_INET ? (void *)&(((struct sockaddr_in *)sa)->sin_addr) : (void *)&(((struct sockaddr_in6 *)sa)->sin6_addr); @@ -214,7 +242,8 @@ bool send_reply(int sockfd, cmd_type_t type) return false; } -typedef struct { +typedef struct +{ int sockfd; pid_t pid; } thread_notify_client_spawn_error_t; @@ -290,7 +319,7 @@ bool handle_exec(int sockfd) if (background) { - CHECK(0 == pthread_create(&thread, NULL, (void * (*)(void *))thread_waitpid, (void *)(intptr_t)pid)); + CHECK(0 == pthread_create(&thread, NULL, (void *(*)(void *))thread_waitpid, (void *)(intptr_t)pid)); } else { @@ -348,11 +377,11 @@ bool handle_exec(int sockfd) TRACE("wait for process to finish"); s32 error; CHECK(pid == waitpid(pid, &error, 0)); - + cmd_exec_chunk_t chunk; chunk.type = CMD_EXEC_CHUNK_TYPE_EXITCODE; chunk.size = sizeof(error); - + CHECK(sendall(sockfd, (const char *)&chunk, sizeof(chunk))); CHECK(sendall(sockfd, (const char *)&error, sizeof(error))); } @@ -459,9 +488,9 @@ bool handle_dlsym(int sockfd) #ifdef __ARM_ARCH_ISA_A64 bool call_function(int sockfd, intptr_t address, size_t argc, argument_t **p_argv); __asm__( -"_call_function:\n" + "_call_function:\n" // the "stack_arguments" must be the first local ([sp, 0]) to serialize stack arguments - // the 0x100 is enough to store 0x100/8 = 32 stack arguments which should be enough for + // the 0x100 is enough to store 0x100/8 = 32 stack arguments which should be enough for // every function ".set stack_arguments, 0\n" ".set result, stack_arguments+0x100\n" @@ -469,9 +498,28 @@ __asm__( ".set argc, address+0x08\n" ".set argv, argc+0x08\n" ".set sockfd, argv+0x08\n" - ".set err_integer, sockfd+0x08\n" - ".set err_double, err_integer+0x08\n" - ".set size, err_double\n" + + ".set register_x0, sockfd+0x08\n" + ".set register_x1, register_x0+0x08\n" + ".set register_x2, register_x1+0x08\n" + ".set register_x3, register_x2+0x08\n" + ".set register_x4, register_x3+0x08\n" + ".set register_x5, register_x4+0x08\n" + ".set register_x6, register_x5+0x08\n" + ".set register_x7, register_x6+0x08\n" + + ".set register_d0, register_x7+0x08\n" + ".set register_d1, register_d0+0x08\n" + ".set register_d2, register_d1+0x08\n" + ".set register_d3, register_d2+0x08\n" + ".set register_d4, register_d3+0x08\n" + ".set register_d5, register_d4+0x08\n" + ".set register_d6, register_d5+0x08\n" + ".set register_d7, register_d6+0x08\n" + + ".set register_end, register_d7+0x08\n" + + ".set size, register_end+0x08\n" // backup registers x19 -> x30 = 8*12 bytes = 0x60 bytes // according to arm abi, the stack is structured as follows: @@ -533,7 +581,7 @@ __asm__( // else { // -- double argument - + // x20 = argument.value "ldr x20, [x19]\n" "add x19, x19, 8\n" @@ -568,7 +616,7 @@ __asm__( // if (integer_offset*8 >= MAX_INT_REG*8) goto 7 "cmp x21, 8 * 8\n" "bge 7f\n" - + // 5[integer_offset]() "adr x25, 5f\n" "add x25, x25, x21\n" @@ -587,13 +635,29 @@ __asm__( // err.integer, err.double = address(params) "ldr x19, [sp, address]\n" "blr x19\n" - "str x0, [sp, err_integer]\n" - "str d0, [sp, err_double]\n" - // if (!sendall(sockfd, &err, 0x10)) goto 4; + "str x0, [sp, register_x0]\n" + "str x1, [sp, register_x1]\n" + "str x2, [sp, register_x2]\n" + "str x3, [sp, register_x3]\n" + "str x4, [sp, register_x4]\n" + "str x5, [sp, register_x5]\n" + "str x6, [sp, register_x6]\n" + "str x7, [sp, register_x7]\n" + + "str d0, [sp, register_d0]\n" + "str d1, [sp, register_d1]\n" + "str d2, [sp, register_d2]\n" + "str d3, [sp, register_d3]\n" + "str d4, [sp, register_d4]\n" + "str d5, [sp, register_d5]\n" + "str d6, [sp, register_d6]\n" + "str d7, [sp, register_d7]\n" + + // if (!sendall(sockfd, &err, register_end - register_x0)) goto 4; "ldr x0, [sp, sockfd]\n" - "add x1, sp, err_integer\n" - "mov x2, 0x10\n" + "add x1, sp, register_x0\n" + "mov x2, register_end - register_x0\n" "bl _sendall\n" "cmp x0, 0\n" "beq 4f\n" @@ -602,7 +666,7 @@ __asm__( "mov x0, 1\n" "str x0, [sp, result]\n" -"4:\n" + "4:\n" // return result "ldr x0, [sp, result]\n" "add sp, sp, size\n" @@ -667,8 +731,7 @@ __asm__( // stack_offset += 8 "add x26, x26, 8\n" - "b 1b\n" -); + "b 1b\n"); #else bool call_function(int sockfd, intptr_t address, size_t argc, argument_t **p_argv) @@ -733,18 +796,17 @@ bool call_function(int sockfd, intptr_t address, size_t argc, argument_t **p_arg break; } - CHECK(sendall(sockfd, (char *)&err, sizeof(err))); - - // return double isn't supported - err = 0; - CHECK(sendall(sockfd, (char *)&err, sizeof(err))); + call_response_t response = {0}; + response.return_values.return_value = err; + + CHECK(sendall(sockfd, (char *)&response, sizeof(response))); result = true; error: return result; } -#endif // __ARM_ARCH +#endif // __ARM_ARCH_ISA_A64 bool handle_call(int sockfd) { @@ -843,7 +905,7 @@ bool handle_poke(int sockfd) CHECK(recvall(sockfd, (char *)&cmd, sizeof(cmd))); CHECK(recvall(sockfd, (char *)cmd.address, cmd.size)); CHECK(send_reply(sockfd, CMD_REPLY_POKE)); -#endif // __APPLE__ +#endif // __APPLE__ success = true; @@ -859,7 +921,7 @@ bool handle_poke(int sockfd) return success; } -#if __APPLE__ +#if __APPLE__ void (^dummy_block)(void) = ^{ }; @@ -887,14 +949,19 @@ void handle_client(int sockfd) bool disconnected = false; TRACE("enter. fd: %d", sockfd); - // send MAGIC - u32 magic = SERVER_MAGIC_VERSION; - CHECK(sendall(sockfd, (const char *)&magic, sizeof(magic))); - - // notify client of the connected target os version struct utsname uname_buf; CHECK(0 == uname(&uname_buf)); - CHECK(sendall(sockfd, uname_buf.sysname, UNAME_VERSION_LEN)); + + protocol_handshake_t handshake = {0}; + handshake.magic = SERVER_MAGIC_VERSION; + handshake.arch = ARCH_UNKNOWN; + strncpy(handshake.sysname, uname_buf.sysname, HANDSHAKE_SYSNAME_LEN - 1); + +#ifdef __ARM_ARCH_ISA_A64 + handshake.arch = ARCH_ARM64; +#endif + + CHECK(sendall(sockfd, (char *)&handshake, sizeof(handshake))); while (true) { @@ -1045,8 +1112,8 @@ int main(int argc, const char *argv[]) pthread_t thread; #ifdef __APPLE__ - CHECK(0 == pthread_create(&thread, NULL, (void * (*)(void *))CFRunLoopRun, NULL)); -#endif // __APPLE__ + CHECK(0 == pthread_create(&thread, NULL, (void *(*)(void *))CFRunLoopRun, NULL)); +#endif // __APPLE__ while (1) { @@ -1060,7 +1127,7 @@ int main(int argc, const char *argv[]) CHECK(inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), ipstr, sizeof(ipstr))); TRACE("Got a connection from %s [%d]", ipstr, client_fd); - CHECK(0 == pthread_create(&thread, NULL, (void * (*)(void *))handle_client, (void *)(long)client_fd)); + CHECK(0 == pthread_create(&thread, NULL, (void *(*)(void *))handle_client, (void *)(long)client_fd)); } error: