mirror of
https://github.com/frida/frida-core.git
synced 2026-11-11 10:01:27 -10:00
Compare commits
No files matched your search
@@ -44,7 +44,7 @@ jobs:
|
||||
if: matrix.id == 'linux-x86'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-multilib lib32stdc++-11-dev
|
||||
sudo apt-get install gcc-multilib lib32stdc++-13-dev
|
||||
- name: Build
|
||||
if: ${{ startsWith(matrix.id, 'windows-') }}
|
||||
run: |
|
||||
@@ -249,7 +249,7 @@ jobs:
|
||||
check-linux-helpers:
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86, x86_64, arm, arm64, mips, mipsel, mips64, mips64el]
|
||||
arch: [x86, x86_64, arm, armbe8, arm64, arm64be, arm64beilp32, mips, mipsel, mips64, mips64el]
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/frida/core-linux-helpers-${{ matrix.arch }}:latest
|
||||
steps:
|
||||
|
||||
@@ -204,6 +204,13 @@ namespace Frida {
|
||||
return peek_scope ().get_object<Darwin.Xpc.UInt64> (Darwin.Xpc.UInt64.TYPE).get_value ();
|
||||
}
|
||||
|
||||
public unowned uint8[] get_data_value () throws Error {
|
||||
var data = peek_scope ().get_object<Darwin.Xpc.Data> (Darwin.Xpc.Data.TYPE);
|
||||
unowned uint8[] buf = (uint8[]) data.get_bytes_ptr ();
|
||||
buf.length = (int) data.get_length ();
|
||||
return buf;
|
||||
}
|
||||
|
||||
public unowned string get_string_value () throws Error {
|
||||
return peek_scope ().get_object<Darwin.Xpc.String> (Darwin.Xpc.String.TYPE).get_string_ptr ();
|
||||
}
|
||||
|
||||
+1
-1
Submodule releng updated: f45bc3e00f...2eecc41cbe.
+51
-8
@@ -3,6 +3,7 @@ namespace Frida.Server {
|
||||
|
||||
private const string DEFAULT_DIRECTORY = "re.frida.server";
|
||||
private static bool output_version = false;
|
||||
private static string? device_id = null;
|
||||
private static string? listen_address = null;
|
||||
private static string? certpath = null;
|
||||
private static string? origin = null;
|
||||
@@ -30,6 +31,7 @@ namespace Frida.Server {
|
||||
|
||||
const OptionEntry[] option_entries = {
|
||||
{ "version", 0, 0, OptionArg.NONE, ref output_version, "Output version information and exit", null },
|
||||
{ "device", 0, 0, OptionArg.STRING, ref device_id, "Serve device with the given ID", "ID" },
|
||||
{ "listen", 'l', 0, OptionArg.STRING, ref listen_address, "Listen on ADDRESS", "ADDRESS" },
|
||||
{ "certificate", 0, 0, OptionArg.FILENAME, ref certpath, "Enable TLS using CERTIFICATE", "CERTIFICATE" },
|
||||
{ "origin", 0, 0, OptionArg.STRING, ref origin, "Only accept requests with “Origin” header matching ORIGIN " +
|
||||
@@ -178,7 +180,7 @@ namespace Frida.Server {
|
||||
|
||||
#if DARWIN
|
||||
var worker = new Thread<int> ("frida-server-main-loop", () => {
|
||||
var exit_code = run_application (endpoint_params, options, on_ready);
|
||||
var exit_code = run_application (device_id, endpoint_params, options, on_ready);
|
||||
|
||||
_stop_run_loop ();
|
||||
|
||||
@@ -190,15 +192,16 @@ namespace Frida.Server {
|
||||
|
||||
return exit_code;
|
||||
#else
|
||||
return run_application (endpoint_params, options, on_ready);
|
||||
return run_application (device_id, endpoint_params, options, on_ready);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static int run_application (EndpointParameters endpoint_params, ControlServiceOptions options, ReadyHandler on_ready) {
|
||||
private static int run_application (string? device_id, EndpointParameters endpoint_params, ControlServiceOptions options,
|
||||
ReadyHandler on_ready) {
|
||||
TemporaryDirectory.always_use ((directory != null) ? directory : DEFAULT_DIRECTORY);
|
||||
TemporaryDirectory.use_sysroot (options.sysroot);
|
||||
|
||||
application = new Application (new ControlService (endpoint_params, options));
|
||||
application = new Application (device_id, endpoint_params, options);
|
||||
|
||||
Posix.signal (Posix.Signal.INT, (sig) => {
|
||||
application.stop ();
|
||||
@@ -235,19 +238,36 @@ namespace Frida.Server {
|
||||
private class Application : Object {
|
||||
public signal void ready (bool success);
|
||||
|
||||
public ControlService service {
|
||||
public string? device_id {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public EndpointParameters endpoint_params {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public ControlServiceOptions options {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private DeviceManager? manager;
|
||||
private ControlService? service;
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
private MainLoop loop = new MainLoop ();
|
||||
private int exit_code;
|
||||
private bool stopping;
|
||||
|
||||
public Application (ControlService service) {
|
||||
Object (service: service);
|
||||
public Application (string? device_id, EndpointParameters endpoint_params, ControlServiceOptions options) {
|
||||
Object (
|
||||
device_id: device_id,
|
||||
endpoint_params: endpoint_params,
|
||||
options: options
|
||||
);
|
||||
}
|
||||
|
||||
public int run () {
|
||||
@@ -265,6 +285,17 @@ namespace Frida.Server {
|
||||
|
||||
private async void start () {
|
||||
try {
|
||||
if (device_id != null && device_id != "local") {
|
||||
manager = new DeviceManager.with_nonlocal_backends_only ();
|
||||
|
||||
var device = yield manager.get_device_by_id (device_id, 0, io_cancellable);
|
||||
device.lost.connect (on_device_lost);
|
||||
|
||||
service = yield new ControlService.with_device (device, endpoint_params, options);
|
||||
} else {
|
||||
service = new ControlService (endpoint_params, options);
|
||||
}
|
||||
|
||||
yield service.start (io_cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
if (e is IOError.CANCELLED)
|
||||
@@ -297,7 +328,15 @@ namespace Frida.Server {
|
||||
io_cancellable.cancel ();
|
||||
|
||||
try {
|
||||
yield service.stop ();
|
||||
if (service != null) {
|
||||
yield service.stop ();
|
||||
service = null;
|
||||
}
|
||||
|
||||
if (manager != null) {
|
||||
yield manager.close ();
|
||||
manager = null;
|
||||
}
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
|
||||
@@ -306,6 +345,10 @@ namespace Frida.Server {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private void on_device_lost () {
|
||||
stop ();
|
||||
}
|
||||
}
|
||||
|
||||
private TlsCertificate? parse_certificate (string? path) throws GLib.Error {
|
||||
|
||||
Generated
+7
-7
@@ -17,7 +17,7 @@
|
||||
"@rollup/plugin-node-resolve": "^14.1.0",
|
||||
"@rollup/plugin-replace": "^4.0.0",
|
||||
"@rollup/plugin-typescript": "^8.3.4",
|
||||
"@types/frida-gum": "18.7.2",
|
||||
"@types/frida-gum": "18.8.1",
|
||||
"@types/glob": "^8.0.0",
|
||||
"@types/node": "18.7.23",
|
||||
"glob": "^8.0.3",
|
||||
@@ -468,9 +468,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/frida-gum": {
|
||||
"version": "18.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.7.2.tgz",
|
||||
"integrity": "sha512-nOxTk8n45nQlFQhSSXcnePrzjw6k6JMJMESZ8HlHhUiIQqvGI4RYa69FYdUbGoBRnITn8srEq5vn0dkVwO/ezQ==",
|
||||
"version": "18.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.8.1.tgz",
|
||||
"integrity": "sha512-FhlHORjaw43QbNYIyj5Ji7iYSvk7t5nPiC+GuYDVndqc1bFheeAs88b1odp8HhmpQUrrYVU90wapapKVLlmJHg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -1466,9 +1466,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/frida-gum": {
|
||||
"version": "18.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.7.2.tgz",
|
||||
"integrity": "sha512-nOxTk8n45nQlFQhSSXcnePrzjw6k6JMJMESZ8HlHhUiIQqvGI4RYa69FYdUbGoBRnITn8srEq5vn0dkVwO/ezQ==",
|
||||
"version": "18.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.8.1.tgz",
|
||||
"integrity": "sha512-FhlHORjaw43QbNYIyj5Ji7iYSvk7t5nPiC+GuYDVndqc1bFheeAs88b1odp8HhmpQUrrYVU90wapapKVLlmJHg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/glob": {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"@rollup/plugin-node-resolve": "^14.1.0",
|
||||
"@rollup/plugin-replace": "^4.0.0",
|
||||
"@rollup/plugin-typescript": "^8.3.4",
|
||||
"@types/frida-gum": "18.7.2",
|
||||
"@types/frida-gum": "18.8.1",
|
||||
"@types/glob": "^8.0.0",
|
||||
"@types/node": "18.7.23",
|
||||
"glob": "^8.0.3",
|
||||
|
||||
@@ -66,6 +66,20 @@ namespace Frida {
|
||||
assign_session (session);
|
||||
}
|
||||
|
||||
public async ControlService.with_device (Device device, EndpointParameters endpoint_params,
|
||||
ControlServiceOptions? options = null, Cancellable? cancellable = null) throws Error, IOError {
|
||||
ControlServiceOptions opts = (options != null) ? options : new ControlServiceOptions ();
|
||||
|
||||
var session = yield device.get_host_session (cancellable);
|
||||
|
||||
Object (
|
||||
endpoint_params: endpoint_params,
|
||||
options: opts
|
||||
);
|
||||
|
||||
assign_session (session);
|
||||
}
|
||||
|
||||
internal ControlService.with_host_session (HostSession host_session, EndpointParameters endpoint_params,
|
||||
ControlServiceOptions? options = null) {
|
||||
Object (
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
# define CORE_FOUNDATION "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
|
||||
#endif
|
||||
|
||||
typedef struct _FridaHelperContext FridaHelperContext;
|
||||
typedef struct _FridaDispatchContext FridaDispatchContext;
|
||||
typedef struct _FridaSpawnInstance FridaSpawnInstance;
|
||||
typedef guint FridaDyldFlavor;
|
||||
typedef struct _FridaSpawnInstanceDyldData FridaSpawnInstanceDyldData;
|
||||
@@ -106,7 +106,7 @@ typedef union _FridaDebugState FridaDebugState;
|
||||
typedef int FridaConvertThreadStateDirection;
|
||||
typedef guint FridaAslr;
|
||||
|
||||
struct _FridaHelperContext
|
||||
struct _FridaDispatchContext
|
||||
{
|
||||
dispatch_queue_t dispatch_queue;
|
||||
};
|
||||
@@ -376,7 +376,7 @@ enum _FridaAslr
|
||||
};
|
||||
|
||||
static FridaSpawnInstance * frida_spawn_instance_new (FridaDarwinHelperBackend * backend);
|
||||
static void frida_spawn_instance_free (FridaSpawnInstance * instance);
|
||||
static void frida_spawn_instance_close (FridaSpawnInstance * instance);
|
||||
static void frida_spawn_instance_resume (FridaSpawnInstance * self);
|
||||
|
||||
static void frida_spawn_instance_on_server_cancel (void * context);
|
||||
@@ -410,7 +410,7 @@ static void frida_configure_terminal_attributes (gint fd);
|
||||
|
||||
static FridaInjectInstance * frida_inject_instance_new (FridaDarwinHelperBackend * backend, guint id, guint pid);
|
||||
static FridaInjectInstance * frida_inject_instance_clone (const FridaInjectInstance * instance, guint id);
|
||||
static void frida_inject_instance_free (FridaInjectInstance * instance);
|
||||
static void frida_inject_instance_close (FridaInjectInstance * instance);
|
||||
static gboolean frida_inject_instance_task_did_not_exec (FridaInjectInstance * instance);
|
||||
|
||||
static gboolean frida_inject_instance_start_thread (FridaInjectInstance * self, GError ** error);
|
||||
@@ -762,30 +762,30 @@ permission_denied:
|
||||
}
|
||||
|
||||
void
|
||||
_frida_darwin_helper_backend_create_context (FridaDarwinHelperBackend * self)
|
||||
_frida_darwin_helper_backend_create_dispatch_context (FridaDarwinHelperBackend * self)
|
||||
{
|
||||
FridaHelperContext * ctx;
|
||||
FridaDispatchContext * ctx;
|
||||
|
||||
ctx = g_slice_new (FridaHelperContext);
|
||||
ctx = g_slice_new (FridaDispatchContext);
|
||||
ctx->dispatch_queue = dispatch_queue_create ("re.frida.helper.queue", DISPATCH_QUEUE_SERIAL);
|
||||
|
||||
self->context = ctx;
|
||||
self->dispatch_context = ctx;
|
||||
}
|
||||
|
||||
void
|
||||
_frida_darwin_helper_backend_destroy_context (FridaDarwinHelperBackend * self)
|
||||
_frida_darwin_helper_backend_destroy_dispatch_context (FridaDarwinHelperBackend * self)
|
||||
{
|
||||
FridaHelperContext * ctx = self->context;
|
||||
FridaDispatchContext * ctx = self->dispatch_context;
|
||||
|
||||
dispatch_release (ctx->dispatch_queue);
|
||||
|
||||
g_slice_free (FridaHelperContext, ctx);
|
||||
g_slice_free (FridaDispatchContext, ctx);
|
||||
}
|
||||
|
||||
void
|
||||
_frida_darwin_helper_backend_schedule_on_dispatch_queue (FridaDarwinHelperBackend * self, FridaDarwinHelperBackendDispatchWorker worker, gpointer user_data)
|
||||
{
|
||||
FridaHelperContext * ctx = self->context;
|
||||
FridaDispatchContext * ctx = self->dispatch_context;
|
||||
|
||||
dispatch_async (ctx->dispatch_queue, ^
|
||||
{
|
||||
@@ -934,7 +934,7 @@ any_failure:
|
||||
{
|
||||
if (instance->pid != 0)
|
||||
kill (instance->pid, SIGKILL);
|
||||
frida_spawn_instance_free (instance);
|
||||
frida_spawn_instance_close (instance);
|
||||
|
||||
pid = 0;
|
||||
|
||||
@@ -1869,7 +1869,7 @@ void
|
||||
_frida_darwin_helper_backend_prepare_spawn_instance_for_injection (FridaDarwinHelperBackend * self, void * opaque_instance, guint task, GError ** error)
|
||||
{
|
||||
FridaSpawnInstance * instance = opaque_instance;
|
||||
FridaHelperContext * ctx = self->context;
|
||||
FridaDispatchContext * ctx = self->dispatch_context;
|
||||
const gchar * failed_operation;
|
||||
kern_return_t kr;
|
||||
mach_port_t self_task, child_thread;
|
||||
@@ -2200,9 +2200,9 @@ _frida_darwin_helper_backend_resume_spawn_instance (FridaDarwinHelperBackend * s
|
||||
}
|
||||
|
||||
void
|
||||
_frida_darwin_helper_backend_free_spawn_instance (FridaDarwinHelperBackend * self, void * instance)
|
||||
_frida_darwin_helper_backend_close_spawn_instance (FridaDarwinHelperBackend * self, void * instance)
|
||||
{
|
||||
frida_spawn_instance_free (instance);
|
||||
frida_spawn_instance_close (instance);
|
||||
}
|
||||
|
||||
guint
|
||||
@@ -2489,7 +2489,7 @@ mach_failure:
|
||||
}
|
||||
failure:
|
||||
{
|
||||
frida_inject_instance_free (instance);
|
||||
frida_inject_instance_close (instance);
|
||||
goto beach;
|
||||
}
|
||||
beach:
|
||||
@@ -2599,7 +2599,7 @@ frida_inject_instance_start_thread (FridaInjectInstance * self, GError ** error)
|
||||
mach_msg_type_number_t thread_state_count;
|
||||
kern_return_t kr;
|
||||
const gchar * failed_operation;
|
||||
FridaHelperContext * ctx = self->backend->context;
|
||||
FridaDispatchContext * ctx = self->backend->dispatch_context;
|
||||
dispatch_source_t source;
|
||||
|
||||
thread_state = g_alloca (self->thread_state_count * sizeof (natural_t));
|
||||
@@ -2646,7 +2646,7 @@ frida_inject_instance_on_thread_monitor_cancel (void * context)
|
||||
FridaInjectInstance * self = context;
|
||||
|
||||
dispatch_release (g_steal_pointer (&self->thread_monitor_source));
|
||||
frida_inject_instance_free (self);
|
||||
frida_inject_instance_close (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2705,7 +2705,7 @@ _frida_darwin_helper_backend_join_inject_instance_posix_thread (FridaDarwinHelpe
|
||||
static void
|
||||
frida_inject_instance_join_posix_thread (FridaInjectInstance * self, mach_port_t posix_thread)
|
||||
{
|
||||
FridaHelperContext * ctx = self->backend->context;
|
||||
FridaDispatchContext * ctx = self->backend->dispatch_context;
|
||||
mach_port_t self_task;
|
||||
dispatch_source_t source;
|
||||
|
||||
@@ -2738,9 +2738,9 @@ _frida_darwin_helper_backend_get_pid_of_inject_instance (FridaDarwinHelperBacken
|
||||
}
|
||||
|
||||
void
|
||||
_frida_darwin_helper_backend_free_inject_instance (FridaDarwinHelperBackend * self, void * instance)
|
||||
_frida_darwin_helper_backend_close_inject_instance (FridaDarwinHelperBackend * self, void * instance)
|
||||
{
|
||||
frida_inject_instance_free (instance);
|
||||
frida_inject_instance_close (instance);
|
||||
}
|
||||
|
||||
static FridaSpawnInstance *
|
||||
@@ -2750,7 +2750,7 @@ frida_spawn_instance_new (FridaDarwinHelperBackend * backend)
|
||||
guint i;
|
||||
|
||||
instance = g_slice_new0 (FridaSpawnInstance);
|
||||
instance->backend = backend;
|
||||
instance->backend = g_object_ref (backend);
|
||||
instance->thread = MACH_PORT_NULL;
|
||||
|
||||
instance->server_port = MACH_PORT_NULL;
|
||||
@@ -2773,11 +2773,13 @@ frida_spawn_instance_new (FridaDarwinHelperBackend * backend)
|
||||
instance->page_pool[i].scratch_page = 0;
|
||||
}
|
||||
|
||||
_frida_darwin_helper_backend_on_instance_created (backend, instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void
|
||||
frida_spawn_instance_free (FridaSpawnInstance * instance)
|
||||
frida_spawn_instance_close (FridaSpawnInstance * instance)
|
||||
{
|
||||
task_t self_task;
|
||||
FridaExceptionPortSet * previous_ports;
|
||||
@@ -2816,6 +2818,9 @@ frida_spawn_instance_free (FridaSpawnInstance * instance)
|
||||
if (instance->dyld != NULL)
|
||||
g_object_unref (instance->dyld);
|
||||
|
||||
_frida_darwin_helper_backend_on_instance_destroyed (instance->backend, instance);
|
||||
g_object_unref (instance->backend);
|
||||
|
||||
g_slice_free (FridaSpawnInstance, instance);
|
||||
}
|
||||
|
||||
@@ -2858,7 +2863,7 @@ frida_spawn_instance_on_server_cancel (void * context)
|
||||
FridaSpawnInstance * self = context;
|
||||
|
||||
dispatch_release (g_steal_pointer (&self->server_recv_source));
|
||||
frida_spawn_instance_free (self);
|
||||
frida_spawn_instance_close (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4114,6 +4119,8 @@ frida_inject_instance_new (FridaDarwinHelperBackend * backend, guint id, guint p
|
||||
|
||||
instance->backend = g_object_ref (backend);
|
||||
|
||||
_frida_darwin_helper_backend_on_instance_created (backend, instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -4143,11 +4150,13 @@ frida_inject_instance_clone (const FridaInjectInstance * instance, guint id)
|
||||
|
||||
g_object_ref (clone->backend);
|
||||
|
||||
_frida_darwin_helper_backend_on_instance_created (clone->backend, clone);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
static void
|
||||
frida_inject_instance_free (FridaInjectInstance * instance)
|
||||
frida_inject_instance_close (FridaInjectInstance * instance)
|
||||
{
|
||||
FridaAgentContext * agent_context = instance->agent_context;
|
||||
task_t self_task;
|
||||
@@ -4187,6 +4196,7 @@ frida_inject_instance_free (FridaInjectInstance * instance)
|
||||
if (instance->task != MACH_PORT_NULL)
|
||||
mach_port_deallocate (self_task, instance->task);
|
||||
|
||||
_frida_darwin_helper_backend_on_instance_destroyed (instance->backend, instance);
|
||||
g_object_unref (instance->backend);
|
||||
|
||||
g_slice_free (FridaInjectInstance, instance);
|
||||
@@ -4292,6 +4302,7 @@ frida_agent_context_init (FridaAgentContext * self, const FridaAgentDetails * de
|
||||
static gboolean
|
||||
frida_agent_context_init_functions (FridaAgentContext * self, GumDarwinModuleResolver * resolver, GumDarwinMapper * mapper, GError ** error)
|
||||
{
|
||||
gboolean success = FALSE;
|
||||
GumDarwinModule * module;
|
||||
|
||||
module = gum_darwin_module_resolver_find_module_by_name (resolver, "/usr/lib/system/libsystem_kernel.dylib");
|
||||
@@ -4303,6 +4314,8 @@ frida_agent_context_init_functions (FridaAgentContext * self, GumDarwinModuleRes
|
||||
FRIDA_AGENT_CONTEXT_RESOLVE (mach_msg_receive);
|
||||
FRIDA_AGENT_CONTEXT_RESOLVE (mach_port_destroy);
|
||||
FRIDA_AGENT_CONTEXT_RESOLVE (thread_terminate);
|
||||
g_object_unref (module);
|
||||
module = NULL;
|
||||
|
||||
module = gum_darwin_module_resolver_find_module_by_name (resolver, "/usr/lib/system/libsystem_pthread.dylib");
|
||||
if (module == NULL)
|
||||
@@ -4315,6 +4328,8 @@ frida_agent_context_init_functions (FridaAgentContext * self, GumDarwinModuleRes
|
||||
FRIDA_AGENT_CONTEXT_TRY_RESOLVE (pthread_threadid_np);
|
||||
FRIDA_AGENT_CONTEXT_RESOLVE (pthread_detach);
|
||||
FRIDA_AGENT_CONTEXT_RESOLVE (pthread_self);
|
||||
g_object_unref (module);
|
||||
module = NULL;
|
||||
|
||||
if (mapper == NULL)
|
||||
{
|
||||
@@ -4324,9 +4339,12 @@ frida_agent_context_init_functions (FridaAgentContext * self, GumDarwinModuleRes
|
||||
FRIDA_AGENT_CONTEXT_RESOLVE (dlopen);
|
||||
FRIDA_AGENT_CONTEXT_RESOLVE (dlsym);
|
||||
FRIDA_AGENT_CONTEXT_RESOLVE (dlclose);
|
||||
g_object_unref (module);
|
||||
module = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
success = TRUE;
|
||||
goto beach;
|
||||
|
||||
no_libc:
|
||||
{
|
||||
@@ -4334,7 +4352,7 @@ no_libc:
|
||||
FRIDA_ERROR,
|
||||
FRIDA_ERROR_NOT_SUPPORTED,
|
||||
"Unable to attach to processes without Apple's libc (for now)");
|
||||
goto failure;
|
||||
goto beach;
|
||||
}
|
||||
missing_symbol:
|
||||
{
|
||||
@@ -4342,11 +4360,13 @@ missing_symbol:
|
||||
FRIDA_ERROR,
|
||||
FRIDA_ERROR_NOT_SUPPORTED,
|
||||
"Unexpected error while resolving functions");
|
||||
goto failure;
|
||||
goto beach;
|
||||
}
|
||||
failure:
|
||||
beach:
|
||||
{
|
||||
return FALSE;
|
||||
g_clear_object (&module);
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace Frida {
|
||||
protected delegate void DispatchWorker ();
|
||||
protected delegate void LaunchCompletionHandler (owned StdioPipes? pipes, owned Error? error);
|
||||
|
||||
public void * context;
|
||||
private MainContext main_context;
|
||||
public void * dispatch_context;
|
||||
|
||||
public Gee.HashMap<uint, void *> spawn_instances = new Gee.HashMap<uint, void *> ();
|
||||
private Gee.HashMap<uint, OutputStream> stdin_streams = new Gee.HashMap<uint, OutputStream> ();
|
||||
@@ -32,6 +33,9 @@ namespace Frida {
|
||||
private Gee.HashMap<void *, uint> inject_cleaner_by_instance = new Gee.HashMap<void *, uint> ();
|
||||
private Gee.HashMap<uint, uint> inject_expiry_timers = new Gee.HashMap<uint, uint> ();
|
||||
|
||||
private Gee.Set<void *> instances = new Gee.HashSet<void *> ();
|
||||
private SourceFunc? on_last_instance_destroyed = null;
|
||||
|
||||
public uint next_id = 1;
|
||||
|
||||
private PolicySoftener policy_softener;
|
||||
@@ -40,7 +44,8 @@ namespace Frida {
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
construct {
|
||||
_create_context ();
|
||||
main_context = MainContext.ref_thread_default ();
|
||||
_create_dispatch_context ();
|
||||
|
||||
dtrace_agent = DTraceAgent.try_open ();
|
||||
if (dtrace_agent != null) {
|
||||
@@ -63,11 +68,7 @@ namespace Frida {
|
||||
}
|
||||
|
||||
~DarwinHelperBackend () {
|
||||
foreach (var instance in spawn_instances.values)
|
||||
_free_spawn_instance (instance);
|
||||
foreach (var instance in inject_instances.values)
|
||||
_free_inject_instance (instance);
|
||||
_destroy_context ();
|
||||
_destroy_dispatch_context ();
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
@@ -77,11 +78,24 @@ namespace Frida {
|
||||
pending.complete ();
|
||||
|
||||
foreach (var entry in inject_cleaner_by_instance.entries) {
|
||||
_free_inject_instance (entry.key);
|
||||
_close_inject_instance (entry.key);
|
||||
Source.remove (entry.value);
|
||||
}
|
||||
inject_cleaner_by_instance.clear ();
|
||||
|
||||
foreach (var instance in spawn_instances.values)
|
||||
_close_spawn_instance (instance);
|
||||
spawn_instances.clear ();
|
||||
|
||||
bool any_pending = false;
|
||||
lock (instances) {
|
||||
any_pending = !instances.is_empty;
|
||||
if (any_pending)
|
||||
on_last_instance_destroyed = close.callback;
|
||||
}
|
||||
if (any_pending)
|
||||
yield;
|
||||
|
||||
if (dtrace_agent != null) {
|
||||
dtrace_agent.spawn_added.disconnect (on_dtrace_agent_spawn_added);
|
||||
dtrace_agent.spawn_removed.disconnect (on_dtrace_agent_spawn_removed);
|
||||
@@ -139,11 +153,11 @@ namespace Frida {
|
||||
Error error = null;
|
||||
|
||||
_launch (identifier, options, (p, e) => {
|
||||
Idle.add (() => {
|
||||
schedule_on_frida_thread (() => {
|
||||
pipes = p;
|
||||
error = e;
|
||||
launch.callback ();
|
||||
return false;
|
||||
return Source.REMOVE;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -187,7 +201,7 @@ namespace Frida {
|
||||
inject_cleaner_by_instance.unset (instance, out source_id);
|
||||
Source.remove (source_id);
|
||||
|
||||
_free_inject_instance (instance);
|
||||
_close_inject_instance (instance);
|
||||
}
|
||||
|
||||
policy_softener.forget (pid);
|
||||
@@ -205,7 +219,7 @@ namespace Frida {
|
||||
|
||||
void * instance;
|
||||
if (spawn_instances.unset (pid, out instance))
|
||||
_free_spawn_instance (instance);
|
||||
_close_spawn_instance (instance);
|
||||
|
||||
child_dead (pid);
|
||||
}
|
||||
@@ -293,7 +307,7 @@ namespace Frida {
|
||||
void * instance;
|
||||
if (spawn_instances.unset (pid, out instance)) {
|
||||
_resume_spawn_instance (instance);
|
||||
_free_spawn_instance (instance);
|
||||
_close_spawn_instance (instance);
|
||||
} else {
|
||||
resume_with_validation (pid);
|
||||
}
|
||||
@@ -412,7 +426,7 @@ namespace Frida {
|
||||
} catch (GLib.Error e) {
|
||||
if (instance_created_here) {
|
||||
spawn_instances.unset (pid);
|
||||
_free_spawn_instance (spawn_instance);
|
||||
_close_spawn_instance (spawn_instance);
|
||||
}
|
||||
|
||||
throw_api_error (e);
|
||||
@@ -495,21 +509,21 @@ namespace Frida {
|
||||
}
|
||||
|
||||
public void _on_spawn_instance_ready (uint pid) {
|
||||
Idle.add (() => {
|
||||
schedule_on_frida_thread (() => {
|
||||
spawn_instance_ready (pid);
|
||||
return false;
|
||||
return Source.REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
public void _on_spawn_instance_error (uint pid, Error error) {
|
||||
Idle.add (() => {
|
||||
schedule_on_frida_thread (() => {
|
||||
spawn_instance_error (pid, error);
|
||||
return false;
|
||||
return Source.REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
public void _on_mach_thread_dead (uint id, void * posix_thread) {
|
||||
Idle.add (() => {
|
||||
schedule_on_frida_thread (() => {
|
||||
var instance = inject_instances[id];
|
||||
assert (instance != null);
|
||||
|
||||
@@ -518,14 +532,14 @@ namespace Frida {
|
||||
else
|
||||
_destroy_inject_instance (id);
|
||||
|
||||
return false;
|
||||
return Source.REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
public void _on_posix_thread_dead (uint id) {
|
||||
Idle.add (() => {
|
||||
schedule_on_frida_thread (() => {
|
||||
_destroy_inject_instance (id);
|
||||
return false;
|
||||
return Source.REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -545,7 +559,7 @@ namespace Frida {
|
||||
private void schedule_inject_instance_cleanup (void * instance) {
|
||||
var cleanup_source = new TimeoutSource (50);
|
||||
cleanup_source.set_callback (() => {
|
||||
_free_inject_instance (instance);
|
||||
_close_inject_instance (instance);
|
||||
|
||||
var removed = inject_cleaner_by_instance.unset (instance);
|
||||
assert (removed);
|
||||
@@ -601,6 +615,19 @@ namespace Frida {
|
||||
policy_softener.forget (pid);
|
||||
}
|
||||
|
||||
public void _on_instance_created (void * instance) {
|
||||
lock (instances)
|
||||
instances.add (instance);
|
||||
}
|
||||
|
||||
public void _on_instance_destroyed (void * instance) {
|
||||
lock (instances) {
|
||||
instances.remove (instance);
|
||||
if (on_last_instance_destroyed != null && instances.is_empty)
|
||||
schedule_on_frida_thread ((owned) on_last_instance_destroyed);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_dtrace_agent_spawn_added (HostSpawnInfo info) {
|
||||
spawn_added (info);
|
||||
}
|
||||
@@ -611,11 +638,17 @@ namespace Frida {
|
||||
|
||||
private async void flush_dispatch_queue () {
|
||||
_schedule_on_dispatch_queue (() => {
|
||||
Idle.add (flush_dispatch_queue.callback);
|
||||
schedule_on_frida_thread (flush_dispatch_queue.callback);
|
||||
});
|
||||
yield;
|
||||
}
|
||||
|
||||
private void schedule_on_frida_thread (owned SourceFunc function) {
|
||||
var source = new IdleSource ();
|
||||
source.set_callback ((owned) function);
|
||||
source.attach (main_context);
|
||||
}
|
||||
|
||||
public extern static PipeEndpoints make_pipe_endpoints (uint local_task, uint remote_pid, uint remote_task) throws Error;
|
||||
public extern static void make_pipe_endpoint_from_socket (uint pid, uint task, GLib.Socket sock, out string address)
|
||||
throws Error;
|
||||
@@ -626,8 +659,8 @@ namespace Frida {
|
||||
public extern static bool is_mmap_available ();
|
||||
public extern static MappedLibraryBlob mmap (uint task, Bytes blob) throws Error;
|
||||
|
||||
protected extern void _create_context ();
|
||||
protected extern void _destroy_context ();
|
||||
protected extern void _create_dispatch_context ();
|
||||
protected extern void _destroy_dispatch_context ();
|
||||
protected extern void _schedule_on_dispatch_queue (DispatchWorker worker);
|
||||
|
||||
protected extern uint _spawn (string path, HostSpawnOptions options, out StdioPipes? pipes) throws Error;
|
||||
@@ -642,7 +675,7 @@ namespace Frida {
|
||||
protected extern void * _create_spawn_instance (uint pid);
|
||||
protected extern void _prepare_spawn_instance_for_injection (void * instance, uint task) throws Error;
|
||||
protected extern void _resume_spawn_instance (void * instance);
|
||||
protected extern void _free_spawn_instance (void * instance);
|
||||
protected extern void _close_spawn_instance (void * instance);
|
||||
|
||||
protected extern uint _inject_into_task (uint pid, uint task, string path_or_name, MappedLibraryBlob? blob, string entrypoint, string data) throws Error;
|
||||
protected extern void _demonitor (void * instance);
|
||||
@@ -650,7 +683,7 @@ namespace Frida {
|
||||
protected extern void _recreate_injectee_thread (void * instance, uint pid, uint task) throws Error;
|
||||
protected extern void _join_inject_instance_posix_thread (void * instance, void * posix_thread);
|
||||
protected extern uint _get_pid_of_inject_instance (void * instance);
|
||||
protected extern void _free_inject_instance (void * instance);
|
||||
protected extern void _close_inject_instance (void * instance);
|
||||
}
|
||||
|
||||
public class DTraceAgent : Object {
|
||||
|
||||
@@ -791,7 +791,7 @@ namespace Frida.Droidy {
|
||||
}
|
||||
|
||||
private const uint16 ADB_SERVER_DEFAULT_PORT = 5037;
|
||||
private const uint16 MAX_MESSAGE_LENGTH = 1024;
|
||||
private const size_t MAX_MESSAGE_LENGTH = 65536;
|
||||
|
||||
public static async Client open (Cancellable? cancellable = null) throws Error, IOError {
|
||||
SocketConnectable? connectable = null;
|
||||
|
||||
+13
-2
@@ -34,12 +34,24 @@ namespace Frida {
|
||||
private Promise<bool> start_request;
|
||||
private Promise<bool> stop_request;
|
||||
|
||||
private HostSessionService service = null;
|
||||
private HostSessionService service;
|
||||
private Gee.ArrayList<Device> devices = new Gee.ArrayList<Device> ();
|
||||
private Gee.ArrayList<DeviceObserverEntry> on_device_added = new Gee.ArrayList<DeviceObserverEntry> ();
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
public DeviceManager () {
|
||||
service = new HostSessionService.with_default_backends ();
|
||||
}
|
||||
|
||||
public DeviceManager.with_nonlocal_backends_only () {
|
||||
service = new HostSessionService.with_nonlocal_backends_only ();
|
||||
}
|
||||
|
||||
public DeviceManager.with_socket_backend_only () {
|
||||
service = new HostSessionService.with_socket_backend_only ();
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable = null) throws IOError {
|
||||
yield stop_service (cancellable);
|
||||
}
|
||||
@@ -340,7 +352,6 @@ namespace Frida {
|
||||
}
|
||||
|
||||
private async void start_service () {
|
||||
service = new HostSessionService.with_default_backends ();
|
||||
try {
|
||||
service.provider_available.connect (on_provider_available);
|
||||
service.provider_unavailable.connect (on_provider_unavailable);
|
||||
|
||||
@@ -177,12 +177,14 @@ namespace Frida.Fruity {
|
||||
Linux.Network.IfAddrs ifaddrs;
|
||||
Linux.Network.getifaddrs (out ifaddrs);
|
||||
for (unowned Linux.Network.IfAddrs candidate = ifaddrs; candidate != null; candidate = candidate.ifa_next) {
|
||||
unowned Posix.SockAddr? address = candidate.ifa_addr;
|
||||
if (address == null || address.sa_family != Posix.AF_INET6)
|
||||
continue;
|
||||
|
||||
if (candidate.ifa_name != ifname)
|
||||
continue;
|
||||
if (candidate.ifa_addr.sa_family != Posix.AF_INET6)
|
||||
continue;
|
||||
return (InetSocketAddress)
|
||||
SocketAddress.from_native ((void *) candidate.ifa_addr, sizeof (Posix.SockAddrIn6));
|
||||
|
||||
return (InetSocketAddress) SocketAddress.from_native ((void *) address, sizeof (Posix.SockAddrIn6));
|
||||
}
|
||||
|
||||
throw new Error.NOT_SUPPORTED ("Unable to resolve interface address");
|
||||
|
||||
@@ -129,6 +129,7 @@ namespace Frida.Fruity {
|
||||
private ConnectionType _connection_type;
|
||||
private string _udid;
|
||||
private string _name;
|
||||
private Bytes? _remote_unlock_host_key;
|
||||
|
||||
private Promise<Tunnel>? tunnel_request;
|
||||
|
||||
@@ -153,6 +154,13 @@ namespace Frida.Fruity {
|
||||
var reader = new XpcObjectReader (device_info);
|
||||
_name = reader.read_member ("name").get_string_value ();
|
||||
reader.end_member ();
|
||||
|
||||
if (reader.has_member ("remoteUnlockHostKey")) {
|
||||
_remote_unlock_host_key = new Bytes (reader.read_member ("remoteUnlockHostKey").get_data_value ());
|
||||
reader.end_member ();
|
||||
} else {
|
||||
_remote_unlock_host_key = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void on_state_changed (Object obj, ParamSpec pspec) {
|
||||
@@ -224,7 +232,7 @@ namespace Frida.Fruity {
|
||||
tunnel_request = new Promise<Tunnel> ();
|
||||
|
||||
try {
|
||||
var tunnel = new MacOSTunnel (pairing_device);
|
||||
var tunnel = new MacOSTunnel (pairing_device, _remote_unlock_host_key);
|
||||
yield tunnel.attach (cancellable);
|
||||
|
||||
tunnel_request.resolve (tunnel);
|
||||
@@ -252,6 +260,12 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public Bytes? remote_unlock_host_key {
|
||||
get {
|
||||
return _remote_unlock_host_key;
|
||||
}
|
||||
}
|
||||
|
||||
public Darwin.Xpc.Uuid? assertion_identifier {
|
||||
get {
|
||||
return _assertion_identifier;
|
||||
@@ -259,13 +273,15 @@ namespace Frida.Fruity {
|
||||
}
|
||||
|
||||
private XpcClient pairing_device;
|
||||
private Bytes? _remote_unlock_host_key;
|
||||
private Darwin.Xpc.Uuid? _assertion_identifier;
|
||||
private InetAddress? tunnel_device_address;
|
||||
private DiscoveryService? _discovery;
|
||||
private int64 _opened_at = -1;
|
||||
|
||||
public MacOSTunnel (XpcClient pairing_device) {
|
||||
public MacOSTunnel (XpcClient pairing_device, Bytes? remote_unlock_host_key) {
|
||||
this.pairing_device = pairing_device;
|
||||
_remote_unlock_host_key = remote_unlock_host_key;
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
|
||||
@@ -188,6 +188,18 @@ namespace Frida.Fruity {
|
||||
new Gee.ArrayQueue<UsbmuxLockdownServiceRequest> ();
|
||||
private LockdownClient? cached_usbmux_lockdown_client;
|
||||
|
||||
private const string[] LOCKDOWN_SERVICES_WITHOUT_ESCROW_BAG_SUPPORT = {
|
||||
"com.apple.accessibility.axAuditDaemon.remoteserver",
|
||||
"com.apple.afc",
|
||||
"com.apple.companion_proxy",
|
||||
"com.apple.crashreportcopymobile",
|
||||
"com.apple.GPUTools.MobileService",
|
||||
"com.apple.idamd",
|
||||
"com.apple.PurpleReverseProxy.Conn",
|
||||
"com.apple.streaming_zip_conduit",
|
||||
"com.apple.webinspector",
|
||||
};
|
||||
|
||||
internal void close () {
|
||||
transports.clear ();
|
||||
}
|
||||
@@ -247,6 +259,9 @@ namespace Frida.Fruity {
|
||||
checkin.set_string ("Request", "RSDCheckin");
|
||||
checkin.set_string ("Label", "Xcode");
|
||||
checkin.set_string ("ProtocolVersion", "2");
|
||||
unowned Bytes? key = tunnel.remote_unlock_host_key;
|
||||
if (key != null && lockdown_service_supports_escrow_bag (service_name))
|
||||
checkin.set_bytes ("EscrowBag", key);
|
||||
|
||||
try {
|
||||
yield service.query (checkin, cancellable);
|
||||
@@ -283,6 +298,15 @@ namespace Frida.Fruity {
|
||||
return yield request.promise.future.wait_async (cancellable);
|
||||
}
|
||||
|
||||
// FIXME: Replace with `element in array`-check once Vala compiler bug has been fixed so generated C code is warning-free.
|
||||
private static bool lockdown_service_supports_escrow_bag (string name) {
|
||||
foreach (unowned string s in LOCKDOWN_SERVICES_WITHOUT_ESCROW_BAG_SUPPORT) {
|
||||
if (s == name)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private async void process_usbmux_lockdown_service_requests () {
|
||||
UsbmuxLockdownServiceRequest? req;
|
||||
bool already_invalidated = false;
|
||||
@@ -496,6 +520,10 @@ namespace Frida.Fruity {
|
||||
get;
|
||||
}
|
||||
|
||||
public abstract Bytes? remote_unlock_host_key {
|
||||
get;
|
||||
}
|
||||
|
||||
public abstract async void close (Cancellable? cancellable) throws IOError;
|
||||
public abstract async IOStream open_tcp_connection (uint16 port, Cancellable? cancellable) throws Error, IOError;
|
||||
}
|
||||
@@ -1002,6 +1030,11 @@ namespace Frida.Fruity {
|
||||
}
|
||||
|
||||
unowned string udid = usb_device.udid;
|
||||
|
||||
// iPhones before iOS 17 on Windows are sometimes misdetected with an empty udid -> skip those devices
|
||||
if (udid.length == 0)
|
||||
return;
|
||||
|
||||
var transport = usb_transports.first_match (t => t.udid == udid);
|
||||
|
||||
bool may_need_time_to_settle = state != STARTING && (transport == null || transport.modeswitch_in_progress);
|
||||
@@ -1454,13 +1487,15 @@ namespace Frida.Fruity {
|
||||
Linux.Network.IfAddrs ifaddrs;
|
||||
Linux.Network.getifaddrs (out ifaddrs);
|
||||
for (unowned Linux.Network.IfAddrs candidate = ifaddrs; candidate != null; candidate = candidate.ifa_next) {
|
||||
if (candidate.ifa_addr.sa_family != Posix.AF_INET6)
|
||||
unowned Posix.SockAddr? address = candidate.ifa_addr;
|
||||
if (address == null || address.sa_family != Posix.AF_INET6)
|
||||
continue;
|
||||
|
||||
if (!ncm_interfaces.contains (candidate.ifa_name))
|
||||
continue;
|
||||
|
||||
device_ifaddrs.add ((InetSocketAddress) SocketAddress.from_native ((void *) candidate.ifa_addr, sizeof (Posix.SockAddrIn6)));
|
||||
device_ifaddrs.add ((InetSocketAddress) SocketAddress.from_native ((void *) address,
|
||||
sizeof (Posix.SockAddrIn6)));
|
||||
}
|
||||
if (device_ifaddrs.is_empty && !ncm_interfaces.is_empty)
|
||||
throw new Error.NOT_SUPPORTED ("no IPv6 address on NCM network interface");
|
||||
@@ -1675,10 +1710,17 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public Bytes? remote_unlock_host_key {
|
||||
get {
|
||||
return _remote_unlock_host_key;
|
||||
}
|
||||
}
|
||||
|
||||
private UsbNcmDriver? ncm;
|
||||
private TunnelConnection? tunnel_connection;
|
||||
private DiscoveryService? _discovery_service;
|
||||
private int64 _opened_at = -1;
|
||||
private Bytes? _remote_unlock_host_key;
|
||||
|
||||
public PortableUsbTunnel (UsbDevice device, NcmPeer peer, PairingStore store) {
|
||||
Object (
|
||||
@@ -1707,11 +1749,11 @@ namespace Frida.Fruity {
|
||||
);
|
||||
var pairing_transport = new XpcPairingTransport (yield netstack.open_tcp_connection (tunnel_endpoint, cancellable));
|
||||
var pairing_service = yield PairingService.open (pairing_transport, pairing_store, cancellable);
|
||||
|
||||
TunnelConnection tc = yield pairing_service.open_tunnel (ncm_peer.ip, netstack, cancellable);
|
||||
tc.closed.connect (on_tunnel_connection_close);
|
||||
|
||||
_opened_at = get_monotonic_time ();
|
||||
_remote_unlock_host_key = pairing_service.established_peer.remote_unlock_host_key;
|
||||
|
||||
var rsd_endpoint = (InetSocketAddress) Object.new (typeof (InetSocketAddress),
|
||||
address: tc.remote_address,
|
||||
@@ -1880,9 +1922,16 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public Bytes? remote_unlock_host_key {
|
||||
get {
|
||||
return _remote_unlock_host_key;
|
||||
}
|
||||
}
|
||||
|
||||
private TunnelConnection? tunnel_connection;
|
||||
private DiscoveryService? _discovery_service;
|
||||
private int64 _opened_at = -1;
|
||||
private Bytes? _remote_unlock_host_key;
|
||||
|
||||
private const uint PAIRING_CONNECTION_TIMEOUT = 2000;
|
||||
|
||||
@@ -1905,6 +1954,7 @@ namespace Frida.Fruity {
|
||||
TunnelConnection tc = yield pairing_service.open_tunnel (endpoint.get_address (), netstack, cancellable);
|
||||
|
||||
_opened_at = get_monotonic_time ();
|
||||
_remote_unlock_host_key = pairing_service.established_peer.remote_unlock_host_key;
|
||||
|
||||
var rsd_endpoint = (InetSocketAddress) Object.new (typeof (InetSocketAddress),
|
||||
address: tc.remote_address,
|
||||
|
||||
+148
-15
@@ -146,6 +146,11 @@ namespace Frida.Fruity {
|
||||
private set;
|
||||
}
|
||||
|
||||
public PairingPeer? established_peer {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private Gee.Map<uint64?, Promise<ObjectReader>> requests =
|
||||
new Gee.HashMap<uint64?, Promise<ObjectReader>> (Numeric.uint64_hash, Numeric.uint64_equal);
|
||||
private uint64 next_control_sequence_number = 0;
|
||||
@@ -181,15 +186,35 @@ namespace Frida.Fruity {
|
||||
|
||||
yield attempt_pair_verify (cancellable);
|
||||
|
||||
Bytes? shared_key = yield verify_manual_pairing (cancellable);
|
||||
if (shared_key == null) {
|
||||
PairingPeer? peer = yield verify_manual_pairing (cancellable);
|
||||
if (peer == null) {
|
||||
if (!device_options.allows_pair_setup)
|
||||
throw new Error.NOT_SUPPORTED ("Device not paired and pairing not allowed on current transport");
|
||||
shared_key = yield setup_manual_pairing (cancellable);
|
||||
peer = yield setup_manual_pairing (cancellable);
|
||||
}
|
||||
|
||||
client_cipher = new ChaCha20Poly1305 (derive_chacha_key (shared_key, "ClientEncrypt-main"));
|
||||
server_cipher = new ChaCha20Poly1305 (derive_chacha_key (shared_key, "ServerEncrypt-main"));
|
||||
if (peer.remote_unlock_host_key == null) {
|
||||
bool peer_modified = false;
|
||||
try {
|
||||
peer.remote_unlock_host_key = yield create_remote_unlock_key (cancellable);
|
||||
peer_modified = true;
|
||||
} catch (Error e) {
|
||||
if (e is Error.INVALID_OPERATION) {
|
||||
store.forget_peer (peer);
|
||||
throw e;
|
||||
}
|
||||
if (!(e is Error.NOT_SUPPORTED))
|
||||
throw e;
|
||||
}
|
||||
if (peer_modified) {
|
||||
try {
|
||||
store.save_peer (peer);
|
||||
} catch (Error e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
established_peer = peer;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -377,7 +402,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
private async Bytes? verify_manual_pairing (Cancellable? cancellable) throws Error, IOError {
|
||||
private async PairingPeer? verify_manual_pairing (Cancellable? cancellable) throws Error, IOError {
|
||||
Key host_keypair = make_keypair (X25519);
|
||||
uint8[] raw_host_pubkey = get_raw_public_key (host_keypair).get_data ();
|
||||
|
||||
@@ -414,10 +439,18 @@ namespace Frida.Fruity {
|
||||
|
||||
var cipher = new ChaCha20Poly1305 (operation_key);
|
||||
|
||||
// TODO: Verify signature using peer's public key.
|
||||
/* var start_inner_response = */ new VariantReader (PairingParamsParser.parse (cipher.decrypt (
|
||||
var start_inner_response = new VariantReader (PairingParamsParser.parse (cipher.decrypt (
|
||||
new Bytes.static ("\x00\x00\x00\x00PV-Msg02".data[:12]),
|
||||
start_response.read_member ("encrypted-data").get_data_value ())));
|
||||
string peer_identifier = start_inner_response
|
||||
.read_member ("identifier")
|
||||
.get_uuid_value ();
|
||||
PairingPeer? peer = store.find_peer_by_identifier (peer_identifier);
|
||||
if (peer == null) {
|
||||
yield notify_pair_verify_failed (cancellable);
|
||||
return null;
|
||||
}
|
||||
// TODO: Verify signature using peer's public key.
|
||||
|
||||
unowned string host_identifier = store.self_identity.identifier;
|
||||
|
||||
@@ -457,7 +490,9 @@ namespace Frida.Fruity {
|
||||
return null;
|
||||
}
|
||||
|
||||
return shared_key;
|
||||
setup_main_encryption_keys (shared_key);
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
private async void notify_pair_verify_failed (Cancellable? cancellable) throws Error, IOError {
|
||||
@@ -476,7 +511,7 @@ namespace Frida.Fruity {
|
||||
.build (), cancellable);
|
||||
}
|
||||
|
||||
private async Bytes setup_manual_pairing (Cancellable? cancellable) throws Error, IOError {
|
||||
private async PairingPeer setup_manual_pairing (Cancellable? cancellable) throws Error, IOError {
|
||||
Bytes start_params = new PairingParamsBuilder ()
|
||||
.add_method (0)
|
||||
.add_state (1)
|
||||
@@ -612,9 +647,78 @@ namespace Frida.Fruity {
|
||||
inner_finish_response.end_member ();
|
||||
Bytes peer_info = inner_finish_response.read_member ("info").get_data_value ();
|
||||
inner_finish_response.end_member ();
|
||||
store.add_peer (peer_identifier, peer_pubkey, peer_info);
|
||||
|
||||
return shared_key;
|
||||
PairingPeer peer = store.add_peer (peer_identifier, peer_pubkey, peer_info);
|
||||
|
||||
setup_main_encryption_keys (shared_key);
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
private async Bytes? create_remote_unlock_key (Cancellable? cancellable) throws Error, IOError {
|
||||
string request = Json.to_string (
|
||||
new Json.Builder ()
|
||||
.begin_object ()
|
||||
.set_member_name ("request")
|
||||
.begin_object ()
|
||||
.set_member_name ("_0")
|
||||
.begin_object ()
|
||||
.set_member_name ("createRemoteUnlockKey")
|
||||
.begin_object ()
|
||||
.end_object ()
|
||||
.end_object ()
|
||||
.end_object ()
|
||||
.end_object ()
|
||||
.get_root (), false);
|
||||
|
||||
string response = yield request_encrypted (request, cancellable);
|
||||
|
||||
Json.Reader reader;
|
||||
try {
|
||||
reader = new Json.Reader (Json.from_string (response));
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.PROTOCOL ("Invalid createRemoteUnlockKey response JSON");
|
||||
}
|
||||
|
||||
reader.read_member ("response");
|
||||
reader.read_member ("_1");
|
||||
|
||||
if (reader.read_member ("errorExtended")) {
|
||||
reader.read_member ("_0");
|
||||
|
||||
reader.read_member ("domain");
|
||||
unowned string? domain = reader.get_string_value ();
|
||||
reader.end_member ();
|
||||
|
||||
reader.read_member ("code");
|
||||
int64 code = reader.get_int_value ();
|
||||
reader.end_member ();
|
||||
|
||||
reader.read_member ("userInfo");
|
||||
reader.read_member ("NSLocalizedDescription");
|
||||
unowned string? description = reader.get_string_value ();
|
||||
|
||||
if (domain == null || description == null)
|
||||
throw new Error.PROTOCOL ("Invalid createRemoteUnlockKey error response");
|
||||
|
||||
if (domain == "com.apple.CoreDevice.ControlChannelConnectionError" && code == 2)
|
||||
throw new Error.INVALID_OPERATION ("%s", description);
|
||||
|
||||
throw new Error.NOT_SUPPORTED ("%s", description);
|
||||
}
|
||||
reader.end_member ();
|
||||
|
||||
reader.read_member ("createRemoteUnlockKey");
|
||||
reader.read_member ("hostKey");
|
||||
unowned string? key = reader.get_string_value ();
|
||||
if (key == null)
|
||||
throw new Error.PROTOCOL ("Malformed createRemoteUnlockKey response");
|
||||
return new Bytes (Base64.decode (key));
|
||||
}
|
||||
|
||||
private void setup_main_encryption_keys (Bytes shared_key) {
|
||||
client_cipher = new ChaCha20Poly1305 (derive_chacha_key (shared_key, "ClientEncrypt-main"));
|
||||
server_cipher = new ChaCha20Poly1305 (derive_chacha_key (shared_key, "ServerEncrypt-main"));
|
||||
}
|
||||
|
||||
private async ObjectReader request_pairing_data (Bytes payload, Cancellable? cancellable) throws Error, IOError {
|
||||
@@ -1383,7 +1487,7 @@ namespace Frida.Fruity {
|
||||
_peers = load_peers ();
|
||||
}
|
||||
|
||||
public void add_peer (string identifier, Bytes public_key, Bytes info) throws Error {
|
||||
public PairingPeer add_peer (string identifier, Bytes public_key, Bytes info) throws Error {
|
||||
var r = new VariantReader (OpackParser.parse (info));
|
||||
|
||||
Bytes irk = r.read_member ("altIRK").get_data_value ();
|
||||
@@ -1406,6 +1510,7 @@ namespace Frida.Fruity {
|
||||
model = model,
|
||||
udid = udid,
|
||||
info = info,
|
||||
remote_unlock_host_key = null,
|
||||
};
|
||||
_peers.add (peer);
|
||||
|
||||
@@ -1413,6 +1518,12 @@ namespace Frida.Fruity {
|
||||
save_peer (peer);
|
||||
} catch (Error e) {
|
||||
}
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
public PairingPeer? find_peer_by_identifier (string identifier) {
|
||||
return peers.first_match (p => p.identifier == identifier);
|
||||
}
|
||||
|
||||
public PairingPeer? find_peer_matching_service (PairingServiceDetails service) {
|
||||
@@ -1480,6 +1591,10 @@ namespace Frida.Fruity {
|
||||
var r = new VariantReader (OpackParser.parse (info));
|
||||
unowned string udid = r.read_member ("remotepairing_udid").get_string_value ();
|
||||
|
||||
Bytes? remote_unlock_host_key = null;
|
||||
if (plist.has ("remoteUnlockHostKey"))
|
||||
remote_unlock_host_key = plist.get_bytes ("remoteUnlockHostKey");
|
||||
|
||||
peers.add (new PairingPeer () {
|
||||
identifier = plist.get_string ("identifier"),
|
||||
public_key = plist.get_bytes ("publicKey"),
|
||||
@@ -1488,6 +1603,7 @@ namespace Frida.Fruity {
|
||||
model = plist.get_string ("model"),
|
||||
udid = udid,
|
||||
info = info,
|
||||
remote_unlock_host_key = remote_unlock_host_key,
|
||||
});
|
||||
}
|
||||
} catch (GLib.Error e) {
|
||||
@@ -1496,7 +1612,7 @@ namespace Frida.Fruity {
|
||||
return peers;
|
||||
}
|
||||
|
||||
private static void save_peer (PairingPeer peer) throws Error {
|
||||
public void save_peer (PairingPeer peer) throws Error {
|
||||
var plist = new Plist ();
|
||||
plist.set_string ("identifier", peer.identifier);
|
||||
plist.set_bytes ("publicKey", peer.public_key);
|
||||
@@ -1504,13 +1620,29 @@ namespace Frida.Fruity {
|
||||
plist.set_string ("name", peer.name);
|
||||
plist.set_string ("model", peer.model);
|
||||
plist.set_bytes ("info", peer.info);
|
||||
save_plist (plist, query_peers_location ().get_child (peer.identifier + ".plist"));
|
||||
if (peer.remote_unlock_host_key != null)
|
||||
plist.set_bytes ("remoteUnlockHostKey", peer.remote_unlock_host_key);
|
||||
|
||||
save_plist (plist, query_peer_location (peer));
|
||||
}
|
||||
|
||||
public void forget_peer (PairingPeer peer) {
|
||||
try {
|
||||
query_peer_location (peer).delete ();
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
|
||||
_peers.remove (peer);
|
||||
}
|
||||
|
||||
private static File query_self_identity_location () {
|
||||
return query_base_location ().get_child ("self-identity.plist");
|
||||
}
|
||||
|
||||
private static File query_peer_location (PairingPeer peer) {
|
||||
return query_peers_location ().get_child (peer.identifier + ".plist");
|
||||
}
|
||||
|
||||
private static File query_peers_location () {
|
||||
return query_base_location ().get_child ("peers");
|
||||
}
|
||||
@@ -1557,6 +1689,7 @@ namespace Frida.Fruity {
|
||||
public string model;
|
||||
public string udid;
|
||||
public Bytes info;
|
||||
public Bytes? remote_unlock_host_key;
|
||||
}
|
||||
|
||||
public class PairingServiceMetadata {
|
||||
|
||||
@@ -9,26 +9,17 @@ namespace Frida {
|
||||
|
||||
public HostSessionService.with_default_backends () {
|
||||
add_local_backends ();
|
||||
#if !IOS && !ANDROID && !TVOS
|
||||
#if HAVE_FRUITY_BACKEND
|
||||
add_backend (new FruityHostSessionBackend ());
|
||||
#endif
|
||||
#if HAVE_DROIDY_BACKEND
|
||||
add_backend (new DroidyHostSessionBackend ());
|
||||
#endif
|
||||
#endif
|
||||
#if HAVE_SOCKET_BACKEND
|
||||
add_backend (new SocketHostSessionBackend ());
|
||||
#endif
|
||||
#if HAVE_BAREBONE_BACKEND
|
||||
add_backend (new BareboneHostSessionBackend ());
|
||||
#endif
|
||||
add_nonlocal_backends ();
|
||||
}
|
||||
|
||||
public HostSessionService.with_local_backend_only () {
|
||||
add_local_backends ();
|
||||
}
|
||||
|
||||
public HostSessionService.with_nonlocal_backends_only () {
|
||||
add_nonlocal_backends ();
|
||||
}
|
||||
|
||||
public HostSessionService.with_socket_backend_only () {
|
||||
#if HAVE_SOCKET_BACKEND
|
||||
add_backend (new SocketHostSessionBackend ());
|
||||
@@ -55,6 +46,23 @@ namespace Frida {
|
||||
#endif
|
||||
}
|
||||
|
||||
private void add_nonlocal_backends () {
|
||||
#if !IOS && !ANDROID && !TVOS
|
||||
#if HAVE_FRUITY_BACKEND
|
||||
add_backend (new FruityHostSessionBackend ());
|
||||
#endif
|
||||
#if HAVE_DROIDY_BACKEND
|
||||
add_backend (new DroidyHostSessionBackend ());
|
||||
#endif
|
||||
#endif
|
||||
#if HAVE_SOCKET_BACKEND
|
||||
add_backend (new SocketHostSessionBackend ());
|
||||
#endif
|
||||
#if HAVE_BAREBONE_BACKEND
|
||||
add_backend (new BareboneHostSessionBackend ());
|
||||
#endif
|
||||
}
|
||||
|
||||
public async void start (Cancellable? cancellable = null) throws IOError {
|
||||
var remaining = backends.size + 1;
|
||||
|
||||
|
||||
@@ -844,19 +844,19 @@ namespace Frida {
|
||||
private const uint64 SOCK_CLOEXEC = 0x80000;
|
||||
|
||||
private class InjectSession : SeizeSession {
|
||||
private static ProcMapsEntry local_libc;
|
||||
private static ProcMapsSoEntry local_libc;
|
||||
private static uint64 mmap_offset;
|
||||
private static uint64 munmap_offset;
|
||||
|
||||
private static string fallback_ld;
|
||||
private static string fallback_libc;
|
||||
|
||||
private static ProcMapsEntry? local_android_ld;
|
||||
private static ProcMapsSoEntry? local_android_ld;
|
||||
|
||||
static construct {
|
||||
var libc = Gum.Process.get_libc_module ();
|
||||
uint local_pid = Posix.getpid ();
|
||||
local_libc = ProcMapsEntry.find_by_path (local_pid, libc.path);
|
||||
local_libc = ProcMapsSoEntry.find_by_path (local_pid, libc.path);
|
||||
assert (local_libc != null);
|
||||
mmap_offset = (uint64) (uintptr) libc.find_export_by_name ("mmap") - local_libc.base_address;
|
||||
munmap_offset = (uint64) (uintptr) libc.find_export_by_name ("munmap") - local_libc.base_address;
|
||||
@@ -877,7 +877,7 @@ namespace Frida {
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
local_android_ld = ProcMapsEntry.find_by_path (local_pid, fallback_ld);
|
||||
local_android_ld = ProcMapsSoEntry.find_by_path (local_pid, fallback_ld);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1084,8 +1084,18 @@ namespace Frida {
|
||||
|
||||
uint64 remote_mmap = 0;
|
||||
uint64 remote_munmap = 0;
|
||||
ProcMapsEntry? remote_libc = ProcMapsEntry.find_by_path (pid, local_libc.path);
|
||||
ProcMapsSoEntry? remote_libc = ProcMapsSoEntry.find_by_path (pid, local_libc.path);
|
||||
#if ANDROID
|
||||
bool same_libc = false;
|
||||
if (remote_libc != null) {
|
||||
bool same_device = remote_libc.identity.split (":")[0] == local_libc.identity.split (":")[0];
|
||||
bool same_inode = remote_libc.identity.split (" ")[1] == local_libc.identity.split (" ")[1];
|
||||
bool same_path = remote_libc.path == local_libc.path;
|
||||
same_libc = same_device && same_inode && same_path;
|
||||
}
|
||||
#else
|
||||
bool same_libc = remote_libc != null && remote_libc.identity == local_libc.identity;
|
||||
#endif
|
||||
if (same_libc) {
|
||||
remote_mmap = remote_libc.base_address + mmap_offset;
|
||||
remote_munmap = remote_libc.base_address + munmap_offset;
|
||||
@@ -1186,7 +1196,7 @@ namespace Frida {
|
||||
result.context.libc = &result.libc;
|
||||
|
||||
if (result.context.rtld_flavor == ANDROID && result.libc.dlopen == null) {
|
||||
ProcMapsEntry? remote_ld = ProcMapsEntry.find_by_address (pid, (uintptr) result.context.rtld_base);
|
||||
ProcMapsSoEntry? remote_ld = ProcMapsSoEntry.find_by_address (pid, (uintptr) result.context.rtld_base);
|
||||
bool same_ld = remote_ld != null && local_android_ld != null && remote_ld.identity == local_android_ld.identity;
|
||||
if (!same_ld)
|
||||
throw new Error.NOT_SUPPORTED ("Unable to locate Android dynamic linker; please file a bug");
|
||||
@@ -1236,7 +1246,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private static void * rebase_pointer (uintptr local_ptr, ProcMapsEntry local_module, ProcMapsEntry remote_module) {
|
||||
private static void * rebase_pointer (uintptr local_ptr, ProcMapsSoEntry local_module, ProcMapsSoEntry remote_module) {
|
||||
var offset = local_ptr - local_module.base_address;
|
||||
return (void *) (remote_module.base_address + offset);
|
||||
}
|
||||
@@ -1996,7 +2006,7 @@ namespace Frida {
|
||||
else
|
||||
breakpoint_data = (uint8[]) &arm_breakpoint_val;
|
||||
#elif ARM64
|
||||
uint32 breakpoint_val = 0xd4200000U;
|
||||
uint32 breakpoint_val = (0xd4200000U).to_little_endian ();
|
||||
breakpoint_data = (uint8[]) &breakpoint_val;
|
||||
#elif MIPS
|
||||
uint32 breakpoint_val = 0x0000000dU;
|
||||
@@ -2280,6 +2290,9 @@ namespace Frida {
|
||||
this.session = session;
|
||||
|
||||
Gum.Linux.enumerate_ranges ((Posix.pid_t) session.pid, READ | EXECUTE, d => {
|
||||
unowned Gum.FileMapping? file = d.file;
|
||||
if (file != null && file.path.has_prefix ("memfd:"))
|
||||
return true;
|
||||
if (d.range.size >= code.length) {
|
||||
code_start = d.range.base_address + d.range.size - round_size_to_page_size (code.length);
|
||||
code_end = code_start + code.length;
|
||||
@@ -3306,46 +3319,87 @@ namespace Frida {
|
||||
}
|
||||
#endif
|
||||
|
||||
private class ProcMapsEntry {
|
||||
private class ProcMapsSoEntry {
|
||||
public uint64 base_address;
|
||||
public string path;
|
||||
public string identity;
|
||||
|
||||
private ProcMapsEntry (uint64 base_address, string path, string identity) {
|
||||
private ProcMapsSoEntry (uint64 base_address, string path, string identity) {
|
||||
this.base_address = base_address;
|
||||
this.path = path;
|
||||
this.identity = identity;
|
||||
}
|
||||
|
||||
public static ProcMapsEntry? find_by_address (uint pid, uint64 address) {
|
||||
public static ProcMapsSoEntry? find_by_address (uint pid, uint64 address) {
|
||||
var iter = MapsIter.for_pid (pid);
|
||||
while (iter.next ()) {
|
||||
uint64 start = iter.start_address;
|
||||
uint64 end = iter.end_address;
|
||||
if (address >= start && address < end)
|
||||
return new ProcMapsEntry (start, iter.path, iter.identity);
|
||||
return new ProcMapsSoEntry (start, iter.path, iter.identity);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ProcMapsEntry? find_by_path (uint pid, string path) {
|
||||
public static ProcMapsSoEntry? find_by_path (uint pid, string path) {
|
||||
var candidates = new Gee.ArrayList<Candidate> ();
|
||||
Candidate? latest_candidate = null;
|
||||
var iter = MapsIter.for_pid (pid);
|
||||
#if ANDROID
|
||||
unowned string libc_path = Gum.Process.get_libc_module ().path;
|
||||
#endif
|
||||
while (iter.next ()) {
|
||||
string candidate_path = iter.path;
|
||||
if (candidate_path == path) {
|
||||
string current_path = iter.path;
|
||||
if (current_path == "[page size compat]")
|
||||
continue;
|
||||
if (current_path != path) {
|
||||
latest_candidate = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
string flags = iter.flags;
|
||||
|
||||
#if ANDROID
|
||||
if (candidate_path == libc_path && iter.flags[3] == 's')
|
||||
continue;
|
||||
if (current_path == libc_path && flags[3] == 's')
|
||||
continue;
|
||||
#endif
|
||||
return new ProcMapsEntry (iter.start_address, candidate_path, iter.identity);
|
||||
|
||||
if (iter.file_offset == 0) {
|
||||
latest_candidate = new Candidate () {
|
||||
entry = new ProcMapsSoEntry (iter.start_address, current_path, iter.identity),
|
||||
total_ranges = 0,
|
||||
executable_ranges = 0,
|
||||
};
|
||||
candidates.add (latest_candidate);
|
||||
}
|
||||
|
||||
if (latest_candidate != null) {
|
||||
latest_candidate.total_ranges++;
|
||||
if (flags[2] == 'x')
|
||||
latest_candidate.executable_ranges++;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
candidates.sort ((a, b) => b.score () - a.score ());
|
||||
|
||||
if (candidates.is_empty)
|
||||
return null;
|
||||
|
||||
return candidates.first ().entry;
|
||||
}
|
||||
|
||||
private class Candidate {
|
||||
public ProcMapsSoEntry entry;
|
||||
public uint total_ranges;
|
||||
public uint executable_ranges;
|
||||
|
||||
public int score () {
|
||||
int result = (int) total_ranges;
|
||||
if (executable_ranges == 0)
|
||||
result = -result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private class MapsIter {
|
||||
@@ -3371,15 +3425,21 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public uint64 file_offset {
|
||||
get {
|
||||
return uint64.parse (info.fetch (4), 16);
|
||||
}
|
||||
}
|
||||
|
||||
public string identity {
|
||||
owned get {
|
||||
return info.fetch (4);
|
||||
return info.fetch (5);
|
||||
}
|
||||
}
|
||||
|
||||
public string path {
|
||||
owned get {
|
||||
return info.fetch (5);
|
||||
return info.fetch (6);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3394,7 +3454,7 @@ namespace Frida {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!/^([0-9a-f]+)-([0-9a-f]+) (\S{4}) [0-9a-f]+ ([0-9a-f]{2,}:[0-9a-f]{2,} \d+) +([^\n]+)$/m.match (
|
||||
if (!/^([0-9a-f]+)-([0-9a-f]+) (\S{4}) ([0-9a-f]+) ([0-9a-f]{2,}:[0-9a-f]{2,} \d+) +([^\n]+)$/m.match (
|
||||
contents, 0, out info)) {
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
@@ -204,8 +204,14 @@ namespace Frida {
|
||||
private async LinuxHelper obtain_for_64bit (Cancellable? cancellable) throws Error, IOError {
|
||||
if (factory64 == null) {
|
||||
var store = get_resource_store ();
|
||||
#if !ARM64
|
||||
/*
|
||||
* If we are building for ARM64 and our pointer size is not 8-bytes, then we must be building for
|
||||
* ILP32, so avoid the spurious error.
|
||||
*/
|
||||
if (sizeof (void *) != 8 && store.helper64 == null)
|
||||
throw new Error.NOT_SUPPORTED ("Unable to handle 64-bit processes due to build configuration");
|
||||
#endif
|
||||
factory64 = new HelperFactory (store.helper64, store, main_context);
|
||||
factory64.lost.connect (on_factory_lost);
|
||||
factory64.output.connect (on_factory_output);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef __FRIDA_SYSCALL_H__
|
||||
#define __FRIDA_SYSCALL_H__
|
||||
|
||||
#include <linux/unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#undef SYS_process_vm_readv
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -9,7 +9,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef __ELF_NATIVE_CLASS
|
||||
# if defined (__x86_64__) || defined (__aarch64__) || defined (__mips64)
|
||||
# if defined (__x86_64__) || (defined (__aarch64__) && !defined (__ILP32__)) || defined (__mips64)
|
||||
# define __ELF_NATIVE_CLASS 64
|
||||
# else
|
||||
# define __ELF_NATIVE_CLASS 32
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -197,19 +197,31 @@ diff --git a/tools/include/nolibc/std.h b/tools/include/nolibc/std.h
|
||||
index 1747ae125..5f30e6e0c 100644
|
||||
--- a/tools/include/nolibc/std.h
|
||||
+++ b/tools/include/nolibc/std.h
|
||||
@@ -25,25 +25,61 @@ typedef unsigned short uint16_t;
|
||||
@@ -25,25 +25,71 @@ typedef unsigned short uint16_t;
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef signed int int32_t;
|
||||
-typedef unsigned long long uint64_t;
|
||||
-typedef signed long long int64_t;
|
||||
+#if defined(__x86_64__) || defined(__aarch64__) || defined(__mips64) || defined(__riscv)
|
||||
+#if defined(__ILP32__)
|
||||
+typedef unsigned long long uint64_t;
|
||||
+typedef signed long long int64_t;
|
||||
+#else
|
||||
+typedef unsigned long uint64_t;
|
||||
+typedef signed long int64_t;
|
||||
+#endif
|
||||
typedef unsigned long size_t;
|
||||
typedef signed long ssize_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef signed long intptr_t;
|
||||
-typedef unsigned long uintptr_t;
|
||||
-typedef signed long intptr_t;
|
||||
+#if defined(__ILP32__)
|
||||
+typedef unsigned int uintptr_t;
|
||||
+typedef signed int intptr_t;
|
||||
+#else
|
||||
+typedef unsigned long uintptr_t;
|
||||
+typedef signed long intptr_t;
|
||||
+#endif
|
||||
typedef signed long ptrdiff_t;
|
||||
+#elif defined(__arm__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
+typedef unsigned long long uint64_t;
|
||||
|
||||
@@ -48,7 +48,10 @@ ARCHS=(
|
||||
x86
|
||||
x86_64
|
||||
arm
|
||||
armbe8
|
||||
arm64
|
||||
arm64be
|
||||
arm64beilp32
|
||||
mips
|
||||
mipsel
|
||||
mips64
|
||||
@@ -66,11 +69,14 @@ build_arch () {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$ARCH" == arm* ]]; then
|
||||
case "$ARCH" in
|
||||
arm | arm64)
|
||||
export FRIDA_HOST=android-$ARCH
|
||||
else
|
||||
;;
|
||||
*)
|
||||
export FRIDA_HOST=linux-$ARCH
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
EXTRA_FLAGS=()
|
||||
if [ "$FRIDA_HOST" == "linux-x86" ]; then
|
||||
@@ -78,6 +84,12 @@ build_arch () {
|
||||
export CC="gcc -m32" CXX="g++ -m32" STRIP="strip"
|
||||
fi
|
||||
|
||||
case "$ARCH" in
|
||||
armbe8 | arm64be | arm64beilp32)
|
||||
EXTRA_FLAGS+=("--without-prebuilds=sdk:host")
|
||||
;;
|
||||
esac
|
||||
|
||||
cd "$FRIDA_CORE_DIR"
|
||||
|
||||
rm -rf "$BUILD_DIR"
|
||||
|
||||
@@ -321,6 +321,8 @@ if have_local_backend
|
||||
endif
|
||||
if host_lowlevel_abi == 'arm' and host_machine.endian() == 'big'
|
||||
host_lowlevel_abi = 'armbe8'
|
||||
elif host_lowlevel_abi == 'arm64' and host_machine.endian() == 'big'
|
||||
host_lowlevel_abi = 'arm64be'
|
||||
endif
|
||||
fs = import('fs')
|
||||
helper_backend_data = custom_target('frida-data-helper-backend',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/frida-gum.git
|
||||
revision = 16.6.4
|
||||
revision = 16.7.2
|
||||
depth = 1
|
||||
|
||||
[provide]
|
||||
|
||||
@@ -76,6 +76,20 @@ namespace Darwin.Xpc {
|
||||
public uint64 get_value ();
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer")]
|
||||
public class Data : Object {
|
||||
[CCode (cname = "XPC_TYPE_DATA")]
|
||||
public static Type TYPE;
|
||||
|
||||
[CCode (cname = "xpc_data_create")]
|
||||
public Data (uint8[] bytes);
|
||||
|
||||
public size_t get_length ();
|
||||
|
||||
public void * get_bytes_ptr ();
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer")]
|
||||
public class String : Object {
|
||||
@@ -133,6 +147,10 @@ namespace Darwin.Xpc {
|
||||
public uint64 get_uint64 (string key);
|
||||
public void set_uint64 (string key, uint64 val);
|
||||
|
||||
[CCode (array_length_type = "size_t")]
|
||||
public unowned uint8[]? get_data (string key);
|
||||
public void set_data (string key, uint8[] bytes);
|
||||
|
||||
public unowned string? get_string (string key);
|
||||
public void set_string (string key, string val);
|
||||
|
||||
|
||||
Reference in new issue
Block a user