mirror of
https://github.com/frida/frida-core.git
synced 2026-11-09 10:09:38 -10:00
Compare commits
No files matched your search
@@ -1400,12 +1400,12 @@ namespace Frida.Agent {
|
||||
if (nb_api.unload_library == null)
|
||||
parameters.append ("|eternal|sticky");
|
||||
/*
|
||||
* Disable ExitMonitor to work around a bug in Android's libndk_translation.so on Android 11.
|
||||
* We need to avoid modifying libc.so ranges that the translator potentially depends on, to
|
||||
* avoid blowing up when Interceptor's CPU cache flush results in the translated code being
|
||||
* discarded, which seems like an edge-case the translator doesn't handle.
|
||||
* Disable Exceptor and ExitMonitor to work around a bug in Android's libndk_translation.so
|
||||
* on Android 11. We need to avoid modifying libc.so ranges that the translator potentially
|
||||
* depends on, to avoid blowing up when Interceptor's CPU cache flush results in the translated
|
||||
* code being discarded, which seems like an edge-case the translator doesn't handle.
|
||||
*/
|
||||
parameters.append ("|exit-monitor:off");
|
||||
parameters.append ("|exceptor:off|exit-monitor:off");
|
||||
|
||||
emulated_bridge_state = new BridgeState (parameters.str);
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "frida-base.h"
|
||||
|
||||
GBytes *
|
||||
frida_make_bytes_with_owner (GType t_type,
|
||||
GBoxedCopyFunc t_dup_func,
|
||||
GDestroyNotify t_destroy_func,
|
||||
void * data,
|
||||
gsize size,
|
||||
gpointer owner)
|
||||
{
|
||||
return g_bytes_new_with_free_func (data, size, t_destroy_func, owner);
|
||||
}
|
||||
+95
-33
@@ -356,10 +356,20 @@ namespace Frida {
|
||||
return *((int8 *) get_pointer (offset, sizeof (int8)));
|
||||
}
|
||||
|
||||
public unowned Buffer write_int8 (size_t offset, int8 val) {
|
||||
*((int8 *) get_pointer (offset, sizeof (int8))) = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public uint8 read_uint8 (size_t offset) {
|
||||
return *get_pointer (offset, sizeof (uint8));
|
||||
}
|
||||
|
||||
public unowned Buffer write_uint8 (size_t offset, uint8 val) {
|
||||
*((uint8 *) get_pointer (offset, sizeof (uint8))) = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int16 read_int16 (size_t offset) {
|
||||
int16 val = *((int16 *) get_pointer (offset, sizeof (int16)));
|
||||
return (byte_order == BIG_ENDIAN)
|
||||
@@ -367,6 +377,14 @@ namespace Frida {
|
||||
: int16.from_little_endian (val);
|
||||
}
|
||||
|
||||
public unowned Buffer write_int16 (size_t offset, int16 val) {
|
||||
int16 target_val = (byte_order == BIG_ENDIAN)
|
||||
? val.to_big_endian ()
|
||||
: val.to_little_endian ();
|
||||
*((int16 *) get_pointer (offset, sizeof (int16))) = target_val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public uint16 read_uint16 (size_t offset) {
|
||||
uint16 val = *((uint16 *) get_pointer (offset, sizeof (uint16)));
|
||||
return (byte_order == BIG_ENDIAN)
|
||||
@@ -374,6 +392,14 @@ namespace Frida {
|
||||
: uint16.from_little_endian (val);
|
||||
}
|
||||
|
||||
public unowned Buffer write_uint16 (size_t offset, uint16 val) {
|
||||
uint16 target_val = (byte_order == BIG_ENDIAN)
|
||||
? val.to_big_endian ()
|
||||
: val.to_little_endian ();
|
||||
*((uint16 *) get_pointer (offset, sizeof (uint16))) = target_val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int32 read_int32 (size_t offset) {
|
||||
int32 val = *((int32 *) get_pointer (offset, sizeof (int32)));
|
||||
return (byte_order == BIG_ENDIAN)
|
||||
@@ -381,6 +407,14 @@ namespace Frida {
|
||||
: int32.from_little_endian (val);
|
||||
}
|
||||
|
||||
public unowned Buffer write_int32 (size_t offset, int32 val) {
|
||||
int32 target_val = (byte_order == BIG_ENDIAN)
|
||||
? val.to_big_endian ()
|
||||
: val.to_little_endian ();
|
||||
*((int32 *) get_pointer (offset, sizeof (int32))) = target_val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public uint32 read_uint32 (size_t offset) {
|
||||
uint32 val = *((uint32 *) get_pointer (offset, sizeof (uint32)));
|
||||
return (byte_order == BIG_ENDIAN)
|
||||
@@ -403,6 +437,14 @@ namespace Frida {
|
||||
: int64.from_little_endian (val);
|
||||
}
|
||||
|
||||
public unowned Buffer write_int64 (size_t offset, int64 val) {
|
||||
int64 target_val = (byte_order == BIG_ENDIAN)
|
||||
? val.to_big_endian ()
|
||||
: val.to_little_endian ();
|
||||
*((int64 *) get_pointer (offset, sizeof (int64))) = target_val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public uint64 read_uint64 (size_t offset) {
|
||||
uint64 val = *((uint64 *) get_pointer (offset, sizeof (uint64)));
|
||||
return (byte_order == BIG_ENDIAN)
|
||||
@@ -446,7 +488,7 @@ namespace Frida {
|
||||
|
||||
public string read_fixed_string (size_t offset, size_t size) throws Error {
|
||||
string * start = (string *) get_pointer (offset, size);
|
||||
size_t max_length = size - offset;
|
||||
size_t max_length = size_t.min (size, this.size - offset);
|
||||
string * end = memchr (start, 0, max_length);
|
||||
size_t n;
|
||||
if (end != null)
|
||||
@@ -465,6 +507,18 @@ namespace Frida {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Bytes read_bytes (size_t offset, size_t size) {
|
||||
var data = new uint8[size + 1];
|
||||
Memory.copy (data, get_pointer (offset, size), size);
|
||||
return new Bytes.take ((owned) data);
|
||||
}
|
||||
|
||||
public unowned Buffer write_bytes (size_t offset, Bytes bytes) {
|
||||
size_t size = bytes.get_size ();
|
||||
Memory.copy (get_pointer (offset, size), bytes.get_data (), size);
|
||||
return this;
|
||||
}
|
||||
|
||||
private uint8 * get_pointer (size_t offset, size_t n) {
|
||||
size_t minimum_size = offset + n;
|
||||
assert (size >= minimum_size);
|
||||
@@ -474,121 +528,127 @@ namespace Frida {
|
||||
}
|
||||
|
||||
public sealed class BufferReader {
|
||||
public size_t offset {
|
||||
get {
|
||||
return _offset;
|
||||
}
|
||||
}
|
||||
|
||||
public size_t available {
|
||||
get {
|
||||
return buffer.bytes.get_size () - offset;
|
||||
return buffer.bytes.get_size () - _offset;
|
||||
}
|
||||
}
|
||||
|
||||
private Buffer buffer;
|
||||
private size_t offset = 0;
|
||||
private size_t _offset = 0;
|
||||
|
||||
public BufferReader (Buffer buf) {
|
||||
buffer = buf;
|
||||
}
|
||||
|
||||
public uint64 read_pointer (size_t offset) throws Error {
|
||||
public uint64 read_pointer () throws Error {
|
||||
var pointer_size = buffer.pointer_size;
|
||||
check_available (pointer_size);
|
||||
var ptr = buffer.read_pointer (offset);
|
||||
offset += pointer_size;
|
||||
var ptr = buffer.read_pointer (_offset);
|
||||
_offset += pointer_size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
public int8 read_int8 () throws Error {
|
||||
check_available (sizeof (int8));
|
||||
var val = buffer.read_int8 (offset);
|
||||
offset += sizeof (int8);
|
||||
var val = buffer.read_int8 (_offset);
|
||||
_offset += sizeof (int8);
|
||||
return val;
|
||||
}
|
||||
|
||||
public uint8 read_uint8 () throws Error {
|
||||
check_available (sizeof (uint8));
|
||||
var val = buffer.read_uint8 (offset);
|
||||
offset += sizeof (uint8);
|
||||
var val = buffer.read_uint8 (_offset);
|
||||
_offset += sizeof (uint8);
|
||||
return val;
|
||||
}
|
||||
|
||||
public int16 read_int16 () throws Error {
|
||||
check_available (sizeof (int16));
|
||||
var val = buffer.read_int16 (offset);
|
||||
offset += sizeof (int16);
|
||||
var val = buffer.read_int16 (_offset);
|
||||
_offset += sizeof (int16);
|
||||
return val;
|
||||
}
|
||||
|
||||
public uint16 read_uint16 () throws Error {
|
||||
check_available (sizeof (uint16));
|
||||
var val = buffer.read_uint16 (offset);
|
||||
offset += sizeof (uint16);
|
||||
var val = buffer.read_uint16 (_offset);
|
||||
_offset += sizeof (uint16);
|
||||
return val;
|
||||
}
|
||||
|
||||
public int32 read_int32 () throws Error {
|
||||
check_available (sizeof (int32));
|
||||
var val = buffer.read_int32 (offset);
|
||||
offset += sizeof (int32);
|
||||
var val = buffer.read_int32 (_offset);
|
||||
_offset += sizeof (int32);
|
||||
return val;
|
||||
}
|
||||
|
||||
public uint32 read_uint32 () throws Error {
|
||||
check_available (sizeof (uint32));
|
||||
var val = buffer.read_uint32 (offset);
|
||||
offset += sizeof (uint32);
|
||||
var val = buffer.read_uint32 (_offset);
|
||||
_offset += sizeof (uint32);
|
||||
return val;
|
||||
}
|
||||
|
||||
public int64 read_int64 () throws Error {
|
||||
check_available (sizeof (int64));
|
||||
var val = buffer.read_int64 (offset);
|
||||
offset += sizeof (int64);
|
||||
var val = buffer.read_int64 (_offset);
|
||||
_offset += sizeof (int64);
|
||||
return val;
|
||||
}
|
||||
|
||||
public uint64 read_uint64 () throws Error {
|
||||
check_available (sizeof (uint64));
|
||||
var val = buffer.read_uint64 (offset);
|
||||
offset += sizeof (uint64);
|
||||
var val = buffer.read_uint64 (_offset);
|
||||
_offset += sizeof (uint64);
|
||||
return val;
|
||||
}
|
||||
|
||||
public float read_float () throws Error {
|
||||
check_available (sizeof (float));
|
||||
var val = buffer.read_float (offset);
|
||||
offset += sizeof (float);
|
||||
var val = buffer.read_float (_offset);
|
||||
_offset += sizeof (float);
|
||||
return val;
|
||||
}
|
||||
|
||||
public double read_double () throws Error {
|
||||
check_available (sizeof (double));
|
||||
var val = buffer.read_double (offset);
|
||||
offset += sizeof (double);
|
||||
var val = buffer.read_double (_offset);
|
||||
_offset += sizeof (double);
|
||||
return val;
|
||||
}
|
||||
|
||||
public string read_string () throws Error {
|
||||
check_available (1);
|
||||
var val = buffer.read_string (offset);
|
||||
offset += val.length + 1;
|
||||
var val = buffer.read_string (_offset);
|
||||
_offset += val.length + 1;
|
||||
return val;
|
||||
}
|
||||
|
||||
public string read_fixed_string (size_t size) throws Error {
|
||||
check_available (size);
|
||||
var val = buffer.read_fixed_string (offset, size);
|
||||
offset += size;
|
||||
var val = buffer.read_fixed_string (_offset, size);
|
||||
_offset += size;
|
||||
return val;
|
||||
}
|
||||
|
||||
public Bytes read_bytes (size_t size) throws Error {
|
||||
check_available (size);
|
||||
var val = buffer.bytes[offset:offset + size];
|
||||
offset += size;
|
||||
var val = buffer.bytes[_offset:_offset + size];
|
||||
_offset += size;
|
||||
return val;
|
||||
}
|
||||
|
||||
public unowned BufferReader skip (size_t n) throws Error {
|
||||
check_available (n);
|
||||
offset += n;
|
||||
_offset += n;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -597,4 +657,6 @@ namespace Frida {
|
||||
throw new Error.PROTOCOL ("Malformed buffer: truncated");
|
||||
}
|
||||
}
|
||||
|
||||
public extern Bytes make_bytes_with_owner<T> (void * data, size_t size, owned T? owner = null);
|
||||
}
|
||||
@@ -13,6 +13,7 @@ base_sources = [
|
||||
'socket.vala',
|
||||
'socket-glue.c',
|
||||
'buffer.vala',
|
||||
'buffer-glue.c',
|
||||
'value.vala',
|
||||
]
|
||||
|
||||
|
||||
+52
-12
@@ -46,7 +46,8 @@ namespace Frida {
|
||||
}
|
||||
private GLib.Error? _error;
|
||||
|
||||
private Gee.ArrayQueue<CompletionFuncEntry> on_complete;
|
||||
private Gee.ArrayQueue<CompletionFuncEntry>? on_complete;
|
||||
private Gee.ArrayQueue<ThenHandlerEntry<T>>? on_then;
|
||||
|
||||
public async T wait_async (Cancellable? cancellable) throws Frida.Error, IOError {
|
||||
if (_ready)
|
||||
@@ -74,7 +75,21 @@ namespace Frida {
|
||||
return get_result ();
|
||||
}
|
||||
|
||||
private T get_result () throws Frida.Error, IOError {
|
||||
public void then (owned FutureCompletionHandler<T> handler) {
|
||||
if (_ready) {
|
||||
schedule (() => {
|
||||
handler (this);
|
||||
return Source.REMOVE;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (on_then == null)
|
||||
on_then = new Gee.ArrayQueue<ThenHandlerEntry<T>> ();
|
||||
on_then.offer (new ThenHandlerEntry<T> ((owned) handler));
|
||||
}
|
||||
|
||||
public T get_result () throws Frida.Error, IOError {
|
||||
if (error != null) {
|
||||
if (error is Frida.Error)
|
||||
throw (Frida.Error) error;
|
||||
@@ -111,19 +126,32 @@ namespace Frida {
|
||||
internal void transition_to_ready () {
|
||||
_ready = true;
|
||||
|
||||
if (on_complete != null && !on_complete.is_empty) {
|
||||
var source = new IdleSource ();
|
||||
source.set_priority (Priority.HIGH);
|
||||
source.set_callback (() => {
|
||||
CompletionFuncEntry? entry;
|
||||
while ((entry = on_complete.poll ()) != null)
|
||||
entry.func ();
|
||||
on_complete = null;
|
||||
return false;
|
||||
if (on_complete != null || on_then != null) {
|
||||
schedule (() => {
|
||||
if (on_complete != null) {
|
||||
CompletionFuncEntry? entry;
|
||||
while ((entry = on_complete.poll ()) != null)
|
||||
entry.func ();
|
||||
on_complete = null;
|
||||
}
|
||||
|
||||
if (on_then != null) {
|
||||
ThenHandlerEntry? entry;
|
||||
while ((entry = on_then.poll ()) != null)
|
||||
entry.handler (this);
|
||||
on_then = null;
|
||||
}
|
||||
|
||||
return Source.REMOVE;
|
||||
});
|
||||
source.attach (MainContext.get_thread_default ());
|
||||
}
|
||||
}
|
||||
|
||||
private static void schedule (owned SourceFunc function) {
|
||||
var source = new IdleSource ();
|
||||
source.set_callback ((owned) function);
|
||||
source.attach (MainContext.get_thread_default ());
|
||||
}
|
||||
}
|
||||
|
||||
private class CompletionFuncEntry {
|
||||
@@ -133,6 +161,14 @@ namespace Frida {
|
||||
this.func = (owned) func;
|
||||
}
|
||||
}
|
||||
|
||||
private class ThenHandlerEntry<T> {
|
||||
public FutureCompletionHandler<T> handler;
|
||||
|
||||
public ThenHandlerEntry (owned FutureCompletionHandler<T> handler) {
|
||||
this.handler = (owned) handler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Future<T> : Object {
|
||||
@@ -140,5 +176,9 @@ namespace Frida {
|
||||
public abstract T? value { get; }
|
||||
public abstract GLib.Error? error { get; }
|
||||
public abstract async T wait_async (Cancellable? cancellable) throws Frida.Error, IOError;
|
||||
public abstract void then (owned FutureCompletionHandler<T> handler);
|
||||
public abstract T get_result () throws Frida.Error, IOError;
|
||||
}
|
||||
|
||||
public delegate void FutureCompletionHandler<T> (Future<T> future);
|
||||
}
|
||||
@@ -30,7 +30,7 @@ _frida_query_windows_computer_name (void)
|
||||
return g_utf16_to_utf8 (buffer, -1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
#elif defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#elif defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
@@ -749,6 +749,19 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.GadgetSession17")]
|
||||
public interface GadgetSession : Object {
|
||||
public abstract async void break_and_resume (Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void break_and_detach (Cancellable? cancellable) throws GLib.Error;
|
||||
}
|
||||
|
||||
public enum GadgetBreakpointAction {
|
||||
INVOKE_RETURN,
|
||||
RESUME,
|
||||
DETACH,
|
||||
PAGE_PLAN,
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.Channel17")]
|
||||
public interface Channel : Object {
|
||||
public abstract async void close (Cancellable? cancellable) throws GLib.Error;
|
||||
@@ -1952,6 +1965,8 @@ namespace Frida {
|
||||
id = "watchos";
|
||||
#elif TVOS
|
||||
id = "tvos";
|
||||
#elif XROS
|
||||
id = "xros";
|
||||
#elif ANDROID
|
||||
id = "android";
|
||||
#elif FREEBSD
|
||||
@@ -2119,6 +2134,7 @@ namespace Frida {
|
||||
public const string AGENT_SESSION = "/re/frida/AgentSession";
|
||||
public const string AGENT_CONTROLLER = "/re/frida/AgentController";
|
||||
public const string AGENT_MESSAGE_SINK = "/re/frida/AgentMessageSink";
|
||||
public const string GADGET_SESSION = "/re/frida/GadgetSession";
|
||||
public const string CHANNEL = "/re/frida/Channel";
|
||||
public const string SERVICE = "/re/frida/Service";
|
||||
public const string TRANSPORT_BROKER = "/re/frida/TransportBroker";
|
||||
|
||||
+166
-1
@@ -1,9 +1,25 @@
|
||||
#if defined (HAVE_TVOS) || defined (HAVE_WATCHOS)
|
||||
# include <Availability.h>
|
||||
# undef __TVOS_PROHIBITED
|
||||
# define __TVOS_PROHIBITED
|
||||
# undef __WATCHOS_PROHIBITED
|
||||
# define __WATCHOS_PROHIBITED
|
||||
#endif
|
||||
|
||||
#include "frida-gadget.h"
|
||||
|
||||
#include "frida-base.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <gum/gumdarwin.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <objc/runtime.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static void frida_on_breakpoints_steal_attempt (GumInvocationContext * ic, gpointer user_data);
|
||||
|
||||
static GumInvocationListener * frida_dont_steal_my_breakpoints;
|
||||
|
||||
gchar *
|
||||
frida_gadget_environment_detect_bundle_id (void)
|
||||
{
|
||||
@@ -27,7 +43,7 @@ frida_gadget_environment_detect_bundle_name (void)
|
||||
gchar *
|
||||
frida_gadget_environment_detect_documents_dir (void)
|
||||
{
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
@autoreleasepool
|
||||
{
|
||||
NSArray<NSString *> * paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
@@ -51,3 +67,152 @@ frida_gadget_environment_set_thread_name (const gchar * name)
|
||||
/* For now only implemented on i/macOS as Fruity.Injector relies on it there. */
|
||||
pthread_setname_np (name);
|
||||
}
|
||||
|
||||
void
|
||||
frida_gadget_environment_detect_darwin_location_fields (GumAddress our_address, gchar ** executable_name, gchar ** our_path,
|
||||
GumMemoryRange ** our_range)
|
||||
{
|
||||
mach_port_t task;
|
||||
GumDarwinModuleResolver * resolver;
|
||||
GPtrArray * modules;
|
||||
guint i;
|
||||
|
||||
task = mach_task_self ();
|
||||
|
||||
resolver = gum_darwin_module_resolver_new (task, NULL);
|
||||
if (resolver == NULL)
|
||||
return;
|
||||
|
||||
gum_darwin_module_resolver_fetch_modules (resolver, &modules, NULL);
|
||||
|
||||
for (i = 0; i != modules->len; i++)
|
||||
{
|
||||
GumModule * module;
|
||||
const GumMemoryRange * range;
|
||||
|
||||
module = g_ptr_array_index (modules, i);
|
||||
range = gum_module_get_range (module);
|
||||
|
||||
if (*executable_name == NULL)
|
||||
{
|
||||
gum_mach_header_t * header = GSIZE_TO_POINTER (range->base_address);
|
||||
if (header->filetype == MH_EXECUTE)
|
||||
*executable_name = g_strdup (gum_module_get_name (module));
|
||||
}
|
||||
|
||||
if (our_address >= range->base_address && our_address < range->base_address + range->size)
|
||||
{
|
||||
if (*our_path == NULL)
|
||||
*our_path = g_strdup (gum_module_get_path (module));
|
||||
|
||||
if (*our_range == NULL)
|
||||
*our_range = gum_memory_range_copy (range);
|
||||
}
|
||||
|
||||
if (*executable_name != NULL && *our_path != NULL && *our_range != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
g_ptr_array_unref (modules);
|
||||
|
||||
g_object_unref (resolver);
|
||||
}
|
||||
|
||||
void
|
||||
frida_gadget_environment_ensure_debugger_breakpoints_only (void)
|
||||
{
|
||||
task_set_exception_ports (
|
||||
mach_task_self (),
|
||||
EXC_MASK_ALL & ~EXC_MASK_BREAKPOINT,
|
||||
MACH_PORT_NULL,
|
||||
EXCEPTION_DEFAULT,
|
||||
THREAD_STATE_NONE
|
||||
);
|
||||
|
||||
if (gum_process_get_code_signing_policy () == GUM_CODE_SIGNING_OPTIONAL &&
|
||||
frida_dont_steal_my_breakpoints == NULL &&
|
||||
gum_darwin_is_debugger_mapping_enforced ())
|
||||
{
|
||||
gpointer exceptions_set, exceptions_swap;
|
||||
GumInterceptor * interceptor;
|
||||
|
||||
exceptions_set = &task_set_exception_ports;
|
||||
exceptions_swap = &task_swap_exception_ports;
|
||||
|
||||
frida_dont_steal_my_breakpoints = gum_make_call_listener (frida_on_breakpoints_steal_attempt,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
interceptor = gum_interceptor_obtain ();
|
||||
|
||||
gum_interceptor_attach (interceptor, exceptions_set, frida_dont_steal_my_breakpoints,
|
||||
NULL, GUM_ATTACH_FLAGS_NONE);
|
||||
gum_interceptor_attach (interceptor, exceptions_swap, frida_dont_steal_my_breakpoints,
|
||||
NULL, GUM_ATTACH_FLAGS_NONE);
|
||||
|
||||
g_object_unref (interceptor);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
frida_gadget_environment_allow_stolen_breakpoints (void)
|
||||
{
|
||||
GumInterceptor * interceptor;
|
||||
|
||||
if (frida_dont_steal_my_breakpoints == NULL)
|
||||
return;
|
||||
|
||||
interceptor = gum_interceptor_obtain ();
|
||||
|
||||
gum_interceptor_detach (interceptor, frida_dont_steal_my_breakpoints);
|
||||
|
||||
g_object_unref (frida_dont_steal_my_breakpoints);
|
||||
frida_dont_steal_my_breakpoints = NULL;
|
||||
|
||||
g_object_unref (interceptor);
|
||||
}
|
||||
|
||||
static void
|
||||
frida_on_breakpoints_steal_attempt (GumInvocationContext * ic, gpointer user_data)
|
||||
{
|
||||
exception_mask_t exception_mask;
|
||||
|
||||
exception_mask = GPOINTER_TO_SIZE (gum_invocation_context_get_nth_argument (ic, 1));
|
||||
exception_mask &= ~EXC_MASK_BREAKPOINT;
|
||||
gum_invocation_context_replace_nth_argument (ic, 1, GSIZE_TO_POINTER (exception_mask));
|
||||
}
|
||||
|
||||
void
|
||||
frida_gadget_environment_break_and_resume (void)
|
||||
{
|
||||
#ifdef HAVE_ARM64
|
||||
asm volatile (
|
||||
"mov x1, #1337\n\t"
|
||||
"mov x2, #1337\n\t"
|
||||
"mov x3, %0\n\t"
|
||||
"brk #1337\n\t"
|
||||
:
|
||||
: "r" ((gsize) FRIDA_GADGET_BREAKPOINT_ACTION_RESUME)
|
||||
: "x1", "x2", "x3"
|
||||
);
|
||||
#else
|
||||
g_assert_not_reached ();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
frida_gadget_environment_break_and_detach (void)
|
||||
{
|
||||
#ifdef HAVE_ARM64
|
||||
asm volatile (
|
||||
"mov x1, #1337\n\t"
|
||||
"mov x2, #1337\n\t"
|
||||
"mov x3, %0\n\t"
|
||||
"brk #1337\n\t"
|
||||
:
|
||||
: "r" ((gsize) FRIDA_GADGET_BREAKPOINT_ACTION_DETACH)
|
||||
: "x1", "x2", "x3"
|
||||
);
|
||||
#else
|
||||
g_assert_not_reached ();
|
||||
#endif
|
||||
}
|
||||
+46
-84
@@ -24,12 +24,6 @@ namespace Frida.Gadget {
|
||||
default = Gum.CodeSigningPolicy.OPTIONAL;
|
||||
}
|
||||
|
||||
private ObjectClass klass = (ObjectClass) typeof (Config).class_ref ();
|
||||
|
||||
public Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
|
||||
return default_serialize_property (property_name, value, pspec);
|
||||
}
|
||||
|
||||
public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
|
||||
if (property_name == "interaction" && property_node.get_node_type () == Json.NodeType.OBJECT) {
|
||||
var interaction_node = property_node.get_object ();
|
||||
@@ -77,20 +71,6 @@ namespace Frida.Gadget {
|
||||
value = Value (pspec.value_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
public unowned ParamSpec? find_property (string name) {
|
||||
return klass.find_property (name);
|
||||
}
|
||||
|
||||
public new Value get_property (ParamSpec pspec) {
|
||||
var val = Value (pspec.value_type);
|
||||
base.get_property (pspec.name, ref val);
|
||||
return val;
|
||||
}
|
||||
|
||||
public new void set_property (ParamSpec pspec, Value value) {
|
||||
base.set_property (pspec.name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class ScriptInteraction : Object, Json.Serializable {
|
||||
@@ -112,12 +92,6 @@ namespace Frida.Gadget {
|
||||
default = Script.ChangeBehavior.IGNORE;
|
||||
}
|
||||
|
||||
private ObjectClass klass = (ObjectClass) typeof (ScriptInteraction).class_ref ();
|
||||
|
||||
public Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
|
||||
return default_serialize_property (property_name, value, pspec);
|
||||
}
|
||||
|
||||
public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
|
||||
if (property_name == "parameters" && property_node.get_node_type () == Json.NodeType.OBJECT) {
|
||||
var v = Value (typeof (Json.Node));
|
||||
@@ -129,20 +103,6 @@ namespace Frida.Gadget {
|
||||
value = Value (pspec.value_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
public unowned ParamSpec? find_property (string name) {
|
||||
return klass.find_property (name);
|
||||
}
|
||||
|
||||
public new Value get_property (ParamSpec pspec) {
|
||||
var val = Value (pspec.value_type);
|
||||
base.get_property (pspec.name, ref val);
|
||||
return val;
|
||||
}
|
||||
|
||||
public new void set_property (ParamSpec pspec, Value value) {
|
||||
base.set_property (pspec.name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class ScriptDirectoryInteraction : Object {
|
||||
@@ -183,12 +143,6 @@ namespace Frida.Gadget {
|
||||
default = Script.ChangeBehavior.IGNORE;
|
||||
}
|
||||
|
||||
private ObjectClass klass = (ObjectClass) typeof (ScriptConfig).class_ref ();
|
||||
|
||||
public Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
|
||||
return default_serialize_property (property_name, value, pspec);
|
||||
}
|
||||
|
||||
public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
|
||||
if (property_name == "parameters" && property_node.get_node_type () == Json.NodeType.OBJECT) {
|
||||
var v = Value (typeof (Json.Node));
|
||||
@@ -200,20 +154,6 @@ namespace Frida.Gadget {
|
||||
value = Value (pspec.value_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
public unowned ParamSpec? find_property (string name) {
|
||||
return klass.find_property (name);
|
||||
}
|
||||
|
||||
public new Value get_property (ParamSpec pspec) {
|
||||
var val = Value (pspec.value_type);
|
||||
base.get_property (pspec.name, ref val);
|
||||
return val;
|
||||
}
|
||||
|
||||
public new void set_property (ParamSpec pspec, Value value) {
|
||||
base.set_property (pspec.name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class ProcessFilter : Object {
|
||||
@@ -299,8 +239,6 @@ namespace Frida.Gadget {
|
||||
default = make_empty_json_object ();
|
||||
}
|
||||
|
||||
private ObjectClass klass = (ObjectClass) typeof (ConnectInteraction).class_ref ();
|
||||
|
||||
public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
|
||||
if (property_name == "parameters" && property_node.get_node_type () == Json.NodeType.OBJECT) {
|
||||
var v = Value (typeof (Json.Node));
|
||||
@@ -312,20 +250,6 @@ namespace Frida.Gadget {
|
||||
value = Value (pspec.value_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
public unowned ParamSpec? find_property (string name) {
|
||||
return klass.find_property (name);
|
||||
}
|
||||
|
||||
public new Value get_property (ParamSpec pspec) {
|
||||
var val = Value (pspec.value_type);
|
||||
base.get_property (pspec.name, ref val);
|
||||
return val;
|
||||
}
|
||||
|
||||
public new void set_property (ParamSpec pspec, Value value) {
|
||||
base.set_property (pspec.name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class Location : Object {
|
||||
@@ -481,6 +405,12 @@ namespace Frida.Gadget {
|
||||
|
||||
interceptor = Gum.Interceptor.obtain ();
|
||||
interceptor.begin_transaction ();
|
||||
|
||||
#if DARWIN
|
||||
if (mapped_range != null)
|
||||
Environment.ensure_debugger_breakpoints_only ();
|
||||
#endif
|
||||
|
||||
exceptor = Gum.Exceptor.obtain ();
|
||||
|
||||
try {
|
||||
@@ -700,6 +630,11 @@ namespace Frida.Gadget {
|
||||
controller = null;
|
||||
|
||||
exceptor = null;
|
||||
|
||||
#if DARWIN
|
||||
Environment.allow_stolen_breakpoints ();
|
||||
#endif
|
||||
|
||||
interceptor = null;
|
||||
}
|
||||
}
|
||||
@@ -759,7 +694,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
|
||||
try {
|
||||
return Json.gobject_from_data (typeof (Config), config_data) as Config;
|
||||
return (Config) Json.gobject_from_data (typeof (Config), config_data);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid config: %s", e.message);
|
||||
}
|
||||
@@ -767,7 +702,7 @@ namespace Frida.Gadget {
|
||||
|
||||
private Config parse_config (string config_data) throws Error {
|
||||
try {
|
||||
return Json.gobject_from_data (typeof (Config), config_data) as Config;
|
||||
return (Config) Json.gobject_from_data (typeof (Config), config_data);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid config: %s", e.message);
|
||||
}
|
||||
@@ -775,21 +710,20 @@ namespace Frida.Gadget {
|
||||
|
||||
private Location detect_location (Gum.MemoryRange? mapped_range) {
|
||||
string? executable_name = null;
|
||||
string? executable_path = null;
|
||||
Gum.MemoryRange? executable_range = null;
|
||||
string? our_path = null;
|
||||
Gum.MemoryRange? our_range = mapped_range;
|
||||
|
||||
Gum.Address our_address = Gum.Address.from_pointer (Gum.strip_code_pointer ((void *) detect_location));
|
||||
|
||||
#if DARWIN
|
||||
Environment.detect_darwin_location_fields (our_address, ref executable_name, ref our_path, ref our_range);
|
||||
#else
|
||||
var index = 0;
|
||||
Gum.Process.enumerate_modules ((details) => {
|
||||
var range = details.range;
|
||||
|
||||
if (index == 0) {
|
||||
executable_name = details.name;
|
||||
executable_path = details.path;
|
||||
executable_range = details.range;
|
||||
}
|
||||
|
||||
if (mapped_range != null)
|
||||
@@ -805,6 +739,7 @@ namespace Frida.Gadget {
|
||||
|
||||
return true;
|
||||
});
|
||||
#endif
|
||||
|
||||
assert (our_range != null);
|
||||
|
||||
@@ -1234,7 +1169,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
|
||||
try {
|
||||
return Json.gobject_from_data (typeof (ScriptConfig), data) as ScriptConfig;
|
||||
return (ScriptConfig) Json.gobject_from_data (typeof (ScriptConfig), data);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid config: %s", e.message);
|
||||
}
|
||||
@@ -1748,7 +1683,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class ControlChannel : Object, Peer, HostSession {
|
||||
private class ControlChannel : Object, Peer, HostSession, GadgetSession {
|
||||
public weak ControlServer parent {
|
||||
get;
|
||||
construct;
|
||||
@@ -1779,6 +1714,9 @@ namespace Frida.Gadget {
|
||||
HostSession host_session = this;
|
||||
registrations.add (connection.register_object (Frida.ObjectPath.HOST_SESSION, host_session));
|
||||
|
||||
GadgetSession gadget_session = this;
|
||||
registrations.add (connection.register_object (Frida.ObjectPath.GADGET_SESSION, gadget_session));
|
||||
|
||||
AuthenticationService null_auth = new NullAuthenticationService ();
|
||||
registrations.add (connection.register_object (Frida.ObjectPath.AUTHENTICATION_SERVICE, null_auth));
|
||||
} catch (IOError e) {
|
||||
@@ -1941,6 +1879,22 @@ namespace Frida.Gadget {
|
||||
throw new Error.NOT_SUPPORTED ("Unable to open services when embedded");
|
||||
}
|
||||
|
||||
public async void break_and_resume (Cancellable? cancellable) throws Error, IOError {
|
||||
#if DARWIN
|
||||
Environment.break_and_resume ();
|
||||
#else
|
||||
throw new Error.NOT_SUPPORTED ("This API is only applicable on Darwin");
|
||||
#endif
|
||||
}
|
||||
|
||||
public async void break_and_detach (Cancellable? cancellable) throws Error, IOError {
|
||||
#if DARWIN
|
||||
Environment.break_and_detach ();
|
||||
#else
|
||||
throw new Error.NOT_SUPPORTED ("This API is only applicable on Darwin");
|
||||
#endif
|
||||
}
|
||||
|
||||
private void validate_pid (uint pid) throws Error {
|
||||
if (pid != this_process.pid)
|
||||
throw new Error.NOT_SUPPORTED ("Unable to act on other processes when embedded");
|
||||
@@ -2176,6 +2130,14 @@ namespace Frida.Gadget {
|
||||
private extern bool has_objc_class (string name);
|
||||
|
||||
private extern void set_thread_name (string name);
|
||||
#if DARWIN
|
||||
private extern void detect_darwin_location_fields (Gum.Address our_address, ref string? executable_name,
|
||||
ref string? our_path, ref Gum.MemoryRange? our_range);
|
||||
private extern void ensure_debugger_breakpoints_only ();
|
||||
private extern void allow_stolen_breakpoints ();
|
||||
private extern void break_and_resume ();
|
||||
private extern void break_and_detach ();
|
||||
#endif
|
||||
}
|
||||
|
||||
private extern void log_info (string message);
|
||||
|
||||
+68
-33
@@ -44,11 +44,17 @@ namespace Frida {
|
||||
|
||||
#if ANDROID
|
||||
public sealed class ThreadCountCloaker : Object {
|
||||
private GetOsThreadStat * get_os_thread_stat_slot;
|
||||
private static GetOsThreadStat old_get_os_thread_stat_impl;
|
||||
|
||||
private ReadFunc * read_slot;
|
||||
private static ReadFunc old_read_impl;
|
||||
|
||||
private static string expected_magic = "%u (".printf (Posix.getpid ());
|
||||
|
||||
[CCode (has_target = false)]
|
||||
private delegate ssize_t GetOsThreadStat (Posix.pid_t tid, void * buf, size_t count);
|
||||
|
||||
[CCode (has_target = false)]
|
||||
private delegate ssize_t ReadFunc (int fd, void * buf, size_t count);
|
||||
|
||||
@@ -56,39 +62,64 @@ namespace Frida {
|
||||
var art = Gum.Process.find_module_by_name ("libart.so");
|
||||
if (art != null) {
|
||||
art.enumerate_imports (imp => {
|
||||
if (imp.name == "read") {
|
||||
if (imp.name == "_ZN3art15GetOsThreadStatEiPcm" || imp.name == "_ZN3art15GetOsThreadStatEiPcj") {
|
||||
get_os_thread_stat_slot = (GetOsThreadStat *) imp.slot;
|
||||
} else if (imp.name == "read") {
|
||||
read_slot = (ReadFunc *) imp.slot;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (read_slot != null)
|
||||
old_read_impl = update_read_slot (on_read);
|
||||
if (get_os_thread_stat_slot != null) {
|
||||
old_get_os_thread_stat_impl = (GetOsThreadStat) update_slot ((void **) get_os_thread_stat_slot,
|
||||
(void *) on_get_os_thread_stat);
|
||||
}
|
||||
if (read_slot != null) {
|
||||
old_read_impl = (ReadFunc) update_slot ((void **) read_slot, (void *) on_read);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~ThreadCountCloaker () {
|
||||
if (read_slot != null)
|
||||
update_read_slot (old_read_impl);
|
||||
public override void dispose () {
|
||||
if (get_os_thread_stat_slot != null) {
|
||||
update_slot ((void **) get_os_thread_stat_slot, (void *) old_get_os_thread_stat_impl);
|
||||
}
|
||||
if (read_slot != null) {
|
||||
update_slot ((void **) read_slot, (void *) old_read_impl);
|
||||
}
|
||||
|
||||
base.dispose ();
|
||||
}
|
||||
|
||||
private ReadFunc update_read_slot (ReadFunc new_impl) {
|
||||
private static void * update_slot (void ** orig, void * new_impl) {
|
||||
Gum.PageProtection old_prot = READ;
|
||||
Gum.Memory.query_protection (read_slot, out old_prot);
|
||||
Gum.Memory.query_protection (orig, out old_prot);
|
||||
|
||||
bool is_writable = (old_prot & Gum.PageProtection.WRITE) != 0;
|
||||
if (!is_writable)
|
||||
Gum.mprotect (read_slot, sizeof (void *), old_prot | WRITE);
|
||||
Gum.mprotect (orig, sizeof (void *), old_prot | WRITE);
|
||||
|
||||
ReadFunc old_impl = *read_slot;
|
||||
*read_slot = new_impl;
|
||||
void * old_impl = *orig;
|
||||
*orig = new_impl;
|
||||
|
||||
if (!is_writable)
|
||||
Gum.mprotect (read_slot, sizeof (void *), old_prot);
|
||||
Gum.mprotect (orig, sizeof (void *), old_prot);
|
||||
|
||||
return old_impl;
|
||||
}
|
||||
|
||||
private static ssize_t on_get_os_thread_stat (Posix.pid_t tid, void * buf, size_t count) {
|
||||
ssize_t n = old_get_os_thread_stat_impl (tid, buf, count);
|
||||
|
||||
if (tid == Posix.getpid ()) {
|
||||
try {
|
||||
n = adjust_thread_count (buf, n, count);
|
||||
} catch (FileError e) {
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
private static ssize_t on_read (int fd, void * buf, size_t count) {
|
||||
var n = old_read_impl (fd, buf, count);
|
||||
if (n <= 0)
|
||||
@@ -101,32 +132,36 @@ namespace Frida {
|
||||
if (!file_descriptor_is_proc_self_stat (fd))
|
||||
return n;
|
||||
|
||||
unowned string raw_str = (string) buf;
|
||||
string str = raw_str.substring (0, n);
|
||||
|
||||
MatchInfo info;
|
||||
if (!/^(\d+ \(.+\)(?: [^ ]+){17}) \d+ (.+)/s.match (str, 0, out info))
|
||||
return n;
|
||||
string fields_before = info.fetch (1);
|
||||
string fields_after = info.fetch (2);
|
||||
|
||||
// We cannot simply use the value we got from the kernel and subtract the number of cloaked threads,
|
||||
// as there's a chance the total may have changed in the last moment.
|
||||
uint num_uncloaked_threads = query_num_uncloaked_threads ();
|
||||
|
||||
string adjusted_str = "%s %u %s".printf (fields_before, num_uncloaked_threads, fields_after);
|
||||
|
||||
var adjusted_length = adjusted_str.length;
|
||||
if (adjusted_length > count)
|
||||
return n;
|
||||
Memory.copy (buf, adjusted_str, adjusted_length);
|
||||
n = adjusted_length;
|
||||
n = adjust_thread_count (buf, n, count);
|
||||
} catch (FileError e) {
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
private static ssize_t adjust_thread_count (void * buf, ssize_t n, size_t count) throws FileError {
|
||||
unowned string raw_str = (string) buf;
|
||||
string str = raw_str.substring (0, n);
|
||||
|
||||
MatchInfo info;
|
||||
if (!/^(\d+ \(.+\)(?: [^ ]+){17}) \d+ (.+)/s.match (str, 0, out info))
|
||||
return n;
|
||||
string fields_before = info.fetch (1);
|
||||
string fields_after = info.fetch (2);
|
||||
|
||||
// We cannot simply use the value we got from the kernel and subtract the number of cloaked threads,
|
||||
// as there's a chance the total may have changed in the last moment.
|
||||
uint num_uncloaked_threads = query_num_uncloaked_threads ();
|
||||
|
||||
string adjusted_str = "%s %u %s".printf (fields_before, num_uncloaked_threads, fields_after);
|
||||
|
||||
var adjusted_length = adjusted_str.length;
|
||||
if (adjusted_length > count)
|
||||
return n;
|
||||
Memory.copy (buf, adjusted_str, adjusted_length);
|
||||
return adjusted_length;
|
||||
}
|
||||
|
||||
private static bool file_content_might_be_from_proc_self_stat (void * content, ssize_t size) {
|
||||
if (size < expected_magic.length)
|
||||
return false;
|
||||
|
||||
+10
-5
@@ -12,9 +12,11 @@ if not meson.get_compiler('vala').version().endswith('-frida')
|
||||
error('''Incompatible Vala compiler detected.
|
||||
|
||||
Frida currently relies on features not yet upstream. Grab the Frida-optimized
|
||||
Vala compiler from:
|
||||
Vala sources from:
|
||||
|
||||
https://github.com/frida/vala''')
|
||||
https://github.com/frida/vala
|
||||
|
||||
and compile them with Meson.''')
|
||||
endif
|
||||
|
||||
c_languages = ['c', 'cpp']
|
||||
@@ -269,12 +271,14 @@ if host_os == 'linux'
|
||||
#endif
|
||||
'''
|
||||
if cc.compiles(glibc_src, name: 'compiling for glibc')
|
||||
cdata.set('HAVE_GLIBC', 1)
|
||||
libc = 'glibc'
|
||||
elif cc.compiles(uclibc_src, name: 'compiling for uClibc')
|
||||
cdata.set('HAVE_UCLIBC', 1)
|
||||
libc = 'uclibc'
|
||||
else
|
||||
cdata.set('HAVE_MUSL', 1)
|
||||
libc = 'musl'
|
||||
endif
|
||||
cdata.set('HAVE_' + libc.to_upper(), 1)
|
||||
vala_flags += '--define=' + libc.to_upper()
|
||||
endif
|
||||
|
||||
if get_option('b_sanitize') == 'address'
|
||||
@@ -654,6 +658,7 @@ if get_option('devkits').length() != 0
|
||||
mkdevkit = [python, releng / 'mkdevkit.py']
|
||||
uninstalled_dir = meson.global_build_root() / 'meson-uninstalled'
|
||||
devkit_options = [
|
||||
'--dep-symbol-scope', get_option('devkit_symbol_scope'),
|
||||
'--cc', '>>>', cc.cmd_array(), '<<<',
|
||||
'--c-args', '>>>', get_option('c_args'), '<<<',
|
||||
'--pkg-config', '>>>', find_program('pkg-config'), '<<<',
|
||||
|
||||
@@ -150,6 +150,15 @@ option('devkits',
|
||||
description: 'Devkits to build'
|
||||
)
|
||||
|
||||
option('devkit_symbol_scope',
|
||||
type: 'combo',
|
||||
choices: ['prefixed', 'original'],
|
||||
value: 'prefixed',
|
||||
description : 'How devkit generation treats third-party symbols:\n'
|
||||
+ ' - prefixed: add the \'_frida_\' prefix\n'
|
||||
+ ' - original: keep symbols exactly as upstream\n'
|
||||
)
|
||||
|
||||
option('tests',
|
||||
type: 'feature',
|
||||
value: 'auto',
|
||||
|
||||
+1
-1
Submodule releng updated: e10baa39a2...2b34e1c008.
+1
-1
@@ -6,7 +6,7 @@ server_sources = [
|
||||
if host_os_family == 'darwin'
|
||||
server_sources += ['server-darwin.m']
|
||||
endif
|
||||
if host_os in ['ios', 'tvos']
|
||||
if host_os in ['ios', 'tvos', 'xros']
|
||||
server_sources += [
|
||||
'server-ios-tvos.c',
|
||||
]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "server-glue.h"
|
||||
|
||||
#include "frida-core.h"
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
# include "server-ios-tvos.h"
|
||||
#endif
|
||||
#ifdef HAVE_ANDROID
|
||||
@@ -54,7 +54,7 @@ frida_server_environment_set_verbose_logging_enabled (gboolean enabled)
|
||||
void
|
||||
frida_server_environment_configure (void)
|
||||
{
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
_frida_server_ios_tvos_configure ();
|
||||
#endif
|
||||
|
||||
|
||||
+99
-23
@@ -14,59 +14,79 @@ namespace Frida.Barebone {
|
||||
get;
|
||||
}
|
||||
|
||||
public abstract size_t size {
|
||||
get;
|
||||
}
|
||||
|
||||
public abstract async void deallocate (Cancellable? cancellable) throws Error, IOError;
|
||||
}
|
||||
|
||||
public sealed class SimpleAllocator : Object, Allocator {
|
||||
public sealed class NullAllocator : Object, Allocator {
|
||||
public size_t page_size {
|
||||
get { return _page_size; }
|
||||
get {
|
||||
return _page_size;
|
||||
}
|
||||
}
|
||||
|
||||
private size_t _page_size;
|
||||
|
||||
public NullAllocator (size_t page_size) {
|
||||
this._page_size = page_size;
|
||||
}
|
||||
|
||||
public async Allocation allocate (size_t size, size_t alignment, Cancellable? cancellable) throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("To enable this feature, specify an allocator in your FRIDA_BAREBONE_CONFIG");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PhysicalAllocator : Object, Allocator {
|
||||
public size_t page_size {
|
||||
get {
|
||||
return _page_size;
|
||||
}
|
||||
}
|
||||
|
||||
private Machine machine;
|
||||
private size_t _page_size;
|
||||
private uint64 base_pa;
|
||||
|
||||
private uint64 cursor;
|
||||
|
||||
public SimpleAllocator (Machine machine, size_t page_size, uint64 base_pa) {
|
||||
public PhysicalAllocator (Machine machine, size_t page_size, PhysicalAllocatorConfig config) {
|
||||
this.machine = machine;
|
||||
this._page_size = page_size;
|
||||
this.base_pa = base_pa;
|
||||
this.cursor = base_pa;
|
||||
this.cursor = config.physical_base;
|
||||
}
|
||||
|
||||
public async Allocation allocate (size_t size, size_t alignment, Cancellable? cancellable) throws Error, IOError {
|
||||
if (base_pa == 0) {
|
||||
uint64 example_base;
|
||||
if ("corellium" in machine.gdb.features)
|
||||
example_base = 0x0800000000 + ((2048 - 3) * 1024 * 1024);
|
||||
else
|
||||
example_base = 0x0040000000 + (128 * 1024 * 1024);
|
||||
throw new Error.NOT_SUPPORTED ("To enable this feature, set FRIDA_BAREBONE_HEAP_BASE to the physical " +
|
||||
"base address to use, e.g. 0x%" + uint64.FORMAT_MODIFIER + "x", example_base);
|
||||
}
|
||||
|
||||
uint64 address_pa = cursor;
|
||||
|
||||
size_t vm_size = round_size_up (size, page_size);
|
||||
size_t vm_size = round_size_up (size, _page_size);
|
||||
cursor += vm_size;
|
||||
|
||||
uint num_pages = (uint) (vm_size / page_size);
|
||||
uint num_pages = (uint) (vm_size / _page_size);
|
||||
|
||||
Allocation page_allocation = yield machine.allocate_pages (address_pa, num_pages, cancellable);
|
||||
|
||||
return new SimpleAllocation (page_allocation);
|
||||
return new PhysicalAllocation (page_allocation);
|
||||
}
|
||||
|
||||
private class SimpleAllocation : Object, Allocation {
|
||||
private class PhysicalAllocation : Object, Allocation {
|
||||
public uint64 virtual_address {
|
||||
get { return page_allocation.virtual_address; }
|
||||
get {
|
||||
return page_allocation.virtual_address;
|
||||
}
|
||||
}
|
||||
|
||||
public size_t size {
|
||||
get {
|
||||
return page_allocation.size;
|
||||
}
|
||||
}
|
||||
|
||||
private Allocation page_allocation;
|
||||
|
||||
public SimpleAllocation (Allocation page_allocation) {
|
||||
this.page_allocation = page_allocation;
|
||||
public PhysicalAllocation (Allocation allocation) {
|
||||
page_allocation = allocation;
|
||||
}
|
||||
|
||||
public async void deallocate (Cancellable? cancellable) throws Error, IOError {
|
||||
@@ -75,4 +95,60 @@ namespace Frida.Barebone {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TargetFunctionsAllocator : Object, Allocator {
|
||||
public size_t page_size {
|
||||
get {
|
||||
return _page_size;
|
||||
}
|
||||
}
|
||||
|
||||
private Machine machine;
|
||||
private size_t _page_size;
|
||||
private TargetFunctionsAllocatorConfig config;
|
||||
|
||||
public TargetFunctionsAllocator (Machine machine, size_t page_size, TargetFunctionsAllocatorConfig config) {
|
||||
this.machine = machine;
|
||||
this._page_size = page_size;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public async Allocation allocate (size_t size, size_t alignment, Cancellable? cancellable) throws Error, IOError {
|
||||
uint64 address = yield machine.invoke (config.alloc_function, { size }, cancellable);
|
||||
|
||||
// TODO: Handle alignment.
|
||||
|
||||
return new TargetAllocation (address, size, machine, config);
|
||||
}
|
||||
|
||||
private class TargetAllocation : Object, Allocation {
|
||||
public uint64 virtual_address {
|
||||
get {
|
||||
return _virtual_address;
|
||||
}
|
||||
}
|
||||
|
||||
public size_t size {
|
||||
get {
|
||||
return _size;
|
||||
}
|
||||
}
|
||||
|
||||
private uint64 _virtual_address;
|
||||
public size_t _size;
|
||||
private Machine machine;
|
||||
private TargetFunctionsAllocatorConfig config;
|
||||
|
||||
public TargetAllocation (uint64 address, size_t size, Machine m, TargetFunctionsAllocatorConfig c) {
|
||||
_virtual_address = address;
|
||||
_size = size;
|
||||
machine = m;
|
||||
config = c;
|
||||
}
|
||||
|
||||
public async void deallocate (Cancellable? cancellable) throws Error, IOError {
|
||||
yield machine.invoke (config.free_function, { _virtual_address, size }, cancellable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,11 @@ namespace Frida.Barebone {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async void protect_pages (uint64 virtual_address, size_t size, Gum.PageProtection prot,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async Gee.List<uint64?> scan_ranges (Gee.List<Gum.MemoryRange?> ranges, MatchPattern pattern, uint max_matches,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
@@ -45,8 +50,7 @@ namespace Frida.Barebone {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async uint64 invoke (uint64 impl, uint64[] args, uint64 landing_zone, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
public async uint64 invoke (uint64 impl, uint64[] args, Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,13 @@ namespace Frida.Barebone {
|
||||
private const uint64 INT6_MASK = 0x3fULL;
|
||||
private const uint64 INT48_MASK = 0xffffffffffffULL;
|
||||
|
||||
private const uint64 TABLE_PXN_BIT = 1ULL << 59;
|
||||
|
||||
private const uint64 UXN_BIT = 1ULL << 54;
|
||||
private const uint64 PXN_BIT = 1ULL << 53;
|
||||
private const uint64 AP1_BIT = 1ULL << 7;
|
||||
private const uint64 AP0_BIT = 1ULL << 6;
|
||||
|
||||
public Arm64Machine (GDB.Client gdb) {
|
||||
Object (gdb: gdb);
|
||||
}
|
||||
@@ -55,7 +62,7 @@ namespace Frida.Barebone {
|
||||
|
||||
yield set_addressing_mode (gdb, PHYSICAL, cancellable);
|
||||
try {
|
||||
yield collect_ranges_in_table (p.tt1, p.first_level, p.upper_bits, p.granule, result, cancellable);
|
||||
yield collect_ranges_in_table (p.tt1, p.first_level, p.upper_bits, p, result, cancellable);
|
||||
} finally {
|
||||
set_addressing_mode.begin (gdb, VIRTUAL, null);
|
||||
}
|
||||
@@ -63,30 +70,30 @@ namespace Frida.Barebone {
|
||||
return result;
|
||||
}
|
||||
|
||||
private async void collect_ranges_in_table (uint64 table_address, uint level, uint64 upper_bits, Granule granule,
|
||||
private async void collect_ranges_in_table (uint64 table_address, uint level, uint64 upper_bits, MMUParameters p,
|
||||
Gee.List<RangeDetails> ranges, Cancellable? cancellable) throws Error, IOError {
|
||||
uint max_entries = compute_max_entries (level, granule);
|
||||
uint max_entries = compute_max_entries (level, p);
|
||||
Buffer entries = yield gdb.read_buffer (table_address, max_entries * Descriptor.SIZE, cancellable);
|
||||
uint shift = address_shift_at_level (level, granule);
|
||||
uint shift = address_shift_at_level (level, p.granule);
|
||||
for (uint i = 0; i != max_entries; i++) {
|
||||
uint64 raw_descriptor = entries.read_uint64 (i * Descriptor.SIZE);
|
||||
|
||||
Descriptor desc = Descriptor.parse (raw_descriptor, level, granule);
|
||||
Descriptor desc = Descriptor.parse (raw_descriptor, level, p.granule);
|
||||
if (desc.kind == INVALID)
|
||||
continue;
|
||||
|
||||
uint64 address = upper_bits | ((uint64) i << shift);
|
||||
|
||||
if (desc.kind == BLOCK) {
|
||||
size_t size = 1 << num_block_bits_at_level (level, granule);
|
||||
Gum.PageProtection prot = protection_from_flags (desc.flags);
|
||||
size_t size = 1 << num_block_bits_at_level (level, p.granule);
|
||||
Gum.PageProtection prot = protection_from_flags (desc.flags, p);
|
||||
|
||||
ranges.add (new RangeDetails (address, desc.target_address, size, prot, MappingType.UNKNOWN));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
yield collect_ranges_in_table (desc.target_address, level + 1, address, granule, ranges, cancellable);
|
||||
yield collect_ranges_in_table (desc.target_address, level + 1, address, p, ranges, cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,9 +159,10 @@ namespace Frida.Barebone {
|
||||
yield set_addressing_mode (gdb, PHYSICAL, cancellable);
|
||||
try {
|
||||
Allocation? allocation = yield maybe_insert_descriptor_in_table (physical_address, num_pages, p.tt1,
|
||||
p.first_level, p.upper_bits, p.granule, cancellable);
|
||||
p.first_level, p.upper_bits, p, cancellable);
|
||||
if (allocation == null)
|
||||
throw new Error.NOT_SUPPORTED ("Unable to insert page table mapping; please file a bug");
|
||||
|
||||
return allocation;
|
||||
} finally {
|
||||
set_addressing_mode.begin (gdb, VIRTUAL, null);
|
||||
@@ -162,10 +170,10 @@ namespace Frida.Barebone {
|
||||
}
|
||||
|
||||
private async Allocation? maybe_insert_descriptor_in_table (uint64 physical_address, uint num_pages,
|
||||
uint64 table_address, uint level, uint64 upper_bits, Granule granule, Cancellable? cancellable)
|
||||
uint64 table_address, uint level, uint64 upper_bits, MMUParameters p, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
uint max_entries = compute_max_entries (level, granule);
|
||||
uint shift = address_shift_at_level (level, granule);
|
||||
uint max_entries = compute_max_entries (level, p);
|
||||
uint shift = address_shift_at_level (level, p.granule);
|
||||
|
||||
uint64 first_available_va = 0;
|
||||
uint64 first_available_slot = 0;
|
||||
@@ -184,13 +192,15 @@ namespace Frida.Barebone {
|
||||
uint table_index = chunk_offset + i;
|
||||
uint64 address = upper_bits | ((uint64) table_index << shift);
|
||||
|
||||
Descriptor desc = Descriptor.parse (raw_descriptor, level, granule);
|
||||
Descriptor desc = Descriptor.parse (raw_descriptor, level, p.granule);
|
||||
|
||||
if (level < 3) {
|
||||
if (desc.kind != TABLE)
|
||||
continue;
|
||||
if ((desc.flags & DescriptorFlags.PXNTABLE) != 0)
|
||||
continue;
|
||||
Allocation? allocation = yield maybe_insert_descriptor_in_table (physical_address,
|
||||
num_pages, desc.target_address, level + 1, address, granule, cancellable);
|
||||
num_pages, desc.target_address, level + 1, address, p, cancellable);
|
||||
if (allocation != null)
|
||||
return allocation;
|
||||
continue;
|
||||
@@ -215,17 +225,197 @@ namespace Frida.Barebone {
|
||||
if (num_available_slots != num_pages)
|
||||
return null;
|
||||
|
||||
Gum.PageProtection page_prot = Gum.PageProtection.READ | Gum.PageProtection.WRITE;
|
||||
if (!p.sprr_enabled)
|
||||
page_prot |= Gum.PageProtection.EXECUTE;
|
||||
|
||||
var builder = gdb.make_buffer_builder ();
|
||||
for (uint i = 0; i != num_available_slots; i++) {
|
||||
uint64 cur_physical_address = physical_address + (i * granule);
|
||||
uint64 new_descriptor = cur_physical_address | 0x40000000000403ULL;
|
||||
uint64 cur_physical_address = physical_address + (i * p.granule);
|
||||
uint64 base_descriptor = cur_physical_address | 0x403ULL;
|
||||
|
||||
uint64 new_descriptor = apply_protection_bits (base_descriptor, page_prot, p);
|
||||
|
||||
builder.append_uint64 (new_descriptor);
|
||||
}
|
||||
Bytes new_descriptors = builder.build ();
|
||||
Bytes old_descriptors = yield gdb.read_byte_array (first_available_slot, new_descriptors.get_size (), cancellable);
|
||||
yield gdb.write_byte_array (first_available_slot, new_descriptors, cancellable);
|
||||
|
||||
return new DescriptorAllocation (first_available_va, first_available_slot, old_descriptors, gdb);
|
||||
size_t size = num_pages * p.granule;
|
||||
return new DescriptorAllocation (first_available_va, size, first_available_slot, old_descriptors, gdb);
|
||||
}
|
||||
|
||||
public async void protect_pages (uint64 virtual_address, size_t size, Gum.PageProtection prot, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
MMUParameters p = yield MMUParameters.load (gdb, cancellable);
|
||||
|
||||
yield set_addressing_mode (gdb, PHYSICAL, cancellable);
|
||||
try {
|
||||
uint64 page_mask = p.granule - 1;
|
||||
uint64 aligned_va = virtual_address & ~page_mask;
|
||||
uint64 aligned_end = (virtual_address + size + page_mask) & ~page_mask;
|
||||
uint num_pages = (uint) ((aligned_end - aligned_va) / p.granule);
|
||||
|
||||
yield perform_protect_pages (aligned_va, num_pages, prot, p, cancellable);
|
||||
} finally {
|
||||
set_addressing_mode.begin (gdb, VIRTUAL, null);
|
||||
}
|
||||
}
|
||||
|
||||
private async void perform_protect_pages (uint64 start_va, uint num_pages, Gum.PageProtection prot, MMUParameters p,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
var table_cache = new TableWalkCache ();
|
||||
uint pages_processed = 0;
|
||||
|
||||
var processed_tables = new Gee.HashSet<uint64?> (Numeric.uint64_hash, Numeric.uint64_equal);
|
||||
bool need_exec = (prot & Gum.PageProtection.EXECUTE) != 0;
|
||||
|
||||
while (pages_processed != num_pages) {
|
||||
uint64 current_va = start_va + (uint64) pages_processed * p.granule;
|
||||
|
||||
uint64 table_pa = yield find_level3_table (current_va, p, table_cache, cancellable);
|
||||
|
||||
if (need_exec && !processed_tables.contains (table_pa)) {
|
||||
yield clear_pxn_table_bits_for_va (current_va, p, table_cache, cancellable);
|
||||
processed_tables.add (table_pa);
|
||||
}
|
||||
|
||||
uint level3_shift = address_shift_at_level (3, p.granule);
|
||||
uint64 level3_mask = (1ULL << level3_shift) - 1;
|
||||
uint64 table_base_va = current_va & ~level3_mask;
|
||||
uint64 table_end_va = table_base_va + (1ULL << level3_shift);
|
||||
uint64 remaining_va = start_va + num_pages * p.granule;
|
||||
uint64 batch_end_va = uint64.min (remaining_va, table_end_va);
|
||||
uint batch_size = (uint) ((batch_end_va - current_va) / p.granule);
|
||||
|
||||
yield protect_pages_in_table (current_va, batch_size, prot, table_pa, p, cancellable);
|
||||
|
||||
pages_processed += batch_size;
|
||||
}
|
||||
}
|
||||
|
||||
private async void protect_pages_in_table (uint64 current_va, uint batch_size, Gum.PageProtection prot,
|
||||
uint64 table_pa, MMUParameters p, Cancellable? cancellable) throws Error, IOError {
|
||||
uint index_bits = num_address_bits_at_level (3, p);
|
||||
uint index_shift = inpage_bits_for_granule (p.granule);
|
||||
uint index_mask = (1U << index_bits) - 1;
|
||||
|
||||
uint64 first_index = (current_va >> index_shift) & index_mask;
|
||||
uint64 first_slot_pa = table_pa + (first_index * Descriptor.SIZE);
|
||||
|
||||
Buffer descriptors = yield gdb.read_buffer (first_slot_pa, batch_size * Descriptor.SIZE, cancellable);
|
||||
|
||||
bool any_changed = false;
|
||||
for (uint i = 0; i != batch_size; i++) {
|
||||
uint64 raw_desc = descriptors.read_uint64 (i * Descriptor.SIZE);
|
||||
uint64 new_desc = apply_protection_bits (raw_desc, prot, p);
|
||||
|
||||
if (new_desc != raw_desc) {
|
||||
descriptors.write_uint64 (i * Descriptor.SIZE, new_desc);
|
||||
any_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (any_changed)
|
||||
yield gdb.write_byte_array (first_slot_pa, descriptors.bytes, cancellable);
|
||||
}
|
||||
|
||||
private async uint64 find_level3_table (uint64 va, MMUParameters p, TableWalkCache cache, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
TableWalkResult? cached = cache.lookup (va, p);
|
||||
if (cached != null)
|
||||
return yield walk_to_level3 (va, cached.table_pa, cached.level, p, cache, cancellable);
|
||||
|
||||
return yield walk_to_level3 (va, p.tt1, p.first_level, p, cache, cancellable);
|
||||
}
|
||||
|
||||
private async uint64 walk_to_level3 (uint64 va, uint64 start_table_pa, uint start_level, MMUParameters p,
|
||||
TableWalkCache cache, Cancellable? cancellable) throws Error, IOError {
|
||||
uint64 table_pa = start_table_pa;
|
||||
uint level = start_level;
|
||||
|
||||
while (level != 3) {
|
||||
cache.store (va, level, table_pa, p);
|
||||
|
||||
uint shift = address_shift_at_level (level, p.granule);
|
||||
uint entries = compute_max_entries (level, p);
|
||||
uint index = (uint) ((va >> shift) & (entries - 1));
|
||||
uint64 slot_pa = table_pa + ((uint64) index * Descriptor.SIZE);
|
||||
|
||||
Buffer d_buf = yield gdb.read_buffer (slot_pa, Descriptor.SIZE, cancellable);
|
||||
uint64 raw = d_buf.read_uint64 (0);
|
||||
Descriptor desc = Descriptor.parse (raw, level, p.granule);
|
||||
|
||||
if (desc.kind != TABLE)
|
||||
throw new Error.NOT_SUPPORTED ("Walk failed at level %u", level);
|
||||
|
||||
table_pa = desc.target_address;
|
||||
level++;
|
||||
}
|
||||
|
||||
return table_pa;
|
||||
}
|
||||
|
||||
private async void clear_pxn_table_bits_for_va (uint64 va, MMUParameters p, TableWalkCache cache, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
uint64 table_pa = p.tt1;
|
||||
for (uint level = p.first_level; level != 3; level++) {
|
||||
uint entries = compute_max_entries (level, p);
|
||||
uint shift = address_shift_at_level (level, p.granule);
|
||||
uint index = (uint) ((va >> shift) & (entries - 1));
|
||||
uint64 slot_pa = table_pa + (index * Descriptor.SIZE);
|
||||
|
||||
Buffer d_buf = yield gdb.read_buffer (slot_pa, Descriptor.SIZE, cancellable);
|
||||
uint64 raw_desc = d_buf.read_uint64 (0);
|
||||
Descriptor desc = Descriptor.parse (raw_desc, level, p.granule);
|
||||
if (desc.kind != TABLE)
|
||||
break;
|
||||
|
||||
if ((raw_desc & TABLE_PXN_BIT) != 0) {
|
||||
uint64 new_desc = raw_desc & ~TABLE_PXN_BIT;
|
||||
d_buf.write_uint64 (0, new_desc);
|
||||
yield gdb.write_byte_array (slot_pa, d_buf.bytes, cancellable);
|
||||
}
|
||||
|
||||
table_pa = desc.target_address;
|
||||
}
|
||||
}
|
||||
|
||||
private class TableWalkCache {
|
||||
private Gee.Map<uint64?, TableWalkResult> cache =
|
||||
new Gee.HashMap<uint64?, TableWalkResult> (Numeric.uint64_hash, Numeric.uint64_equal);
|
||||
|
||||
public TableWalkResult? lookup (uint64 va, MMUParameters p) {
|
||||
for (int level = 2; level >= (int) p.first_level; level--) {
|
||||
uint64 cache_key = compute_cache_key (va, (uint) level, p);
|
||||
TableWalkResult? result = cache[cache_key];
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void store (uint64 va, uint level, uint64 table_pa, MMUParameters p) {
|
||||
if (level >= 3)
|
||||
return;
|
||||
|
||||
uint64 cache_key = compute_cache_key (va, level, p);
|
||||
cache[cache_key] = new TableWalkResult () {
|
||||
table_pa = table_pa,
|
||||
level = level
|
||||
};
|
||||
}
|
||||
|
||||
private uint64 compute_cache_key (uint64 va, uint level, MMUParameters p) {
|
||||
uint shift = address_shift_at_level (level + 1, p.granule);
|
||||
return (va >> shift) << shift;
|
||||
}
|
||||
}
|
||||
|
||||
private class TableWalkResult {
|
||||
public uint64 table_pa;
|
||||
public uint level;
|
||||
}
|
||||
|
||||
public async Gee.List<uint64?> scan_ranges (Gee.List<Gum.MemoryRange?> ranges, MatchPattern pattern, uint max_matches,
|
||||
@@ -354,14 +544,17 @@ namespace Frida.Barebone {
|
||||
case ABS64:
|
||||
relocated.write_uint64 ((size_t) r.address, base_va + r.symbol.address + r.addend);
|
||||
break;
|
||||
case PREL32:
|
||||
var diff = (int64) (base_va + r.symbol.address + r.addend) - (int64) (base_va + r.address);
|
||||
relocated.write_int32 ((size_t) r.address, (int32) diff);
|
||||
break;
|
||||
default:
|
||||
throw new Error.NOT_SUPPORTED ("Unsupported relocation type: %s",
|
||||
Marshal.enum_to_nick<Gum.ElfArm64Relocation> (type));
|
||||
}
|
||||
}
|
||||
|
||||
public async uint64 invoke (uint64 impl, uint64[] args, uint64 landing_zone, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
public async uint64 invoke (uint64 impl, uint64[] args, Cancellable? cancellable) throws Error, IOError {
|
||||
if (args.length > 8)
|
||||
throw new Error.NOT_SUPPORTED ("Unsupported number of arguments; please open a PR");
|
||||
|
||||
@@ -377,6 +570,7 @@ namespace Frida.Barebone {
|
||||
|
||||
regs["pc"] = impl;
|
||||
|
||||
uint64 landing_zone = saved_regs["pc"].get_uint64 ();
|
||||
regs["x30"] = landing_zone;
|
||||
|
||||
uint64 sp = saved_regs["sp"].get_uint64 ();
|
||||
@@ -406,6 +600,35 @@ namespace Frida.Barebone {
|
||||
return retval;
|
||||
}
|
||||
|
||||
public async void execute (uint64 start, uint64 end, Cancellable? cancellable) throws Error, IOError {
|
||||
bool was_running = gdb.state != STOPPED;
|
||||
if (was_running)
|
||||
yield gdb.stop (cancellable);
|
||||
|
||||
GDB.Thread thread = gdb.exception.thread;
|
||||
Gee.Map<string, Variant> saved_regs = yield thread.read_registers (cancellable);
|
||||
|
||||
var regs = new Gee.HashMap<string, Variant> ();
|
||||
regs.set_all (saved_regs);
|
||||
|
||||
regs["pc"] = start;
|
||||
|
||||
yield thread.write_registers (regs, cancellable);
|
||||
|
||||
GDB.Breakpoint bp = yield gdb.add_breakpoint (SOFT, end, 4, cancellable);
|
||||
GDB.Exception ex = null;
|
||||
do {
|
||||
ex = yield gdb.continue_until_exception (cancellable);
|
||||
} while (ex.breakpoint != bp || ex.thread.id != thread.id);
|
||||
// TODO: Improve GDB.Client to guarantee a single GDB.Thread instance per ID.
|
||||
yield bp.remove (cancellable);
|
||||
|
||||
yield thread.write_registers (saved_regs, cancellable);
|
||||
|
||||
if (was_running)
|
||||
yield gdb.continue (cancellable);
|
||||
}
|
||||
|
||||
public async CallFrame load_call_frame (GDB.Thread thread, uint arity, Cancellable? cancellable) throws Error, IOError {
|
||||
var regs = yield thread.read_registers (cancellable);
|
||||
|
||||
@@ -689,6 +912,10 @@ namespace Frida.Barebone {
|
||||
public uint first_level;
|
||||
public uint64 upper_bits;
|
||||
public uint64 tt1;
|
||||
public uint t1sz;
|
||||
|
||||
public bool sprr_enabled;
|
||||
public uint64 sprr_perm;
|
||||
|
||||
public static async MMUParameters load (GDB.Client gdb, Cancellable? cancellable) throws Error, IOError {
|
||||
GDB.Exception? exception = gdb.exception;
|
||||
@@ -716,6 +943,10 @@ namespace Frida.Barebone {
|
||||
parameters.upper_bits |= 1ULL << (63 - i);
|
||||
|
||||
parameters.tt1 = regs.ttbr1 & INT48_MASK;
|
||||
parameters.t1sz = t1sz;
|
||||
|
||||
parameters.sprr_enabled = (regs.sprr_config & 1) != 0;
|
||||
parameters.sprr_perm = regs.sprr_perm;
|
||||
|
||||
return parameters;
|
||||
}
|
||||
@@ -724,6 +955,8 @@ namespace Frida.Barebone {
|
||||
private class MMURegisters {
|
||||
public uint64 tcr;
|
||||
public uint64 ttbr1;
|
||||
public uint64 sprr_config;
|
||||
public uint64 sprr_perm;
|
||||
|
||||
public static async MMURegisters read (GDB.Thread thread, Cancellable? cancellable) throws Error, IOError {
|
||||
var regs = new MMURegisters ();
|
||||
@@ -741,10 +974,19 @@ namespace Frida.Barebone {
|
||||
regs.tcr = val;
|
||||
else if (name == "ttbr1_el1")
|
||||
regs.ttbr1 = val;
|
||||
else if (name == "sprr_config_el1")
|
||||
regs.sprr_config = val;
|
||||
else if (name == "sprr_el1br1_el1")
|
||||
regs.sprr_perm = val;
|
||||
}
|
||||
} else {
|
||||
regs.tcr = yield thread.read_register ("tcr_el1", cancellable);
|
||||
regs.ttbr1 = yield thread.read_register ("ttbr1_el1", cancellable);
|
||||
try {
|
||||
regs.sprr_config = yield thread.read_register ("sprr_config_el1", cancellable);
|
||||
regs.sprr_perm = yield thread.read_register ("sprr_el1br1_el1", cancellable);
|
||||
} catch (Error e) {
|
||||
}
|
||||
}
|
||||
|
||||
return regs;
|
||||
@@ -850,16 +1092,27 @@ namespace Frida.Barebone {
|
||||
|
||||
private class DescriptorAllocation : Object, Allocation {
|
||||
public uint64 virtual_address {
|
||||
get { return base_va; }
|
||||
get {
|
||||
return base_va;
|
||||
}
|
||||
}
|
||||
|
||||
public size_t size {
|
||||
get {
|
||||
return _size;
|
||||
}
|
||||
}
|
||||
|
||||
private uint64 base_va;
|
||||
private size_t _size;
|
||||
private uint64 first_slot;
|
||||
private Bytes? old_descriptors;
|
||||
private GDB.Client gdb;
|
||||
|
||||
public DescriptorAllocation (uint64 base_va, uint64 first_slot, Bytes old_descriptors, GDB.Client gdb) {
|
||||
public DescriptorAllocation (uint64 base_va, size_t size, uint64 first_slot, Bytes old_descriptors,
|
||||
GDB.Client gdb) {
|
||||
this.base_va = base_va;
|
||||
this._size = size;
|
||||
this.first_slot = first_slot;
|
||||
this.old_descriptors = old_descriptors;
|
||||
this.gdb = gdb;
|
||||
@@ -908,11 +1161,23 @@ namespace Frida.Barebone {
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
private static uint compute_max_entries (uint level, Granule granule) {
|
||||
return 1 << num_address_bits_at_level (level, granule);
|
||||
private static uint compute_max_entries (uint level, MMUParameters p) {
|
||||
return 1 << num_address_bits_at_level (level, p);
|
||||
}
|
||||
|
||||
private static uint num_address_bits_at_level (uint level, Granule granule) {
|
||||
private static uint num_address_bits_at_level (uint level, MMUParameters p) {
|
||||
if (level == p.first_level) {
|
||||
uint available_address_bits = 64 - p.t1sz - inpage_bits_for_granule (p.granule);
|
||||
uint consumed_by_lower_levels = 0;
|
||||
for (uint l = level + 1; l <= 3; l++)
|
||||
consumed_by_lower_levels += unclipped_address_bits_at_level (l, p.granule);
|
||||
return available_address_bits - consumed_by_lower_levels;
|
||||
} else {
|
||||
return unclipped_address_bits_at_level (level, p.granule);
|
||||
}
|
||||
}
|
||||
|
||||
private static uint unclipped_address_bits_at_level (uint level, Granule granule) {
|
||||
switch (granule) {
|
||||
case 4K:
|
||||
return 9;
|
||||
@@ -932,7 +1197,7 @@ namespace Frida.Barebone {
|
||||
private static uint address_shift_at_level (uint level, Granule granule) {
|
||||
uint shift = inpage_bits_for_granule (granule);
|
||||
for (int l = 2; l != (int) level - 1; l--)
|
||||
shift += num_address_bits_at_level (l, granule);
|
||||
shift += unclipped_address_bits_at_level (l, granule);
|
||||
return shift;
|
||||
}
|
||||
|
||||
@@ -949,7 +1214,45 @@ namespace Frida.Barebone {
|
||||
}
|
||||
}
|
||||
|
||||
private static Gum.PageProtection protection_from_flags (DescriptorFlags flags) {
|
||||
private static Gum.PageProtection protection_from_flags (DescriptorFlags flags, MMUParameters p) {
|
||||
if (p.sprr_enabled) {
|
||||
uint idx = 0;
|
||||
if ((flags & DescriptorFlags.AP_READ_ONLY) != 0)
|
||||
idx |= 1 << 3;
|
||||
if ((flags & DescriptorFlags.AP_ALLOW_APPLICATION) != 0)
|
||||
idx |= 1 << 2;
|
||||
if ((flags & DescriptorFlags.UXN) != 0)
|
||||
idx |= 1 << 1;
|
||||
if ((flags & DescriptorFlags.PXN) != 0)
|
||||
idx |= 1 << 0;
|
||||
|
||||
uint perm = (uint) ((p.sprr_perm >> (idx * 4)) & 0xf);
|
||||
|
||||
Gum.PageProtection prot;
|
||||
switch (perm & 3) {
|
||||
case 0:
|
||||
prot = 0;
|
||||
break;
|
||||
case 1:
|
||||
prot = READ | EXECUTE;
|
||||
if ((perm >> 2) == 2)
|
||||
prot = EXECUTE;
|
||||
break;
|
||||
case 2:
|
||||
prot = READ;
|
||||
break;
|
||||
case 3:
|
||||
prot = READ | WRITE;
|
||||
if ((perm >> 2) == 1)
|
||||
prot = 0;
|
||||
break;
|
||||
default:
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
return prot;
|
||||
}
|
||||
|
||||
Gum.PageProtection prot = READ;
|
||||
if ((flags & DescriptorFlags.PXN) == 0)
|
||||
prot |= EXECUTE;
|
||||
@@ -958,6 +1261,93 @@ namespace Frida.Barebone {
|
||||
return prot;
|
||||
}
|
||||
|
||||
private static uint64 apply_protection_bits (uint64 descriptor, Gum.PageProtection prot, MMUParameters p) throws Error {
|
||||
uint64 result = descriptor;
|
||||
|
||||
if (p.sprr_enabled) {
|
||||
uint target_sprr_index = find_sprr_index_for_permissions (prot, p);
|
||||
result = apply_sprr_index_to_descriptor (result, target_sprr_index);
|
||||
} else {
|
||||
result = apply_non_sprr_protection_bits (result, prot);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static uint64 apply_non_sprr_protection_bits (uint64 descriptor, Gum.PageProtection prot) {
|
||||
uint64 result = descriptor;
|
||||
|
||||
bool want_exec = (prot & Gum.PageProtection.EXECUTE) != 0;
|
||||
bool want_write = (prot & Gum.PageProtection.WRITE) != 0;
|
||||
|
||||
if (want_exec)
|
||||
result &= ~(UXN_BIT | PXN_BIT);
|
||||
else
|
||||
result |= (UXN_BIT | PXN_BIT);
|
||||
|
||||
if (want_write) {
|
||||
result &= ~(AP1_BIT | AP0_BIT);
|
||||
} else {
|
||||
result |= AP1_BIT;
|
||||
result &= ~AP0_BIT;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static uint find_sprr_index_for_permissions (Gum.PageProtection prot, MMUParameters p) throws Error {
|
||||
bool want_read = (prot & Gum.PageProtection.READ) != 0;
|
||||
bool want_write = (prot & Gum.PageProtection.WRITE) != 0;
|
||||
bool want_exec = (prot & Gum.PageProtection.EXECUTE) != 0;
|
||||
|
||||
for (uint i = 0; i != 16; i++) {
|
||||
uint perm = (uint) ((p.sprr_perm >> (i * 4)) & 0xf);
|
||||
|
||||
bool slot_allows_read = false;
|
||||
bool slot_allows_write = false;
|
||||
bool slot_allows_exec = false;
|
||||
|
||||
switch (perm & 3) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
slot_allows_exec = true;
|
||||
if ((perm >> 2) != 2)
|
||||
slot_allows_read = true;
|
||||
break;
|
||||
case 2:
|
||||
slot_allows_read = true;
|
||||
break;
|
||||
case 3:
|
||||
slot_allows_read = true;
|
||||
slot_allows_write = ((perm >> 2) != 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (slot_allows_read == want_read && slot_allows_write == want_write && slot_allows_exec == want_exec)
|
||||
return i;
|
||||
}
|
||||
|
||||
throw new Error.INVALID_ARGUMENT ("No suitable SPRR slot found for protection 0x%x", prot);
|
||||
}
|
||||
|
||||
private static uint64 apply_sprr_index_to_descriptor (uint64 descriptor, uint sprr_index) {
|
||||
uint64 result = descriptor;
|
||||
|
||||
result &= ~(AP1_BIT | AP0_BIT | UXN_BIT | PXN_BIT);
|
||||
|
||||
if ((sprr_index & 0x8) != 0)
|
||||
result |= AP1_BIT;
|
||||
if ((sprr_index & 0x4) != 0)
|
||||
result |= AP0_BIT;
|
||||
if ((sprr_index & 0x2) != 0)
|
||||
result |= UXN_BIT;
|
||||
if ((sprr_index & 0x1) != 0)
|
||||
result |= PXN_BIT;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Gum.PageProtection protection_from_corellium_pt_details (string details) {
|
||||
Gum.PageProtection prot = READ;
|
||||
if (!("pXN" in details))
|
||||
|
||||
@@ -31,6 +31,11 @@ namespace Frida.Barebone {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async void protect_pages (uint64 virtual_address, size_t size, Gum.PageProtection prot,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async Gee.List<uint64?> scan_ranges (Gee.List<Gum.MemoryRange?> ranges, MatchPattern pattern,
|
||||
uint max_matches, Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
@@ -40,8 +45,7 @@ namespace Frida.Barebone {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async uint64 invoke (uint64 impl, uint64[] args, uint64 landing_zone, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
public async uint64 invoke (uint64 impl, uint64[] args, Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,11 @@ namespace Frida.Barebone {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async void protect_pages (uint64 virtual_address, size_t size, Gum.PageProtection prot,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async Gee.List<uint64?> scan_ranges (Gee.List<Gum.MemoryRange?> ranges, MatchPattern pattern, uint max_matches,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
@@ -41,8 +46,7 @@ namespace Frida.Barebone {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async uint64 invoke (uint64 impl, uint64[] args, uint64 landing_zone, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
public async uint64 invoke (uint64 impl, uint64[] args, Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,11 @@ namespace Frida.Barebone {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async void protect_pages (uint64 virtual_address, size_t size, Gum.PageProtection prot,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async Gee.List<uint64?> scan_ranges (Gee.List<Gum.MemoryRange?> ranges, MatchPattern pattern, uint max_matches,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
@@ -43,8 +48,7 @@ namespace Frida.Barebone {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async uint64 invoke (uint64 impl, uint64[] args, uint64 landing_zone, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
public async uint64 invoke (uint64 impl, uint64[] args, Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,26 +2,8 @@ namespace Frida {
|
||||
public sealed class BareboneHostSessionBackend : Object, HostSessionBackend {
|
||||
private BareboneHostSessionProvider? provider;
|
||||
|
||||
private const uint16 DEFAULT_PORT = 3333;
|
||||
|
||||
public async void start (Cancellable? cancellable) throws IOError {
|
||||
SocketConnectable? connectable = null;
|
||||
unowned string? address = Environment.get_variable ("FRIDA_BAREBONE_ADDRESS");
|
||||
if (address != null) {
|
||||
try {
|
||||
connectable = NetworkAddress.parse (address, DEFAULT_PORT);
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
}
|
||||
if (connectable == null)
|
||||
connectable = new InetSocketAddress (new InetAddress.loopback (SocketFamily.IPV4), DEFAULT_PORT);
|
||||
|
||||
uint64 heap_base_pa = 0;
|
||||
unowned string? heap_base_preference = Environment.get_variable ("FRIDA_BAREBONE_HEAP_BASE");
|
||||
if (heap_base_preference != null)
|
||||
heap_base_pa = uint64.parse (heap_base_preference, 16);
|
||||
|
||||
provider = new BareboneHostSessionProvider (connectable, heap_base_pa);
|
||||
provider = new BareboneHostSessionProvider ();
|
||||
provider_available (provider);
|
||||
}
|
||||
|
||||
@@ -49,22 +31,8 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public SocketConnectable connectable {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public uint64 heap_base_pa {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private BareboneHostSession? host_session;
|
||||
|
||||
public BareboneHostSessionProvider (SocketConnectable connectable, uint64 heap_base_pa) {
|
||||
Object (connectable: connectable, heap_base_pa: heap_base_pa);
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
if (host_session != null) {
|
||||
yield host_session.close (cancellable);
|
||||
@@ -76,6 +44,27 @@ namespace Frida {
|
||||
if (host_session != null)
|
||||
throw new Error.INVALID_OPERATION ("Already created");
|
||||
|
||||
Barebone.Config config;
|
||||
unowned string? config_path = Environment.get_variable ("FRIDA_BAREBONE_CONFIG");
|
||||
if (config_path != null) {
|
||||
try {
|
||||
var config_data = yield FS.read_all_text (File.new_for_path (config_path), cancellable);
|
||||
config = (Barebone.Config) Json.gobject_from_data (typeof (Barebone.Config), config_data);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.INVALID_ARGUMENT ("Unable to load %s: %s", config_path, e.message);
|
||||
}
|
||||
} else {
|
||||
config = new Barebone.Config ();
|
||||
}
|
||||
|
||||
SocketConnectable connectable;
|
||||
try {
|
||||
Barebone.ConnectionConfig c = config.connection;
|
||||
connectable = NetworkAddress.parse (c.host, c.port);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.INVALID_ARGUMENT ("Unable to load %s: %s", config_path, e.message);
|
||||
}
|
||||
|
||||
IOStream stream;
|
||||
try {
|
||||
var client = new SocketClient ();
|
||||
@@ -109,10 +98,26 @@ namespace Frida {
|
||||
break;
|
||||
}
|
||||
|
||||
var page_size = yield machine.query_page_size (cancellable);
|
||||
size_t page_size;
|
||||
try {
|
||||
page_size = yield machine.query_page_size (cancellable);
|
||||
} catch (Error e) {
|
||||
page_size = 0;
|
||||
}
|
||||
|
||||
// TODO: Locate and use kernel's allocator when possible.
|
||||
Barebone.Allocator allocator = new Barebone.SimpleAllocator (machine, page_size, heap_base_pa);
|
||||
Barebone.Allocator allocator;
|
||||
Barebone.AllocatorConfig ac = config.allocator;
|
||||
if (ac is Barebone.NoAllocatorConfig) {
|
||||
allocator = new Barebone.NullAllocator (page_size);
|
||||
} else if (ac is Barebone.PhysicalAllocatorConfig) {
|
||||
allocator = new Barebone.PhysicalAllocator (machine, page_size,
|
||||
(Barebone.PhysicalAllocatorConfig) ac);
|
||||
} else if (ac is Barebone.TargetFunctionsAllocatorConfig) {
|
||||
allocator = new Barebone.TargetFunctionsAllocator (machine, page_size,
|
||||
(Barebone.TargetFunctionsAllocatorConfig) ac);
|
||||
} else {
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
var interceptor = new Barebone.Interceptor (machine, allocator);
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
private sealed class CModule : Object {
|
||||
public signal void console_output (string message);
|
||||
|
||||
public Gee.List<Export> exports {
|
||||
get;
|
||||
default = new Gee.ArrayList<Export> ();
|
||||
}
|
||||
|
||||
public class Export {
|
||||
public string name;
|
||||
public uint64 address;
|
||||
|
||||
internal Export (string name, uint64 address) {
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
|
||||
private Gum.ElfModule elf;
|
||||
private Allocation allocation;
|
||||
private Callback console_log_callback;
|
||||
|
||||
public async CModule.from_blob (Bytes blob, Machine machine, Allocator allocator, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
try {
|
||||
elf = new Gum.ElfModule.from_blob (blob);
|
||||
} catch (Gum.Error e) {
|
||||
throw new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
}
|
||||
|
||||
allocation = yield inject_elf (elf, machine, allocator, cancellable);
|
||||
|
||||
uint64 base_va = allocation.virtual_address;
|
||||
uint64 console_log_trap = 0;
|
||||
elf.enumerate_symbols (e => {
|
||||
if (e.name == "")
|
||||
return true;
|
||||
|
||||
if (e.name[0] == '_') {
|
||||
if (e.name == "_console_log")
|
||||
console_log_trap = base_va + e.address;
|
||||
return true;
|
||||
}
|
||||
|
||||
exports.add (new Export (e.name, base_va + e.address));
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (console_log_trap != 0) {
|
||||
var handler = new ConsoleLogHandler (machine.gdb);
|
||||
handler.output.connect (on_console_output);
|
||||
console_log_callback = yield new Callback (console_log_trap, handler, machine, cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_console_output (string message) {
|
||||
console_output (message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
/**
|
||||
* Barebone backend configuration. This is specified via the FRIDA_BAREBONE_CONFIG environment
|
||||
* variable, which should point to the filesystem path of a JSON-encoded configuration file.
|
||||
*
|
||||
* Example JSON configurations:
|
||||
*
|
||||
* 1. Using all defaults:
|
||||
* {
|
||||
* "connection": {
|
||||
* "host": "127.0.0.1",
|
||||
* "port": 3333
|
||||
* },
|
||||
* "allocator": {
|
||||
* "mode": "none"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* 2. Using a physical memory allocator:
|
||||
* {
|
||||
* "connection": {
|
||||
* "host": "127.0.0.1",
|
||||
* "port": 9000
|
||||
* },
|
||||
* "allocator": {
|
||||
* "mode": "physical",
|
||||
* "physical_base": "0x8ec9b4000"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* 3. Using target-specific allocation functions:
|
||||
* {
|
||||
* "connection": {
|
||||
* "host": "127.0.0.1",
|
||||
* "port": 9000
|
||||
* },
|
||||
* "allocator": {
|
||||
* "mode": "target-functions",
|
||||
* "alloc_function": "0xfffffff007a3c278",
|
||||
* "free_function": "0xfffffff007a3c338"
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
public sealed class Config : Object, Json.Serializable {
|
||||
public ConnectionConfig connection {
|
||||
get;
|
||||
set;
|
||||
default = new ConnectionConfig ();
|
||||
}
|
||||
|
||||
public AllocatorConfig allocator {
|
||||
get;
|
||||
set;
|
||||
default = new NoAllocatorConfig ();
|
||||
}
|
||||
|
||||
public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
|
||||
if (property_name == "allocator" && property_node.get_node_type () == Json.NodeType.OBJECT) {
|
||||
var obj_node = property_node.get_object ();
|
||||
string? mode = obj_node.get_string_member ("mode");
|
||||
|
||||
Type t = 0;
|
||||
switch (mode) {
|
||||
case "none":
|
||||
t = typeof (NoAllocatorConfig);
|
||||
break;
|
||||
case "physical":
|
||||
t = typeof (PhysicalAllocatorConfig);
|
||||
break;
|
||||
case "target-functions":
|
||||
t = typeof (TargetFunctionsAllocatorConfig);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (t != 0) {
|
||||
var obj = (AllocatorConfig) Json.gobject_deserialize (t, property_node);
|
||||
if (obj != null && obj.is_valid) {
|
||||
var v = Value (t);
|
||||
v.set_object (obj);
|
||||
value = v;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value = Value (pspec.value_type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ConnectionConfig : Object {
|
||||
public string host {
|
||||
get;
|
||||
set;
|
||||
default = "127.0.0.1";
|
||||
}
|
||||
|
||||
public uint16 port {
|
||||
get;
|
||||
set;
|
||||
default = 3333;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class AllocatorConfig : Object {
|
||||
public abstract bool is_valid {
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class NoAllocatorConfig : AllocatorConfig {
|
||||
public override bool is_valid {
|
||||
get {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PhysicalAllocatorConfig : AllocatorConfig, Json.Serializable {
|
||||
public override bool is_valid {
|
||||
get {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public uint64 physical_base {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
|
||||
if (try_deserialize_address ("physical_base", property_node, out value))
|
||||
return true;
|
||||
|
||||
value = Value (pspec.value_type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TargetFunctionsAllocatorConfig : AllocatorConfig, Json.Serializable {
|
||||
public override bool is_valid {
|
||||
get {
|
||||
return alloc_function != 0 && free_function != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public uint64 alloc_function {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public uint64 free_function {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
|
||||
if (try_deserialize_address ("alloc_function", property_node, out value))
|
||||
return true;
|
||||
|
||||
if (try_deserialize_address ("free_function", property_node, out value))
|
||||
return true;
|
||||
|
||||
value = Value (pspec.value_type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool try_deserialize_address (string name, Json.Node node, out Value val) {
|
||||
val = Value (typeof (uint64));
|
||||
|
||||
if (node.get_value_type () != typeof (string))
|
||||
return false;
|
||||
|
||||
uint64 v;
|
||||
if (!uint64.try_parse (node.get_string (), out v, null, 16))
|
||||
return false;
|
||||
|
||||
val = v;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
private class ConsoleLogHandler : Object, CallbackHandler {
|
||||
public signal void output (string message);
|
||||
|
||||
public uint arity {
|
||||
get { return 2; }
|
||||
}
|
||||
|
||||
private GDB.Client gdb;
|
||||
|
||||
public ConsoleLogHandler (GDB.Client gdb) {
|
||||
this.gdb = gdb;
|
||||
}
|
||||
|
||||
public async uint64 handle_invocation (uint64[] args, CallFrame frame, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
var message = args[0];
|
||||
var len = (long) args[1];
|
||||
|
||||
Bytes str_bytes = yield gdb.read_byte_array (message, len, cancellable);
|
||||
unowned uint8[] str_data = str_bytes.get_data ();
|
||||
unowned string str_raw = (string) str_data;
|
||||
string str = str_raw.substring (0, len);
|
||||
|
||||
output (str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
public async Allocation inject_elf (Gum.ElfModule elf, Machine machine, Allocator allocator, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
size_t vm_size = (size_t) elf.mapped_size;
|
||||
|
||||
size_t page_size = yield machine.query_page_size (cancellable);
|
||||
uint num_pages = (uint) (vm_size / page_size);
|
||||
if (vm_size % page_size != 0)
|
||||
num_pages++;
|
||||
|
||||
var allocation = yield allocator.allocate (num_pages * page_size, page_size, cancellable);
|
||||
try {
|
||||
uint64 base_va = allocation.virtual_address;
|
||||
|
||||
Bytes relocated_image = machine.relocate (elf, base_va);
|
||||
yield machine.gdb.write_byte_array (base_va, relocated_image, cancellable);
|
||||
|
||||
yield machine.protect_pages (base_va, vm_size, READ | EXECUTE, cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
yield allocation.deallocate (cancellable);
|
||||
throw_api_error (e);
|
||||
}
|
||||
|
||||
return allocation;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,9 @@ namespace Frida.Barebone {
|
||||
public abstract async Allocation allocate_pages (uint64 physical_address, uint num_pages, Cancellable? cancellable)
|
||||
throws Error, IOError;
|
||||
|
||||
public abstract async void protect_pages (uint64 virtual_address, size_t size, Gum.PageProtection prot,
|
||||
Cancellable? cancellable) throws Error, IOError;
|
||||
|
||||
public abstract async Gee.List<uint64?> scan_ranges (Gee.List<Gum.MemoryRange?> ranges, MatchPattern pattern,
|
||||
uint max_matches, Cancellable? cancellable) throws Error, IOError;
|
||||
|
||||
@@ -65,8 +68,7 @@ namespace Frida.Barebone {
|
||||
|
||||
public abstract void apply_relocation (Gum.ElfRelocationDetails r, uint64 base_va, Buffer relocated) throws Error;
|
||||
|
||||
public abstract async uint64 invoke (uint64 impl, uint64[] args, uint64 landing_zone, Cancellable? cancellable)
|
||||
throws Error, IOError;
|
||||
public abstract async uint64 invoke (uint64 impl, uint64[] args, Cancellable? cancellable) throws Error, IOError;
|
||||
|
||||
public abstract async CallFrame load_call_frame (GDB.Thread thread, uint arity, Cancellable? cancellable)
|
||||
throws Error, IOError;
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
backend_sources += files(
|
||||
'barebone-host-session.vala',
|
||||
'config.vala',
|
||||
'script.vala',
|
||||
'machine.vala',
|
||||
'allocator.vala',
|
||||
'callback.vala',
|
||||
'memory-scanner.vala',
|
||||
'interceptor.vala',
|
||||
'c-module.vala',
|
||||
'rust-module.vala',
|
||||
'console.vala',
|
||||
'elf.vala',
|
||||
'arch-x86' / 'machine.vala',
|
||||
'arch-x86_64' / 'machine.vala',
|
||||
'arch-arm' / 'machine.vala',
|
||||
|
||||
Generated
+4
-4
@@ -8,7 +8,7 @@
|
||||
"name": "frida-barebone-script-runtime",
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@types/frida-gum": "^19.0.0",
|
||||
"@types/frida-gum": "^19.0.1",
|
||||
"esbuild": "^0.25.5",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
@@ -439,9 +439,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/frida-gum": {
|
||||
"version": "19.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.0.tgz",
|
||||
"integrity": "sha512-qViK1KwvPEAkajwSUv0wpZvZLiX8xO4JFFCh8dfYZfzSyOEfoE0KliCP/nJSKIKG6N3hXnPowrvPufjs5fLKAA==",
|
||||
"version": "19.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.1.tgz",
|
||||
"integrity": "sha512-mp8BpWWkQFJH86ZN5uXZuDiA7KY/+jDknrw0a06x0/+F5ucPwctHrCuV6iT+LLCp/GyICc36ssedF33B1WoLsw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"watch": "tsc -w"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/frida-gum": "^19.0.0",
|
||||
"@types/frida-gum": "^19.0.1",
|
||||
"esbuild": "^0.25.5",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
|
||||
@@ -84,23 +84,11 @@ namespace Frida.Barebone {
|
||||
throw new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
}
|
||||
|
||||
size_t vm_size = (size_t) elf.mapped_size;
|
||||
allocation = yield inject_elf (elf, machine, allocator, cancellable);
|
||||
|
||||
size_t page_size = yield machine.query_page_size (cancellable);
|
||||
uint num_pages = (uint) (vm_size / page_size);
|
||||
if (vm_size % page_size != 0)
|
||||
num_pages++;
|
||||
|
||||
var gdb = machine.gdb;
|
||||
|
||||
allocation = yield allocator.allocate (num_pages * page_size, page_size, cancellable);
|
||||
uint64 base_va = allocation.virtual_address;
|
||||
|
||||
Bytes relocated_image = machine.relocate (elf, base_va);
|
||||
yield gdb.write_byte_array (base_va, relocated_image, cancellable);
|
||||
|
||||
uint64 console_log_trap = 0;
|
||||
elf.enumerate_dynamic_symbols (e => {
|
||||
elf.enumerate_symbols (e => {
|
||||
if (e.name == "")
|
||||
return true;
|
||||
|
||||
@@ -116,38 +104,14 @@ namespace Frida.Barebone {
|
||||
});
|
||||
|
||||
if (console_log_trap != 0) {
|
||||
console_log_callback = yield new Callback (console_log_trap, new ConsoleLogHandler (this, gdb),
|
||||
machine, cancellable);
|
||||
var handler = new ConsoleLogHandler (machine.gdb);
|
||||
handler.output.connect (on_console_output);
|
||||
console_log_callback = yield new Callback (console_log_trap, handler, machine, cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
private class ConsoleLogHandler : Object, CallbackHandler {
|
||||
public uint arity {
|
||||
get { return 2; }
|
||||
}
|
||||
|
||||
private weak RustModule parent;
|
||||
private GDB.Client gdb;
|
||||
|
||||
public ConsoleLogHandler (RustModule parent, GDB.Client gdb) {
|
||||
this.parent = parent;
|
||||
this.gdb = gdb;
|
||||
}
|
||||
|
||||
public async uint64 handle_invocation (uint64[] args, CallFrame frame, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
var message = args[0];
|
||||
var len = (long) args[1];
|
||||
|
||||
Bytes str_bytes = yield gdb.read_byte_array (message, len, cancellable);
|
||||
unowned uint8[] str_data = str_bytes.get_data ();
|
||||
unowned string str_raw = (string) str_data;
|
||||
string str = str_raw.substring (0, len);
|
||||
|
||||
parent.console_output (str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
private void on_console_output (string message) {
|
||||
console_output (message);
|
||||
}
|
||||
|
||||
private const string CRATE_NAME = "rustmodule";
|
||||
@@ -201,7 +165,7 @@ namespace Frida.Barebone {
|
||||
.resolve_relative_path (CRATE_NAME);
|
||||
}
|
||||
|
||||
yield write_text_file (workdir, "module.lds", make_linker_script (symbols), cancellable);
|
||||
yield write_text_file (workdir, "module.lds", make_linker_script (code, symbols), cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.PERMISSION_DENIED ("%s", e.message);
|
||||
}
|
||||
@@ -270,8 +234,8 @@ namespace Frida.Barebone {
|
||||
return rs.str;
|
||||
}
|
||||
|
||||
private static string make_linker_script (Gee.Map<string, uint64?> symbols) {
|
||||
var script = new StringBuilder.sized (256);
|
||||
private static string make_linker_script (string code, Gee.Map<string, uint64?> symbols) {
|
||||
var script = new StringBuilder.sized (512);
|
||||
|
||||
foreach (var e in symbols.entries) {
|
||||
unowned string name = e.key;
|
||||
@@ -282,15 +246,16 @@ namespace Frida.Barebone {
|
||||
.append_printf ("0x%" + uint64.FORMAT_MODIFIER + "x;\n", address);
|
||||
}
|
||||
|
||||
script.append (prettify_text_asset (BASE_LINKER_SCRIPT));
|
||||
|
||||
return script.str;
|
||||
}
|
||||
|
||||
private const string BASE_LINKER_SCRIPT = """
|
||||
script.append ("""
|
||||
SECTIONS {
|
||||
.text : {
|
||||
*(.text*);
|
||||
""");
|
||||
|
||||
foreach (string name in extract_extern_c_symbols (code))
|
||||
script.append_printf (" KEEP(*(.text.%s))\n", name);
|
||||
|
||||
script.append ("""
|
||||
_console_log = .;
|
||||
. += 8;
|
||||
}
|
||||
@@ -307,7 +272,25 @@ namespace Frida.Barebone {
|
||||
*(.bss*)
|
||||
}
|
||||
}
|
||||
""";
|
||||
""");
|
||||
|
||||
return prettify_text_asset (script.str);
|
||||
}
|
||||
|
||||
private static Gee.List<string> extract_extern_c_symbols (string code) {
|
||||
var names = new Gee.ArrayList<string> ();
|
||||
|
||||
var export_pattern = /\#\[\s*no_mangle\s*\]\s*pub\s+(?:unsafe\s+)?extern\s*"C"\s+fn\s+([A-Za-z_]\w*)\s*\(/;
|
||||
|
||||
try {
|
||||
MatchInfo info;
|
||||
for (export_pattern.match (code, 0, out info); info.matches (); info.next ())
|
||||
names.add (info.fetch (1));
|
||||
} catch (RegexError e) {
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
private const string BUILTINS = """
|
||||
#![no_main]
|
||||
|
||||
@@ -304,6 +304,13 @@ Object.defineProperties(Process, {
|
||||
});
|
||||
|
||||
const marshalers: { [type: string]: Marshaler } = {
|
||||
void: {
|
||||
fromNative(v) {
|
||||
},
|
||||
toNative(v) {
|
||||
throw new Error("invalid operation");
|
||||
}
|
||||
},
|
||||
pointer: {
|
||||
fromNative(v) {
|
||||
return new BNativePointer(v);
|
||||
@@ -338,6 +345,28 @@ const marshalers: { [type: string]: Marshaler } = {
|
||||
return BigInt(v);
|
||||
}
|
||||
},
|
||||
uint: {
|
||||
fromNative(v) {
|
||||
return Number(v);
|
||||
},
|
||||
toNative(v) {
|
||||
if (typeof v !== "number") {
|
||||
throw new Error("expected an integer");
|
||||
}
|
||||
return BigInt(v);
|
||||
}
|
||||
},
|
||||
size_t: {
|
||||
fromNative(v) {
|
||||
return new BUInt64(v);
|
||||
},
|
||||
toNative(v) {
|
||||
if (typeof v === "number") {
|
||||
return BigInt(v);
|
||||
}
|
||||
return v.$v;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function getMarshalerFor(t: NativeFunctionReturnType | NativeFunctionArgumentType): Marshaler {
|
||||
|
||||
+114
-9
@@ -42,8 +42,6 @@ namespace Frida {
|
||||
|
||||
private Gee.Queue<QuickJS.Value?> tick_callbacks = new Gee.ArrayQueue<QuickJS.Value?> ();
|
||||
|
||||
private Barebone.Allocation? cached_landing_zone; // TODO: Deallocate on teardown.
|
||||
|
||||
private Gee.Set<Barebone.Callback> native_callbacks = new Gee.HashSet<Barebone.Callback> ();
|
||||
|
||||
private static QuickJS.ClassID cpu_context_class;
|
||||
@@ -56,6 +54,9 @@ namespace Frida {
|
||||
private static QuickJS.ClassExoticMethods invocation_args_exotic_methods;
|
||||
private static QuickJS.ClassID invocation_retval_class;
|
||||
|
||||
private static QuickJS.ClassID c_module_class;
|
||||
private Gee.Set<Barebone.CModule> c_modules = new Gee.HashSet<Barebone.CModule> ();
|
||||
|
||||
private static QuickJS.ClassID rust_module_class;
|
||||
private Gee.Set<Barebone.RustModule> rust_modules = new Gee.HashSet<Barebone.RustModule> ();
|
||||
|
||||
@@ -155,6 +156,7 @@ namespace Frida {
|
||||
|
||||
var memory_obj = ctx.make_object ();
|
||||
add_cfunc (memory_obj, "alloc", on_memory_alloc, 1);
|
||||
add_cfunc (memory_obj, "protect", on_memory_protect, 3);
|
||||
add_cfunc (memory_obj, "scan", on_memory_scan, 4);
|
||||
add_cfunc (memory_obj, "scanSync", on_memory_scan_sync, 3);
|
||||
global.set_property_str (ctx, "Memory", memory_obj);
|
||||
@@ -206,6 +208,17 @@ namespace Frida {
|
||||
ir.class_name = "InvocationReturnValue";
|
||||
rt.make_class (QuickJS.make_class_id (ref invocation_retval_class), ir);
|
||||
|
||||
QuickJS.ClassDef cm;
|
||||
cm.class_name = "CModule";
|
||||
cm.finalizer = on_c_module_finalize;
|
||||
rt.make_class (QuickJS.make_class_id (ref c_module_class), cm);
|
||||
var cm_proto = ctx.make_object ();
|
||||
add_cfunc (cm_proto, "dispose", on_c_module_dispose, 0);
|
||||
ctx.set_class_proto (c_module_class, cm_proto);
|
||||
var cm_ctor = ctx.make_cfunction2 (on_c_module_construct, cm.class_name, 1, constructor, 0);
|
||||
cm_ctor.set_constructor (ctx, cm_proto);
|
||||
global.set_property_str (ctx, "CModule", cm_ctor);
|
||||
|
||||
QuickJS.ClassDef rm;
|
||||
rm.class_name = "RustModule";
|
||||
rm.finalizer = on_rust_module_finalize;
|
||||
@@ -672,11 +685,7 @@ namespace Frida {
|
||||
|
||||
private async void do_invoke (uint64 impl, uint64[] args, Promise<uint64?> promise) {
|
||||
try {
|
||||
if (cached_landing_zone == null)
|
||||
cached_landing_zone = yield services.allocator.allocate (4, 1, io_cancellable);
|
||||
|
||||
uint64 retval = yield services.machine.invoke (impl, args, cached_landing_zone.virtual_address,
|
||||
io_cancellable);
|
||||
uint64 retval = yield services.machine.invoke (impl, args, io_cancellable);
|
||||
|
||||
promise.resolve (retval);
|
||||
} catch (GLib.Error e) {
|
||||
@@ -1124,6 +1133,41 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private static QuickJS.Value on_memory_protect (QuickJS.Context ctx, QuickJS.Value this_val, QuickJS.Value[] argv) {
|
||||
BareboneScript * script = ctx.get_opaque ();
|
||||
|
||||
uint64 address;
|
||||
if (!script->unparse_native_pointer (argv[0], out address))
|
||||
return QuickJS.Exception;
|
||||
|
||||
uint size;
|
||||
if (!script->unparse_uint (argv[1], out size))
|
||||
return QuickJS.Exception;
|
||||
|
||||
Gum.PageProtection prot;
|
||||
if (!script->unparse_page_protection (argv[2], out prot))
|
||||
return QuickJS.Exception;
|
||||
|
||||
var promise = new Promise<bool?> ();
|
||||
script->do_memory_protect.begin (address, size, prot, promise);
|
||||
|
||||
bool? result = script->process_events_until_ready (promise);
|
||||
if (result == null)
|
||||
return QuickJS.Exception;
|
||||
|
||||
return ctx.make_bool (result);
|
||||
}
|
||||
|
||||
private async void do_memory_protect (uint64 address, size_t size, Gum.PageProtection prot, Promise<bool?> promise) {
|
||||
try {
|
||||
yield services.machine.protect_pages (address, size, prot, io_cancellable);
|
||||
|
||||
promise.resolve (true);
|
||||
} catch (GLib.Error e) {
|
||||
promise.resolve (false);
|
||||
}
|
||||
}
|
||||
|
||||
private static QuickJS.Value on_memory_scan (QuickJS.Context ctx, QuickJS.Value this_val, QuickJS.Value[] argv) {
|
||||
BareboneScript * script = ctx.get_opaque ();
|
||||
|
||||
@@ -1791,6 +1835,67 @@ namespace Frida {
|
||||
return QuickJS.Undefined;
|
||||
}
|
||||
|
||||
private static QuickJS.Value on_c_module_construct (QuickJS.Context ctx, QuickJS.Value new_target,
|
||||
QuickJS.Value[] argv) {
|
||||
BareboneScript * script = ctx.get_opaque ();
|
||||
|
||||
Bytes blob;
|
||||
if (!script->unparse_bytes (argv[0], out blob))
|
||||
return QuickJS.Exception;
|
||||
|
||||
var promise = new Promise<Barebone.CModule> ();
|
||||
script->load_c_module.begin (blob, promise);
|
||||
|
||||
Barebone.CModule? mod = script->process_events_until_ready (promise);
|
||||
if (mod == null)
|
||||
return QuickJS.Exception;
|
||||
|
||||
var proto = new_target.get_property (ctx, script->prototype_key);
|
||||
var wrapper = ctx.make_object_with_proto_and_class (proto, c_module_class);
|
||||
ctx.free_value (proto);
|
||||
|
||||
wrapper.set_opaque (mod);
|
||||
script->c_modules.add (mod);
|
||||
|
||||
foreach (var e in mod.exports)
|
||||
wrapper.set_property_str (ctx, e.name, script->make_native_pointer (e.address));
|
||||
|
||||
mod.console_output.connect (script->on_console_output);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
private async void load_c_module (Bytes blob, Promise<Barebone.CModule> promise) {
|
||||
try {
|
||||
var mod = yield new Barebone.CModule.from_blob (blob, services.machine, services.allocator, io_cancellable);
|
||||
|
||||
promise.resolve (mod);
|
||||
} catch (GLib.Error e) {
|
||||
promise.reject (e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void on_c_module_finalize (QuickJS.Runtime rt, QuickJS.Value val) {
|
||||
Barebone.CModule * mod = val.get_opaque (c_module_class);
|
||||
if (mod == null)
|
||||
return;
|
||||
|
||||
BareboneScript * script = rt.get_opaque ();
|
||||
script->c_modules.remove (mod);
|
||||
}
|
||||
|
||||
private static QuickJS.Value on_c_module_dispose (QuickJS.Context ctx, QuickJS.Value this_val, QuickJS.Value[] argv) {
|
||||
Barebone.CModule * mod = this_val.get_opaque (c_module_class);
|
||||
|
||||
if (mod != null) {
|
||||
this_val.set_opaque (null);
|
||||
BareboneScript * script = ctx.get_opaque ();
|
||||
script->c_modules.remove (mod);
|
||||
}
|
||||
|
||||
return QuickJS.Undefined;
|
||||
}
|
||||
|
||||
private static QuickJS.Value on_rust_module_construct (QuickJS.Context ctx, QuickJS.Value new_target,
|
||||
QuickJS.Value[] argv) {
|
||||
BareboneScript * script = ctx.get_opaque ();
|
||||
@@ -1860,7 +1965,7 @@ namespace Frida {
|
||||
foreach (var e in mod.exports)
|
||||
wrapper.set_property_str (ctx, e.name, script->make_native_pointer (e.address));
|
||||
|
||||
mod.console_output.connect (script->on_rust_module_console_output);
|
||||
mod.console_output.connect (script->on_console_output);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
@@ -1898,7 +2003,7 @@ namespace Frida {
|
||||
return QuickJS.Undefined;
|
||||
}
|
||||
|
||||
private void on_rust_module_console_output (string message) {
|
||||
private void on_console_output (string message) {
|
||||
var builder = new Json.Builder ();
|
||||
builder
|
||||
.begin_object ()
|
||||
|
||||
Generated
+4
-4
@@ -33,7 +33,7 @@
|
||||
"@frida/url": "^1.0.2",
|
||||
"@frida/util": "^1.0.3",
|
||||
"@frida/vm": "^2.0.0",
|
||||
"@types/frida-gum": "19.0.0",
|
||||
"@types/frida-gum": "19.0.1",
|
||||
"@types/node": "18.19.103",
|
||||
"frida-fs": "7.0.0"
|
||||
}
|
||||
@@ -248,9 +248,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/frida-gum": {
|
||||
"version": "19.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.0.tgz",
|
||||
"integrity": "sha512-qViK1KwvPEAkajwSUv0wpZvZLiX8xO4JFFCh8dfYZfzSyOEfoE0KliCP/nJSKIKG6N3hXnPowrvPufjs5fLKAA==",
|
||||
"version": "19.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.1.tgz",
|
||||
"integrity": "sha512-mp8BpWWkQFJH86ZN5uXZuDiA7KY/+jDknrw0a06x0/+F5ucPwctHrCuV6iT+LLCp/GyICc36ssedF33B1WoLsw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"@frida/url": "^1.0.2",
|
||||
"@frida/util": "^1.0.3",
|
||||
"@frida/vm": "^2.0.0",
|
||||
"@types/frida-gum": "19.0.0",
|
||||
"@types/frida-gum": "19.0.1",
|
||||
"@types/node": "18.19.103",
|
||||
"frida-fs": "7.0.0"
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ namespace Frida {
|
||||
}
|
||||
|
||||
private void on_server_connection (IOStream connection, SocketAddress remote_address, DynamicInterface? dynamic_iface) {
|
||||
#if IOS || TVOS
|
||||
#if HAVE_LOCAL_BACKEND && (IOS || TVOS)
|
||||
/*
|
||||
* We defer the launchd injection until the first connection is established in order
|
||||
* to avoid bootloops on unsupported jailbreaks.
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
goto bsd_failure; \
|
||||
}
|
||||
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
# define CORE_FOUNDATION "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation"
|
||||
#else
|
||||
# define CORE_FOUNDATION "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
|
||||
@@ -390,7 +390,7 @@ static gboolean frida_spawn_instance_is_libc_initialized (FridaSpawnInstance * s
|
||||
static void frida_spawn_instance_set_libc_initialized (FridaSpawnInstance * self);
|
||||
static kern_return_t frida_spawn_instance_create_dyld_data (FridaSpawnInstance * self);
|
||||
static void frida_spawn_instance_destroy_dyld_data (FridaSpawnInstance * self);
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
static gboolean frida_pick_ios_tvos_bootstrapper (GumModule * module, gpointer user_data);
|
||||
#endif
|
||||
static void frida_spawn_instance_unset_helpers (FridaSpawnInstance * self);
|
||||
@@ -971,7 +971,7 @@ invalid_pid:
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
|
||||
#import "springboard.h"
|
||||
|
||||
@@ -2669,7 +2669,7 @@ frida_inject_instance_on_mach_thread_dead (void * context)
|
||||
|
||||
self->agent_context->posix_thread = MACH_PORT_NULL;
|
||||
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
port_might_be_guarded = gum_darwin_check_xnu_version (7938, 0, 0);
|
||||
#else
|
||||
port_might_be_guarded = FALSE;
|
||||
@@ -3284,7 +3284,7 @@ next_phase:
|
||||
return TRUE;
|
||||
|
||||
case FRIDA_BREAKPOINT_DLOPEN_BOOTSTRAPPER:
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
if (self->bootstrapper_name != 0)
|
||||
{
|
||||
frida_spawn_instance_set_libc_initialized (self);
|
||||
@@ -3577,7 +3577,7 @@ frida_spawn_instance_create_dyld_data (FridaSpawnInstance * self)
|
||||
if (!gum_darwin_query_ptrauth_support (self->task, &ptrauth_support))
|
||||
return KERN_FAILURE;
|
||||
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
gum_darwin_enumerate_modules (self->task, frida_pick_ios_tvos_bootstrapper, &data);
|
||||
#endif
|
||||
|
||||
@@ -3655,7 +3655,7 @@ frida_spawn_instance_destroy_dyld_data (FridaSpawnInstance * self)
|
||||
self->dyld_data = 0;
|
||||
}
|
||||
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
|
||||
static gboolean
|
||||
frida_pick_ios_tvos_bootstrapper (GumModule * module, gpointer user_data)
|
||||
@@ -5449,7 +5449,7 @@ frida_set_hardware_single_step (gpointer debug_state, GumDarwinUnifiedThreadStat
|
||||
static gboolean
|
||||
frida_is_hardware_breakpoint_support_working (void)
|
||||
{
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
static gsize cached_result = 0;
|
||||
|
||||
if (g_once_init_enter (&cached_result))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "frida-helper-backend.h"
|
||||
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
# include "policyd.h"
|
||||
# include "substituted-client.h"
|
||||
# include "substituted2-client.h"
|
||||
|
||||
+12
-12
@@ -16,11 +16,11 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
# import "springboard.h"
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_WATCHOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_WATCHOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
# import <Foundation/Foundation.h>
|
||||
#endif
|
||||
|
||||
@@ -35,7 +35,7 @@ struct _FridaEnumerateApplicationsOperation
|
||||
{
|
||||
FridaScope scope;
|
||||
GHashTable * process_by_identifier;
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
FridaSpringboardApi * api;
|
||||
#endif
|
||||
|
||||
@@ -45,14 +45,14 @@ struct _FridaEnumerateApplicationsOperation
|
||||
struct _FridaEnumerateProcessesOperation
|
||||
{
|
||||
FridaScope scope;
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
FridaSpringboardApi * api;
|
||||
#endif
|
||||
|
||||
GArray * result;
|
||||
};
|
||||
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
static void frida_collect_application_info_from_id_cstring (const gchar * identifier, FridaEnumerateApplicationsOperation * op);
|
||||
static void frida_collect_application_info_from_id_nsstring (NSString * identifier, FridaEnumerateApplicationsOperation * op);
|
||||
#endif
|
||||
@@ -60,13 +60,13 @@ static void frida_collect_application_info_from_id_nsstring (NSString * identifi
|
||||
static void frida_collect_process_info_from_pid (guint pid, FridaEnumerateProcessesOperation * op);
|
||||
static void frida_collect_process_info_from_kinfo (struct kinfo_proc * process, FridaEnumerateProcessesOperation * op);
|
||||
|
||||
#if defined (HAVE_MACOS) || defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_MACOS) || defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
static void frida_add_app_id (GHashTable * parameters, NSString * identifier);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_MACOS)
|
||||
static void frida_add_app_icons (GHashTable * parameters, NSImage * image);
|
||||
#elif defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#elif defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
static void frida_add_app_metadata (GHashTable * parameters, NSString * identifier, FridaSpringboardApi * api);
|
||||
static void frida_add_app_state (GHashTable * parameters, guint pid, FridaSpringboardApi * api);
|
||||
static void frida_add_app_icons (GHashTable * parameters, NSString * identifier);
|
||||
@@ -100,7 +100,7 @@ frida_system_enumerate_applications (FridaApplicationQueryOptions * options, int
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#elif defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#elif defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
|
||||
void
|
||||
frida_system_get_frontmost_application (FridaFrontmostQueryOptions * options, FridaHostApplicationInfo * result, GError ** error)
|
||||
@@ -306,7 +306,7 @@ frida_system_enumerate_processes (FridaProcessQueryOptions * options, int * resu
|
||||
NSAutoreleasePool * pool;
|
||||
|
||||
op.scope = frida_process_query_options_get_scope (options);
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
op.api = _frida_get_springboard_api ();
|
||||
#endif
|
||||
|
||||
@@ -395,7 +395,7 @@ frida_collect_process_info_from_kinfo (struct kinfo_proc * process, FridaEnumera
|
||||
frida_add_app_icons (info.parameters, app.icon);
|
||||
}
|
||||
}
|
||||
#elif defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#elif defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
{
|
||||
FridaSpringboardApi * api = op->api;
|
||||
NSString * identifier;
|
||||
@@ -469,7 +469,7 @@ frida_temporary_directory_get_system_tmp (void)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (HAVE_MACOS) || defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#if defined (HAVE_MACOS) || defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
|
||||
static void
|
||||
frida_add_app_id (GHashTable * parameters, NSString * identifier)
|
||||
@@ -541,7 +541,7 @@ frida_add_app_icons (GHashTable * parameters, NSImage * image)
|
||||
g_hash_table_insert (parameters, g_strdup ("icons"), g_variant_ref_sink (g_variant_builder_end (&builder)));
|
||||
}
|
||||
|
||||
#elif defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
#elif defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
|
||||
static void
|
||||
frida_add_app_metadata (GHashTable * parameters, NSString * identifier, FridaSpringboardApi * api)
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ def main(argv):
|
||||
for asset in {embedded_agent, embedded_dbghelp, embedded_symsrv}:
|
||||
asset.write_bytes(b"")
|
||||
embedded_assets += [asset]
|
||||
elif host_os in {"macos", "ios", "watchos", "tvos"}:
|
||||
elif host_os in {"macos", "ios", "watchos", "tvos", "xros"}:
|
||||
embedded_agent = priv_dir / "frida-agent.dylib"
|
||||
if agent_modern is not None and agent_legacy is not None:
|
||||
subprocess.run(lipo + [agent_modern, agent_legacy, "-create", "-output", embedded_agent],
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ def main(argv):
|
||||
embedded_helper = priv_dir / f"frida-helper-{missing_arch}.exe"
|
||||
embedded_helper.write_bytes(b"")
|
||||
embedded_assets += [embedded_helper]
|
||||
elif host_os in {"macos", "ios", "watchos", "tvos"}:
|
||||
elif host_os in {"macos", "ios", "watchos", "tvos", "xros"}:
|
||||
embedded_helper = priv_dir / "frida-helper"
|
||||
|
||||
if helper_modern is not None and helper_legacy is not None:
|
||||
|
||||
@@ -1626,7 +1626,9 @@ frida_run_to_entrypoint (pid_t pid, GError ** error)
|
||||
ret = frida_get_regs (pid, ®s);
|
||||
CHECK_OS_RESULT (ret, ==, 0, "frida_get_regs");
|
||||
|
||||
#if defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8
|
||||
#if defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 4
|
||||
regs.r_eip = entrypoint;
|
||||
#elif defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8
|
||||
regs.r_rip = entrypoint;
|
||||
#elif defined (HAVE_ARM64)
|
||||
regs.elr = entrypoint;
|
||||
@@ -1823,7 +1825,33 @@ frida_remote_call (pid_t pid, GumAddress func, const GumAddress * args, gint arg
|
||||
ret = frida_get_regs (pid, ®s);
|
||||
CHECK_OS_RESULT (ret, ==, 0, "frida_get_regs");
|
||||
|
||||
#if defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8
|
||||
#if defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 4
|
||||
regs.r_esp -= FRIDA_RED_ZONE_SIZE;
|
||||
regs.r_esp -= (regs.r_esp - (args_length * 4)) % FRIDA_STACK_ALIGNMENT;
|
||||
|
||||
regs.r_eip = func;
|
||||
|
||||
if (args_length != 0)
|
||||
{
|
||||
guintptr * stack_args;
|
||||
|
||||
stack_args = g_newa (guintptr, args_length);
|
||||
for (i = 0; i != args_length; i++)
|
||||
stack_args[i] = args[i];
|
||||
|
||||
regs.r_esp -= args_length * sizeof (guintptr);
|
||||
if (!frida_remote_write (pid, regs.r_esp, stack_args, args_length * sizeof (guintptr), error))
|
||||
goto propagate_error;
|
||||
}
|
||||
|
||||
{
|
||||
guintptr dummy_return_address = FRIDA_DUMMY_RETURN_ADDRESS;
|
||||
|
||||
regs.r_esp -= 4;
|
||||
if (!frida_remote_write (pid, regs.r_esp, &dummy_return_address, sizeof (dummy_return_address), error))
|
||||
goto propagate_error;
|
||||
}
|
||||
#elif defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8
|
||||
regs.r_rsp -= FRIDA_RED_ZONE_SIZE;
|
||||
regs.r_rsp -= (regs.r_rsp - (MAX (args_length - 6, 0) * 8)) % FRIDA_STACK_ALIGNMENT;
|
||||
|
||||
@@ -1905,7 +1933,9 @@ frida_remote_call (pid_t pid, GumAddress func, const GumAddress * args, gint arg
|
||||
ret = frida_get_regs (pid, ®s);
|
||||
CHECK_OS_RESULT (ret, ==, 0, "frida_get_regs");
|
||||
|
||||
#if defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8
|
||||
#if defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 4
|
||||
*retval = regs.r_eax;
|
||||
#elif defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8
|
||||
*retval = regs.r_rax;
|
||||
#elif defined (HAVE_ARM64)
|
||||
*retval = regs.x[0];
|
||||
@@ -1924,7 +1954,7 @@ os_failure:
|
||||
failed_operation, g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
#if defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8
|
||||
#ifdef HAVE_I386
|
||||
propagate_error:
|
||||
{
|
||||
return FALSE;
|
||||
@@ -1943,7 +1973,10 @@ frida_remote_exec (pid_t pid, GumAddress remote_address, GumAddress remote_stack
|
||||
ret = frida_get_regs (pid, ®s);
|
||||
CHECK_OS_RESULT (ret, ==, 0, "frida_get_regs");
|
||||
|
||||
#if defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8
|
||||
#if defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 4
|
||||
regs.r_eip = remote_address;
|
||||
regs.r_esp = remote_stack;
|
||||
#elif defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8
|
||||
regs.r_rip = remote_address;
|
||||
regs.r_rsp = remote_stack;
|
||||
#elif defined (HAVE_ARM64)
|
||||
@@ -1967,7 +2000,9 @@ frida_remote_exec (pid_t pid, GumAddress remote_address, GumAddress remote_stack
|
||||
ret = frida_get_regs (pid, ®s);
|
||||
CHECK_OS_RESULT (ret, ==, 0, "frida_get_regs");
|
||||
|
||||
#if defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8
|
||||
#if defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 4
|
||||
*result = regs.r_eax;
|
||||
#elif defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8
|
||||
*result = regs.r_rax;
|
||||
#elif defined (HAVE_ARM64)
|
||||
*result = regs.x[0];
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
|
||||
namespace Frida.DebuggerMappings {
|
||||
internal async void spray_pages (GDB.Client gdb, uint64 address, size_t size, size_t page_size, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
int n_pages = (int) (size / page_size);
|
||||
if (n_pages == 0)
|
||||
throw new Error.INVALID_ARGUMENT ("Expected one or more pages");
|
||||
|
||||
var builder = gdb.make_packet_builder_sized (64);
|
||||
Future<bool>? last_write = null;
|
||||
|
||||
for (int i = 0; i < n_pages; i += 2) {
|
||||
bool is_last = (i + 2 >= n_pages);
|
||||
|
||||
uint64 last_byte_addr = address + ((uint64) i * page_size) + page_size - 1;
|
||||
size_t write_count = is_last ? 1 : 2;
|
||||
|
||||
builder
|
||||
.append_c ('M')
|
||||
.append_address (last_byte_addr)
|
||||
.append_c (',')
|
||||
.append_size (write_count)
|
||||
.append_c (':')
|
||||
.append_escaped ((write_count == 2) ? "0000" : "00");
|
||||
|
||||
var request = new Promise<bool> ();
|
||||
gdb.perform_execute.begin (builder.build (), cancellable, request);
|
||||
|
||||
builder.reset ();
|
||||
|
||||
if (is_last)
|
||||
last_write = request.future;
|
||||
}
|
||||
|
||||
yield last_write.wait_async (cancellable);
|
||||
}
|
||||
|
||||
internal async void handle_page_plan (GDB.Client gdb, uint64 address, size_t size, size_t page_size, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
var plan = new BufferReader (yield gdb.read_buffer (address, size, cancellable));
|
||||
|
||||
var n_blocks = plan.read_uint32 ();
|
||||
if (n_blocks == 0)
|
||||
return;
|
||||
|
||||
var builder = gdb.make_packet_builder_sized (64);
|
||||
Future<bool>? last_write = null;
|
||||
|
||||
for (uint32 i = 0; i != n_blocks; i++) {
|
||||
uint64 start = plan.read_pointer ();
|
||||
uint32 count = plan.read_uint32 ();
|
||||
|
||||
for (size_t j = 0; j < count; j += 2) {
|
||||
bool is_last = (j + 2 >= count) && (i == n_blocks - 1);
|
||||
|
||||
uint64 last_byte_addr = start + ((uint64) j * page_size) + page_size - 1;
|
||||
size_t write_count = size_t.min (2, count - j);
|
||||
|
||||
builder
|
||||
.append_c ('M')
|
||||
.append_address (last_byte_addr)
|
||||
.append_c (',')
|
||||
.append_size (write_count)
|
||||
.append_c (':')
|
||||
.append_hexbyte (plan.read_uint8 ());
|
||||
|
||||
if (write_count == 2)
|
||||
builder.append_hexbyte (plan.read_uint8 ());
|
||||
|
||||
var request = new Promise<bool> ();
|
||||
gdb.perform_execute.begin (builder.build (), cancellable, request);
|
||||
|
||||
builder.reset ();
|
||||
|
||||
if (is_last)
|
||||
last_write = request.future;
|
||||
}
|
||||
}
|
||||
|
||||
yield last_write.wait_async (cancellable);
|
||||
}
|
||||
}
|
||||
@@ -808,14 +808,17 @@ namespace Frida {
|
||||
var lldb = yield start_lldb_service (cancellable);
|
||||
var process = yield lldb.launch (argv, launch_options, cancellable);
|
||||
if (process.observed_state == ALREADY_RUNNING) {
|
||||
yield lldb.kill (cancellable);
|
||||
try {
|
||||
yield lldb.kill (cancellable);
|
||||
} catch (Error e) {
|
||||
}
|
||||
yield lldb.close (cancellable);
|
||||
|
||||
lldb = yield start_lldb_service (cancellable);
|
||||
process = yield lldb.launch (argv, launch_options, cancellable);
|
||||
}
|
||||
|
||||
var session = new LLDBSession (lldb, process, gadget_path, device);
|
||||
var session = new LLDBSession (lldb, process, gadget_path, ExceptionHandlingStatus.LIMITED, device);
|
||||
add_lldb_session (session);
|
||||
|
||||
return process.pid;
|
||||
@@ -833,8 +836,13 @@ namespace Frida {
|
||||
public async void resume (uint pid, Cancellable? cancellable) throws Error, IOError {
|
||||
var session = lldb_sessions[pid];
|
||||
if (session != null) {
|
||||
yield session.resume (cancellable);
|
||||
return;
|
||||
foreach (var entry in gadget_entries.values) {
|
||||
if (entry.pid == pid) {
|
||||
yield entry.resume (cancellable);
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
var server = yield get_remote_server (cancellable);
|
||||
@@ -867,7 +875,7 @@ namespace Frida {
|
||||
var lldb = yield start_lldb_service (cancellable);
|
||||
var process = yield lldb.attach_by_pid (pid, cancellable);
|
||||
|
||||
lldb_session = new LLDBSession (lldb, process, null, device);
|
||||
lldb_session = new LLDBSession (lldb, process, null, ExceptionHandlingStatus.FULL, device);
|
||||
yield lldb_session.kill (cancellable);
|
||||
yield lldb_session.close (cancellable);
|
||||
} catch (Error e) {
|
||||
@@ -903,7 +911,7 @@ namespace Frida {
|
||||
|
||||
string? gadget_path = null;
|
||||
|
||||
lldb_session = new LLDBSession (lldb, process, gadget_path, device);
|
||||
lldb_session = new LLDBSession (lldb, process, gadget_path, ExceptionHandlingStatus.LIMITED, device);
|
||||
add_lldb_session (lldb_session);
|
||||
|
||||
var gadget_details = yield lldb_session.query_gadget_details (cancellable);
|
||||
@@ -955,7 +963,7 @@ namespace Frida {
|
||||
}
|
||||
|
||||
var local_session_id = AgentSessionId.generate ();
|
||||
var gadget_entry = new GadgetEntry (local_session_id, host_session, connection);
|
||||
var gadget_entry = new GadgetEntry (local_session_id, host_session, connection, pid);
|
||||
gadget_entry.detached.connect (on_gadget_entry_detached);
|
||||
gadget_entries[local_session_id] = gadget_entry;
|
||||
agent_sessions[local_session_id] = new AgentSessionEntry (remote_session_id, connection);
|
||||
@@ -1139,9 +1147,22 @@ namespace Frida {
|
||||
}
|
||||
|
||||
private void on_gadget_entry_detached (GadgetEntry entry, SessionDetachReason reason) {
|
||||
detach_entry.begin (entry, reason);
|
||||
}
|
||||
|
||||
private async void detach_entry (GadgetEntry entry, SessionDetachReason reason) throws Error, IOError {
|
||||
AgentSessionId id = entry.local_session_id;
|
||||
var no_crash = CrashInfo.empty ();
|
||||
|
||||
var lldb_session = lldb_sessions[entry.pid];
|
||||
if (lldb_session != null) {
|
||||
remove_lldb_session (lldb_session);
|
||||
if (reason == SessionDetachReason.APPLICATION_REQUESTED)
|
||||
yield entry.detach_lldb (lldb_session, io_cancellable);
|
||||
else
|
||||
yield lldb_session.close (io_cancellable);
|
||||
}
|
||||
|
||||
gadget_entries.unset (id);
|
||||
agent_sessions.unset (id);
|
||||
|
||||
@@ -1375,6 +1396,7 @@ namespace Frida {
|
||||
|
||||
private class LLDBSession : Object {
|
||||
public signal void closed ();
|
||||
public signal void detached ();
|
||||
public signal void output (Bytes bytes);
|
||||
|
||||
public LLDB.Client lldb {
|
||||
@@ -1397,14 +1419,27 @@ namespace Frida {
|
||||
construct;
|
||||
}
|
||||
|
||||
private Promise<Fruity.Injector.GadgetDetails>? gadget_request;
|
||||
public ExceptionHandlingStatus exception_handling_status {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public LLDBSession (LLDB.Client lldb, LLDB.Process process, string? gadget_path,
|
||||
private Promise<Fruity.Injector.GadgetDetails>? gadget_request;
|
||||
private ulong? exception_handler;
|
||||
private string? main_thread_id;
|
||||
private bool resumed = false;
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
private const size_t PAGE_SIZE = 0x4000;
|
||||
|
||||
public LLDBSession (LLDB.Client lldb, LLDB.Process process, string? gadget_path, ExceptionHandlingStatus ehs,
|
||||
HostChannelProvider channel_provider) {
|
||||
Object (
|
||||
lldb: lldb,
|
||||
process: process,
|
||||
gadget_path: gadget_path,
|
||||
exception_handling_status: ehs,
|
||||
channel_provider: channel_provider
|
||||
);
|
||||
}
|
||||
@@ -1415,20 +1450,90 @@ namespace Frida {
|
||||
}
|
||||
|
||||
~LLDBSession () {
|
||||
detach_exception_handler ();
|
||||
|
||||
lldb.closed.disconnect (on_lldb_closed);
|
||||
lldb.console_output.disconnect (on_lldb_console_output);
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
io_cancellable.cancel ();
|
||||
|
||||
detach_exception_handler ();
|
||||
|
||||
yield lldb.close (cancellable);
|
||||
}
|
||||
|
||||
public async void resume (Cancellable? cancellable) throws Error, IOError {
|
||||
yield lldb.detach (cancellable);
|
||||
private async void handle_exception (GDB.Exception exception) throws Error, IOError {
|
||||
var e = (Frida.LLDB.Exception) exception;
|
||||
|
||||
var sig = (LLDB.Signal) e.signum;
|
||||
var medata = e.medata;
|
||||
if (sig == SIGTRAP && e.metype == EXC_BREAKPOINT && medata.size == 2) {
|
||||
uint64 x1 = e.context["x1"];
|
||||
uint64 x2 = e.context["x2"];
|
||||
var action = (GadgetBreakpointAction) e.context["x3"];
|
||||
if (x1 == x2 == 1337) {
|
||||
uint64 pc = e.context["pc"];
|
||||
var thread = e.thread;
|
||||
yield thread.write_register ("pc", pc + 4, io_cancellable);
|
||||
|
||||
switch (action) {
|
||||
case RESUME: {
|
||||
resumed = true;
|
||||
yield lldb.continue (io_cancellable);
|
||||
|
||||
return;
|
||||
}
|
||||
case DETACH: {
|
||||
yield lldb.detach (io_cancellable);
|
||||
detached ();
|
||||
|
||||
break;
|
||||
}
|
||||
case PAGE_PLAN: {
|
||||
var plan_size = (size_t) e.context["x4"];
|
||||
var plan_address = e.context["x5"];
|
||||
yield DebuggerMappings.handle_page_plan (lldb, plan_address, plan_size,
|
||||
PAGE_SIZE, io_cancellable);
|
||||
|
||||
yield thread.write_register ("x0", 0x1337, io_cancellable);
|
||||
|
||||
if (resumed)
|
||||
yield lldb.continue (io_cancellable);
|
||||
else
|
||||
yield continue_gadget_threads (io_cancellable);
|
||||
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
detach_exception_handler ();
|
||||
|
||||
yield lldb.close (io_cancellable);
|
||||
}
|
||||
|
||||
private async void continue_gadget_threads (Cancellable? cancellable) throws Error, IOError {
|
||||
var gadget_threads = new Gee.ArrayList<LLDB.Thread> ();
|
||||
yield lldb.enumerate_threads (thread => {
|
||||
if (thread.id != main_thread_id)
|
||||
gadget_threads.add (thread);
|
||||
return true;
|
||||
}, cancellable);
|
||||
yield lldb.continue_specific_threads (gadget_threads, cancellable);
|
||||
}
|
||||
|
||||
public async void kill (Cancellable? cancellable) throws Error, IOError {
|
||||
yield lldb.kill (cancellable);
|
||||
detach_exception_handler ();
|
||||
|
||||
if (exception_handling_status == FULL)
|
||||
yield lldb.kill (cancellable);
|
||||
else
|
||||
yield lldb.close (cancellable);
|
||||
}
|
||||
|
||||
public async Fruity.Injector.GadgetDetails query_gadget_details (Cancellable? cancellable) throws Error, IOError {
|
||||
@@ -1461,13 +1566,26 @@ namespace Frida {
|
||||
: Gum.PtrauthSupport.UNSUPPORTED;
|
||||
var module = new Gum.DarwinModule.from_file (path, Gum.CpuType.ARM64, ptrauth_support);
|
||||
|
||||
var details = yield Fruity.Injector.inject ((owned) module, lldb, channel_provider, cancellable);
|
||||
Fruity.Injector.Transaction transaction =
|
||||
yield Fruity.Injector.inject ((owned) module, lldb, channel_provider, cancellable);
|
||||
Fruity.Injector.GadgetDetails gadget = transaction.gadget;
|
||||
main_thread_id = transaction.main_thread_id;
|
||||
|
||||
gadget_request.resolve (details);
|
||||
exception_handler = lldb.notify["exception"].connect ((obj, pspec) => {
|
||||
var exception = lldb.exception;
|
||||
if (exception != null)
|
||||
handle_exception.begin (exception);
|
||||
});
|
||||
|
||||
return details;
|
||||
yield transaction.commit (cancellable);
|
||||
|
||||
gadget_request.resolve (gadget);
|
||||
|
||||
return gadget;
|
||||
} catch (GLib.Error e) {
|
||||
var api_error = new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
var api_error = (e is Error)
|
||||
? (Error) e
|
||||
: new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
|
||||
gadget_request.reject (api_error);
|
||||
gadget_request = null;
|
||||
@@ -1476,6 +1594,13 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private void detach_exception_handler () {
|
||||
if (exception_handler != null) {
|
||||
lldb.disconnect (exception_handler);
|
||||
exception_handler = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void on_lldb_closed () {
|
||||
closed ();
|
||||
}
|
||||
@@ -1485,6 +1610,11 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private enum ExceptionHandlingStatus {
|
||||
FULL,
|
||||
LIMITED,
|
||||
}
|
||||
|
||||
private class GadgetEntry : Object {
|
||||
public signal void detached (SessionDetachReason reason);
|
||||
|
||||
@@ -1503,13 +1633,20 @@ namespace Frida {
|
||||
construct;
|
||||
}
|
||||
|
||||
private Promise<bool>? close_request;
|
||||
public uint pid {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public GadgetEntry (AgentSessionId local_session_id, HostSession host_session, DBusConnection connection) {
|
||||
private Promise<bool>? close_request;
|
||||
private Promise<bool>? detach_request;
|
||||
|
||||
public GadgetEntry (AgentSessionId local_session_id, HostSession host_session, DBusConnection connection, uint pid) {
|
||||
Object (
|
||||
local_session_id: local_session_id,
|
||||
host_session: host_session,
|
||||
connection: connection
|
||||
connection: connection,
|
||||
pid: pid
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1550,6 +1687,48 @@ namespace Frida {
|
||||
close_request.resolve (true);
|
||||
}
|
||||
|
||||
public async void resume (Cancellable? cancellable) throws Error, IOError {
|
||||
try {
|
||||
GadgetSession session = yield connection.get_proxy (null, ObjectPath.GADGET_SESSION,
|
||||
DO_NOT_LOAD_PROPERTIES, cancellable);
|
||||
|
||||
yield session.break_and_resume (cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw_dbus_error (e);
|
||||
}
|
||||
}
|
||||
|
||||
public async void detach_lldb (LLDBSession lldb_session, Cancellable? cancellable) throws Error, IOError {
|
||||
while (detach_request != null) {
|
||||
try {
|
||||
yield detach_request.future.wait_async (cancellable);
|
||||
return;
|
||||
} catch (Error e) {
|
||||
assert_not_reached ();
|
||||
} catch (IOError e) {
|
||||
cancellable.set_error_if_cancelled ();
|
||||
}
|
||||
}
|
||||
detach_request = new Promise<bool> ();
|
||||
|
||||
try {
|
||||
GadgetSession session = yield connection.get_proxy (null, ObjectPath.GADGET_SESSION,
|
||||
DO_NOT_LOAD_PROPERTIES, cancellable);
|
||||
|
||||
lldb_session.detached.connect (on_lldb_session_detached);
|
||||
|
||||
yield session.break_and_detach (cancellable);
|
||||
|
||||
yield detach_request.future.wait_async (cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
detach_request.reject (e);
|
||||
throw_dbus_error (e);
|
||||
} finally {
|
||||
lldb_session.detached.disconnect (on_lldb_session_detached);
|
||||
detach_request = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void on_connection_closed (DBusConnection connection, bool remote_peer_vanished, GLib.Error? error) {
|
||||
if (close_request == null) {
|
||||
close_request = new Promise<bool> ();
|
||||
@@ -1562,6 +1741,11 @@ namespace Frida {
|
||||
private void on_session_detached (AgentSessionId id, SessionDetachReason reason) {
|
||||
detached (reason);
|
||||
}
|
||||
|
||||
private void on_lldb_session_detached () {
|
||||
if (detach_request != null)
|
||||
detach_request.resolve (true);
|
||||
}
|
||||
}
|
||||
|
||||
private class AgentSessionEntry {
|
||||
|
||||
@@ -24,17 +24,21 @@ struct _FridaUploadApi
|
||||
int (* listen) (int socket, int backlog);
|
||||
int (* getsockname) (int socket, struct sockaddr * restrict address, socklen_t * restrict address_len);
|
||||
int (* accept) (int socket, struct sockaddr * restrict address, socklen_t * restrict address_len);
|
||||
int (* close) (int fd);
|
||||
ssize_t (* read) (int fd, void * buf, size_t n);
|
||||
ssize_t (* write) (int fd, const void *buf, size_t n);
|
||||
int (* getpagesize) (void);
|
||||
int (* mprotect) (void * addr, size_t len, int prot);
|
||||
void (* sys_icache_invalidate) (void * start, size_t len);
|
||||
void (* sys_dcache_flush) (void * start, size_t len);
|
||||
mach_port_t (* _mach_task_self) (void);
|
||||
kern_return_t (* mach_vm_allocate) (vm_map_t target, mach_vm_address_t * address, mach_vm_size_t size, int flags);
|
||||
kern_return_t (* mach_vm_deallocate) (vm_map_t target, mach_vm_address_t address, mach_vm_size_t size);
|
||||
kern_return_t (* vm_remap) (vm_map_t target_task, vm_address_t * target_address, vm_size_t size, vm_address_t mask, int flags,
|
||||
vm_map_t src_task, vm_address_t src_address, boolean_t copy, vm_prot_t * cur_protection, vm_prot_t * max_protection,
|
||||
vm_inherit_t inheritance);
|
||||
void * (* dlopen) (const char * path, int mode);
|
||||
void * (* dlsym) (void * handle, const char * symbol);
|
||||
int (* mprotect) (void * addr, size_t len, int prot);
|
||||
int (* close) (int fd);
|
||||
|
||||
int * (* get_errno_storage) (void);
|
||||
};
|
||||
@@ -46,18 +50,20 @@ struct _FridaUploadApi
|
||||
listen, \
|
||||
getsockname, \
|
||||
accept, \
|
||||
close, \
|
||||
read, \
|
||||
write, \
|
||||
getpagesize, \
|
||||
mprotect, \
|
||||
sys_icache_invalidate, \
|
||||
sys_dcache_flush, \
|
||||
dlsym (RTLD_DEFAULT, "mach_task_self"), \
|
||||
mach_vm_allocate, \
|
||||
mach_vm_deallocate, \
|
||||
vm_remap, \
|
||||
dlopen, \
|
||||
dlsym, \
|
||||
mprotect, \
|
||||
close, \
|
||||
__error \
|
||||
__error, \
|
||||
}
|
||||
|
||||
#define FRIDA_RX_BUFFER_SIZE (1024 * 1024)
|
||||
|
||||
@@ -67,7 +67,7 @@ failure:
|
||||
if (fd != -1)
|
||||
api->close (fd);
|
||||
|
||||
return ((uint64_t) error_code << 56);
|
||||
return ((uint64_t) error_code << 57);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -258,6 +258,7 @@ int64_t
|
||||
frida_receive (int listener_fd, uint64_t session_id_top, uint64_t session_id_bottom, const char * apple[], const FridaUploadApi * api)
|
||||
{
|
||||
int result = 0;
|
||||
mach_port_t task;
|
||||
bool expecting_client;
|
||||
int res;
|
||||
struct sockaddr_in addr;
|
||||
@@ -265,6 +266,8 @@ frida_receive (int listener_fd, uint64_t session_id_top, uint64_t session_id_bot
|
||||
int client_fd;
|
||||
uint32_t ACK_MAGIC = 0xac4ac4ac;
|
||||
|
||||
task = api->_mach_task_self ();
|
||||
|
||||
expecting_client = true;
|
||||
|
||||
do
|
||||
@@ -307,16 +310,33 @@ frida_receive (int listener_fd, uint64_t session_id_top, uint64_t session_id_bot
|
||||
{
|
||||
uint64_t address;
|
||||
uint32_t size;
|
||||
vm_address_t writable_address;
|
||||
vm_prot_t cur_prot, max_prot;
|
||||
size_t n;
|
||||
|
||||
FRIDA_READ_VALUE (address);
|
||||
FRIDA_READ_VALUE (size);
|
||||
|
||||
success = frida_read_chunk (client_fd, (void *) address, size, &n, api);
|
||||
writable_address = 0;
|
||||
success = api->vm_remap (task, &writable_address, size, 0, VM_FLAGS_ANYWHERE, task, address, FALSE, &cur_prot, &max_prot,
|
||||
VM_INHERIT_NONE) == 0;
|
||||
if (!success)
|
||||
break;
|
||||
|
||||
success = api->mprotect ((void *) writable_address, size, VM_PROT_READ | VM_PROT_WRITE) == 0;
|
||||
if (!success)
|
||||
goto unmap_writable;
|
||||
|
||||
success = frida_read_chunk (client_fd, (void *) writable_address, size, &n, api);
|
||||
if (!success)
|
||||
goto unmap_writable;
|
||||
|
||||
api->sys_icache_invalidate ((void *) address, n);
|
||||
api->sys_dcache_flush ((void *) address, n);
|
||||
|
||||
unmap_writable:
|
||||
api->mach_vm_deallocate (task, writable_address, size);
|
||||
|
||||
break;
|
||||
}
|
||||
case FRIDA_UPLOAD_COMMAND_APPLY_THREADED:
|
||||
@@ -449,6 +469,19 @@ next_client:
|
||||
beach:
|
||||
api->close (listener_fd);
|
||||
|
||||
#ifndef BUILDING_TEST_PROGRAM
|
||||
asm volatile (
|
||||
"mov x0, %0\n\t"
|
||||
"mov x1, #1337\n\t"
|
||||
"mov x2, #1337\n\t"
|
||||
"mov x3, #0\n\t"
|
||||
"brk #1337\n\t"
|
||||
:
|
||||
: "r" ((uint64_t) result)
|
||||
: "x0", "x1", "x2", "x3"
|
||||
);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+359
-296
@@ -1,11 +1,45 @@
|
||||
[CCode (gir_namespace = "FridaFruityInjector", gir_version = "1.0")]
|
||||
namespace Frida.Fruity.Injector {
|
||||
public static async GadgetDetails inject (owned Gum.DarwinModule module, LLDB.Client lldb, HostChannelProvider channel_provider,
|
||||
public static async Transaction inject (owned Gum.DarwinModule module, LLDB.Client lldb, HostChannelProvider channel_provider,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
var session = new Session (module, lldb, channel_provider);
|
||||
return yield session.run (cancellable);
|
||||
}
|
||||
|
||||
public sealed class Transaction : Object {
|
||||
public GadgetDetails gadget {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public string main_thread_id;
|
||||
|
||||
private bool is_early_instrumentation;
|
||||
private LLDB.Client lldb;
|
||||
|
||||
internal Transaction (GadgetDetails gadget, bool is_early_instrumentation, string main_thread_id, LLDB.Client lldb) {
|
||||
Object (gadget: gadget);
|
||||
|
||||
this.is_early_instrumentation = is_early_instrumentation;
|
||||
this.main_thread_id = main_thread_id;
|
||||
this.lldb = lldb;
|
||||
}
|
||||
|
||||
public async void commit (Cancellable? cancellable) throws Error, IOError {
|
||||
if (is_early_instrumentation) {
|
||||
var gadget_threads = new Gee.ArrayList<LLDB.Thread> ();
|
||||
yield lldb.enumerate_threads (thread => {
|
||||
if (thread.id != main_thread_id)
|
||||
gadget_threads.add (thread);
|
||||
return true;
|
||||
}, cancellable);
|
||||
yield lldb.continue_specific_threads (gadget_threads, cancellable);
|
||||
} else {
|
||||
yield lldb.continue (cancellable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class GadgetDetails : Object {
|
||||
public uint16 port {
|
||||
get;
|
||||
@@ -17,10 +51,6 @@ namespace Frida.Fruity.Injector {
|
||||
}
|
||||
}
|
||||
|
||||
public errordomain Error {
|
||||
UNSUPPORTED
|
||||
}
|
||||
|
||||
private sealed class Session : Object {
|
||||
public Gum.DarwinModule module {
|
||||
get;
|
||||
@@ -77,36 +107,26 @@ namespace Frida.Fruity.Injector {
|
||||
);
|
||||
}
|
||||
|
||||
public async GadgetDetails run (Cancellable? cancellable) throws Error, IOError {
|
||||
public async Transaction run (Cancellable? cancellable) throws Error, IOError {
|
||||
try {
|
||||
bool is_early_instrumentation;
|
||||
|
||||
var existing_gadget = yield setup (cancellable);
|
||||
if (existing_gadget != null) {
|
||||
yield lldb.detach (cancellable);
|
||||
return existing_gadget;
|
||||
is_early_instrumentation = false;
|
||||
return new Transaction (existing_gadget, is_early_instrumentation, main_thread.id, lldb);
|
||||
}
|
||||
|
||||
bool is_early_instrumentation = !libsystem_initialized;
|
||||
is_early_instrumentation = !libsystem_initialized;
|
||||
|
||||
yield ensure_libsystem_initialized (cancellable);
|
||||
var result = yield inject_module (cancellable);
|
||||
var gadget = yield inject_module (cancellable);
|
||||
|
||||
yield teardown (cancellable);
|
||||
|
||||
if (is_early_instrumentation) {
|
||||
var gadget_threads = new Gee.ArrayList<LLDB.Thread> ();
|
||||
yield lldb.enumerate_threads (thread => {
|
||||
if (thread.id != main_thread.id)
|
||||
gadget_threads.add (thread);
|
||||
return true;
|
||||
}, cancellable);
|
||||
yield lldb.continue_specific_threads (gadget_threads, cancellable);
|
||||
} else {
|
||||
yield lldb.detach (cancellable);
|
||||
}
|
||||
|
||||
return result;
|
||||
return new Transaction (gadget, is_early_instrumentation, main_thread.id, lldb);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.UNSUPPORTED ("%s", e.message);
|
||||
throw new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +171,9 @@ namespace Frida.Fruity.Injector {
|
||||
dyld_base = yield lldb.read_pointer (dyld_fields.dyld_load_address, cancellable);
|
||||
} else {
|
||||
yield lldb.enumerate_modules (m => {
|
||||
if (m.pathname == "/usr/lib/dyld" || m.pathname == "/binpack/lib/dyld") {
|
||||
if (m.pathname == "/usr/lib/dyld" ||
|
||||
m.pathname == "/binpack/lib/dyld" ||
|
||||
m.pathname == "/cores/usr/lib/dyld") {
|
||||
dyld_base = m.load_address;
|
||||
return false;
|
||||
}
|
||||
@@ -185,7 +207,10 @@ namespace Frida.Fruity.Injector {
|
||||
|
||||
private async GadgetDetails inject_module (Cancellable? cancellable) throws GLib.Error {
|
||||
module_size = compute_virtual_size (module);
|
||||
module.base_address = yield lldb.allocate (module_size, "rw", cancellable);
|
||||
module.base_address = yield lldb.allocate (module_size, "rx", cancellable);
|
||||
|
||||
yield DebuggerMappings.spray_pages (lldb, module.base_address, (size_t) module.segments.index (0).vm_size,
|
||||
page_size, cancellable);
|
||||
|
||||
unowned Gum.DarwinModuleImage image = module.image;
|
||||
unowned uint8[] image_data = ((uint8[]) image.data)[0:image.size];
|
||||
@@ -221,7 +246,7 @@ namespace Frida.Fruity.Injector {
|
||||
case TEXT_ABSOLUTE32:
|
||||
break;
|
||||
default:
|
||||
pending_error = new Error.UNSUPPORTED ("Unsupported rebase type: %u", rebase.type);
|
||||
pending_error = new Error.NOT_SUPPORTED ("Unsupported rebase type: %u", rebase.type);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -250,7 +275,7 @@ namespace Frida.Fruity.Injector {
|
||||
case MAIN_EXECUTABLE:
|
||||
case FLAT_LOOKUP:
|
||||
case WEAK_LOOKUP:
|
||||
pending_error = new Error.UNSUPPORTED ("Unsupported bind ordinal: %d",
|
||||
pending_error = new Error.NOT_SUPPORTED ("Unsupported bind ordinal: %d",
|
||||
bind.library_ordinal);
|
||||
return false;
|
||||
default:
|
||||
@@ -273,7 +298,7 @@ namespace Frida.Fruity.Injector {
|
||||
threaded_items.add_region (bind.segment.vm_address + slide + bind.offset);
|
||||
break;
|
||||
default:
|
||||
pending_error = new Error.UNSUPPORTED ("Unsupported bind type: %u", bind.type);
|
||||
pending_error = new Error.NOT_SUPPORTED ("Unsupported bind type: %u", bind.type);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -308,7 +333,7 @@ namespace Frida.Fruity.Injector {
|
||||
bool is_weak = (bind.symbol_flags & Gum.DarwinBindSymbolFlags.WEAK_IMPORT) != 0;
|
||||
if (is_weak || is_dyld_stub_binder (module_name, symbol_name))
|
||||
return true;
|
||||
pending_error = new Error.UNSUPPORTED ("Unable to resolve symbol: %s", bind.symbol_name);
|
||||
pending_error = new Error.NOT_SUPPORTED ("Unable to resolve symbol: %s", bind.symbol_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -375,17 +400,19 @@ namespace Frida.Fruity.Injector {
|
||||
.append_pointer (symbols.listen)
|
||||
.append_pointer (symbols.getsockname)
|
||||
.append_pointer (symbols.accept)
|
||||
.append_pointer (symbols.close)
|
||||
.append_pointer (symbols.read)
|
||||
.append_pointer (symbols.write)
|
||||
.append_pointer (symbols.getpagesize)
|
||||
.append_pointer (symbols.mprotect)
|
||||
.append_pointer (symbols.sys_icache_invalidate)
|
||||
.append_pointer (symbols.sys_dcache_flush)
|
||||
.append_pointer (symbols._mach_task_self)
|
||||
.append_pointer (symbols.mach_vm_allocate)
|
||||
.append_pointer (symbols.mach_vm_deallocate)
|
||||
.append_pointer (symbols.vm_remap)
|
||||
.append_pointer (symbols.dlopen)
|
||||
.append_pointer (symbols.dlsym)
|
||||
.append_pointer (symbols.mprotect)
|
||||
.append_pointer (symbols.close)
|
||||
.append_pointer (symbols.get_errno_storage);
|
||||
|
||||
apple_strv_builder.build (args);
|
||||
@@ -400,12 +427,12 @@ namespace Frida.Fruity.Injector {
|
||||
upload_api
|
||||
}, null, cancellable);
|
||||
|
||||
uint8 error_code = (uint8) ((listen_result >> 56) & 0xff);
|
||||
uint32 listener_fd = (uint32) ((listen_result >> 16) & 0xffffffffU);
|
||||
uint16 listener_port = (uint16) (listen_result & 0xffff);
|
||||
uint8 error_code = (uint8) ((listen_result >> 56) & 0xff);
|
||||
uint32 listener_fd = (uint32) ((listen_result >> 16) & 0xffffffffU);
|
||||
uint16 listener_port = (uint16) (listen_result & 0xffff);
|
||||
|
||||
if (error_code != 0)
|
||||
throw new Error.UNSUPPORTED ("Unable to listen on TCP (error_code=%u)", error_code);
|
||||
throw new Error.NOT_SUPPORTED ("Unable to listen on TCP (error_code=%u)", error_code);
|
||||
|
||||
yield lldb.write_byte_array (code, new Bytes.static (UPLOAD_RECEIVER_CODE), cancellable);
|
||||
|
||||
@@ -425,7 +452,7 @@ namespace Frida.Fruity.Injector {
|
||||
upload_api
|
||||
}, null, cancellable);
|
||||
if (receive_result <= 0)
|
||||
throw new Error.UNSUPPORTED ("Unable to start gadget: %" + int64.FORMAT_MODIFIER + "d", receive_result);
|
||||
throw new Error.NOT_SUPPORTED ("Unable to start gadget: %" + int64.FORMAT_MODIFIER + "d", receive_result);
|
||||
|
||||
return (uint16) receive_result;
|
||||
}
|
||||
@@ -565,17 +592,19 @@ namespace Frida.Fruity.Injector {
|
||||
public uint64 listen;
|
||||
public uint64 getsockname;
|
||||
public uint64 accept;
|
||||
public uint64 close;
|
||||
public uint64 read;
|
||||
public uint64 write;
|
||||
public uint64 getpagesize;
|
||||
public uint64 mprotect;
|
||||
public uint64 sys_icache_invalidate;
|
||||
public uint64 sys_dcache_flush;
|
||||
public uint64 _mach_task_self;
|
||||
public uint64 mach_vm_allocate;
|
||||
public uint64 mach_vm_deallocate;
|
||||
public uint64 vm_remap;
|
||||
public uint64 dlopen;
|
||||
public uint64 dlsym;
|
||||
public uint64 mprotect;
|
||||
public uint64 close;
|
||||
public uint64 get_errno_storage;
|
||||
|
||||
private const string LIBSYSTEM = "/usr/lib/libSystem.B.dylib";
|
||||
@@ -588,17 +617,19 @@ namespace Frida.Fruity.Injector {
|
||||
.add (LIBSYSTEM, "_listen")
|
||||
.add (LIBSYSTEM, "_getsockname")
|
||||
.add (LIBSYSTEM, "_accept")
|
||||
.add (LIBSYSTEM, "_close")
|
||||
.add (LIBSYSTEM, "_read")
|
||||
.add (LIBSYSTEM, "_write")
|
||||
.add (LIBSYSTEM, "_getpagesize")
|
||||
.add (LIBSYSTEM, "_mprotect")
|
||||
.add (LIBSYSTEM, "_sys_icache_invalidate")
|
||||
.add (LIBSYSTEM, "_sys_dcache_flush")
|
||||
.add (LIBSYSTEM, "_mach_task_self")
|
||||
.add (LIBSYSTEM, "_mach_vm_allocate")
|
||||
.add (LIBSYSTEM, "_mach_vm_deallocate")
|
||||
.add (LIBSYSTEM, "_vm_remap")
|
||||
.add (LIBSYSTEM, "_dlopen")
|
||||
.add (LIBSYSTEM, "_dlsym")
|
||||
.add (LIBSYSTEM, "_mprotect")
|
||||
.add (LIBSYSTEM, "_close")
|
||||
.add (LIBSYSTEM, "___error")
|
||||
;
|
||||
}
|
||||
@@ -610,17 +641,19 @@ namespace Frida.Fruity.Injector {
|
||||
listen = symbols.get (LIBSYSTEM, "_listen");
|
||||
getsockname = symbols.get (LIBSYSTEM, "_getsockname");
|
||||
accept = symbols.get (LIBSYSTEM, "_accept");
|
||||
close = symbols.get (LIBSYSTEM, "_close");
|
||||
read = symbols.get (LIBSYSTEM, "_read");
|
||||
write = symbols.get (LIBSYSTEM, "_write");
|
||||
getpagesize = symbols.get (LIBSYSTEM, "_getpagesize");
|
||||
mprotect = symbols.get (LIBSYSTEM, "_mprotect");
|
||||
sys_icache_invalidate = symbols.get (LIBSYSTEM, "_sys_icache_invalidate");
|
||||
sys_dcache_flush = symbols.get (LIBSYSTEM, "_sys_dcache_flush");
|
||||
_mach_task_self = symbols.get (LIBSYSTEM, "_mach_task_self");
|
||||
mach_vm_allocate = symbols.get (LIBSYSTEM, "_mach_vm_allocate");
|
||||
mach_vm_deallocate = symbols.get (LIBSYSTEM, "_mach_vm_deallocate");
|
||||
vm_remap = symbols.get (LIBSYSTEM, "_vm_remap");
|
||||
dlopen = symbols.get (LIBSYSTEM, "_dlopen");
|
||||
dlsym = symbols.get (LIBSYSTEM, "_dlsym");
|
||||
mprotect = symbols.get (LIBSYSTEM, "_mprotect");
|
||||
close = symbols.get (LIBSYSTEM, "_close");
|
||||
get_errno_storage = symbols.get (LIBSYSTEM, "___error");
|
||||
}
|
||||
}
|
||||
@@ -638,9 +671,9 @@ namespace Frida.Fruity.Injector {
|
||||
0x68, 0x12, 0x40, 0xf9, 0xe1, 0x43, 0x00, 0x91, 0xe2, 0x33, 0x00, 0x91, 0xe0, 0x03, 0x14, 0xaa, 0x00, 0x01, 0x3f,
|
||||
0xd6, 0x1f, 0x04, 0x00, 0x31, 0x60, 0x02, 0x00, 0x54, 0x68, 0x0e, 0x40, 0xf9, 0xe0, 0x03, 0x14, 0xaa, 0x21, 0x00,
|
||||
0x80, 0x52, 0x00, 0x01, 0x3f, 0xd6, 0x1f, 0x04, 0x00, 0x31, 0xe0, 0x01, 0x00, 0x54, 0x88, 0x7e, 0x40, 0x93, 0xe9,
|
||||
0x27, 0x40, 0x79, 0x29, 0x09, 0xc0, 0x5a, 0x35, 0x7d, 0x10, 0x53, 0x15, 0xbd, 0x70, 0xb3, 0x0d, 0x00, 0x00, 0x14,
|
||||
0x15, 0x20, 0xe0, 0xd2, 0x0b, 0x00, 0x00, 0x14, 0x15, 0x40, 0xe0, 0xd2, 0x06, 0x00, 0x00, 0x14, 0x15, 0x60, 0xe0,
|
||||
0xd2, 0x04, 0x00, 0x00, 0x14, 0x15, 0x80, 0xe0, 0xd2, 0x02, 0x00, 0x00, 0x14, 0x15, 0xa0, 0xe0, 0xd2, 0x68, 0x42,
|
||||
0x27, 0x40, 0x79, 0x29, 0x09, 0xc0, 0x5a, 0x29, 0x7d, 0x10, 0x53, 0x35, 0x41, 0x08, 0xaa, 0x0d, 0x00, 0x00, 0x14,
|
||||
0x15, 0x40, 0xe0, 0xd2, 0x0b, 0x00, 0x00, 0x14, 0x15, 0x80, 0xe0, 0xd2, 0x06, 0x00, 0x00, 0x14, 0x15, 0xc0, 0xe0,
|
||||
0xd2, 0x04, 0x00, 0x00, 0x14, 0x15, 0x00, 0xe1, 0xd2, 0x02, 0x00, 0x00, 0x14, 0x15, 0x40, 0xe1, 0xd2, 0x68, 0x1a,
|
||||
0x40, 0xf9, 0xe0, 0x03, 0x14, 0xaa, 0x00, 0x01, 0x3f, 0xd6, 0xe0, 0x03, 0x15, 0xaa, 0xfd, 0x7b, 0x45, 0xa9, 0xf4,
|
||||
0x4f, 0x44, 0xa9, 0xf6, 0x57, 0x43, 0xa9, 0xff, 0x83, 0x01, 0x91, 0xc0, 0x03, 0x5f, 0xd6, 0x00, 0x1e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@@ -650,144 +683,153 @@ namespace Frida.Fruity.Injector {
|
||||
/* Compiled from helpers/upload-receiver.c */
|
||||
private const uint8[] UPLOAD_RECEIVER_CODE = {
|
||||
0xfc, 0x6f, 0xba, 0xa9, 0xfa, 0x67, 0x01, 0xa9, 0xf8, 0x5f, 0x02, 0xa9, 0xf6, 0x57, 0x03, 0xa9, 0xf4, 0x4f, 0x04,
|
||||
0xa9, 0xfd, 0x7b, 0x05, 0xa9, 0xfd, 0x43, 0x01, 0x91, 0xff, 0x03, 0x03, 0xd1, 0xfa, 0x03, 0x04, 0xaa, 0xfb, 0x03,
|
||||
0x03, 0xaa, 0xf7, 0x03, 0x02, 0xaa, 0xf8, 0x03, 0x01, 0xaa, 0xf9, 0x03, 0x00, 0xaa, 0xbf, 0xc3, 0x19, 0xb8, 0x88,
|
||||
0x95, 0x98, 0x52, 0x48, 0x89, 0xb5, 0x72, 0xa8, 0x03, 0x18, 0xb8, 0x13, 0x02, 0x80, 0x52, 0xb3, 0x43, 0x18, 0xb8,
|
||||
0x48, 0x17, 0x40, 0xf9, 0xa1, 0xe3, 0x01, 0xd1, 0xa2, 0xf3, 0x01, 0xd1, 0xe0, 0x03, 0x19, 0xaa, 0x00, 0x01, 0x3f,
|
||||
0xd6, 0x1f, 0x04, 0x00, 0x31, 0xe1, 0x00, 0x00, 0x54, 0x48, 0x47, 0x40, 0xf9, 0x00, 0x01, 0x3f, 0xd6, 0x08, 0x00,
|
||||
0x40, 0xb9, 0x1f, 0x11, 0x00, 0x71, 0xa0, 0xfe, 0xff, 0x54, 0xd7, 0x01, 0x00, 0x14, 0xf6, 0x03, 0x00, 0xaa, 0xa1,
|
||||
0x43, 0x02, 0xd1, 0x02, 0x02, 0x80, 0x52, 0x53, 0x02, 0x00, 0x94, 0xa8, 0x27, 0x77, 0xa9, 0x1f, 0x00, 0x00, 0x71,
|
||||
0x00, 0x11, 0x58, 0xfa, 0x20, 0x01, 0x57, 0xfa, 0x60, 0x00, 0x00, 0x54, 0x65, 0x02, 0x00, 0x94, 0xe8, 0xff, 0xff,
|
||||
0x17, 0x58, 0x02, 0x00, 0x94, 0x20, 0x39, 0x00, 0x34, 0xa8, 0x23, 0x00, 0xd1, 0x1a, 0x01, 0x10, 0xf8, 0xa8, 0x33,
|
||||
0x00, 0xd1, 0x19, 0x01, 0x10, 0xb8, 0xbb, 0x83, 0x11, 0xf8, 0xa1, 0x47, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x22,
|
||||
0x00, 0x80, 0x52, 0x41, 0x02, 0x00, 0x94, 0xe0, 0x37, 0x00, 0x34, 0xa8, 0xf3, 0x56, 0x38, 0x10, 0x05, 0x00, 0x51,
|
||||
0x1f, 0x1a, 0x00, 0x71, 0x68, 0x37, 0x00, 0x54, 0x1f, 0x1a, 0x00, 0xf1, 0x10, 0x92, 0x9f, 0x9a, 0xb1, 0x38, 0x00,
|
||||
0x10, 0x1f, 0x20, 0x03, 0xd5, 0x30, 0x7a, 0xb0, 0xb8, 0x11, 0x00, 0x00, 0x10, 0x30, 0x02, 0x10, 0x8b, 0x00, 0x02,
|
||||
0x1f, 0xd6, 0xa1, 0x83, 0x01, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x02, 0x01, 0x80, 0x52, 0x30, 0x02, 0x00, 0x94, 0xc0,
|
||||
0x35, 0x00, 0x34, 0xa1, 0xa3, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x82, 0x00, 0x80, 0x52, 0x2b, 0x02, 0x00, 0x94,
|
||||
0x20, 0x35, 0x00, 0x36, 0xa1, 0x03, 0x5a, 0xf8, 0xa2, 0x83, 0x55, 0xb8, 0xa3, 0x83, 0x02, 0xd1, 0xe0, 0x03, 0x16,
|
||||
0xaa, 0xe4, 0x03, 0x1a, 0xaa, 0xbb, 0x01, 0x00, 0x94, 0xf7, 0x03, 0x00, 0xaa, 0x48, 0x23, 0x40, 0xf9, 0x36, 0x02,
|
||||
0x00, 0x94, 0x48, 0x27, 0x40, 0xf9, 0x34, 0x02, 0x00, 0x94, 0x57, 0xfb, 0x07, 0x37, 0x9c, 0x01, 0x00, 0x14, 0xa1,
|
||||
0x83, 0x01, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x02, 0x01, 0x80, 0x52, 0x19, 0x02, 0x00, 0x94, 0xe0, 0x32, 0x00, 0x34,
|
||||
0xa1, 0x83, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x02, 0x01, 0x80, 0x52, 0x14, 0x02, 0x00, 0x94, 0x40, 0x32, 0x00,
|
||||
0x34, 0xa1, 0xa3, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x42, 0x00, 0x80, 0x52, 0x0f, 0x02, 0x00, 0x94, 0xa0, 0x31,
|
||||
0x00, 0x34, 0xf5, 0x03, 0x00, 0x91, 0xa8, 0x83, 0x55, 0x78, 0x08, 0x71, 0x1d, 0x53, 0x08, 0x3d, 0x00, 0x11, 0x08,
|
||||
0x3d, 0x7c, 0x92, 0xe9, 0x03, 0x00, 0x91, 0x37, 0x01, 0x08, 0xcb, 0xff, 0x02, 0x00, 0x91, 0xa8, 0x83, 0x55, 0x78,
|
||||
0x02, 0xf1, 0x7d, 0xd3, 0xe0, 0x03, 0x16, 0xaa, 0xe1, 0x03, 0x17, 0xaa, 0x01, 0x02, 0x00, 0x94, 0xc0, 0x2f, 0x00,
|
||||
0x34, 0xa1, 0xc3, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x42, 0x00, 0x80, 0x52, 0xfc, 0x01, 0x00, 0x94, 0x20, 0x2f,
|
||||
0x00, 0x34, 0xa8, 0x03, 0x55, 0x78, 0x09, 0x71, 0x1d, 0x53, 0x29, 0x3d, 0x00, 0x11, 0x29, 0x3d, 0x7c, 0x92, 0xea,
|
||||
0x03, 0x00, 0x91, 0x58, 0x01, 0x09, 0xcb, 0x1f, 0x03, 0x00, 0x91, 0x02, 0xf1, 0x7d, 0xd3, 0xe0, 0x03, 0x16, 0xaa,
|
||||
0xe1, 0x03, 0x18, 0xaa, 0xf0, 0x01, 0x00, 0x94, 0xa0, 0x2d, 0x00, 0x34, 0x14, 0x00, 0x80, 0xd2, 0xba, 0x03, 0x5a,
|
||||
0xf8, 0xbb, 0x03, 0x56, 0xf8, 0xbc, 0x03, 0x55, 0x78, 0x9f, 0x02, 0x1c, 0xeb, 0x40, 0x27, 0x00, 0x54, 0x19, 0x7b,
|
||||
0x74, 0xf8, 0x33, 0x03, 0x40, 0xf9, 0xf3, 0x01, 0xf0, 0xb7, 0x68, 0xfe, 0x6b, 0xd3, 0x69, 0xaa, 0x40, 0x92, 0x6a,
|
||||
0xaa, 0x6a, 0x93, 0x4a, 0x31, 0x55, 0x92, 0x09, 0x1d, 0x48, 0xb3, 0x28, 0x01, 0x0a, 0xaa, 0x69, 0x7e, 0x40, 0x92,
|
||||
0x7f, 0x02, 0x41, 0xf2, 0xea, 0x03, 0x9a, 0x9a, 0x08, 0x01, 0x89, 0x9a, 0x49, 0x01, 0x1b, 0x8b, 0x20, 0x01, 0x08,
|
||||
0x8b, 0x53, 0x01, 0xf8, 0xb6, 0x04, 0x00, 0x00, 0x14, 0x68, 0x3e, 0x40, 0x92, 0xe0, 0x7a, 0x68, 0xf8, 0xd3, 0x00,
|
||||
0xf8, 0xb6, 0x61, 0xca, 0x71, 0xd3, 0x63, 0xc2, 0x70, 0xd3, 0x62, 0xbe, 0x60, 0xd3, 0xe4, 0x03, 0x19, 0xaa, 0xb6,
|
||||
0x01, 0x00, 0x94, 0x68, 0xf6, 0x73, 0xd3, 0x20, 0x03, 0x00, 0xf9, 0x39, 0x4f, 0x28, 0x8b, 0xa8, 0xfc, 0xff, 0x35,
|
||||
0x94, 0x06, 0x00, 0x91, 0xe0, 0xff, 0xff, 0x17, 0xa1, 0x83, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x02, 0x01, 0x80,
|
||||
0x52, 0xc6, 0x01, 0x00, 0x94, 0x80, 0x28, 0x00, 0x34, 0xa1, 0xa3, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x02, 0x01,
|
||||
0x80, 0x52, 0xc1, 0x01, 0x00, 0x94, 0xe0, 0x27, 0x00, 0x34, 0xa1, 0xc3, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x02,
|
||||
0x01, 0x80, 0x52, 0xbc, 0x01, 0x00, 0x94, 0x40, 0x27, 0x00, 0x34, 0xb9, 0xf3, 0x75, 0xa9, 0xa8, 0x03, 0x55, 0xf8,
|
||||
0xa8, 0x83, 0x10, 0xf8, 0x48, 0x2b, 0x40, 0xf9, 0x00, 0x01, 0x3f, 0xd6, 0xbf, 0x03, 0x1a, 0xf8, 0x48, 0x2f, 0x40,
|
||||
0xf9, 0xa1, 0x83, 0x01, 0xd1, 0xa9, 0x43, 0x00, 0xd1, 0x20, 0x01, 0x10, 0xb8, 0x22, 0x00, 0xa0, 0x52, 0x23, 0x00,
|
||||
0x80, 0x52, 0x00, 0x01, 0x3f, 0xd6, 0x14, 0x00, 0x80, 0x52, 0x13, 0x00, 0x80, 0xd2, 0xb8, 0x03, 0x5a, 0xf8, 0x35,
|
||||
0x83, 0x00, 0x91, 0x37, 0x00, 0x80, 0x52, 0x28, 0x13, 0x40, 0xb9, 0x9f, 0x02, 0x08, 0x6b, 0x60, 0x0c, 0x00, 0x54,
|
||||
0xa8, 0x02, 0x40, 0xb9, 0x09, 0xfd, 0x9f, 0x52, 0xe9, 0xff, 0xaf, 0x72, 0x09, 0x01, 0x09, 0x0b, 0x3f, 0x2d, 0x00,
|
||||
0x71, 0xe9, 0x22, 0xc9, 0x1a, 0x2a, 0x10, 0x81, 0x52, 0x29, 0x01, 0x0a, 0x0a, 0x24, 0x99, 0x40, 0x7a, 0x04, 0x09,
|
||||
0x4c, 0x7a, 0x01, 0x01, 0x00, 0x54, 0xa8, 0x0a, 0x40, 0xb9, 0xa0, 0x02, 0x08, 0x8b, 0x48, 0x37, 0x40, 0xf9, 0x21,
|
||||
0x01, 0x80, 0x52, 0x00, 0x01, 0x3f, 0xd6, 0x00, 0x7b, 0x33, 0xf8, 0x73, 0x06, 0x00, 0x91, 0xa8, 0x06, 0x40, 0xb9,
|
||||
0xb5, 0x02, 0x08, 0x8b, 0x94, 0x06, 0x00, 0x11, 0xe8, 0xff, 0xff, 0x17, 0xa1, 0x83, 0x01, 0xd1, 0xe0, 0x03, 0x16,
|
||||
0xaa, 0x02, 0x01, 0x80, 0x52, 0x8c, 0x01, 0x00, 0x94, 0x40, 0x21, 0x00, 0x34, 0xa1, 0x83, 0x02, 0xd1, 0xe0, 0x03,
|
||||
0x16, 0xaa, 0x82, 0x00, 0x80, 0x52, 0x87, 0x01, 0x00, 0x94, 0xa0, 0x20, 0x00, 0x34, 0xa1, 0xa3, 0x02, 0xd1, 0xe0,
|
||||
0x03, 0x16, 0xaa, 0x82, 0x00, 0x80, 0x52, 0x82, 0x01, 0x00, 0x94, 0x00, 0x20, 0x00, 0x36, 0x48, 0x3f, 0x40, 0xf9,
|
||||
0xa0, 0x03, 0x5a, 0xf8, 0xa1, 0x03, 0x56, 0xb8, 0xa2, 0x83, 0x55, 0xb8, 0x00, 0x01, 0x3f, 0xd6, 0xe0, 0xe6, 0xff,
|
||||
0x34, 0xf9, 0x00, 0x00, 0x14, 0xa1, 0x83, 0x01, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x02, 0x01, 0x80, 0x52, 0x76, 0x01,
|
||||
0x00, 0x94, 0x80, 0x1e, 0x00, 0x34, 0xa1, 0xc3, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x82, 0x00, 0x80, 0x52, 0x71,
|
||||
0x01, 0x00, 0x94, 0xe0, 0x1d, 0x00, 0x34, 0x13, 0x00, 0x80, 0x52, 0xb4, 0x03, 0x5a, 0xf8, 0xa8, 0x03, 0x55, 0xb8,
|
||||
0x7f, 0x02, 0x08, 0x6b, 0xe0, 0xe4, 0xff, 0x54, 0xbf, 0xff, 0x35, 0xa9, 0x88, 0x5a, 0x73, 0xf8, 0xa1, 0x83, 0x02,
|
||||
0xd1, 0xa2, 0xa3, 0x02, 0xd1, 0x77, 0x01, 0x00, 0x94, 0x73, 0x06, 0x00, 0x11, 0xf7, 0xff, 0xff, 0x17, 0xa1, 0x83,
|
||||
0x01, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x02, 0x01, 0x80, 0x52, 0x60, 0x01, 0x00, 0x94, 0xc0, 0x1b, 0x00, 0x34, 0xa1,
|
||||
0xd3, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x82, 0x00, 0x80, 0x52, 0x5b, 0x01, 0x00, 0x94, 0x20, 0x1b, 0x00, 0x34,
|
||||
0xa1, 0x83, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0x02, 0x01, 0x80, 0x52, 0x56, 0x01, 0x00, 0x94, 0x80, 0x1a, 0x00,
|
||||
0x34, 0x13, 0x00, 0x80, 0x52, 0xb4, 0x03, 0x5a, 0xf8, 0xa8, 0xc3, 0x54, 0xb8, 0x7f, 0x02, 0x08, 0x6b, 0x80, 0xe1,
|
||||
0xff, 0x54, 0xbf, 0x7f, 0x35, 0xa9, 0xa8, 0x03, 0x56, 0xf8, 0x89, 0x5a, 0x73, 0xb8, 0x08, 0x01, 0x09, 0x8b, 0xa1,
|
||||
0xa3, 0x02, 0xd1, 0xa2, 0xc3, 0x02, 0xd1, 0x5a, 0x01, 0x00, 0x94, 0x73, 0x06, 0x00, 0x11, 0xf5, 0xff, 0xff, 0x17,
|
||||
0x53, 0x01, 0x00, 0x94, 0x20, 0xe0, 0x07, 0x37, 0xc3, 0x00, 0x00, 0x14, 0x1a, 0x0f, 0x13, 0x8b, 0x88, 0xdf, 0x41,
|
||||
0x29, 0x95, 0x03, 0x08, 0x8b, 0x88, 0x17, 0x40, 0xb9, 0x1f, 0x0d, 0x00, 0x71, 0xc0, 0x12, 0x00, 0x54, 0x1f, 0x09,
|
||||
0x00, 0x71, 0xe0, 0x14, 0x00, 0x54, 0x1f, 0x05, 0x00, 0x71, 0x21, 0x02, 0x00, 0x54, 0x88, 0x0b, 0x40, 0xb9, 0x93,
|
||||
0x03, 0x08, 0x8b, 0xf4, 0x03, 0x1a, 0xaa, 0xb7, 0x01, 0x00, 0xb4, 0x69, 0x02, 0x40, 0xb9, 0x28, 0x1d, 0x00, 0x72,
|
||||
0xa0, 0x00, 0x00, 0x54, 0xa9, 0x26, 0x49, 0x8b, 0x34, 0x01, 0x00, 0x94, 0xe0, 0x43, 0xc1, 0xda, 0x02, 0x00, 0x00,
|
||||
0x14, 0x00, 0x00, 0x80, 0xd2, 0x80, 0x86, 0x00, 0xf8, 0x73, 0x12, 0x00, 0x91, 0xf7, 0x06, 0x00, 0xd1, 0xb7, 0xfe,
|
||||
0xff, 0xb5, 0x09, 0x00, 0x80, 0xd2, 0x88, 0x07, 0x40, 0xb9, 0x88, 0x03, 0x08, 0x8b, 0xa8, 0x03, 0x10, 0xf8, 0x0a,
|
||||
0x45, 0x40, 0xb8, 0xaa, 0x03, 0x12, 0xf8, 0xa8, 0x03, 0x11, 0xf8, 0xa8, 0x03, 0x52, 0xf8, 0x3f, 0x01, 0x08, 0xeb,
|
||||
0xc0, 0x0c, 0x00, 0x54, 0xa9, 0x83, 0x12, 0xf8, 0xa8, 0x03, 0x51, 0xf8, 0x08, 0x79, 0x69, 0xb8, 0xc8, 0x0b, 0x00,
|
||||
0x34, 0x15, 0x00, 0x80, 0xd2, 0xa9, 0x03, 0x50, 0xf8, 0x3b, 0x01, 0x08, 0x8b, 0x68, 0x0f, 0x40, 0x79, 0x6a, 0x2b,
|
||||
0x40, 0x79, 0x69, 0x5b, 0x00, 0x91, 0xa9, 0xab, 0x33, 0xa9, 0x09, 0x79, 0x1d, 0x12, 0xa9, 0x43, 0x13, 0xb8, 0x1f,
|
||||
0x31, 0x00, 0x71, 0xe9, 0xff, 0x9f, 0x52, 0x0a, 0xe0, 0xbf, 0x12, 0x54, 0x01, 0x89, 0x9a, 0x1f, 0x05, 0x00, 0x71,
|
||||
0xaa, 0x83, 0x50, 0xf8, 0x49, 0x01, 0x9f, 0x9a, 0x3c, 0x03, 0x09, 0xcb, 0x1f, 0x19, 0x00, 0x71, 0xe8, 0x03, 0x8a,
|
||||
0x9a, 0x37, 0x03, 0x08, 0xcb, 0xa8, 0x03, 0x54, 0xf8, 0xbf, 0x02, 0x08, 0xeb, 0xe0, 0x08, 0x00, 0x54, 0xa8, 0x83,
|
||||
0x53, 0xf8, 0x08, 0x79, 0x75, 0x78, 0xe9, 0xff, 0x9f, 0x52, 0x1f, 0x01, 0x09, 0xeb, 0x00, 0x08, 0x00, 0x54, 0x69,
|
||||
0x07, 0x40, 0xf9, 0x29, 0x03, 0x09, 0x8b, 0x6a, 0x0b, 0x40, 0x79, 0xa9, 0x26, 0x0a, 0x9b, 0x38, 0x01, 0x08, 0x8b,
|
||||
0xa8, 0x43, 0x53, 0xb8, 0x1f, 0x09, 0x00, 0x71, 0x41, 0x02, 0x00, 0x54, 0x08, 0x03, 0x40, 0xf9, 0xe8, 0x00, 0xf8,
|
||||
0xb7, 0x09, 0xad, 0x6c, 0xd3, 0x29, 0x1d, 0x48, 0x92, 0x0a, 0x8d, 0x40, 0x92, 0xea, 0x02, 0x0a, 0x8b, 0x49, 0x01,
|
||||
0x09, 0x8b, 0x05, 0x00, 0x00, 0x14, 0x09, 0x5d, 0x40, 0x92, 0x49, 0x7b, 0x69, 0xf8, 0x0a, 0xfd, 0x58, 0xd3, 0x29,
|
||||
0x01, 0x2a, 0x8b, 0x09, 0x03, 0x00, 0xf9, 0x08, 0xf9, 0x73, 0xd3, 0x18, 0x0b, 0x08, 0x8b, 0x28, 0xfe, 0xff, 0xb5,
|
||||
0x27, 0x00, 0x00, 0x14, 0x13, 0x03, 0x40, 0xf9, 0x70, 0xfe, 0x7e, 0xd3, 0x62, 0xbe, 0x60, 0xd3, 0x63, 0xc2, 0x70,
|
||||
0xd3, 0x61, 0xca, 0x71, 0xd3, 0x1f, 0x0e, 0x00, 0xf1, 0x10, 0x92, 0x9f, 0x9a, 0x51, 0x0e, 0x00, 0x10, 0x1f, 0x20,
|
||||
0x03, 0xd5, 0x30, 0x7a, 0xb0, 0xb8, 0x11, 0x00, 0x00, 0x10, 0x30, 0x02, 0x10, 0x8b, 0x00, 0x02, 0x1f, 0xd6, 0x68,
|
||||
0xca, 0x73, 0xd3, 0x08, 0x1d, 0x48, 0x92, 0x69, 0xaa, 0x40, 0x92, 0x89, 0x03, 0x09, 0x8b, 0x20, 0x01, 0x08, 0x8b,
|
||||
0x10, 0x00, 0x00, 0x14, 0x68, 0x02, 0x14, 0x8a, 0x48, 0x7b, 0x68, 0xf8, 0x69, 0xca, 0x60, 0xd3, 0x3f, 0x01, 0x41,
|
||||
0xf1, 0xe9, 0xb3, 0x6d, 0xb2, 0xe9, 0x33, 0x89, 0x9a, 0x69, 0xca, 0x60, 0xb3, 0x00, 0x01, 0x09, 0x8b, 0x07, 0x00,
|
||||
0x00, 0x14, 0x20, 0x43, 0x33, 0x8b, 0x03, 0x00, 0x00, 0x14, 0x68, 0x02, 0x14, 0x8a, 0x40, 0x7b, 0x68, 0xf8, 0xe4,
|
||||
0x03, 0x18, 0xaa, 0xab, 0x00, 0x00, 0x94, 0x00, 0x03, 0x00, 0xf9, 0x68, 0xf6, 0x73, 0xd3, 0x18, 0x0f, 0x08, 0x8b,
|
||||
0x68, 0xfb, 0xff, 0xb5, 0xb5, 0x06, 0x00, 0x91, 0xb8, 0xff, 0xff, 0x17, 0xa9, 0x83, 0x52, 0xf8, 0x29, 0x05, 0x00,
|
||||
0x91, 0xbb, 0x83, 0x51, 0xf8, 0x99, 0xff, 0xff, 0x17, 0xa8, 0x23, 0x00, 0xd1, 0x1a, 0x01, 0x50, 0xf8, 0x48, 0x33,
|
||||
0x40, 0xf9, 0xa1, 0x03, 0x5a, 0xf8, 0xa9, 0x43, 0x00, 0xd1, 0x20, 0x01, 0x50, 0xb8, 0x22, 0x00, 0xa0, 0x52, 0x00,
|
||||
0x01, 0x3f, 0xd6, 0xa8, 0x33, 0x00, 0xd1, 0x19, 0x01, 0x50, 0xb8, 0x6c, 0xfe, 0xff, 0x17, 0xbf, 0x02, 0x00, 0x91,
|
||||
0xa8, 0x23, 0x00, 0xd1, 0x1a, 0x01, 0x50, 0xf8, 0xa8, 0x33, 0x00, 0xd1, 0x19, 0x01, 0x50, 0xb8, 0xbb, 0x83, 0x51,
|
||||
0xf8, 0x65, 0xfe, 0xff, 0x17, 0xe8, 0x03, 0x1c, 0xaa, 0x09, 0x8d, 0x40, 0xb8, 0x13, 0x01, 0x09, 0x8b, 0xf4, 0x03,
|
||||
0x1a, 0xaa, 0x77, 0xef, 0xff, 0xb4, 0x69, 0x82, 0x5f, 0xf8, 0x28, 0x3d, 0x00, 0x72, 0xa0, 0x00, 0x00, 0x54, 0xa9,
|
||||
0x82, 0x49, 0x8b, 0xa2, 0x00, 0x00, 0x94, 0xe0, 0x43, 0xc1, 0xda, 0x02, 0x00, 0x00, 0x14, 0x00, 0x00, 0x80, 0xd2,
|
||||
0x68, 0x06, 0x41, 0xf8, 0x08, 0x00, 0x08, 0x8b, 0x88, 0x86, 0x00, 0xf8, 0xf7, 0x06, 0x00, 0xd1, 0x97, 0xfe, 0xff,
|
||||
0xb5, 0x6d, 0xff, 0xff, 0x17, 0x88, 0x0b, 0x40, 0xb9, 0x88, 0x03, 0x08, 0x8b, 0x13, 0x11, 0x00, 0x91, 0xf4, 0x03,
|
||||
0x1a, 0xaa, 0x17, 0xed, 0xff, 0xb4, 0x69, 0xc2, 0x5f, 0xb8, 0x28, 0x1d, 0x00, 0x72, 0xa0, 0x00, 0x00, 0x54, 0xa9,
|
||||
0x26, 0x49, 0x8b, 0x8f, 0x00, 0x00, 0x94, 0xe0, 0x43, 0xc1, 0xda, 0x02, 0x00, 0x00, 0x14, 0x00, 0x00, 0x80, 0xd2,
|
||||
0x68, 0x86, 0x80, 0xb8, 0x08, 0x00, 0x08, 0x8b, 0x88, 0x86, 0x00, 0xf8, 0xf7, 0x06, 0x00, 0xd1, 0x97, 0xfe, 0xff,
|
||||
0xb5, 0x5a, 0xff, 0xff, 0x17, 0xbf, 0x02, 0x00, 0x91, 0x99, 0x00, 0x00, 0x94, 0x48, 0x43, 0x40, 0xf9, 0xe0, 0x03,
|
||||
0x19, 0xaa, 0x00, 0x01, 0x3f, 0xd6, 0xa0, 0xc3, 0x99, 0xb8, 0xbf, 0x43, 0x01, 0xd1, 0xfd, 0x7b, 0x45, 0xa9, 0xf4,
|
||||
0x4f, 0x44, 0xa9, 0xf6, 0x57, 0x43, 0xa9, 0xf8, 0x5f, 0x42, 0xa9, 0xfa, 0x67, 0x41, 0xa9, 0xfc, 0x6f, 0xc6, 0xa8,
|
||||
0xc0, 0x03, 0x5f, 0xd6, 0x0c, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00, 0x9c, 0x02, 0x00,
|
||||
0x00, 0xf4, 0x02, 0x00, 0x00, 0x4c, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x24, 0x00,
|
||||
0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xf8, 0x5f, 0xbc, 0xa9, 0xf6, 0x57, 0x01, 0xa9, 0xf4,
|
||||
0x4f, 0x02, 0xa9, 0xfd, 0x7b, 0x03, 0xa9, 0xfd, 0xc3, 0x00, 0x91, 0xf3, 0x03, 0x04, 0xaa, 0xf4, 0x03, 0x03, 0xaa,
|
||||
0xf5, 0x03, 0x02, 0xaa, 0xf6, 0x03, 0x01, 0xaa, 0xf7, 0x03, 0x00, 0xaa, 0x43, 0x00, 0x00, 0xb4, 0x9f, 0x02, 0x00,
|
||||
0xf9, 0xbf, 0x02, 0x00, 0xf1, 0xf8, 0x17, 0x9f, 0x1a, 0xd5, 0x03, 0x00, 0xb4, 0x68, 0x1a, 0x40, 0xf9, 0xe0, 0x03,
|
||||
0x17, 0xaa, 0xe1, 0x03, 0x16, 0xaa, 0xe2, 0x03, 0x15, 0xaa, 0x00, 0x01, 0x3f, 0xd6, 0x1f, 0x04, 0x00, 0xb1, 0xe1,
|
||||
0x00, 0x00, 0x54, 0x68, 0x46, 0x40, 0xf9, 0x00, 0x01, 0x3f, 0xd6, 0x08, 0x00, 0x40, 0xb9, 0x1f, 0x11, 0x00, 0x71,
|
||||
0xa0, 0xfe, 0xff, 0x54, 0x0a, 0x00, 0x00, 0x14, 0x1f, 0x04, 0x00, 0xf1, 0x2b, 0x01, 0x00, 0x54, 0x94, 0x00, 0x00,
|
||||
0xb4, 0x88, 0x02, 0x40, 0xf9, 0x08, 0x01, 0x00, 0x8b, 0x88, 0x02, 0x00, 0xf9, 0xd6, 0x02, 0x00, 0x8b, 0xb5, 0x02,
|
||||
0x00, 0xcb, 0xe8, 0xff, 0xff, 0x17, 0x18, 0x00, 0x80, 0x52, 0xe0, 0x03, 0x18, 0xaa, 0xfd, 0x7b, 0x43, 0xa9, 0xf4,
|
||||
0x4f, 0x42, 0xa9, 0xf6, 0x57, 0x41, 0xa9, 0xf8, 0x5f, 0xc4, 0xa8, 0xc0, 0x03, 0x5f, 0xd6, 0x38, 0x00, 0x80, 0x52,
|
||||
0xf9, 0xff, 0xff, 0x17, 0xf6, 0x57, 0xbd, 0xa9, 0xf4, 0x4f, 0x01, 0xa9, 0xfd, 0x7b, 0x02, 0xa9, 0xfd, 0x83, 0x00,
|
||||
0x91, 0xf3, 0x03, 0x02, 0xaa, 0xf4, 0x03, 0x01, 0xaa, 0xf5, 0x03, 0x00, 0xaa, 0x88, 0x00, 0x80, 0x52, 0xf6, 0x03,
|
||||
0x08, 0xaa, 0x48, 0x02, 0x00, 0xb4, 0x68, 0x1e, 0x40, 0xf9, 0xe0, 0x03, 0x15, 0xaa, 0xe1, 0x03, 0x14, 0xaa, 0xe2,
|
||||
0x03, 0x16, 0xaa, 0x00, 0x01, 0x3f, 0xd6, 0x1f, 0x04, 0x00, 0xb1, 0xe1, 0x00, 0x00, 0x54, 0x68, 0x46, 0x40, 0xf9,
|
||||
0x00, 0x01, 0x3f, 0xd6, 0x08, 0x00, 0x40, 0xb9, 0x1f, 0x11, 0x00, 0x71, 0xa0, 0xfe, 0xff, 0x54, 0x05, 0x00, 0x00,
|
||||
0x14, 0x94, 0x02, 0x00, 0x8b, 0xc8, 0x02, 0x00, 0xcb, 0x1f, 0x00, 0x00, 0xf1, 0xcc, 0xfd, 0xff, 0x54, 0xdf, 0x02,
|
||||
0x00, 0xf1, 0xe0, 0x17, 0x9f, 0x1a, 0xfd, 0x7b, 0x42, 0xa9, 0xf4, 0x4f, 0x41, 0xa9, 0xf6, 0x57, 0xc3, 0xa8, 0xc0,
|
||||
0x03, 0x5f, 0xd6, 0x44, 0x3c, 0x50, 0xb3, 0x7f, 0x00, 0x00, 0x71, 0x48, 0x00, 0x84, 0x9a, 0x3f, 0x0c, 0x00, 0x71,
|
||||
0x28, 0x02, 0x00, 0x54, 0xf0, 0x03, 0x01, 0x2a, 0x1f, 0x0e, 0x00, 0xf1, 0x10, 0x92, 0x9f, 0x9a, 0xd1, 0x01, 0x00,
|
||||
0x10, 0x1f, 0x20, 0x03, 0xd5, 0x30, 0x7a, 0xb0, 0xb8, 0x11, 0x00, 0x00, 0x10, 0x30, 0x02, 0x10, 0x8b, 0x00, 0x02,
|
||||
0x1f, 0xd6, 0x00, 0x01, 0xc1, 0xda, 0xc0, 0x03, 0x5f, 0xd6, 0x00, 0x05, 0xc1, 0xda, 0xc0, 0x03, 0x5f, 0xd6, 0x00,
|
||||
0x09, 0xc1, 0xda, 0xc0, 0x03, 0x5f, 0xd6, 0x00, 0x0d, 0xc1, 0xda, 0xc0, 0x03, 0x5f, 0xd6, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x03, 0x00, 0x80, 0xd2, 0xe4, 0x03, 0x1a,
|
||||
0xaa, 0x95, 0xff, 0xff, 0x17, 0xea, 0x03, 0x09, 0xaa, 0x4b, 0x15, 0x40, 0x38, 0x7f, 0x7d, 0x01, 0x71, 0x21, 0x11,
|
||||
0x8a, 0x9a, 0xa9, 0x23, 0x00, 0xd1, 0x29, 0x01, 0x50, 0xf8, 0x29, 0x39, 0x40, 0xf9, 0x08, 0x05, 0x00, 0x51, 0x00,
|
||||
0x5b, 0x68, 0xf8, 0x20, 0x01, 0x1f, 0xd6, 0xa1, 0x03, 0x02, 0xd1, 0xe0, 0x03, 0x16, 0xaa, 0xe2, 0x03, 0x1a, 0xaa,
|
||||
0xb5, 0xff, 0xff, 0x17, 0xa4, 0x93, 0x01, 0xd1, 0x00, 0x00, 0x80, 0x52, 0xe3, 0x03, 0x1b, 0xaa, 0x00, 0x01, 0x1f,
|
||||
0xd6, 0xa0, 0x03, 0x5a, 0xf8, 0xa1, 0x03, 0x56, 0xf8, 0x00, 0x01, 0x1f, 0xd6, 0x48, 0x43, 0x40, 0xf9, 0xe0, 0x03,
|
||||
0x16, 0xaa, 0x00, 0x01, 0x1f, 0xd6
|
||||
0xa9, 0xfd, 0x7b, 0x05, 0xa9, 0xfd, 0x43, 0x01, 0x91, 0xff, 0x43, 0x03, 0xd1, 0xfb, 0x03, 0x04, 0xaa, 0xf6, 0x03,
|
||||
0x03, 0xaa, 0xf8, 0x03, 0x02, 0xaa, 0xf9, 0x03, 0x01, 0xaa, 0xf5, 0x03, 0x00, 0xaa, 0xbf, 0xc3, 0x19, 0xb8, 0x88,
|
||||
0x95, 0x98, 0x52, 0x48, 0x89, 0xb5, 0x72, 0xa8, 0x43, 0x18, 0xb8, 0x88, 0x34, 0x40, 0xf9, 0x00, 0x01, 0x3f, 0xd6,
|
||||
0xfa, 0x03, 0x00, 0xaa, 0x13, 0x02, 0x80, 0x52, 0xb3, 0x83, 0x18, 0xb8, 0x68, 0x17, 0x40, 0xf9, 0xa1, 0xd3, 0x01,
|
||||
0xd1, 0xa2, 0xe3, 0x01, 0xd1, 0xe0, 0x03, 0x15, 0xaa, 0x00, 0x01, 0x3f, 0xd6, 0x1f, 0x04, 0x00, 0x31, 0xe1, 0x00,
|
||||
0x00, 0x54, 0x68, 0x4f, 0x40, 0xf9, 0x00, 0x01, 0x3f, 0xd6, 0x08, 0x00, 0x40, 0xb9, 0x1f, 0x11, 0x00, 0x71, 0xa0,
|
||||
0xfe, 0xff, 0x54, 0xf1, 0x01, 0x00, 0x14, 0xf7, 0x03, 0x00, 0xaa, 0xa1, 0x43, 0x02, 0xd1, 0x02, 0x02, 0x80, 0x52,
|
||||
0x7f, 0x02, 0x00, 0x94, 0xa8, 0x27, 0x77, 0xa9, 0x1f, 0x00, 0x00, 0x71, 0x00, 0x11, 0x59, 0xfa, 0x20, 0x01, 0x58,
|
||||
0xfa, 0x60, 0x00, 0x00, 0x54, 0x8a, 0x02, 0x00, 0x94, 0xe8, 0xff, 0xff, 0x17, 0x80, 0x02, 0x00, 0x94, 0x60, 0x3c,
|
||||
0x00, 0x34, 0x38, 0x00, 0x80, 0x52, 0xbb, 0x83, 0x11, 0xf8, 0xa8, 0x13, 0x00, 0xd1, 0x15, 0x01, 0x10, 0xb8, 0xa8,
|
||||
0x43, 0x00, 0xd1, 0x16, 0x01, 0x10, 0xf8, 0xa8, 0x53, 0x00, 0xd1, 0x1a, 0x01, 0x10, 0xb8, 0xa1, 0x47, 0x02, 0xd1,
|
||||
0xe0, 0x03, 0x17, 0xaa, 0x22, 0x00, 0x80, 0x52, 0x6a, 0x02, 0x00, 0x94, 0xc0, 0x3a, 0x00, 0x34, 0xa8, 0xf3, 0x56,
|
||||
0x38, 0x10, 0x05, 0x00, 0x51, 0x1f, 0x1a, 0x00, 0x71, 0x48, 0x3a, 0x00, 0x54, 0x1f, 0x1a, 0x00, 0xf1, 0x10, 0x92,
|
||||
0x9f, 0x9a, 0x11, 0x00, 0x00, 0x90, 0x31, 0x52, 0x22, 0x91, 0x30, 0x7a, 0xb0, 0xb8, 0x11, 0x00, 0x00, 0x10, 0x30,
|
||||
0x02, 0x10, 0x8b, 0x00, 0x02, 0x1f, 0xd6, 0xa1, 0x83, 0x01, 0xd1, 0x56, 0x02, 0x00, 0x94, 0xe0, 0x38, 0x00, 0x34,
|
||||
0xa1, 0xe3, 0x02, 0xd1, 0xe0, 0x03, 0x17, 0xaa, 0x82, 0x00, 0x80, 0x52, 0x56, 0x02, 0x00, 0x94, 0x40, 0x38, 0x00,
|
||||
0x34, 0xbf, 0x03, 0x16, 0xf8, 0x68, 0x43, 0x40, 0xf9, 0xa2, 0x83, 0x54, 0xb8, 0xa6, 0x03, 0x5a, 0xf8, 0xff, 0x83,
|
||||
0x00, 0xd1, 0x49, 0x00, 0x80, 0x52, 0xe9, 0x13, 0x00, 0xb9, 0xa1, 0x83, 0x02, 0xd1, 0xa9, 0xa3, 0x02, 0xd1, 0xe9,
|
||||
0x07, 0x00, 0xf9, 0xa9, 0x93, 0x02, 0xd1, 0xe9, 0x03, 0x00, 0xf9, 0xe0, 0x03, 0x1a, 0xaa, 0x03, 0x00, 0x80, 0xd2,
|
||||
0x24, 0x00, 0x80, 0x52, 0xe5, 0x03, 0x1a, 0xaa, 0x07, 0x00, 0x80, 0x52, 0x00, 0x01, 0x3f, 0xd6, 0xff, 0x83, 0x00,
|
||||
0x91, 0xc0, 0x35, 0x00, 0x35, 0x68, 0x2b, 0x40, 0xf9, 0xa0, 0x03, 0x56, 0xf8, 0xa1, 0x83, 0x54, 0xb8, 0x62, 0x00,
|
||||
0x80, 0x52, 0x00, 0x01, 0x3f, 0xd6, 0x60, 0x2e, 0x00, 0x35, 0xa1, 0x03, 0x56, 0xf8, 0xa2, 0x83, 0x54, 0xb8, 0xa3,
|
||||
0xc3, 0x02, 0xd1, 0xe0, 0x03, 0x17, 0xaa, 0xe4, 0x03, 0x1b, 0xaa, 0xc0, 0x01, 0x00, 0x94, 0x80, 0x2d, 0x00, 0x34,
|
||||
0x68, 0x2f, 0x40, 0xf9, 0x46, 0x02, 0x00, 0x94, 0x68, 0x33, 0x40, 0xf9, 0x44, 0x02, 0x00, 0x94, 0x33, 0x00, 0x80,
|
||||
0x52, 0x67, 0x01, 0x00, 0x14, 0xa1, 0x83, 0x01, 0xd1, 0x27, 0x02, 0x00, 0x94, 0x00, 0x33, 0x00, 0x34, 0xa1, 0xe3,
|
||||
0x02, 0xd1, 0xe0, 0x03, 0x17, 0xaa, 0x82, 0x00, 0x80, 0x52, 0x27, 0x02, 0x00, 0x94, 0x60, 0x32, 0x00, 0x34, 0x13,
|
||||
0x00, 0x80, 0x52, 0xb4, 0x03, 0x5a, 0xf8, 0xa8, 0x83, 0x54, 0xb8, 0x7f, 0x02, 0x08, 0x6b, 0x80, 0xf6, 0xff, 0x54,
|
||||
0xbf, 0x03, 0x16, 0xf8, 0xbf, 0x03, 0x15, 0xf8, 0x88, 0x5a, 0x73, 0xf8, 0xa1, 0x83, 0x02, 0xd1, 0xa2, 0xc3, 0x02,
|
||||
0xd1, 0x28, 0x02, 0x00, 0x94, 0x73, 0x06, 0x00, 0x11, 0xf6, 0xff, 0xff, 0x17, 0xa1, 0x83, 0x02, 0xd1, 0x12, 0x02,
|
||||
0x00, 0x94, 0x60, 0x30, 0x00, 0x34, 0xa1, 0xc3, 0x02, 0xd1, 0x0f, 0x02, 0x00, 0x94, 0x00, 0x30, 0x00, 0x34, 0xa1,
|
||||
0xe3, 0x02, 0xd1, 0x0c, 0x02, 0x00, 0x94, 0xa0, 0x2f, 0x00, 0x34, 0xbc, 0x03, 0x56, 0xf8, 0xa8, 0xeb, 0x74, 0xa9,
|
||||
0xa8, 0x83, 0x10, 0xf8, 0x68, 0x37, 0x40, 0xf9, 0x00, 0x01, 0x3f, 0xd6, 0xbf, 0x03, 0x1a, 0xf8, 0x68, 0x3b, 0x40,
|
||||
0xf9, 0xa1, 0x83, 0x01, 0xd1, 0xa9, 0x63, 0x00, 0xd1, 0x20, 0x01, 0x10, 0xb8, 0x22, 0x00, 0xa0, 0x52, 0x23, 0x00,
|
||||
0x80, 0x52, 0x00, 0x01, 0x3f, 0xd6, 0x13, 0x00, 0x80, 0x52, 0x15, 0x00, 0x80, 0xd2, 0xb4, 0x03, 0x5a, 0xf8, 0x56,
|
||||
0x83, 0x00, 0x91, 0x48, 0x13, 0x40, 0xb9, 0x7f, 0x02, 0x08, 0x6b, 0xe0, 0x12, 0x00, 0x54, 0xc8, 0x02, 0x40, 0xb9,
|
||||
0x09, 0xfd, 0x9f, 0x52, 0xe9, 0xff, 0xaf, 0x72, 0x09, 0x01, 0x09, 0x0b, 0x3f, 0x2d, 0x00, 0x71, 0x09, 0x23, 0xc9,
|
||||
0x1a, 0x2a, 0x10, 0x81, 0x52, 0x29, 0x01, 0x0a, 0x0a, 0x24, 0x99, 0x40, 0x7a, 0x04, 0x09, 0x4c, 0x7a, 0x01, 0x01,
|
||||
0x00, 0x54, 0xc8, 0x0a, 0x40, 0xb9, 0x69, 0x47, 0x40, 0xf9, 0xc0, 0x02, 0x08, 0x8b, 0x21, 0x01, 0x80, 0x52, 0x20,
|
||||
0x01, 0x3f, 0xd6, 0x80, 0x7a, 0x35, 0xf8, 0xb5, 0x06, 0x00, 0x91, 0xc8, 0x06, 0x40, 0xb9, 0xd6, 0x02, 0x08, 0x8b,
|
||||
0x73, 0x06, 0x00, 0x11, 0xe8, 0xff, 0xff, 0x17, 0xa1, 0x83, 0x01, 0xd1, 0xdf, 0x01, 0x00, 0x94, 0x00, 0x2a, 0x00,
|
||||
0x34, 0xa1, 0x83, 0x02, 0xd1, 0xe0, 0x03, 0x17, 0xaa, 0x82, 0x00, 0x80, 0x52, 0xdf, 0x01, 0x00, 0x94, 0x60, 0x29,
|
||||
0x00, 0x34, 0xa1, 0xc3, 0x02, 0xd1, 0xe0, 0x03, 0x17, 0xaa, 0x82, 0x00, 0x80, 0x52, 0xda, 0x01, 0x00, 0x94, 0xc0,
|
||||
0x28, 0x00, 0x36, 0x68, 0x2b, 0x40, 0xf9, 0xa0, 0x03, 0x5a, 0xf8, 0xa1, 0x03, 0x56, 0xb8, 0xa2, 0x03, 0x55, 0xb8,
|
||||
0x00, 0x01, 0x3f, 0xd6, 0xc0, 0xec, 0xff, 0x34, 0x3f, 0x01, 0x00, 0x14, 0xa1, 0x83, 0x01, 0xd1, 0xcb, 0x01, 0x00,
|
||||
0x94, 0x80, 0x27, 0x00, 0x34, 0xa1, 0x83, 0x02, 0xd1, 0xc8, 0x01, 0x00, 0x94, 0x20, 0x27, 0x00, 0x34, 0xa1, 0xc3,
|
||||
0x02, 0xd1, 0xe0, 0x03, 0x17, 0xaa, 0x42, 0x00, 0x80, 0x52, 0xc8, 0x01, 0x00, 0x94, 0x80, 0x26, 0x00, 0x34, 0xf4,
|
||||
0x03, 0x00, 0x91, 0xa8, 0x03, 0x55, 0x78, 0x08, 0x71, 0x1d, 0x53, 0x08, 0x3d, 0x00, 0x11, 0x08, 0x3d, 0x7c, 0x92,
|
||||
0xe9, 0x03, 0x00, 0x91, 0x38, 0x01, 0x08, 0xcb, 0x1f, 0x03, 0x00, 0x91, 0xa8, 0x03, 0x55, 0x78, 0x02, 0xf1, 0x7d,
|
||||
0xd3, 0xe0, 0x03, 0x17, 0xaa, 0xe1, 0x03, 0x18, 0xaa, 0xba, 0x01, 0x00, 0x94, 0xa0, 0x24, 0x00, 0x34, 0xa1, 0xe3,
|
||||
0x02, 0xd1, 0xe0, 0x03, 0x17, 0xaa, 0x42, 0x00, 0x80, 0x52, 0xb5, 0x01, 0x00, 0x94, 0x00, 0x24, 0x00, 0x34, 0xa8,
|
||||
0x83, 0x54, 0x78, 0x09, 0x71, 0x1d, 0x53, 0x29, 0x3d, 0x00, 0x11, 0x29, 0x3d, 0x7c, 0x92, 0xea, 0x03, 0x00, 0x91,
|
||||
0x59, 0x01, 0x09, 0xcb, 0x3f, 0x03, 0x00, 0x91, 0x02, 0x7d, 0x7d, 0xd3, 0xe0, 0x03, 0x17, 0xaa, 0xe1, 0x03, 0x19,
|
||||
0xaa, 0xa9, 0x01, 0x00, 0x94, 0x80, 0x22, 0x00, 0x34, 0x15, 0x00, 0x80, 0xd2, 0xb6, 0x03, 0x5a, 0xf8, 0xbb, 0x03,
|
||||
0x56, 0xf8, 0xbc, 0x83, 0x54, 0x78, 0xbf, 0x02, 0x1c, 0xeb, 0x00, 0x1a, 0x00, 0x54, 0x3a, 0x7b, 0x75, 0xf8, 0x53,
|
||||
0x03, 0x40, 0xf9, 0xf3, 0x01, 0xf0, 0xb7, 0x68, 0xfe, 0x6b, 0xd3, 0x69, 0xaa, 0x40, 0x92, 0x6a, 0xaa, 0x6a, 0x93,
|
||||
0x4a, 0x31, 0x55, 0x92, 0x09, 0x1d, 0x48, 0xb3, 0x28, 0x01, 0x0a, 0xaa, 0xe9, 0x03, 0x13, 0x2a, 0x7f, 0x02, 0x41,
|
||||
0xf2, 0xea, 0x03, 0x96, 0x9a, 0x08, 0x01, 0x89, 0x9a, 0x49, 0x01, 0x1b, 0x8b, 0x20, 0x01, 0x08, 0x8b, 0x53, 0x01,
|
||||
0xf8, 0xb6, 0x04, 0x00, 0x00, 0x14, 0x68, 0x3e, 0x40, 0x92, 0x00, 0x7b, 0x68, 0xf8, 0xd3, 0x00, 0xf8, 0xb6, 0x61,
|
||||
0xca, 0x71, 0xd3, 0x63, 0xc2, 0x70, 0xd3, 0x62, 0xbe, 0x60, 0xd3, 0xe4, 0x03, 0x1a, 0xaa, 0x63, 0x01, 0x00, 0x94,
|
||||
0x40, 0x03, 0x00, 0xf9, 0x68, 0xf6, 0x73, 0xd3, 0x5a, 0x0f, 0x08, 0x8b, 0x7f, 0x2a, 0x4d, 0xf2, 0x81, 0xfc, 0xff,
|
||||
0x54, 0xb5, 0x06, 0x00, 0x91, 0xdf, 0xff, 0xff, 0x17, 0xa1, 0x83, 0x01, 0xd1, 0x7b, 0x01, 0x00, 0x94, 0x80, 0x1d,
|
||||
0x00, 0x34, 0xa1, 0x93, 0x02, 0xd1, 0xe0, 0x03, 0x17, 0xaa, 0x82, 0x00, 0x80, 0x52, 0x7b, 0x01, 0x00, 0x94, 0xe0,
|
||||
0x1c, 0x00, 0x34, 0xa1, 0x83, 0x02, 0xd1, 0x73, 0x01, 0x00, 0x94, 0x80, 0x1c, 0x00, 0x34, 0x13, 0x00, 0x80, 0x52,
|
||||
0xb4, 0x03, 0x5a, 0xf8, 0xa8, 0xc3, 0x55, 0xb8, 0x7f, 0x02, 0x08, 0x6b, 0xa0, 0xe0, 0xff, 0x54, 0xbf, 0xff, 0x34,
|
||||
0xa9, 0xa8, 0x03, 0x56, 0xf8, 0x89, 0x5a, 0x73, 0xb8, 0x08, 0x01, 0x09, 0x8b, 0xa1, 0xc3, 0x02, 0xd1, 0xa2, 0xe3,
|
||||
0x02, 0xd1, 0x78, 0x01, 0x00, 0x94, 0x73, 0x06, 0x00, 0x11, 0xf5, 0xff, 0xff, 0x17, 0x71, 0x01, 0x00, 0x94, 0x40,
|
||||
0xdf, 0x07, 0x37, 0xd3, 0x00, 0x00, 0x14, 0x98, 0x0e, 0x15, 0x8b, 0x88, 0xe7, 0x41, 0x29, 0x96, 0x03, 0x08, 0x8b,
|
||||
0x88, 0x17, 0x40, 0xb9, 0x1f, 0x0d, 0x00, 0x71, 0xc0, 0x16, 0x00, 0x54, 0x1f, 0x09, 0x00, 0x71, 0xc0, 0x13, 0x00,
|
||||
0x54, 0x1f, 0x05, 0x00, 0x71, 0x81, 0x02, 0x00, 0x54, 0x88, 0x0b, 0x40, 0xb9, 0x93, 0x03, 0x08, 0x8b, 0x94, 0x22,
|
||||
0x00, 0xd1, 0xf5, 0x03, 0x18, 0xaa, 0xf9, 0x01, 0x00, 0xb4, 0x69, 0x02, 0x40, 0xb9, 0x28, 0x1d, 0x40, 0x92, 0xe8,
|
||||
0x00, 0x00, 0x34, 0xc9, 0x26, 0x49, 0x8b, 0x55, 0x01, 0x00, 0x94, 0x80, 0x7a, 0x68, 0xf8, 0x20, 0x01, 0x3f, 0xd6,
|
||||
0xe0, 0x43, 0xc1, 0xda, 0x02, 0x00, 0x00, 0x14, 0x00, 0x00, 0x80, 0xd2, 0xa0, 0x86, 0x00, 0xf8, 0x73, 0x12, 0x00,
|
||||
0x91, 0x39, 0x07, 0x00, 0xd1, 0x79, 0xfe, 0xff, 0xb5, 0x09, 0x00, 0x80, 0xd2, 0x88, 0x07, 0x40, 0xb9, 0x88, 0x03,
|
||||
0x08, 0x8b, 0xa8, 0x03, 0x10, 0xf8, 0x0a, 0x45, 0x40, 0xb8, 0xaa, 0x03, 0x12, 0xf8, 0xa8, 0x03, 0x11, 0xf8, 0xa8,
|
||||
0x03, 0x52, 0xf8, 0x3f, 0x01, 0x08, 0xeb, 0xc0, 0x0c, 0x00, 0x54, 0xa9, 0x83, 0x12, 0xf8, 0xa8, 0x03, 0x51, 0xf8,
|
||||
0x08, 0x79, 0x69, 0xb8, 0xc8, 0x0b, 0x00, 0x34, 0x1c, 0x00, 0x80, 0xd2, 0xa9, 0x03, 0x50, 0xf8, 0x35, 0x01, 0x08,
|
||||
0x8b, 0xa8, 0x0e, 0x40, 0x79, 0xa9, 0x2a, 0x40, 0x79, 0xa9, 0x03, 0x14, 0xf8, 0xa9, 0x5a, 0x00, 0x91, 0xa9, 0x83,
|
||||
0x13, 0xf8, 0x09, 0x79, 0x1d, 0x12, 0xa9, 0x43, 0x13, 0xb8, 0x1f, 0x31, 0x00, 0x71, 0xe9, 0xff, 0x9f, 0x52, 0x0a,
|
||||
0xe0, 0xbf, 0x12, 0x54, 0x01, 0x89, 0x9a, 0x1f, 0x05, 0x00, 0x71, 0xaa, 0x83, 0x50, 0xf8, 0x49, 0x01, 0x9f, 0x9a,
|
||||
0x56, 0x03, 0x09, 0xcb, 0x1f, 0x19, 0x00, 0x71, 0xe8, 0x03, 0x8a, 0x9a, 0x5b, 0x03, 0x08, 0xcb, 0xa8, 0x03, 0x54,
|
||||
0xf8, 0x9f, 0x03, 0x08, 0xeb, 0xc0, 0x08, 0x00, 0x54, 0xa8, 0x83, 0x53, 0xf8, 0x08, 0x79, 0x7c, 0x78, 0xe9, 0xff,
|
||||
0x9f, 0x52, 0x1f, 0x01, 0x09, 0xeb, 0xe0, 0x07, 0x00, 0x54, 0xa9, 0x06, 0x40, 0xf9, 0x49, 0x03, 0x09, 0x8b, 0xaa,
|
||||
0x0a, 0x40, 0x79, 0x89, 0x27, 0x0a, 0x9b, 0x39, 0x01, 0x08, 0x8b, 0xa8, 0x43, 0x53, 0xb8, 0x1f, 0x09, 0x00, 0x71,
|
||||
0x41, 0x02, 0x00, 0x54, 0x29, 0x03, 0x40, 0xf9, 0xe9, 0x00, 0xf8, 0xb7, 0x28, 0xfd, 0x73, 0xd3, 0x2a, 0xfd, 0x64,
|
||||
0xd3, 0x29, 0x8d, 0x40, 0x92, 0x69, 0x03, 0x09, 0x8b, 0x29, 0xe1, 0x0a, 0x8b, 0x06, 0x00, 0x00, 0x14, 0x28, 0xf9,
|
||||
0x73, 0xd3, 0x2a, 0x5d, 0x40, 0x92, 0x0a, 0x7b, 0x6a, 0xf8, 0x29, 0xfd, 0x58, 0xd3, 0x49, 0x01, 0x29, 0x8b, 0x29,
|
||||
0x03, 0x00, 0xf9, 0x39, 0x0b, 0x08, 0x8b, 0x28, 0xfe, 0xff, 0xb5, 0x26, 0x00, 0x00, 0x14, 0x33, 0x03, 0x40, 0xf9,
|
||||
0x70, 0xfe, 0x7e, 0xd3, 0x62, 0xbe, 0x60, 0xd3, 0x63, 0xc2, 0x70, 0xd3, 0x61, 0xca, 0x71, 0xd3, 0x1f, 0x0e, 0x00,
|
||||
0xf1, 0x10, 0x92, 0x9f, 0x9a, 0x11, 0x00, 0x00, 0x90, 0x31, 0xc2, 0x22, 0x91, 0x30, 0x7a, 0xb0, 0xb8, 0x11, 0x00,
|
||||
0x00, 0x10, 0x30, 0x02, 0x10, 0x8b, 0x00, 0x02, 0x1f, 0xd6, 0x68, 0xfe, 0x6b, 0xd3, 0x69, 0xaa, 0x40, 0x92, 0xc9,
|
||||
0x02, 0x09, 0x8b, 0x20, 0xe1, 0x08, 0x8b, 0x10, 0x00, 0x00, 0x14, 0x40, 0x43, 0x33, 0x8b, 0x03, 0x00, 0x00, 0x14,
|
||||
0x68, 0x02, 0x14, 0x8a, 0x00, 0x7b, 0x68, 0xf8, 0xe4, 0x03, 0x19, 0xaa, 0xc7, 0x00, 0x00, 0x94, 0x09, 0x00, 0x00,
|
||||
0x14, 0x68, 0x02, 0x14, 0x8a, 0x08, 0x7b, 0x68, 0xf8, 0x89, 0x00, 0xa0, 0x52, 0x3f, 0x81, 0x53, 0xea, 0xe9, 0xb3,
|
||||
0x6d, 0xb2, 0xe9, 0x03, 0x89, 0x9a, 0x69, 0xca, 0x60, 0xb3, 0x00, 0x01, 0x09, 0x8b, 0x20, 0x03, 0x00, 0xf9, 0x68,
|
||||
0xf6, 0x73, 0xd3, 0x39, 0x0f, 0x08, 0x8b, 0x88, 0xfb, 0xff, 0xb5, 0x9c, 0x07, 0x00, 0x91, 0xb9, 0xff, 0xff, 0x17,
|
||||
0xa9, 0x83, 0x52, 0xf8, 0x29, 0x05, 0x00, 0x91, 0xbb, 0x83, 0x51, 0xf8, 0x99, 0xff, 0xff, 0x17, 0x68, 0x3f, 0x40,
|
||||
0xf9, 0xa1, 0x03, 0x5a, 0xf8, 0xa9, 0x63, 0x00, 0xd1, 0x20, 0x01, 0x50, 0xb8, 0x22, 0x00, 0xa0, 0x52, 0x00, 0x01,
|
||||
0x3f, 0xd6, 0x03, 0x00, 0x00, 0x14, 0x9f, 0x02, 0x00, 0x91, 0xbb, 0x83, 0x51, 0xf8, 0xa8, 0x13, 0x00, 0xd1, 0x15,
|
||||
0x01, 0x50, 0xb8, 0xa8, 0x43, 0x00, 0xd1, 0x16, 0x01, 0x50, 0xf8, 0xa8, 0x53, 0x00, 0xd1, 0x1a, 0x01, 0x50, 0xb8,
|
||||
0x38, 0x00, 0x80, 0x52, 0x5c, 0xfe, 0xff, 0x17, 0x13, 0x00, 0x80, 0x52, 0x68, 0x3f, 0x40, 0xf9, 0xa1, 0x03, 0x56,
|
||||
0xf8, 0xa2, 0x83, 0x54, 0xb8, 0xe0, 0x03, 0x1a, 0xaa, 0x00, 0x01, 0x3f, 0xd6, 0xb3, 0xca, 0x07, 0x37, 0x2e, 0x00,
|
||||
0x00, 0x14, 0x88, 0x0b, 0x40, 0xb9, 0x93, 0x22, 0x00, 0xd1, 0x88, 0x03, 0x08, 0x8b, 0x14, 0x11, 0x00, 0x91, 0xf5,
|
||||
0x03, 0x18, 0xaa, 0x79, 0xee, 0xff, 0xb4, 0x89, 0xc2, 0x5f, 0xb8, 0x28, 0x1d, 0x40, 0x92, 0xe8, 0x00, 0x00, 0x34,
|
||||
0xc9, 0x26, 0x49, 0x8b, 0xb9, 0x00, 0x00, 0x94, 0x60, 0x7a, 0x68, 0xf8, 0x20, 0x01, 0x3f, 0xd6, 0xe0, 0x43, 0xc1,
|
||||
0xda, 0x02, 0x00, 0x00, 0x14, 0x00, 0x00, 0x80, 0xd2, 0x88, 0x86, 0x80, 0xb8, 0x08, 0x00, 0x08, 0x8b, 0xa8, 0x86,
|
||||
0x00, 0xf8, 0x39, 0x07, 0x00, 0xd1, 0x59, 0xfe, 0xff, 0xb5, 0x63, 0xff, 0xff, 0x17, 0xe8, 0x03, 0x1c, 0xaa, 0x09,
|
||||
0x8d, 0x40, 0xb8, 0x93, 0x22, 0x00, 0xd1, 0x14, 0x01, 0x09, 0x8b, 0xf5, 0x03, 0x18, 0xaa, 0xb9, 0xeb, 0xff, 0xb4,
|
||||
0x89, 0x82, 0x5f, 0xf8, 0x28, 0x3d, 0x40, 0xf2, 0xe0, 0x00, 0x00, 0x54, 0xc9, 0x82, 0x49, 0x8b, 0xa3, 0x00, 0x00,
|
||||
0x94, 0x60, 0x7a, 0x68, 0xf8, 0x20, 0x01, 0x3f, 0xd6, 0xe0, 0x43, 0xc1, 0xda, 0x02, 0x00, 0x00, 0x14, 0x00, 0x00,
|
||||
0x80, 0xd2, 0x88, 0x06, 0x41, 0xf8, 0x08, 0x00, 0x08, 0x8b, 0xa8, 0x86, 0x00, 0xf8, 0x39, 0x07, 0x00, 0xd1, 0x59,
|
||||
0xfe, 0xff, 0xb5, 0x4d, 0xff, 0xff, 0x17, 0x9f, 0x02, 0x00, 0x91, 0xa4, 0x00, 0x00, 0x94, 0x68, 0x1b, 0x40, 0xf9,
|
||||
0xe0, 0x03, 0x15, 0xaa, 0x00, 0x01, 0x3f, 0xd6, 0xa8, 0xc3, 0x99, 0xb8, 0xe0, 0x03, 0x08, 0xaa, 0x21, 0xa7, 0x80,
|
||||
0xd2, 0x22, 0xa7, 0x80, 0xd2, 0x03, 0x00, 0x80, 0xd2, 0x20, 0xa7, 0x20, 0xd4, 0xa0, 0xc3, 0x99, 0xb8, 0xbf, 0x43,
|
||||
0x01, 0xd1, 0xfd, 0x7b, 0x45, 0xa9, 0xf4, 0x4f, 0x44, 0xa9, 0xf6, 0x57, 0x43, 0xa9, 0xf8, 0x5f, 0x42, 0xa9, 0xfa,
|
||||
0x67, 0x41, 0xa9, 0xfc, 0x6f, 0xc6, 0xa8, 0xc0, 0x03, 0x5f, 0xd6, 0x0c, 0x00, 0x00, 0x00, 0x38, 0x02, 0x00, 0x00,
|
||||
0x1c, 0x01, 0x00, 0x00, 0xe8, 0x01, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x78, 0x03, 0x00, 0x00, 0xdc, 0x03, 0x00,
|
||||
0x00, 0x0c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xf8, 0x5f,
|
||||
0xbc, 0xa9, 0xf6, 0x57, 0x01, 0xa9, 0xf4, 0x4f, 0x02, 0xa9, 0xfd, 0x7b, 0x03, 0xa9, 0xfd, 0xc3, 0x00, 0x91, 0xf3,
|
||||
0x03, 0x04, 0xaa, 0xf4, 0x03, 0x03, 0xaa, 0xf5, 0x03, 0x02, 0xaa, 0xf6, 0x03, 0x01, 0xaa, 0xf7, 0x03, 0x00, 0xaa,
|
||||
0x43, 0x00, 0x00, 0xb4, 0x9f, 0x02, 0x00, 0xf9, 0xbf, 0x02, 0x00, 0xf1, 0xf8, 0x17, 0x9f, 0x1a, 0xd5, 0x03, 0x00,
|
||||
0xb4, 0x68, 0x1e, 0x40, 0xf9, 0xe0, 0x03, 0x17, 0xaa, 0xe1, 0x03, 0x16, 0xaa, 0xe2, 0x03, 0x15, 0xaa, 0x00, 0x01,
|
||||
0x3f, 0xd6, 0x1f, 0x04, 0x00, 0xb1, 0xe1, 0x00, 0x00, 0x54, 0x68, 0x4e, 0x40, 0xf9, 0x00, 0x01, 0x3f, 0xd6, 0x08,
|
||||
0x00, 0x40, 0xb9, 0x1f, 0x11, 0x00, 0x71, 0xa0, 0xfe, 0xff, 0x54, 0x0a, 0x00, 0x00, 0x14, 0x1f, 0x04, 0x00, 0xf1,
|
||||
0x2b, 0x01, 0x00, 0x54, 0x94, 0x00, 0x00, 0xb4, 0x88, 0x02, 0x40, 0xf9, 0x08, 0x01, 0x00, 0x8b, 0x88, 0x02, 0x00,
|
||||
0xf9, 0xd6, 0x02, 0x00, 0x8b, 0xb5, 0x02, 0x00, 0xcb, 0xe8, 0xff, 0xff, 0x17, 0x18, 0x00, 0x80, 0x52, 0xe0, 0x03,
|
||||
0x18, 0xaa, 0xfd, 0x7b, 0x43, 0xa9, 0xf4, 0x4f, 0x42, 0xa9, 0xf6, 0x57, 0x41, 0xa9, 0xf8, 0x5f, 0xc4, 0xa8, 0xc0,
|
||||
0x03, 0x5f, 0xd6, 0x38, 0x00, 0x80, 0x52, 0xf9, 0xff, 0xff, 0x17, 0xf6, 0x57, 0xbd, 0xa9, 0xf4, 0x4f, 0x01, 0xa9,
|
||||
0xfd, 0x7b, 0x02, 0xa9, 0xfd, 0x83, 0x00, 0x91, 0xf3, 0x03, 0x02, 0xaa, 0xf4, 0x03, 0x01, 0xaa, 0xf5, 0x03, 0x00,
|
||||
0xaa, 0x88, 0x00, 0x80, 0x52, 0xf6, 0x03, 0x08, 0xaa, 0x48, 0x02, 0x00, 0xb4, 0x68, 0x22, 0x40, 0xf9, 0xe0, 0x03,
|
||||
0x15, 0xaa, 0xe1, 0x03, 0x14, 0xaa, 0xe2, 0x03, 0x16, 0xaa, 0x00, 0x01, 0x3f, 0xd6, 0x1f, 0x04, 0x00, 0xb1, 0xe1,
|
||||
0x00, 0x00, 0x54, 0x68, 0x4e, 0x40, 0xf9, 0x00, 0x01, 0x3f, 0xd6, 0x08, 0x00, 0x40, 0xb9, 0x1f, 0x11, 0x00, 0x71,
|
||||
0xa0, 0xfe, 0xff, 0x54, 0x05, 0x00, 0x00, 0x14, 0x94, 0x02, 0x00, 0x8b, 0xc8, 0x02, 0x00, 0xcb, 0x1f, 0x00, 0x00,
|
||||
0xf1, 0xcc, 0xfd, 0xff, 0x54, 0xdf, 0x02, 0x00, 0xf1, 0xe0, 0x17, 0x9f, 0x1a, 0xfd, 0x7b, 0x42, 0xa9, 0xf4, 0x4f,
|
||||
0x41, 0xa9, 0xf6, 0x57, 0xc3, 0xa8, 0xc0, 0x03, 0x5f, 0xd6, 0x44, 0x3c, 0x50, 0xb3, 0x7f, 0x00, 0x00, 0x71, 0x48,
|
||||
0x00, 0x84, 0x9a, 0xf0, 0x03, 0x01, 0x2a, 0x1f, 0x0e, 0x00, 0xf1, 0x10, 0x92, 0x9f, 0x9a, 0x11, 0x00, 0x00, 0x90,
|
||||
0x31, 0xc2, 0x29, 0x91, 0x30, 0x7a, 0xb0, 0xb8, 0x11, 0x00, 0x00, 0x10, 0x30, 0x02, 0x10, 0x8b, 0x00, 0x02, 0x1f,
|
||||
0xd6, 0xf1, 0x03, 0x00, 0xaa, 0xf0, 0x03, 0x08, 0xaa, 0x1f, 0x21, 0x03, 0xd5, 0x0c, 0x00, 0x00, 0x14, 0xf1, 0x03,
|
||||
0x00, 0xaa, 0xf0, 0x03, 0x08, 0xaa, 0x11, 0x0a, 0xc1, 0xda, 0x08, 0x00, 0x00, 0x14, 0xf1, 0x03, 0x00, 0xaa, 0xf0,
|
||||
0x03, 0x08, 0xaa, 0x11, 0x0e, 0xc1, 0xda, 0x04, 0x00, 0x00, 0x14, 0xf1, 0x03, 0x00, 0xaa, 0xf0, 0x03, 0x08, 0xaa,
|
||||
0x5f, 0x21, 0x03, 0xd5, 0xe0, 0x03, 0x11, 0xaa, 0xc0, 0x03, 0x5f, 0xd6, 0x0c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00,
|
||||
0x00, 0x1c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x17, 0xaa, 0x02, 0x01, 0x80, 0x52, 0x03, 0x00,
|
||||
0x80, 0xd2, 0xe4, 0x03, 0x1b, 0xaa, 0x8c, 0xff, 0xff, 0x17, 0x03, 0x00, 0x80, 0xd2, 0xe4, 0x03, 0x1b, 0xaa, 0x89,
|
||||
0xff, 0xff, 0x17, 0xea, 0x03, 0x09, 0xaa, 0x4b, 0x15, 0x40, 0x38, 0x7f, 0x7d, 0x01, 0x71, 0x21, 0x11, 0x8a, 0x9a,
|
||||
0x69, 0x4b, 0x40, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0xa1, 0xf3, 0x01, 0xd1, 0xe0, 0x03, 0x17, 0xaa, 0xe2, 0x03, 0x1b,
|
||||
0xaa, 0xad, 0xff, 0xff, 0x17, 0xa4, 0x93, 0x01, 0xd1, 0x00, 0x00, 0x80, 0x52, 0xe3, 0x03, 0x16, 0xaa, 0x00, 0x01,
|
||||
0x1f, 0xd6, 0x68, 0x1b, 0x40, 0xf9, 0xe0, 0x03, 0x17, 0xaa, 0x00, 0x01, 0x1f, 0xd6, 0xa0, 0x03, 0x5a, 0xf8, 0xa1,
|
||||
0x03, 0x55, 0xf8, 0x00, 0x01, 0x1f, 0xd6
|
||||
};
|
||||
|
||||
private static bool is_dyld_stub_binder (string module_name, string symbol_name) {
|
||||
@@ -813,7 +855,7 @@ namespace Frida.Fruity.Injector {
|
||||
private static uint64 resolve_dyld_symbol (string name, string nick, Gee.Map<string, uint64?> dyld_symbols) throws Error {
|
||||
uint64? val = dyld_symbols[name];
|
||||
if (val == null)
|
||||
throw new Error.UNSUPPORTED ("Unsupported iOS version (%s not found)", nick);
|
||||
throw new Error.NOT_SUPPORTED ("Unsupported iOS version (%s not found)", nick);
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -863,7 +905,7 @@ namespace Frida.Fruity.Injector {
|
||||
|
||||
GDB.Breakpoint? hit_breakpoint = exception.breakpoint;
|
||||
if (hit_breakpoint == null)
|
||||
throw new Error.UNSUPPORTED ("Unexpected exception");
|
||||
throw new Error.NOT_SUPPORTED ("Unexpected exception");
|
||||
|
||||
if (restart_breakpoint != null)
|
||||
yield restart_breakpoint.remove (cancellable);
|
||||
@@ -871,7 +913,7 @@ namespace Frida.Fruity.Injector {
|
||||
|
||||
if (hit_breakpoint == restart_breakpoint) {
|
||||
if (process_info_ptr == null)
|
||||
throw new Error.UNSUPPORTED ("Missing gProcessInfo");
|
||||
throw new Error.NOT_SUPPORTED ("Missing gProcessInfo");
|
||||
uint64 process_info = yield lldb.read_pointer (process_info_ptr, cancellable);
|
||||
uint64 dyld_image_load_address = yield lldb.read_pointer (process_info + 0x20, cancellable);
|
||||
|
||||
@@ -892,7 +934,7 @@ namespace Frida.Fruity.Injector {
|
||||
|
||||
hit_breakpoint = exception.breakpoint;
|
||||
if (hit_breakpoint == null)
|
||||
throw new Error.UNSUPPORTED ("Unexpected exception");
|
||||
throw new Error.NOT_SUPPORTED ("Unexpected exception");
|
||||
|
||||
dyld_fields = yield lldb.get_apple_dyld_fields (BYPASS_CACHE, cancellable);
|
||||
}
|
||||
@@ -924,7 +966,7 @@ namespace Frida.Fruity.Injector {
|
||||
|
||||
hit_breakpoint = exception.breakpoint;
|
||||
if (hit_breakpoint == null)
|
||||
throw new Error.UNSUPPORTED ("Unexpected exception");
|
||||
throw new Error.NOT_SUPPORTED ("Unexpected exception");
|
||||
|
||||
assert (hit_breakpoint == caller_breakpoint);
|
||||
yield caller_breakpoint.remove (cancellable);
|
||||
@@ -959,7 +1001,7 @@ namespace Frida.Fruity.Injector {
|
||||
|
||||
GDB.Breakpoint? hit_breakpoint = exception.breakpoint;
|
||||
if (hit_breakpoint == null)
|
||||
throw new Error.UNSUPPORTED ("Unexpected exception");
|
||||
throw new Error.NOT_SUPPORTED ("Unexpected exception");
|
||||
|
||||
yield legacy_breakpoint.remove (cancellable);
|
||||
|
||||
@@ -1005,7 +1047,7 @@ namespace Frida.Fruity.Injector {
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error.UNSUPPORTED ("Unable to probe dyld v3 internals; please file a bug");
|
||||
throw new Error.NOT_SUPPORTED ("Unable to probe dyld v3 internals; please file a bug");
|
||||
}
|
||||
|
||||
private async void initialize_libsystem_from_legacy_codepath (Gee.Map<string, uint64?> dyld_symbols,
|
||||
@@ -1178,14 +1220,14 @@ namespace Frida.Fruity.Injector {
|
||||
}, null, cancellable);
|
||||
size_t size = length + 1;
|
||||
if (size > page_size)
|
||||
throw new Error.UNSUPPORTED ("Buffer too small; please file a bug");
|
||||
throw new Error.NOT_SUPPORTED ("Buffer too small; please file a bug");
|
||||
|
||||
Bytes output_bytes = yield lldb.read_byte_array (output, size, cancellable);
|
||||
unowned string output_str = (string) output_bytes.get_data ();
|
||||
foreach (var line in output_str.split ("\n")) {
|
||||
var tokens = line.split ("\t", 2);
|
||||
if (tokens.length != 2)
|
||||
throw new Error.UNSUPPORTED ("Unable to fetch dyld symbols; please file a bug");
|
||||
throw new Error.NOT_SUPPORTED ("Unable to fetch dyld symbols; please file a bug");
|
||||
|
||||
unowned string raw_address = tokens[0];
|
||||
unowned string name = tokens[1];
|
||||
@@ -1202,73 +1244,72 @@ namespace Frida.Fruity.Injector {
|
||||
/* Compiled from helpers/symbol-fetcher.c */
|
||||
private const uint8[] SYMBOL_FETCHER_CODE = {
|
||||
0xff, 0x03, 0x02, 0xd1, 0xfc, 0x6f, 0x02, 0xa9, 0xfa, 0x67, 0x03, 0xa9, 0xf8, 0x5f, 0x04, 0xa9, 0xf6, 0x57, 0x05,
|
||||
0xa9, 0xf4, 0x4f, 0x06, 0xa9, 0xfd, 0x7b, 0x07, 0xa9, 0xfd, 0xc3, 0x01, 0x91, 0xf4, 0x03, 0x01, 0xaa, 0xe0, 0x07,
|
||||
0x00, 0xf9, 0x13, 0x00, 0x80, 0xd2, 0x19, 0x00, 0x80, 0xd2, 0x35, 0x80, 0x00, 0x91, 0x3a, 0x10, 0x40, 0xb9, 0x16,
|
||||
0x00, 0x00, 0x90, 0xd6, 0x3e, 0x13, 0x91, 0x17, 0x00, 0x00, 0x90, 0xf7, 0x5a, 0x13, 0x91, 0x1a, 0x04, 0x00, 0x34,
|
||||
0xa8, 0x02, 0x40, 0xb9, 0x1f, 0x09, 0x00, 0x71, 0xa0, 0x01, 0x00, 0x54, 0x1f, 0x2d, 0x00, 0x71, 0xa0, 0x01, 0x00,
|
||||
0x54, 0x1f, 0x65, 0x00, 0x71, 0x81, 0x01, 0x00, 0x54, 0xb8, 0x22, 0x00, 0x91, 0xe0, 0x03, 0x18, 0xaa, 0xe1, 0x03,
|
||||
0x16, 0xaa, 0xaa, 0x00, 0x00, 0x94, 0x80, 0x01, 0x00, 0x34, 0xb3, 0xa2, 0x41, 0xa9, 0xe8, 0x0b, 0x00, 0xf9, 0x04,
|
||||
0x00, 0x00, 0x14, 0xfc, 0x03, 0x15, 0xaa, 0x02, 0x00, 0x00, 0x14, 0xfb, 0x03, 0x15, 0xaa, 0xa8, 0x06, 0x40, 0xb9,
|
||||
0xb5, 0x02, 0x08, 0x8b, 0x5a, 0x07, 0x00, 0x51, 0x7a, 0xfd, 0xff, 0x35, 0x09, 0x00, 0x00, 0x14, 0xe0, 0x03, 0x18,
|
||||
0xaa, 0xe1, 0x03, 0x17, 0xaa, 0x9b, 0x00, 0x00, 0x94, 0x00, 0xff, 0xff, 0x34, 0xa8, 0x0e, 0x40, 0xf9, 0xa9, 0x16,
|
||||
0x40, 0xf9, 0x19, 0x01, 0x09, 0xcb, 0xf4, 0xff, 0xff, 0x17, 0x88, 0x02, 0x13, 0xcb, 0x28, 0x03, 0x08, 0x8b, 0x89,
|
||||
0x0b, 0x40, 0xb9, 0x13, 0x01, 0x09, 0x8b, 0x89, 0x13, 0x40, 0xb9, 0x19, 0x01, 0x09, 0x8b, 0xe8, 0x07, 0x40, 0xf9,
|
||||
0xe8, 0x0f, 0x00, 0xf9, 0x16, 0x00, 0x00, 0x90, 0xd6, 0x72, 0x0f, 0x91, 0x35, 0x01, 0x80, 0x52, 0x78, 0x0b, 0x40,
|
||||
0xb9, 0x68, 0x0f, 0x40, 0xb9, 0x1f, 0x03, 0x08, 0x6b, 0xc0, 0x0a, 0x00, 0x54, 0x77, 0x52, 0x38, 0x8b, 0xe8, 0x02,
|
||||
0x40, 0xb9, 0x3c, 0x03, 0x08, 0x8b, 0xe0, 0x03, 0x1c, 0xaa, 0xe1, 0x03, 0x16, 0xaa, 0x6a, 0x00, 0x00, 0x94, 0xa0,
|
||||
0x07, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0xbc, 0x0f, 0x91, 0x65, 0x00, 0x00, 0x94,
|
||||
0x00, 0x07, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0xf8, 0x0f, 0x91, 0x60, 0x00, 0x00,
|
||||
0x94, 0x60, 0x06, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x54, 0x10, 0x91, 0x72, 0x00,
|
||||
0x00, 0x94, 0xc0, 0x05, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x8c, 0x10, 0x91, 0x6d,
|
||||
0x00, 0x00, 0x94, 0x20, 0x05, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0xf4, 0x10, 0x91,
|
||||
0x68, 0x00, 0x00, 0x94, 0x80, 0x04, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x40, 0x11,
|
||||
0x91, 0x4c, 0x00, 0x00, 0x94, 0xe0, 0x03, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x88,
|
||||
0x11, 0x91, 0x47, 0x00, 0x00, 0x94, 0x40, 0x03, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21,
|
||||
0xec, 0x11, 0x91, 0x42, 0x00, 0x00, 0x94, 0xa0, 0x02, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90,
|
||||
0x21, 0x44, 0x12, 0x91, 0x5c, 0x00, 0x00, 0x94, 0x00, 0x02, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00,
|
||||
0x90, 0x21, 0x64, 0x12, 0x91, 0x57, 0x00, 0x00, 0x94, 0x60, 0x01, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00,
|
||||
0x00, 0x90, 0x21, 0x84, 0x12, 0x91, 0x33, 0x00, 0x00, 0x94, 0xc0, 0x00, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01,
|
||||
0x00, 0x00, 0x90, 0x21, 0xd0, 0x12, 0x91, 0x2e, 0x00, 0x00, 0x94, 0x20, 0x02, 0x00, 0x34, 0xba, 0x00, 0x00, 0x34,
|
||||
0xe8, 0x0f, 0x40, 0xf9, 0x49, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe8, 0x06, 0x40,
|
||||
0xf9, 0x81, 0x02, 0x08, 0x8b, 0xe0, 0x63, 0x00, 0x91, 0x4c, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40, 0xf9, 0x15, 0x15,
|
||||
0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0xe1, 0x03, 0x1c, 0xaa, 0x5d, 0x00, 0x00, 0x94, 0x5a,
|
||||
0x07, 0x00, 0x11, 0x18, 0x07, 0x00, 0x11, 0xa9, 0xff, 0xff, 0x17, 0xe1, 0x23, 0x41, 0xa9, 0x49, 0x01, 0x80, 0x52,
|
||||
0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0x3d, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40,
|
||||
0xf9, 0x29, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0x01, 0x00, 0x00, 0x90, 0x21, 0x14,
|
||||
0x13, 0x91, 0xe0, 0x63, 0x00, 0x91, 0x4c, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40, 0xf9, 0xe9, 0x07, 0x40, 0xf9, 0x00,
|
||||
0x01, 0x09, 0xcb, 0x1f, 0x01, 0x00, 0x39, 0xfd, 0x7b, 0x47, 0xa9, 0xf4, 0x4f, 0x46, 0xa9, 0xf6, 0x57, 0x45, 0xa9,
|
||||
0xf8, 0x5f, 0x44, 0xa9, 0xfa, 0x67, 0x43, 0xa9, 0xfc, 0x6f, 0x42, 0xa9, 0xff, 0x03, 0x02, 0x91, 0xc0, 0x03, 0x5f,
|
||||
0xd6, 0xf6, 0x57, 0xbd, 0xa9, 0xf4, 0x4f, 0x01, 0xa9, 0xfd, 0x7b, 0x02, 0xa9, 0xfd, 0x83, 0x00, 0x91, 0xf3, 0x03,
|
||||
0x01, 0xaa, 0xf4, 0x03, 0x00, 0xaa, 0x35, 0x00, 0x40, 0x39, 0x96, 0x02, 0x40, 0x39, 0x36, 0x01, 0x00, 0x34, 0xdf,
|
||||
0x02, 0x15, 0x6b, 0xa1, 0x00, 0x00, 0x54, 0xe0, 0x03, 0x14, 0xaa, 0xe1, 0x03, 0x13, 0xaa, 0x12, 0x00, 0x00, 0x94,
|
||||
0x60, 0x00, 0x00, 0x37, 0x94, 0x06, 0x00, 0x91, 0xf7, 0xff, 0xff, 0x17, 0xdf, 0x02, 0x00, 0x71, 0xe0, 0x07, 0x9f,
|
||||
0x1a, 0xfd, 0x7b, 0x42, 0xa9, 0xf4, 0x4f, 0x41, 0xa9, 0xf6, 0x57, 0xc3, 0xa8, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x14,
|
||||
0x40, 0x38, 0x29, 0x14, 0x40, 0x38, 0x1f, 0x01, 0x00, 0x71, 0x00, 0x11, 0x49, 0x7a, 0x80, 0xff, 0xff, 0x54, 0x1f,
|
||||
0x01, 0x09, 0x6b, 0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03, 0x5f, 0xd6, 0x28, 0x00, 0x40, 0x39, 0xa8, 0x00, 0x00, 0x34,
|
||||
0x21, 0x04, 0x00, 0x91, 0x09, 0x14, 0x40, 0x38, 0x3f, 0x01, 0x08, 0x6b, 0x60, 0xff, 0xff, 0x54, 0x1f, 0x01, 0x00,
|
||||
0x71, 0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03, 0x5f, 0xd6, 0x09, 0x00, 0x80, 0x52, 0x08, 0x00, 0x40, 0xf9, 0x8a, 0x07,
|
||||
0x80, 0x52, 0x0b, 0x00, 0x00, 0x90, 0x6b, 0xc1, 0x13, 0x91, 0x5f, 0x11, 0x00, 0x31, 0x80, 0x01, 0x00, 0x54, 0x2c,
|
||||
0x24, 0xca, 0x9a, 0x8c, 0x0d, 0x40, 0x92, 0x2d, 0x01, 0x00, 0x12, 0x9f, 0x01, 0x00, 0x71, 0xa0, 0x19, 0x40, 0x7a,
|
||||
0x29, 0x15, 0x9f, 0x1a, 0x69, 0x00, 0x00, 0x36, 0x6c, 0x69, 0x6c, 0x38, 0x0c, 0x15, 0x00, 0x38, 0x4a, 0x11, 0x00,
|
||||
0x51, 0xf4, 0xff, 0xff, 0x17, 0x69, 0x00, 0x00, 0x37, 0x09, 0x06, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0x08, 0x00,
|
||||
0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x00, 0x40, 0xf9, 0x29, 0x00, 0x40, 0x39, 0x89, 0x00, 0x00, 0x34, 0x21,
|
||||
0x04, 0x00, 0x91, 0x09, 0x15, 0x00, 0x38, 0xfc, 0xff, 0xff, 0x17, 0x08, 0x00, 0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6,
|
||||
0x6c, 0x69, 0x62, 0x64, 0x79, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x00,
|
||||
0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4f, 0x62, 0x6a, 0x43, 0x49, 0x6e, 0x69, 0x74, 0x00, 0x72, 0x65, 0x73, 0x74,
|
||||
0x61, 0x72, 0x74, 0x57, 0x69, 0x74, 0x68, 0x44, 0x79, 0x6c, 0x64, 0x49, 0x6e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x00,
|
||||
0x5f, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x00, 0x5f, 0x5f, 0x5a, 0x4e, 0x35,
|
||||
0x64, 0x79, 0x6c, 0x64, 0x34, 0x31, 0x32, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f,
|
||||
0x45, 0x00, 0x5f, 0x5f, 0x5a, 0x4c, 0x31, 0x32, 0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66,
|
||||
0x6f, 0x00, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x6f, 0x73, 0x75, 0x72, 0x65,
|
||||
0x00, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4d, 0x61, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63,
|
||||
0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x54, 0x68, 0x72, 0x65,
|
||||
0x61, 0x64, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x73, 0x00, 0x5f, 0x64, 0x6c, 0x6f, 0x70, 0x65, 0x6e, 0x00, 0x5f,
|
||||
0x73, 0x74, 0x72, 0x63, 0x6d, 0x70, 0x00, 0x64, 0x6f, 0x4d, 0x6f, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x46, 0x75, 0x6e,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x64, 0x6f, 0x47, 0x65, 0x74, 0x44, 0x4f, 0x46, 0x53, 0x65, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x00, 0x64, 0x79, 0x6c, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x5f, 0x5f, 0x54, 0x45,
|
||||
0x58, 0x54, 0x00, 0x5f, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x45, 0x44, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
|
||||
0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
|
||||
0xa9, 0xf4, 0x4f, 0x06, 0xa9, 0xfd, 0x7b, 0x07, 0xa9, 0xfd, 0xc3, 0x01, 0x91, 0xf4, 0x03, 0x01, 0xaa, 0xe0, 0x0b,
|
||||
0x00, 0xf9, 0x13, 0x00, 0x80, 0xd2, 0x15, 0x00, 0x80, 0xd2, 0x38, 0x80, 0x00, 0x91, 0x39, 0x10, 0x40, 0xb9, 0x16,
|
||||
0x00, 0x00, 0x90, 0xd6, 0x1e, 0x13, 0x91, 0x1a, 0x00, 0x00, 0x90, 0x5a, 0x3b, 0x13, 0x91, 0xd9, 0x03, 0x00, 0x34,
|
||||
0x08, 0x03, 0x40, 0xb9, 0x1f, 0x09, 0x00, 0x71, 0xa0, 0x01, 0x00, 0x54, 0x1f, 0x2d, 0x00, 0x71, 0x20, 0x01, 0x00,
|
||||
0x54, 0x1f, 0x65, 0x00, 0x71, 0x41, 0x01, 0x00, 0x54, 0x00, 0x23, 0x00, 0x91, 0xe1, 0x03, 0x16, 0xaa, 0xa4, 0x00,
|
||||
0x00, 0x94, 0x60, 0x01, 0x00, 0x34, 0x13, 0xef, 0x41, 0xa9, 0x04, 0x00, 0x00, 0x14, 0xfc, 0x03, 0x18, 0xaa, 0x02,
|
||||
0x00, 0x00, 0x14, 0xf7, 0x03, 0x18, 0xaa, 0x08, 0x07, 0x40, 0xb9, 0x18, 0x03, 0x08, 0x8b, 0x39, 0x07, 0x00, 0x51,
|
||||
0xb9, 0xfd, 0xff, 0x35, 0x09, 0x00, 0x00, 0x14, 0x00, 0x23, 0x00, 0x91, 0xe1, 0x03, 0x1a, 0xaa, 0x96, 0x00, 0x00,
|
||||
0x94, 0x00, 0xff, 0xff, 0x34, 0x08, 0x0f, 0x40, 0xf9, 0x09, 0x17, 0x40, 0xf9, 0x15, 0x01, 0x09, 0xcb, 0xf4, 0xff,
|
||||
0xff, 0x17, 0xfb, 0x07, 0x00, 0xf9, 0x1b, 0x00, 0x80, 0x52, 0x88, 0x02, 0x13, 0xcb, 0xa8, 0x02, 0x08, 0x8b, 0xe9,
|
||||
0x0a, 0x40, 0xb9, 0x1a, 0x01, 0x09, 0x8b, 0xe9, 0x12, 0x40, 0xb9, 0x13, 0x01, 0x09, 0x8b, 0xe8, 0x0b, 0x40, 0xf9,
|
||||
0xe8, 0x0f, 0x00, 0xf9, 0x16, 0x00, 0x00, 0x90, 0xd6, 0x52, 0x0f, 0x91, 0x39, 0x01, 0x80, 0x52, 0x95, 0x0b, 0x40,
|
||||
0xb9, 0x88, 0x0f, 0x40, 0xb9, 0xbf, 0x02, 0x08, 0x6b, 0x40, 0x0a, 0x00, 0x54, 0x58, 0x53, 0x35, 0x8b, 0x17, 0x03,
|
||||
0x40, 0xb9, 0x60, 0x02, 0x17, 0x8b, 0xe1, 0x03, 0x16, 0xaa, 0x64, 0x00, 0x00, 0x94, 0xa0, 0x07, 0x00, 0x37, 0x60,
|
||||
0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0x9c, 0x0f, 0x91, 0x5f, 0x00, 0x00, 0x94, 0x00, 0x07, 0x00, 0x37,
|
||||
0x60, 0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0xd8, 0x0f, 0x91, 0x5a, 0x00, 0x00, 0x94, 0x60, 0x06, 0x00,
|
||||
0x37, 0x60, 0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0x34, 0x10, 0x91, 0x6c, 0x00, 0x00, 0x94, 0xc0, 0x05,
|
||||
0x00, 0x37, 0x60, 0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0x6c, 0x10, 0x91, 0x67, 0x00, 0x00, 0x94, 0x20,
|
||||
0x05, 0x00, 0x37, 0x60, 0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0xd4, 0x10, 0x91, 0x62, 0x00, 0x00, 0x94,
|
||||
0x80, 0x04, 0x00, 0x37, 0x60, 0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0x20, 0x11, 0x91, 0x46, 0x00, 0x00,
|
||||
0x94, 0xe0, 0x03, 0x00, 0x37, 0x60, 0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0x68, 0x11, 0x91, 0x41, 0x00,
|
||||
0x00, 0x94, 0x40, 0x03, 0x00, 0x37, 0x60, 0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0xcc, 0x11, 0x91, 0x3c,
|
||||
0x00, 0x00, 0x94, 0xa0, 0x02, 0x00, 0x37, 0x60, 0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0x24, 0x12, 0x91,
|
||||
0x56, 0x00, 0x00, 0x94, 0x00, 0x02, 0x00, 0x37, 0x60, 0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0x44, 0x12,
|
||||
0x91, 0x51, 0x00, 0x00, 0x94, 0x60, 0x01, 0x00, 0x37, 0x60, 0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0x64,
|
||||
0x12, 0x91, 0x2d, 0x00, 0x00, 0x94, 0xc0, 0x00, 0x00, 0x37, 0x60, 0x02, 0x17, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21,
|
||||
0xb0, 0x12, 0x91, 0x28, 0x00, 0x00, 0x94, 0xc0, 0x01, 0x00, 0x34, 0x5b, 0x00, 0x00, 0x34, 0x6c, 0x00, 0x00, 0x94,
|
||||
0x08, 0x07, 0x40, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0x81, 0x02, 0x08, 0x8b, 0x49, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40,
|
||||
0xf9, 0x19, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0x61, 0x02, 0x17, 0x8b, 0x5a, 0x00,
|
||||
0x00, 0x94, 0x7b, 0x07, 0x00, 0x11, 0xb5, 0x06, 0x00, 0x11, 0xad, 0xff, 0xff, 0x17, 0x5e, 0x00, 0x00, 0x94, 0xe0,
|
||||
0x63, 0x00, 0x91, 0xe1, 0x07, 0x40, 0xf9, 0x3c, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40, 0xf9, 0x29, 0x01, 0x80, 0x52,
|
||||
0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0x01, 0x00, 0x00, 0x90, 0x21, 0xf4, 0x12, 0x91, 0xe0, 0x63, 0x00,
|
||||
0x91, 0x4b, 0x00, 0x00, 0x94, 0xe9, 0x23, 0x41, 0xa9, 0x00, 0x01, 0x09, 0xcb, 0x1f, 0x01, 0x00, 0x39, 0xfd, 0x7b,
|
||||
0x47, 0xa9, 0xf4, 0x4f, 0x46, 0xa9, 0xf6, 0x57, 0x45, 0xa9, 0xf8, 0x5f, 0x44, 0xa9, 0xfa, 0x67, 0x43, 0xa9, 0xfc,
|
||||
0x6f, 0x42, 0xa9, 0xff, 0x03, 0x02, 0x91, 0xc0, 0x03, 0x5f, 0xd6, 0xf6, 0x57, 0xbd, 0xa9, 0xf4, 0x4f, 0x01, 0xa9,
|
||||
0xfd, 0x7b, 0x02, 0xa9, 0xfd, 0x83, 0x00, 0x91, 0xf3, 0x03, 0x01, 0xaa, 0xf4, 0x03, 0x00, 0xaa, 0x35, 0x00, 0x40,
|
||||
0x39, 0x96, 0x02, 0x40, 0x39, 0x36, 0x01, 0x00, 0x34, 0xdf, 0x02, 0x15, 0x6b, 0xa1, 0x00, 0x00, 0x54, 0xe0, 0x03,
|
||||
0x14, 0xaa, 0xe1, 0x03, 0x13, 0xaa, 0x12, 0x00, 0x00, 0x94, 0x60, 0x00, 0x00, 0x37, 0x94, 0x06, 0x00, 0x91, 0xf7,
|
||||
0xff, 0xff, 0x17, 0xdf, 0x02, 0x00, 0x71, 0xe0, 0x07, 0x9f, 0x1a, 0xfd, 0x7b, 0x42, 0xa9, 0xf4, 0x4f, 0x41, 0xa9,
|
||||
0xf6, 0x57, 0xc3, 0xa8, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x14, 0x40, 0x38, 0x29, 0x14, 0x40, 0x38, 0x1f, 0x01, 0x00,
|
||||
0x71, 0x00, 0x11, 0x49, 0x7a, 0x80, 0xff, 0xff, 0x54, 0x1f, 0x01, 0x09, 0x6b, 0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03,
|
||||
0x5f, 0xd6, 0x28, 0x00, 0x40, 0x39, 0xa8, 0x00, 0x00, 0x34, 0x21, 0x04, 0x00, 0x91, 0x09, 0x14, 0x40, 0x38, 0x3f,
|
||||
0x01, 0x08, 0x6b, 0x60, 0xff, 0xff, 0x54, 0x1f, 0x01, 0x00, 0x71, 0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03, 0x5f, 0xd6,
|
||||
0x09, 0x00, 0x80, 0x52, 0x08, 0x00, 0x40, 0xf9, 0x8a, 0x07, 0x80, 0x52, 0x0b, 0x00, 0x00, 0x90, 0x6b, 0x81, 0x13,
|
||||
0x91, 0x5f, 0x11, 0x00, 0x31, 0x80, 0x01, 0x00, 0x54, 0x2c, 0x24, 0xca, 0x9a, 0x8c, 0x0d, 0x40, 0xf2, 0xed, 0x17,
|
||||
0x9f, 0x1a, 0x2d, 0x01, 0x0d, 0x2a, 0xbf, 0x01, 0x00, 0x72, 0x29, 0x15, 0x9f, 0x1a, 0x69, 0x00, 0x00, 0x36, 0x6c,
|
||||
0x69, 0x6c, 0x38, 0x0c, 0x15, 0x00, 0x38, 0x4a, 0x11, 0x00, 0x51, 0xf4, 0xff, 0xff, 0x17, 0x69, 0x00, 0x00, 0x37,
|
||||
0x09, 0x06, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0x08, 0x00, 0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x00, 0x40,
|
||||
0xf9, 0x29, 0x00, 0x40, 0x39, 0x89, 0x00, 0x00, 0x34, 0x21, 0x04, 0x00, 0x91, 0x09, 0x15, 0x00, 0x38, 0xfc, 0xff,
|
||||
0xff, 0x17, 0x08, 0x00, 0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0xe8, 0x0f, 0x40, 0xf9, 0x49, 0x01, 0x80, 0x52, 0x09,
|
||||
0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0x6c, 0x69, 0x62, 0x64, 0x79, 0x6c, 0x64, 0x5f,
|
||||
0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x00, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4f, 0x62,
|
||||
0x6a, 0x43, 0x49, 0x6e, 0x69, 0x74, 0x00, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x57, 0x69, 0x74, 0x68, 0x44,
|
||||
0x79, 0x6c, 0x64, 0x49, 0x6e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x00, 0x5f, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
|
||||
0x73, 0x49, 0x6e, 0x66, 0x6f, 0x00, 0x5f, 0x5f, 0x5a, 0x4e, 0x35, 0x64, 0x79, 0x6c, 0x64, 0x34, 0x31, 0x32, 0x67,
|
||||
0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x00, 0x5f, 0x5f, 0x5a, 0x4c, 0x31, 0x32,
|
||||
0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x00, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68,
|
||||
0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x6f, 0x73, 0x75, 0x72, 0x65, 0x00, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c,
|
||||
0x69, 0x7a, 0x65, 0x4d, 0x61, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x72,
|
||||
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72,
|
||||
0x73, 0x00, 0x5f, 0x64, 0x6c, 0x6f, 0x70, 0x65, 0x6e, 0x00, 0x5f, 0x73, 0x74, 0x72, 0x63, 0x6d, 0x70, 0x00, 0x64,
|
||||
0x6f, 0x4d, 0x6f, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x64,
|
||||
0x6f, 0x47, 0x65, 0x74, 0x44, 0x4f, 0x46, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x64, 0x79, 0x6c,
|
||||
0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x5f, 0x5f, 0x4c, 0x49, 0x4e,
|
||||
0x4b, 0x45, 0x44, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
|
||||
0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
|
||||
};
|
||||
|
||||
private async SymbolSet resolve_symbols (SymbolQuery query, Cancellable? cancellable) throws GLib.Error {
|
||||
@@ -1343,52 +1384,52 @@ namespace Frida.Fruity.Injector {
|
||||
private const uint8[] SYMBOL_RESOLVER_CODE = {
|
||||
0xff, 0xc3, 0x01, 0xd1, 0xfc, 0x6f, 0x01, 0xa9, 0xfa, 0x67, 0x02, 0xa9, 0xf8, 0x5f, 0x03, 0xa9, 0xf6, 0x57, 0x04,
|
||||
0xa9, 0xf4, 0x4f, 0x05, 0xa9, 0xfd, 0x7b, 0x06, 0xa9, 0xfd, 0x83, 0x01, 0x91, 0xf5, 0x03, 0x02, 0xaa, 0xf3, 0x03,
|
||||
0x01, 0xaa, 0xf4, 0x03, 0x00, 0xaa, 0x08, 0x00, 0x80, 0xd2, 0x49, 0x04, 0x40, 0xb9, 0x0a, 0x03, 0x80, 0x52, 0xeb,
|
||||
0x07, 0x7d, 0xb2, 0x37, 0x2d, 0x0a, 0x9b, 0x76, 0x19, 0x00, 0x30, 0x1f, 0x20, 0x03, 0xd5, 0x18, 0x61, 0x00, 0x91,
|
||||
0x01, 0xaa, 0xf4, 0x03, 0x00, 0xaa, 0x08, 0x00, 0x80, 0xd2, 0x49, 0x04, 0x40, 0xb9, 0x0a, 0x03, 0x80, 0x52, 0x29,
|
||||
0x7d, 0xaa, 0x9b, 0x37, 0x61, 0x00, 0x91, 0x16, 0x00, 0x00, 0x90, 0xd6, 0xa6, 0x0d, 0x91, 0x18, 0x61, 0x00, 0x91,
|
||||
0xff, 0x02, 0x18, 0xeb, 0x60, 0x01, 0x00, 0x54, 0xb9, 0x06, 0x40, 0xf9, 0x28, 0x03, 0x08, 0x8b, 0x00, 0x05, 0x40,
|
||||
0xf9, 0xe1, 0x03, 0x16, 0xaa, 0xad, 0x00, 0x00, 0x94, 0xe8, 0x03, 0x18, 0xaa, 0xe0, 0xfe, 0xff, 0x34, 0x28, 0x03,
|
||||
0x18, 0x8b, 0x08, 0x81, 0x5e, 0xf8, 0x02, 0x00, 0x00, 0x14, 0x08, 0x00, 0x80, 0xd2, 0x19, 0x00, 0x80, 0xd2, 0xe8,
|
||||
0x7f, 0x00, 0xa9, 0x16, 0x00, 0x80, 0xd2, 0x1b, 0x00, 0x80, 0xd2, 0x1c, 0x81, 0x00, 0x91, 0x1a, 0x11, 0x40, 0xb9,
|
||||
0x58, 0x04, 0x80, 0x52, 0x18, 0x00, 0xb0, 0x72, 0x75, 0x06, 0x80, 0x52, 0x15, 0x00, 0xb0, 0x72, 0x5a, 0x04, 0x00,
|
||||
0x34, 0x88, 0x03, 0x40, 0xb9, 0x1f, 0x01, 0x18, 0x6b, 0xa0, 0x01, 0x00, 0x54, 0x1f, 0x01, 0x15, 0x6b, 0xa0, 0x01,
|
||||
0x00, 0x54, 0x1f, 0x65, 0x00, 0x71, 0x81, 0x01, 0x00, 0x54, 0x97, 0x23, 0x00, 0x91, 0xe0, 0x03, 0x17, 0xaa, 0x41,
|
||||
0x14, 0x00, 0x70, 0x1f, 0x20, 0x03, 0xd5, 0x90, 0x00, 0x00, 0x94, 0x60, 0x01, 0x00, 0x34, 0x99, 0x0f, 0x40, 0xf9,
|
||||
0x04, 0x00, 0x00, 0x14, 0xf6, 0x03, 0x1c, 0xaa, 0x02, 0x00, 0x00, 0x14, 0xfb, 0x03, 0x1c, 0xaa, 0x88, 0x07, 0x40,
|
||||
0xb9, 0x9c, 0x03, 0x08, 0x8b, 0x5a, 0x07, 0x00, 0x51, 0x7a, 0xfd, 0xff, 0x35, 0x0b, 0x00, 0x00, 0x14, 0xe0, 0x03,
|
||||
0x17, 0xaa, 0xa1, 0x12, 0x00, 0x50, 0x1f, 0x20, 0x03, 0xd5, 0x81, 0x00, 0x00, 0x94, 0xe0, 0xfe, 0xff, 0x34, 0x88,
|
||||
0xf9, 0xe1, 0x03, 0x16, 0xaa, 0xaf, 0x00, 0x00, 0x94, 0xe8, 0x03, 0x18, 0xaa, 0xe0, 0xfe, 0xff, 0x34, 0x28, 0x03,
|
||||
0x18, 0x8b, 0x08, 0x81, 0x5e, 0xf8, 0x02, 0x00, 0x00, 0x14, 0x08, 0x00, 0x80, 0xd2, 0x18, 0x00, 0x80, 0xd2, 0xe8,
|
||||
0x7f, 0x00, 0xa9, 0x1a, 0x00, 0x80, 0xd2, 0x1b, 0x00, 0x80, 0xd2, 0x1c, 0x81, 0x00, 0x91, 0x16, 0x11, 0x40, 0xb9,
|
||||
0x59, 0x04, 0x80, 0x52, 0x19, 0x00, 0xb0, 0x72, 0x77, 0x06, 0x80, 0x52, 0x17, 0x00, 0xb0, 0x72, 0x15, 0x00, 0x00,
|
||||
0x90, 0xb5, 0x5e, 0x0d, 0x91, 0x16, 0x04, 0x00, 0x34, 0x88, 0x03, 0x40, 0xb9, 0x1f, 0x01, 0x19, 0x6b, 0xa0, 0x01,
|
||||
0x00, 0x54, 0x1f, 0x01, 0x17, 0x6b, 0x20, 0x01, 0x00, 0x54, 0x1f, 0x65, 0x00, 0x71, 0x41, 0x01, 0x00, 0x54, 0x80,
|
||||
0x23, 0x00, 0x91, 0xe1, 0x03, 0x15, 0xaa, 0x92, 0x00, 0x00, 0x94, 0x60, 0x01, 0x00, 0x34, 0x98, 0x0f, 0x40, 0xf9,
|
||||
0x04, 0x00, 0x00, 0x14, 0xfb, 0x03, 0x1c, 0xaa, 0x02, 0x00, 0x00, 0x14, 0xfa, 0x03, 0x1c, 0xaa, 0x88, 0x07, 0x40,
|
||||
0xb9, 0x9c, 0x03, 0x08, 0x8b, 0xd6, 0x06, 0x00, 0x51, 0xb6, 0xfd, 0xff, 0x35, 0x0b, 0x00, 0x00, 0x14, 0x80, 0x23,
|
||||
0x00, 0x91, 0x01, 0x00, 0x00, 0x90, 0x21, 0x78, 0x0d, 0x91, 0x83, 0x00, 0x00, 0x94, 0xe0, 0xfe, 0xff, 0x34, 0x88,
|
||||
0x0f, 0x40, 0xf9, 0x89, 0x17, 0x40, 0xf9, 0x08, 0x01, 0x09, 0xcb, 0xe8, 0x07, 0x00, 0xf9, 0xf2, 0xff, 0xff, 0x17,
|
||||
0x96, 0x00, 0x00, 0xb4, 0xc8, 0xa2, 0x00, 0x91, 0xf7, 0x03, 0x40, 0xf9, 0x04, 0x00, 0x00, 0x14, 0xf7, 0x03, 0x40,
|
||||
0xf9, 0xbb, 0x05, 0x00, 0xb4, 0x68, 0x23, 0x00, 0x91, 0xe9, 0x02, 0x19, 0xcb, 0xea, 0x07, 0x40, 0xf9, 0x49, 0x01,
|
||||
0x09, 0x8b, 0x08, 0x01, 0x40, 0xb9, 0x35, 0x01, 0x08, 0x8b, 0x61, 0x0f, 0x00, 0x10, 0x1f, 0x20, 0x03, 0xd5, 0xe0,
|
||||
0x03, 0x15, 0xaa, 0x31, 0x00, 0x00, 0x94, 0xf6, 0x02, 0x00, 0x8b, 0x01, 0x0f, 0x00, 0x10, 0x1f, 0x20, 0x03, 0xd5,
|
||||
0x9a, 0x00, 0x00, 0xb4, 0x48, 0xa3, 0x00, 0x91, 0xf7, 0x03, 0x40, 0xf9, 0x04, 0x00, 0x00, 0x14, 0xf7, 0x03, 0x40,
|
||||
0xf9, 0xbb, 0x05, 0x00, 0xb4, 0x68, 0x23, 0x00, 0x91, 0xe9, 0x02, 0x18, 0xcb, 0xea, 0x07, 0x40, 0xf9, 0x49, 0x01,
|
||||
0x09, 0x8b, 0x08, 0x01, 0x40, 0xb9, 0x35, 0x01, 0x08, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0x20, 0x0d, 0x91, 0xe0,
|
||||
0x03, 0x15, 0xaa, 0x31, 0x00, 0x00, 0x94, 0xf6, 0x02, 0x00, 0x8b, 0x01, 0x00, 0x00, 0x90, 0x21, 0x40, 0x0d, 0x91,
|
||||
0xe0, 0x03, 0x15, 0xaa, 0x2c, 0x00, 0x00, 0x94, 0xf7, 0x02, 0x00, 0x8b, 0x80, 0x02, 0x40, 0xf9, 0x60, 0x02, 0x00,
|
||||
0xb4, 0x21, 0x01, 0x80, 0x52, 0xc0, 0x02, 0x3f, 0xd6, 0x40, 0x01, 0x00, 0xb4, 0xf5, 0x03, 0x00, 0xaa, 0x94, 0x42,
|
||||
0x00, 0x91, 0x81, 0x82, 0x5f, 0xf8, 0x01, 0xff, 0xff, 0xb4, 0xe0, 0x03, 0x15, 0xaa, 0xe0, 0x02, 0x3f, 0xd6, 0x60,
|
||||
0x86, 0x00, 0xf8, 0x94, 0x22, 0x00, 0x91, 0xfa, 0xff, 0xff, 0x17, 0x94, 0x42, 0x00, 0x91, 0x88, 0x82, 0x5f, 0xf8,
|
||||
0x08, 0xfe, 0xff, 0xb4, 0x7f, 0x86, 0x00, 0xf8, 0x94, 0x22, 0x00, 0x91, 0xfc, 0xff, 0xff, 0x17, 0xfd, 0x7b, 0x46,
|
||||
0xa9, 0xf4, 0x4f, 0x45, 0xa9, 0xf6, 0x57, 0x44, 0xa9, 0xf8, 0x5f, 0x43, 0xa9, 0xfa, 0x67, 0x42, 0xa9, 0xfc, 0x6f,
|
||||
0x41, 0xa9, 0xff, 0xc3, 0x01, 0x91, 0xc0, 0x03, 0x5f, 0xd6, 0x15, 0x00, 0x80, 0xd2, 0xd9, 0xff, 0xff, 0x17, 0xe8,
|
||||
0x03, 0x00, 0xaa, 0x0a, 0x00, 0x80, 0xd2, 0x00, 0x00, 0x80, 0xd2, 0x09, 0x01, 0x40, 0xf9, 0x2b, 0x15, 0x40, 0x38,
|
||||
0x6c, 0x19, 0x40, 0x92, 0x8c, 0x21, 0xca, 0x9a, 0x80, 0x01, 0x00, 0xaa, 0x4a, 0x1d, 0x00, 0x91, 0x6b, 0xff, 0x3f,
|
||||
0x37, 0x09, 0x01, 0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0xff, 0x43, 0x01, 0xd1, 0xf8, 0x5f, 0x01, 0xa9, 0xf6, 0x57,
|
||||
0x41, 0xa9, 0xff, 0xc3, 0x01, 0x91, 0xc0, 0x03, 0x5f, 0xd6, 0x15, 0x00, 0x80, 0xd2, 0xd9, 0xff, 0xff, 0x17, 0x09,
|
||||
0x00, 0x80, 0xd2, 0x08, 0x00, 0x80, 0xd2, 0x0a, 0x00, 0x40, 0xf9, 0x4b, 0x15, 0x40, 0x38, 0x6c, 0x19, 0x40, 0x92,
|
||||
0x8c, 0x21, 0xc9, 0x9a, 0x88, 0x01, 0x08, 0xaa, 0x29, 0x1d, 0x00, 0x91, 0x6b, 0xff, 0x3f, 0x37, 0x0a, 0x00, 0x00,
|
||||
0xf9, 0xe0, 0x03, 0x08, 0xaa, 0xc0, 0x03, 0x5f, 0xd6, 0xff, 0x43, 0x01, 0xd1, 0xf8, 0x5f, 0x01, 0xa9, 0xf6, 0x57,
|
||||
0x02, 0xa9, 0xf4, 0x4f, 0x03, 0xa9, 0xfd, 0x7b, 0x04, 0xa9, 0xfd, 0x03, 0x01, 0x91, 0xf4, 0x03, 0x01, 0xaa, 0xf3,
|
||||
0x03, 0x00, 0xaa, 0xe8, 0x03, 0x00, 0xaa, 0xe8, 0x07, 0x00, 0xf9, 0xc8, 0x04, 0x00, 0xb4, 0x3a, 0x00, 0x00, 0x94,
|
||||
0x60, 0x00, 0x00, 0xb4, 0x88, 0x02, 0x40, 0x39, 0x88, 0x04, 0x00, 0x34, 0x15, 0x00, 0x80, 0x52, 0xe8, 0x07, 0x40,
|
||||
0xf9, 0x08, 0x01, 0x00, 0x8b, 0x16, 0x15, 0x40, 0x38, 0xe8, 0x07, 0x00, 0xf9, 0xdf, 0x02, 0x35, 0x6b, 0xc0, 0x02,
|
||||
0x03, 0x00, 0xaa, 0xe8, 0x03, 0x00, 0xaa, 0xe8, 0x07, 0x00, 0xf9, 0x08, 0x05, 0x00, 0xb4, 0x39, 0x00, 0x00, 0x94,
|
||||
0x88, 0x02, 0x40, 0x39, 0x48, 0x00, 0x00, 0x35, 0xc0, 0x04, 0x00, 0xb5, 0x15, 0x00, 0x80, 0x52, 0xe8, 0x07, 0x40,
|
||||
0xf9, 0x08, 0x01, 0x00, 0x8b, 0x16, 0x15, 0x40, 0x38, 0xe8, 0x07, 0x00, 0xf9, 0xdf, 0x02, 0x35, 0x6b, 0xa0, 0x02,
|
||||
0x00, 0x54, 0xe8, 0x07, 0x40, 0xf9, 0x08, 0x05, 0x00, 0x91, 0x38, 0x00, 0x80, 0x52, 0xf7, 0x03, 0x14, 0xaa, 0x09,
|
||||
0xf1, 0x5f, 0x38, 0x49, 0x01, 0x00, 0x34, 0xb8, 0x00, 0x00, 0x36, 0xea, 0x16, 0xc0, 0x38, 0x3f, 0x01, 0x0a, 0x6b,
|
||||
0xf8, 0x17, 0x9f, 0x1a, 0x02, 0x00, 0x00, 0x14, 0x18, 0x00, 0x80, 0x52, 0xe8, 0x07, 0x00, 0xf9, 0x08, 0x05, 0x00,
|
||||
0x91, 0xf6, 0xff, 0xff, 0x17, 0xe8, 0x07, 0x00, 0xf9, 0x1f, 0x00, 0x00, 0x94, 0xb5, 0x06, 0x00, 0x11, 0x98, 0xfd,
|
||||
0x07, 0x36, 0xf4, 0x03, 0x17, 0xaa, 0x02, 0x00, 0x00, 0x14, 0x00, 0x00, 0x80, 0xd2, 0x68, 0x02, 0x00, 0x8b, 0x1f,
|
||||
0x00, 0x00, 0xf1, 0xe8, 0x03, 0x88, 0x9a, 0xda, 0xff, 0xff, 0x17, 0x00, 0x00, 0x80, 0xd2, 0x03, 0x00, 0x00, 0x14,
|
||||
0x13, 0x00, 0x00, 0x94, 0x12, 0x00, 0x00, 0x94, 0xfd, 0x7b, 0x44, 0xa9, 0xf4, 0x4f, 0x43, 0xa9, 0xf6, 0x57, 0x42,
|
||||
0xa9, 0xf8, 0x5f, 0x41, 0xa9, 0xff, 0x43, 0x01, 0x91, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x00, 0x40, 0x39, 0x29, 0x00,
|
||||
0x40, 0x39, 0x1f, 0x01, 0x09, 0x6b, 0xc1, 0x00, 0x00, 0x54, 0x00, 0x04, 0x00, 0x91, 0x21, 0x04, 0x00, 0x91, 0x48,
|
||||
0xff, 0xff, 0x35, 0x20, 0x00, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6, 0x00, 0x00, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6,
|
||||
0xe0, 0x23, 0x00, 0x91, 0xae, 0xff, 0xff, 0x17, 0x5f, 0x64, 0x6c, 0x6f, 0x70, 0x65, 0x6e, 0x00, 0x5f, 0x64, 0x6c,
|
||||
0x73, 0x79, 0x6d, 0x00, 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x5f, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x45, 0x44,
|
||||
0x49, 0x54, 0x00, 0x2f, 0x75, 0x73, 0x72, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2f,
|
||||
0x6c, 0x69, 0x62, 0x64, 0x79, 0x6c, 0x64, 0x2e, 0x64, 0x79, 0x6c, 0x69, 0x62, 0x00
|
||||
0x91, 0xf6, 0xff, 0xff, 0x17, 0xe8, 0x07, 0x00, 0xf9, 0x1e, 0x00, 0x00, 0x94, 0xb8, 0x00, 0x00, 0x37, 0xb5, 0x06,
|
||||
0x00, 0x11, 0xeb, 0xff, 0xff, 0x17, 0xf7, 0x03, 0x14, 0xaa, 0x04, 0x00, 0x00, 0x14, 0x68, 0x02, 0x00, 0x8b, 0xf4,
|
||||
0x03, 0x17, 0xaa, 0x60, 0xfb, 0xff, 0xb5, 0x08, 0x00, 0x80, 0xd2, 0xf4, 0x03, 0x17, 0xaa, 0xd8, 0xff, 0xff, 0x17,
|
||||
0x00, 0x00, 0x80, 0xd2, 0x03, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, 0x94, 0x0f, 0x00, 0x00, 0x94, 0xfd, 0x7b, 0x44,
|
||||
0xa9, 0xf4, 0x4f, 0x43, 0xa9, 0xf6, 0x57, 0x42, 0xa9, 0xf8, 0x5f, 0x41, 0xa9, 0xff, 0x43, 0x01, 0x91, 0xc0, 0x03,
|
||||
0x5f, 0xd6, 0x08, 0x14, 0x40, 0x38, 0x29, 0x14, 0x40, 0x38, 0x1f, 0x01, 0x00, 0x71, 0x00, 0x11, 0x49, 0x7a, 0x80,
|
||||
0xff, 0xff, 0x54, 0x1f, 0x01, 0x09, 0x6b, 0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03, 0x5f, 0xd6, 0xe0, 0x23, 0x00, 0x91,
|
||||
0xaf, 0xff, 0xff, 0x17, 0x5f, 0x64, 0x6c, 0x6f, 0x70, 0x65, 0x6e, 0x00, 0x5f, 0x64, 0x6c, 0x73, 0x79, 0x6d, 0x00,
|
||||
0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x5f, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x45, 0x44, 0x49, 0x54, 0x00, 0x2f,
|
||||
0x75, 0x73, 0x72, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2f, 0x6c, 0x69, 0x62, 0x64,
|
||||
0x79, 0x6c, 0x64, 0x2e, 0x64, 0x79, 0x6c, 0x69, 0x62, 0x00
|
||||
};
|
||||
|
||||
private string demangle (string symbol_name) {
|
||||
@@ -1470,7 +1511,7 @@ namespace Frida.Fruity.Injector {
|
||||
public uint64 get (string module_name, string symbol_name) throws Error {
|
||||
uint64 address;
|
||||
if (!lookup (module_name, symbol_name, out address))
|
||||
throw new Error.UNSUPPORTED ("Symbol not found: %s", symbol_name);
|
||||
throw new Error.NOT_SUPPORTED ("Symbol not found: %s", symbol_name);
|
||||
return address;
|
||||
}
|
||||
|
||||
@@ -1655,13 +1696,35 @@ namespace Frida.Fruity.Injector {
|
||||
if (pc == 1337)
|
||||
break;
|
||||
|
||||
if ((LLDB.Signal) exception.signum == SIGTRAP && exception.metype == EXC_BREAKPOINT) {
|
||||
uint64 x1 = exception.context["x1"];
|
||||
uint64 x2 = exception.context["x2"];
|
||||
var action = (GadgetBreakpointAction) exception.context["x3"];
|
||||
|
||||
if (x1 == x2 == 1337 && action == INVOKE_RETURN)
|
||||
break;
|
||||
|
||||
if (x1 == x2 == 1337 && action == PAGE_PLAN) {
|
||||
var plan_size = (size_t) exception.context["x4"];
|
||||
var plan_address = exception.context["x5"];
|
||||
yield DebuggerMappings.handle_page_plan (lldb, plan_address, plan_size, page_size,
|
||||
cancellable);
|
||||
|
||||
var thread = exception.thread;
|
||||
yield thread.write_register ("x0", 0x1337, cancellable);
|
||||
yield thread.write_register ("pc", pc + 4, cancellable);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (exception_handler != null) {
|
||||
bool handled = yield exception_handler.try_handle_exception (exception, cancellable);
|
||||
if (handled)
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new Error.UNSUPPORTED ("Invocation of 0x%" + uint64.FORMAT_MODIFIER + "x crashed at %s",
|
||||
throw new Error.NOT_SUPPORTED ("Invocation of 0x%" + uint64.FORMAT_MODIFIER + "x crashed at %s",
|
||||
impl, yield summarize_exception (exception, cancellable));
|
||||
}
|
||||
|
||||
|
||||
+10
-1
@@ -729,6 +729,15 @@ namespace Frida.GDB {
|
||||
check_execute_response (response);
|
||||
}
|
||||
|
||||
public async void perform_execute (Bytes command, Cancellable? cancellable, Promise<bool> request) throws Error, IOError {
|
||||
try {
|
||||
yield execute (command, cancellable);
|
||||
request.resolve (true);
|
||||
} catch (GLib.Error e) {
|
||||
request.reject (e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void check_execute_response (Packet packet) throws Error {
|
||||
unowned string response = packet.payload;
|
||||
if (response[0] == 'E') {
|
||||
@@ -1678,7 +1687,7 @@ namespace Frida.GDB {
|
||||
|
||||
var response = yield client.query (request, cancellable);
|
||||
|
||||
return Protocol.parse_pointer_value (response.payload, client.pointer_size, client.byte_order);
|
||||
return Protocol.parse_integer_value (response.payload, client.byte_order);
|
||||
}
|
||||
|
||||
public async void write_register (string name, uint64 val, Cancellable? cancellable = null) throws Error, IOError {
|
||||
|
||||
+4
-4
@@ -9,7 +9,7 @@
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@frida/buffer": "^7.0.4",
|
||||
"frida-java-bridge": "^7.0.4"
|
||||
"frida-java-bridge": "^7.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.25.5",
|
||||
@@ -534,9 +534,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/frida-java-bridge": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/frida-java-bridge/-/frida-java-bridge-7.0.4.tgz",
|
||||
"integrity": "sha512-dE5XCvasUwA/wiVb5gSwBPf6dortI8VtD0qLlw2T0ryqX/0lg4BEtEkg1oRr9IlHDVBTjPOqe9KRzdPar8U3EQ==",
|
||||
"version": "7.0.8",
|
||||
"resolved": "https://registry.npmjs.org/frida-java-bridge/-/frida-java-bridge-7.0.8.tgz",
|
||||
"integrity": "sha512-EmqoTGzcDuCd+YFcjBJJPf7iVQCSbbj9fD0/TN8YYYwl5ZJtTqaCLTTsaC07o3bJaDVs/f3ks+Vu1bOw0S1PnQ==",
|
||||
"license": "LGPL-2.0 WITH WxWindows-exception-3.1"
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@frida/buffer": "^7.0.4",
|
||||
"frida-java-bridge": "^7.0.4"
|
||||
"frida-java-bridge": "^7.0.8"
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -167,7 +167,7 @@ if have_local_backend
|
||||
'darwin' / 'policy-softener.vala',
|
||||
'darwin' / 'policy-softener-glue.c',
|
||||
]
|
||||
if host_os in ['macos', 'ios', 'tvos']
|
||||
if host_os in ['macos', 'ios', 'tvos', 'xros']
|
||||
helper_backend_sources += [
|
||||
'darwin' / 'frida-helper-backend.vala',
|
||||
'darwin' / 'frida-helper-backend-glue.m',
|
||||
@@ -179,7 +179,7 @@ if have_local_backend
|
||||
'darwin' / 'frida-helper-null-backend.vala',
|
||||
]
|
||||
endif
|
||||
if host_os in ['ios', 'tvos']
|
||||
if host_os in ['ios', 'tvos', 'xros']
|
||||
helper_backend_sources += [
|
||||
'darwin' / 'springboard.m',
|
||||
'darwin' / 'substituted-client.c',
|
||||
@@ -511,6 +511,7 @@ if have_fruity_backend
|
||||
'fruity' / 'springboard-services.vala',
|
||||
'fruity' / 'lldb.vala',
|
||||
'fruity' / 'injector.vala',
|
||||
'fruity' / 'debugger-mappings.vala',
|
||||
'fruity' / 'usbmux.vala',
|
||||
'fruity' / 'dns.vala',
|
||||
'fruity' / 'keyed-archive.vala',
|
||||
|
||||
+2015
-737
File diff suppressed because it is too large.
Load diff
@@ -1,6 +1,6 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/frida-gum.git
|
||||
revision = 17.2.2
|
||||
revision = 17.2.16
|
||||
depth = 1
|
||||
|
||||
[provide]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/lwip.git
|
||||
revision = 267d9f082e9e38083b643421a93c03d4a7046fd0
|
||||
revision = c5e2835a213436eaf0c40d0a95a35e7cf0dad2d3
|
||||
depth = 1
|
||||
|
||||
[provide]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# include <psapi.h>
|
||||
typedef HANDLE FridaProcessHandle;
|
||||
#elif defined (HAVE_DARWIN)
|
||||
# if defined (HAVE_IOS) || defined (HAVE_TVOS)
|
||||
# if defined (HAVE_IOS) || defined (HAVE_TVOS) || defined (HAVE_XROS)
|
||||
# define PROC_PIDLISTFDS 1
|
||||
# define PROC_PIDLISTFD_SIZE (sizeof (struct proc_fdinfo))
|
||||
struct proc_fdinfo
|
||||
|
||||
@@ -3762,6 +3762,11 @@ namespace Frida.HostSessionTest {
|
||||
timer.reset ();
|
||||
var script = yield session.create_script ("""
|
||||
send(Module.getGlobalExportByName('open'));
|
||||
try {
|
||||
ptr(0x69).writeU32(1337);
|
||||
} catch (e) {
|
||||
send('I cannot believe Exceptor works!');
|
||||
}
|
||||
""");
|
||||
printerr (" => took %u ms\n", (uint) (timer.elapsed () * 1000.0));
|
||||
|
||||
|
||||
@@ -118,6 +118,9 @@ namespace QuickJS {
|
||||
[CCode (cname = "JS_NewAtom")]
|
||||
public Atom make_atom (string str);
|
||||
|
||||
[CCode (cname = "JS_NewBool")]
|
||||
public Value make_bool (bool v);
|
||||
|
||||
[CCode (cname = "JS_NewInt32")]
|
||||
public Value make_int32 (int32 v);
|
||||
|
||||
|
||||
Reference in new issue
Block a user