Compare commits

...
10 Commits
Author SHA1 Message Date
Ole André Vadla Ravnås cf61fda141 subprojects: Prepare for release 2024-07-16 15:24:54 +02:00
Ole André Vadla Ravnås b272dda27d subprojects: Bump outdated 2024-07-16 15:20:35 +02:00
Ole André Vadla Ravnås 300d176e85 ci: Re-enable tests on macOS 2024-07-16 15:14:43 +02:00
Ole André Vadla Ravnås e7f045bbe9 darwin: Await ObjC init on macOS Sequoia and iOS 18
By making use of notifyObjCInit() if available.
2024-07-16 11:45:16 +02:00
Ole André Vadla Ravnås 0b6abfeb7c darwin: Handle dyld restart on macOS Sequoia and iOS 18 2024-07-16 11:12:02 +02:00
Ole André Vadla Ravnås c17c6e31bc tests: Avoid relying on executable name on Darwin 2024-07-16 11:06:55 +02:00
Ole André Vadla Ravnås 0825aab1d0 fruity: Improve CoreDevice pairing support
- Fix support for multiple pairing relationships.
- Keep the in-memory peer store up-to-date, so new pairing relationships
  don't require a process restart to be able to match them up with
  pairing services on the network.
2024-07-15 14:41:03 +02:00
Ole André Vadla Ravnås be65296610 ncm: Fix a stylistic inconsistency 2024-07-15 13:24:16 +02:00
Ole André Vadla Ravnås 0a6002a3ce ncm: Avoid using a broken kernel NCM driver
Where only one of the two network interfaces exist, i.e. the tethering
interface.
2024-07-15 13:03:49 +02:00
Ole André Vadla Ravnås a3deb22999 ncm: Detach all drivers before changing configuration
We would previously only try to detach for the data interface, which
makes no sense if that interface is on a different configuration.
2024-07-15 12:54:14 +02:00
7 changed files with 276 additions and 184 deletions

No files matched your search

-1
View File
@@ -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:
+23 -2
View File
@@ -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);
+43 -47
View File
@@ -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
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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]
+2 -4
View File
@@ -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 ();