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
@@ -273,3 +273,35 @@ jobs:
|
||||
else
|
||||
echo "No unexpected changes detected."
|
||||
fi
|
||||
|
||||
# This job is used to check that the Linux labrats are built correctly for all
|
||||
# supported architectures. We do this because the binary artifacts are checked
|
||||
# in, and we want to ensure that they are up-to-date with respect to the source
|
||||
# for all architectures.
|
||||
check-labrats:
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86, x86_64, arm, armbe8, arm64, arm64be, arm64beilp32, mips, mipsel, mips64, mips64el]
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/frida/core-linux-helpers-${{ matrix.arch }}:latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build
|
||||
run: |
|
||||
./tests/labrats/rebuild.sh ${{ matrix.arch }}
|
||||
- name: Check for unexpected changes
|
||||
run: |
|
||||
git config --global --add safe.directory "$(realpath .)"
|
||||
status_output="$(git status --porcelain)"
|
||||
if [ -n "$status_output" ]; then
|
||||
echo "Unexpected changes detected:"
|
||||
echo "$status_output"
|
||||
echo "Diff:"
|
||||
git diff
|
||||
exit 1
|
||||
else
|
||||
echo "No unexpected changes detected."
|
||||
fi
|
||||
@@ -3,9 +3,16 @@
|
||||
/src/barebone/helpers/memory-scanner/target/
|
||||
/src/barebone/helpers/target/
|
||||
/src/barebone/node_modules/
|
||||
/src/barebone/script-runtime.js
|
||||
/src/compiler/node_modules/
|
||||
/src/darwin/agent/osanalytics/node_modules/
|
||||
/src/darwin/agent/osanalytics/osanalytics.js
|
||||
/src/darwin/agent/reportcrash/node_modules/
|
||||
/src/darwin/agent/reportcrash/reportcrash.js
|
||||
/src/droidy/helper/build/
|
||||
/src/fruity/helpers/build/
|
||||
/src/linux/agent/system-server/node_modules/
|
||||
/src/linux/agent/system-server/system-server.js
|
||||
/src/linux/helpers/build/
|
||||
/src/linux/helpers/ext/
|
||||
/subprojects/*
|
||||
+2
-2
@@ -147,7 +147,7 @@ namespace Frida.Inject {
|
||||
public extern void init ();
|
||||
}
|
||||
|
||||
public class Application : Object {
|
||||
public sealed class Application : Object {
|
||||
public string? device_id {
|
||||
get;
|
||||
construct;
|
||||
@@ -426,7 +426,7 @@ namespace Frida.Inject {
|
||||
#endif
|
||||
}
|
||||
|
||||
private class ScriptRunner : Object, RpcPeer {
|
||||
private sealed class ScriptRunner : Object, RpcPeer {
|
||||
public TerminalMode terminal_mode {
|
||||
get;
|
||||
private set;
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Frida.Agent {
|
||||
PROCESS_TRANSITION
|
||||
}
|
||||
|
||||
private class Runner : Object, ProcessInvader, AgentSessionProvider, ExitHandler, ForkHandler, SpawnHandler {
|
||||
private sealed class Runner : Object, ProcessInvader, AgentSessionProvider, ExitHandler, ForkHandler, SpawnHandler {
|
||||
public static Runner shared_instance = null;
|
||||
public static Mutex shared_mutex;
|
||||
private static string? cached_agent_path = null;
|
||||
@@ -1621,7 +1621,7 @@ namespace Frida.Agent {
|
||||
}
|
||||
#endif
|
||||
|
||||
private class LiveAgentSession : BaseAgentSession {
|
||||
private sealed class LiveAgentSession : BaseAgentSession {
|
||||
public uint registration_id {
|
||||
get;
|
||||
set;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class BufferBuilder : Object {
|
||||
public sealed class BufferBuilder : Object {
|
||||
public ByteOrder byte_order {
|
||||
get;
|
||||
construct;
|
||||
@@ -307,7 +307,7 @@ namespace Frida {
|
||||
NUL
|
||||
}
|
||||
|
||||
public class Buffer : Object {
|
||||
public sealed class Buffer : Object {
|
||||
public Bytes bytes {
|
||||
get;
|
||||
construct;
|
||||
@@ -466,7 +466,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class BufferReader {
|
||||
public sealed class BufferReader {
|
||||
public size_t available {
|
||||
get {
|
||||
return buffer.bytes.get_size () - offset;
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
namespace Frida {
|
||||
public sealed class ChannelRegistry : Object {
|
||||
public signal void channel_closed (ChannelId id);
|
||||
|
||||
private Gee.Map<ChannelId?, weak IOStream> channels =
|
||||
new Gee.HashMap<ChannelId?, weak IOStream> (ChannelId.hash, ChannelId.equal);
|
||||
|
||||
~ChannelRegistry () {
|
||||
clear ();
|
||||
}
|
||||
|
||||
public void clear () {
|
||||
foreach (IOStream stream in channels.values.to_array ()) {
|
||||
var channel_stream = stream as ChannelStream;
|
||||
if (channel_stream != null)
|
||||
channel_stream.abandon ();
|
||||
}
|
||||
channels.clear ();
|
||||
}
|
||||
|
||||
public void register (ChannelId id, IOStream stream) {
|
||||
stream.set_data ("channel-registry-entry", new Entry (this, id));
|
||||
lock (channels)
|
||||
channels[id] = stream;
|
||||
}
|
||||
|
||||
public IOStream link (ChannelId id) throws Error {
|
||||
IOStream? stream;
|
||||
lock (channels)
|
||||
stream = channels[id];
|
||||
if (stream == null)
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid channel ID");
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void unlink (ChannelId id) {
|
||||
lock (channels) {
|
||||
if (!channels.unset (id))
|
||||
return;
|
||||
}
|
||||
|
||||
channel_closed (id);
|
||||
}
|
||||
|
||||
private class Entry {
|
||||
public ChannelRegistry parent;
|
||||
public ChannelId id;
|
||||
|
||||
public Entry (ChannelRegistry parent, ChannelId id) {
|
||||
this.parent = parent;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
~Entry () {
|
||||
parent.unlink (id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ChannelEndpoint : Object, Channel {
|
||||
private IOStream? stream;
|
||||
|
||||
private ByteArray write_queue = new ByteArray ();
|
||||
private bool writing = false;
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
public ChannelEndpoint (IOStream stream) {
|
||||
this.stream = stream;
|
||||
|
||||
read_loop.begin ();
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws Error, IOError {
|
||||
io_cancellable.cancel ();
|
||||
}
|
||||
|
||||
public async void input (uint8[] data, Cancellable? cancellable) throws Error, IOError {
|
||||
if (io_cancellable.is_cancelled ())
|
||||
throw new Error.INVALID_OPERATION ("Channel is closed");
|
||||
|
||||
write_queue.append (data);
|
||||
|
||||
if (!writing) {
|
||||
writing = true;
|
||||
|
||||
var source = new IdleSource ();
|
||||
source.set_callback (() => {
|
||||
process_write_queue.begin ();
|
||||
return false;
|
||||
});
|
||||
source.attach (MainContext.get_thread_default ());
|
||||
}
|
||||
}
|
||||
|
||||
private async void read_loop () {
|
||||
var input = stream.get_input_stream ();
|
||||
var buffer = new uint8[64 * 1024];
|
||||
|
||||
while (true) {
|
||||
ssize_t n;
|
||||
try {
|
||||
n = yield input.read_async (buffer, Priority.DEFAULT, io_cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
break;
|
||||
}
|
||||
|
||||
output (buffer[:n]);
|
||||
|
||||
if (n == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
stream.close_async.begin ();
|
||||
stream = null;
|
||||
}
|
||||
|
||||
private async void process_write_queue () {
|
||||
if (stream != null) {
|
||||
var output = stream.get_output_stream ();
|
||||
|
||||
while (write_queue.len > 0) {
|
||||
uint8[] batch = write_queue.steal ();
|
||||
|
||||
size_t bytes_written;
|
||||
try {
|
||||
yield output.write_all_async (batch, Priority.DEFAULT, io_cancellable, out bytes_written);
|
||||
} catch (GLib.Error e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ChannelStream : VirtualStream {
|
||||
public Channel channel {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private ByteArray recv_queue = new ByteArray ();
|
||||
private ByteArray send_queue = new ByteArray ();
|
||||
|
||||
public ChannelStream (Channel channel) {
|
||||
Object (channel: channel);
|
||||
}
|
||||
|
||||
construct {
|
||||
channel.output.connect (on_output);
|
||||
}
|
||||
|
||||
public void abandon () {
|
||||
with_state_lock (() => {
|
||||
state = CLOSED;
|
||||
update_pending_io ();
|
||||
});
|
||||
}
|
||||
|
||||
protected override IOCondition query_events () {
|
||||
IOCondition new_events = 0;
|
||||
|
||||
if (recv_queue.len != 0 || state == CLOSED)
|
||||
new_events |= IN;
|
||||
|
||||
if (state == OPEN)
|
||||
new_events |= OUT;
|
||||
|
||||
return new_events;
|
||||
}
|
||||
|
||||
protected override void handle_close () {
|
||||
channel.close.begin (null);
|
||||
}
|
||||
|
||||
public override ssize_t read (uint8[] buffer) throws IOError {
|
||||
ssize_t n = 0;
|
||||
with_state_lock (() => {
|
||||
n = ssize_t.min (recv_queue.len, buffer.length);
|
||||
if (n > 0) {
|
||||
Memory.copy (buffer, recv_queue.data, n);
|
||||
recv_queue.remove_range (0, (uint) n);
|
||||
|
||||
update_pending_io ();
|
||||
} else {
|
||||
if (state == OPEN)
|
||||
n = -1;
|
||||
}
|
||||
});
|
||||
|
||||
if (n == -1)
|
||||
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
public override ssize_t write (uint8[] buffer) throws IOError {
|
||||
with_state_lock (() => {
|
||||
send_queue.append (buffer);
|
||||
});
|
||||
|
||||
if (main_context.is_owner ()) {
|
||||
process_send_queue ();
|
||||
} else {
|
||||
var source = new IdleSource ();
|
||||
source.set_callback (() => {
|
||||
process_send_queue ();
|
||||
return Source.REMOVE;
|
||||
});
|
||||
source.attach (main_context);
|
||||
}
|
||||
|
||||
return buffer.length;
|
||||
}
|
||||
|
||||
private void process_send_queue () {
|
||||
uint8[]? chunk = null;
|
||||
with_state_lock (() => {
|
||||
size_t n = send_queue.len;
|
||||
if (n == 0)
|
||||
return;
|
||||
chunk = send_queue.data[0:n];
|
||||
send_queue.remove_range (0, (uint) n);
|
||||
});
|
||||
if (chunk == null)
|
||||
return;
|
||||
|
||||
channel.input.begin (chunk, io_cancellable);
|
||||
}
|
||||
|
||||
private void on_output (uint8[] data) {
|
||||
with_state_lock (() => {
|
||||
if (data.length != 0)
|
||||
recv_queue.append (data);
|
||||
else
|
||||
state = CLOSED;
|
||||
update_pending_io ();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class CFArray<T> {
|
||||
public sealed class CFArray<T> {
|
||||
private CoreFoundation.Array handle;
|
||||
|
||||
public static CFArray<T> wrap<T> (void * handle) {
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ namespace Frida {
|
||||
return yield connection.get_proxy (null, ObjectPath.HOST_SESSION, DBusProxyFlags.NONE, cancellable);
|
||||
}
|
||||
|
||||
private class DummyInputStream : InputStream {
|
||||
private sealed class DummyInputStream : InputStream {
|
||||
private bool done = false;
|
||||
private Mutex mutex;
|
||||
private Cond cond;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
base_sources = [
|
||||
'session.vala',
|
||||
'session-glue.c',
|
||||
'channel.vala',
|
||||
'service.vala',
|
||||
'stream.vala',
|
||||
'rpc.vala',
|
||||
'p2p.vala',
|
||||
'p2p-glue.c',
|
||||
|
||||
+35
-233
@@ -169,7 +169,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class PeerSocket : Object, DatagramBased {
|
||||
public sealed class PeerSocket : Object, DatagramBased {
|
||||
public Nice.Agent agent {
|
||||
get;
|
||||
construct;
|
||||
@@ -452,6 +452,8 @@ namespace Frida {
|
||||
if ((_pending_io & c) != 0)
|
||||
source.set_ready_time (0);
|
||||
}
|
||||
|
||||
notify_property ("pending-io");
|
||||
}
|
||||
|
||||
private void prepare_for_io (int64 timeout, Cancellable? cancellable, out int64 deadline) throws IOError {
|
||||
@@ -563,7 +565,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class SctpConnection : IOStream {
|
||||
public sealed class SctpConnection : VirtualStream {
|
||||
public DatagramBased transport_socket {
|
||||
get;
|
||||
construct;
|
||||
@@ -584,55 +586,14 @@ namespace Frida {
|
||||
construct;
|
||||
}
|
||||
|
||||
public State state {
|
||||
get {
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
|
||||
public override InputStream input_stream {
|
||||
get {
|
||||
return _input_stream;
|
||||
}
|
||||
}
|
||||
|
||||
public override OutputStream output_stream {
|
||||
get {
|
||||
return _output_stream;
|
||||
}
|
||||
}
|
||||
|
||||
public IOCondition pending_io {
|
||||
get {
|
||||
lock (state)
|
||||
return sctp_events;
|
||||
}
|
||||
}
|
||||
|
||||
private State _state = CREATED;
|
||||
private SctpInputStream _input_stream;
|
||||
private SctpOutputStream _output_stream;
|
||||
|
||||
private DatagramBasedSource transport_source;
|
||||
private uint8[] transport_buffer = new uint8[65536];
|
||||
|
||||
private void * sctp_socket;
|
||||
private IOCondition sctp_events = 0;
|
||||
private SctpTimerSource sctp_source;
|
||||
private uint16 stream_id;
|
||||
private ByteArray dcep_message = new ByteArray ();
|
||||
|
||||
private Gee.Map<unowned Source, IOCondition> sources = new Gee.HashMap<unowned Source, IOCondition> ();
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
public enum State {
|
||||
CREATED,
|
||||
OPENING,
|
||||
OPENED,
|
||||
CLOSED
|
||||
}
|
||||
|
||||
public SctpConnection (DatagramBased transport_socket, PeerSetup setup, uint16 port, size_t max_message_size) {
|
||||
Object (
|
||||
transport_socket: transport_socket,
|
||||
@@ -649,14 +610,9 @@ namespace Frida {
|
||||
protected extern static void _initialize_sctp_backend ();
|
||||
|
||||
construct {
|
||||
_input_stream = new SctpInputStream (this);
|
||||
_output_stream = new SctpOutputStream (this);
|
||||
|
||||
sctp_socket = _create_sctp_socket ();
|
||||
_connect_sctp_socket (sctp_socket, port);
|
||||
|
||||
var main_context = MainContext.get_thread_default ();
|
||||
|
||||
transport_source = transport_socket.create_source (IOCondition.IN, io_cancellable);
|
||||
transport_source.set_callback (on_transport_socket_readable);
|
||||
transport_source.attach (main_context);
|
||||
@@ -669,17 +625,22 @@ namespace Frida {
|
||||
|
||||
protected extern void _connect_sctp_socket (void * sock, uint16 port);
|
||||
|
||||
public override bool close (GLib.Cancellable? cancellable) throws IOError {
|
||||
do_close ();
|
||||
return true;
|
||||
protected override VirtualStream.State query_initial_state () {
|
||||
return CREATED;
|
||||
}
|
||||
|
||||
public override async bool close_async (int io_priority, GLib.Cancellable? cancellable) throws IOError {
|
||||
do_close ();
|
||||
return true;
|
||||
protected override IOCondition query_events () {
|
||||
return _query_sctp_socket_events (sctp_socket);
|
||||
}
|
||||
|
||||
private void do_close () {
|
||||
protected override void update_pending_io () {
|
||||
base.update_pending_io ();
|
||||
sctp_source.invalidate ();
|
||||
}
|
||||
|
||||
protected extern static IOCondition _query_sctp_socket_events (void * sock);
|
||||
|
||||
protected override void handle_close () {
|
||||
sctp_source.destroy ();
|
||||
transport_source.destroy ();
|
||||
|
||||
@@ -689,13 +650,17 @@ namespace Frida {
|
||||
|
||||
public extern static void _close (void * sock);
|
||||
|
||||
public void shutdown (SctpShutdownType type) throws IOError {
|
||||
_shutdown (sctp_socket, type);
|
||||
public override void shutdown_read () throws IOError {
|
||||
_shutdown (sctp_socket, READ);
|
||||
}
|
||||
|
||||
public override void shutdown_write () throws IOError {
|
||||
_shutdown (sctp_socket, WRITE);
|
||||
}
|
||||
|
||||
public extern static void _shutdown (void * sock, SctpShutdownType type) throws IOError;
|
||||
|
||||
public ssize_t recv (uint8[] buffer) throws IOError {
|
||||
public override ssize_t read (uint8[] buffer) throws IOError {
|
||||
ssize_t n = -1;
|
||||
|
||||
try {
|
||||
@@ -711,18 +676,18 @@ namespace Frida {
|
||||
handle_dcep_message (stream_id, dcep_message.steal ());
|
||||
}
|
||||
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
|
||||
} else if (protocol_id == NONE || _state != OPENED) {
|
||||
} else if (protocol_id == NONE || state != OPEN) {
|
||||
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
|
||||
}
|
||||
} finally {
|
||||
update_sctp_events ();
|
||||
update_pending_io ();
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
public ssize_t send (uint8[] buffer) throws IOError {
|
||||
if (_state != OPENED)
|
||||
public override ssize_t write (uint8[] buffer) throws IOError {
|
||||
if (state != OPEN)
|
||||
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
|
||||
|
||||
ssize_t n = ssize_t.min (buffer.length, (ssize_t) max_message_size);
|
||||
@@ -730,20 +695,10 @@ namespace Frida {
|
||||
try {
|
||||
return _send (sctp_socket, stream_id, WEBRTC_BINARY, buffer[0:n]);
|
||||
} finally {
|
||||
update_sctp_events ();
|
||||
update_pending_io ();
|
||||
}
|
||||
}
|
||||
|
||||
public void register_source (Source source, IOCondition condition) {
|
||||
lock (state)
|
||||
sources[source] = condition | IOCondition.ERR | IOCondition.HUP;
|
||||
}
|
||||
|
||||
public void unregister_source (Source source) {
|
||||
lock (state)
|
||||
sources.unset (source);
|
||||
}
|
||||
|
||||
private bool on_transport_socket_readable (DatagramBased datagram_based, IOCondition condition) {
|
||||
var v = InputVector ();
|
||||
v.buffer = transport_buffer;
|
||||
@@ -783,9 +738,9 @@ namespace Frida {
|
||||
}
|
||||
|
||||
protected void _on_sctp_socket_events_changed () {
|
||||
update_sctp_events ();
|
||||
update_pending_io ();
|
||||
|
||||
if (_state == CREATED && setup == ACTIVE && (sctp_events & IOCondition.OUT) != 0) {
|
||||
if (state == CREATED && setup == ACTIVE && (pending_io & IOCondition.OUT) != 0) {
|
||||
stream_id = 1;
|
||||
|
||||
uint8[] open_message = {
|
||||
@@ -799,31 +754,12 @@ namespace Frida {
|
||||
};
|
||||
try {
|
||||
_send (sctp_socket, stream_id, WEBRTC_DCEP, open_message);
|
||||
_state = OPENING;
|
||||
state = OPENING;
|
||||
} catch (IOError e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void update_sctp_events () {
|
||||
IOCondition new_events = _query_sctp_socket_events (sctp_socket);
|
||||
|
||||
lock (state) {
|
||||
sctp_events = new_events;
|
||||
|
||||
foreach (var entry in sources.entries) {
|
||||
unowned Source source = entry.key;
|
||||
IOCondition c = entry.value;
|
||||
if ((new_events & c) != 0)
|
||||
source.set_ready_time (0);
|
||||
}
|
||||
|
||||
sctp_source.invalidate ();
|
||||
}
|
||||
}
|
||||
|
||||
protected extern static IOCondition _query_sctp_socket_events (void * sock);
|
||||
|
||||
protected extern static ssize_t _recv (void * sock, uint8[] buffer, out uint16 stream_id,
|
||||
out PayloadProtocolId protocol_id, out SctpMessageFlags message_flags) throws IOError;
|
||||
|
||||
@@ -835,7 +771,7 @@ namespace Frida {
|
||||
|
||||
switch (type) {
|
||||
case DATA_CHANNEL_OPEN: {
|
||||
if (_state != CREATED || setup == ACTIVE)
|
||||
if (state != CREATED || setup == ACTIVE)
|
||||
return;
|
||||
|
||||
this.stream_id = stream_id;
|
||||
@@ -843,15 +779,15 @@ namespace Frida {
|
||||
uint8[] reply = { DcepMessageType.DATA_CHANNEL_ACK };
|
||||
_send (sctp_socket, stream_id, WEBRTC_DCEP, reply);
|
||||
|
||||
_state = OPENED;
|
||||
state = OPEN;
|
||||
|
||||
break;
|
||||
}
|
||||
case DATA_CHANNEL_ACK:
|
||||
if (_state != OPENING)
|
||||
if (state != OPENING)
|
||||
return;
|
||||
|
||||
_state = OPENED;
|
||||
state = OPEN;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -886,140 +822,6 @@ namespace Frida {
|
||||
DATA_CHANNEL_ACK = 0x02
|
||||
}
|
||||
|
||||
private class SctpInputStream : InputStream, PollableInputStream {
|
||||
public weak SctpConnection connection {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public SctpInputStream (SctpConnection connection) {
|
||||
Object (connection: connection);
|
||||
}
|
||||
|
||||
public override bool close (Cancellable? cancellable) throws IOError {
|
||||
connection.shutdown (READ);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
|
||||
return close (cancellable);
|
||||
}
|
||||
|
||||
public override ssize_t read (uint8[] buffer, Cancellable? cancellable) throws IOError {
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
public bool can_poll () {
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool is_readable () {
|
||||
return (connection.pending_io & IOCondition.IN) != 0;
|
||||
}
|
||||
|
||||
public PollableSource create_source (Cancellable? cancellable) {
|
||||
return new PollableSource.full (this, new SctpIOSource (connection, IOCondition.IN), cancellable);
|
||||
}
|
||||
|
||||
public ssize_t read_nonblocking_fn (uint8[] buffer) throws GLib.Error {
|
||||
return connection.recv (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private class SctpOutputStream : OutputStream, PollableOutputStream {
|
||||
public weak SctpConnection connection {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public SctpOutputStream (SctpConnection connection) {
|
||||
Object (connection: connection);
|
||||
}
|
||||
|
||||
public override bool close (Cancellable? cancellable) throws IOError {
|
||||
connection.shutdown (WRITE);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
|
||||
return close (cancellable);
|
||||
}
|
||||
|
||||
public override bool flush (GLib.Cancellable? cancellable) throws GLib.Error {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async bool flush_async (int io_priority, GLib.Cancellable? cancellable) throws GLib.Error {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override ssize_t write (uint8[] buffer, Cancellable? cancellable) throws IOError {
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
public bool can_poll () {
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool is_writable () {
|
||||
return (connection.pending_io & IOCondition.OUT) != 0;
|
||||
}
|
||||
|
||||
public PollableSource create_source (Cancellable? cancellable) {
|
||||
return new PollableSource.full (this, new SctpIOSource (connection, IOCondition.OUT), cancellable);
|
||||
}
|
||||
|
||||
public ssize_t write_nonblocking_fn (uint8[]? buffer) throws GLib.Error {
|
||||
return connection.send (buffer);
|
||||
}
|
||||
|
||||
public PollableReturn writev_nonblocking_fn (OutputVector[] vectors, out size_t bytes_written) throws GLib.Error {
|
||||
assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
private class SctpIOSource : Source {
|
||||
public SctpConnection connection;
|
||||
public IOCondition condition;
|
||||
|
||||
public SctpIOSource (SctpConnection connection, IOCondition condition) {
|
||||
this.connection = connection;
|
||||
this.condition = condition;
|
||||
|
||||
connection.register_source (this, condition);
|
||||
}
|
||||
|
||||
~SctpIOSource () {
|
||||
connection.unregister_source (this);
|
||||
}
|
||||
|
||||
protected override bool prepare (out int timeout) {
|
||||
timeout = -1;
|
||||
return (connection.pending_io & condition) != 0;
|
||||
}
|
||||
|
||||
protected override bool check () {
|
||||
return (connection.pending_io & condition) != 0;
|
||||
}
|
||||
|
||||
protected override bool dispatch (SourceFunc? callback) {
|
||||
set_ready_time (-1);
|
||||
|
||||
if (callback == null)
|
||||
return Source.REMOVE;
|
||||
|
||||
return callback ();
|
||||
}
|
||||
|
||||
protected static bool closure_callback (Closure closure) {
|
||||
var return_value = Value (typeof (bool));
|
||||
|
||||
closure.invoke (ref return_value, {});
|
||||
|
||||
return return_value.get_boolean ();
|
||||
}
|
||||
}
|
||||
|
||||
private class SctpTimerSource : Source {
|
||||
private static int64 last_process_time = -1;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class Promise<T> {
|
||||
public sealed class Promise<T> {
|
||||
private Impl<T> impl;
|
||||
|
||||
public Future<T> future {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class RpcClient : Object {
|
||||
public sealed class RpcClient : Object {
|
||||
public weak RpcPeer peer {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
namespace Frida {
|
||||
public sealed class ServiceSessionRegistry : Object {
|
||||
public signal void session_closed (ServiceSessionId id);
|
||||
|
||||
private Gee.Map<ServiceSessionId?, ServiceSession> sessions =
|
||||
new Gee.HashMap<ServiceSessionId?, ServiceSession> (ServiceSessionId.hash, ServiceSessionId.equal);
|
||||
|
||||
~ServiceSessionRegistry () {
|
||||
clear ();
|
||||
}
|
||||
|
||||
public void clear () {
|
||||
foreach (var session in sessions.values.to_array ())
|
||||
session.close ();
|
||||
sessions.clear ();
|
||||
}
|
||||
|
||||
public void register (ServiceSessionId id, ServiceSession session) {
|
||||
sessions[id] = session;
|
||||
|
||||
ServiceSessionId? boxed_id = id;
|
||||
session.set_data ("service-session-id", boxed_id);
|
||||
|
||||
session.close.connect (on_session_close);
|
||||
}
|
||||
|
||||
public ServiceSession link (ServiceSessionId id) throws Error {
|
||||
var session = sessions[id];
|
||||
if (session == null)
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid session ID");
|
||||
return session;
|
||||
}
|
||||
|
||||
public void unlink (ServiceSessionId id) {
|
||||
ServiceSession? session;
|
||||
if (sessions.unset (id, out session)) {
|
||||
session.close.disconnect (on_session_close);
|
||||
|
||||
session_closed (id);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_session_close (ServiceSession session) {
|
||||
ServiceSessionId? id = session.get_data ("service-session-id");
|
||||
unlink (id);
|
||||
}
|
||||
}
|
||||
}
|
||||
+105
-25
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
[DBus (name = "re.frida.HostSession16")]
|
||||
[DBus (name = "re.frida.HostSession17")]
|
||||
public interface HostSession : Object {
|
||||
public abstract async void ping (uint interval_seconds, Cancellable? cancellable) throws GLib.Error;
|
||||
|
||||
@@ -27,6 +27,10 @@ namespace Frida {
|
||||
public abstract async InjectorPayloadId inject_library_blob (uint pid, uint8[] blob, string entrypoint, string data,
|
||||
Cancellable? cancellable) throws GLib.Error;
|
||||
|
||||
public abstract async ChannelId open_channel (string address, Cancellable? cancellable) throws GLib.Error;
|
||||
|
||||
public abstract async ServiceSessionId open_service (string address, Cancellable? cancellable) throws GLib.Error;
|
||||
|
||||
public signal void spawn_added (HostSpawnInfo info);
|
||||
public signal void spawn_removed (HostSpawnInfo info);
|
||||
public signal void child_added (HostChildInfo info);
|
||||
@@ -34,10 +38,12 @@ namespace Frida {
|
||||
public signal void process_crashed (CrashInfo crash);
|
||||
public signal void output (uint pid, int fd, uint8[] data);
|
||||
public signal void agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash);
|
||||
public signal void channel_closed (ChannelId id);
|
||||
public signal void service_session_closed (ServiceSessionId id);
|
||||
public signal void uninjected (InjectorPayloadId id);
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.AgentSessionProvider16")]
|
||||
[DBus (name = "re.frida.AgentSessionProvider17")]
|
||||
public interface AgentSessionProvider : Object {
|
||||
public abstract async void open (AgentSessionId id, HashTable<string, Variant> options,
|
||||
Cancellable? cancellable) throws GLib.Error;
|
||||
@@ -52,7 +58,7 @@ namespace Frida {
|
||||
public signal void child_gating_changed (uint subscriber_count);
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.AgentSession16")]
|
||||
[DBus (name = "re.frida.AgentSession17")]
|
||||
public interface AgentSession : Object {
|
||||
public abstract async void close (Cancellable? cancellable) throws GLib.Error;
|
||||
|
||||
@@ -94,7 +100,7 @@ namespace Frida {
|
||||
public signal void candidate_gathering_done ();
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.AgentController16")]
|
||||
[DBus (name = "re.frida.AgentController17")]
|
||||
public interface AgentController : Object {
|
||||
#if !WINDOWS
|
||||
public abstract async HostChildId prepare_to_fork (uint parent_pid, Cancellable? cancellable, out uint parent_injectee_id,
|
||||
@@ -115,7 +121,7 @@ namespace Frida {
|
||||
Cancellable? cancellable) throws GLib.Error;
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.AgentMessageSink16")]
|
||||
[DBus (name = "re.frida.AgentMessageSink17")]
|
||||
public interface AgentMessageSink : Object {
|
||||
public abstract async void post_messages (AgentMessage[] messages, uint batch_id,
|
||||
Cancellable? cancellable) throws GLib.Error;
|
||||
@@ -145,7 +151,7 @@ namespace Frida {
|
||||
DEBUGGER
|
||||
}
|
||||
|
||||
public class AgentMessageTransmitter : Object {
|
||||
public sealed class AgentMessageTransmitter : Object {
|
||||
public signal void closed ();
|
||||
public signal void new_candidates (string[] candidate_sdps);
|
||||
public signal void candidate_gathering_done ();
|
||||
@@ -743,13 +749,30 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.TransportBroker16")]
|
||||
[DBus (name = "re.frida.Channel17")]
|
||||
public interface Channel : Object {
|
||||
public abstract async void close (Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void input (uint8[] data, Cancellable? cancellable) throws GLib.Error;
|
||||
public signal void output (uint8[] data);
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.ServiceSession17")]
|
||||
public interface ServiceSession : Object {
|
||||
public signal void close ();
|
||||
public signal void message (Variant message);
|
||||
|
||||
public abstract async void activate (Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void cancel (Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async Variant request (Variant parameters, Cancellable? cancellable) throws GLib.Error;
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.TransportBroker17")]
|
||||
public interface TransportBroker : Object {
|
||||
public abstract async void open_tcp_transport (AgentSessionId id, Cancellable? cancellable, out uint16 port,
|
||||
out string token) throws GLib.Error;
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.PortalSession16")]
|
||||
[DBus (name = "re.frida.PortalSession17")]
|
||||
public interface PortalSession : Object {
|
||||
public abstract async void join (HostApplicationInfo app, SpawnStartState current_state,
|
||||
AgentSessionId[] interrupted_sessions, HashTable<string, Variant> options, Cancellable? cancellable,
|
||||
@@ -758,19 +781,19 @@ namespace Frida {
|
||||
public signal void kill ();
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.BusSession16")]
|
||||
[DBus (name = "re.frida.BusSession17")]
|
||||
public interface BusSession : Object {
|
||||
public abstract async void attach (Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void post (string json, bool has_data, uint8[] data, Cancellable? cancellable) throws GLib.Error;
|
||||
public signal void message (string json, bool has_data, uint8[] data);
|
||||
}
|
||||
|
||||
[DBus (name = "re.frida.AuthenticationService16")]
|
||||
[DBus (name = "re.frida.AuthenticationService17")]
|
||||
public interface AuthenticationService : Object {
|
||||
public abstract async string authenticate (string token, Cancellable? cancellable) throws GLib.Error;
|
||||
}
|
||||
|
||||
public class StaticAuthenticationService : Object, AuthenticationService {
|
||||
public sealed class StaticAuthenticationService : Object, AuthenticationService {
|
||||
public string token_hash {
|
||||
get;
|
||||
construct;
|
||||
@@ -795,13 +818,13 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class NullAuthenticationService : Object, AuthenticationService {
|
||||
public sealed class NullAuthenticationService : Object, AuthenticationService {
|
||||
public async string authenticate (string token, Cancellable? cancellable) throws Error, IOError {
|
||||
throw new Error.INVALID_OPERATION ("Authentication not expected");
|
||||
}
|
||||
}
|
||||
|
||||
public class UnauthorizedHostSession : Object, HostSession {
|
||||
public sealed class UnauthorizedHostSession : Object, HostSession {
|
||||
public async void ping (uint interval_seconds, Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_authorized ();
|
||||
}
|
||||
@@ -875,9 +898,17 @@ namespace Frida {
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_authorized ();
|
||||
}
|
||||
|
||||
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_authorized ();
|
||||
}
|
||||
|
||||
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_authorized ();
|
||||
}
|
||||
}
|
||||
|
||||
public class UnauthorizedPortalSession : Object, PortalSession {
|
||||
public sealed class UnauthorizedPortalSession : Object, PortalSession {
|
||||
public async void join (HostApplicationInfo app, SpawnStartState current_state,
|
||||
AgentSessionId[] interrupted_sessions, HashTable<string, Variant> options,
|
||||
Cancellable? cancellable, out SpawnStartState next_state) throws Error, IOError {
|
||||
@@ -885,7 +916,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class UnauthorizedBusSession : Object, BusSession {
|
||||
public sealed class UnauthorizedBusSession : Object, BusSession {
|
||||
public async void attach (Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_authorized ();
|
||||
}
|
||||
@@ -1083,7 +1114,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class FrontmostQueryOptions : Object {
|
||||
public sealed class FrontmostQueryOptions : Object {
|
||||
public Scope scope {
|
||||
get;
|
||||
set;
|
||||
@@ -1113,7 +1144,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class ApplicationQueryOptions : Object {
|
||||
public sealed class ApplicationQueryOptions : Object {
|
||||
public Scope scope {
|
||||
get;
|
||||
set;
|
||||
@@ -1171,7 +1202,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcessQueryOptions : Object {
|
||||
public sealed class ProcessQueryOptions : Object {
|
||||
public Scope scope {
|
||||
get;
|
||||
set;
|
||||
@@ -1313,7 +1344,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class SessionOptions : Object {
|
||||
public sealed class SessionOptions : Object {
|
||||
public Realm realm {
|
||||
get;
|
||||
set;
|
||||
@@ -1502,6 +1533,46 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ChannelId {
|
||||
public string handle;
|
||||
|
||||
public ChannelId (string handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public ChannelId.generate () {
|
||||
this.handle = Uuid.string_random ().replace ("-", "");
|
||||
}
|
||||
|
||||
public static uint hash (ChannelId? id) {
|
||||
return id.handle.hash ();
|
||||
}
|
||||
|
||||
public static bool equal (ChannelId? a, ChannelId? b) {
|
||||
return a.handle == b.handle;
|
||||
}
|
||||
}
|
||||
|
||||
public struct ServiceSessionId {
|
||||
public string handle;
|
||||
|
||||
public ServiceSessionId (string handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public ServiceSessionId.generate () {
|
||||
this.handle = Uuid.string_random ().replace ("-", "");
|
||||
}
|
||||
|
||||
public static uint hash (ServiceSessionId? id) {
|
||||
return id.handle.hash ();
|
||||
}
|
||||
|
||||
public static bool equal (ServiceSessionId? a, ServiceSessionId? b) {
|
||||
return a.handle == b.handle;
|
||||
}
|
||||
}
|
||||
|
||||
public struct AgentScriptId {
|
||||
public uint handle;
|
||||
|
||||
@@ -1518,7 +1589,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class ScriptOptions : Object {
|
||||
public sealed class ScriptOptions : Object {
|
||||
public string? name {
|
||||
get;
|
||||
set;
|
||||
@@ -1608,7 +1679,7 @@ namespace Frida {
|
||||
SHARED_MEMORY
|
||||
}
|
||||
|
||||
public class SnapshotOptions : Object {
|
||||
public sealed class SnapshotOptions : Object {
|
||||
public string? warmup_script {
|
||||
get;
|
||||
set;
|
||||
@@ -1683,7 +1754,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class PortalOptions : Object {
|
||||
public sealed class PortalOptions : Object {
|
||||
public TlsCertificate? certificate {
|
||||
get;
|
||||
set;
|
||||
@@ -1746,7 +1817,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class PeerOptions : Object {
|
||||
public sealed class PeerOptions : Object {
|
||||
public string? stun_server {
|
||||
get;
|
||||
set;
|
||||
@@ -1807,7 +1878,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class Relay : Object {
|
||||
public sealed class Relay : Object {
|
||||
public string address {
|
||||
get;
|
||||
construct;
|
||||
@@ -2048,7 +2119,8 @@ 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 CHILD_SESSION = "/re/frida/ChildSession";
|
||||
public const string CHANNEL = "/re/frida/Channel";
|
||||
public const string SERVICE = "/re/frida/Service";
|
||||
public const string TRANSPORT_BROKER = "/re/frida/TransportBroker";
|
||||
public const string PORTAL_SESSION = "/re/frida/PortalSession";
|
||||
public const string BUS_SESSION = "/re/frida/BusSession";
|
||||
@@ -2061,6 +2133,14 @@ namespace Frida {
|
||||
public static string for_agent_message_sink (AgentSessionId id) {
|
||||
return AGENT_MESSAGE_SINK + "/" + id.handle;
|
||||
}
|
||||
|
||||
public static string for_channel (ChannelId id) {
|
||||
return CHANNEL + "/" + id.handle;
|
||||
}
|
||||
|
||||
public static string for_service_session (ServiceSessionId id) {
|
||||
return SERVICE + "/" + id.handle;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Marshal {
|
||||
|
||||
+53
-240
@@ -97,7 +97,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class EndpointParameters : Object {
|
||||
public sealed class EndpointParameters : Object {
|
||||
public string? address {
|
||||
get;
|
||||
construct;
|
||||
@@ -234,7 +234,7 @@ namespace Frida {
|
||||
return (inet_addr.get_family () == IPV6) ? @"[$host]" : host;
|
||||
}
|
||||
|
||||
public class WebService : Object {
|
||||
public sealed class WebService : Object {
|
||||
public signal void incoming (IOStream connection, SocketAddress remote_address, DynamicInterface? dynamic_iface);
|
||||
|
||||
public EndpointParameters endpoint_params {
|
||||
@@ -548,12 +548,17 @@ namespace Frida {
|
||||
|
||||
IOStream soup_stream = connection.get_io_stream ();
|
||||
|
||||
SocketConnection socket_stream;
|
||||
soup_stream.get ("base-iostream", out socket_stream);
|
||||
IOStream base_iostream;
|
||||
soup_stream.get ("base-iostream", out base_iostream);
|
||||
|
||||
SocketAddress remote_address;
|
||||
SocketAddress? remote_address = null;
|
||||
SocketConnection? sc = base_iostream as SocketConnection;
|
||||
if (sc == null) {
|
||||
IOStream tls_stream = base_iostream;
|
||||
tls_stream.get ("base-io-stream", out sc);
|
||||
}
|
||||
try {
|
||||
remote_address = socket_stream.get_remote_address ();
|
||||
remote_address = sc.get_remote_address ();
|
||||
} catch (GLib.Error e) {
|
||||
assert_not_reached ();
|
||||
}
|
||||
@@ -852,7 +857,7 @@ namespace Frida {
|
||||
public abstract void start ();
|
||||
}
|
||||
|
||||
public class DynamicInterface : Object {
|
||||
public sealed class DynamicInterface : Object {
|
||||
public string name {
|
||||
get;
|
||||
construct;
|
||||
@@ -870,7 +875,7 @@ namespace Frida {
|
||||
|
||||
public extern static unowned string _version_string ();
|
||||
|
||||
private class WebConnection : IOStream {
|
||||
private sealed class WebConnection : VirtualStream {
|
||||
public signal void websocket_closed ();
|
||||
|
||||
public Soup.WebsocketConnection websocket {
|
||||
@@ -878,37 +883,9 @@ namespace Frida {
|
||||
construct;
|
||||
}
|
||||
|
||||
public override InputStream input_stream {
|
||||
get {
|
||||
return _input_stream;
|
||||
}
|
||||
}
|
||||
|
||||
public override OutputStream output_stream {
|
||||
get {
|
||||
return _output_stream;
|
||||
}
|
||||
}
|
||||
|
||||
public IOCondition pending_io {
|
||||
get {
|
||||
lock (state)
|
||||
return _pending_io;
|
||||
}
|
||||
}
|
||||
|
||||
private WebInputStream _input_stream;
|
||||
private WebOutputStream _output_stream;
|
||||
|
||||
private Soup.WebsocketState state;
|
||||
private IOCondition _pending_io;
|
||||
private ByteArray recv_queue = new ByteArray ();
|
||||
private ByteArray send_queue = new ByteArray ();
|
||||
|
||||
private Gee.Map<unowned Source, IOCondition> sources = new Gee.HashMap<unowned Source, IOCondition> ();
|
||||
|
||||
private MainContext main_context;
|
||||
|
||||
public WebConnection (Soup.WebsocketConnection websocket) {
|
||||
Object (websocket: websocket);
|
||||
}
|
||||
@@ -916,14 +893,6 @@ namespace Frida {
|
||||
construct {
|
||||
websocket.max_incoming_payload_size = (256 * 1024) + 1; // XXX: There's an off-by-one error in libsoup
|
||||
|
||||
_input_stream = new WebInputStream (this);
|
||||
_output_stream = new WebOutputStream (this);
|
||||
|
||||
state = websocket.state;
|
||||
_pending_io = (state == OPEN) ? IOCondition.OUT : IOCondition.IN;
|
||||
|
||||
main_context = MainContext.ref_thread_default ();
|
||||
|
||||
websocket.closed.connect (on_closed);
|
||||
websocket.message.connect (on_message);
|
||||
}
|
||||
@@ -933,51 +902,50 @@ namespace Frida {
|
||||
websocket.closed.disconnect (on_closed);
|
||||
}
|
||||
|
||||
public override bool close (GLib.Cancellable? cancellable) throws IOError {
|
||||
_close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async bool close_async (int io_priority, GLib.Cancellable? cancellable) throws IOError {
|
||||
_close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void _close () {
|
||||
if (main_context.is_owner ()) {
|
||||
do_close ();
|
||||
} else {
|
||||
var source = new IdleSource ();
|
||||
source.set_callback (() => {
|
||||
do_close ();
|
||||
return Source.REMOVE;
|
||||
});
|
||||
source.attach (main_context);
|
||||
protected override VirtualStream.State query_initial_state () {
|
||||
switch (websocket.state) {
|
||||
case OPEN:
|
||||
case CLOSING:
|
||||
return OPEN;
|
||||
case CLOSED:
|
||||
return CLOSED;
|
||||
}
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
private void do_close () {
|
||||
protected override IOCondition query_events () {
|
||||
IOCondition new_events = 0;
|
||||
|
||||
if (recv_queue.len > 0 || state != OPEN)
|
||||
new_events |= IN;
|
||||
|
||||
if (state == OPEN)
|
||||
new_events |= OUT;
|
||||
|
||||
return new_events;
|
||||
}
|
||||
|
||||
protected override void handle_close () {
|
||||
if (websocket.state != OPEN)
|
||||
return;
|
||||
|
||||
websocket.close (1000, "Closing");
|
||||
}
|
||||
|
||||
public ssize_t recv (uint8[] buffer) throws IOError {
|
||||
ssize_t n;
|
||||
lock (state) {
|
||||
public override ssize_t read (uint8[] buffer) throws IOError {
|
||||
ssize_t n = 0;
|
||||
with_state_lock (() => {
|
||||
n = ssize_t.min (recv_queue.len, buffer.length);
|
||||
if (n > 0) {
|
||||
Memory.copy (buffer, recv_queue.data, n);
|
||||
recv_queue.remove_range (0, (uint) n);
|
||||
|
||||
recompute_pending_io_unlocked ();
|
||||
update_pending_io ();
|
||||
} else {
|
||||
if (state == OPEN)
|
||||
n = -1;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
if (n == -1)
|
||||
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
|
||||
@@ -985,9 +953,10 @@ namespace Frida {
|
||||
return n;
|
||||
}
|
||||
|
||||
public ssize_t send (uint8[] buffer) {
|
||||
lock (state)
|
||||
public override ssize_t write (uint8[] buffer) {
|
||||
with_state_lock (() => {
|
||||
send_queue.append (buffer);
|
||||
});
|
||||
|
||||
if (main_context.is_owner ()) {
|
||||
process_send_queue ();
|
||||
@@ -1011,190 +980,34 @@ namespace Frida {
|
||||
|
||||
while (true) {
|
||||
uint8[]? chunk = null;
|
||||
lock (state) {
|
||||
with_state_lock (() => {
|
||||
size_t n = size_t.min (send_queue.len, max_message_size);
|
||||
if (n == 0)
|
||||
return;
|
||||
chunk = send_queue.data[0:n];
|
||||
send_queue.remove_range (0, (uint) n);
|
||||
}
|
||||
});
|
||||
if (chunk == null)
|
||||
return;
|
||||
|
||||
websocket.send_binary (chunk);
|
||||
}
|
||||
}
|
||||
|
||||
public void register_source (Source source, IOCondition condition) {
|
||||
lock (state)
|
||||
sources[source] = condition;
|
||||
}
|
||||
|
||||
public void unregister_source (Source source) {
|
||||
lock (state)
|
||||
sources.unset (source);
|
||||
}
|
||||
|
||||
private void on_closed () {
|
||||
lock (state) {
|
||||
state = websocket.state;
|
||||
recompute_pending_io_unlocked ();
|
||||
}
|
||||
with_state_lock (() => {
|
||||
state = CLOSED;
|
||||
update_pending_io ();
|
||||
});
|
||||
|
||||
websocket_closed ();
|
||||
}
|
||||
|
||||
private void on_message (int type, Bytes message) {
|
||||
lock (state) {
|
||||
with_state_lock (() => {
|
||||
recv_queue.append (message.get_data ());
|
||||
recompute_pending_io_unlocked ();
|
||||
}
|
||||
}
|
||||
|
||||
private void recompute_pending_io_unlocked () {
|
||||
IOCondition new_io = 0;
|
||||
if (recv_queue.len > 0 || state != OPEN)
|
||||
new_io |= IN;
|
||||
if (state == OPEN)
|
||||
new_io |= OUT;
|
||||
_pending_io = new_io;
|
||||
|
||||
foreach (var entry in sources.entries) {
|
||||
unowned Source source = entry.key;
|
||||
IOCondition c = entry.value;
|
||||
if ((new_io & c) != 0)
|
||||
source.set_ready_time (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class WebInputStream : InputStream, PollableInputStream {
|
||||
public weak WebConnection connection {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public WebInputStream (WebConnection connection) {
|
||||
Object (connection: connection);
|
||||
}
|
||||
|
||||
public override bool close (Cancellable? cancellable) throws IOError {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
|
||||
return close (cancellable);
|
||||
}
|
||||
|
||||
public override ssize_t read (uint8[] buffer, Cancellable? cancellable) throws IOError {
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
public bool can_poll () {
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool is_readable () {
|
||||
return (connection.pending_io & IOCondition.IN) != 0;
|
||||
}
|
||||
|
||||
public PollableSource create_source (Cancellable? cancellable) {
|
||||
return new PollableSource.full (this, new WebIOSource (connection, IOCondition.IN), cancellable);
|
||||
}
|
||||
|
||||
public ssize_t read_nonblocking_fn (uint8[] buffer) throws GLib.Error {
|
||||
return connection.recv (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private class WebOutputStream : OutputStream, PollableOutputStream {
|
||||
public weak WebConnection connection {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public WebOutputStream (WebConnection connection) {
|
||||
Object (connection: connection);
|
||||
}
|
||||
|
||||
public override bool close (Cancellable? cancellable) throws IOError {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
|
||||
return close (cancellable);
|
||||
}
|
||||
|
||||
public override bool flush (GLib.Cancellable? cancellable) throws GLib.Error {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async bool flush_async (int io_priority, GLib.Cancellable? cancellable) throws GLib.Error {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override ssize_t write (uint8[] buffer, Cancellable? cancellable) throws IOError {
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
public bool can_poll () {
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool is_writable () {
|
||||
return (connection.pending_io & IOCondition.OUT) != 0;
|
||||
}
|
||||
|
||||
public PollableSource create_source (Cancellable? cancellable) {
|
||||
return new PollableSource.full (this, new WebIOSource (connection, IOCondition.OUT), cancellable);
|
||||
}
|
||||
|
||||
public ssize_t write_nonblocking_fn (uint8[]? buffer) throws GLib.Error {
|
||||
return connection.send (buffer);
|
||||
}
|
||||
|
||||
public PollableReturn writev_nonblocking_fn (OutputVector[] vectors, out size_t bytes_written) throws GLib.Error {
|
||||
assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
private class WebIOSource : Source {
|
||||
public WebConnection connection;
|
||||
public IOCondition condition;
|
||||
|
||||
public WebIOSource (WebConnection connection, IOCondition condition) {
|
||||
this.connection = connection;
|
||||
this.condition = condition;
|
||||
|
||||
connection.register_source (this, condition);
|
||||
}
|
||||
|
||||
~WebIOSource () {
|
||||
connection.unregister_source (this);
|
||||
}
|
||||
|
||||
protected override bool prepare (out int timeout) {
|
||||
timeout = -1;
|
||||
return (connection.pending_io & condition) != 0;
|
||||
}
|
||||
|
||||
protected override bool check () {
|
||||
return (connection.pending_io & condition) != 0;
|
||||
}
|
||||
|
||||
protected override bool dispatch (SourceFunc? callback) {
|
||||
set_ready_time (-1);
|
||||
|
||||
if (callback == null)
|
||||
return Source.REMOVE;
|
||||
|
||||
return callback ();
|
||||
}
|
||||
|
||||
protected static bool closure_callback (Closure closure) {
|
||||
var return_value = Value (typeof (bool));
|
||||
|
||||
closure.invoke (ref return_value, {});
|
||||
|
||||
return return_value.get_boolean ();
|
||||
update_pending_io ();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
namespace Frida {
|
||||
public abstract class VirtualStream : IOStream {
|
||||
public override InputStream input_stream {
|
||||
get {
|
||||
return _input_stream;
|
||||
}
|
||||
}
|
||||
|
||||
public override OutputStream output_stream {
|
||||
get {
|
||||
return _output_stream;
|
||||
}
|
||||
}
|
||||
|
||||
public IOCondition pending_io {
|
||||
get {
|
||||
lock (state)
|
||||
return _pending_io;
|
||||
}
|
||||
}
|
||||
|
||||
protected State state = OPEN;
|
||||
|
||||
private VirtualInputStream _input_stream;
|
||||
private VirtualOutputStream _output_stream;
|
||||
|
||||
private IOCondition _pending_io;
|
||||
|
||||
private Gee.Map<unowned Source, IOCondition> sources = new Gee.HashMap<unowned Source, IOCondition> ();
|
||||
|
||||
protected Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
protected MainContext main_context;
|
||||
|
||||
protected enum State {
|
||||
CREATED,
|
||||
OPENING,
|
||||
OPEN,
|
||||
CLOSED
|
||||
}
|
||||
|
||||
protected delegate void WorkFunc ();
|
||||
|
||||
construct {
|
||||
_input_stream = new VirtualInputStream (this);
|
||||
_output_stream = new VirtualOutputStream (this);
|
||||
|
||||
main_context = MainContext.ref_thread_default ();
|
||||
|
||||
state = query_initial_state ();
|
||||
_pending_io = query_events ();
|
||||
}
|
||||
|
||||
public override void dispose () {
|
||||
_output_stream.detach ();
|
||||
_input_stream.detach ();
|
||||
|
||||
io_cancellable.cancel ();
|
||||
|
||||
base.dispose ();
|
||||
}
|
||||
|
||||
protected virtual State query_initial_state () {
|
||||
return OPEN;
|
||||
}
|
||||
|
||||
protected abstract IOCondition query_events ();
|
||||
|
||||
public override bool close (GLib.Cancellable? cancellable) throws IOError {
|
||||
_close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async bool close_async (int io_priority, GLib.Cancellable? cancellable) throws IOError {
|
||||
_close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void _close () {
|
||||
if (main_context.is_owner ()) {
|
||||
do_close ();
|
||||
} else {
|
||||
var source = new IdleSource ();
|
||||
source.set_callback (() => {
|
||||
do_close ();
|
||||
return Source.REMOVE;
|
||||
});
|
||||
source.attach (main_context);
|
||||
}
|
||||
}
|
||||
|
||||
private void do_close () {
|
||||
if (state == CLOSED)
|
||||
return;
|
||||
|
||||
handle_close ();
|
||||
}
|
||||
|
||||
protected abstract void handle_close ();
|
||||
|
||||
public virtual void shutdown_read () throws IOError {
|
||||
}
|
||||
|
||||
public virtual void shutdown_write () throws IOError {
|
||||
}
|
||||
|
||||
public abstract ssize_t read (uint8[] buffer) throws IOError;
|
||||
|
||||
public abstract ssize_t write (uint8[] buffer) throws IOError;
|
||||
|
||||
protected void with_state_lock (WorkFunc func) {
|
||||
lock (state)
|
||||
func ();
|
||||
}
|
||||
|
||||
public void register_source (Source source, IOCondition condition) {
|
||||
lock (state)
|
||||
sources[source] = condition | IOCondition.ERR | IOCondition.HUP;
|
||||
}
|
||||
|
||||
public void unregister_source (Source source) {
|
||||
lock (state)
|
||||
sources.unset (source);
|
||||
}
|
||||
|
||||
protected virtual void update_pending_io () {
|
||||
lock (state) {
|
||||
_pending_io = query_events ();
|
||||
|
||||
foreach (var entry in sources.entries) {
|
||||
unowned Source source = entry.key;
|
||||
IOCondition c = entry.value;
|
||||
if ((_pending_io & c) != 0)
|
||||
source.set_ready_time (0);
|
||||
}
|
||||
}
|
||||
|
||||
notify_property ("pending-io");
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class VirtualInputStream : InputStream, PollableInputStream {
|
||||
private weak VirtualStream stream;
|
||||
|
||||
public VirtualInputStream (VirtualStream stream) {
|
||||
Object ();
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
internal void detach () {
|
||||
stream = null;
|
||||
}
|
||||
|
||||
public override bool close (Cancellable? cancellable) throws IOError {
|
||||
if (stream != null)
|
||||
stream.shutdown_read ();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
|
||||
return close (cancellable);
|
||||
}
|
||||
|
||||
public override ssize_t read (uint8[] buffer, Cancellable? cancellable) throws IOError {
|
||||
if (stream == null)
|
||||
return 0;
|
||||
|
||||
if (!is_readable ()) {
|
||||
bool done = false;
|
||||
var mutex = Mutex ();
|
||||
var cond = Cond ();
|
||||
|
||||
ulong io_handler = stream.notify["pending-io"].connect ((obj, pspec) => {
|
||||
if (is_readable ()) {
|
||||
mutex.lock ();
|
||||
done = true;
|
||||
cond.signal ();
|
||||
mutex.unlock ();
|
||||
}
|
||||
});
|
||||
ulong cancellation_handler = 0;
|
||||
if (cancellable != null) {
|
||||
cancellation_handler = cancellable.connect (() => {
|
||||
mutex.lock ();
|
||||
done = true;
|
||||
cond.signal ();
|
||||
mutex.unlock ();
|
||||
});
|
||||
}
|
||||
|
||||
if (!is_readable ()) {
|
||||
mutex.lock ();
|
||||
while (!done)
|
||||
cond.wait (mutex);
|
||||
mutex.unlock ();
|
||||
}
|
||||
|
||||
if (cancellation_handler != 0)
|
||||
cancellable.disconnect (cancellation_handler);
|
||||
stream.disconnect (io_handler);
|
||||
|
||||
cancellable.set_error_if_cancelled ();
|
||||
}
|
||||
|
||||
return stream.read (buffer);
|
||||
}
|
||||
|
||||
public bool can_poll () {
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool is_readable () {
|
||||
if (stream == null)
|
||||
return true;
|
||||
return (stream.pending_io & IOCondition.IN) != 0;
|
||||
}
|
||||
|
||||
public PollableSource create_source (Cancellable? cancellable) {
|
||||
return new PollableSource.full (this, new VirtualIOSource (stream, IOCondition.IN), cancellable);
|
||||
}
|
||||
|
||||
public ssize_t read_nonblocking_fn (uint8[] buffer) throws GLib.Error {
|
||||
if (stream == null)
|
||||
return 0;
|
||||
return stream.read (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class VirtualOutputStream : OutputStream, PollableOutputStream {
|
||||
private weak VirtualStream? stream;
|
||||
|
||||
public VirtualOutputStream (VirtualStream stream) {
|
||||
Object ();
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
internal void detach () {
|
||||
stream = null;
|
||||
}
|
||||
|
||||
public override bool close (Cancellable? cancellable) throws IOError {
|
||||
if (stream != null)
|
||||
stream.shutdown_write ();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
|
||||
return close (cancellable);
|
||||
}
|
||||
|
||||
public override bool flush (GLib.Cancellable? cancellable) throws GLib.Error {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async bool flush_async (int io_priority, GLib.Cancellable? cancellable) throws GLib.Error {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override ssize_t write (uint8[] buffer, Cancellable? cancellable) throws IOError {
|
||||
return stream.write (buffer);
|
||||
}
|
||||
|
||||
public bool can_poll () {
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool is_writable () {
|
||||
if (stream == null)
|
||||
return false;
|
||||
return (stream.pending_io & IOCondition.OUT) != 0;
|
||||
}
|
||||
|
||||
public PollableSource create_source (Cancellable? cancellable) {
|
||||
return new PollableSource.full (this, new VirtualIOSource (stream, IOCondition.OUT), cancellable);
|
||||
}
|
||||
|
||||
public ssize_t write_nonblocking_fn (uint8[]? buffer) throws GLib.Error {
|
||||
if (stream == null)
|
||||
throw new IOError.CLOSED ("Virtual is closed");
|
||||
return stream.write (buffer);
|
||||
}
|
||||
|
||||
public PollableReturn writev_nonblocking_fn (OutputVector[] vectors, out size_t bytes_written) throws GLib.Error {
|
||||
assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
private class VirtualIOSource : Source {
|
||||
public VirtualStream? stream;
|
||||
public IOCondition condition;
|
||||
|
||||
public VirtualIOSource (VirtualStream stream, IOCondition condition) {
|
||||
this.stream = stream;
|
||||
this.condition = condition;
|
||||
|
||||
if (stream != null)
|
||||
stream.register_source (this, condition);
|
||||
}
|
||||
|
||||
~VirtualIOSource () {
|
||||
if (stream != null)
|
||||
stream.unregister_source (this);
|
||||
}
|
||||
|
||||
protected override bool prepare (out int timeout) {
|
||||
timeout = -1;
|
||||
return is_ready ();
|
||||
}
|
||||
|
||||
protected override bool check () {
|
||||
return is_ready ();
|
||||
}
|
||||
|
||||
private bool is_ready () {
|
||||
IOCondition pending_io = (stream != null) ? stream.pending_io : IOCondition.IN;
|
||||
return (pending_io & condition) != 0;
|
||||
}
|
||||
|
||||
protected override bool dispatch (SourceFunc? callback) {
|
||||
set_ready_time (-1);
|
||||
|
||||
if (callback == null)
|
||||
return Source.REMOVE;
|
||||
|
||||
return callback ();
|
||||
}
|
||||
|
||||
protected static bool closure_callback (Closure closure) {
|
||||
var return_value = Value (typeof (bool));
|
||||
|
||||
closure.invoke (ref return_value, {});
|
||||
|
||||
return return_value.get_boolean ();
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -38,7 +38,7 @@ namespace Frida {
|
||||
public abstract unowned string get_uuid_value () throws Error;
|
||||
}
|
||||
|
||||
public class VariantReader : Object, ObjectReader {
|
||||
public sealed class VariantReader : Object, ObjectReader {
|
||||
public Variant root_object {
|
||||
get {
|
||||
return scopes.peek_head ().val;
|
||||
@@ -180,7 +180,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class JsonObjectBuilder : Object, ObjectBuilder {
|
||||
public sealed class JsonObjectBuilder : Object, ObjectBuilder {
|
||||
private Json.Builder builder = new Json.Builder ();
|
||||
private Gee.Map<string, Bytes> raw_values = new Gee.HashMap<string, Bytes> ();
|
||||
|
||||
@@ -267,7 +267,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class JsonObjectReader : Object, ObjectReader {
|
||||
public sealed class JsonObjectReader : Object, ObjectReader {
|
||||
private Json.Reader reader;
|
||||
|
||||
public JsonObjectReader (string json) throws Error {
|
||||
|
||||
+26
-2
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class XpcClient : Object {
|
||||
public sealed class XpcClient : Object {
|
||||
public signal void message (Darwin.Xpc.Object obj);
|
||||
|
||||
public State state {
|
||||
@@ -123,7 +123,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class XpcObjectReader {
|
||||
public sealed class XpcObjectReader {
|
||||
public Darwin.Xpc.Object root_object {
|
||||
get {
|
||||
return scopes.peek_head ().object;
|
||||
@@ -136,6 +136,8 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public delegate int TranslateErrorFunc (string domain, int code, string description);
|
||||
|
||||
private Gee.Deque<Scope> scopes = new Gee.ArrayQueue<Scope> ();
|
||||
|
||||
public XpcObjectReader (Darwin.Xpc.Object obj) {
|
||||
@@ -224,6 +226,28 @@ namespace Frida {
|
||||
return error.get_string (Darwin.Xpc.Error.KEY_DESCRIPTION);
|
||||
}
|
||||
|
||||
public void check_nserror (TranslateErrorFunc translate_error) throws Error {
|
||||
if (!has_member ("error"))
|
||||
return;
|
||||
|
||||
read_member ("error");
|
||||
|
||||
unowned string domain = read_member ("domain").get_string_value ();
|
||||
end_member ();
|
||||
|
||||
var code = (int) read_member ("code").get_int64_value ();
|
||||
end_member ();
|
||||
|
||||
string description = read_member ("userInfo").read_member ("NSLocalizedDescription").get_string_value ();
|
||||
if (description.has_suffix ("."))
|
||||
description = description[:description.length - 1];
|
||||
|
||||
throw (Error) new GLib.Error.literal (
|
||||
Quark.from_string ("frida-error-quark"),
|
||||
translate_error (domain, code, description),
|
||||
description);
|
||||
}
|
||||
|
||||
public unowned Darwin.Xpc.Object get_object_value (Darwin.Xpc.Type expected_type) throws Error {
|
||||
return peek_scope ().get_object<Darwin.Xpc.Object> (expected_type);
|
||||
}
|
||||
|
||||
+21
-13
@@ -1,5 +1,5 @@
|
||||
namespace Frida.Gadget {
|
||||
private class Config : Object, Json.Serializable {
|
||||
private sealed class Config : Object, Json.Serializable {
|
||||
public Object interaction {
|
||||
get;
|
||||
set;
|
||||
@@ -93,7 +93,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class ScriptInteraction : Object, Json.Serializable {
|
||||
private sealed class ScriptInteraction : Object, Json.Serializable {
|
||||
public string path {
|
||||
get;
|
||||
set;
|
||||
@@ -145,7 +145,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class ScriptDirectoryInteraction : Object {
|
||||
private sealed class ScriptDirectoryInteraction : Object {
|
||||
public string path {
|
||||
get;
|
||||
set;
|
||||
@@ -164,7 +164,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class ScriptConfig : Object, Json.Serializable {
|
||||
private sealed class ScriptConfig : Object, Json.Serializable {
|
||||
public ProcessFilter? filter {
|
||||
get;
|
||||
set;
|
||||
@@ -216,7 +216,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class ProcessFilter : Object {
|
||||
private sealed class ProcessFilter : Object {
|
||||
public string[] executables {
|
||||
get;
|
||||
set;
|
||||
@@ -258,7 +258,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class ListenInteraction : SocketInteraction {
|
||||
private sealed class ListenInteraction : SocketInteraction {
|
||||
public PortConflictBehavior on_port_conflict {
|
||||
get;
|
||||
set;
|
||||
@@ -287,7 +287,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class ConnectInteraction : SocketInteraction, Json.Serializable {
|
||||
private sealed class ConnectInteraction : SocketInteraction, Json.Serializable {
|
||||
public string[]? acl {
|
||||
get;
|
||||
set;
|
||||
@@ -328,7 +328,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class Location : Object {
|
||||
private sealed class Location : Object {
|
||||
public string executable_name {
|
||||
get;
|
||||
construct;
|
||||
@@ -988,7 +988,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class ScriptRunner : BaseController {
|
||||
private sealed class ScriptRunner : BaseController {
|
||||
private ScriptEngine engine;
|
||||
private Script script;
|
||||
|
||||
@@ -1036,7 +1036,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class ScriptDirectoryRunner : BaseController {
|
||||
private sealed class ScriptDirectoryRunner : BaseController {
|
||||
public string directory_path {
|
||||
get;
|
||||
construct;
|
||||
@@ -1241,7 +1241,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class Script : Object, RpcPeer {
|
||||
private sealed class Script : Object, RpcPeer {
|
||||
private const uint8 QUICKJS_BYTECODE_MAGIC = 0x02;
|
||||
|
||||
public enum ChangeBehavior {
|
||||
@@ -1453,7 +1453,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class ControlServer : BaseController {
|
||||
private sealed class ControlServer : BaseController {
|
||||
public EndpointParameters endpoint_params {
|
||||
get;
|
||||
construct;
|
||||
@@ -1927,6 +1927,14 @@ namespace Frida.Gadget {
|
||||
throw new Error.NOT_SUPPORTED ("Unable to inject libraries when embedded");
|
||||
}
|
||||
|
||||
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("Unable to open channels when embedded");
|
||||
}
|
||||
|
||||
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("Unable to open services when embedded");
|
||||
}
|
||||
|
||||
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");
|
||||
@@ -1958,7 +1966,7 @@ namespace Frida.Gadget {
|
||||
}
|
||||
}
|
||||
|
||||
private class ClusterClient : BaseController {
|
||||
private sealed class ClusterClient : BaseController {
|
||||
public SocketConnectable connectable {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
public class Frida.TunnelInterfaceObserver : Object, DynamicInterfaceObserver {
|
||||
public sealed class Frida.TunnelInterfaceObserver : Object, DynamicInterfaceObserver {
|
||||
#if IOS || TVOS
|
||||
private Gee.Map<string, DynamicInterface> interfaces = new Gee.HashMap<string, DynamicInterface> ();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class ThreadIgnoreScope {
|
||||
public sealed class ThreadIgnoreScope {
|
||||
public enum Kind {
|
||||
APPLICATION_THREAD,
|
||||
FRIDA_THREAD
|
||||
@@ -43,7 +43,7 @@ namespace Frida {
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
public class ThreadCountCloaker : Object {
|
||||
public sealed class ThreadCountCloaker : Object {
|
||||
private ReadFunc * read_slot;
|
||||
private static ReadFunc old_read_impl;
|
||||
|
||||
@@ -156,12 +156,12 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
#else
|
||||
public class ThreadCountCloaker : Object {
|
||||
public sealed class ThreadCountCloaker : Object {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX
|
||||
public class ThreadListCloaker : Object, DirListFilter {
|
||||
public sealed class ThreadListCloaker : Object, DirListFilter {
|
||||
private string our_dir_by_pid;
|
||||
private DirListCloaker cloaker;
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class FDListCloaker : Object, DirListFilter {
|
||||
public sealed class FDListCloaker : Object, DirListFilter {
|
||||
private string our_dir_by_pid;
|
||||
private DirListCloaker cloaker;
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private class DirListCloaker : Object {
|
||||
private sealed class DirListCloaker : Object {
|
||||
public weak DirListFilter filter {
|
||||
get;
|
||||
construct;
|
||||
@@ -467,10 +467,10 @@ namespace Frida {
|
||||
public abstract bool matches_file (string name);
|
||||
}
|
||||
#else
|
||||
public class ThreadListCloaker : Object {
|
||||
public sealed class ThreadListCloaker : Object {
|
||||
}
|
||||
|
||||
public class FDListCloaker : Object {
|
||||
public sealed class FDListCloaker : Object {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class ExitMonitor : Object, Gum.InvocationListener {
|
||||
public sealed class ExitMonitor : Object, Gum.InvocationListener {
|
||||
public weak ExitHandler handler {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Frida {
|
||||
#if WINDOWS
|
||||
public class FileDescriptorGuard : Object {
|
||||
public sealed class FileDescriptorGuard : Object {
|
||||
public Gum.MemoryRange agent_range {
|
||||
get;
|
||||
construct;
|
||||
@@ -11,7 +11,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
#else
|
||||
public class FileDescriptorGuard : Object {
|
||||
public sealed class FileDescriptorGuard : Object {
|
||||
public Gum.MemoryRange agent_range {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Frida {
|
||||
#if WINDOWS
|
||||
public class FileDescriptorTablePadder {
|
||||
public sealed class FileDescriptorTablePadder {
|
||||
public static FileDescriptorTablePadder obtain () {
|
||||
return new FileDescriptorTablePadder ();
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
#else
|
||||
public class FileDescriptorTablePadder {
|
||||
public sealed class FileDescriptorTablePadder {
|
||||
private const int MIN_TABLE_SIZE = 32;
|
||||
|
||||
private static unowned FileDescriptorTablePadder shared_instance = null;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Frida {
|
||||
#if WINDOWS
|
||||
public class ForkMonitor : Object {
|
||||
public sealed class ForkMonitor : Object {
|
||||
public weak ForkHandler handler {
|
||||
get;
|
||||
construct;
|
||||
@@ -11,7 +11,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
#else
|
||||
public class ForkMonitor : Object, Gum.InvocationListener {
|
||||
public sealed class ForkMonitor : Object, Gum.InvocationListener {
|
||||
public weak ForkHandler handler {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class PortalClient : Object, AgentSessionProvider {
|
||||
public sealed class PortalClient : Object, AgentSessionProvider {
|
||||
public signal void resume ();
|
||||
public signal void kill ();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class ScriptEngine : Object {
|
||||
public sealed class ScriptEngine : Object {
|
||||
public signal void message_from_script (AgentScriptId script_id, string json, Bytes? data);
|
||||
public signal void message_from_debugger (AgentScriptId script_id, string message);
|
||||
|
||||
@@ -223,7 +223,7 @@ namespace Frida {
|
||||
source.attach (Gum.ScriptBackend.get_scheduler ().get_js_context ());
|
||||
}
|
||||
|
||||
public class ScriptInstance : Object, RpcPeer {
|
||||
public sealed class ScriptInstance : Object, RpcPeer {
|
||||
public signal void closed ();
|
||||
public signal void message (string json, Bytes? data);
|
||||
public signal void debug_message (string message);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class SpawnMonitor : Object, Gum.InvocationListener {
|
||||
public sealed class SpawnMonitor : Object, Gum.InvocationListener {
|
||||
public weak SpawnHandler handler {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Frida {
|
||||
#if DARWIN
|
||||
public class ThreadSuspendMonitor : Object {
|
||||
public sealed class ThreadSuspendMonitor : Object {
|
||||
public weak ProcessInvader invader {
|
||||
get;
|
||||
construct;
|
||||
@@ -131,7 +131,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
#else
|
||||
public class ThreadSuspendMonitor : Object {
|
||||
public sealed class ThreadSuspendMonitor : Object {
|
||||
public weak ProcessInvader invader {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Frida {
|
||||
#if DARWIN
|
||||
public class UnwindSitter : Object {
|
||||
public sealed class UnwindSitter : Object {
|
||||
public weak ProcessInvader invader {
|
||||
get;
|
||||
construct;
|
||||
@@ -62,7 +62,7 @@ namespace Frida {
|
||||
public extern static void _unhook_libunwind ();
|
||||
}
|
||||
#else
|
||||
public class UnwindSitter : Object {
|
||||
public sealed class UnwindSitter : Object {
|
||||
public weak ProcessInvader invader {
|
||||
get;
|
||||
construct;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class PipeTransport : Object {
|
||||
public sealed class PipeTransport : Object {
|
||||
public string local_address {
|
||||
get;
|
||||
construct;
|
||||
@@ -42,7 +42,7 @@ namespace Frida {
|
||||
}
|
||||
|
||||
#if WINDOWS
|
||||
public class WindowsPipe : IOStream {
|
||||
public sealed class WindowsPipe : IOStream {
|
||||
public string address {
|
||||
get;
|
||||
construct;
|
||||
|
||||
+11
-2
@@ -162,6 +162,14 @@ if host_os_family == 'darwin'
|
||||
endif
|
||||
endif
|
||||
|
||||
if host_machine.endian() == 'big'
|
||||
if host_abi in ['arm', 'armhf']
|
||||
host_abi = 'armbe8'
|
||||
elif host_abi == 'arm64'
|
||||
host_abi = 'arm64be'
|
||||
endif
|
||||
endif
|
||||
|
||||
if host_os_family == 'darwin' and host_arch == 'arm64'
|
||||
host_is_modern = host_abi == 'arm64e'
|
||||
else
|
||||
@@ -414,7 +422,7 @@ foreach b : [['local', have_local_backend],
|
||||
endif
|
||||
endforeach
|
||||
|
||||
if have_barebone_backend or have_compiler_backend
|
||||
if host_os_family == 'darwin' or host_os == 'android' or have_barebone_backend or have_compiler_backend
|
||||
node = find_program('node', version: '>=18.0.0', native: true, required: false)
|
||||
if not node.found()
|
||||
error('Need Node.js >= 18.0.0 to process JavaScript code at build time')
|
||||
@@ -431,7 +439,6 @@ if gi_dep.found()
|
||||
else
|
||||
girdir = get_option('prefix') / get_option('datadir') / 'gir-1.0'
|
||||
endif
|
||||
uninstalled_girdir = meson.current_build_dir() / 'src'
|
||||
|
||||
vapidir = get_option('prefix') / get_option('datadir') / 'vala' / 'vapi'
|
||||
|
||||
@@ -665,6 +672,8 @@ post_process = [
|
||||
'@INPUT0@',
|
||||
]
|
||||
|
||||
compile_js_agent = files('tools' / 'compile-js-agent.py')
|
||||
|
||||
mapper_opt = get_option('mapper')
|
||||
if mapper_opt.auto()
|
||||
have_mapper = host_os_family == 'darwin'
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ namespace Frida.Portal {
|
||||
return application.run ();
|
||||
}
|
||||
|
||||
private class Application : Object {
|
||||
private sealed class Application : Object {
|
||||
public signal void ready (bool success);
|
||||
|
||||
public PortalService service {
|
||||
|
||||
+1
-1
Submodule releng updated: 2eecc41cbe...5d9edf166c.
+1
-1
@@ -235,7 +235,7 @@ namespace Frida.Server {
|
||||
}
|
||||
#endif
|
||||
|
||||
private class Application : Object {
|
||||
private sealed class Application : Object {
|
||||
public signal void ready (bool success);
|
||||
|
||||
public string? device_id {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class AgentContainer : Object, AgentSessionProvider {
|
||||
public sealed class AgentContainer : Object, AgentSessionProvider {
|
||||
public DBusConnection connection {
|
||||
get;
|
||||
private set;
|
||||
|
||||
+91284
File diff suppressed because it is too large.
Load diff
+29500
File diff suppressed because it is too large.
Load diff
+141723
File diff suppressed because it is too large.
Load diff
+17
-5
@@ -16,10 +16,13 @@ GIR_NAMESPACES = {
|
||||
"glib": GLIB_NAMESPACE,
|
||||
}
|
||||
|
||||
CORE_TAG_IMPLEMENTS = f"{{{CORE_NAMESPACE}}}implements"
|
||||
CORE_TAG_FIELD = f"{{{CORE_NAMESPACE}}}field"
|
||||
CORE_TAG_CONSTRUCTOR = f"{{{CORE_NAMESPACE}}}constructor"
|
||||
CORE_TAG_METHOD = f"{{{CORE_NAMESPACE}}}method"
|
||||
|
||||
OBJECT_TYPE_PATTERN = re.compile(r"\bpublic\s+(sealed )?(class|interface)\s+(\w+)\b")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Generate refined Frida API definitions")
|
||||
parser.add_argument('--output', dest='output_type', choices=['bundle', 'header', 'gir', 'vapi', 'vapi-stamp'], default='bundle')
|
||||
@@ -203,7 +206,9 @@ def emit_gir(api: ApiSpec, core_gir: str, base_gir: str, output_dir: Path) -> st
|
||||
for elem in core_elements + base_elements:
|
||||
if tag_name == "class":
|
||||
for child in list(elem):
|
||||
if child.tag == CORE_TAG_FIELD or child.get("name").startswith("_"):
|
||||
if (child.tag == CORE_TAG_IMPLEMENTS and child.get("name") == "FridaBase.AgentMessageSink") \
|
||||
or child.tag == CORE_TAG_FIELD \
|
||||
or child.get("name").startswith("_"):
|
||||
elem.remove(child)
|
||||
merged_namespace.append(elem)
|
||||
|
||||
@@ -215,6 +220,7 @@ def emit_gir(api: ApiSpec, core_gir: str, base_gir: str, output_dir: Path) -> st
|
||||
result = ET.tostring(merged_root,
|
||||
encoding="unicode",
|
||||
xml_declaration=True)
|
||||
result = result.replace("FridaBase.", "Frida.")
|
||||
with OutputFile(output_dir / f"Frida-{api.version}.gir") as output_gir:
|
||||
output_gir.write(result)
|
||||
|
||||
@@ -288,12 +294,18 @@ def parse_api(api_version, toplevel_code, core_header, core_vapi, base_header, b
|
||||
"StaticAuthenticationService": "AuthenticationService",
|
||||
}
|
||||
internal_type_prefixes = [
|
||||
"AgentMessageKind",
|
||||
"Fruity",
|
||||
"HostSession",
|
||||
"MessageType",
|
||||
"PeerSetup",
|
||||
"PortConflictBehavior",
|
||||
"ResultCode",
|
||||
"SpawnStartState",
|
||||
"State",
|
||||
"StringTerminator",
|
||||
"UnloadPolicy",
|
||||
"WebService",
|
||||
"Winjector"
|
||||
]
|
||||
seen_enum_names = set()
|
||||
@@ -375,7 +387,7 @@ def parse_api(api_version, toplevel_code, core_header, core_vapi, base_header, b
|
||||
if delegate_cname not in seen_cdelegates:
|
||||
seen_cdelegates.add(delegate_cname)
|
||||
object_type.c_delegate_typedefs.append(beautify_cprototype(d.group(0)))
|
||||
if object_type.kind == 'interface' and object_type.name != "Injector":
|
||||
if object_type.kind == 'interface':
|
||||
for m in re.finditer("^(struct _" + object_type.c_name + "Iface {[^}]+};)$", all_headers, re.MULTILINE):
|
||||
object_type.c_iface_definition = beautify_cinterface(m.group(1))
|
||||
|
||||
@@ -412,8 +424,8 @@ def parse_api(api_version, toplevel_code, core_header, core_vapi, base_header, b
|
||||
current_enum.vapi_declaration = stripped_line
|
||||
else:
|
||||
ignoring = True
|
||||
elif stripped_line.startswith("public class") or stripped_line.startswith("public interface"):
|
||||
name = re.match(r"^public (class|interface) (\w+) ", stripped_line).group(2)
|
||||
elif (match := OBJECT_TYPE_PATTERN.match(stripped_line)) is not None:
|
||||
name = match.group(3)
|
||||
if name not in object_type_by_name:
|
||||
ignoring = True
|
||||
else:
|
||||
@@ -470,7 +482,7 @@ def function_is_public(name):
|
||||
]
|
||||
|
||||
def parse_vala_object_types(source) -> List[ApiObjectType]:
|
||||
return [ApiObjectType(m.group(2), m.group(1)) for m in re.finditer(r"^\t+public\s+(class|interface)\s+(\w+)\s+", source, re.MULTILINE)]
|
||||
return [ApiObjectType(m.group(3), m.group(2)) for m in OBJECT_TYPE_PATTERN.finditer(source, re.MULTILINE)]
|
||||
|
||||
def parse_vapi_functions(vapi) -> List[ApiFunction]:
|
||||
return [ApiFunction(m.group(1), m.group(0)) for m in re.finditer(r"^\tpublic static .+ (\w+) \(.+;", vapi, re.MULTILINE)]
|
||||
|
||||
+9
-3
@@ -1,3 +1,5 @@
|
||||
fs = import('fs')
|
||||
|
||||
generate_api = [python, files('generate.py')]
|
||||
|
||||
generate_api_args = [
|
||||
@@ -32,6 +34,11 @@ core_public_h = core_api[0]
|
||||
core_public_gir = core_api[1]
|
||||
core_public_vapi = [core_api[2], core_api[3]]
|
||||
|
||||
install_glib_girs = not gi_dep.found() and not fs.exists(girdir / 'GLib-2.0.gir')
|
||||
glib_gir = fs.copyfile('GLib-2.0.gir', install: install_glib_girs, install_dir: girdir)
|
||||
gobject_gir = fs.copyfile('GObject-2.0.gir', install: install_glib_girs, install_dir: girdir)
|
||||
gio_gir = fs.copyfile('Gio-2.0.gir', install: install_glib_girs, install_dir: girdir)
|
||||
|
||||
core_public_vapi_stamp = custom_target('frida-core-vapi-stamp',
|
||||
input: core_public_vapi,
|
||||
output: f'frida-core-@[email protected]',
|
||||
@@ -59,8 +66,6 @@ core_public_lib = custom_target('frida-core-library',
|
||||
install_dir: get_option('libdir'),
|
||||
)
|
||||
|
||||
fs = import('fs')
|
||||
|
||||
core_public_extra_headers = []
|
||||
if host_os == 'android'
|
||||
core_public_extra_headers += fs.copyfile(frida_selinux_h)
|
||||
@@ -71,6 +76,7 @@ if build_machine.system() == 'windows'
|
||||
else
|
||||
uninstalled_incdir = meson.current_build_dir()
|
||||
endif
|
||||
uninstalled_girdir = uninstalled_incdir
|
||||
uninstalled_vapidir = uninstalled_incdir
|
||||
|
||||
uninstalled_variables = {
|
||||
@@ -86,7 +92,7 @@ installed_variables = {
|
||||
}
|
||||
|
||||
core_public_dep = declare_dependency(
|
||||
sources: [core_public_h, core_public_gir, core_public_vapi_stamp, core_public_extra_headers],
|
||||
sources: [core_public_h, core_public_gir, glib_gir, gobject_gir, gio_gir, core_public_vapi_stamp, core_public_extra_headers],
|
||||
include_directories: include_directories('.'),
|
||||
link_args: backend_libs_private,
|
||||
link_with: core_public_lib,
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Frida.Barebone {
|
||||
public abstract async void deallocate (Cancellable? cancellable) throws Error, IOError;
|
||||
}
|
||||
|
||||
public class SimpleAllocator : Object, Allocator {
|
||||
public sealed class SimpleAllocator : Object, Allocator {
|
||||
public size_t page_size {
|
||||
get { return _page_size; }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
public class ArmMachine : Object, Machine {
|
||||
public sealed class ArmMachine : Object, Machine {
|
||||
public override GDB.Client gdb {
|
||||
get;
|
||||
set;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
public class Arm64Machine : Object, Machine {
|
||||
public sealed class Arm64Machine : Object, Machine {
|
||||
public override GDB.Client gdb {
|
||||
get;
|
||||
set;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
public class UnknownMachine : Object, Machine {
|
||||
public sealed class UnknownMachine : Object, Machine {
|
||||
public GDB.Client gdb {
|
||||
get;
|
||||
set;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
public class IA32Machine : Object, Machine {
|
||||
public sealed class IA32Machine : Object, Machine {
|
||||
public override GDB.Client gdb {
|
||||
get;
|
||||
set;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
public class X64Machine : Object, Machine {
|
||||
public sealed class X64Machine : Object, Machine {
|
||||
public override GDB.Client gdb {
|
||||
get;
|
||||
set;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class BareboneHostSessionBackend : Object, HostSessionBackend {
|
||||
public sealed class BareboneHostSessionBackend : Object, HostSessionBackend {
|
||||
private BareboneHostSessionProvider? provider;
|
||||
|
||||
private const uint16 DEFAULT_PORT = 3333;
|
||||
@@ -30,7 +30,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class BareboneHostSessionProvider : Object, HostSessionProvider {
|
||||
public sealed class BareboneHostSessionProvider : Object, HostSessionProvider {
|
||||
public string id {
|
||||
get { return "barebone"; }
|
||||
}
|
||||
@@ -141,12 +141,35 @@ namespace Frida {
|
||||
return yield this.host_session.link_agent_session (id, sink, cancellable);
|
||||
}
|
||||
|
||||
public void unlink_agent_session (HostSession host_session, AgentSessionId id) {
|
||||
if (host_session != this.host_session)
|
||||
return;
|
||||
|
||||
this.host_session.unlink_agent_session (id);
|
||||
}
|
||||
|
||||
public async IOStream link_channel (HostSession host_session, ChannelId id, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("Channels are not supported by this backend");
|
||||
}
|
||||
|
||||
public void unlink_channel (HostSession host_session, ChannelId id) {
|
||||
}
|
||||
|
||||
public async ServiceSession link_service_session (HostSession host_session, ServiceSessionId id, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
|
||||
}
|
||||
|
||||
public void unlink_service_session (HostSession host_session, ServiceSessionId id) {
|
||||
}
|
||||
|
||||
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
|
||||
agent_session_detached (id, reason, crash);
|
||||
}
|
||||
}
|
||||
|
||||
public class BareboneHostSession : Object, HostSession {
|
||||
public sealed class BareboneHostSession : Object, HostSession {
|
||||
public Barebone.Services services {
|
||||
get;
|
||||
construct;
|
||||
@@ -260,6 +283,14 @@ namespace Frida {
|
||||
return session;
|
||||
}
|
||||
|
||||
public void unlink_agent_session (AgentSessionId id) {
|
||||
BareboneAgentSession? session = agent_sessions[id];
|
||||
if (session == null)
|
||||
return;
|
||||
|
||||
session.message_sink = null;
|
||||
}
|
||||
|
||||
public async InjectorPayloadId inject_library_file (uint pid, string path, string entrypoint, string data,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
throw_not_supported ();
|
||||
@@ -270,6 +301,14 @@ namespace Frida {
|
||||
throw_not_supported ();
|
||||
}
|
||||
|
||||
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("Channels are not supported by this backend");
|
||||
}
|
||||
|
||||
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
|
||||
}
|
||||
|
||||
private void on_agent_session_closed (BareboneAgentSession session) {
|
||||
AgentSessionId id = session.id;
|
||||
|
||||
@@ -282,7 +321,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private class BareboneAgentSession : Object, AgentSession {
|
||||
private sealed class BareboneAgentSession : Object, AgentSession {
|
||||
public signal void closed ();
|
||||
|
||||
public AgentSessionId id {
|
||||
@@ -525,7 +564,7 @@ namespace Frida {
|
||||
}
|
||||
|
||||
namespace Barebone {
|
||||
public class Services : Object {
|
||||
public sealed class Services : Object {
|
||||
public Machine machine {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
public class Callback : Object {
|
||||
public sealed class Callback : Object {
|
||||
private uint64 code;
|
||||
private CallbackHandler handler;
|
||||
private Machine machine;
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def main(argv):
|
||||
output_dir, priv_dir, input_dir, npm = [Path(d).resolve() for d in argv[1:]]
|
||||
|
||||
try:
|
||||
generate_runtime(output_dir, priv_dir, input_dir, npm)
|
||||
except Exception as e:
|
||||
print(e, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def generate_runtime(output_dir, priv_dir, input_dir, npm):
|
||||
priv_dir.mkdir(exist_ok=True)
|
||||
|
||||
shutil.copy(input_dir / "package.json", priv_dir)
|
||||
shutil.copy(input_dir / "package-lock.json", priv_dir)
|
||||
|
||||
runtime_reldir = Path("script-runtime")
|
||||
runtime_srcdir = input_dir / runtime_reldir
|
||||
runtime_intdir = priv_dir / runtime_reldir
|
||||
if runtime_intdir.exists():
|
||||
shutil.rmtree(runtime_intdir)
|
||||
shutil.copytree(runtime_srcdir, runtime_intdir)
|
||||
|
||||
subprocess.run([npm, "install"], capture_output=True, cwd=priv_dir, check=True)
|
||||
|
||||
shutil.copy(priv_dir / "script-runtime.js", output_dir)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv)
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
public class Interceptor : Object {
|
||||
public sealed class Interceptor : Object {
|
||||
public Machine machine {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -29,11 +29,11 @@ barebone_script_runtime = custom_target('frida-barebone-script-runtime',
|
||||
],
|
||||
command: [
|
||||
python,
|
||||
files('generate-script-runtime.py'),
|
||||
meson.current_build_dir(),
|
||||
compile_js_agent,
|
||||
'@OUTPUT@',
|
||||
'@PRIVATE_DIR@',
|
||||
meson.current_source_dir(),
|
||||
npm,
|
||||
'@INPUT@',
|
||||
],
|
||||
)
|
||||
backend_sources += custom_target('frida-data-barebone',
|
||||
|
||||
Generated
+32
-21
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "frida-barebone-runtime",
|
||||
"name": "frida-barebone-script-runtime",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "frida-barebone-runtime",
|
||||
"name": "frida-barebone-script-runtime",
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@types/frida-gum": "^18.3.2",
|
||||
"frida-compile": "^16.2.1"
|
||||
"@types/frida-gum": "^19.0.0",
|
||||
"frida-compile": "^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/assert": {
|
||||
@@ -74,6 +74,13 @@
|
||||
"node": ">=14.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/crypto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@frida/crypto/-/crypto-1.0.1.tgz",
|
||||
"integrity": "sha512-WXTkVjESvX8TIVXIynJJv9BKSIdQP0Iis04StIXknkDi1ULdMlrypA9p5C4KW1H6GCkNsVnKbybpzsulYCTvag==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/diagnostics_channel": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/diagnostics_channel/-/diagnostics_channel-1.0.0.tgz",
|
||||
@@ -316,10 +323,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/frida-gum": {
|
||||
"version": "18.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.3.2.tgz",
|
||||
"integrity": "sha512-bso8bJRxrhchNRrOMmT18st/THIdjzxFdcMtJ/gGSYSknJeerQ8ArBwBtlWt/f3pqVVs1Mz1Fg6lvUdjXswa+g==",
|
||||
"dev": true
|
||||
"version": "19.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.0.tgz",
|
||||
"integrity": "sha512-qViK1KwvPEAkajwSUv0wpZvZLiX8xO4JFFCh8dfYZfzSyOEfoE0KliCP/nJSKIKG6N3hXnPowrvPufjs5fLKAA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "17.0.45",
|
||||
@@ -366,24 +374,26 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
|
||||
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
|
||||
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || >=14"
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/frida-compile": {
|
||||
"version": "16.2.1",
|
||||
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-16.2.1.tgz",
|
||||
"integrity": "sha512-be/U5h8l0cb0b+fWeZclhfw1s2xER8fPOjnTU4rZF8oh5GkB0BeAEaApwfGrdmeZkVNdUhDLXud7DqEljHRWmA==",
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-17.0.0.tgz",
|
||||
"integrity": "sha512-ixJRj14qLH/Z0ckFWd5fKeDMm0W2+2WDpSGnLRgpn0nuCQAbDHRCqVCWtPnV8uzPJmA6XOX0pujsMpYe9q9RRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@frida/assert": "^3.0.1",
|
||||
"@frida/base64-js": "^2.0.3",
|
||||
"@frida/buffer": "^7.0.4",
|
||||
"@frida/crosspath": "^3.0.0",
|
||||
"@frida/crypto": "^1.0.1",
|
||||
"@frida/diagnostics_channel": "^1.0.0",
|
||||
"@frida/events": "^4.0.4",
|
||||
"@frida/http": "^4.0.2",
|
||||
@@ -406,8 +416,8 @@
|
||||
"@frida/url": "^1.0.2",
|
||||
"@frida/util": "^1.0.3",
|
||||
"@frida/vm": "^2.0.0",
|
||||
"commander": "^9.4.0",
|
||||
"frida-fs": "^5.2.3",
|
||||
"commander": "^11.1.0",
|
||||
"frida-fs": "^6.0.0",
|
||||
"typed-emitter": "^2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -415,10 +425,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/frida-fs": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-5.2.3.tgz",
|
||||
"integrity": "sha512-jJhtNI86UqDkOtB72XR7Ia9KHudQUxIFIbZadS9kxrDU6Io1jLhoMNp++iW7n7MaDgFQLRR8VgNj9VViGzaydA==",
|
||||
"dev": true
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-6.0.0.tgz",
|
||||
"integrity": "sha512-I0fnKupZh7fU2ixwCIjJnEqNdhfm/SC1ZYBMy58EmeqOWSbjw1Dpy99mJ7BJdbk2KNXJeaBZGxDYLtn0J9S+UA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/http-parser-js": {
|
||||
"version": "0.5.8",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"build": "frida-compile script-runtime/entrypoint.ts -o script-runtime.js -c"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/frida-gum": "^18.3.2",
|
||||
"frida-compile": "^16.2.1"
|
||||
"@types/frida-gum": "^19.0.0",
|
||||
"frida-compile": "^17.0.0"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
|
||||
namespace Frida.Barebone {
|
||||
private class RustModule : Object {
|
||||
private sealed class RustModule : Object {
|
||||
public signal void console_output (string message);
|
||||
|
||||
public Gee.List<Export> exports {
|
||||
|
||||
@@ -278,6 +278,8 @@ Object.defineProperties(Process, {
|
||||
base: NULL,
|
||||
size: 0x1000,
|
||||
path: "/kernel",
|
||||
ensureInitialized() {
|
||||
},
|
||||
enumerateImports() {
|
||||
return [];
|
||||
},
|
||||
@@ -290,11 +292,23 @@ Object.defineProperties(Process, {
|
||||
enumerateRanges() {
|
||||
return [];
|
||||
},
|
||||
enumerateSections() {
|
||||
return [];
|
||||
},
|
||||
enumerateDependencies() {
|
||||
return [];
|
||||
},
|
||||
findExportByName() {
|
||||
return null;
|
||||
},
|
||||
getExportByName(exportName) {
|
||||
throw new Error(`unable to find export '${exportName}'`);
|
||||
getExportByName(name) {
|
||||
throw new Error(`unable to find export '${name}'`);
|
||||
},
|
||||
findSymbolByName() {
|
||||
return null;
|
||||
},
|
||||
getSymbolByName(name) {
|
||||
throw new Error(`unable to find symbol '${name}'`);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
private class BareboneScript : Object {
|
||||
private sealed class BareboneScript : Object {
|
||||
public signal void message (string json, Bytes? data);
|
||||
|
||||
public AgentScriptId id {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class Compiler : Object {
|
||||
public sealed class Compiler : Object {
|
||||
public signal void starting ();
|
||||
public signal void finished ();
|
||||
public signal void output (string bundle);
|
||||
@@ -199,7 +199,7 @@ namespace Frida {
|
||||
try {
|
||||
var device = yield manager.get_device_by_type (LOCAL, 0, io_cancellable);
|
||||
var session = yield device.get_host_session (io_cancellable);
|
||||
var agent = new Agent (this, (BaseDBusHostSession) session);
|
||||
var agent = new Agent (this, (LocalHostSession) session);
|
||||
|
||||
load_request.resolve (agent);
|
||||
} catch (GLib.Error e) {
|
||||
@@ -238,7 +238,7 @@ namespace Frida {
|
||||
private Promise<string> source_request = new Promise<string> ();
|
||||
private Promise<Bytes?> snapshot_request = new Promise<Bytes?> ();
|
||||
|
||||
public Agent (Compiler parent, BaseDBusHostSession host_session) {
|
||||
public Agent (Compiler parent, LocalHostSession host_session) {
|
||||
Object (
|
||||
parent: parent,
|
||||
host_session: host_session,
|
||||
@@ -465,10 +465,10 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class BuildOptions : CompilerOptions {
|
||||
public sealed class BuildOptions : CompilerOptions {
|
||||
}
|
||||
|
||||
public class WatchOptions : CompilerOptions {
|
||||
public sealed class WatchOptions : CompilerOptions {
|
||||
}
|
||||
|
||||
public enum SourceMaps {
|
||||
|
||||
Generated
+39
-23
@@ -9,15 +9,15 @@
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@frida/crosspath": "3.0.0",
|
||||
"frida-compile": "16.4.1",
|
||||
"frida-fs": "5.2.5"
|
||||
"frida-compile": "17.0.0",
|
||||
"frida-fs": "6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@frida/rollup-plugin-node-polyfills": "^1.0.3",
|
||||
"@rollup/plugin-node-resolve": "^14.1.0",
|
||||
"@rollup/plugin-replace": "^4.0.0",
|
||||
"@rollup/plugin-typescript": "^8.3.4",
|
||||
"@types/frida-gum": "18.8.1",
|
||||
"@types/frida-gum": "19.0.0",
|
||||
"@types/glob": "^8.0.0",
|
||||
"@types/node": "18.7.23",
|
||||
"glob": "^8.0.3",
|
||||
@@ -252,6 +252,13 @@
|
||||
"frida-fs": "^5.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/rollup-plugin-node-polyfills/node_modules/frida-fs": {
|
||||
"version": "5.2.5",
|
||||
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-5.2.5.tgz",
|
||||
"integrity": "sha512-Eyb4OqUlcv1/Eq7Q+B9IZmYZIgIM2YjqDojrjmAGzPSSXBuUKwSkuObQcQ8Dup9JTOMIUcSII9/I8DaTe6LFKw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/stream": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/stream/-/stream-1.0.2.tgz",
|
||||
@@ -468,9 +475,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/frida-gum": {
|
||||
"version": "18.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.8.1.tgz",
|
||||
"integrity": "sha512-FhlHORjaw43QbNYIyj5Ji7iYSvk7t5nPiC+GuYDVndqc1bFheeAs88b1odp8HhmpQUrrYVU90wapapKVLlmJHg==",
|
||||
"version": "19.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.0.tgz",
|
||||
"integrity": "sha512-qViK1KwvPEAkajwSUv0wpZvZLiX8xO4JFFCh8dfYZfzSyOEfoE0KliCP/nJSKIKG6N3hXnPowrvPufjs5fLKAA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -641,9 +648,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/frida-compile": {
|
||||
"version": "16.4.1",
|
||||
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-16.4.1.tgz",
|
||||
"integrity": "sha512-xI9HNtUFpHxuKBGXaL6XJAYH1zWTvNJDrHRnz1hp0oS24iPHt6c01Jmm3qljZek3oQWn8HhvfNvrzfgbsKzoBQ==",
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-17.0.0.tgz",
|
||||
"integrity": "sha512-ixJRj14qLH/Z0ckFWd5fKeDMm0W2+2WDpSGnLRgpn0nuCQAbDHRCqVCWtPnV8uzPJmA6XOX0pujsMpYe9q9RRw==",
|
||||
"dependencies": {
|
||||
"@frida/assert": "^3.0.1",
|
||||
"@frida/base64-js": "^2.0.3",
|
||||
@@ -673,7 +680,7 @@
|
||||
"@frida/util": "^1.0.3",
|
||||
"@frida/vm": "^2.0.0",
|
||||
"commander": "^11.1.0",
|
||||
"frida-fs": "^5.2.3",
|
||||
"frida-fs": "^6.0.0",
|
||||
"typed-emitter": "^2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -681,9 +688,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/frida-fs": {
|
||||
"version": "5.2.5",
|
||||
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-5.2.5.tgz",
|
||||
"integrity": "sha512-Eyb4OqUlcv1/Eq7Q+B9IZmYZIgIM2YjqDojrjmAGzPSSXBuUKwSkuObQcQ8Dup9JTOMIUcSII9/I8DaTe6LFKw=="
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-6.0.0.tgz",
|
||||
"integrity": "sha512-I0fnKupZh7fU2ixwCIjJnEqNdhfm/SC1ZYBMy58EmeqOWSbjw1Dpy99mJ7BJdbk2KNXJeaBZGxDYLtn0J9S+UA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
@@ -1290,6 +1298,14 @@
|
||||
"@frida/vm": "^2.0.0",
|
||||
"@rollup/plugin-inject": "^4.0.4",
|
||||
"frida-fs": "^5.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"frida-fs": {
|
||||
"version": "5.2.5",
|
||||
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-5.2.5.tgz",
|
||||
"integrity": "sha512-Eyb4OqUlcv1/Eq7Q+B9IZmYZIgIM2YjqDojrjmAGzPSSXBuUKwSkuObQcQ8Dup9JTOMIUcSII9/I8DaTe6LFKw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@frida/stream": {
|
||||
@@ -1466,9 +1482,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/frida-gum": {
|
||||
"version": "18.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.8.1.tgz",
|
||||
"integrity": "sha512-FhlHORjaw43QbNYIyj5Ji7iYSvk7t5nPiC+GuYDVndqc1bFheeAs88b1odp8HhmpQUrrYVU90wapapKVLlmJHg==",
|
||||
"version": "19.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.0.tgz",
|
||||
"integrity": "sha512-qViK1KwvPEAkajwSUv0wpZvZLiX8xO4JFFCh8dfYZfzSyOEfoE0KliCP/nJSKIKG6N3hXnPowrvPufjs5fLKAA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/glob": {
|
||||
@@ -1597,9 +1613,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"frida-compile": {
|
||||
"version": "16.4.1",
|
||||
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-16.4.1.tgz",
|
||||
"integrity": "sha512-xI9HNtUFpHxuKBGXaL6XJAYH1zWTvNJDrHRnz1hp0oS24iPHt6c01Jmm3qljZek3oQWn8HhvfNvrzfgbsKzoBQ==",
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-17.0.0.tgz",
|
||||
"integrity": "sha512-ixJRj14qLH/Z0ckFWd5fKeDMm0W2+2WDpSGnLRgpn0nuCQAbDHRCqVCWtPnV8uzPJmA6XOX0pujsMpYe9q9RRw==",
|
||||
"requires": {
|
||||
"@frida/assert": "^3.0.1",
|
||||
"@frida/base64-js": "^2.0.3",
|
||||
@@ -1629,14 +1645,14 @@
|
||||
"@frida/util": "^1.0.3",
|
||||
"@frida/vm": "^2.0.0",
|
||||
"commander": "^11.1.0",
|
||||
"frida-fs": "^5.2.3",
|
||||
"frida-fs": "^6.0.0",
|
||||
"typed-emitter": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"frida-fs": {
|
||||
"version": "5.2.5",
|
||||
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-5.2.5.tgz",
|
||||
"integrity": "sha512-Eyb4OqUlcv1/Eq7Q+B9IZmYZIgIM2YjqDojrjmAGzPSSXBuUKwSkuObQcQ8Dup9JTOMIUcSII9/I8DaTe6LFKw=="
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-6.0.0.tgz",
|
||||
"integrity": "sha512-I0fnKupZh7fU2ixwCIjJnEqNdhfm/SC1ZYBMy58EmeqOWSbjw1Dpy99mJ7BJdbk2KNXJeaBZGxDYLtn0J9S+UA=="
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
|
||||
@@ -9,15 +9,15 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@frida/crosspath": "3.0.0",
|
||||
"frida-compile": "16.4.1",
|
||||
"frida-fs": "5.2.5"
|
||||
"frida-compile": "17.0.0",
|
||||
"frida-fs": "6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@frida/rollup-plugin-node-polyfills": "^1.0.3",
|
||||
"@rollup/plugin-node-resolve": "^14.1.0",
|
||||
"@rollup/plugin-replace": "^4.0.0",
|
||||
"@rollup/plugin-typescript": "^8.3.4",
|
||||
"@types/frida-gum": "18.8.1",
|
||||
"@types/frida-gum": "19.0.0",
|
||||
"@types/glob": "^8.0.0",
|
||||
"@types/node": "18.7.23",
|
||||
"glob": "^8.0.3",
|
||||
|
||||
+230
-150
@@ -1,6 +1,5 @@
|
||||
namespace Frida {
|
||||
#if HAVE_LOCAL_BACKEND
|
||||
public class ControlService : Object {
|
||||
public sealed class ControlService : Object {
|
||||
public EndpointParameters endpoint_params {
|
||||
get;
|
||||
construct;
|
||||
@@ -12,6 +11,7 @@ namespace Frida {
|
||||
}
|
||||
|
||||
private HostSession host_session;
|
||||
private HostSessionProvider provider;
|
||||
|
||||
private State state = STOPPED;
|
||||
|
||||
@@ -21,8 +21,12 @@ namespace Frida {
|
||||
|
||||
private Gee.Set<ControlChannel> spawn_gaters = new Gee.HashSet<ControlChannel> ();
|
||||
private Gee.Map<uint, PendingSpawn> pending_spawn = new Gee.HashMap<uint, PendingSpawn> ();
|
||||
private Gee.Map<AgentSessionId?, AgentSessionEntry> sessions =
|
||||
private Gee.Map<AgentSessionId?, AgentSessionEntry> agent_sessions =
|
||||
new Gee.HashMap<AgentSessionId?, AgentSessionEntry> (AgentSessionId.hash, AgentSessionId.equal);
|
||||
private Gee.Map<ChannelId?, ChannelEntry> channels =
|
||||
new Gee.HashMap<ChannelId?, ChannelEntry> (ChannelId.hash, ChannelId.equal);
|
||||
private Gee.Map<ServiceSessionId?, ServiceSessionEntry> service_sessions =
|
||||
new Gee.HashMap<ServiceSessionId?, ServiceSessionEntry> (ServiceSessionId.hash, ServiceSessionId.equal);
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
@@ -35,7 +39,8 @@ namespace Frida {
|
||||
STOPPING
|
||||
}
|
||||
|
||||
public ControlService (EndpointParameters endpoint_params, ControlServiceOptions? options = null) {
|
||||
public ControlService (EndpointParameters endpoint_params, ControlServiceOptions? options = null) throws Error {
|
||||
#if HAVE_LOCAL_BACKEND
|
||||
ControlServiceOptions opts = (options != null) ? options : new ControlServiceOptions ();
|
||||
|
||||
HostSession session;
|
||||
@@ -63,7 +68,10 @@ namespace Frida {
|
||||
options: opts
|
||||
);
|
||||
|
||||
assign_session (session);
|
||||
assign_session (session, new PrecreatedLocalHostSessionProvider ((LocalHostSession) session));
|
||||
#else
|
||||
throw new Error.NOT_SUPPORTED ("Local backend not available");
|
||||
#endif
|
||||
}
|
||||
|
||||
public async ControlService.with_device (Device device, EndpointParameters endpoint_params,
|
||||
@@ -77,17 +85,7 @@ namespace Frida {
|
||||
options: opts
|
||||
);
|
||||
|
||||
assign_session (session);
|
||||
}
|
||||
|
||||
internal ControlService.with_host_session (HostSession host_session, EndpointParameters endpoint_params,
|
||||
ControlServiceOptions? options = null) {
|
||||
Object (
|
||||
endpoint_params: endpoint_params,
|
||||
options: (options != null) ? options : new ControlServiceOptions ()
|
||||
);
|
||||
|
||||
assign_session (host_session);
|
||||
assign_session (session, device.provider);
|
||||
}
|
||||
|
||||
construct {
|
||||
@@ -99,7 +97,7 @@ namespace Frida {
|
||||
main_handler = new ConnectionHandler (this, null);
|
||||
}
|
||||
|
||||
private void assign_session (HostSession session) {
|
||||
private void assign_session (HostSession session, HostSessionProvider provider) {
|
||||
host_session = session;
|
||||
host_session.spawn_added.connect (notify_spawn_added);
|
||||
host_session.child_added.connect (notify_child_added);
|
||||
@@ -107,7 +105,11 @@ namespace Frida {
|
||||
host_session.process_crashed.connect (notify_process_crashed);
|
||||
host_session.output.connect (notify_output);
|
||||
host_session.agent_session_detached.connect (on_agent_session_detached);
|
||||
host_session.channel_closed.connect (on_channel_closed);
|
||||
host_session.service_session_closed.connect (on_service_session_closed);
|
||||
host_session.uninjected.connect (notify_uninjected);
|
||||
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public async void start (Cancellable? cancellable = null) throws Error, IOError {
|
||||
@@ -123,7 +125,7 @@ namespace Frida {
|
||||
yield service.start (cancellable);
|
||||
|
||||
if (options.enable_preload) {
|
||||
var base_host_session = host_session as BaseDBusHostSession;
|
||||
var base_host_session = host_session as LocalHostSession;
|
||||
if (base_host_session != null)
|
||||
base_host_session.preload.begin (io_cancellable);
|
||||
}
|
||||
@@ -162,9 +164,8 @@ namespace Frida {
|
||||
|
||||
yield main_handler.close (cancellable);
|
||||
|
||||
var base_host_session = host_session as BaseDBusHostSession;
|
||||
if (base_host_session != null)
|
||||
yield base_host_session.close (cancellable);
|
||||
if (provider is PrecreatedLocalHostSessionProvider)
|
||||
yield provider.destroy (host_session, cancellable);
|
||||
|
||||
state = STOPPED;
|
||||
}
|
||||
@@ -226,17 +227,15 @@ namespace Frida {
|
||||
}
|
||||
|
||||
private async void teardown_control_channel (ControlChannel channel) {
|
||||
foreach (AgentSessionId id in channel.sessions) {
|
||||
AgentSessionEntry entry = sessions[id];
|
||||
foreach (AgentSessionId id in channel.agent_sessions) {
|
||||
AgentSessionEntry entry = agent_sessions[id];
|
||||
|
||||
var base_host_session = host_session as BaseDBusHostSession;
|
||||
if (base_host_session != null)
|
||||
base_host_session.unlink_agent_session (id);
|
||||
provider.unlink_agent_session (host_session, id);
|
||||
|
||||
AgentSession? session = entry.session;
|
||||
|
||||
if (entry.persist_timeout == 0 || session == null) {
|
||||
sessions.unset (id);
|
||||
agent_sessions.unset (id);
|
||||
if (session != null)
|
||||
session.close.begin (io_cancellable);
|
||||
} else {
|
||||
@@ -245,6 +244,24 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ChannelId id in channel.channels.to_array ()) {
|
||||
ChannelEntry entry = channels[id];
|
||||
|
||||
provider.unlink_channel (host_session, id);
|
||||
|
||||
channels.unset (id);
|
||||
|
||||
Channel? ch = entry.channel;
|
||||
if (ch != null)
|
||||
ch.close.begin (null);
|
||||
}
|
||||
|
||||
foreach (ServiceSessionId id in channel.service_sessions.to_array ()) {
|
||||
provider.unlink_service_session (host_session, id);
|
||||
|
||||
service_sessions.unset (id);
|
||||
}
|
||||
|
||||
try {
|
||||
yield disable_spawn_gating (channel);
|
||||
} catch (GLib.Error e) {
|
||||
@@ -379,12 +396,22 @@ namespace Frida {
|
||||
yield parent.reattach (id, requester, cancellable);
|
||||
}
|
||||
|
||||
public async ChannelId open_channel (string address, ControlChannel requester, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
return yield parent.open_channel (address, requester, cancellable);
|
||||
}
|
||||
|
||||
public async ServiceSessionId open_service (string address, ControlChannel requester, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
return yield parent.open_service (address, requester, cancellable);
|
||||
}
|
||||
|
||||
public void open_tcp_transport (AgentSessionId id, Cancellable? cancellable, out uint16 port, out string token)
|
||||
throws Error {
|
||||
#if WINDOWS
|
||||
throw new Error.NOT_SUPPORTED ("Not yet supported on Windows");
|
||||
#else
|
||||
var base_host_session = host_session as BaseDBusHostSession;
|
||||
var base_host_session = host_session as LocalHostSession;
|
||||
if (base_host_session == null)
|
||||
throw new Error.NOT_SUPPORTED ("Not supported for remote host sessions");
|
||||
if (!base_host_session.can_pass_file_descriptors_to_agent_session (id))
|
||||
@@ -454,7 +481,7 @@ namespace Frida {
|
||||
#if !WINDOWS
|
||||
AgentSessionId session_id = transport.session_id;
|
||||
|
||||
var base_host_session = host_session as BaseDBusHostSession;
|
||||
var base_host_session = host_session as LocalHostSession;
|
||||
if (base_host_session == null)
|
||||
throw new Error.NOT_SUPPORTED ("Not supported for remote host sessions");
|
||||
|
||||
@@ -537,12 +564,12 @@ namespace Frida {
|
||||
throw_dbus_error (e);
|
||||
}
|
||||
|
||||
requester.sessions.add (id);
|
||||
requester.agent_sessions.add (id);
|
||||
|
||||
var opts = SessionOptions._deserialize (options);
|
||||
|
||||
var entry = new AgentSessionEntry (requester, id, opts.persist_timeout, io_cancellable);
|
||||
sessions[id] = entry;
|
||||
var entry = new AgentSessionEntry (requester, id, opts.persist_timeout);
|
||||
agent_sessions[id] = entry;
|
||||
entry.expired.connect (on_agent_session_expired);
|
||||
|
||||
yield link_session (id, entry, requester, cancellable);
|
||||
@@ -551,11 +578,11 @@ namespace Frida {
|
||||
}
|
||||
|
||||
private async void reattach (AgentSessionId id, ControlChannel requester, Cancellable? cancellable) throws Error, IOError {
|
||||
AgentSessionEntry? entry = sessions[id];
|
||||
AgentSessionEntry? entry = agent_sessions[id];
|
||||
if (entry == null || entry.controller != null)
|
||||
throw new Error.INVALID_OPERATION ("Invalid session ID");
|
||||
|
||||
requester.sessions.add (id);
|
||||
requester.agent_sessions.add (id);
|
||||
|
||||
entry.attach_controller (requester);
|
||||
|
||||
@@ -574,28 +601,7 @@ namespace Frida {
|
||||
throw_dbus_error (e);
|
||||
}
|
||||
|
||||
AgentSession session;
|
||||
var base_host_session = host_session as BaseDBusHostSession;
|
||||
if (base_host_session != null) {
|
||||
session = yield base_host_session.link_agent_session (id, sink, cancellable);
|
||||
} else {
|
||||
DBusConnection internal_connection = ((DBusProxy) host_session).g_connection;
|
||||
|
||||
try {
|
||||
session = yield internal_connection.get_proxy (null, ObjectPath.for_agent_session (id),
|
||||
DO_NOT_LOAD_PROPERTIES, cancellable);
|
||||
} catch (IOError e) {
|
||||
throw_dbus_error (e);
|
||||
}
|
||||
|
||||
entry.internal_connection = internal_connection;
|
||||
try {
|
||||
entry.take_internal_registration (
|
||||
internal_connection.register_object (ObjectPath.for_agent_message_sink (id), sink));
|
||||
} catch (IOError e) {
|
||||
assert_not_reached ();
|
||||
}
|
||||
}
|
||||
var session = yield provider.link_agent_session (host_session, id, sink, cancellable);
|
||||
|
||||
entry.session = session;
|
||||
try {
|
||||
@@ -606,6 +612,52 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private async ChannelId open_channel (string address, ControlChannel requester, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
ChannelId id;
|
||||
try {
|
||||
id = yield host_session.open_channel (address, cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw_dbus_error (e);
|
||||
}
|
||||
|
||||
requester.channels.add (id);
|
||||
|
||||
var entry = new ChannelEntry (requester, id);
|
||||
channels[id] = entry;
|
||||
|
||||
var stream = yield provider.link_channel (host_session, id, cancellable);
|
||||
|
||||
Channel channel = new ChannelEndpoint (stream);
|
||||
entry.channel = channel;
|
||||
entry.take_controller_registration (requester.connection.register_object (ObjectPath.for_channel (id), channel));
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private async ServiceSessionId open_service (string address, ControlChannel requester, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
ServiceSessionId id;
|
||||
try {
|
||||
id = yield host_session.open_service (address, cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw_dbus_error (e);
|
||||
}
|
||||
|
||||
requester.service_sessions.add (id);
|
||||
|
||||
var entry = new ServiceSessionEntry (requester, id);
|
||||
service_sessions[id] = entry;
|
||||
|
||||
var session = yield provider.link_service_session (host_session, id, cancellable);
|
||||
|
||||
entry.session = session;
|
||||
entry.take_controller_registration (
|
||||
requester.connection.register_object (ObjectPath.for_service_session (id), session));
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private void notify_spawn_added (HostSpawnInfo info) {
|
||||
foreach (ControlChannel channel in spawn_gaters)
|
||||
channel.spawn_added (info);
|
||||
@@ -646,15 +698,33 @@ namespace Frida {
|
||||
|
||||
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
|
||||
AgentSessionEntry entry;
|
||||
if (sessions.unset (id, out entry)) {
|
||||
if (agent_sessions.unset (id, out entry)) {
|
||||
ControlChannel? controller = entry.controller;
|
||||
if (controller != null) {
|
||||
controller.sessions.remove (id);
|
||||
controller.agent_sessions.remove (id);
|
||||
controller.agent_session_detached (id, reason, crash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void on_channel_closed (ChannelId id) {
|
||||
ChannelEntry entry;
|
||||
if (channels.unset (id, out entry)) {
|
||||
ControlChannel controller = entry.controller;
|
||||
controller.channels.remove (id);
|
||||
controller.channel_closed (id);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_service_session_closed (ServiceSessionId id) {
|
||||
ServiceSessionEntry entry;
|
||||
if (service_sessions.unset (id, out entry)) {
|
||||
ControlChannel controller = entry.controller;
|
||||
controller.service_sessions.remove (id);
|
||||
controller.service_session_closed (id);
|
||||
}
|
||||
}
|
||||
|
||||
private void notify_uninjected (InjectorPayloadId id) {
|
||||
all_control_channels ().foreach (channel => {
|
||||
channel.uninjected (id);
|
||||
@@ -663,7 +733,7 @@ namespace Frida {
|
||||
}
|
||||
|
||||
private void on_agent_session_expired (AgentSessionEntry entry) {
|
||||
sessions.unset (entry.id);
|
||||
agent_sessions.unset (entry.id);
|
||||
}
|
||||
|
||||
private interface Peer : Object {
|
||||
@@ -738,11 +808,21 @@ namespace Frida {
|
||||
construct;
|
||||
}
|
||||
|
||||
public Gee.Set<AgentSessionId?> sessions {
|
||||
public Gee.Set<AgentSessionId?> agent_sessions {
|
||||
get;
|
||||
default = new Gee.HashSet<AgentSessionId?> (AgentSessionId.hash, AgentSessionId.equal);
|
||||
}
|
||||
|
||||
public Gee.Set<ChannelId?> channels {
|
||||
get;
|
||||
default = new Gee.HashSet<ChannelId?> (ChannelId.hash, ChannelId.equal);
|
||||
}
|
||||
|
||||
public Gee.Set<ServiceSessionId?> service_sessions {
|
||||
get;
|
||||
default = new Gee.HashSet<ServiceSessionId?> (ServiceSessionId.hash, ServiceSessionId.equal);
|
||||
}
|
||||
|
||||
private Gee.Set<uint> registrations = new Gee.HashSet<uint> ();
|
||||
private TimeoutSource? ping_timer;
|
||||
|
||||
@@ -867,6 +947,14 @@ namespace Frida {
|
||||
return yield parent.host_session.inject_library_blob (pid, blob, entrypoint, data, cancellable);
|
||||
}
|
||||
|
||||
public async ChannelId open_channel (string address, Cancellable? cancellable) throws GLib.Error {
|
||||
return yield parent.open_channel (address, this, cancellable);
|
||||
}
|
||||
|
||||
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws GLib.Error {
|
||||
return yield parent.open_service (address, this, cancellable);
|
||||
}
|
||||
|
||||
private async void open_tcp_transport (AgentSessionId id, Cancellable? cancellable, out uint16 port,
|
||||
out string token) throws Error {
|
||||
parent.open_tcp_transport (id, cancellable, out port, out token);
|
||||
@@ -890,14 +978,45 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private class AgentSessionEntry {
|
||||
public signal void expired ();
|
||||
|
||||
private abstract class Entry {
|
||||
public ControlChannel? controller {
|
||||
get;
|
||||
private set;
|
||||
get {
|
||||
return _controller;
|
||||
}
|
||||
protected set {
|
||||
unregister_all ();
|
||||
_controller = value;
|
||||
}
|
||||
}
|
||||
|
||||
private ControlChannel? _controller;
|
||||
private Gee.Collection<uint> registrations = new Gee.ArrayList<uint> ();
|
||||
|
||||
protected Entry (ControlChannel? controller) {
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
~Entry () {
|
||||
unregister_all ();
|
||||
}
|
||||
|
||||
public void take_controller_registration (uint id) {
|
||||
registrations.add (id);
|
||||
}
|
||||
|
||||
private void unregister_all () {
|
||||
if (_controller == null)
|
||||
return;
|
||||
var connection = _controller.connection;
|
||||
foreach (uint id in registrations)
|
||||
connection.unregister_object (id);
|
||||
registrations.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
private class AgentSessionEntry : Entry {
|
||||
public signal void expired ();
|
||||
|
||||
public AgentSessionId id {
|
||||
get;
|
||||
private set;
|
||||
@@ -913,36 +1032,20 @@ namespace Frida {
|
||||
private set;
|
||||
}
|
||||
|
||||
public DBusConnection? internal_connection {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Cancellable io_cancellable {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private Gee.Collection<uint> internal_registrations = new Gee.ArrayList<uint> ();
|
||||
private Gee.Collection<uint> controller_registrations = new Gee.ArrayList<uint> ();
|
||||
|
||||
private TimeoutSource? expiry_timer;
|
||||
|
||||
public AgentSessionEntry (ControlChannel controller, AgentSessionId id, uint persist_timeout,
|
||||
Cancellable io_cancellable) {
|
||||
this.controller = controller;
|
||||
public AgentSessionEntry (ControlChannel? controller, AgentSessionId id, uint persist_timeout) {
|
||||
base (controller);
|
||||
|
||||
this.id = id;
|
||||
this.persist_timeout = persist_timeout;
|
||||
this.io_cancellable = io_cancellable;
|
||||
}
|
||||
|
||||
~AgentSessionEntry () {
|
||||
stop_expiry_timer ();
|
||||
unregister_all ();
|
||||
}
|
||||
|
||||
public void detach_controller () {
|
||||
unregister_all ();
|
||||
controller = null;
|
||||
session = null;
|
||||
|
||||
@@ -956,27 +1059,6 @@ namespace Frida {
|
||||
controller = c;
|
||||
}
|
||||
|
||||
public void take_internal_registration (uint id) {
|
||||
internal_registrations.add (id);
|
||||
}
|
||||
|
||||
public void take_controller_registration (uint id) {
|
||||
controller_registrations.add (id);
|
||||
}
|
||||
|
||||
private void unregister_all () {
|
||||
if (controller != null)
|
||||
unregister_all_in (controller_registrations, controller.connection);
|
||||
if (internal_connection != null)
|
||||
unregister_all_in (internal_registrations, internal_connection);
|
||||
}
|
||||
|
||||
private void unregister_all_in (Gee.Collection<uint> ids, DBusConnection connection) {
|
||||
foreach (uint id in ids)
|
||||
connection.unregister_object (id);
|
||||
ids.clear ();
|
||||
}
|
||||
|
||||
private void start_expiry_timer () {
|
||||
if (expiry_timer != null)
|
||||
return;
|
||||
@@ -995,57 +1077,55 @@ namespace Frida {
|
||||
expiry_timer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
public class ControlService : Object {
|
||||
public ControlService (EndpointParameters endpoint_params, ControlServiceOptions? options = null) {
|
||||
}
|
||||
|
||||
public ControlService.with_host_session (HostSession host_session, EndpointParameters endpoint_params,
|
||||
ControlServiceOptions? options = null) {
|
||||
}
|
||||
|
||||
public async void start (Cancellable? cancellable = null) throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("Local backend not available");
|
||||
}
|
||||
|
||||
public void start_sync (Cancellable? cancellable = null) throws Error, IOError {
|
||||
create<StartTask> ().execute (cancellable);
|
||||
}
|
||||
|
||||
private class StartTask : ControlServiceTask<void> {
|
||||
protected override async void perform_operation () throws Error, IOError {
|
||||
yield parent.start (cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
public async void stop (Cancellable? cancellable = null) throws Error, IOError {
|
||||
}
|
||||
|
||||
public void stop_sync (Cancellable? cancellable = null) throws Error, IOError {
|
||||
create<StopTask> ().execute (cancellable);
|
||||
}
|
||||
|
||||
private class StopTask : ControlServiceTask<void> {
|
||||
protected override async void perform_operation () throws Error, IOError {
|
||||
yield parent.stop (cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
private T create<T> () {
|
||||
return Object.new (typeof (T), parent: this);
|
||||
}
|
||||
|
||||
private abstract class ControlServiceTask<T> : AsyncTask<T> {
|
||||
public weak ControlService parent {
|
||||
private class ChannelEntry : Entry {
|
||||
public ChannelId id {
|
||||
get;
|
||||
construct;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Channel? channel {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public ChannelEntry (ControlChannel controller, ChannelId id) {
|
||||
base (controller);
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
private class ServiceSessionEntry : Entry {
|
||||
public ServiceSessionId id {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public ServiceSession? session {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public ServiceSessionEntry (ControlChannel controller, ServiceSessionId id) {
|
||||
base (controller);
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public class ControlServiceOptions : Object {
|
||||
private sealed class PrecreatedLocalHostSessionProvider : LocalHostSessionProvider {
|
||||
public PrecreatedLocalHostSessionProvider (LocalHostSession session) {
|
||||
take_host_session (session);
|
||||
}
|
||||
|
||||
protected override LocalHostSession make_host_session (HostSessionOptions? options) throws Error {
|
||||
throw new Error.NOT_SUPPORTED ("Not supported");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ControlServiceOptions : Object {
|
||||
public string? sysroot {
|
||||
get;
|
||||
set;
|
||||
|
||||
@@ -21,7 +21,7 @@ const substratePidsPending = new Map();
|
||||
rpc.exports = {
|
||||
dispose() {
|
||||
if (suspendedPids.size > 0) {
|
||||
const kill = new NativeFunction(Module.getExportByName(null, 'kill'), 'int', ['int', 'int']);
|
||||
const kill = new NativeFunction(Module.getGlobalExportByName('kill'), 'int', ['int', 'int']);
|
||||
for (const pid of suspendedPids) {
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
@@ -49,7 +49,7 @@ rpc.exports = {
|
||||
|
||||
applyJailbreakQuirks();
|
||||
|
||||
Interceptor.attach(Module.getExportByName('/usr/lib/system/libsystem_kernel.dylib', '__posix_spawn'), {
|
||||
Interceptor.attach(Process.getModuleByName('/usr/lib/system/libsystem_kernel.dylib').getExportByName('__posix_spawn'), {
|
||||
onEnter(args) {
|
||||
const env = parseStringv(args[4]);
|
||||
const prewarm = isPrewarmLaunch(env);
|
||||
@@ -238,7 +238,7 @@ function instrumentInserter(at) {
|
||||
}
|
||||
|
||||
function findJbdCallImpl() {
|
||||
const impl = Module.findExportByName(null, 'jbd_call');
|
||||
const impl = Module.findGlobalExportByName('jbd_call');
|
||||
if (impl !== null)
|
||||
return impl;
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import ObjC from 'frida-objc-bridge';
|
||||
|
||||
const YES = ptr(1);
|
||||
|
||||
const {
|
||||
@@ -53,7 +55,8 @@ function tryInitialize() {
|
||||
}
|
||||
|
||||
if (!tryInitialize()) {
|
||||
const listener = Interceptor.attach(Module.getExportByName('/usr/lib/system/libsystem_trace.dylib', 'os_log_type_enabled'), () => {
|
||||
const listener = Interceptor.attach(
|
||||
Process.getModuleByName('/usr/lib/system/libsystem_trace.dylib').getExportByName('os_log_type_enabled'), () => {
|
||||
tryInitialize();
|
||||
listener.detach();
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
osanalytics_js = custom_target('osanalytics.js',
|
||||
input: [
|
||||
'package.json',
|
||||
'package-lock.json',
|
||||
'index.js',
|
||||
],
|
||||
output: [
|
||||
'osanalytics.js',
|
||||
],
|
||||
command: [
|
||||
python,
|
||||
compile_js_agent,
|
||||
'@OUTPUT@',
|
||||
'@PRIVATE_DIR@',
|
||||
npm,
|
||||
'@INPUT@',
|
||||
],
|
||||
)
|
||||
+553
@@ -0,0 +1,553 @@
|
||||
{
|
||||
"name": "frida-osanalytics-agent",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "frida-osanalytics-agent",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"frida-objc-bridge": "^8.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/frida-gum": "^19.0.0",
|
||||
"frida-compile": "^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/assert": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/assert/-/assert-3.0.2.tgz",
|
||||
"integrity": "sha512-JXJq5SbXGrM5EkjrZKfRmB29zOoEOix02NC6A5TSJ+C1GE/X051EinJJsuOO2pEOx7KZwpvAHvS0WXW0+levKg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/base64-js": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@frida/base64-js/-/base64-js-2.0.3.tgz",
|
||||
"integrity": "sha512-2w0F+1TynOTCZ/v7du9LdHPWwq0lJhazjo2fF9upMyQmA1zHetT14fLuQ1v/6T0qPgyeEGkiSrybstU8EsgeUA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/buffer": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@frida/buffer/-/buffer-7.0.4.tgz",
|
||||
"integrity": "sha512-RxQ1lZRRiCJj7nhcCiD8xeJx0NsLpGGnjqsmTg7jShGmbnVFMN5W7+J+3gqdPSQhc/IxNBIWc6zRXVp4+qnYHg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.5.1",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/crosspath": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/crosspath/-/crosspath-3.0.0.tgz",
|
||||
"integrity": "sha512-bNdO1spIPD2P40XtK89N49oZpJhstdlnkJZcD4yJ17jrdkm9Ctu0sd9MIEX6Z8Tm8ydhVJBAOMEKl9/R27onAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "^17.0.36"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/crypto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@frida/crypto/-/crypto-1.0.1.tgz",
|
||||
"integrity": "sha512-WXTkVjESvX8TIVXIynJJv9BKSIdQP0Iis04StIXknkDi1ULdMlrypA9p5C4KW1H6GCkNsVnKbybpzsulYCTvag==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/diagnostics_channel": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/diagnostics_channel/-/diagnostics_channel-1.0.0.tgz",
|
||||
"integrity": "sha512-mYX1jp/5Bpk24tHArJNx65iCk7qSuV8YJkdU0gFNVtJUXxfV8BG5WuPa4mL+ynxsbWWpsg/cwKZbLAepYKTdQQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/events": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@frida/events/-/events-4.0.4.tgz",
|
||||
"integrity": "sha512-qJVQ6VWHf9sjUKuiJzoCAC00frbpcwxeYfvQ+PP9LU/d70j+QvjWgYe98Qa3ekLaBU6r/AvWm8ThKCDUCLWrQQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/http": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/http/-/http-4.0.2.tgz",
|
||||
"integrity": "sha512-cvkc7ex7GmVXVOWqtjXKBWUUbYEBgpNRKZbEEoMeI8KiIs8zejKwg+N7rx7296Ao+EP3+xcUr4wBVr3xLaUVfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"http-parser-js": "^0.5.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/http-parser-js": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/http-parser-js/-/http-parser-js-1.0.0.tgz",
|
||||
"integrity": "sha512-2nMrNXt/OeTlWbqnE8AH4Sfz4I2+BGoN206dzKEyC/g2svtn83Xu+zuv/V3TkwrA27s26Mcy84ZwsXeNlqNxUQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/https": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/https/-/https-1.0.0.tgz",
|
||||
"integrity": "sha512-OiqQ6qsALcWOktRLq07oJ0i6sH8eX6MXb/MdZS1qVKDRf6wchH4Pjn6fiLB+pt/OlYbggk+DOfpHwSdjTwuHMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/ieee754": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/ieee754/-/ieee754-2.0.2.tgz",
|
||||
"integrity": "sha512-wlcUebnne4ENN7GDr5pTH598ZDLMVOsh0FjenxeVOe6u7ewZkz9gGRnLnZKJAm9kl5G6XhdxhI0cSXVQK/rQUw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@frida/net": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/net/-/net-4.0.2.tgz",
|
||||
"integrity": "sha512-qQRe7hQ+ZfCcG/SE3P1TRqQ9bmuK/T7wPCYaT4z56rBPWAxsaQbQHpX4fR6OrFaSDr7X0xJLsTbdIp9hGhhLZg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/os": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/os/-/os-1.0.2.tgz",
|
||||
"integrity": "sha512-3ISAiGNiyIya3QN2EHBCz1wqP0enTdSxP99wUeroeh8+AQRmgoOr/5TRnrVry8pe378anay3fmV/tdUMMSkehQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/path": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@frida/path/-/path-2.0.3.tgz",
|
||||
"integrity": "sha512-2RQy36QatoC846fzBhBhV8sXMsSOBGoYvwTHeaE1zUdz7F4RNScP4QEekTTooBYWYX/XjiF36KQpYAzc9OYFtg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/process": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@frida/process/-/process-1.2.1.tgz",
|
||||
"integrity": "sha512-nvCu22DstFW2ttGFtOKekHM7vnjbZm+XgtvavOt427GNT6uV7k0JYK9tnMbcLMRWv57DG6udAmuJlWs8Paq1ag==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/punycode": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/punycode/-/punycode-3.0.0.tgz",
|
||||
"integrity": "sha512-XVSDY2KamDs1D5/fTVgHcOSNxdU4kTboxzqJMBbTjcQC7XScIT9c0EfbwKCq7Kci6gWQdsHSCr7lU+9Oc4KAdg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/querystring": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/querystring/-/querystring-1.0.0.tgz",
|
||||
"integrity": "sha512-15m1fOZPmoO/vWlgPJrG/J9/BJDz6a2/JpVGpS8ynNzo+fBhTznaStX5nHxUs24mVTqh/OqLo0EiYJM5WWHXxg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/readable-stream": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@frida/readable-stream/-/readable-stream-4.1.3.tgz",
|
||||
"integrity": "sha512-ntGUFmi+CryRGRJIK13a/VST2Ad19uivbln8Xd92vKPAARq+6vMIASDyZIqyl5BLRccfiyCHdYgrgQ6RI5rUig==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/reserved-words": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/reserved-words/-/reserved-words-1.0.0.tgz",
|
||||
"integrity": "sha512-2yG/XxJlsGlk/mm6eZTb4OAaQEhkTI2qaFfZFtAsrA/XuCpuMWkS4y/guyBlsRu4hAuhK2HPmNM8+OLLK1zM9Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/stream": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/stream/-/stream-1.0.2.tgz",
|
||||
"integrity": "sha512-4OuaC1ztmEKgTq3WeBhsy8Oq+AwW9n9cYnvLklcC9jwD93AEwgbWpecLlxJCVuALvTMdhKPg0nQVfyGYP/i9Bw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@frida/readable-stream": "^4.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/string_decoder": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/string_decoder/-/string_decoder-2.0.0.tgz",
|
||||
"integrity": "sha512-in371tYZMHQiW9HF5MS3JDw6Ao6tyBoq34UWy2rzOswYyMG1rpizh85ofi/yVkxDiaqybEZefxzkVittpPGT6g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/terser": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/terser/-/terser-1.0.0.tgz",
|
||||
"integrity": "sha512-59h9WuNzD1Rx/zwoWqQ/FW/4Y/Q3R91Eng2hEwdHapqiTDvtKbZ08F6CynCR7ZVinrh4tLYsF46AtVPTz1ys9g==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.2",
|
||||
"acorn": "^8.5.0",
|
||||
"commander": "^2.20.0",
|
||||
"source-map-support": "~0.5.20"
|
||||
},
|
||||
"bin": {
|
||||
"terser": "bin/terser"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/terser/node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/timers": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/timers/-/timers-3.0.0.tgz",
|
||||
"integrity": "sha512-3b+0igv10aT8TMxefrTAd06rActqbxJLY2Xkkq9vYcPBffB/yHszl0NYIp/5ko8WC3ecDYPU6bQiY6fjs72zTA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/tty": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/tty/-/tty-1.0.0.tgz",
|
||||
"integrity": "sha512-p/kjLnKYxEAB1MdYP8+5rKv9CsHzyA+0jg9BcGETzjQVKHHcroHDULRxDYUh+DC7qs6cpX8QdDQh9E+a6ydgsQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/url": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/url/-/url-1.0.2.tgz",
|
||||
"integrity": "sha512-ZKunbKJHMr8w2Eb/5K1avy0MzK1B998S17wYXNv3RmzBGxMm8S5T0F3qEpRxkU7/72P8m4izyQU87fWl+FjQsQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@frida/punycode": "^3.0.0",
|
||||
"@frida/querystring": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/util": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@frida/util/-/util-1.0.3.tgz",
|
||||
"integrity": "sha512-htcG3uDiRXv89ERVNNYhfase39kJ2X75ZARfrYcYEtJLFEsSk0nemM1YnEIR4CjrHvdvkWHrwgKkS+acOyoNEg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/vm": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/vm/-/vm-2.0.0.tgz",
|
||||
"integrity": "sha512-7fsjLWscZT5odNIBtg6qbLNI+vAk1xmii6H5W2kaYkMYt0vRohQEcDSUWacA+eaWlu5SvMjZI82Yibj/3G9pJw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.8",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
||||
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/set-array": "^1.2.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
"@jridgewell/trace-mapping": "^0.3.24"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/resolve-uri": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/set-array": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/source-map": {
|
||||
"version": "0.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
||||
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.25",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "17.0.45",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
|
||||
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
|
||||
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/frida-compile": {
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-17.0.0.tgz",
|
||||
"integrity": "sha512-ixJRj14qLH/Z0ckFWd5fKeDMm0W2+2WDpSGnLRgpn0nuCQAbDHRCqVCWtPnV8uzPJmA6XOX0pujsMpYe9q9RRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@frida/assert": "^3.0.1",
|
||||
"@frida/base64-js": "^2.0.3",
|
||||
"@frida/buffer": "^7.0.4",
|
||||
"@frida/crosspath": "^3.0.0",
|
||||
"@frida/crypto": "^1.0.1",
|
||||
"@frida/diagnostics_channel": "^1.0.0",
|
||||
"@frida/events": "^4.0.4",
|
||||
"@frida/http": "^4.0.2",
|
||||
"@frida/http-parser-js": "^1.0.0",
|
||||
"@frida/https": "^1.0.0",
|
||||
"@frida/ieee754": "^2.0.2",
|
||||
"@frida/net": "^4.0.1",
|
||||
"@frida/os": "^1.0.0",
|
||||
"@frida/path": "^2.0.3",
|
||||
"@frida/process": "^1.2.1",
|
||||
"@frida/punycode": "^3.0.0",
|
||||
"@frida/querystring": "^1.0.0",
|
||||
"@frida/readable-stream": "^4.1.3",
|
||||
"@frida/reserved-words": "^1.0.0",
|
||||
"@frida/stream": "^1.0.2",
|
||||
"@frida/string_decoder": "^2.0.0",
|
||||
"@frida/terser": "^1.0.0",
|
||||
"@frida/timers": "^3.0.0",
|
||||
"@frida/tty": "^1.0.0",
|
||||
"@frida/url": "^1.0.2",
|
||||
"@frida/util": "^1.0.3",
|
||||
"@frida/vm": "^2.0.0",
|
||||
"commander": "^11.1.0",
|
||||
"frida-fs": "^6.0.0",
|
||||
"typed-emitter": "^2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"frida-compile": "dist/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/frida-fs": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-6.0.0.tgz",
|
||||
"integrity": "sha512-I0fnKupZh7fU2ixwCIjJnEqNdhfm/SC1ZYBMy58EmeqOWSbjw1Dpy99mJ7BJdbk2KNXJeaBZGxDYLtn0J9S+UA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/frida-objc-bridge": {
|
||||
"version": "8.0.4",
|
||||
"resolved": "https://registry.npmjs.org/frida-objc-bridge/-/frida-objc-bridge-8.0.4.tgz",
|
||||
"integrity": "sha512-AUzwq/+TFtblQLTI97UPX22pBcvyG2oUde9380DXbcJ0zXts4n9JDVONHUr03aBowa0Le+bdBoVdCs7jyyjvlg==",
|
||||
"license": "LGPL-2.0 WITH WxWindows-exception-3.1"
|
||||
},
|
||||
"node_modules/http-parser-js": {
|
||||
"version": "0.5.10",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz",
|
||||
"integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "7.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
|
||||
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"dev": true,
|
||||
"license": "0BSD",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/typed-emitter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"rxjs": "*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "frida-osanalytics-agent",
|
||||
"version": "1.0.0",
|
||||
"description": "Agent used by Frida's Darwin backend on iOS/iPadOS/tvOS",
|
||||
"scripts": {
|
||||
"prepare": "npm run build",
|
||||
"build": "frida-compile index.js -o osanalytics.js -S -c"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/frida-gum": "^19.0.0",
|
||||
"frida-compile": "^17.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"frida-objc-bridge": "^8.0.4"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
const LIBSYSTEM_KERNEL_PATH = '/usr/lib/system/libsystem_kernel.dylib';
|
||||
const CORESYMBOLICATION_PATH = '/System/Library/PrivateFrameworks/CoreSymbolication.framework/CoreSymbolication';
|
||||
const CRASH_REPORTER_SUPPORT_PATH = '/System/Library/PrivateFrameworks/CrashReporterSupport.framework/CrashReporterSupport';
|
||||
import ObjC from 'frida-objc-bridge';
|
||||
|
||||
const YES = ptr(1);
|
||||
|
||||
const CSTypeRef = ['pointer', 'pointer'];
|
||||
@@ -17,42 +16,45 @@ const complexFuncOptions = {
|
||||
scheduling: 'cooperative',
|
||||
exceptions: 'propagate'
|
||||
};
|
||||
const libsystemKernel = Process.getModuleByName('/usr/lib/system/libsystem_kernel.dylib');
|
||||
const _pidForTask = new NativeFunction(
|
||||
Module.getExportByName(LIBSYSTEM_KERNEL_PATH, 'pid_for_task'),
|
||||
libsystemKernel.getExportByName('pid_for_task'),
|
||||
'int',
|
||||
['uint', 'pointer'],
|
||||
simpleFuncOptions
|
||||
);
|
||||
const unlink = new NativeFunction(
|
||||
Module.getExportByName(LIBSYSTEM_KERNEL_PATH, 'unlink'),
|
||||
libsystemKernel.getExportByName('unlink'),
|
||||
'int',
|
||||
['pointer'],
|
||||
simpleFuncOptions
|
||||
);
|
||||
const coreSymbolication = Process.getModuleByName('/System/Library/PrivateFrameworks/CoreSymbolication.framework/CoreSymbolication');
|
||||
const CSSymbolicatorGetSymbolWithAddressAtTime = new NativeFunction(
|
||||
Module.getExportByName(CORESYMBOLICATION_PATH, 'CSSymbolicatorGetSymbolWithAddressAtTime'),
|
||||
coreSymbolication.getExportByName('CSSymbolicatorGetSymbolWithAddressAtTime'),
|
||||
CSTypeRef,
|
||||
[CSTypeRef, 'uint64', 'uint64'],
|
||||
complexFuncOptions
|
||||
);
|
||||
const CSIsNull = new NativeFunction(
|
||||
Module.getExportByName(CORESYMBOLICATION_PATH, 'CSIsNull'),
|
||||
coreSymbolication.getExportByName('CSIsNull'),
|
||||
'int',
|
||||
[CSTypeRef],
|
||||
simpleFuncOptions
|
||||
);
|
||||
const mappedMemoryRead = new NativeFunction(
|
||||
Module.getExportByName(CORESYMBOLICATION_PATH, 'mapped_memory_read'),
|
||||
coreSymbolication.getExportByName('mapped_memory_read'),
|
||||
'uint',
|
||||
['pointer', 'uint64', 'uint64', 'pointer'],
|
||||
simpleFuncOptions
|
||||
);
|
||||
const mappedMemoryReadPointer = new NativeFunction(
|
||||
Module.getExportByName(CORESYMBOLICATION_PATH, 'mapped_memory_read_pointer'),
|
||||
coreSymbolication.getExportByName('mapped_memory_read_pointer'),
|
||||
'uint',
|
||||
['pointer', 'uint64', 'pointer'],
|
||||
simpleFuncOptions
|
||||
);
|
||||
const crashReporterSupport = Process.getModuleByName('/System/Library/PrivateFrameworks/CrashReporterSupport.framework/CrashReporterSupport');
|
||||
|
||||
const {
|
||||
AppleErrorReport,
|
||||
@@ -67,7 +69,7 @@ const sessions = new Map();
|
||||
let osaHookState = 'pending';
|
||||
|
||||
function initialize() {
|
||||
const listener = Interceptor.attach(Module.getExportByName(CRASH_REPORTER_SUPPORT_PATH, 'CRCreateDirectoryStructure'), () => {
|
||||
const listener = Interceptor.attach(crashReporterSupport.getExportByName('CRCreateDirectoryStructure'), () => {
|
||||
applyInstrumentation();
|
||||
listener.detach();
|
||||
});
|
||||
@@ -144,7 +146,7 @@ function applyInstrumentation() {
|
||||
},
|
||||
});
|
||||
|
||||
Interceptor.attach(Module.getExportByName(CORESYMBOLICATION_PATH, 'task_is_64bit'), {
|
||||
Interceptor.attach(coreSymbolication.getExportByName('task_is_64bit'), {
|
||||
onEnter(args) {
|
||||
this.pid = pidForTask(args[0].toUInt32());
|
||||
},
|
||||
@@ -216,7 +218,7 @@ function applyInstrumentation() {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Interceptor.attach(Module.getExportByName(LIBSYSTEM_KERNEL_PATH, 'rename'), {
|
||||
Interceptor.attach(libsystemKernel.getExportByName('rename'), {
|
||||
onEnter(args) {
|
||||
const newPath = args[1].readUtf8String();
|
||||
const session = getSession(this.threadId, 'rename');
|
||||
@@ -225,7 +227,7 @@ function applyInstrumentation() {
|
||||
},
|
||||
});
|
||||
|
||||
Interceptor.attach(Module.getExportByName(LIBSYSTEM_KERNEL_PATH, 'open_dprotected_np'), {
|
||||
Interceptor.attach(libsystemKernel.getExportByName('open_dprotected_np'), {
|
||||
onEnter(args) {
|
||||
const path = args[0].readUtf8String();
|
||||
this.isCrashLog = /\.ips$/.test(path);
|
||||
@@ -237,7 +239,7 @@ function applyInstrumentation() {
|
||||
},
|
||||
});
|
||||
|
||||
Interceptor.attach(Module.getExportByName(LIBSYSTEM_KERNEL_PATH, 'write'), {
|
||||
Interceptor.attach(libsystemKernel.getExportByName('write'), {
|
||||
onEnter(args) {
|
||||
const fd = args[0].toInt32();
|
||||
this.buf = args[1];
|
||||
@@ -266,7 +268,7 @@ function applyInstrumentation() {
|
||||
});
|
||||
}
|
||||
|
||||
Interceptor.attach(Module.getExportByName(CRASH_REPORTER_SUPPORT_PATH, 'OSAPreferencesGetBoolValue'), {
|
||||
Interceptor.attach(crashReporterSupport.getExportByName('OSAPreferencesGetBoolValue'), {
|
||||
onEnter(args) {
|
||||
this.name = new ObjC.Object(args[0]).toString();
|
||||
this.domain = new ObjC.Object(args[1]).toString();
|
||||
@@ -0,0 +1,18 @@
|
||||
reportcrash_js = custom_target('reportcrash.js',
|
||||
input: [
|
||||
'package.json',
|
||||
'package-lock.json',
|
||||
'index.js',
|
||||
],
|
||||
output: [
|
||||
'reportcrash.js',
|
||||
],
|
||||
command: [
|
||||
python,
|
||||
compile_js_agent,
|
||||
'@OUTPUT@',
|
||||
'@PRIVATE_DIR@',
|
||||
npm,
|
||||
'@INPUT@',
|
||||
],
|
||||
)
|
||||
+553
@@ -0,0 +1,553 @@
|
||||
{
|
||||
"name": "frida-reportcrash-agent",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "frida-reportcrash-agent",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"frida-objc-bridge": "^8.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/frida-gum": "^19.0.0",
|
||||
"frida-compile": "^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/assert": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/assert/-/assert-3.0.2.tgz",
|
||||
"integrity": "sha512-JXJq5SbXGrM5EkjrZKfRmB29zOoEOix02NC6A5TSJ+C1GE/X051EinJJsuOO2pEOx7KZwpvAHvS0WXW0+levKg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/base64-js": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@frida/base64-js/-/base64-js-2.0.3.tgz",
|
||||
"integrity": "sha512-2w0F+1TynOTCZ/v7du9LdHPWwq0lJhazjo2fF9upMyQmA1zHetT14fLuQ1v/6T0qPgyeEGkiSrybstU8EsgeUA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/buffer": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@frida/buffer/-/buffer-7.0.4.tgz",
|
||||
"integrity": "sha512-RxQ1lZRRiCJj7nhcCiD8xeJx0NsLpGGnjqsmTg7jShGmbnVFMN5W7+J+3gqdPSQhc/IxNBIWc6zRXVp4+qnYHg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.5.1",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/crosspath": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/crosspath/-/crosspath-3.0.0.tgz",
|
||||
"integrity": "sha512-bNdO1spIPD2P40XtK89N49oZpJhstdlnkJZcD4yJ17jrdkm9Ctu0sd9MIEX6Z8Tm8ydhVJBAOMEKl9/R27onAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "^17.0.36"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/crypto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@frida/crypto/-/crypto-1.0.1.tgz",
|
||||
"integrity": "sha512-WXTkVjESvX8TIVXIynJJv9BKSIdQP0Iis04StIXknkDi1ULdMlrypA9p5C4KW1H6GCkNsVnKbybpzsulYCTvag==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/diagnostics_channel": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/diagnostics_channel/-/diagnostics_channel-1.0.0.tgz",
|
||||
"integrity": "sha512-mYX1jp/5Bpk24tHArJNx65iCk7qSuV8YJkdU0gFNVtJUXxfV8BG5WuPa4mL+ynxsbWWpsg/cwKZbLAepYKTdQQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/events": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@frida/events/-/events-4.0.4.tgz",
|
||||
"integrity": "sha512-qJVQ6VWHf9sjUKuiJzoCAC00frbpcwxeYfvQ+PP9LU/d70j+QvjWgYe98Qa3ekLaBU6r/AvWm8ThKCDUCLWrQQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/http": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/http/-/http-4.0.2.tgz",
|
||||
"integrity": "sha512-cvkc7ex7GmVXVOWqtjXKBWUUbYEBgpNRKZbEEoMeI8KiIs8zejKwg+N7rx7296Ao+EP3+xcUr4wBVr3xLaUVfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"http-parser-js": "^0.5.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/http-parser-js": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/http-parser-js/-/http-parser-js-1.0.0.tgz",
|
||||
"integrity": "sha512-2nMrNXt/OeTlWbqnE8AH4Sfz4I2+BGoN206dzKEyC/g2svtn83Xu+zuv/V3TkwrA27s26Mcy84ZwsXeNlqNxUQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/https": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/https/-/https-1.0.0.tgz",
|
||||
"integrity": "sha512-OiqQ6qsALcWOktRLq07oJ0i6sH8eX6MXb/MdZS1qVKDRf6wchH4Pjn6fiLB+pt/OlYbggk+DOfpHwSdjTwuHMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/ieee754": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/ieee754/-/ieee754-2.0.2.tgz",
|
||||
"integrity": "sha512-wlcUebnne4ENN7GDr5pTH598ZDLMVOsh0FjenxeVOe6u7ewZkz9gGRnLnZKJAm9kl5G6XhdxhI0cSXVQK/rQUw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@frida/net": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/net/-/net-4.0.2.tgz",
|
||||
"integrity": "sha512-qQRe7hQ+ZfCcG/SE3P1TRqQ9bmuK/T7wPCYaT4z56rBPWAxsaQbQHpX4fR6OrFaSDr7X0xJLsTbdIp9hGhhLZg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/os": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/os/-/os-1.0.2.tgz",
|
||||
"integrity": "sha512-3ISAiGNiyIya3QN2EHBCz1wqP0enTdSxP99wUeroeh8+AQRmgoOr/5TRnrVry8pe378anay3fmV/tdUMMSkehQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/path": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@frida/path/-/path-2.0.3.tgz",
|
||||
"integrity": "sha512-2RQy36QatoC846fzBhBhV8sXMsSOBGoYvwTHeaE1zUdz7F4RNScP4QEekTTooBYWYX/XjiF36KQpYAzc9OYFtg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/process": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@frida/process/-/process-1.2.1.tgz",
|
||||
"integrity": "sha512-nvCu22DstFW2ttGFtOKekHM7vnjbZm+XgtvavOt427GNT6uV7k0JYK9tnMbcLMRWv57DG6udAmuJlWs8Paq1ag==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/punycode": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/punycode/-/punycode-3.0.0.tgz",
|
||||
"integrity": "sha512-XVSDY2KamDs1D5/fTVgHcOSNxdU4kTboxzqJMBbTjcQC7XScIT9c0EfbwKCq7Kci6gWQdsHSCr7lU+9Oc4KAdg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/querystring": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/querystring/-/querystring-1.0.0.tgz",
|
||||
"integrity": "sha512-15m1fOZPmoO/vWlgPJrG/J9/BJDz6a2/JpVGpS8ynNzo+fBhTznaStX5nHxUs24mVTqh/OqLo0EiYJM5WWHXxg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/readable-stream": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@frida/readable-stream/-/readable-stream-4.1.3.tgz",
|
||||
"integrity": "sha512-ntGUFmi+CryRGRJIK13a/VST2Ad19uivbln8Xd92vKPAARq+6vMIASDyZIqyl5BLRccfiyCHdYgrgQ6RI5rUig==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/reserved-words": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/reserved-words/-/reserved-words-1.0.0.tgz",
|
||||
"integrity": "sha512-2yG/XxJlsGlk/mm6eZTb4OAaQEhkTI2qaFfZFtAsrA/XuCpuMWkS4y/guyBlsRu4hAuhK2HPmNM8+OLLK1zM9Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/stream": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/stream/-/stream-1.0.2.tgz",
|
||||
"integrity": "sha512-4OuaC1ztmEKgTq3WeBhsy8Oq+AwW9n9cYnvLklcC9jwD93AEwgbWpecLlxJCVuALvTMdhKPg0nQVfyGYP/i9Bw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@frida/readable-stream": "^4.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/string_decoder": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/string_decoder/-/string_decoder-2.0.0.tgz",
|
||||
"integrity": "sha512-in371tYZMHQiW9HF5MS3JDw6Ao6tyBoq34UWy2rzOswYyMG1rpizh85ofi/yVkxDiaqybEZefxzkVittpPGT6g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/terser": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/terser/-/terser-1.0.0.tgz",
|
||||
"integrity": "sha512-59h9WuNzD1Rx/zwoWqQ/FW/4Y/Q3R91Eng2hEwdHapqiTDvtKbZ08F6CynCR7ZVinrh4tLYsF46AtVPTz1ys9g==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.2",
|
||||
"acorn": "^8.5.0",
|
||||
"commander": "^2.20.0",
|
||||
"source-map-support": "~0.5.20"
|
||||
},
|
||||
"bin": {
|
||||
"terser": "bin/terser"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/terser/node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/timers": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/timers/-/timers-3.0.0.tgz",
|
||||
"integrity": "sha512-3b+0igv10aT8TMxefrTAd06rActqbxJLY2Xkkq9vYcPBffB/yHszl0NYIp/5ko8WC3ecDYPU6bQiY6fjs72zTA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/tty": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/tty/-/tty-1.0.0.tgz",
|
||||
"integrity": "sha512-p/kjLnKYxEAB1MdYP8+5rKv9CsHzyA+0jg9BcGETzjQVKHHcroHDULRxDYUh+DC7qs6cpX8QdDQh9E+a6ydgsQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/url": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@frida/url/-/url-1.0.2.tgz",
|
||||
"integrity": "sha512-ZKunbKJHMr8w2Eb/5K1avy0MzK1B998S17wYXNv3RmzBGxMm8S5T0F3qEpRxkU7/72P8m4izyQU87fWl+FjQsQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@frida/punycode": "^3.0.0",
|
||||
"@frida/querystring": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@frida/util": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@frida/util/-/util-1.0.3.tgz",
|
||||
"integrity": "sha512-htcG3uDiRXv89ERVNNYhfase39kJ2X75ZARfrYcYEtJLFEsSk0nemM1YnEIR4CjrHvdvkWHrwgKkS+acOyoNEg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@frida/vm": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@frida/vm/-/vm-2.0.0.tgz",
|
||||
"integrity": "sha512-7fsjLWscZT5odNIBtg6qbLNI+vAk1xmii6H5W2kaYkMYt0vRohQEcDSUWacA+eaWlu5SvMjZI82Yibj/3G9pJw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.8",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
||||
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/set-array": "^1.2.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
"@jridgewell/trace-mapping": "^0.3.24"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/resolve-uri": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/set-array": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/source-map": {
|
||||
"version": "0.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
||||
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.25",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "17.0.45",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
|
||||
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
|
||||
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/frida-compile": {
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-17.0.0.tgz",
|
||||
"integrity": "sha512-ixJRj14qLH/Z0ckFWd5fKeDMm0W2+2WDpSGnLRgpn0nuCQAbDHRCqVCWtPnV8uzPJmA6XOX0pujsMpYe9q9RRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@frida/assert": "^3.0.1",
|
||||
"@frida/base64-js": "^2.0.3",
|
||||
"@frida/buffer": "^7.0.4",
|
||||
"@frida/crosspath": "^3.0.0",
|
||||
"@frida/crypto": "^1.0.1",
|
||||
"@frida/diagnostics_channel": "^1.0.0",
|
||||
"@frida/events": "^4.0.4",
|
||||
"@frida/http": "^4.0.2",
|
||||
"@frida/http-parser-js": "^1.0.0",
|
||||
"@frida/https": "^1.0.0",
|
||||
"@frida/ieee754": "^2.0.2",
|
||||
"@frida/net": "^4.0.1",
|
||||
"@frida/os": "^1.0.0",
|
||||
"@frida/path": "^2.0.3",
|
||||
"@frida/process": "^1.2.1",
|
||||
"@frida/punycode": "^3.0.0",
|
||||
"@frida/querystring": "^1.0.0",
|
||||
"@frida/readable-stream": "^4.1.3",
|
||||
"@frida/reserved-words": "^1.0.0",
|
||||
"@frida/stream": "^1.0.2",
|
||||
"@frida/string_decoder": "^2.0.0",
|
||||
"@frida/terser": "^1.0.0",
|
||||
"@frida/timers": "^3.0.0",
|
||||
"@frida/tty": "^1.0.0",
|
||||
"@frida/url": "^1.0.2",
|
||||
"@frida/util": "^1.0.3",
|
||||
"@frida/vm": "^2.0.0",
|
||||
"commander": "^11.1.0",
|
||||
"frida-fs": "^6.0.0",
|
||||
"typed-emitter": "^2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"frida-compile": "dist/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/frida-fs": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-6.0.0.tgz",
|
||||
"integrity": "sha512-I0fnKupZh7fU2ixwCIjJnEqNdhfm/SC1ZYBMy58EmeqOWSbjw1Dpy99mJ7BJdbk2KNXJeaBZGxDYLtn0J9S+UA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/frida-objc-bridge": {
|
||||
"version": "8.0.4",
|
||||
"resolved": "https://registry.npmjs.org/frida-objc-bridge/-/frida-objc-bridge-8.0.4.tgz",
|
||||
"integrity": "sha512-AUzwq/+TFtblQLTI97UPX22pBcvyG2oUde9380DXbcJ0zXts4n9JDVONHUr03aBowa0Le+bdBoVdCs7jyyjvlg==",
|
||||
"license": "LGPL-2.0 WITH WxWindows-exception-3.1"
|
||||
},
|
||||
"node_modules/http-parser-js": {
|
||||
"version": "0.5.10",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz",
|
||||
"integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "7.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
|
||||
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"dev": true,
|
||||
"license": "0BSD",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/typed-emitter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"rxjs": "*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "frida-reportcrash-agent",
|
||||
"version": "1.0.0",
|
||||
"description": "Agent used by Frida's Darwin backend on iOS/iPadOS/tvOS",
|
||||
"scripts": {
|
||||
"prepare": "npm run build",
|
||||
"build": "frida-compile index.js -o reportcrash.js -S -c"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/frida-gum": "^19.0.0",
|
||||
"frida-compile": "^17.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"frida-objc-bridge": "^8.0.4"
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ const POSIX_SPAWN_START_SUSPENDED = 0x0080;
|
||||
|
||||
applyJailbreakQuirks();
|
||||
|
||||
Interceptor.attach(Module.getExportByName('/usr/lib/system/libsystem_kernel.dylib', '__posix_spawn'), {
|
||||
Interceptor.attach(Process.getModuleByName('/usr/lib/system/libsystem_kernel.dylib').getExportByName('__posix_spawn'), {
|
||||
onEnter(args) {
|
||||
const attrs = args[2].add(Process.pointerSize).readPointer();
|
||||
|
||||
@@ -42,7 +42,7 @@ function sabotageJbdCall(jbdCallImpl) {
|
||||
}
|
||||
|
||||
function instrumentSubstrateBootstrapper(bootstrapper) {
|
||||
Interceptor.attach(Module.getExportByName('/usr/lib/system/libdyld.dylib', 'dlopen'), {
|
||||
Interceptor.attach(Process.getModuleByName('/usr/lib/system/libdyld.dylib').getExportByName('dlopen'), {
|
||||
onEnter(args) {
|
||||
this.path = args[0].readUtf8String();
|
||||
},
|
||||
@@ -66,7 +66,7 @@ function instrumentSubstrateExec(exec) {
|
||||
}
|
||||
|
||||
function findJbdCallImpl() {
|
||||
const impl = Module.findExportByName(null, 'jbd_call');
|
||||
const impl = Module.findGlobalExportByName('jbd_call');
|
||||
if (impl !== null)
|
||||
return impl;
|
||||
|
||||
|
||||
@@ -1,98 +1,24 @@
|
||||
namespace Frida {
|
||||
public class DarwinHostSessionBackend : Object, HostSessionBackend {
|
||||
private DarwinHostSessionProvider local_provider;
|
||||
|
||||
public async void start (Cancellable? cancellable) throws IOError {
|
||||
assert (local_provider == null);
|
||||
local_provider = new DarwinHostSessionProvider ();
|
||||
provider_available (local_provider);
|
||||
}
|
||||
|
||||
public async void stop (Cancellable? cancellable) throws IOError {
|
||||
assert (local_provider != null);
|
||||
provider_unavailable (local_provider);
|
||||
yield local_provider.close (cancellable);
|
||||
local_provider = null;
|
||||
public sealed class DarwinHostSessionBackend : LocalHostSessionBackend {
|
||||
protected override LocalHostSessionProvider make_provider () {
|
||||
return new DarwinHostSessionProvider ();
|
||||
}
|
||||
}
|
||||
|
||||
public class DarwinHostSessionProvider : Object, HostSessionProvider {
|
||||
public string id {
|
||||
get { return "local"; }
|
||||
}
|
||||
|
||||
public string name {
|
||||
get { return "Local System"; }
|
||||
}
|
||||
|
||||
public Variant? icon {
|
||||
get { return _icon; }
|
||||
}
|
||||
private Variant? _icon;
|
||||
|
||||
public HostSessionProviderKind kind {
|
||||
get { return HostSessionProviderKind.LOCAL; }
|
||||
}
|
||||
|
||||
private DarwinHostSession host_session;
|
||||
|
||||
construct {
|
||||
_icon = _try_extract_icon ();
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
if (host_session == null)
|
||||
return;
|
||||
host_session.agent_session_detached.disconnect (on_agent_session_detached);
|
||||
yield host_session.close (cancellable);
|
||||
host_session = null;
|
||||
}
|
||||
|
||||
public async HostSession create (HostSessionOptions? options, Cancellable? cancellable) throws Error, IOError {
|
||||
if (host_session != null)
|
||||
throw new Error.INVALID_OPERATION ("Already created");
|
||||
|
||||
public sealed class DarwinHostSessionProvider : LocalHostSessionProvider {
|
||||
protected override LocalHostSession make_host_session (HostSessionOptions? options) throws Error {
|
||||
var tempdir = new TemporaryDirectory ();
|
||||
|
||||
host_session = new DarwinHostSession (new DarwinHelperProcess (tempdir), tempdir);
|
||||
host_session.agent_session_detached.connect (on_agent_session_detached);
|
||||
|
||||
return host_session;
|
||||
return new DarwinHostSession (new DarwinHelperProcess (tempdir), tempdir);
|
||||
}
|
||||
|
||||
public async void destroy (HostSession session, Cancellable? cancellable) throws Error, IOError {
|
||||
if (session != host_session)
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid host session");
|
||||
|
||||
host_session.agent_session_detached.disconnect (on_agent_session_detached);
|
||||
|
||||
yield host_session.close (cancellable);
|
||||
host_session = null;
|
||||
}
|
||||
|
||||
public async AgentSession link_agent_session (HostSession host_session, AgentSessionId id, AgentMessageSink sink,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
if (host_session != this.host_session)
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid host session");
|
||||
|
||||
return yield this.host_session.link_agent_session (id, sink, cancellable);
|
||||
}
|
||||
|
||||
public void unlink_agent_session (HostSession host_session, AgentSessionId id) {
|
||||
if (host_session != this.host_session)
|
||||
return;
|
||||
|
||||
this.host_session.unlink_agent_session (id);
|
||||
}
|
||||
|
||||
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
|
||||
agent_session_detached (id, reason, crash);
|
||||
protected override Variant? load_icon () {
|
||||
return _try_extract_icon ();
|
||||
}
|
||||
|
||||
public extern static Variant? _try_extract_icon ();
|
||||
}
|
||||
|
||||
public class DarwinHostSession : BaseDBusHostSession {
|
||||
public sealed class DarwinHostSession : LocalHostSession {
|
||||
public DarwinHelper helper {
|
||||
get;
|
||||
construct;
|
||||
@@ -410,7 +336,7 @@ namespace Frida {
|
||||
}
|
||||
|
||||
#if IOS || TVOS
|
||||
private class FruitController : Object, MappedAgentContainer {
|
||||
private sealed class FruitController : Object, MappedAgentContainer {
|
||||
public signal void spawn_added (HostSpawnInfo info);
|
||||
public signal void spawn_removed (HostSpawnInfo info);
|
||||
public signal void process_crashed (CrashInfo crash);
|
||||
@@ -815,7 +741,7 @@ namespace Frida {
|
||||
crash_deliveries.unset (delivery.pid);
|
||||
}
|
||||
|
||||
private class CrashDelivery : Object {
|
||||
private sealed class CrashDelivery : Object {
|
||||
public signal void expired ();
|
||||
|
||||
public uint pid {
|
||||
@@ -882,7 +808,7 @@ namespace Frida {
|
||||
|
||||
private delegate void FoundMappedAgentFunc (MappedAgent agent);
|
||||
|
||||
private class MappedAgent {
|
||||
private sealed class MappedAgent {
|
||||
public uint id {
|
||||
get;
|
||||
private set;
|
||||
@@ -905,7 +831,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private class LaunchdAgent : InternalAgent {
|
||||
private sealed class LaunchdAgent : InternalAgent {
|
||||
public signal void app_launch_started (string identifier, uint pid);
|
||||
public signal void app_launch_completed (string identifier, uint pid, GLib.Error? error);
|
||||
public signal void spawn_preparation_started (HostSpawnInfo info);
|
||||
@@ -1015,7 +941,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private class XpcProxyAgent : InternalAgent {
|
||||
private sealed class XpcProxyAgent : InternalAgent {
|
||||
public string identifier {
|
||||
get;
|
||||
construct;
|
||||
@@ -1057,7 +983,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private class ReportCrashAgent : InternalAgent {
|
||||
private sealed class ReportCrashAgent : InternalAgent {
|
||||
public signal void crash_detected (uint pid);
|
||||
public signal void crash_received (CrashInfo crash);
|
||||
|
||||
@@ -1289,7 +1215,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private class OSAnalyticsAgent : InternalAgent {
|
||||
private sealed class OSAnalyticsAgent : InternalAgent {
|
||||
public uint pid {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -2027,7 +2027,9 @@ _frida_darwin_helper_backend_prepare_spawn_instance_for_injection (FridaDarwinHe
|
||||
}
|
||||
}
|
||||
|
||||
modern_entry_address = gum_darwin_module_resolve_symbol_address (dyld, "__ZN5dyld44APIs19_libdyld_initializeEPKNS_16LibSystemHelpersE");
|
||||
modern_entry_address = gum_darwin_module_resolve_symbol_address (dyld, "__ZN5dyld44APIs19_libdyld_initializeEv");
|
||||
if (modern_entry_address == 0)
|
||||
modern_entry_address = gum_darwin_module_resolve_symbol_address (dyld, "__ZN5dyld44APIs19_libdyld_initializeEPKNS_16LibSystemHelpersE");
|
||||
instance->dyld_flavor = (modern_entry_address != 0) ? FRIDA_DYLD_V4_PLUS : FRIDA_DYLD_V3_MINUS;
|
||||
if (instance->dyld_flavor == FRIDA_DYLD_V4_PLUS)
|
||||
{
|
||||
@@ -2113,7 +2115,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");
|
||||
"__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN6mach_o6HeaderEPK15DyldSharedCachePv");
|
||||
if (restart_with_dyld_in_cache == 0)
|
||||
{
|
||||
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,
|
||||
|
||||
@@ -686,7 +686,7 @@ namespace Frida {
|
||||
protected extern void _close_inject_instance (void * instance);
|
||||
}
|
||||
|
||||
public class DTraceAgent : Object {
|
||||
public sealed class DTraceAgent : Object {
|
||||
public signal void spawn_added (HostSpawnInfo info);
|
||||
public signal void spawn_removed (HostSpawnInfo info);
|
||||
|
||||
@@ -845,7 +845,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private class PendingLaunch : Object {
|
||||
private sealed class PendingLaunch : Object {
|
||||
public signal void completed ();
|
||||
|
||||
public string identifier {
|
||||
@@ -889,7 +889,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class StdioPipes : Object {
|
||||
public sealed class StdioPipes : Object {
|
||||
public int input {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class DarwinHelperBackend : Object, DarwinHelper {
|
||||
public sealed class DarwinHelperBackend : Object, DarwinHelper {
|
||||
public signal void idle ();
|
||||
public signal void child_dead (uint pid);
|
||||
public signal void spawn_instance_ready (uint pid);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class DarwinHelperProcess : Object, DarwinHelper {
|
||||
public sealed class DarwinHelperProcess : Object, DarwinHelper {
|
||||
public uint pid {
|
||||
get {
|
||||
return (uint) process_pid;
|
||||
@@ -473,7 +473,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private class ResourceStore {
|
||||
private sealed class ResourceStore {
|
||||
public HelperFile helper {
|
||||
get;
|
||||
private set;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Frida {
|
||||
public extern void _start_run_loop ();
|
||||
public extern void _stop_run_loop ();
|
||||
|
||||
public class DarwinHelperService : Object, DarwinRemoteHelper {
|
||||
public sealed class DarwinHelperService : Object, DarwinRemoteHelper {
|
||||
public string parent_address {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class Fruitjector : Object, Injector {
|
||||
public sealed class Fruitjector : Object, Injector {
|
||||
public signal void injected (uint id, uint pid, bool has_mapped_module, DarwinModuleDetails mapped_module);
|
||||
|
||||
public DarwinHelper helper {
|
||||
@@ -117,7 +117,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class AgentResource : Object {
|
||||
public sealed class AgentResource : Object {
|
||||
public string name {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Frida {
|
||||
public abstract void forget (uint pid);
|
||||
}
|
||||
|
||||
public class NullPolicySoftener : Object, PolicySoftener {
|
||||
public sealed class NullPolicySoftener : Object, PolicySoftener {
|
||||
public void soften (uint pid) throws Error {
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class InternalIOSTVOSPolicySoftener : IOSTVOSPolicySoftener {
|
||||
public sealed class InternalIOSTVOSPolicySoftener : IOSTVOSPolicySoftener {
|
||||
private static bool enabled = false;
|
||||
|
||||
public static void enable () {
|
||||
@@ -184,7 +184,7 @@ namespace Frida {
|
||||
private extern static void _soften (uint pid) throws Error;
|
||||
}
|
||||
|
||||
public class ElectraPolicySoftener : IOSTVOSPolicySoftener {
|
||||
public sealed class ElectraPolicySoftener : IOSTVOSPolicySoftener {
|
||||
private const string LIBJAILBREAK_PATH = "/usr/lib/libjailbreak.dylib";
|
||||
|
||||
private Module libjailbreak;
|
||||
@@ -237,7 +237,7 @@ namespace Frida {
|
||||
private extern static int _internal_jb_entitle_now (void * jbd_call, uint connection, uint pid);
|
||||
}
|
||||
|
||||
public class Unc0verPolicySoftener : IOSTVOSPolicySoftener {
|
||||
public sealed class Unc0verPolicySoftener : IOSTVOSPolicySoftener {
|
||||
private const string SUBSTITUTED_PATH = "/usr/libexec/substituted";
|
||||
|
||||
private uint connection;
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace Frida.AXML {
|
||||
}
|
||||
}
|
||||
|
||||
public class ElementTree : Object {
|
||||
public sealed class ElementTree : Object {
|
||||
public string name {
|
||||
get;
|
||||
set;
|
||||
@@ -135,7 +135,7 @@ namespace Frida.AXML {
|
||||
}
|
||||
}
|
||||
|
||||
public class ResourceValue : Object {
|
||||
public sealed class ResourceValue : Object {
|
||||
private uint16 size;
|
||||
private uint8 unused;
|
||||
private ResourceType type;
|
||||
@@ -173,7 +173,7 @@ namespace Frida.AXML {
|
||||
}
|
||||
}
|
||||
|
||||
public class Attribute : Object {
|
||||
public sealed class Attribute : Object {
|
||||
private uint32 namespace;
|
||||
private uint32 name;
|
||||
private uint32 unused;
|
||||
@@ -238,7 +238,7 @@ namespace Frida.AXML {
|
||||
}
|
||||
}
|
||||
|
||||
private class ResourceMap {
|
||||
private sealed class ResourceMap {
|
||||
private Gee.ArrayList<uint32> resources = new Gee.ArrayList<uint32> ();
|
||||
|
||||
public ResourceMap.with_stream (DataInputStream input, uint32 size) throws IOError {
|
||||
@@ -247,7 +247,7 @@ namespace Frida.AXML {
|
||||
}
|
||||
}
|
||||
|
||||
private class StringPool {
|
||||
private sealed class StringPool {
|
||||
private uint32 flags;
|
||||
private Gee.ArrayList<string> strings = new Gee.ArrayList<string> ();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaDroidy", gir_version = "1.0")]
|
||||
namespace Frida.Droidy {
|
||||
public class DeviceTracker : Object {
|
||||
public sealed class DeviceTracker : Object {
|
||||
public signal void device_attached (DeviceDetails details);
|
||||
public signal void device_detached (string serial);
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace Frida.Droidy {
|
||||
}
|
||||
}
|
||||
|
||||
public class DeviceDetails : Object {
|
||||
public sealed class DeviceDetails : Object {
|
||||
public string serial {
|
||||
get;
|
||||
construct;
|
||||
@@ -205,7 +205,7 @@ namespace Frida.Droidy {
|
||||
}
|
||||
}
|
||||
|
||||
public class ShellSession : Object {
|
||||
public sealed class ShellSession : Object {
|
||||
public signal void output (StdioPipe pipe, Bytes bytes);
|
||||
public signal void closed ();
|
||||
|
||||
@@ -594,7 +594,7 @@ namespace Frida.Droidy {
|
||||
STDERR
|
||||
}
|
||||
|
||||
public class ShellCommandResult : Object {
|
||||
public sealed class ShellCommandResult : Object {
|
||||
public uint8 status {
|
||||
get;
|
||||
construct;
|
||||
@@ -686,7 +686,7 @@ namespace Frida.Droidy {
|
||||
}
|
||||
}
|
||||
|
||||
public class FileMetadata : Object {
|
||||
public sealed class FileMetadata : Object {
|
||||
public uint32 mode {
|
||||
get;
|
||||
set;
|
||||
@@ -700,7 +700,7 @@ namespace Frida.Droidy {
|
||||
}
|
||||
}
|
||||
|
||||
public class JDWPTracker : Object {
|
||||
public sealed class JDWPTracker : Object {
|
||||
public signal void debugger_attached (uint pid);
|
||||
public signal void debugger_detached (uint pid);
|
||||
|
||||
@@ -768,7 +768,7 @@ namespace Frida.Droidy {
|
||||
}
|
||||
}
|
||||
|
||||
public class Client : Object {
|
||||
public sealed class Client : Object {
|
||||
public signal void closed ();
|
||||
public signal void message (string payload);
|
||||
|
||||
@@ -1154,7 +1154,7 @@ namespace Frida.Droidy {
|
||||
}
|
||||
}
|
||||
|
||||
public class SyncSession : Object {
|
||||
public sealed class SyncSession : Object {
|
||||
public Client client {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class DroidyHostSessionBackend : Object, HostSessionBackend {
|
||||
public sealed class DroidyHostSessionBackend : Object, HostSessionBackend {
|
||||
private Droidy.DeviceTracker tracker;
|
||||
|
||||
private Gee.HashMap<string, DroidyHostSessionProvider> providers = new Gee.HashMap<string, DroidyHostSessionProvider> ();
|
||||
@@ -86,7 +86,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class DroidyHostSessionProvider : Object, HostSessionProvider, HostChannelProvider {
|
||||
public sealed class DroidyHostSessionProvider : Object, HostSessionProvider, HostChannelProvider {
|
||||
public string id {
|
||||
get { return device_details.serial; }
|
||||
}
|
||||
@@ -158,6 +158,36 @@ namespace Frida {
|
||||
return yield this.host_session.link_agent_session (id, sink, cancellable);
|
||||
}
|
||||
|
||||
public void unlink_agent_session (HostSession host_session, AgentSessionId id) {
|
||||
if (host_session != this.host_session)
|
||||
return;
|
||||
|
||||
this.host_session.unlink_agent_session (id);
|
||||
}
|
||||
|
||||
public async IOStream link_channel (HostSession host_session, ChannelId id, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
if (host_session != this.host_session)
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid host session");
|
||||
|
||||
return this.host_session.link_channel (id);
|
||||
}
|
||||
|
||||
public void unlink_channel (HostSession host_session, ChannelId id) {
|
||||
if (host_session != this.host_session)
|
||||
return;
|
||||
|
||||
this.host_session.unlink_channel (id);
|
||||
}
|
||||
|
||||
public async ServiceSession link_service_session (HostSession host_session, ServiceSessionId id, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
|
||||
}
|
||||
|
||||
public void unlink_service_session (HostSession host_session, ServiceSessionId id) {
|
||||
}
|
||||
|
||||
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
|
||||
agent_session_detached (id, reason, crash);
|
||||
}
|
||||
@@ -182,7 +212,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class DroidyHostSession : Object, HostSession {
|
||||
public sealed class DroidyHostSession : Object, HostSession {
|
||||
public Droidy.DeviceDetails device_details {
|
||||
get;
|
||||
construct;
|
||||
@@ -211,6 +241,8 @@ namespace Frida {
|
||||
private Gee.HashMap<AgentSessionId?, AgentSessionEntry> agent_sessions =
|
||||
new Gee.HashMap<AgentSessionId?, AgentSessionEntry> (AgentSessionId.hash, AgentSessionId.equal);
|
||||
|
||||
private ChannelRegistry channel_registry = new ChannelRegistry ();
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
private const double MIN_SERVER_CHECK_INTERVAL = 5.0;
|
||||
@@ -223,6 +255,10 @@ namespace Frida {
|
||||
);
|
||||
}
|
||||
|
||||
construct {
|
||||
channel_registry.channel_closed.connect (on_channel_closed);
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
if (remote_server_request != null) {
|
||||
var server = yield try_get_remote_server (cancellable);
|
||||
@@ -832,6 +868,15 @@ namespace Frida {
|
||||
return session;
|
||||
}
|
||||
|
||||
public void unlink_agent_session (AgentSessionId id) {
|
||||
AgentSessionEntry? entry = agent_sessions[id];
|
||||
if (entry == null || entry.sink_registration_id == 0)
|
||||
return;
|
||||
|
||||
entry.connection.unregister_object (entry.sink_registration_id);
|
||||
entry.sink_registration_id = 0;
|
||||
}
|
||||
|
||||
public async InjectorPayloadId inject_library_file (uint pid, string path, string entrypoint, string data,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
var server = yield get_remote_server (cancellable);
|
||||
@@ -852,6 +897,31 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
var stream = yield channel_provider.open_channel (address, cancellable);
|
||||
|
||||
var id = ChannelId.generate ();
|
||||
channel_registry.register (id, stream);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public IOStream link_channel (ChannelId id) throws Error {
|
||||
return channel_registry.link (id);
|
||||
}
|
||||
|
||||
public void unlink_channel (ChannelId id) {
|
||||
channel_registry.unlink (id);
|
||||
}
|
||||
|
||||
private void on_channel_closed (ChannelId id) {
|
||||
channel_closed (id);
|
||||
}
|
||||
|
||||
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
|
||||
}
|
||||
|
||||
private void on_gadget_entry_detached (GadgetEntry entry, SessionDetachReason reason) {
|
||||
AgentSessionId id = entry.local_session_id;
|
||||
var no_crash = CrashInfo.empty ();
|
||||
@@ -1217,7 +1287,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class HelperClient : Object, AsyncInitable {
|
||||
public sealed class HelperClient : Object, AsyncInitable {
|
||||
public signal void closed ();
|
||||
|
||||
public string device_serial {
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Frida.Droidy.Injector {
|
||||
return yield session.run (cancellable);
|
||||
}
|
||||
|
||||
public class GadgetDetails : Object {
|
||||
public sealed class GadgetDetails : Object {
|
||||
public uint pid {
|
||||
get;
|
||||
construct;
|
||||
@@ -31,7 +31,7 @@ namespace Frida.Droidy.Injector {
|
||||
}
|
||||
}
|
||||
|
||||
private class Session : Object {
|
||||
private sealed class Session : Object {
|
||||
public InputStream gadget {
|
||||
get;
|
||||
construct;
|
||||
|
||||
+57
-57
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaJDWP", gir_version = "1.0")]
|
||||
namespace Frida.JDWP {
|
||||
public class Client : GLib.Object, AsyncInitable {
|
||||
public sealed class Client : GLib.Object, AsyncInitable {
|
||||
public signal void closed ();
|
||||
public signal void events_received (Events events);
|
||||
|
||||
@@ -593,7 +593,7 @@ namespace Frida.JDWP {
|
||||
public abstract string to_string ();
|
||||
}
|
||||
|
||||
public class Byte : Value {
|
||||
public sealed class Byte : Value {
|
||||
public uint8 val {
|
||||
get;
|
||||
construct;
|
||||
@@ -608,7 +608,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class Char : Value {
|
||||
public sealed class Char : Value {
|
||||
public string val {
|
||||
get;
|
||||
construct;
|
||||
@@ -623,7 +623,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class Double : Value {
|
||||
public sealed class Double : Value {
|
||||
public double val {
|
||||
get;
|
||||
construct;
|
||||
@@ -638,7 +638,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class Float : Value {
|
||||
public sealed class Float : Value {
|
||||
public float val {
|
||||
get;
|
||||
construct;
|
||||
@@ -653,7 +653,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class Int : Value {
|
||||
public sealed class Int : Value {
|
||||
public int32 val {
|
||||
get;
|
||||
construct;
|
||||
@@ -668,7 +668,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class Long : Value {
|
||||
public sealed class Long : Value {
|
||||
public int64 val {
|
||||
get;
|
||||
construct;
|
||||
@@ -698,7 +698,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class Short : Value {
|
||||
public sealed class Short : Value {
|
||||
public int16 val {
|
||||
get;
|
||||
construct;
|
||||
@@ -713,7 +713,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class Void : Value {
|
||||
public sealed class Void : Value {
|
||||
public Void () {
|
||||
GLib.Object (tag: ValueTag.VOID);
|
||||
}
|
||||
@@ -723,7 +723,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class Boolean : Value {
|
||||
public sealed class Boolean : Value {
|
||||
public bool val {
|
||||
get;
|
||||
construct;
|
||||
@@ -738,43 +738,43 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class Array : Object {
|
||||
public sealed class Array : Object {
|
||||
public Array (ObjectID val) {
|
||||
GLib.Object (tag: ValueTag.ARRAY, val: val);
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassObject : Object {
|
||||
public sealed class ClassObject : Object {
|
||||
public ClassObject (ObjectID val) {
|
||||
GLib.Object (tag: ValueTag.CLASS_OBJECT, val: val);
|
||||
}
|
||||
}
|
||||
|
||||
public class ThreadGroup : Object {
|
||||
public sealed class ThreadGroup : Object {
|
||||
public ThreadGroup (ObjectID val) {
|
||||
GLib.Object (tag: ValueTag.THREAD_GROUP, val: val);
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassLoader : Object {
|
||||
public sealed class ClassLoader : Object {
|
||||
public ClassLoader (ObjectID val) {
|
||||
GLib.Object (tag: ValueTag.CLASS_LOADER, val: val);
|
||||
}
|
||||
}
|
||||
|
||||
public class String : Object {
|
||||
public sealed class String : Object {
|
||||
public String (ObjectID val) {
|
||||
GLib.Object (tag: ValueTag.STRING, val: val);
|
||||
}
|
||||
}
|
||||
|
||||
public class Thread : Object {
|
||||
public sealed class Thread : Object {
|
||||
public Thread (ObjectID val) {
|
||||
GLib.Object (tag: ValueTag.THREAD, val: val);
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassInfo : GLib.Object {
|
||||
public sealed class ClassInfo : GLib.Object {
|
||||
public TaggedReferenceTypeID ref_type {
|
||||
get;
|
||||
construct;
|
||||
@@ -815,7 +815,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class MethodInfo : GLib.Object {
|
||||
public sealed class MethodInfo : GLib.Object {
|
||||
public MethodID id {
|
||||
get;
|
||||
construct;
|
||||
@@ -992,7 +992,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class Location : GLib.Object {
|
||||
public sealed class Location : GLib.Object {
|
||||
public TaggedReferenceTypeID declaring {
|
||||
get;
|
||||
construct;
|
||||
@@ -1071,7 +1071,7 @@ namespace Frida.JDWP {
|
||||
ALL = 2,
|
||||
}
|
||||
|
||||
public class Events : GLib.Object {
|
||||
public sealed class Events : GLib.Object {
|
||||
public SuspendPolicy suspend_policy {
|
||||
get;
|
||||
construct;
|
||||
@@ -1119,7 +1119,7 @@ namespace Frida.JDWP {
|
||||
public abstract string to_string ();
|
||||
}
|
||||
|
||||
public class SingleStepEvent : Event {
|
||||
public sealed class SingleStepEvent : Event {
|
||||
public ThreadID thread {
|
||||
get;
|
||||
construct;
|
||||
@@ -1155,7 +1155,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class BreakpointEvent : Event {
|
||||
public sealed class BreakpointEvent : Event {
|
||||
public ThreadID thread {
|
||||
get;
|
||||
construct;
|
||||
@@ -1191,7 +1191,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class FramePopEvent : Event {
|
||||
public sealed class FramePopEvent : Event {
|
||||
public override string to_string () {
|
||||
return "FramePopEvent()";
|
||||
}
|
||||
@@ -1201,7 +1201,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ExceptionEvent : Event {
|
||||
public sealed class ExceptionEvent : Event {
|
||||
public ThreadID thread {
|
||||
get;
|
||||
construct;
|
||||
@@ -1254,7 +1254,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class UserDefinedEvent : Event {
|
||||
public sealed class UserDefinedEvent : Event {
|
||||
public override string to_string () {
|
||||
return "UserDefinedEvent()";
|
||||
}
|
||||
@@ -1264,7 +1264,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ThreadStartEvent : Event {
|
||||
public sealed class ThreadStartEvent : Event {
|
||||
public ThreadID thread {
|
||||
get;
|
||||
construct;
|
||||
@@ -1292,7 +1292,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ThreadDeathEvent : Event {
|
||||
public sealed class ThreadDeathEvent : Event {
|
||||
public ThreadID thread {
|
||||
get;
|
||||
construct;
|
||||
@@ -1320,7 +1320,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassPrepareEvent : Event {
|
||||
public sealed class ClassPrepareEvent : Event {
|
||||
public ThreadID thread {
|
||||
get;
|
||||
construct;
|
||||
@@ -1373,7 +1373,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassUnloadEvent : Event {
|
||||
public sealed class ClassUnloadEvent : Event {
|
||||
public string signature {
|
||||
get;
|
||||
construct;
|
||||
@@ -1398,7 +1398,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassLoadEvent : Event {
|
||||
public sealed class ClassLoadEvent : Event {
|
||||
public override string to_string () {
|
||||
return "ClassLoadEvent()";
|
||||
}
|
||||
@@ -1435,7 +1435,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class FieldAccessEvent : FieldEvent {
|
||||
public sealed class FieldAccessEvent : FieldEvent {
|
||||
public FieldAccessEvent (EventRequestID request, ThreadID thread, Location location, TaggedReferenceTypeID ref_type,
|
||||
FieldID field, TaggedObjectID object) {
|
||||
GLib.Object (
|
||||
@@ -1471,7 +1471,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class FieldModificationEvent : FieldEvent {
|
||||
public sealed class FieldModificationEvent : FieldEvent {
|
||||
public Value value_to_be {
|
||||
get;
|
||||
construct;
|
||||
@@ -1516,7 +1516,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ExceptionCatchEvent : Event {
|
||||
public sealed class ExceptionCatchEvent : Event {
|
||||
public override string to_string () {
|
||||
return "ExceptionCatchEvent()";
|
||||
}
|
||||
@@ -1538,7 +1538,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class MethodEntryEvent : MethodEvent {
|
||||
public sealed class MethodEntryEvent : MethodEvent {
|
||||
public MethodEntryEvent (EventRequestID request, ThreadID thread, Location location) {
|
||||
GLib.Object (
|
||||
kind: EventKind.METHOD_ENTRY,
|
||||
@@ -1564,7 +1564,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class MethodExitEvent : MethodEvent {
|
||||
public sealed class MethodExitEvent : MethodEvent {
|
||||
public MethodExitEvent (EventRequestID request, ThreadID thread, Location location) {
|
||||
GLib.Object (
|
||||
kind: EventKind.METHOD_EXIT,
|
||||
@@ -1590,7 +1590,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class MethodExitWithReturnValueEvent : MethodEvent {
|
||||
public sealed class MethodExitWithReturnValueEvent : MethodEvent {
|
||||
public Value retval {
|
||||
get;
|
||||
construct;
|
||||
@@ -1641,7 +1641,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class MonitorContendedEnterEvent : MonitorEvent {
|
||||
public sealed class MonitorContendedEnterEvent : MonitorEvent {
|
||||
public MonitorContendedEnterEvent (EventRequestID request, ThreadID thread, TaggedObjectID object, Location location) {
|
||||
GLib.Object (
|
||||
kind: EventKind.MONITOR_CONTENDED_ENTER,
|
||||
@@ -1670,7 +1670,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class MonitorContendedEnteredEvent : MonitorEvent {
|
||||
public sealed class MonitorContendedEnteredEvent : MonitorEvent {
|
||||
public MonitorContendedEnteredEvent (EventRequestID request, ThreadID thread, TaggedObjectID object, Location location) {
|
||||
GLib.Object (
|
||||
kind: EventKind.MONITOR_CONTENDED_ENTERED,
|
||||
@@ -1699,7 +1699,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class MonitorWaitEvent : MonitorEvent {
|
||||
public sealed class MonitorWaitEvent : MonitorEvent {
|
||||
public int64 timeout {
|
||||
get;
|
||||
construct;
|
||||
@@ -1736,7 +1736,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class MonitorWaitedEvent : MonitorEvent {
|
||||
public sealed class MonitorWaitedEvent : MonitorEvent {
|
||||
public bool timed_out {
|
||||
get;
|
||||
construct;
|
||||
@@ -1774,7 +1774,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class VMStartEvent : Event {
|
||||
public sealed class VMStartEvent : Event {
|
||||
public ThreadID thread {
|
||||
get;
|
||||
construct;
|
||||
@@ -1799,7 +1799,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class VMDeathEvent : Event {
|
||||
public sealed class VMDeathEvent : Event {
|
||||
public VMDeathEvent (EventRequestID request) {
|
||||
GLib.Object (kind: EventKind.VM_DEATH, request: request);
|
||||
}
|
||||
@@ -1814,7 +1814,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class VMDisconnectedEvent : Event {
|
||||
public sealed class VMDisconnectedEvent : Event {
|
||||
public override string to_string () {
|
||||
return "VMDisconnectedEvent()";
|
||||
}
|
||||
@@ -1828,7 +1828,7 @@ namespace Frida.JDWP {
|
||||
internal abstract void serialize (PacketBuilder builder);
|
||||
}
|
||||
|
||||
public class CountModifier : EventModifier {
|
||||
public sealed class CountModifier : EventModifier {
|
||||
public int32 count {
|
||||
get;
|
||||
construct;
|
||||
@@ -1845,7 +1845,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ThreadOnlyModifier : EventModifier {
|
||||
public sealed class ThreadOnlyModifier : EventModifier {
|
||||
public ThreadID thread {
|
||||
get;
|
||||
construct;
|
||||
@@ -1862,7 +1862,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassOnlyModifier : EventModifier {
|
||||
public sealed class ClassOnlyModifier : EventModifier {
|
||||
public ReferenceTypeID clazz {
|
||||
get;
|
||||
construct;
|
||||
@@ -1879,7 +1879,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassMatchModifier : EventModifier {
|
||||
public sealed class ClassMatchModifier : EventModifier {
|
||||
public string class_pattern {
|
||||
get;
|
||||
construct;
|
||||
@@ -1896,7 +1896,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassExcludeModifier : EventModifier {
|
||||
public sealed class ClassExcludeModifier : EventModifier {
|
||||
public string class_pattern {
|
||||
get;
|
||||
construct;
|
||||
@@ -1913,7 +1913,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class LocationOnlyModifier : EventModifier {
|
||||
public sealed class LocationOnlyModifier : EventModifier {
|
||||
public Location location {
|
||||
get;
|
||||
construct;
|
||||
@@ -1929,7 +1929,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class ExceptionOnlyModifier : EventModifier {
|
||||
public sealed class ExceptionOnlyModifier : EventModifier {
|
||||
public ReferenceTypeID exception_or_null {
|
||||
get;
|
||||
construct;
|
||||
@@ -1962,7 +1962,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class FieldOnlyModifier : EventModifier {
|
||||
public sealed class FieldOnlyModifier : EventModifier {
|
||||
public ReferenceTypeID declaring {
|
||||
get;
|
||||
construct;
|
||||
@@ -1988,7 +1988,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class StepModifier : EventModifier {
|
||||
public sealed class StepModifier : EventModifier {
|
||||
public ThreadID thread {
|
||||
get;
|
||||
construct;
|
||||
@@ -2032,7 +2032,7 @@ namespace Frida.JDWP {
|
||||
OUT = 2,
|
||||
}
|
||||
|
||||
public class InstanceOnlyModifier : EventModifier {
|
||||
public sealed class InstanceOnlyModifier : EventModifier {
|
||||
public ObjectID instance {
|
||||
get;
|
||||
construct;
|
||||
@@ -2049,7 +2049,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
public class SourceNameMatchModifier : EventModifier {
|
||||
public sealed class SourceNameMatchModifier : EventModifier {
|
||||
public string source_name_pattern {
|
||||
get;
|
||||
construct;
|
||||
@@ -2149,7 +2149,7 @@ namespace Frida.JDWP {
|
||||
REPLY = (1 << 7),
|
||||
}
|
||||
|
||||
private class CommandBuilder : PacketBuilder {
|
||||
private sealed class CommandBuilder : PacketBuilder {
|
||||
public CommandBuilder (uint32 id, CommandSet command_set, uint8 command, IDSizes id_sizes) {
|
||||
base (id, 0, id_sizes);
|
||||
|
||||
@@ -2354,7 +2354,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
private class PacketReader {
|
||||
private sealed class PacketReader {
|
||||
public size_t available_bytes {
|
||||
get {
|
||||
return end - cursor;
|
||||
@@ -2574,7 +2574,7 @@ namespace Frida.JDWP {
|
||||
}
|
||||
}
|
||||
|
||||
private class IDSizes {
|
||||
private sealed class IDSizes {
|
||||
private bool valid;
|
||||
private int field_id_size = -1;
|
||||
private int method_id_size = -1;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class FileMonitor : Object {
|
||||
public sealed class FileMonitor : Object {
|
||||
public signal void change (string file_path, string? other_file_path, FileMonitorEvent event);
|
||||
|
||||
public string path {
|
||||
|
||||
@@ -408,7 +408,7 @@ namespace Frida {
|
||||
protected extern InputStream _get_fifo_for_inject_instance (void * instance);
|
||||
protected extern void _free_inject_instance (void * instance, UnloadPolicy unload_policy);
|
||||
|
||||
public class ResourceStore {
|
||||
public sealed class ResourceStore {
|
||||
public TemporaryDirectory tempdir {
|
||||
get;
|
||||
private set;
|
||||
@@ -439,7 +439,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class AgentDescriptor : Object {
|
||||
public sealed class AgentDescriptor : Object {
|
||||
public string name {
|
||||
get;
|
||||
construct;
|
||||
@@ -553,7 +553,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private class RemoteModule {
|
||||
private sealed class RemoteModule {
|
||||
private Gum.Address base_address;
|
||||
private Gum.ElfModule module;
|
||||
|
||||
@@ -587,7 +587,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private class RemoteThreadSession : Object {
|
||||
private sealed class RemoteThreadSession : Object {
|
||||
public signal void ended (UnloadPolicy unload_policy);
|
||||
|
||||
public uint id {
|
||||
|
||||
@@ -1,82 +1,17 @@
|
||||
namespace Frida {
|
||||
public class FreebsdHostSessionBackend : Object, HostSessionBackend {
|
||||
private FreebsdHostSessionProvider local_provider;
|
||||
|
||||
public async void start (Cancellable? cancellable) throws IOError {
|
||||
assert (local_provider == null);
|
||||
local_provider = new FreebsdHostSessionProvider ();
|
||||
provider_available (local_provider);
|
||||
}
|
||||
|
||||
public async void stop (Cancellable? cancellable) throws IOError {
|
||||
assert (local_provider != null);
|
||||
provider_unavailable (local_provider);
|
||||
yield local_provider.close (cancellable);
|
||||
local_provider = null;
|
||||
public sealed class FreebsdHostSessionBackend : LocalHostSessionBackend {
|
||||
protected override LocalHostSessionProvider make_provider () {
|
||||
return new FreebsdHostSessionProvider ();
|
||||
}
|
||||
}
|
||||
|
||||
public class FreebsdHostSessionProvider : Object, HostSessionProvider {
|
||||
public string id {
|
||||
get { return "local"; }
|
||||
}
|
||||
|
||||
public string name {
|
||||
get { return "Local System"; }
|
||||
}
|
||||
|
||||
public Variant? icon {
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public HostSessionProviderKind kind {
|
||||
get { return HostSessionProviderKind.LOCAL; }
|
||||
}
|
||||
|
||||
private FreebsdHostSession host_session;
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
if (host_session == null)
|
||||
return;
|
||||
host_session.agent_session_detached.disconnect (on_agent_session_detached);
|
||||
yield host_session.close (cancellable);
|
||||
host_session = null;
|
||||
}
|
||||
|
||||
public async HostSession create (HostSessionOptions? options, Cancellable? cancellable) throws Error, IOError {
|
||||
if (host_session != null)
|
||||
throw new Error.INVALID_OPERATION ("Already created");
|
||||
|
||||
host_session = new FreebsdHostSession ();
|
||||
host_session.agent_session_detached.connect (on_agent_session_detached);
|
||||
|
||||
return host_session;
|
||||
}
|
||||
|
||||
public async void destroy (HostSession session, Cancellable? cancellable) throws Error, IOError {
|
||||
if (session != host_session)
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid host session");
|
||||
|
||||
host_session.agent_session_detached.disconnect (on_agent_session_detached);
|
||||
|
||||
yield host_session.close (cancellable);
|
||||
host_session = null;
|
||||
}
|
||||
|
||||
public async AgentSession link_agent_session (HostSession host_session, AgentSessionId id, AgentMessageSink sink,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
if (host_session != this.host_session)
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid host session");
|
||||
|
||||
return yield this.host_session.link_agent_session (id, sink, cancellable);
|
||||
}
|
||||
|
||||
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
|
||||
agent_session_detached (id, reason, crash);
|
||||
public sealed class FreebsdHostSessionProvider : LocalHostSessionProvider {
|
||||
protected override LocalHostSession make_host_session (HostSessionOptions? options) throws Error {
|
||||
return new FreebsdHostSession ();
|
||||
}
|
||||
}
|
||||
|
||||
public class FreebsdHostSession : BaseDBusHostSession {
|
||||
public sealed class FreebsdHostSession : LocalHostSession {
|
||||
private AgentContainer system_session_container;
|
||||
|
||||
private AgentDescriptor agent_desc;
|
||||
|
||||
+144
-64
@@ -24,17 +24,17 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class DeviceManager : Object {
|
||||
public sealed class DeviceManager : Object {
|
||||
public signal void added (Device device);
|
||||
public signal void removed (Device device);
|
||||
public signal void changed ();
|
||||
|
||||
public delegate bool Predicate (Device device);
|
||||
|
||||
private Promise<bool> start_request;
|
||||
private Promise<bool> stop_request;
|
||||
private Promise<bool>? start_request;
|
||||
private Promise<bool>? stop_request;
|
||||
|
||||
private HostSessionService service;
|
||||
private HostSessionService? service;
|
||||
private Gee.ArrayList<Device> devices = new Gee.ArrayList<Device> ();
|
||||
private Gee.ArrayList<DeviceObserverEntry> on_device_added = new Gee.ArrayList<DeviceObserverEntry> ();
|
||||
|
||||
@@ -360,12 +360,7 @@ namespace Frida {
|
||||
|
||||
start_request.resolve (true);
|
||||
} catch (IOError e) {
|
||||
service.provider_available.disconnect (on_provider_available);
|
||||
service.provider_unavailable.disconnect (on_provider_unavailable);
|
||||
service = null;
|
||||
|
||||
start_request.reject (e);
|
||||
start_request = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,19 +420,18 @@ namespace Frida {
|
||||
} catch (GLib.Error e) {
|
||||
cancellable.set_error_if_cancelled ();
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var device in devices.to_array ())
|
||||
yield device._do_close (APPLICATION_REQUESTED, true, cancellable);
|
||||
devices.clear ();
|
||||
foreach (var device in devices.to_array ())
|
||||
yield device._do_close (APPLICATION_REQUESTED, true, cancellable);
|
||||
devices.clear ();
|
||||
|
||||
if (service != null) {
|
||||
yield service.stop (cancellable);
|
||||
service.provider_available.disconnect (on_provider_available);
|
||||
service.provider_unavailable.disconnect (on_provider_unavailable);
|
||||
service = null;
|
||||
}
|
||||
|
||||
service = null;
|
||||
|
||||
stop_request.resolve (true);
|
||||
} catch (IOError e) {
|
||||
stop_request.reject (e);
|
||||
@@ -468,7 +462,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class DeviceList : Object {
|
||||
public sealed class DeviceList : Object {
|
||||
private Gee.List<Device> items;
|
||||
|
||||
internal DeviceList (Gee.List<Device> items) {
|
||||
@@ -484,7 +478,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class Device : Object {
|
||||
public sealed class Device : Object {
|
||||
public signal void spawn_added (Spawn spawn);
|
||||
public signal void spawn_removed (Spawn spawn);
|
||||
public signal void child_added (Child child);
|
||||
@@ -551,7 +545,6 @@ namespace Frida {
|
||||
private Gee.HashSet<Promise<Session>> pending_attach_requests = new Gee.HashSet<Promise<Session>> ();
|
||||
private Gee.HashMap<AgentSessionId?, Promise<bool>> pending_detach_requests =
|
||||
new Gee.HashMap<AgentSessionId?, Promise<bool>> (AgentSessionId.hash, AgentSessionId.equal);
|
||||
private Gee.Set<Service> services = new Gee.HashSet<Service> ();
|
||||
private Bus _bus;
|
||||
|
||||
public delegate bool ProcessPredicate (Process process);
|
||||
@@ -1238,11 +1231,16 @@ namespace Frida {
|
||||
public async IOStream open_channel (string address, Cancellable? cancellable = null) throws Error, IOError {
|
||||
check_open ();
|
||||
|
||||
var channel_provider = provider as HostChannelProvider;
|
||||
if (channel_provider == null)
|
||||
throw new Error.NOT_SUPPORTED ("Channels are not supported by this device");
|
||||
var host_session = yield get_host_session (cancellable);
|
||||
|
||||
return yield channel_provider.open_channel (address, cancellable);
|
||||
ChannelId id;
|
||||
try {
|
||||
id = yield host_session.open_channel (address, cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw_dbus_error (e);
|
||||
}
|
||||
|
||||
return yield provider.link_channel (host_session, id, cancellable);
|
||||
}
|
||||
|
||||
public IOStream open_channel_sync (string address, Cancellable? cancellable = null) throws Error, IOError {
|
||||
@@ -1262,15 +1260,18 @@ namespace Frida {
|
||||
public async Service open_service (string address, Cancellable? cancellable = null) throws Error, IOError {
|
||||
check_open ();
|
||||
|
||||
var service_provider = provider as HostServiceProvider;
|
||||
if (service_provider == null)
|
||||
throw new Error.NOT_SUPPORTED ("Services are not supported by this device");
|
||||
var host_session = yield get_host_session (cancellable);
|
||||
|
||||
var service = yield service_provider.open_service (address, cancellable);
|
||||
service.close.connect (on_service_closed);
|
||||
services.add (service);
|
||||
ServiceSessionId id;
|
||||
try {
|
||||
id = yield host_session.open_service (address, cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw_dbus_error (e);
|
||||
}
|
||||
|
||||
return service;
|
||||
var service_session = yield provider.link_service_session (host_session, id, cancellable);
|
||||
|
||||
return new Service (service_session);
|
||||
}
|
||||
|
||||
public Service open_service_sync (string address, Cancellable? cancellable = null) throws Error, IOError {
|
||||
@@ -1287,10 +1288,6 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private void on_service_closed (Service service) {
|
||||
services.remove (service);
|
||||
}
|
||||
|
||||
public async void unpair (Cancellable? cancellable = null) throws Error, IOError {
|
||||
check_open ();
|
||||
|
||||
@@ -1389,10 +1386,6 @@ namespace Frida {
|
||||
close_request = new Promise<bool> ();
|
||||
|
||||
try {
|
||||
foreach (var service in services.to_array ())
|
||||
yield service.cancel (cancellable);
|
||||
services.clear ();
|
||||
|
||||
while (!pending_detach_requests.is_empty) {
|
||||
var iterator = pending_detach_requests.entries.iterator ();
|
||||
iterator.next ();
|
||||
@@ -1546,7 +1539,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class RemoteDeviceOptions : Object {
|
||||
public sealed class RemoteDeviceOptions : Object {
|
||||
public TlsCertificate? certificate {
|
||||
get;
|
||||
set;
|
||||
@@ -1569,7 +1562,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class ApplicationList : Object {
|
||||
public sealed class ApplicationList : Object {
|
||||
private Gee.List<Application> items;
|
||||
|
||||
internal ApplicationList (Gee.List<Application> items) {
|
||||
@@ -1585,7 +1578,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class Application : Object {
|
||||
public sealed class Application : Object {
|
||||
public string identifier {
|
||||
get;
|
||||
construct;
|
||||
@@ -1611,7 +1604,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcessList : Object {
|
||||
public sealed class ProcessList : Object {
|
||||
private Gee.List<Process> items;
|
||||
|
||||
internal ProcessList (Gee.List<Process> items) {
|
||||
@@ -1627,7 +1620,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class Process : Object {
|
||||
public sealed class Process : Object {
|
||||
public uint pid {
|
||||
get;
|
||||
construct;
|
||||
@@ -1648,7 +1641,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcessMatchOptions : Object {
|
||||
public sealed class ProcessMatchOptions : Object {
|
||||
public int timeout {
|
||||
get;
|
||||
set;
|
||||
@@ -1662,7 +1655,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class SpawnOptions : Object {
|
||||
public sealed class SpawnOptions : Object {
|
||||
public string[]? argv {
|
||||
get;
|
||||
set;
|
||||
@@ -1696,7 +1689,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class SpawnList : Object {
|
||||
public sealed class SpawnList : Object {
|
||||
private Gee.List<Spawn> items;
|
||||
|
||||
internal SpawnList (Gee.List<Spawn> items) {
|
||||
@@ -1712,7 +1705,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class Spawn : Object {
|
||||
public sealed class Spawn : Object {
|
||||
public uint pid {
|
||||
get;
|
||||
construct;
|
||||
@@ -1736,7 +1729,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class ChildList : Object {
|
||||
public sealed class ChildList : Object {
|
||||
private Gee.List<Child> items;
|
||||
|
||||
internal ChildList (Gee.List<Child> items) {
|
||||
@@ -1752,7 +1745,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class Child : Object {
|
||||
public sealed class Child : Object {
|
||||
public uint pid {
|
||||
get;
|
||||
construct;
|
||||
@@ -1816,7 +1809,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class Crash : Object {
|
||||
public sealed class Crash : Object {
|
||||
public uint pid {
|
||||
get;
|
||||
construct;
|
||||
@@ -1865,22 +1858,19 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class Bus : Object {
|
||||
public sealed class Bus : Object {
|
||||
public signal void detached ();
|
||||
public signal void message (string json, Bytes? data);
|
||||
|
||||
public weak Device device {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
private weak Device device;
|
||||
|
||||
private Promise<BusSession>? attach_request;
|
||||
|
||||
private BusSession? active_session;
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
internal Bus (Device device) {
|
||||
Object (device: device);
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
public bool is_detached () {
|
||||
@@ -2000,13 +1990,71 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public interface Service : Object {
|
||||
public sealed class Service : Object {
|
||||
public signal void close ();
|
||||
public signal void message (Variant message);
|
||||
|
||||
public abstract bool is_closed ();
|
||||
private ServiceSession? session;
|
||||
private bool disposed = false;
|
||||
|
||||
public abstract async void activate (Cancellable? cancellable = null) throws Error, IOError;
|
||||
internal Service (ServiceSession session) {
|
||||
this.session = session;
|
||||
|
||||
session.close.connect (on_close);
|
||||
session.message.connect (on_message);
|
||||
}
|
||||
|
||||
public override void dispose () {
|
||||
if (!disposed) {
|
||||
disposed = true;
|
||||
|
||||
MainContext context = get_main_context ();
|
||||
if (context.is_owner ()) {
|
||||
abandon ();
|
||||
} else {
|
||||
var source = new IdleSource ();
|
||||
source.set_callback (() => {
|
||||
abandon ();
|
||||
return false;
|
||||
});
|
||||
source.attach (context);
|
||||
}
|
||||
}
|
||||
|
||||
base.dispose ();
|
||||
}
|
||||
|
||||
~Service () {
|
||||
forget_session ();
|
||||
}
|
||||
|
||||
private void abandon () {
|
||||
var s = session;
|
||||
if (s != null) {
|
||||
forget_session ();
|
||||
s.cancel.begin (null);
|
||||
}
|
||||
}
|
||||
|
||||
private void forget_session () {
|
||||
session.close.disconnect (on_close);
|
||||
session.message.disconnect (on_message);
|
||||
session = null;
|
||||
}
|
||||
|
||||
public bool is_closed () {
|
||||
return session == null;
|
||||
}
|
||||
|
||||
public async void activate (Cancellable? cancellable = null) throws Error, IOError {
|
||||
check_open ();
|
||||
|
||||
try {
|
||||
yield session.activate (cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw_dbus_error (e);
|
||||
}
|
||||
}
|
||||
|
||||
public void activate_sync (Cancellable? cancellable = null) throws Error, IOError {
|
||||
create<ActivateTask> ().execute (cancellable);
|
||||
@@ -2018,7 +2066,17 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract async void cancel (Cancellable? cancellable = null) throws IOError;
|
||||
public async void cancel (Cancellable? cancellable = null) throws IOError {
|
||||
if (session == null)
|
||||
return;
|
||||
|
||||
try {
|
||||
yield session.cancel (cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
if (e is IOError.CANCELLED)
|
||||
cancellable.set_error_if_cancelled ();
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel_sync (Cancellable? cancellable = null) throws IOError {
|
||||
try {
|
||||
@@ -2034,7 +2092,15 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract async Variant request (Variant parameters, Cancellable? cancellable = null) throws Error, IOError;
|
||||
public async Variant request (Variant parameters, Cancellable? cancellable = null) throws Error, IOError {
|
||||
check_open ();
|
||||
|
||||
try {
|
||||
return yield session.request (parameters, cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw_dbus_error (e);
|
||||
}
|
||||
}
|
||||
|
||||
public Variant request_sync (Variant parameters, Cancellable? cancellable = null) throws Error, IOError {
|
||||
var task = create<RequestTask> () as RequestTask;
|
||||
@@ -2050,6 +2116,20 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private void check_open () throws Error {
|
||||
if (session == null)
|
||||
throw new Error.INVALID_OPERATION ("Session is gone");
|
||||
}
|
||||
|
||||
private void on_close () {
|
||||
forget_session ();
|
||||
close ();
|
||||
}
|
||||
|
||||
private void on_message (Variant v) {
|
||||
message (v);
|
||||
}
|
||||
|
||||
private T create<T> () {
|
||||
return Object.new (typeof (T), parent: this);
|
||||
}
|
||||
@@ -2062,7 +2142,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class Session : Object, AgentMessageSink {
|
||||
public sealed class Session : Object, AgentMessageSink {
|
||||
public signal void detached (SessionDetachReason reason, Crash? crash);
|
||||
|
||||
public uint pid {
|
||||
@@ -3030,7 +3110,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class Script : Object {
|
||||
public sealed class Script : Object {
|
||||
public signal void destroyed ();
|
||||
public signal void message (string json, Bytes? data);
|
||||
|
||||
@@ -3267,7 +3347,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class PortalMembership : Object {
|
||||
public sealed class PortalMembership : Object {
|
||||
private uint id;
|
||||
private Session session;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
|
||||
namespace Frida.Fruity {
|
||||
public class LinuxFruitFinder : Object, FruitFinder {
|
||||
public sealed class LinuxFruitFinder : Object, FruitFinder {
|
||||
public string? udid_from_iface (string ifname) throws Error {
|
||||
var net = "/sys/class/net";
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class LinuxPairingBrowser : Object, PairingBrowser {
|
||||
public sealed class LinuxPairingBrowser : Object, PairingBrowser {
|
||||
private Resolved.Manager? resolved;
|
||||
private Source? timer;
|
||||
|
||||
@@ -200,6 +200,8 @@ namespace Frida.Fruity {
|
||||
namespace Network {
|
||||
public async void wait_until_interfaces_ready (Gee.Collection<string> interface_names, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
var wait_cancellable = new Cancellable ();
|
||||
|
||||
try {
|
||||
var connection = yield GLib.Bus.get (BusType.SYSTEM, cancellable);
|
||||
|
||||
@@ -215,6 +217,22 @@ namespace Frida.Fruity {
|
||||
return;
|
||||
}
|
||||
|
||||
var main_context = MainContext.get_thread_default ();
|
||||
|
||||
var timeout_source = new TimeoutSource.seconds (5);
|
||||
timeout_source.set_callback (() => {
|
||||
wait_cancellable.cancel ();
|
||||
return Source.REMOVE;
|
||||
});
|
||||
timeout_source.attach (main_context);
|
||||
|
||||
var cancel_source = new CancellableSource (cancellable);
|
||||
cancel_source.set_callback (() => {
|
||||
wait_cancellable.cancel ();
|
||||
return Source.REMOVE;
|
||||
});
|
||||
cancel_source.attach (main_context);
|
||||
|
||||
var remaining = interface_names.size + 1;
|
||||
|
||||
NotifyCompleteFunc on_complete = () => {
|
||||
@@ -225,10 +243,10 @@ namespace Frida.Fruity {
|
||||
|
||||
foreach (var name in interface_names) {
|
||||
if (nm != null) {
|
||||
NetworkManager.wait_until_interface_ready.begin (name, nm, connection, cancellable,
|
||||
NetworkManager.wait_until_interface_ready.begin (name, nm, connection, wait_cancellable,
|
||||
on_complete);
|
||||
} else {
|
||||
Networkd.wait_until_interface_ready.begin (name, netd, connection, cancellable,
|
||||
Networkd.wait_until_interface_ready.begin (name, netd, connection, wait_cancellable,
|
||||
on_complete);
|
||||
}
|
||||
}
|
||||
@@ -238,11 +256,17 @@ namespace Frida.Fruity {
|
||||
on_complete ();
|
||||
return Source.REMOVE;
|
||||
});
|
||||
source.attach (MainContext.get_thread_default ());
|
||||
source.attach (main_context);
|
||||
|
||||
yield;
|
||||
|
||||
cancel_source.destroy ();
|
||||
timeout_source.destroy ();
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
|
||||
if (wait_cancellable.is_cancelled ())
|
||||
throw new Error.TIMED_OUT ("Unexpectedly timed out while waiting for interfaces to become ready");
|
||||
}
|
||||
|
||||
private async bool system_has_service (string name, DBusConnection connection, Cancellable? cancellable) throws GLib.Error {
|
||||
@@ -276,16 +300,25 @@ namespace Frida.Fruity {
|
||||
wait_until_interface_ready.callback ();
|
||||
});
|
||||
|
||||
var cancel_source = new CancellableSource (cancellable);
|
||||
cancel_source.set_callback (wait_until_interface_ready.callback);
|
||||
cancel_source.attach (MainContext.get_thread_default ());
|
||||
|
||||
while (!cancellable.is_cancelled ()) {
|
||||
uint32 state, reason;
|
||||
device_proxy.get_cached_property ("StateReason").get ("(uu)", out state, out reason);
|
||||
if (state == DEVICE_STATE_ACTIVATED)
|
||||
break;
|
||||
if (state == DEVICE_STATE_DISCONNECTED && reason != DEVICE_STATE_REASON_NONE)
|
||||
if (state == DEVICE_STATE_DISCONNECTED &&
|
||||
reason != DEVICE_STATE_REASON_NONE &&
|
||||
reason != DEVICE_STATE_REASON_CARRIER) {
|
||||
break;
|
||||
}
|
||||
yield;
|
||||
}
|
||||
|
||||
cancel_source.destroy ();
|
||||
|
||||
device_proxy.disconnect (handler);
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
@@ -309,6 +342,7 @@ namespace Frida.Fruity {
|
||||
private const uint32 DEVICE_STATE_ACTIVATED = 100;
|
||||
|
||||
private const uint32 DEVICE_STATE_REASON_NONE = 0;
|
||||
private const uint32 DEVICE_STATE_REASON_CARRIER = 40;
|
||||
}
|
||||
|
||||
namespace Networkd {
|
||||
@@ -327,6 +361,10 @@ namespace Frida.Fruity {
|
||||
wait_until_interface_ready.callback ();
|
||||
});
|
||||
|
||||
var cancel_source = new CancellableSource (cancellable);
|
||||
cancel_source.set_callback (wait_until_interface_ready.callback);
|
||||
cancel_source.attach (MainContext.get_thread_default ());
|
||||
|
||||
while (!cancellable.is_cancelled ()) {
|
||||
string operational_state;
|
||||
link_proxy.get_cached_property ("OperationalState").get ("s", out operational_state);
|
||||
@@ -335,6 +373,8 @@ namespace Frida.Fruity {
|
||||
yield;
|
||||
}
|
||||
|
||||
cancel_source.destroy ();
|
||||
|
||||
link_proxy.disconnect (handler);
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ namespace Frida.Fruity {
|
||||
private ConnectionType _connection_type;
|
||||
private string _udid;
|
||||
private string _name;
|
||||
private string _auth_state;
|
||||
private Bytes? _remote_unlock_host_key;
|
||||
|
||||
private Promise<Tunnel>? tunnel_request;
|
||||
@@ -155,6 +156,11 @@ namespace Frida.Fruity {
|
||||
_name = reader.read_member ("name").get_string_value ();
|
||||
reader.end_member ();
|
||||
|
||||
_auth_state = reader.read_member ("authState").read_member ("rawCase").get_string_value ();
|
||||
reader
|
||||
.end_member ()
|
||||
.end_member ();
|
||||
|
||||
if (reader.has_member ("remoteUnlockHostKey")) {
|
||||
_remote_unlock_host_key = new Bytes (reader.read_member ("remoteUnlockHostKey").get_data_value ());
|
||||
reader.end_member ();
|
||||
@@ -232,6 +238,8 @@ namespace Frida.Fruity {
|
||||
tunnel_request = new Promise<Tunnel> ();
|
||||
|
||||
try {
|
||||
yield ensure_paired (cancellable);
|
||||
|
||||
var tunnel = new MacOSTunnel (pairing_device, _remote_unlock_host_key);
|
||||
yield tunnel.attach (cancellable);
|
||||
|
||||
@@ -245,6 +253,17 @@ namespace Frida.Fruity {
|
||||
throw_api_error (e);
|
||||
}
|
||||
}
|
||||
|
||||
private async void ensure_paired (Cancellable? cancellable) throws Error, IOError {
|
||||
if (_auth_state == "authenticated")
|
||||
return;
|
||||
|
||||
var r = new PairingdRequest ("RemotePairing.InitiatePairingCommand");
|
||||
r.body.set_bool ("requireNonInteractive", false);
|
||||
var response = yield pairing_device.request (r.message, cancellable);
|
||||
var reader = new XpcObjectReader (response);
|
||||
reader.check_nserror (() => Error.PERMISSION_DENIED);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MacOSTunnel : Object, Tunnel {
|
||||
@@ -301,6 +320,7 @@ namespace Frida.Fruity {
|
||||
_opened_at = get_monotonic_time ();
|
||||
|
||||
var reader = new XpcObjectReader (response);
|
||||
reader.check_nserror (() => Error.NOT_SUPPORTED);
|
||||
reader.read_member ("response");
|
||||
|
||||
_assertion_identifier = (Darwin.Xpc.Uuid) reader
|
||||
@@ -411,7 +431,7 @@ namespace Frida.Fruity {
|
||||
return new PcbList (pcbs);
|
||||
}
|
||||
|
||||
public class PcbList {
|
||||
public sealed class PcbList {
|
||||
private uint8[] pcbs;
|
||||
|
||||
internal PcbList (owned uint8[] pcbs) {
|
||||
@@ -422,7 +442,7 @@ namespace Frida.Fruity {
|
||||
return new Iterator (this);
|
||||
}
|
||||
|
||||
public class Iterator {
|
||||
public sealed class Iterator {
|
||||
private PcbList list;
|
||||
private InetItem * cursor;
|
||||
|
||||
@@ -461,7 +481,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class Item {
|
||||
public sealed class Item {
|
||||
public SocketFamily family {
|
||||
get {
|
||||
return ((pcb.version_flag & Darwin.XNU.InetVersionFlags.IPV6) != 0)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
|
||||
namespace Frida.Fruity {
|
||||
public class WindowsPairingBrowser : Object, PairingBrowser {
|
||||
public sealed class WindowsPairingBrowser : Object, PairingBrowser {
|
||||
private Gee.Map<string, Monitor> monitors = new Gee.HashMap<string, Monitor> ();
|
||||
|
||||
private MainContext main_context = MainContext.ref_thread_default ();
|
||||
|
||||
+281
-89
@@ -8,6 +8,8 @@ namespace Frida.Fruity {
|
||||
private Gee.List<Backend> backends = new Gee.ArrayList<Backend> ();
|
||||
private Gee.Map<string, Device> devices = new Gee.HashMap<string, Device> ();
|
||||
|
||||
private PairingStore pairing_store = new PairingStore ();
|
||||
|
||||
private enum State {
|
||||
CREATED,
|
||||
STARTING,
|
||||
@@ -18,11 +20,11 @@ namespace Frida.Fruity {
|
||||
private delegate void NotifyCompleteFunc ();
|
||||
|
||||
construct {
|
||||
add_backend (new UsbmuxBackend ());
|
||||
add_backend (new UsbmuxBackend (pairing_store));
|
||||
#if MACOS
|
||||
add_backend (new MacOSCoreDeviceBackend ());
|
||||
#else
|
||||
add_backend (new PortableCoreDeviceBackend ());
|
||||
add_backend (new PortableCoreDeviceBackend (pairing_store));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -184,10 +186,6 @@ namespace Frida.Fruity {
|
||||
default = new Gee.TreeSet<Transport> (compare_transports);
|
||||
}
|
||||
|
||||
private Gee.Queue<UsbmuxLockdownServiceRequest> usbmux_lockdown_service_requests =
|
||||
new Gee.ArrayQueue<UsbmuxLockdownServiceRequest> ();
|
||||
private LockdownClient? cached_usbmux_lockdown_client;
|
||||
|
||||
private const string[] LOCKDOWN_SERVICES_WITHOUT_ESCROW_BAG_SUPPORT = {
|
||||
"com.apple.accessibility.axAuditDaemon.remoteserver",
|
||||
"com.apple.afc",
|
||||
@@ -205,26 +203,30 @@ namespace Frida.Fruity {
|
||||
}
|
||||
|
||||
public UsbmuxDevice? find_usbmux_device () {
|
||||
var transport = transports.first_match (t => t.usbmux_device != null && t.connection_type == USB);
|
||||
if (transport == null)
|
||||
transport = transports.first_match (t => t.usbmux_device != null);
|
||||
return (transport != null) ? transport.usbmux_device : null;
|
||||
var t = transports.first_match (t => t.usbmux_device != null);
|
||||
return (t != null) ? t.usbmux_device : null;
|
||||
}
|
||||
|
||||
public UsbmuxDevice get_usbmux_device () throws Error {
|
||||
var d = find_usbmux_device ();
|
||||
if (d == null)
|
||||
private UsbmuxTransport get_usbmux_transport () throws Error {
|
||||
var t = transports.first_match (t => t is UsbmuxTransport);
|
||||
if (t == null)
|
||||
throw new Error.NOT_SUPPORTED ("USB connection not available");
|
||||
return d;
|
||||
return (UsbmuxTransport) t;
|
||||
}
|
||||
|
||||
public async Tunnel? find_tunnel (Cancellable? cancellable) throws Error, IOError {
|
||||
var usbmux_device = find_usbmux_device ();
|
||||
foreach (var transport in transports) {
|
||||
|
||||
var transports_to_try = new Gee.ArrayList<Transport> ();
|
||||
transports_to_try.add_all_iterator (transports.filter (t => t.usbmux_device == null));
|
||||
transports_to_try.add_all_iterator (transports.filter (t => t.usbmux_device != null));
|
||||
|
||||
foreach (var transport in transports_to_try) {
|
||||
Tunnel? tunnel = yield transport.find_tunnel (usbmux_device, cancellable);
|
||||
if (tunnel != null)
|
||||
return tunnel;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -283,19 +285,7 @@ namespace Frida.Fruity {
|
||||
return stream;
|
||||
}
|
||||
|
||||
if (service_name == "") {
|
||||
var client = yield open_usbmux_lockdown_client (cancellable);
|
||||
return client.service.stream;
|
||||
}
|
||||
|
||||
var request = new UsbmuxLockdownServiceRequest (service_name, cancellable);
|
||||
bool first_request = usbmux_lockdown_service_requests.is_empty;
|
||||
usbmux_lockdown_service_requests.offer (request);
|
||||
|
||||
if (first_request)
|
||||
process_usbmux_lockdown_service_requests.begin ();
|
||||
|
||||
return yield request.promise.future.wait_async (cancellable);
|
||||
return yield get_usbmux_transport ().open_lockdown_service (service_name, cancellable);
|
||||
}
|
||||
|
||||
// FIXME: Replace with `element in array`-check once Vala compiler bug has been fixed so generated C code is warning-free.
|
||||
@@ -307,41 +297,6 @@ namespace Frida.Fruity {
|
||||
return true;
|
||||
}
|
||||
|
||||
private async void process_usbmux_lockdown_service_requests () {
|
||||
UsbmuxLockdownServiceRequest? req;
|
||||
bool already_invalidated = false;
|
||||
while ((req = usbmux_lockdown_service_requests.peek ()) != null) {
|
||||
try {
|
||||
if (cached_usbmux_lockdown_client == null)
|
||||
cached_usbmux_lockdown_client = yield open_usbmux_lockdown_client (req.cancellable);
|
||||
var stream = yield cached_usbmux_lockdown_client.start_service (req.service_name, req.cancellable);
|
||||
req.promise.resolve (stream);
|
||||
} catch (GLib.Error e) {
|
||||
if (e is LockdownError.CONNECTION_CLOSED && cached_usbmux_lockdown_client != null &&
|
||||
!already_invalidated) {
|
||||
cached_usbmux_lockdown_client = null;
|
||||
already_invalidated = true;
|
||||
continue;
|
||||
}
|
||||
req.promise.reject ((e is LockdownError.INVALID_SERVICE)
|
||||
? (Error) new Error.NOT_SUPPORTED ("%s", e.message)
|
||||
: (Error) new Error.TRANSPORT ("%s", e.message));
|
||||
}
|
||||
|
||||
usbmux_lockdown_service_requests.poll ();
|
||||
}
|
||||
}
|
||||
|
||||
private async LockdownClient open_usbmux_lockdown_client (Cancellable? cancellable) throws Error, IOError {
|
||||
try {
|
||||
var client = yield LockdownClient.open (get_usbmux_device (), cancellable);
|
||||
yield client.start_session (cancellable);
|
||||
return client;
|
||||
} catch (LockdownError e) {
|
||||
throw new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
public async IOStream open_channel (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
string[] tokens = address.split (":", 2);
|
||||
unowned string protocol = tokens[0];
|
||||
@@ -452,17 +407,6 @@ namespace Frida.Fruity {
|
||||
score++;
|
||||
return score;
|
||||
}
|
||||
|
||||
private class UsbmuxLockdownServiceRequest {
|
||||
public string service_name;
|
||||
public Cancellable? cancellable;
|
||||
public Promise<IOStream> promise = new Promise<IOStream> ();
|
||||
|
||||
public UsbmuxLockdownServiceRequest (string service_name, Cancellable? cancellable) {
|
||||
this.service_name = service_name;
|
||||
this.cancellable = cancellable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TcpChannel {
|
||||
@@ -537,6 +481,11 @@ namespace Frida.Fruity {
|
||||
}
|
||||
|
||||
private sealed class UsbmuxBackend : Object, Backend {
|
||||
public PairingStore pairing_store {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public bool available {
|
||||
get {
|
||||
return usbmux != null;
|
||||
@@ -553,6 +502,10 @@ namespace Frida.Fruity {
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
public UsbmuxBackend (PairingStore pairing_store) {
|
||||
Object (pairing_store: pairing_store);
|
||||
}
|
||||
|
||||
public async void start (Cancellable? cancellable) throws IOError {
|
||||
start_request = new Promise<bool> ();
|
||||
start_cancellable = new Cancellable ();
|
||||
@@ -669,7 +622,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
|
||||
private async void add_transport (UsbmuxDevice device) {
|
||||
var transport = new UsbmuxTransport (device);
|
||||
var transport = new UsbmuxTransport (device, pairing_store);
|
||||
transports[device] = transport;
|
||||
|
||||
string? name = null;
|
||||
@@ -735,6 +688,11 @@ namespace Frida.Fruity {
|
||||
construct;
|
||||
}
|
||||
|
||||
public PairingStore pairing_store {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public ConnectionType connection_type {
|
||||
get {
|
||||
return device.connection_type;
|
||||
@@ -768,16 +726,218 @@ namespace Frida.Fruity {
|
||||
internal string _name;
|
||||
internal Variant? _icon;
|
||||
|
||||
public UsbmuxTransport (UsbmuxDevice device) {
|
||||
Object (device: device);
|
||||
private Promise<Tunnel?>? tunnel_request;
|
||||
|
||||
private Gee.Queue<UsbmuxLockdownServiceRequest> lockdown_service_requests =
|
||||
new Gee.ArrayQueue<UsbmuxLockdownServiceRequest> ();
|
||||
private LockdownClient? cached_lockdown_client;
|
||||
|
||||
public UsbmuxTransport (UsbmuxDevice device, PairingStore store) {
|
||||
Object (device: device, pairing_store: store);
|
||||
}
|
||||
|
||||
public async Tunnel? find_tunnel (UsbmuxDevice? device, Cancellable? cancellable) throws Error, IOError {
|
||||
return null;
|
||||
while (tunnel_request != null) {
|
||||
try {
|
||||
return yield tunnel_request.future.wait_async (cancellable);
|
||||
} catch (Error e) {
|
||||
throw e;
|
||||
} catch (IOError e) {
|
||||
cancellable.set_error_if_cancelled ();
|
||||
}
|
||||
}
|
||||
tunnel_request = new Promise<Tunnel> ();
|
||||
|
||||
try {
|
||||
IOStream? stream = null;
|
||||
try {
|
||||
stream = yield open_lockdown_service ("com.apple.internal.devicecompute.CoreDeviceProxy", cancellable);
|
||||
} catch (Error e) {
|
||||
if (!(e is Error.NOT_SUPPORTED))
|
||||
throw e;
|
||||
}
|
||||
|
||||
UsbmuxTunnel? tunnel = null;
|
||||
if (stream != null) {
|
||||
tunnel = new UsbmuxTunnel (stream, pairing_store);
|
||||
tunnel.lost.connect (on_tunnel_lost);
|
||||
try {
|
||||
yield tunnel.open (cancellable);
|
||||
} catch (Error e) {
|
||||
if (e is Error.NOT_SUPPORTED)
|
||||
tunnel = null;
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
tunnel_request.resolve (tunnel);
|
||||
|
||||
return tunnel;
|
||||
} catch (GLib.Error e) {
|
||||
tunnel_request.reject (e);
|
||||
tunnel_request = null;
|
||||
|
||||
throw_api_error (e);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_tunnel_lost () {
|
||||
tunnel_request = null;
|
||||
}
|
||||
|
||||
public async IOStream open_lockdown_service (string service_name, Cancellable? cancellable) throws Error, IOError {
|
||||
if (service_name == "") {
|
||||
var client = yield open_usbmux_lockdown_client (cancellable);
|
||||
return client.service.stream;
|
||||
}
|
||||
|
||||
var request = new UsbmuxLockdownServiceRequest (service_name, cancellable);
|
||||
bool first_request = lockdown_service_requests.is_empty;
|
||||
lockdown_service_requests.offer (request);
|
||||
|
||||
if (first_request)
|
||||
process_lockdown_service_requests.begin ();
|
||||
|
||||
return yield request.promise.future.wait_async (cancellable);
|
||||
}
|
||||
|
||||
private async void process_lockdown_service_requests () {
|
||||
UsbmuxLockdownServiceRequest? req;
|
||||
bool already_invalidated = false;
|
||||
while ((req = lockdown_service_requests.peek ()) != null) {
|
||||
try {
|
||||
if (cached_lockdown_client == null)
|
||||
cached_lockdown_client = yield open_usbmux_lockdown_client (req.cancellable);
|
||||
var stream = yield cached_lockdown_client.start_service (req.service_name, req.cancellable);
|
||||
req.promise.resolve (stream);
|
||||
} catch (GLib.Error e) {
|
||||
if (e is LockdownError.CONNECTION_CLOSED && cached_lockdown_client != null &&
|
||||
!already_invalidated) {
|
||||
cached_lockdown_client = null;
|
||||
already_invalidated = true;
|
||||
continue;
|
||||
}
|
||||
req.promise.reject ((e is LockdownError.INVALID_SERVICE)
|
||||
? (Error) new Error.NOT_SUPPORTED ("%s", e.message)
|
||||
: (Error) new Error.TRANSPORT ("%s", e.message));
|
||||
}
|
||||
|
||||
lockdown_service_requests.poll ();
|
||||
}
|
||||
}
|
||||
|
||||
private async LockdownClient open_usbmux_lockdown_client (Cancellable? cancellable) throws Error, IOError {
|
||||
try {
|
||||
var client = yield LockdownClient.open (device, cancellable);
|
||||
yield client.start_session (cancellable);
|
||||
return client;
|
||||
} catch (LockdownError e) {
|
||||
throw new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
private class UsbmuxLockdownServiceRequest {
|
||||
public string service_name;
|
||||
public Cancellable? cancellable;
|
||||
public Promise<IOStream> promise = new Promise<IOStream> ();
|
||||
|
||||
public UsbmuxLockdownServiceRequest (string service_name, Cancellable? cancellable) {
|
||||
this.service_name = service_name;
|
||||
this.cancellable = cancellable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class UsbmuxTunnel : Object, Tunnel {
|
||||
public signal void lost ();
|
||||
|
||||
public IOStream stream {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public PairingStore pairing_store {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public DiscoveryService discovery {
|
||||
get {
|
||||
return _discovery_service;
|
||||
}
|
||||
}
|
||||
|
||||
public int64 opened_at {
|
||||
get {
|
||||
return _opened_at;
|
||||
}
|
||||
}
|
||||
|
||||
public Bytes? remote_unlock_host_key {
|
||||
get {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private UsbNcmDriver? ncm;
|
||||
private TcpTunnelConnection? tunnel_connection;
|
||||
private DiscoveryService? _discovery_service;
|
||||
private int64 _opened_at = -1;
|
||||
|
||||
public UsbmuxTunnel (IOStream stream, PairingStore store) {
|
||||
Object (stream: stream, pairing_store: store);
|
||||
}
|
||||
|
||||
public async void open (Cancellable? cancellable) throws Error, IOError {
|
||||
var tc = yield TcpTunnelConnection.open_stream (stream, cancellable);
|
||||
tunnel_connection = tc;
|
||||
tunnel_connection.closed.connect (on_tunnel_connection_close);
|
||||
|
||||
_opened_at = get_monotonic_time ();
|
||||
|
||||
var rsd_endpoint = (InetSocketAddress) Object.new (typeof (InetSocketAddress),
|
||||
address: tc.remote_address,
|
||||
port: tc.remote_rsd_port,
|
||||
scope_id: tc.tunnel_netstack.scope_id
|
||||
);
|
||||
var rsd_connection = yield tc.tunnel_netstack.open_tcp_connection (rsd_endpoint, cancellable);
|
||||
var disco = yield DiscoveryService.open (rsd_connection, cancellable);
|
||||
|
||||
tunnel_connection = tc;
|
||||
_discovery_service = disco;
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
_discovery_service.close ();
|
||||
|
||||
yield tunnel_connection.close (cancellable);
|
||||
|
||||
if (ncm != null)
|
||||
ncm.close ();
|
||||
}
|
||||
|
||||
public async IOStream open_tcp_connection (uint16 port, Cancellable? cancellable) throws Error, IOError {
|
||||
var netstack = tunnel_connection.tunnel_netstack;
|
||||
var endpoint = (InetSocketAddress) Object.new (typeof (InetSocketAddress),
|
||||
address: tunnel_connection.remote_address,
|
||||
port: port,
|
||||
scope_id: netstack.scope_id
|
||||
);
|
||||
return yield netstack.open_tcp_connection (endpoint, cancellable);
|
||||
}
|
||||
|
||||
private void on_tunnel_connection_close () {
|
||||
lost ();
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class PortableCoreDeviceBackend : Object, Backend, UsbDeviceBackend {
|
||||
public PairingStore pairing_store {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public bool supports_modeswitch {
|
||||
get {
|
||||
return LibUSB.has_capability (HAS_HOTPLUG) != 0;
|
||||
@@ -811,8 +971,6 @@ namespace Frida.Fruity {
|
||||
private Gee.Map<string, PortableCoreDeviceNetworkTransport> network_transports =
|
||||
new Gee.HashMap<string, PortableCoreDeviceNetworkTransport> ();
|
||||
|
||||
private PairingStore pairing_store = new PairingStore ();
|
||||
|
||||
private MainContext main_context;
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
@@ -832,6 +990,10 @@ namespace Frida.Fruity {
|
||||
|
||||
private delegate void NotifyCompleteFunc ();
|
||||
|
||||
public PortableCoreDeviceBackend (PairingStore pairing_store) {
|
||||
Object (pairing_store: pairing_store);
|
||||
}
|
||||
|
||||
construct {
|
||||
main_context = MainContext.ref_thread_default ();
|
||||
|
||||
@@ -1403,7 +1565,8 @@ namespace Frida.Fruity {
|
||||
supported_by_os = ios_major_version >= 17;
|
||||
}
|
||||
} catch (LockdownError e) {
|
||||
throw new Error.PERMISSION_DENIED ("%s", e.message);
|
||||
if (!(e is LockdownError.NOT_PAIRED))
|
||||
throw new Error.PERMISSION_DENIED ("%s", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1564,36 +1727,65 @@ namespace Frida.Fruity {
|
||||
public signal void response_received (Bytes response, InetSocketAddress sender);
|
||||
|
||||
public NetworkStack netstack;
|
||||
public UdpSocket sock;
|
||||
public DatagramBasedSource response_source;
|
||||
private Cancellable? io_cancellable;
|
||||
|
||||
private UdpSocket sock;
|
||||
private DatagramBased sock_datagram;
|
||||
|
||||
private Bytes remoted_mdns_request;
|
||||
private InetSocketAddress mdns_address;
|
||||
|
||||
private TimeoutSource retransmit_source;
|
||||
private DatagramBasedSource response_source;
|
||||
|
||||
public ActiveMulticastDnsProbe (InetSocketAddress ifaddr, MainContext main_context, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
var local_ip = ifaddr.get_address ();
|
||||
netstack = new SystemNetworkStack (local_ip, ifaddr.scope_id);
|
||||
io_cancellable = cancellable;
|
||||
|
||||
sock = netstack.create_udp_socket ();
|
||||
sock.bind ((InetSocketAddress) Object.new (typeof (InetSocketAddress),
|
||||
address: local_ip,
|
||||
scope_id: netstack.scope_id
|
||||
));
|
||||
DatagramBased sock_datagram = sock.datagram_based;
|
||||
sock_datagram = sock.datagram_based;
|
||||
|
||||
var remoted_mdns_request = make_remoted_mdns_request ();
|
||||
var mdns_address = (InetSocketAddress) Object.new (typeof (InetSocketAddress),
|
||||
remoted_mdns_request = make_remoted_mdns_request ();
|
||||
|
||||
mdns_address = (InetSocketAddress) Object.new (typeof (InetSocketAddress),
|
||||
address: new InetAddress.from_string ("ff02::fb"),
|
||||
port: 5353,
|
||||
scope_id: netstack.scope_id
|
||||
);
|
||||
Udp.send_to (remoted_mdns_request.get_data (), mdns_address, sock_datagram, cancellable);
|
||||
|
||||
retransmit_source = new TimeoutSource (250);
|
||||
retransmit_source.set_callback (on_retransmit_tick);
|
||||
retransmit_source.attach (main_context);
|
||||
|
||||
response_source = sock_datagram.create_source (IN, cancellable);
|
||||
response_source.set_callback (on_socket_readable);
|
||||
response_source.attach (main_context);
|
||||
|
||||
transmit_request ();
|
||||
}
|
||||
|
||||
public void cancel () {
|
||||
response_source.destroy ();
|
||||
retransmit_source.destroy ();
|
||||
}
|
||||
|
||||
private void transmit_request () throws Error, IOError {
|
||||
Udp.send_to (remoted_mdns_request.get_data (), mdns_address, sock_datagram, io_cancellable);
|
||||
}
|
||||
|
||||
private bool on_retransmit_tick () {
|
||||
try {
|
||||
transmit_request ();
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
|
||||
return Source.CONTINUE;
|
||||
}
|
||||
|
||||
private bool on_socket_readable () {
|
||||
@@ -1997,7 +2189,7 @@ namespace Frida.Fruity {
|
||||
public abstract string? udid_from_iface (string ifname) throws Error;
|
||||
}
|
||||
|
||||
public class NullFruitFinder : Object, FruitFinder {
|
||||
public sealed class NullFruitFinder : Object, FruitFinder {
|
||||
public string? udid_from_iface (string ifname) throws Error {
|
||||
return null;
|
||||
}
|
||||
@@ -2022,7 +2214,7 @@ namespace Frida.Fruity {
|
||||
public abstract async void stop (Cancellable? cancellable) throws IOError;
|
||||
}
|
||||
|
||||
public class NullPairingBrowser : Object, PairingBrowser {
|
||||
public sealed class NullPairingBrowser : Object, PairingBrowser {
|
||||
public async void start (Cancellable? cancellable) throws IOError {
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
|
||||
namespace Frida.Fruity {
|
||||
public class DnsPacketReader {
|
||||
public sealed class DnsPacketReader {
|
||||
private BufferReader reader;
|
||||
|
||||
public DnsPacketReader (Bytes packet) {
|
||||
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
|
||||
namespace Frida.Fruity {
|
||||
public class DeviceInfoService : Object, AsyncInitable {
|
||||
public sealed class DeviceInfoService : Object, AsyncInitable {
|
||||
public HostChannelProvider channel_provider {
|
||||
get;
|
||||
construct;
|
||||
@@ -75,7 +75,7 @@ namespace Frida.Fruity {
|
||||
return name;
|
||||
}
|
||||
|
||||
public class ProcessInfo : Object {
|
||||
public sealed class ProcessInfo : Object {
|
||||
public uint pid {
|
||||
get;
|
||||
set;
|
||||
@@ -108,7 +108,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class ApplicationListingService : Object, AsyncInitable {
|
||||
public sealed class ApplicationListingService : Object, AsyncInitable {
|
||||
public HostChannelProvider channel_provider {
|
||||
get;
|
||||
construct;
|
||||
@@ -211,7 +211,7 @@ namespace Frida.Fruity {
|
||||
return result;
|
||||
}
|
||||
|
||||
public class ApplicationInfo : Object {
|
||||
public sealed class ApplicationInfo : Object {
|
||||
public ApplicationType app_type {
|
||||
get;
|
||||
set;
|
||||
@@ -306,7 +306,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcessControlService : Object, AsyncInitable {
|
||||
public sealed class ProcessControlService : Object, AsyncInitable {
|
||||
public HostChannelProvider channel_provider {
|
||||
get;
|
||||
construct;
|
||||
@@ -346,7 +346,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class DTXConnection : Object, DTXTransport {
|
||||
public sealed class DTXConnection : Object, DTXTransport {
|
||||
public IOStream stream {
|
||||
get;
|
||||
construct;
|
||||
@@ -847,7 +847,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
private class DTXControlChannel : DTXChannel {
|
||||
private sealed class DTXControlChannel : DTXChannel {
|
||||
public DTXControlChannel (DTXTransport transport) {
|
||||
Object (code: 0, transport: transport);
|
||||
}
|
||||
@@ -1161,7 +1161,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class DTXArgumentListBuilder {
|
||||
public sealed class DTXArgumentListBuilder {
|
||||
private PrimitiveBuilder blob = new PrimitiveBuilder ();
|
||||
|
||||
public DTXArgumentListBuilder () {
|
||||
@@ -1227,7 +1227,7 @@ namespace Frida.Fruity {
|
||||
|
||||
private const size_t PRIMITIVE_DICTIONARY_HEADER_SIZE = 16;
|
||||
|
||||
private class PrimitiveReader {
|
||||
private sealed class PrimitiveReader {
|
||||
public size_t available_bytes {
|
||||
get {
|
||||
return end - cursor;
|
||||
@@ -1317,7 +1317,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
private class PrimitiveBuilder {
|
||||
private sealed class PrimitiveBuilder {
|
||||
public size_t offset {
|
||||
get {
|
||||
return cursor;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace Frida {
|
||||
public class FruityHostSessionBackend : Object, HostSessionBackend {
|
||||
public sealed class FruityHostSessionBackend : Object, HostSessionBackend {
|
||||
private Fruity.DeviceMonitor device_monitor = new Fruity.DeviceMonitor ();
|
||||
private Gee.Map<Fruity.Device, FruityHostSessionProvider> providers =
|
||||
new Gee.HashMap<Fruity.Device, FruityHostSessionProvider> ();
|
||||
@@ -42,7 +42,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class FruityHostSessionProvider : Object, HostSessionProvider, HostChannelProvider, HostServiceProvider, Pairable {
|
||||
public sealed class FruityHostSessionProvider : Object, HostSessionProvider, HostChannelProvider, Pairable {
|
||||
public Fruity.Device device {
|
||||
get;
|
||||
construct;
|
||||
@@ -108,6 +108,43 @@ namespace Frida {
|
||||
return yield this.host_session.link_agent_session (id, sink, cancellable);
|
||||
}
|
||||
|
||||
public void unlink_agent_session (HostSession host_session, AgentSessionId id) {
|
||||
if (host_session != this.host_session)
|
||||
return;
|
||||
|
||||
this.host_session.unlink_agent_session (id);
|
||||
}
|
||||
|
||||
public async IOStream link_channel (HostSession host_session, ChannelId id, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
if (host_session != this.host_session)
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid host session");
|
||||
|
||||
return this.host_session.link_channel (id);
|
||||
}
|
||||
|
||||
public void unlink_channel (HostSession host_session, ChannelId id) {
|
||||
if (host_session != this.host_session)
|
||||
return;
|
||||
|
||||
this.host_session.unlink_channel (id);
|
||||
}
|
||||
|
||||
public async ServiceSession link_service_session (HostSession host_session, ServiceSessionId id, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
if (host_session != this.host_session)
|
||||
throw new Error.INVALID_ARGUMENT ("Invalid host session");
|
||||
|
||||
return this.host_session.link_service_session (id);
|
||||
}
|
||||
|
||||
public void unlink_service_session (HostSession host_session, ServiceSessionId id) {
|
||||
if (host_session != this.host_session)
|
||||
return;
|
||||
|
||||
this.host_session.unlink_service_session (id);
|
||||
}
|
||||
|
||||
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
|
||||
agent_session_detached (id, reason, crash);
|
||||
}
|
||||
@@ -116,37 +153,6 @@ namespace Frida {
|
||||
return yield device.open_channel (address, cancellable);
|
||||
}
|
||||
|
||||
public async Service open_service (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
string[] tokens = address.split (":", 2);
|
||||
unowned string protocol = tokens[0];
|
||||
unowned string service_name = tokens[1];
|
||||
|
||||
if (protocol == "plist") {
|
||||
var stream = yield device.open_lockdown_service (service_name, cancellable);
|
||||
|
||||
return new PlistService (stream);
|
||||
}
|
||||
|
||||
if (protocol == "dtx") {
|
||||
var connection = yield Fruity.DTXConnection.obtain (device, cancellable);
|
||||
|
||||
return new DTXService (service_name, connection);
|
||||
}
|
||||
|
||||
if (protocol == "xpc") {
|
||||
var tunnel = yield device.find_tunnel (cancellable);
|
||||
if (tunnel == null)
|
||||
throw new Error.NOT_SUPPORTED ("RemoteXPC not supported by device");
|
||||
|
||||
var service_info = tunnel.discovery.get_service (service_name);
|
||||
var stream = yield tunnel.open_tcp_connection (service_info.port, cancellable);
|
||||
|
||||
return new XpcService (new Fruity.XpcConnection (stream));
|
||||
}
|
||||
|
||||
throw new Error.NOT_SUPPORTED ("Unsupported service address");
|
||||
}
|
||||
|
||||
private async void unpair (Cancellable? cancellable) throws Error, IOError {
|
||||
try {
|
||||
var client = yield device.get_lockdown_client (cancellable);
|
||||
@@ -159,7 +165,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class FruityHostSession : Object, HostSession {
|
||||
public sealed class FruityHostSession : Object, HostSession {
|
||||
public Fruity.Device device {
|
||||
get;
|
||||
construct;
|
||||
@@ -179,6 +185,10 @@ namespace Frida {
|
||||
private Gee.HashMap<AgentSessionId?, AgentSessionEntry> agent_sessions =
|
||||
new Gee.HashMap<AgentSessionId?, AgentSessionEntry> (AgentSessionId.hash, AgentSessionId.equal);
|
||||
|
||||
private ChannelRegistry channel_registry = new ChannelRegistry ();
|
||||
|
||||
private ServiceSessionRegistry service_session_registry = new ServiceSessionRegistry ();
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
private const double MIN_SERVER_CHECK_INTERVAL = 5.0;
|
||||
@@ -196,6 +206,11 @@ namespace Frida {
|
||||
Object (device: device);
|
||||
}
|
||||
|
||||
construct {
|
||||
channel_registry.channel_closed.connect (on_channel_closed);
|
||||
service_session_registry.session_closed.connect (on_service_session_closed);
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
if (remote_server_request != null) {
|
||||
try {
|
||||
@@ -999,6 +1014,15 @@ namespace Frida {
|
||||
return session;
|
||||
}
|
||||
|
||||
public void unlink_agent_session (AgentSessionId id) {
|
||||
AgentSessionEntry? entry = agent_sessions[id];
|
||||
if (entry == null || entry.sink_registration_id == 0)
|
||||
return;
|
||||
|
||||
entry.connection.unregister_object (entry.sink_registration_id);
|
||||
entry.sink_registration_id = 0;
|
||||
}
|
||||
|
||||
public async InjectorPayloadId inject_library_file (uint pid, string path, string entrypoint, string data,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
var server = yield get_remote_server (cancellable);
|
||||
@@ -1019,6 +1043,79 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
var stream = yield device.open_channel (address, cancellable);
|
||||
|
||||
var id = ChannelId.generate ();
|
||||
channel_registry.register (id, stream);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public IOStream link_channel (ChannelId id) throws Error {
|
||||
return channel_registry.link (id);
|
||||
}
|
||||
|
||||
public void unlink_channel (ChannelId id) {
|
||||
channel_registry.unlink (id);
|
||||
}
|
||||
|
||||
private void on_channel_closed (ChannelId id) {
|
||||
channel_closed (id);
|
||||
}
|
||||
|
||||
private void on_service_session_closed (ServiceSessionId id) {
|
||||
service_session_closed (id);
|
||||
}
|
||||
|
||||
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
var session = yield do_open_service (address, cancellable);
|
||||
|
||||
var id = ServiceSessionId.generate ();
|
||||
service_session_registry.register (id, session);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private async ServiceSession do_open_service (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
string[] tokens = address.split (":", 2);
|
||||
unowned string protocol = tokens[0];
|
||||
unowned string service_name = tokens[1];
|
||||
|
||||
if (protocol == "plist") {
|
||||
var stream = yield device.open_lockdown_service (service_name, cancellable);
|
||||
|
||||
return new PlistServiceSession (stream);
|
||||
}
|
||||
|
||||
if (protocol == "dtx") {
|
||||
var connection = yield Fruity.DTXConnection.obtain (device, cancellable);
|
||||
|
||||
return new DTXServiceSession (service_name, connection);
|
||||
}
|
||||
|
||||
if (protocol == "xpc") {
|
||||
var tunnel = yield device.find_tunnel (cancellable);
|
||||
if (tunnel == null)
|
||||
throw new Error.NOT_SUPPORTED ("RemoteXPC not supported by device");
|
||||
|
||||
var service_info = tunnel.discovery.get_service (service_name);
|
||||
var stream = yield tunnel.open_tcp_connection (service_info.port, cancellable);
|
||||
|
||||
return new XpcServiceSession (new Fruity.XpcConnection (stream));
|
||||
}
|
||||
|
||||
throw new Error.NOT_SUPPORTED ("Unsupported service address");
|
||||
}
|
||||
|
||||
public ServiceSession link_service_session (ServiceSessionId id) throws Error {
|
||||
return service_session_registry.link (id);
|
||||
}
|
||||
|
||||
public void unlink_service_session (ServiceSessionId id) {
|
||||
service_session_registry.unlink (id);
|
||||
}
|
||||
|
||||
private void add_lldb_session (LLDBSession session) {
|
||||
lldb_sessions[session.process.pid] = session;
|
||||
|
||||
@@ -1554,22 +1651,16 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class PlistService : Object, Service {
|
||||
private sealed class PlistServiceSession : Object, ServiceSession {
|
||||
public IOStream stream {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private State state = INACTIVE;
|
||||
private Fruity.PlistServiceClient client;
|
||||
private bool client_closed = false;
|
||||
|
||||
private enum State {
|
||||
INACTIVE,
|
||||
ACTIVE,
|
||||
}
|
||||
|
||||
public PlistService (IOStream stream) {
|
||||
public PlistServiceSession (IOStream stream) {
|
||||
Object (stream: stream);
|
||||
}
|
||||
|
||||
@@ -1578,8 +1669,8 @@ namespace Frida {
|
||||
client.closed.connect (on_client_closed);
|
||||
}
|
||||
|
||||
public bool is_closed () {
|
||||
return client_closed;
|
||||
~PlistServiceSession () {
|
||||
client.closed.disconnect (on_client_closed);
|
||||
}
|
||||
|
||||
public async void activate (Cancellable? cancellable) throws Error, IOError {
|
||||
@@ -1587,14 +1678,8 @@ namespace Frida {
|
||||
}
|
||||
|
||||
private void ensure_active () throws Error {
|
||||
if (state == INACTIVE) {
|
||||
state = ACTIVE;
|
||||
|
||||
if (client_closed) {
|
||||
close ();
|
||||
throw new Error.INVALID_OPERATION ("Service is closed");
|
||||
}
|
||||
}
|
||||
if (client_closed)
|
||||
throw new Error.INVALID_OPERATION ("Service is closed");
|
||||
}
|
||||
|
||||
public async void cancel (Cancellable? cancellable) throws IOError {
|
||||
@@ -1603,6 +1688,8 @@ namespace Frida {
|
||||
client_closed = true;
|
||||
|
||||
yield client.close (cancellable);
|
||||
|
||||
close ();
|
||||
}
|
||||
|
||||
public async Variant request (Variant parameters, Cancellable? cancellable = null) throws Error, IOError {
|
||||
@@ -1757,7 +1844,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class DTXService : Object, Service {
|
||||
private sealed class DTXServiceSession : Object, ServiceSession {
|
||||
public string identifier {
|
||||
get;
|
||||
construct;
|
||||
@@ -1777,7 +1864,7 @@ namespace Frida {
|
||||
ACTIVE,
|
||||
}
|
||||
|
||||
public DTXService (string identifier, Fruity.DTXConnection connection) {
|
||||
public DTXServiceSession (string identifier, Fruity.DTXConnection connection) {
|
||||
Object (identifier: identifier, connection: connection);
|
||||
}
|
||||
|
||||
@@ -1785,8 +1872,8 @@ namespace Frida {
|
||||
connection.notify["state"].connect (on_connection_state_changed);
|
||||
}
|
||||
|
||||
public bool is_closed () {
|
||||
return connection_closed;
|
||||
~DTXServiceSession () {
|
||||
connection.notify["state"].disconnect (on_connection_state_changed);
|
||||
}
|
||||
|
||||
public async void activate (Cancellable? cancellable) throws Error, IOError {
|
||||
@@ -1794,14 +1881,12 @@ namespace Frida {
|
||||
}
|
||||
|
||||
private void ensure_active () throws Error {
|
||||
if (connection_closed)
|
||||
throw new Error.INVALID_OPERATION ("Service is closed");
|
||||
|
||||
if (state == INACTIVE) {
|
||||
state = ACTIVE;
|
||||
|
||||
if (connection_closed) {
|
||||
close ();
|
||||
throw new Error.INVALID_OPERATION ("Service is closed");
|
||||
}
|
||||
|
||||
channel = connection.make_channel (identifier);
|
||||
channel.invocation.connect (on_channel_invocation);
|
||||
channel.notification.connect (on_channel_notification);
|
||||
@@ -1812,7 +1897,13 @@ namespace Frida {
|
||||
if (connection_closed)
|
||||
return;
|
||||
connection_closed = true;
|
||||
channel = null;
|
||||
|
||||
if (channel != null) {
|
||||
channel.invocation.disconnect (on_channel_invocation);
|
||||
channel.notification.disconnect (on_channel_notification);
|
||||
channel = null;
|
||||
}
|
||||
|
||||
close ();
|
||||
}
|
||||
|
||||
@@ -2026,7 +2117,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class XpcService : Object, Service {
|
||||
private sealed class XpcServiceSession : Object, ServiceSession {
|
||||
public Fruity.XpcConnection connection {
|
||||
get;
|
||||
construct;
|
||||
@@ -2040,7 +2131,7 @@ namespace Frida {
|
||||
ACTIVE,
|
||||
}
|
||||
|
||||
public XpcService (Fruity.XpcConnection connection) {
|
||||
public XpcServiceSession (Fruity.XpcConnection connection) {
|
||||
Object (connection: connection);
|
||||
}
|
||||
|
||||
@@ -2049,8 +2140,11 @@ namespace Frida {
|
||||
connection.message.connect (on_message);
|
||||
}
|
||||
|
||||
public bool is_closed () {
|
||||
return connection_closed;
|
||||
~XpcServiceSession () {
|
||||
connection.close.disconnect (on_close);
|
||||
connection.message.disconnect (on_message);
|
||||
|
||||
connection.cancel ();
|
||||
}
|
||||
|
||||
public async void activate (Cancellable? cancellable) throws Error, IOError {
|
||||
@@ -2058,20 +2152,21 @@ namespace Frida {
|
||||
}
|
||||
|
||||
private void ensure_active () throws Error {
|
||||
if (connection_closed)
|
||||
throw new Error.INVALID_OPERATION ("Service is closed");
|
||||
|
||||
if (state == INACTIVE) {
|
||||
state = ACTIVE;
|
||||
|
||||
if (connection_closed) {
|
||||
close ();
|
||||
throw new Error.INVALID_OPERATION ("Service is closed");
|
||||
}
|
||||
|
||||
connection.activate ();
|
||||
}
|
||||
}
|
||||
|
||||
public async void cancel (Cancellable? cancellable) throws IOError {
|
||||
connection.cancel ();
|
||||
if (state == ACTIVE)
|
||||
connection.cancel ();
|
||||
else if (!connection_closed)
|
||||
on_close (null);
|
||||
}
|
||||
|
||||
public async Variant request (Variant parameters, Cancellable? cancellable = null) throws Error, IOError {
|
||||
@@ -2095,6 +2190,7 @@ namespace Frida {
|
||||
|
||||
private void on_close (Error? error) {
|
||||
connection_closed = true;
|
||||
|
||||
close ();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Frida.Fruity.Injector {
|
||||
return yield session.run (cancellable);
|
||||
}
|
||||
|
||||
public class GadgetDetails : Object {
|
||||
public sealed class GadgetDetails : Object {
|
||||
public uint16 port {
|
||||
get;
|
||||
construct;
|
||||
@@ -21,7 +21,7 @@ namespace Frida.Fruity.Injector {
|
||||
UNSUPPORTED
|
||||
}
|
||||
|
||||
private class Session : Object {
|
||||
private sealed class Session : Object {
|
||||
public Gum.DarwinModule module {
|
||||
get;
|
||||
construct;
|
||||
@@ -825,7 +825,9 @@ namespace Frida.Fruity.Injector {
|
||||
|
||||
yield restore_main_thread_state (cancellable);
|
||||
|
||||
uint64? libdyld_initialize = dyld_symbols["__ZN5dyld44APIs19_libdyld_initializeEPKNS_16LibSystemHelpersE"];
|
||||
uint64? libdyld_initialize = dyld_symbols["__ZN5dyld44APIs19_libdyld_initializeEv"];
|
||||
if (libdyld_initialize == null)
|
||||
libdyld_initialize = dyld_symbols["__ZN5dyld44APIs19_libdyld_initializeEPKNS_16LibSystemHelpersE"];
|
||||
if (libdyld_initialize != null)
|
||||
yield ensure_libsystem_initialized_for_dyld_v4_and_above (libdyld_initialize, dyld_symbols, cancellable);
|
||||
else
|
||||
@@ -848,9 +850,10 @@ namespace Frida.Fruity.Injector {
|
||||
uint64? notify_objc_init = dyld_symbols["__ZN5dyld412RuntimeState14notifyObjCInitEPKNS_6LoaderE"];
|
||||
uint64 initializer = (notify_objc_init != null) ? notify_objc_init : libdyld_initialize;
|
||||
GDB.Breakpoint init_breakpoint = yield lldb.add_breakpoint (SOFT, initializer, 4, cancellable);
|
||||
|
||||
GDB.Breakpoint? restart_breakpoint = null;
|
||||
uint64? restart_with_dyld_in_cache = dyld_symbols["__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN5dyld39MachOFileEPK15DyldSharedCachePv"];
|
||||
uint64? restart_with_dyld_in_cache = dyld_symbols["__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN6mach_o6HeaderEPK15DyldSharedCachePv"];
|
||||
if (restart_with_dyld_in_cache == null)
|
||||
restart_with_dyld_in_cache = dyld_symbols["__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN5dyld39MachOFileEPK15DyldSharedCachePv"];
|
||||
if (restart_with_dyld_in_cache == null)
|
||||
restart_with_dyld_in_cache = dyld_symbols["__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN5dyld39MachOFileEPv"];
|
||||
if (restart_with_dyld_in_cache != null)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
|
||||
namespace Frida.Fruity {
|
||||
public class InstallationProxyClient : Object, AsyncInitable {
|
||||
public sealed class InstallationProxyClient : Object, AsyncInitable {
|
||||
public Device device {
|
||||
get;
|
||||
construct;
|
||||
@@ -193,7 +193,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class ApplicationDetails : Object {
|
||||
public sealed class ApplicationDetails : Object {
|
||||
public string identifier {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class NSNumber : NSObject {
|
||||
public sealed class NSNumber : NSObject {
|
||||
public Kind kind {
|
||||
get;
|
||||
private set;
|
||||
@@ -108,7 +108,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class NSString : NSObject {
|
||||
public sealed class NSString : NSObject {
|
||||
public string str {
|
||||
get;
|
||||
private set;
|
||||
@@ -134,7 +134,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class NSData : NSObject {
|
||||
public sealed class NSData : NSObject {
|
||||
public Bytes bytes {
|
||||
get;
|
||||
private set;
|
||||
@@ -160,7 +160,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class NSDictionary : NSObject {
|
||||
public sealed class NSDictionary : NSObject {
|
||||
public int size {
|
||||
get {
|
||||
return storage.size;
|
||||
@@ -221,7 +221,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class NSDictionaryRaw : NSObject {
|
||||
public sealed class NSDictionaryRaw : NSObject {
|
||||
public int size {
|
||||
get {
|
||||
return storage.size;
|
||||
@@ -255,7 +255,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class NSArray : NSObject {
|
||||
public sealed class NSArray : NSObject {
|
||||
public int length {
|
||||
get {
|
||||
return storage.size;
|
||||
@@ -279,7 +279,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class NSDate : NSObject {
|
||||
public sealed class NSDate : NSObject {
|
||||
public double time {
|
||||
get;
|
||||
private set;
|
||||
@@ -298,7 +298,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class NSError : NSObject {
|
||||
public sealed class NSError : NSObject {
|
||||
public NSString domain {
|
||||
get;
|
||||
private set;
|
||||
@@ -321,7 +321,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class DTTapMessage : NSObject {
|
||||
public sealed class DTTapMessage : NSObject {
|
||||
public NSDictionary plist {
|
||||
get;
|
||||
private set;
|
||||
@@ -658,7 +658,7 @@ namespace Frida.Fruity {
|
||||
return new DTTapMessage ((NSDictionary) decode_value (instance.get_uid ("DTTapMessagePlist"), ctx));
|
||||
}
|
||||
|
||||
private class EncodingContext {
|
||||
private sealed class EncodingContext {
|
||||
public PlistArray objects;
|
||||
|
||||
private Gee.HashMap<string, PlistUid> classes = new Gee.HashMap<string, PlistUid> ();
|
||||
@@ -709,7 +709,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
private class DecodingContext {
|
||||
private sealed class DecodingContext {
|
||||
public PlistArray objects;
|
||||
|
||||
public DecodingContext (PlistArray objects) {
|
||||
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaLLDB", gir_version = "1.0")]
|
||||
namespace Frida.LLDB {
|
||||
public class Client : GDB.Client {
|
||||
public sealed class Client : GDB.Client {
|
||||
public Process? process {
|
||||
get {
|
||||
return _process;
|
||||
@@ -438,7 +438,7 @@ namespace Frida.LLDB {
|
||||
}
|
||||
}
|
||||
|
||||
public class LaunchOptions : Object {
|
||||
public sealed class LaunchOptions : Object {
|
||||
public string[] env {
|
||||
get;
|
||||
set;
|
||||
@@ -457,7 +457,7 @@ namespace Frida.LLDB {
|
||||
}
|
||||
}
|
||||
|
||||
public class Process : Object {
|
||||
public sealed class Process : Object {
|
||||
public uint pid {
|
||||
get;
|
||||
set;
|
||||
@@ -556,7 +556,7 @@ namespace Frida.LLDB {
|
||||
ARM64E = 2,
|
||||
}
|
||||
|
||||
public class Thread : GDB.Thread {
|
||||
public sealed class Thread : GDB.Thread {
|
||||
private const uint PAGE_SIZE = 16384U;
|
||||
private const uint32 THREAD_MAGIC = 0x54485244U;
|
||||
|
||||
@@ -656,7 +656,7 @@ namespace Frida.LLDB {
|
||||
return address & ~((uint64) (PAGE_SIZE - 1));
|
||||
}
|
||||
|
||||
public class Snapshot {
|
||||
public sealed class Snapshot {
|
||||
public uint handle {
|
||||
get;
|
||||
private set;
|
||||
@@ -667,7 +667,7 @@ namespace Frida.LLDB {
|
||||
}
|
||||
}
|
||||
|
||||
public class Frame {
|
||||
public sealed class Frame {
|
||||
public uint64 address {
|
||||
get;
|
||||
private set;
|
||||
@@ -695,7 +695,7 @@ namespace Frida.LLDB {
|
||||
}
|
||||
}
|
||||
|
||||
public class Module : Object {
|
||||
public sealed class Module : Object {
|
||||
public uint64 load_address {
|
||||
get;
|
||||
construct;
|
||||
@@ -719,7 +719,7 @@ namespace Frida.LLDB {
|
||||
);
|
||||
}
|
||||
|
||||
public class Segment {
|
||||
public sealed class Segment {
|
||||
public string name;
|
||||
|
||||
public uint64 vmaddr;
|
||||
@@ -730,7 +730,7 @@ namespace Frida.LLDB {
|
||||
}
|
||||
}
|
||||
|
||||
public class Exception : GDB.Exception {
|
||||
public sealed class Exception : GDB.Exception {
|
||||
public MachExceptionType metype {
|
||||
get;
|
||||
construct;
|
||||
@@ -896,7 +896,7 @@ namespace Frida.LLDB {
|
||||
}
|
||||
}
|
||||
|
||||
public class AppleDyldFields : Object {
|
||||
public sealed class AppleDyldFields : Object {
|
||||
public uint64 all_image_info {
|
||||
get;
|
||||
construct;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
|
||||
namespace Frida.Fruity {
|
||||
public class LockdownClient : Object {
|
||||
public sealed class LockdownClient : Object {
|
||||
public signal void closed ();
|
||||
|
||||
public PlistServiceClient service {
|
||||
|
||||
Loaded 100 of 206 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user