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: