mirror of
https://github.com/frida/frida-core.git
synced 2026-11-10 01:51: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: 79d6dfa3d6...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);
|
||||
}
|
||||
@@ -1988,15 +1998,15 @@ namespace Frida {
|
||||
#elif ARM
|
||||
target_address &= ~1;
|
||||
|
||||
uint32 arm_breakpoint_val = 0xe7f001f0U;
|
||||
uint16 thumb_breakpoint_val = 0xde01;
|
||||
uint32 arm_breakpoint_val = (0xe7f001f0U).to_little_endian ();
|
||||
uint16 thumb_breakpoint_val = ((uint16) 0xde01).to_little_endian ();
|
||||
bool is_thumb = (target & 1) != 0;
|
||||
if (is_thumb)
|
||||
breakpoint_data = (uint8[]) &thumb_breakpoint_val;
|
||||
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.
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+24
-16
@@ -303,16 +303,20 @@ frida_receive_chunk (int sockfd, void * buffer, size_t length, const FridaLibcAp
|
||||
.iov_base = cursor,
|
||||
.iov_len = remaining
|
||||
};
|
||||
struct msghdr msg = {
|
||||
.msg_name = NULL,
|
||||
.msg_namelen = 0,
|
||||
.msg_iov = &io,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = NULL,
|
||||
.msg_controllen = 0,
|
||||
};
|
||||
struct msghdr msg;
|
||||
ssize_t n;
|
||||
|
||||
/*
|
||||
* Avoid inline initialization to prevent the compiler attempting to insert
|
||||
* a call to memset.
|
||||
*/
|
||||
msg.msg_name = NULL,
|
||||
msg.msg_namelen = 0,
|
||||
msg.msg_iov = &io,
|
||||
msg.msg_iovlen = 1,
|
||||
msg.msg_control = NULL,
|
||||
msg.msg_controllen = 0,
|
||||
|
||||
n = libc->recvmsg (sockfd, &msg, 0);
|
||||
if (n <= 0)
|
||||
return false;
|
||||
@@ -334,14 +338,18 @@ frida_receive_fd (int sockfd, const FridaLibcApi * libc)
|
||||
.iov_len = sizeof (dummy)
|
||||
};
|
||||
FridaControlMessage control;
|
||||
struct msghdr msg = {
|
||||
.msg_name = NULL,
|
||||
.msg_namelen = 0,
|
||||
.msg_iov = &io,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof (control),
|
||||
};
|
||||
struct msghdr msg;
|
||||
|
||||
/*
|
||||
* Avoid inline initialization to prevent the compiler attempting to insert
|
||||
* a call to memset.
|
||||
*/
|
||||
msg.msg_name = NULL,
|
||||
msg.msg_namelen = 0,
|
||||
msg.msg_iov = &io,
|
||||
msg.msg_iovlen = 1,
|
||||
msg.msg_control = &control,
|
||||
msg.msg_controllen = sizeof (control),
|
||||
|
||||
res = libc->recvmsg (sockfd, &msg, 0);
|
||||
if (res == -1 || res == 0 || msg.msg_controllen == 0)
|
||||
|
||||
@@ -197,20 +197,40 @@ 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,53 @@ 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;
|
||||
+typedef signed long long int64_t;
|
||||
+typedef unsigned int size_t;
|
||||
+typedef signed int ssize_t;
|
||||
+typedef unsigned long uintptr_t;
|
||||
+typedef signed int intptr_t;
|
||||
+typedef signed int ptrdiff_t;
|
||||
+#else
|
||||
+typedef unsigned long long uint64_t;
|
||||
+typedef signed long long int64_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"
|
||||
|
||||
@@ -319,6 +319,11 @@ if have_local_backend
|
||||
else
|
||||
host_lowlevel_abi = host_abi
|
||||
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',
|
||||
input: [
|
||||
|
||||
@@ -306,6 +306,7 @@ frida_remote_worker_context_init (FridaRemoteWorkerContext * rwc, FridaInjection
|
||||
{
|
||||
gpointer code;
|
||||
guint code_size;
|
||||
GumModule * kernel32;
|
||||
SIZE_T page_size, alloc_size;
|
||||
DWORD old_protect;
|
||||
|
||||
@@ -316,7 +317,9 @@ frida_remote_worker_context_init (FridaRemoteWorkerContext * rwc, FridaInjection
|
||||
|
||||
memset (rwc, 0, sizeof (FridaRemoteWorkerContext));
|
||||
|
||||
gum_module_enumerate_exports ("kernel32.dll", frida_remote_worker_context_collect_kernel32_export, rwc);
|
||||
kernel32 = gum_process_find_module_by_name ("kernel32.dll");
|
||||
gum_module_enumerate_exports (kernel32, frida_remote_worker_context_collect_kernel32_export, rwc);
|
||||
g_object_unref (kernel32);
|
||||
if (!frida_remote_worker_context_has_resolved_all_kernel32_functions (rwc))
|
||||
goto failed_to_resolve_kernel32_functions;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/frida-gum.git
|
||||
revision = 16.6.2
|
||||
revision = 16.7.2
|
||||
depth = 1
|
||||
|
||||
[provide]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/lwip.git
|
||||
revision = 2b3efb7862866904f67dc369c9147f527a2982ca
|
||||
revision = 267d9f082e9e38083b643421a93c03d4a7046fd0
|
||||
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