mirror of
https://github.com/frida/frida-core.git
synced 2026-11-13 04:31:07 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf61fda141 | ||
|
|
b272dda27d | ||
|
|
300d176e85 | ||
|
|
e7f045bbe9 | ||
|
|
0b6abfeb7c | ||
|
|
c17c6e31bc | ||
|
|
0825aab1d0 | ||
|
|
be65296610 | ||
|
|
0a6002a3ce | ||
|
|
a3deb22999 |
No files matched your search
@@ -68,7 +68,6 @@ jobs:
|
||||
name: core-devkit-${{ matrix.id }}
|
||||
path: build/src/devkit/
|
||||
- name: Test
|
||||
if: ${{ !startsWith(matrix.id, 'macos-') }}
|
||||
run: make test
|
||||
|
||||
cross:
|
||||
|
||||
@@ -183,6 +183,7 @@ struct _FridaSpawnInstance
|
||||
GumAddress modern_entry_address;
|
||||
|
||||
/* V4+ */
|
||||
GumAddress notify_objc_init;
|
||||
GumAddress info_ptr_address;
|
||||
|
||||
/* V3- */
|
||||
@@ -2030,6 +2031,10 @@ _frida_darwin_helper_backend_prepare_spawn_instance_for_injection (FridaDarwinHe
|
||||
instance->dyld_flavor = (modern_entry_address != 0) ? FRIDA_DYLD_V4_PLUS : FRIDA_DYLD_V3_MINUS;
|
||||
if (instance->dyld_flavor == FRIDA_DYLD_V4_PLUS)
|
||||
{
|
||||
instance->notify_objc_init = gum_darwin_module_resolve_symbol_address (dyld, "__ZN5dyld412RuntimeState14notifyObjCInitEPKNS_6LoaderE");
|
||||
if (instance->notify_objc_init != 0)
|
||||
modern_entry_address = instance->notify_objc_init;
|
||||
|
||||
instance->modern_entry_address = modern_entry_address;
|
||||
legacy_entry_address = 0;
|
||||
|
||||
@@ -2108,7 +2113,12 @@ _frida_darwin_helper_backend_prepare_spawn_instance_for_injection (FridaDarwinHe
|
||||
if (instance->dyld_flavor == FRIDA_DYLD_V4_PLUS)
|
||||
{
|
||||
GumAddress restart_with_dyld_in_cache = gum_darwin_module_resolve_symbol_address (dyld,
|
||||
"__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN5dyld39MachOFileEPK15DyldSharedCachePv");
|
||||
if (restart_with_dyld_in_cache == 0)
|
||||
{
|
||||
restart_with_dyld_in_cache = gum_darwin_module_resolve_symbol_address (dyld,
|
||||
"__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN5dyld39MachOFileEPv");
|
||||
}
|
||||
if (restart_with_dyld_in_cache != 0)
|
||||
frida_spawn_instance_set_nth_breakpoint (instance, i++, restart_with_dyld_in_cache, FRIDA_BREAKPOINT_REPEAT_NEVER);
|
||||
}
|
||||
@@ -3085,9 +3095,15 @@ frida_spawn_instance_handle_breakpoint (FridaSpawnInstance * self, FridaBreakpoi
|
||||
if (self->dyld_flavor == FRIDA_DYLD_V4_PLUS)
|
||||
{
|
||||
if (pc == self->modern_entry_address)
|
||||
self->breakpoint_phase = FRIDA_BREAKPOINT_SET_LIBDYLD_INITIALIZE_CALLER_BREAKPOINT;
|
||||
{
|
||||
self->breakpoint_phase = (pc == self->notify_objc_init)
|
||||
? FRIDA_BREAKPOINT_LIBSYSTEM_INITIALIZED
|
||||
: FRIDA_BREAKPOINT_SET_LIBDYLD_INITIALIZE_CALLER_BREAKPOINT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return frida_spawn_instance_handle_dyld_restart (self);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3353,6 +3369,7 @@ frida_spawn_instance_handle_dyld_restart (FridaSpawnInstance * self)
|
||||
GumAddress * info_ptr;
|
||||
struct dyld_all_image_infos * info = NULL;
|
||||
GumDarwinModule * dyld = NULL;
|
||||
gssize delta;
|
||||
|
||||
info_ptr = (GumAddress *) gum_darwin_read (self->task, self->info_ptr_address, sizeof (GumAddress), NULL);
|
||||
if (info_ptr == NULL)
|
||||
@@ -3367,7 +3384,11 @@ frida_spawn_instance_handle_dyld_restart (FridaSpawnInstance * self)
|
||||
if (dyld == NULL)
|
||||
goto beach;
|
||||
|
||||
self->modern_entry_address = GUM_ADDRESS (info->dyldImageLoadAddress) + (self->modern_entry_address - self->dyld->base_address);
|
||||
delta = (gssize) info->dyldImageLoadAddress - (gssize) self->dyld->base_address;
|
||||
|
||||
self->modern_entry_address += delta;
|
||||
if (self->notify_objc_init != 0)
|
||||
self->notify_objc_init += delta;
|
||||
|
||||
g_object_unref (self->dyld);
|
||||
self->dyld = g_steal_pointer (&dyld);
|
||||
|
||||
@@ -728,7 +728,7 @@ namespace Frida.Fruity {
|
||||
private Gee.Map<string, PortableCoreDeviceNetworkTransport> network_transports =
|
||||
new Gee.HashMap<string, PortableCoreDeviceNetworkTransport> ();
|
||||
|
||||
private Gee.List<PairingIdentity.Peer> peers = PairingIdentity.load_peers ();
|
||||
private PairingStore pairing_store = new PairingStore ();
|
||||
|
||||
private MainContext main_context;
|
||||
|
||||
@@ -919,7 +919,7 @@ namespace Frida.Fruity {
|
||||
if (modeswitch_allowed && yield device.maybe_modeswitch (io_cancellable))
|
||||
break;
|
||||
|
||||
var transport = new PortableCoreDeviceUsbTransport (device);
|
||||
var transport = new PortableCoreDeviceUsbTransport (device, pairing_store);
|
||||
usb_transports.add (transport);
|
||||
transport_attached (transport);
|
||||
|
||||
@@ -988,13 +988,14 @@ namespace Frida.Fruity {
|
||||
}
|
||||
|
||||
private void on_network_pairing_service_discovered (PairingServiceDetails service) {
|
||||
var peer = find_peer (service);
|
||||
var peer = pairing_store.find_peer_matching_service (service);
|
||||
if (peer == null)
|
||||
return;
|
||||
|
||||
var transport = network_transports[peer.udid];
|
||||
if (transport == null) {
|
||||
transport = new PortableCoreDeviceNetworkTransport (peer, service.endpoint, service.interface_address);
|
||||
transport = new PortableCoreDeviceNetworkTransport (peer, pairing_store, service.endpoint,
|
||||
service.interface_address);
|
||||
network_transports[peer.udid] = transport;
|
||||
transport_attached (transport);
|
||||
} else {
|
||||
@@ -1003,36 +1004,6 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
private PairingIdentity.Peer? find_peer (PairingServiceDetails service) {
|
||||
var mac = OpenSSL.Envelope.MessageAuthCode.fetch (null, OpenSSL.ShortName.siphash);
|
||||
|
||||
size_t hash_size = 8;
|
||||
size_t return_size = OpenSSL.ParamReturnSize.UNMODIFIED;
|
||||
OpenSSL.Param mac_params[] = {
|
||||
{ OpenSSL.Envelope.MessageAuthParameter.SIZE, UNSIGNED_INTEGER,
|
||||
(uint8[]) &hash_size, return_size },
|
||||
{ null, INTEGER, null, return_size },
|
||||
};
|
||||
|
||||
foreach (var peer in peers) {
|
||||
var ctx = new OpenSSL.Envelope.MessageAuthCodeContext (mac);
|
||||
ctx.init (peer.irk.get_data (), mac_params);
|
||||
ctx.update (service.identifier.data);
|
||||
uint8 output[8];
|
||||
size_t outlen = 0;
|
||||
ctx.final (output, out outlen);
|
||||
|
||||
uint8 tag[6];
|
||||
for (uint i = 0; i != 6; i++)
|
||||
tag[i] = output[5 - i];
|
||||
|
||||
if (Memory.cmp (tag, service.auth_tag.get_data (), service.auth_tag.get_size ()) == 0)
|
||||
return peer;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void schedule_on_frida_thread (owned SourceFunc function) {
|
||||
var source = new IdleSource ();
|
||||
source.set_callback ((owned) function);
|
||||
@@ -1046,6 +1017,11 @@ namespace Frida.Fruity {
|
||||
construct;
|
||||
}
|
||||
|
||||
public PairingStore pairing_store {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public ConnectionType connection_type {
|
||||
get {
|
||||
return USB;
|
||||
@@ -1078,8 +1054,8 @@ namespace Frida.Fruity {
|
||||
|
||||
private Promise<Tunnel>? tunnel_request;
|
||||
|
||||
public PortableCoreDeviceUsbTransport (UsbDevice usb_device) {
|
||||
Object (usb_device: usb_device);
|
||||
public PortableCoreDeviceUsbTransport (UsbDevice device, PairingStore store) {
|
||||
Object (usb_device: device, pairing_store: store);
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
@@ -1109,7 +1085,7 @@ namespace Frida.Fruity {
|
||||
tunnel_request = new Promise<Tunnel> ();
|
||||
|
||||
try {
|
||||
var tunnel = new PortableUsbTunnel (usb_device);
|
||||
var tunnel = new PortableUsbTunnel (usb_device, pairing_store);
|
||||
yield tunnel.open (cancellable);
|
||||
|
||||
tunnel_request.resolve (tunnel);
|
||||
@@ -1130,6 +1106,11 @@ namespace Frida.Fruity {
|
||||
construct;
|
||||
}
|
||||
|
||||
public PairingStore pairing_store {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public DiscoveryService discovery {
|
||||
get {
|
||||
return _discovery_service;
|
||||
@@ -1140,8 +1121,8 @@ namespace Frida.Fruity {
|
||||
private TunnelConnection? tunnel_connection;
|
||||
private DiscoveryService? _discovery_service;
|
||||
|
||||
public PortableUsbTunnel (UsbDevice usb_device) {
|
||||
Object (usb_device: usb_device);
|
||||
public PortableUsbTunnel (UsbDevice device, PairingStore store) {
|
||||
Object (usb_device: device, pairing_store: store);
|
||||
}
|
||||
|
||||
public async void open (Cancellable? cancellable) throws Error, IOError {
|
||||
@@ -1164,7 +1145,7 @@ namespace Frida.Fruity {
|
||||
scope_id: netstack.scope_id
|
||||
);
|
||||
var pairing_transport = new XpcPairingTransport (yield netstack.open_tcp_connection (tunnel_endpoint, cancellable));
|
||||
var pairing_service = yield PairingService.open (pairing_transport, cancellable);
|
||||
var pairing_service = yield PairingService.open (pairing_transport, pairing_store, cancellable);
|
||||
|
||||
TunnelConnection tc = yield pairing_service.open_tunnel (peer.ip, netstack, cancellable);
|
||||
|
||||
@@ -1201,7 +1182,7 @@ namespace Frida.Fruity {
|
||||
|
||||
private async NcmPeer locate_ncm_peer (Cancellable? cancellable) throws Error, IOError {
|
||||
var device_ifaddrs = detect_ncm_ifaddrs_on_system ();
|
||||
if (!device_ifaddrs.is_empty)
|
||||
if (device_ifaddrs.size == 2)
|
||||
return yield locate_ncm_peer_on_system_netifs (device_ifaddrs, cancellable);
|
||||
return yield establish_ncm_peer_using_our_driver (cancellable);
|
||||
}
|
||||
@@ -1401,7 +1382,12 @@ namespace Frida.Fruity {
|
||||
}
|
||||
|
||||
private sealed class PortableCoreDeviceNetworkTransport : Object, Transport {
|
||||
public PairingIdentity.Peer peer {
|
||||
public PairingPeer peer {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public PairingStore pairing_store {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
@@ -1448,10 +1434,11 @@ namespace Frida.Fruity {
|
||||
|
||||
private Promise<Tunnel>? tunnel_request;
|
||||
|
||||
public PortableCoreDeviceNetworkTransport (PairingIdentity.Peer peer, InetSocketAddress endpoint,
|
||||
public PortableCoreDeviceNetworkTransport (PairingPeer peer, PairingStore store, InetSocketAddress endpoint,
|
||||
InetSocketAddress interface_address) {
|
||||
Object (
|
||||
peer: peer,
|
||||
pairing_store: store,
|
||||
endpoint: endpoint,
|
||||
interface_address: interface_address
|
||||
);
|
||||
@@ -1482,7 +1469,7 @@ namespace Frida.Fruity {
|
||||
tunnel_request = new Promise<Tunnel> ();
|
||||
|
||||
try {
|
||||
var tunnel = new PortableNetworkTunnel (endpoint, interface_address);
|
||||
var tunnel = new PortableNetworkTunnel (endpoint, interface_address, pairing_store);
|
||||
yield tunnel.open (cancellable);
|
||||
|
||||
tunnel_request.resolve (tunnel);
|
||||
@@ -1508,6 +1495,11 @@ namespace Frida.Fruity {
|
||||
construct;
|
||||
}
|
||||
|
||||
public PairingStore pairing_store {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public DiscoveryService discovery {
|
||||
get {
|
||||
return _discovery_service;
|
||||
@@ -1517,8 +1509,12 @@ namespace Frida.Fruity {
|
||||
private TunnelConnection? tunnel_connection;
|
||||
private DiscoveryService? _discovery_service;
|
||||
|
||||
public PortableNetworkTunnel (InetSocketAddress endpoint, InetSocketAddress interface_address) {
|
||||
Object (endpoint: endpoint, interface_address: interface_address);
|
||||
public PortableNetworkTunnel (InetSocketAddress endpoint, InetSocketAddress interface_address, PairingStore store) {
|
||||
Object (
|
||||
endpoint: endpoint,
|
||||
interface_address: interface_address,
|
||||
pairing_store: store
|
||||
);
|
||||
}
|
||||
|
||||
public async void open (Cancellable? cancellable) throws Error, IOError {
|
||||
@@ -1526,7 +1522,7 @@ namespace Frida.Fruity {
|
||||
|
||||
var pairing_connection = yield netstack.open_tcp_connection (endpoint, cancellable);
|
||||
var pairing_transport = new PlainPairingTransport (pairing_connection);
|
||||
var pairing_service = yield PairingService.open (pairing_transport, cancellable);
|
||||
var pairing_service = yield PairingService.open (pairing_transport, pairing_store, cancellable);
|
||||
|
||||
TunnelConnection tc = yield pairing_service.open_tunnel (endpoint.get_address (), netstack, cancellable);
|
||||
|
||||
|
||||
+17
-9
@@ -76,10 +76,10 @@ namespace Frida.Fruity {
|
||||
|
||||
var dev_desc = LibUSB.DeviceDescriptor (raw_device);
|
||||
|
||||
int current_config;
|
||||
Usb.check (handle.get_configuration (out current_config), "Failed to get current configuration");
|
||||
LibUSB.ConfigDescriptor current_config;
|
||||
Usb.check (raw_device.get_active_config_descriptor (out current_config), "Failed to get active config descriptor");
|
||||
|
||||
int desired_config = -1;
|
||||
int desired_config_value = -1;
|
||||
bool found_cdc_header = false;
|
||||
bool found_data_interface = false;
|
||||
uint8 mac_address_index = 0;
|
||||
@@ -107,17 +107,19 @@ namespace Frida.Fruity {
|
||||
data_altsetting = setting.bAlternateSetting;
|
||||
|
||||
foreach (var ep in setting.endpoint) {
|
||||
if ((ep.bEndpointAddress & LibUSB.EndpointDirection.MASK) == LibUSB.EndpointDirection.IN)
|
||||
if ((ep.bEndpointAddress & LibUSB.EndpointDirection.MASK) ==
|
||||
LibUSB.EndpointDirection.IN) {
|
||||
rx_address = ep.bEndpointAddress;
|
||||
else
|
||||
} else {
|
||||
tx_address = ep.bEndpointAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found_cdc_header || found_data_interface) {
|
||||
desired_config = config_value;
|
||||
desired_config_value = config_value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -135,9 +137,15 @@ namespace Frida.Fruity {
|
||||
mac_address[i] = (uint8) v;
|
||||
}
|
||||
|
||||
handle.detach_kernel_driver (data_iface);
|
||||
if (current_config != desired_config)
|
||||
Usb.check (handle.set_configuration (desired_config), "Failed to set configuration");
|
||||
if (current_config.bConfigurationValue != desired_config_value) {
|
||||
foreach (var iface in current_config.@interface) {
|
||||
unowned LibUSB.InterfaceDescriptor setting = iface.altsetting[0];
|
||||
var res = handle.kernel_driver_active (setting.bInterfaceNumber);
|
||||
if (res == 1)
|
||||
handle.detach_kernel_driver (setting.bInterfaceNumber);
|
||||
}
|
||||
Usb.check (handle.set_configuration (desired_config_value), "Failed to set configuration");
|
||||
}
|
||||
try {
|
||||
Usb.check (handle.claim_interface (data_iface), "Failed to claim USB interface");
|
||||
} catch (Error e) {
|
||||
|
||||
+190
-120
@@ -106,6 +106,11 @@ namespace Frida.Fruity {
|
||||
construct;
|
||||
}
|
||||
|
||||
public PairingStore store {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public DeviceOptions device_options {
|
||||
get;
|
||||
private set;
|
||||
@@ -121,14 +126,12 @@ namespace Frida.Fruity {
|
||||
private uint64 next_control_sequence_number = 0;
|
||||
private uint64 next_encrypted_sequence_number = 0;
|
||||
|
||||
private string host_identifier;
|
||||
private Key pair_record_key;
|
||||
private ChaCha20Poly1305? client_cipher;
|
||||
private ChaCha20Poly1305? server_cipher;
|
||||
|
||||
public static async PairingService open (PairingTransport transport, Cancellable? cancellable = null)
|
||||
public static async PairingService open (PairingTransport transport, PairingStore store, Cancellable? cancellable = null)
|
||||
throws Error, IOError {
|
||||
var service = new PairingService (transport);
|
||||
var service = new PairingService (transport, store);
|
||||
|
||||
try {
|
||||
yield service.init_async (Priority.DEFAULT, cancellable);
|
||||
@@ -139,26 +142,13 @@ namespace Frida.Fruity {
|
||||
return service;
|
||||
}
|
||||
|
||||
private PairingService (PairingTransport transport) {
|
||||
Object (transport: transport);
|
||||
private PairingService (PairingTransport transport, PairingStore store) {
|
||||
Object (transport: transport, store: store);
|
||||
}
|
||||
|
||||
construct {
|
||||
transport.close.connect (on_close);
|
||||
transport.message.connect (on_message);
|
||||
|
||||
Bytes? key;
|
||||
var identity = PairingIdentity.try_load ();
|
||||
if (identity != null) {
|
||||
key = identity.private_key;
|
||||
host_identifier = identity.identifier;
|
||||
} else {
|
||||
uint8 dummy_key[32] = { 0, };
|
||||
key = new Bytes (dummy_key);
|
||||
host_identifier = make_host_identifier ();
|
||||
}
|
||||
|
||||
pair_record_key = new Key.from_raw_private_key (ED25519, null, key.get_data ());
|
||||
}
|
||||
|
||||
private async bool init_async (int io_priority, Cancellable? cancellable) throws Error, IOError {
|
||||
@@ -378,11 +368,13 @@ namespace Frida.Fruity {
|
||||
new Bytes.static ("\x00\x00\x00\x00PV-Msg02".data[:12]),
|
||||
start_response.read_member ("encrypted-data").get_data_value ())));
|
||||
|
||||
unowned string host_identifier = store.self_identity.identifier;
|
||||
|
||||
var message = new ByteArray.sized (100);
|
||||
message.append (raw_host_pubkey);
|
||||
message.append (host_identifier.data);
|
||||
message.append (raw_device_pubkey);
|
||||
Bytes signature = compute_message_signature (ByteArray.free_to_bytes ((owned) message), pair_record_key);
|
||||
Bytes signature = compute_message_signature (ByteArray.free_to_bytes ((owned) message), store.self_identity.key);
|
||||
|
||||
Bytes inner_params = new PairingParamsBuilder ()
|
||||
.add_identifier (host_identifier)
|
||||
@@ -494,33 +486,29 @@ namespace Frida.Fruity {
|
||||
|
||||
var cipher = new ChaCha20Poly1305 (operation_key);
|
||||
|
||||
Key new_pair_record_key = make_keypair (ED25519);
|
||||
Bytes new_pair_record_pubkey = get_raw_public_key (new_pair_record_key);
|
||||
|
||||
uint8 raw_irk[16];
|
||||
Rng.generate (raw_irk);
|
||||
Bytes irk = new Bytes (raw_irk);
|
||||
|
||||
Bytes signing_key = derive_chacha_key (shared_key,
|
||||
"Pair-Setup-Controller-Sign-Info",
|
||||
"Pair-Setup-Controller-Sign-Salt");
|
||||
|
||||
unowned PairingIdentity self_identity = store.self_identity;
|
||||
Bytes self_identity_pubkey = get_raw_public_key (self_identity.key);
|
||||
|
||||
var message = new ByteArray.sized (100);
|
||||
message.append (signing_key.get_data ());
|
||||
message.append (host_identifier.data);
|
||||
message.append (new_pair_record_pubkey.get_data ());
|
||||
Bytes signature = compute_message_signature (ByteArray.free_to_bytes ((owned) message), new_pair_record_key);
|
||||
message.append (self_identity.identifier.data);
|
||||
message.append (self_identity_pubkey.get_data ());
|
||||
Bytes signature = compute_message_signature (ByteArray.free_to_bytes ((owned) message), self_identity.key);
|
||||
|
||||
Bytes self_info = new OpackBuilder ()
|
||||
.begin_dictionary ()
|
||||
.set_member_name ("name")
|
||||
.add_string_value (Environment.get_host_name ())
|
||||
.set_member_name ("accountID")
|
||||
.add_string_value (host_identifier)
|
||||
.add_string_value (self_identity.identifier)
|
||||
.set_member_name ("remotepairing_serial_number")
|
||||
.add_string_value ("AAAAAAAAAAAA")
|
||||
.set_member_name ("altIRK")
|
||||
.add_data_value (irk)
|
||||
.add_data_value (self_identity.irk)
|
||||
.set_member_name ("model")
|
||||
.add_string_value ("computer-model")
|
||||
.set_member_name ("mac")
|
||||
@@ -531,8 +519,8 @@ namespace Frida.Fruity {
|
||||
.build ();
|
||||
|
||||
Bytes inner_params = new PairingParamsBuilder ()
|
||||
.add_identifier (host_identifier)
|
||||
.add_raw_public_key (new_pair_record_pubkey)
|
||||
.add_identifier (self_identity.identifier)
|
||||
.add_raw_public_key (self_identity_pubkey)
|
||||
.add_signature (signature)
|
||||
.add_info (self_info)
|
||||
.build ();
|
||||
@@ -569,17 +557,7 @@ namespace Frida.Fruity {
|
||||
inner_finish_response.end_member ();
|
||||
Bytes peer_info = inner_finish_response.read_member ("info").get_data_value ();
|
||||
inner_finish_response.end_member ();
|
||||
PairingIdentity.save_peer (peer_identifier, peer_pubkey, peer_info);
|
||||
|
||||
var identity = new PairingIdentity () {
|
||||
identifier = host_identifier,
|
||||
public_key = new_pair_record_pubkey,
|
||||
private_key = get_raw_private_key (new_pair_record_key),
|
||||
irk = irk
|
||||
};
|
||||
identity.save ();
|
||||
|
||||
pair_record_key = (owned) new_pair_record_key;
|
||||
store.add_peer (peer_identifier, peer_pubkey, peer_info);
|
||||
|
||||
return shared_key;
|
||||
}
|
||||
@@ -745,16 +723,6 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
private static Key make_keypair (KeyType type) {
|
||||
var ctx = new KeyContext.for_key_type (type);
|
||||
ctx.keygen_init ();
|
||||
|
||||
Key? keypair = null;
|
||||
ctx.keygen (ref keypair);
|
||||
|
||||
return keypair;
|
||||
}
|
||||
|
||||
private static uint8[] key_to_der (Key key) {
|
||||
var sink = new BasicIO (BasicIOMethod.memory ());
|
||||
key.to_der (sink);
|
||||
@@ -1331,64 +1299,36 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class PairingIdentity {
|
||||
public string identifier;
|
||||
public Bytes public_key;
|
||||
public Bytes private_key;
|
||||
public Bytes irk;
|
||||
|
||||
public static PairingIdentity? try_load () {
|
||||
try {
|
||||
Bytes raw_identity = query_self_identity_location ().load_bytes ();
|
||||
Plist identity = new Plist.from_data (raw_identity.get_data ());
|
||||
return new PairingIdentity () {
|
||||
identifier = identity.get_string ("identifier"),
|
||||
public_key = identity.get_bytes ("publicKey"),
|
||||
private_key = identity.get_bytes ("privateKey"),
|
||||
irk = identity.get_bytes ("irk")
|
||||
};
|
||||
} catch (GLib.Error e) {
|
||||
return null;
|
||||
public class PairingStore {
|
||||
public PairingIdentity self_identity {
|
||||
get {
|
||||
return _self_identity;
|
||||
}
|
||||
}
|
||||
|
||||
public void save () throws Error {
|
||||
var plist = new Plist ();
|
||||
plist.set_string ("identifier", identifier);
|
||||
plist.set_bytes ("publicKey", public_key);
|
||||
plist.set_bytes ("privateKey", private_key);
|
||||
plist.set_bytes ("irk", irk);
|
||||
save_plist (plist, query_self_identity_location ());
|
||||
public Gee.Iterable<PairingPeer> peers {
|
||||
get {
|
||||
return _peers;
|
||||
}
|
||||
}
|
||||
|
||||
public static Gee.List<Peer> load_peers () {
|
||||
var peers = new Gee.ArrayList<Peer> ();
|
||||
private PairingIdentity _self_identity;
|
||||
private Gee.List<PairingPeer> _peers;
|
||||
|
||||
try {
|
||||
var enumerator = query_peers_location ().enumerate_children (FileAttribute.STANDARD_NAME, FileQueryInfoFlags.NONE);
|
||||
File? child;
|
||||
while (enumerator.iterate (null, out child) && child != null) {
|
||||
Plist plist = new Plist.from_data (child.load_bytes ().get_data ());
|
||||
|
||||
var reader = new VariantReader (OpackParser.parse (plist.get_bytes ("info")));
|
||||
unowned string udid = reader.read_member ("remotepairing_udid").get_string_value ();
|
||||
|
||||
peers.add (new Peer () {
|
||||
identifier = plist.get_string ("identifier"),
|
||||
public_key = plist.get_bytes ("publicKey"),
|
||||
irk = plist.get_bytes ("irk"),
|
||||
name = plist.get_string ("name"),
|
||||
model = plist.get_string ("model"),
|
||||
udid = udid,
|
||||
});
|
||||
public PairingStore () {
|
||||
_self_identity = try_load_identity ();
|
||||
if (_self_identity == null) {
|
||||
_self_identity = PairingIdentity.make ();
|
||||
try {
|
||||
save_identity (_self_identity);
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
|
||||
return peers;
|
||||
_peers = load_peers ();
|
||||
}
|
||||
|
||||
public static void save_peer (string identifier, Bytes public_key, Bytes info) throws Error {
|
||||
public void add_peer (string identifier, Bytes public_key, Bytes info) throws Error {
|
||||
var r = new VariantReader (OpackParser.parse (info));
|
||||
|
||||
Bytes irk = r.read_member ("altIRK").get_data_value ();
|
||||
@@ -1400,21 +1340,123 @@ namespace Frida.Fruity {
|
||||
unowned string model = r.read_member ("model").get_string_value ();
|
||||
r.end_member ();
|
||||
|
||||
var plist = new Plist ();
|
||||
plist.set_string ("identifier", identifier);
|
||||
plist.set_bytes ("publicKey", public_key);
|
||||
plist.set_bytes ("irk", irk);
|
||||
plist.set_string ("name", name);
|
||||
plist.set_string ("model", model);
|
||||
plist.set_bytes ("info", info);
|
||||
save_plist (plist, query_peers_location ().get_child (identifier + ".plist"));
|
||||
unowned string udid = r.read_member ("remotepairing_udid").get_string_value ();
|
||||
r.end_member ();
|
||||
|
||||
var peer = new PairingPeer () {
|
||||
identifier = identifier,
|
||||
public_key = public_key,
|
||||
irk = irk,
|
||||
name = name,
|
||||
model = model,
|
||||
udid = udid,
|
||||
info = info,
|
||||
};
|
||||
_peers.add (peer);
|
||||
|
||||
try {
|
||||
save_peer (peer);
|
||||
} catch (Error e) {
|
||||
}
|
||||
}
|
||||
|
||||
public static File query_self_identity_location () {
|
||||
public PairingPeer? find_peer_matching_service (PairingServiceDetails service) {
|
||||
var mac = OpenSSL.Envelope.MessageAuthCode.fetch (null, OpenSSL.ShortName.siphash);
|
||||
|
||||
size_t hash_size = 8;
|
||||
size_t return_size = OpenSSL.ParamReturnSize.UNMODIFIED;
|
||||
OpenSSL.Param mac_params[] = {
|
||||
{ OpenSSL.Envelope.MessageAuthParameter.SIZE, UNSIGNED_INTEGER,
|
||||
(uint8[]) &hash_size, return_size },
|
||||
{ null, INTEGER, null, return_size },
|
||||
};
|
||||
|
||||
foreach (var peer in _peers) {
|
||||
var ctx = new OpenSSL.Envelope.MessageAuthCodeContext (mac);
|
||||
ctx.init (peer.irk.get_data (), mac_params);
|
||||
ctx.update (service.identifier.data);
|
||||
uint8 output[8];
|
||||
size_t outlen = 0;
|
||||
ctx.final (output, out outlen);
|
||||
|
||||
uint8 tag[6];
|
||||
for (uint i = 0; i != 6; i++)
|
||||
tag[i] = output[5 - i];
|
||||
|
||||
if (Memory.cmp (tag, service.auth_tag.get_data (), service.auth_tag.get_size ()) == 0)
|
||||
return peer;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static PairingIdentity? try_load_identity () {
|
||||
try {
|
||||
var plist = new Plist.from_data (query_self_identity_location ().load_bytes ().get_data ());
|
||||
return new PairingIdentity () {
|
||||
identifier = plist.get_string ("identifier"),
|
||||
key = new Key.from_raw_private_key (ED25519, null, plist.get_bytes ("privateKey").get_data ()),
|
||||
irk = plist.get_bytes ("irk"),
|
||||
};
|
||||
} catch (GLib.Error e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void save_identity (PairingIdentity identity) throws Error {
|
||||
var plist = new Plist ();
|
||||
plist.set_string ("identifier", identity.identifier);
|
||||
plist.set_bytes ("publicKey", get_raw_public_key (identity.key));
|
||||
plist.set_bytes ("privateKey", get_raw_private_key (identity.key));
|
||||
plist.set_bytes ("irk", identity.irk);
|
||||
save_plist (plist, query_self_identity_location ());
|
||||
}
|
||||
|
||||
private static Gee.List<PairingPeer> load_peers () {
|
||||
var peers = new Gee.ArrayList<PairingPeer> ();
|
||||
|
||||
try {
|
||||
var enumerator = query_peers_location ().enumerate_children (FileAttribute.STANDARD_NAME, FileQueryInfoFlags.NONE);
|
||||
File? child;
|
||||
while (enumerator.iterate (null, out child) && child != null) {
|
||||
var plist = new Plist.from_data (child.load_bytes ().get_data ());
|
||||
|
||||
var info = plist.get_bytes ("info");
|
||||
var r = new VariantReader (OpackParser.parse (info));
|
||||
unowned string udid = r.read_member ("remotepairing_udid").get_string_value ();
|
||||
|
||||
peers.add (new PairingPeer () {
|
||||
identifier = plist.get_string ("identifier"),
|
||||
public_key = plist.get_bytes ("publicKey"),
|
||||
irk = plist.get_bytes ("irk"),
|
||||
name = plist.get_string ("name"),
|
||||
model = plist.get_string ("model"),
|
||||
udid = udid,
|
||||
info = info,
|
||||
});
|
||||
}
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
|
||||
return peers;
|
||||
}
|
||||
|
||||
private static void save_peer (PairingPeer peer) throws Error {
|
||||
var plist = new Plist ();
|
||||
plist.set_string ("identifier", peer.identifier);
|
||||
plist.set_bytes ("publicKey", peer.public_key);
|
||||
plist.set_bytes ("irk", peer.irk);
|
||||
plist.set_string ("name", peer.name);
|
||||
plist.set_string ("model", peer.model);
|
||||
plist.set_bytes ("info", peer.info);
|
||||
save_plist (plist, query_peers_location ().get_child (peer.identifier + ".plist"));
|
||||
}
|
||||
|
||||
private static File query_self_identity_location () {
|
||||
return query_base_location ().get_child ("self-identity.plist");
|
||||
}
|
||||
|
||||
public static File query_peers_location () {
|
||||
private static File query_peers_location () {
|
||||
return query_base_location ().get_child ("peers");
|
||||
}
|
||||
|
||||
@@ -1428,22 +1470,40 @@ namespace Frida.Fruity {
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
try {
|
||||
location.replace_contents (plist.to_xml ().data, null, false, PRIVATE | REPLACE_DESTINATION, null);
|
||||
location.replace_contents (plist.to_binary (), null, false, PRIVATE | REPLACE_DESTINATION, null);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Peer {
|
||||
public string identifier;
|
||||
public Bytes public_key;
|
||||
public Bytes irk;
|
||||
public string name;
|
||||
public string model;
|
||||
public string udid;
|
||||
public class PairingIdentity {
|
||||
public string identifier;
|
||||
public Key key;
|
||||
public Bytes irk;
|
||||
|
||||
public static PairingIdentity make () {
|
||||
uint8 raw_irk[16];
|
||||
Rng.generate (raw_irk);
|
||||
|
||||
return new PairingIdentity () {
|
||||
identifier = make_host_identifier (),
|
||||
key = make_keypair (ED25519),
|
||||
irk = new Bytes (raw_irk),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class PairingPeer {
|
||||
public string identifier;
|
||||
public Bytes public_key;
|
||||
public Bytes irk;
|
||||
public string name;
|
||||
public string model;
|
||||
public string udid;
|
||||
public Bytes info;
|
||||
}
|
||||
|
||||
public class PairingServiceMetadata {
|
||||
public string identifier;
|
||||
public Bytes auth_tag;
|
||||
@@ -3643,6 +3703,16 @@ namespace Frida.Fruity {
|
||||
public const uint32 VERSION = 5;
|
||||
}
|
||||
|
||||
private Key make_keypair (KeyType type) {
|
||||
var ctx = new KeyContext.for_key_type (type);
|
||||
ctx.keygen_init ();
|
||||
|
||||
Key? keypair = null;
|
||||
ctx.keygen (ref keypair);
|
||||
|
||||
return keypair;
|
||||
}
|
||||
|
||||
private Bytes get_raw_public_key (Key key) {
|
||||
size_t size = 0;
|
||||
key.get_raw_public_key (null, ref size);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/frida-gum.git
|
||||
revision = 16.4.3
|
||||
revision = 16.4.4
|
||||
depth = 1
|
||||
|
||||
[provide]
|
||||
|
||||
@@ -72,10 +72,8 @@ frida_test_process_backend_filename_of (void * handle)
|
||||
image_count = _dyld_image_count ();
|
||||
for (image_idx = 0; image_idx != image_count; image_idx++)
|
||||
{
|
||||
const gchar * image_path = _dyld_get_image_name (image_idx);
|
||||
|
||||
if (g_str_has_suffix (image_path, "/frida-tests"))
|
||||
return g_strdup (image_path);
|
||||
if (_dyld_get_image_header (image_idx)->filetype == MH_EXECUTE)
|
||||
return g_strdup (_dyld_get_image_name (image_idx));
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
|
||||
Reference in new issue
Block a user