Compare commits

...
54 Commits
Author SHA1 Message Date
Ole André Vadla Ravnås f2e071ed78 subprojects: Prepare for release 2024-06-04 13:41:11 +02:00
Ole André Vadla Ravnås bc7f73b492 subprojects: Bump outdated 2024-06-04 13:38:40 +02:00
f91a3c92fe darwin: Avoid thread_set_state() during injection (#530)
So we don't get killed by the system on e.g. macOS >= 14.5.

We can create the thread in running state. There is no need to keep it
suspended until we have created the dispatch source.

Co-authored-by: Håvard Sørbø <[email protected]>
Co-authored-by: Ole André Vadla Ravnås <[email protected]>
2024-06-04 13:36:31 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 6eacc889cd fruity: Perform RSDCheckin on services that need it
In this way we retain backwards-compatibility for open_channel() of
lockdown services when a CoreDevice tunnel is available.

Co-authored-by: Håvard Sørbø <[email protected]>
2024-06-04 12:27:57 +02:00
Ole André Vadla RavnåsandHåvard Sørbø d21ba21aea fruity: Stop caching the LockdownClient
To avoid issues with multiple consumers.

Co-authored-by: Håvard Sørbø <[email protected]>
2024-06-04 11:34:55 +02:00
Ole André Vadla Ravnås cfcdc26d29 subprojects: Prepare for release 2024-05-31 22:52:22 +02:00
Ole André Vadla Ravnås 69555bbbb6 subprojects: Bump outdated 2024-05-31 22:50:47 +02:00
Ole André Vadla Ravnås d2d014c081 subprojects: Prepare for release 2024-05-31 15:42:49 +02:00
Ole André Vadla Ravnås 8f9c30953b subprojects: Bump outdated 2024-05-31 15:41:33 +02:00
Ole André Vadla Ravnås 2396ad5717 fruity: Remove temporary debug helpers
Useful during bring-up, but not so much anymore.
2024-05-31 14:14:27 +02:00
Ole André Vadla Ravnås ded45c9c93 fruity: Remove the xpc-test program
It has served its purpose. We now have tests that can be run instead.
2024-05-31 14:10:28 +02:00
Ole André Vadla Ravnås 8d375b5e46 fruity: Avoid leaking Posix types into the public API 2024-05-31 14:08:52 +02:00
Ole André Vadla Ravnås 1722429383 subprojects: Bump outdated 2024-05-31 06:45:37 +02:00
Ole André Vadla Ravnås ffd23574a9 submodules: Bump releng 2024-05-31 06:45:36 +02:00
Ole André Vadla Ravnås 5a8bd3fbaf meson: Add new Fruity private requirements to .pc 2024-05-31 00:06:55 +02:00
Ole André Vadla Ravnås 56605717ad meson: Fix build when glib-networking is a subproject 2024-05-30 23:15:15 +02:00
Ole André Vadla Ravnås d8a7c7d3fb subprojects: Bump outdated 2024-05-30 21:58:55 +02:00
Ole André Vadla Ravnås 39725e427b ci: Fix apt-get steps in the native and cross jobs
Need to update the database before installing.
2024-05-30 21:58:13 +02:00
Ole André Vadla Ravnås 7fe3a00543 subprojects: Bump outdated 2024-05-30 21:50:35 +02:00
Ole André Vadla Ravnås 41c31ba0a0 subprojects: Bump outdated 2024-05-30 21:42:28 +02:00
Ole André Vadla Ravnås c8e1ebdb7c ci: Allow Corellium test steps to fail for now
Until we figure out the stability issue.
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 3a678a3553 meson: Fix build when connectivity deps are subprojects
Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 2048115cb3 meson: Change connectivity option default to enabled
So fallbacks trigger, and we build with the same features irrespective
of whether we build with a Frida SDK present.

Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 82a68e55cc fruity: Add RemoteXPC support
With two platform integrations:

- macOS: where we use Apple's tunnel, by talking to remotepairingd and
  creating an assertion to ensure the tunnel is up and stays up for as
  long as we need it. The challenging part here was figuring out the
  device-side RemoteServiceDiscovery (RSD) port inside the tunnel, as
  it appears no API exposes it. Our solution is to ask the kernel for
  a list of TCP sockets, and picking out the ones where the foreign
  address is the device-side IPv6 address inside the tunnel, **and**
  where the process that created the socket is remoted. This seems to
  consistenly result in us finding a single socket, connected to the RSD
  port, but we try all of them in case this behavior ends up changing.
- Linux: where we open our own tunnel, assuming the iDevice has been
  mode-switched (e.g. by usbmuxd), and the Linux CDC NCM driver has been
  patched something along the lines of:
  https://lore.kernel.org/all/[email protected]/T/

We don't yet have a platform integration for Windows, as Apple's
software doesn't currently set up a tunnel. The official driver also
appears to keep the USB device busy, meaning we can't easily trigger
a mode-switch. This is an area that needs more research.

Another area that needs future improvement is that we only support
cabled connectivity on macOS. This should be easy to improve on once we
have updated frida-server and frida-gadget so they listen on tunnel
interfaces whenever they appear.

Kudos to @doronz88 for figuring out most of the protocol bits that we
needed.

Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø e0d6c29c41 meson: Add wrap for lwip
Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 1f820ae2ac meson: Add wrap for ngtcp2
Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø c0bc5f5bd9 base: Add helpers for handling JSON and GLib.Variant
Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 7ab0cf75ea fruity: Fix spawn() on jailed iOS 17
The jailed equivalent of 827eee33cc.

Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 2175cc756a dtx: Use more appropriate GValue setter for NSObject
Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 90d60683dd dtx: Make DTXArgumentList elements visible to consumers
Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø cf09ba46e4 dtx: Allow notification payload to be of any type
The value is not always an NSDictionary, e.g. in case of a DTTapMessage.

Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø ed9fcb10c1 dtx: Fix channel code interpretation for inbound invokes
Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 333ca2f852 dtx: Bump max message size to 128 MB
Screenshots can be quite large, and we might in theory be asked to fetch
large files.

Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø c9e541cc0e keyed-archive: Add support for decoding DTTapMessage
And its subclasses.

Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 3e86270d77 keyed-archive: Add support for encoding NSArray
Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 8a21929415 keyed-archive: Add NSArray.add_object()
Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 4865ea07eb keyed-archive: Add support for decoding NSData
Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 28f7895704 keyed-archive: Improve NSNumber support
So boolean/float/double values are treated distinctly from int64.

Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 859d6cd7de plist: Fix support for float and double in to_binary()
Co-authored-by: Håvard Sørbø <[email protected]>
2024-05-30 21:28:33 +02:00
Ole André Vadla Ravnås b71c861b1d subprojects: Bump outdated 2024-05-30 20:51:53 +02:00
Ole André Vadla Ravnås b486936b33 submodules: Bump releng 2024-05-30 20:51:53 +02:00
Ole André Vadla Ravnås 5b587f587f base: Add Numeric.int64_{hash,equal}() 2024-05-29 23:18:13 +02:00
Ole André Vadla Ravnås 39e2c7bf81 subprojects: Prepare for release 2024-05-21 12:50:31 +02:00
Ole André Vadla Ravnås 2b82c21df1 subprojects: Bump outdated 2024-05-21 12:48:55 +02:00
Ole André Vadla Ravnås e45989dbdf subprojects: Prepare for release 2024-05-20 22:54:26 +02:00
Ole André Vadla Ravnås 204b16a4b7 compat: Escape spaces in depfile paths
Quoting isn't supported, so we should be escaping the spaces instead.
2024-05-20 22:50:29 +02:00
Ole André Vadla Ravnås d9f33a918e meson: Find DbgHelp and SymSrv using Gum's variables 2024-05-20 22:41:48 +02:00
Ole André Vadla Ravnås 082b100ab9 subprojects: Bump outdated 2024-05-20 22:40:31 +02:00
Ole André Vadla Ravnås 20cdf64312 meson: Fix vapidir exported in our .pc 2024-05-20 22:39:15 +02:00
Ole André Vadla Ravnås 0bb558e2a1 meson: Refactor the (un)installed variables logic 2024-05-20 22:37:59 +02:00
Ole André Vadla Ravnås 04f22126a7 subprojects: Prepare for release 2024-05-18 23:04:59 +02:00
Ole André Vadla Ravnås 59deab2ea9 subprojects: Bump outdated 2024-05-18 22:57:58 +02:00
Ole André Vadla Ravnås 1b9e347650 submodules: Bump releng 2024-05-18 22:57:58 +02:00
Ole André Vadla Ravnås 5e149a3f2d compat: Forward yielding built-in options when subproject
So that the parent project's machine-neutral built-in options such as
`prefix` are used.
2024-05-18 22:50:57 +02:00
48 changed files with 10113 additions and 363 deletions

No files matched your search

+8 -2
View File
@@ -42,7 +42,9 @@ jobs:
run: sudo security authorizationdb write system.privilege.taskport allow
- name: Install gcc-multilib
if: matrix.id == 'linux-x86'
run: sudo apt-get install gcc-multilib lib32stdc++-11-dev
run: |
sudo apt-get update
sudo apt-get install gcc-multilib lib32stdc++-11-dev
- name: Build
if: ${{ startsWith(matrix.id, 'windows-') }}
run: |
@@ -87,7 +89,9 @@ jobs:
with:
submodules: recursive
- name: Install toolchain
run: sudo apt-get install ${{ matrix.pkg }}
run: |
sudo apt-get update
sudo apt-get install ${{ matrix.pkg }}
- name: Build
run: |
./configure ${{ matrix.opts }} ${{ env.FRIDA_CORE_OPTIONS }}
@@ -177,6 +181,7 @@ jobs:
tar -C /tmp/pkg -czf /tmp/runner.tar.gz .
- name: Test on Corellium iOS device
if: matrix.id == 'ios-arm64'
continue-on-error: true
uses: frida/corellium-action@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
@@ -192,6 +197,7 @@ jobs:
./frida-tests
- name: Test on Corellium Android device
if: matrix.id == 'android-arm64'
continue-on-error: true
uses: frida/corellium-action@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
+7 -5
View File
@@ -432,7 +432,7 @@ def compile(privdir: Path, state: State):
path = Path(raw_path)
if not path.is_absolute():
path = Path(os.path.relpath(workdir / path, top_builddir))
input_entries.append(quote(path.as_posix()))
input_entries.append(escape_depfile_path(path.as_posix()))
depfile_lines.append(f"{output_relpath}: {' '.join(input_entries)}")
(state.builddir / DEPFILE_FILENAME).write_text("\n".join(depfile_lines), encoding="utf-8")
@@ -480,6 +480,10 @@ def option_should_be_forwarded(k: "OptionKey",
return False
if not str(v.value):
return False
if not is_for_child and role == "subproject" and k.subproject in {"", our_project_id}:
if not coredata.BUILTIN_OPTIONS[k.as_root()].yielding:
return k.subproject == our_project_id
return True
if k.module == "python":
if k.name == "install_env" and v.value == "prefix":
@@ -519,10 +523,8 @@ def scrub_windows_devenv_dirs_from_path(raw_path: str, env: Mapping[str, str]) -
return ";".join(clean_entries)
def quote(path: str) -> str:
if " " not in path:
return path
return "\"" + path.replace ("\"", "\\\"") + "\""
def escape_depfile_path(path: str) -> str:
return path.replace(" ", "\\ ")
def query_releng_location(role: Role) -> Path:
+51
View File
@@ -0,0 +1,51 @@
#include "frida-darwin.h"
gpointer
_frida_dispatch_retain (gpointer object)
{
dispatch_retain (object);
return object;
}
void
_frida_xpc_connection_set_event_handler (xpc_connection_t connection, FridaXpcHandler handler, gpointer user_data)
{
xpc_connection_set_event_handler (connection, ^(xpc_object_t object)
{
handler (object, user_data);
});
}
void
_frida_xpc_connection_send_message_with_reply (xpc_connection_t connection, xpc_object_t message, dispatch_queue_t replyq,
FridaXpcHandler handler, gpointer user_data, GDestroyNotify notify)
{
xpc_connection_send_message_with_reply (connection, message, replyq, ^(xpc_object_t object)
{
handler (object, user_data);
if (notify != NULL)
notify (user_data);
});
}
gchar *
_frida_xpc_object_to_string (xpc_object_t object)
{
gchar * result;
char * str;
str = xpc_copy_description (object);
result = g_strdup (str);
free (str);
return result;
}
gboolean
_frida_xpc_dictionary_apply (xpc_object_t dict, FridaXpcDictionaryApplier applier, gpointer user_data)
{
return xpc_dictionary_apply (dict, ^bool (const char * key, xpc_object_t val)
{
return applier (key, val, user_data);
});
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef __FRIDA_DARWIN_H__
#define __FRIDA_DARWIN_H__
#ifdef HAVE_MACOS
#include <glib.h>
#include <xpc/xpc.h>
typedef void (* FridaXpcHandler) (xpc_object_t object, gpointer user_data);
typedef gboolean (* FridaXpcDictionaryApplier) (const gchar * key, xpc_object_t val, gpointer user_data);
gpointer _frida_dispatch_retain (gpointer object);
void _frida_xpc_connection_set_event_handler (xpc_connection_t connection, FridaXpcHandler handler, gpointer user_data);
void _frida_xpc_connection_send_message_with_reply (xpc_connection_t connection, xpc_object_t message, dispatch_queue_t replyq,
FridaXpcHandler handler, gpointer user_data, GDestroyNotify notify);
gchar * _frida_xpc_object_to_string (xpc_object_t object);
gboolean _frida_xpc_dictionary_apply (xpc_object_t dict, FridaXpcDictionaryApplier applier, gpointer user_data);
#endif
#endif
+15
View File
@@ -9,9 +9,18 @@ base_sources = [
'socket.vala',
'socket-glue.c',
'buffer.vala',
'value.vala',
]
extra_vala_args = []
if host_os == 'macos'
base_sources += [
'xpc.vala',
'frida-darwin.c',
]
endif
extra_deps = []
if host_os_family != 'windows'
extra_vala_args += '--pkg=gio-unix-2.0'
@@ -22,6 +31,12 @@ base_vala_args = [gum_vala_args, '--pkg=gio-2.0', '--pkg=json-glib-1.0']
if nice_dep.found()
base_vala_args += '--pkg=nice'
endif
if host_os_family == 'darwin'
base_vala_args += [
'--pkg=darwin-gcd',
'--pkg=darwin-xpc',
]
endif
base = static_library('frida-base-' + api_version, base_sources,
c_args: frida_component_cflags,
+11
View File
@@ -2079,6 +2079,17 @@ namespace Frida {
}
namespace Numeric {
public uint int64_hash (int64? val) {
uint64 v = (uint64) val.abs ();
return (uint) ((v >> 32) ^ (v & 0xffffffffU));
}
public bool int64_equal (int64? val_a, int64? val_b) {
int64 a = val_a;
int64 b = val_b;
return a == b;
}
public uint uint64_hash (uint64? val) {
uint64 v = val;
return (uint) ((v >> 32) ^ (v & 0xffffffffU));
+392
View File
@@ -0,0 +1,392 @@
namespace Frida {
public interface ObjectBuilder : Object {
public abstract unowned ObjectBuilder begin_dictionary ();
public abstract unowned ObjectBuilder set_member_name (string name);
public abstract unowned ObjectBuilder end_dictionary ();
public abstract unowned ObjectBuilder begin_array ();
public abstract unowned ObjectBuilder end_array ();
public abstract unowned ObjectBuilder add_null_value ();
public abstract unowned ObjectBuilder add_bool_value (bool val);
public abstract unowned ObjectBuilder add_int64_value (int64 val);
public abstract unowned ObjectBuilder add_uint64_value (uint64 val);
public abstract unowned ObjectBuilder add_data_value (Bytes val);
public abstract unowned ObjectBuilder add_string_value (string val);
public abstract unowned ObjectBuilder add_uuid_value (string val);
public abstract unowned ObjectBuilder add_raw_value (Bytes val);
public abstract Bytes build ();
}
public interface ObjectReader : Object {
public abstract bool has_member (string name) throws Error;
public abstract unowned ObjectReader read_member (string name) throws Error;
public abstract unowned ObjectReader end_member ();
public abstract uint count_elements () throws Error;
public abstract unowned ObjectReader read_element (uint index) throws Error;
public abstract unowned ObjectReader end_element () throws Error;
public abstract bool get_bool_value () throws Error;
public abstract uint8 get_uint8_value () throws Error;
public abstract uint16 get_uint16_value () throws Error;
public abstract int64 get_int64_value () throws Error;
public abstract uint64 get_uint64_value () throws Error;
public abstract Bytes get_data_value () throws Error;
public abstract unowned string get_string_value () throws Error;
public abstract unowned string get_uuid_value () throws Error;
}
public class VariantReader : Object, ObjectReader {
public Variant root_object {
get {
return scopes.peek_head ().val;
}
}
public Variant current_object {
get {
return scopes.peek_tail ().val;
}
}
private Gee.Deque<Scope> scopes = new Gee.ArrayQueue<Scope> ();
public VariantReader (Variant v) {
push_scope (v);
}
public bool has_member (string name) throws Error {
var scope = peek_scope ();
if (scope.dict == null)
throw new Error.PROTOCOL ("Dictionary expected, but at %s", scope.val.print (true));
return scope.dict.contains (name);
}
public unowned ObjectReader read_member (string name) throws Error {
var scope = peek_scope ();
if (scope.dict == null)
throw new Error.PROTOCOL ("Dictionary expected, but at %s", scope.val.print (true));
Variant? v = scope.dict.lookup_value (name, null);
if (v == null)
throw new Error.PROTOCOL ("Key '%s' not found in dictionary: %s", name, scope.val.print (true));
push_scope (v);
return this;
}
public unowned ObjectReader end_member () {
pop_scope ();
return this;
}
public uint count_elements () throws Error {
var scope = peek_scope ();
scope.check_array ();
return (uint) scope.val.n_children ();
}
public unowned ObjectReader read_element (uint index) throws Error {
var scope = peek_scope ();
scope.check_array ();
push_scope (scope.val.get_child_value (index).get_variant ());
return this;
}
public unowned ObjectReader end_element () throws Error {
pop_scope ();
return this;
}
public bool get_bool_value () throws Error {
return peek_scope ().get_value (VariantType.BOOLEAN).get_boolean ();
}
public uint8 get_uint8_value () throws Error {
return peek_scope ().get_value (VariantType.BYTE).get_byte ();
}
public uint16 get_uint16_value () throws Error {
return peek_scope ().get_value (VariantType.UINT16).get_uint16 ();
}
public int64 get_int64_value () throws Error {
return peek_scope ().get_value (VariantType.INT64).get_int64 ();
}
public uint64 get_uint64_value () throws Error {
return peek_scope ().get_value (VariantType.UINT64).get_uint64 ();
}
public Bytes get_data_value () throws Error {
return peek_scope ().get_value (new VariantType.array (VariantType.BYTE)).get_data_as_bytes ();
}
public unowned string get_string_value () throws Error {
return peek_scope ().get_value (VariantType.STRING).get_string ();
}
public unowned string get_uuid_value () throws Error {
return peek_scope ().get_value (VariantType.STRING).get_string (); // TODO: Use a tuple to avoid ambiguity.
}
private void push_scope (Variant v) {
scopes.offer_tail (new Scope (v));
}
private Scope peek_scope () {
return scopes.peek_tail ();
}
private Scope pop_scope () {
return scopes.poll_tail ();
}
private class Scope {
public Variant val;
public VariantDict? dict;
public bool is_array = false;
public Scope (Variant v) {
val = v;
VariantType t = v.get_type ();
if (t.equal (VariantType.VARDICT))
dict = new VariantDict (v);
else if (t.is_subtype_of (VariantType.ARRAY))
is_array = true;
}
public Variant get_value (VariantType expected_type) throws Error {
if (!val.get_type ().equal (expected_type)) {
throw new Error.PROTOCOL ("Expected type '%s', got '%s'",
(string) expected_type.peek_string (),
(string) val.get_type ().peek_string ());
}
return val;
}
public void check_array () throws Error {
if (!is_array)
throw new Error.PROTOCOL ("Array expected, but at %s", val.print (true));
}
}
}
public class JsonObjectBuilder : Object, ObjectBuilder {
private Json.Builder builder = new Json.Builder ();
private Gee.Map<string, Bytes> raw_values = new Gee.HashMap<string, Bytes> ();
public unowned ObjectBuilder begin_dictionary () {
builder.begin_object ();
return this;
}
public unowned ObjectBuilder set_member_name (string name) {
builder.set_member_name (name);
return this;
}
public unowned ObjectBuilder end_dictionary () {
builder.end_object ();
return this;
}
public unowned ObjectBuilder begin_array () {
builder.begin_array ();
return this;
}
public unowned ObjectBuilder end_array () {
builder.end_array ();
return this;
}
public unowned ObjectBuilder add_null_value () {
builder.add_null_value ();
return this;
}
public unowned ObjectBuilder add_bool_value (bool val) {
builder.add_boolean_value (val);
return this;
}
public unowned ObjectBuilder add_int64_value (int64 val) {
builder.add_int_value (val);
return this;
}
public unowned ObjectBuilder add_uint64_value (uint64 val) {
builder.add_int_value ((int64) val);
return this;
}
public unowned ObjectBuilder add_data_value (Bytes val) {
builder.add_string_value (Base64.encode (val.get_data ()));
return this;
}
public unowned ObjectBuilder add_string_value (string val) {
builder.add_string_value (val);
return this;
}
public unowned ObjectBuilder add_uuid_value (string val) {
builder.add_string_value (val);
return this;
}
public unowned ObjectBuilder add_raw_value (Bytes val) {
string uuid = Uuid.string_random ();
builder.add_string_value (uuid);
raw_values[uuid] = val;
return this;
}
public Bytes build () {
string json = Json.to_string (builder.get_root (), false);
foreach (var e in raw_values.entries) {
unowned string uuid = e.key;
Bytes val = e.value;
unowned string raw_str = (string) val.get_data ();
string str = raw_str[:(long) val.get_size ()];
json = json.replace ("\"" + uuid + "\"", str);
}
return new Bytes (json.data);
}
}
public class JsonObjectReader : Object, ObjectReader {
private Json.Reader reader;
public JsonObjectReader (string json) throws Error {
try {
reader = new Json.Reader (Json.from_string (json));
} catch (GLib.Error e) {
throw new Error.INVALID_ARGUMENT ("%s", e.message);
}
}
public bool has_member (string name) throws Error {
bool result = reader.read_member (name);
reader.end_member ();
return result;
}
public unowned ObjectReader read_member (string name) throws Error {
if (!reader.read_member (name))
throw_dict_access_error ();
return this;
}
public unowned ObjectReader end_member () {
reader.end_member ();
return this;
}
[NoReturn]
private void throw_dict_access_error () throws Error {
GLib.Error e = reader.get_error ();
reader.end_member ();
throw new Error.PROTOCOL ("%s", e.message);
}
public uint count_elements () throws Error {
int n = reader.count_elements ();
if (n == -1)
throw_array_access_error ();
return n;
}
public unowned ObjectReader read_element (uint index) throws Error {
if (!reader.read_element (index)) {
GLib.Error e = reader.get_error ();
reader.end_element ();
throw new Error.PROTOCOL ("%s", e.message);
}
return this;
}
public unowned ObjectReader end_element () throws Error {
reader.end_element ();
return this;
}
[NoReturn]
private void throw_array_access_error () throws Error {
GLib.Error e = reader.get_error ();
reader.end_element ();
throw new Error.PROTOCOL ("%s", e.message);
}
public bool get_bool_value () throws Error {
bool v = reader.get_boolean_value ();
if (!v)
maybe_throw_value_access_error ();
return v;
}
public uint8 get_uint8_value () throws Error {
int64 v = get_int64_value ();
if (v < 0 || v > uint8.MAX)
throw new Error.PROTOCOL ("Invalid uint8");
return (uint8) v;
}
public uint16 get_uint16_value () throws Error {
int64 v = get_int64_value ();
if (v < 0 || v > uint16.MAX)
throw new Error.PROTOCOL ("Invalid uint16");
return (uint16) v;
}
public int64 get_int64_value () throws Error {
int64 v = reader.get_int_value ();
if (v == 0)
maybe_throw_value_access_error ();
return v;
}
public uint64 get_uint64_value () throws Error {
int64 v = get_int64_value ();
if (v < 0)
throw new Error.PROTOCOL ("Invalid uint64");
return v;
}
public Bytes get_data_value () throws Error {
return new Bytes (Base64.decode (get_string_value ()));
}
public unowned string get_string_value () throws Error {
unowned string? v = reader.get_string_value ();
if (v == null)
maybe_throw_value_access_error ();
return v;
}
public unowned string get_uuid_value () throws Error {
return get_string_value ();
}
private void maybe_throw_value_access_error () throws Error {
GLib.Error? e = reader.get_error ();
if (e == null)
return;
reader.end_member ();
throw new Error.PROTOCOL ("%s", e.message);
}
}
}
+236
View File
@@ -0,0 +1,236 @@
namespace Frida {
public class XpcClient : Object {
public signal void message (Darwin.Xpc.Object obj);
public State state {
get {
return _state;
}
}
public Darwin.Xpc.Connection connection {
get;
construct;
}
public Darwin.GCD.DispatchQueue queue {
get;
construct;
}
private State _state;
private string? close_reason;
private MainContext main_context;
public enum State {
OPEN,
CLOSING,
CLOSED,
}
public static XpcClient make_for_mach_service (string name, Darwin.GCD.DispatchQueue queue) {
return new XpcClient (Darwin.Xpc.Connection.create_mach_service (name, queue, 0), queue);
}
public XpcClient (Darwin.Xpc.Connection connection, Darwin.GCD.DispatchQueue queue) {
Object (connection: connection, queue: queue);
}
construct {
main_context = MainContext.ref_thread_default ();
connection.set_event_handler (on_event);
connection.activate ();
}
public override void dispose () {
if (close_reason != null) {
change_state (CLOSED);
} else {
change_state (CLOSING);
this.ref ();
connection.cancel ();
}
base.dispose ();
}
public async Darwin.Xpc.Object request (Darwin.Xpc.Object message, Cancellable? cancellable) throws Error, IOError {
Darwin.Xpc.Object? reply = null;
connection.send_message_with_reply (message, queue, r => {
schedule_on_frida_thread (() => {
reply = r;
request.callback ();
return Source.REMOVE;
});
});
yield;
if (reply.type == Darwin.Xpc.Error.TYPE) {
var e = (Darwin.Xpc.Error) reply;
throw new Error.NOT_SUPPORTED ("%s", e.get_string (Darwin.Xpc.Error.KEY_DESCRIPTION));
}
return reply;
}
private void change_state (State new_state) {
_state = new_state;
notify_property ("state");
}
private void on_event (Darwin.Xpc.Object obj) {
schedule_on_frida_thread (() => {
if (obj.type == Darwin.Xpc.Error.TYPE) {
var e = (Darwin.Xpc.Error) obj;
close_reason = e.get_string (Darwin.Xpc.Error.KEY_DESCRIPTION);
if (state == CLOSING) {
change_state (CLOSED);
unref ();
}
} else {
message (obj);
}
return Source.REMOVE;
});
}
private void schedule_on_frida_thread (owned SourceFunc function) {
var source = new IdleSource ();
source.set_callback ((owned) function);
source.attach (main_context);
}
}
public class XpcObjectReader {
public Darwin.Xpc.Object root_object {
get {
return scopes.peek_head ().object;
}
}
public Darwin.Xpc.Object current_object {
get {
return scopes.peek_tail ().object;
}
}
private Gee.Deque<Scope> scopes = new Gee.ArrayQueue<Scope> ();
public XpcObjectReader (Darwin.Xpc.Object obj) {
push_scope (obj);
}
public bool has_member (string name) throws Error {
return peek_scope ().get_dictionary ().get_value (name) != null;
}
public bool try_read_member (string name) throws Error {
var scope = peek_scope ();
var dict = scope.get_dictionary ();
var val = dict.get_value (name);
if (val == null)
return false;
push_scope (val);
return true;
}
public unowned XpcObjectReader read_member (string name) throws Error {
var scope = peek_scope ();
var dict = scope.get_dictionary ();
var val = dict.get_value (name);
if (val == null)
throw new Error.PROTOCOL ("Key '%s' not found in dictionary: %s", name, scope.object.to_string ());
push_scope (val);
return this;
}
public unowned XpcObjectReader end_member () {
pop_scope ();
return this;
}
public size_t count_elements () throws Error {
return peek_scope ().get_array ().count;
}
public unowned XpcObjectReader read_element (size_t index) throws Error {
push_scope (peek_scope ().get_array ().get_value (index));
return this;
}
public unowned XpcObjectReader end_element () throws Error {
pop_scope ();
return this;
}
public bool get_bool_value () throws Error {
return peek_scope ().get_object<Darwin.Xpc.Bool> (Darwin.Xpc.Bool.TYPE).get_value ();
}
public int64 get_int64_value () throws Error {
return peek_scope ().get_object<Darwin.Xpc.Int64> (Darwin.Xpc.Int64.TYPE).get_value ();
}
public uint64 get_uint64_value () throws Error {
return peek_scope ().get_object<Darwin.Xpc.UInt64> (Darwin.Xpc.UInt64.TYPE).get_value ();
}
public unowned string get_string_value () throws Error {
return peek_scope ().get_object<Darwin.Xpc.String> (Darwin.Xpc.String.TYPE).get_string_ptr ();
}
public unowned string get_error_description () throws Error {
var error = peek_scope ().get_object<Darwin.Xpc.Error> (Darwin.Xpc.Error.TYPE);
return error.get_string (Darwin.Xpc.Error.KEY_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);
}
private void push_scope (Darwin.Xpc.Object obj) {
scopes.offer_tail (new Scope (obj));
}
private Scope peek_scope () {
return scopes.peek_tail ();
}
private Scope pop_scope () {
return scopes.poll_tail ();
}
private class Scope {
public Darwin.Xpc.Object object;
private unowned Darwin.Xpc.Type type;
public Scope (Darwin.Xpc.Object obj) {
object = obj;
type = obj.type;
}
public unowned T get_object<T> (Darwin.Xpc.Type expected_type) throws Error {
if (type != expected_type)
throw new Error.PROTOCOL ("Expected type '%s', got '%s'", expected_type.name, type.name);
return object;
}
public unowned Darwin.Xpc.Array get_array () throws Error {
return get_object<Darwin.Xpc.Array> (Darwin.Xpc.Array.TYPE);
}
public unowned Darwin.Xpc.Dictionary get_dictionary () throws Error {
return get_object<Darwin.Xpc.Dictionary> (Darwin.Xpc.Dictionary.TYPE);
}
}
}
}
+33 -5
View File
@@ -413,7 +413,7 @@ else
endif
uninstalled_girdir = meson.current_build_dir() / 'src'
vapidir = get_option('datadir') / 'vala' / 'vapi'
vapidir = get_option('prefix') / get_option('datadir') / 'vala' / 'vapi'
gum_vala_args = [
'--pkg=frida-gum-1.0',
@@ -437,6 +437,25 @@ backend_deps_private = []
backend_reqs_private = []
backend_libs_private = []
openssl_options = [
'cli=disabled',
]
if host_os_family == 'windows' and cc.get_argument_syntax() != 'msvc'
openssl_options += 'asm=disabled'
endif
openssl_dep = dependency('openssl',
required: have_fruity_backend or get_option('connectivity').enabled(),
modules: cc.get_argument_syntax() == 'msvc' ? ['OpenSSL::SSL'] : [],
default_options: openssl_options,
)
if have_fruity_backend
foreach dep : ['libnghttp2', 'libngtcp2', 'libngtcp2_crypto_quictls', 'lwip']
backend_deps_private += dependency(dep)
backend_reqs_private += dep
endforeach
endif
if quickjs_dep.found()
backend_deps_private += quickjs_dep
backend_reqs_private += 'quickjs'
@@ -456,8 +475,19 @@ else
termux_elf_cleaner = []
endif
tls_provider_dep = dependency('gioopenssl', required: get_option('connectivity'))
tls_provider_dep = dependency('gioopenssl', required: get_option('connectivity'), default_options: [
'gnutls=disabled',
'openssl=enabled',
'libproxy=disabled',
'gnome_proxy=disabled',
'tests=false',
])
tls_provider_vala_args = []
if tls_provider_dep.found()
tls_provider_vala_args += [
'--pkg=gioopenssl',
'--vapidir=' + tls_provider_dep.get_variable('vapidir'),
]
cdata.set('HAVE_GIOOPENSSL', 1)
vala_flags += ['--define=HAVE_GIOOPENSSL']
backend_deps_private += tls_provider_dep
@@ -473,7 +503,6 @@ nice_dep = dependency('nice', required: get_option('connectivity'), default_opti
'introspection=disabled',
])
if nice_dep.found()
openssl_dep = dependency('openssl')
usrsctp_dep = dependency('usrsctp', default_options: [
'sctp_inet=false',
'sctp_inet6=false',
@@ -489,7 +518,6 @@ if nice_dep.found()
cdata.set('HAVE_SCONN_LEN', 1)
endif
else
openssl_dep = []
usrsctp_dep = []
endif
@@ -500,7 +528,7 @@ if host_os_family == 'darwin'
backend_libs_private += ['-Wl,-framework,Foundation', '-lbsm']
endif
if host_os == 'macos'
backend_libs_private += ['-Wl,-framework,AppKit']
backend_libs_private += ['-Wl,-framework,AppKit', '-Wl,-framework,IOKit']
endif
if host_os in ['ios', 'tvos']
backend_libs_private += ['-Wl,-framework,CoreGraphics', '-Wl,-framework,UIKit']
+1 -11
View File
@@ -101,16 +101,6 @@ option('agent_emulated_legacy',
description: 'Prebuilt agent to embed for use on legacy emulated targets'
)
option('agent_dbghelp_prefix',
type: 'string',
description: 'Location of DbgHelp binaries to embed alongside agent (Windows only)'
)
option('agent_symsrv_prefix',
type: 'string',
description: 'Location of SymSrv binaries to embed alongside agent (Windows only)'
)
option('gadget',
type: 'feature',
value: 'auto',
@@ -137,7 +127,7 @@ option('inject',
option('connectivity',
type: 'feature',
value: 'auto',
value: 'enabled',
description: 'Internet connectivity features (TLS and ICE support)'
)
+1 -1
View File
@@ -20,7 +20,7 @@ if tls_provider_dep.found()
endif
raw_portal = executable('frida-portal-raw', portal_sources,
vala_args: [core_vala_args, '--pkg=posix'],
vala_args: [core_vala_args, tls_provider_vala_args, '--pkg=posix'],
link_args: extra_link_args,
link_depends: extra_link_depends,
dependencies: [core_dep] + extra_deps,
+1 -1
Submodule releng updated: 56b262207c...b0e46f7b69.
+15 -15
View File
@@ -90,17 +90,25 @@ else
endif
uninstalled_vapidir = uninstalled_incdir
uninstalled_variables = {
'frida_includedir': uninstalled_incdir,
'frida_girdir': uninstalled_girdir,
'frida_vapidir': uninstalled_vapidir,
}
installed_variables = {
'frida_includedir': '${includedir}',
'frida_girdir': girdir,
'frida_vapidir': vapidir,
}
core_public_dep = declare_dependency(
sources: [core_public_h, core_public_gir, core_public_vapi_stamp, core_public_extra_headers],
include_directories: include_directories('.'),
link_args: backend_libs_private,
link_with: core_public_lib,
dependencies: core_deps,
variables: {
'frida_includedir': uninstalled_incdir,
'frida_girdir': uninstalled_girdir,
'frida_vapidir': uninstalled_vapidir,
},
variables: uninstalled_variables,
)
pkg = import('pkgconfig')
@@ -115,16 +123,8 @@ pkg.generate(
libraries: core_public_lib,
libraries_private: backend_libs_private,
extra_cflags: ['-I${frida_includedir}'],
variables: {
'frida_includedir': '${includedir}',
'frida_girdir': girdir,
'frida_vapidir': vapidir,
},
uninstalled_variables: {
'frida_includedir': uninstalled_incdir,
'frida_girdir': uninstalled_girdir,
'frida_vapidir': uninstalled_vapidir,
},
variables: installed_variables,
uninstalled_variables: uninstalled_variables,
)
meson.override_dependency(f'frida-core-@api_version@', core_public_dep)
+60 -7
View File
@@ -428,6 +428,8 @@ static void frida_agent_context_emit_mach_stub_code (FridaAgentContext * self, g
static void frida_agent_context_emit_pthread_stub_code (FridaAgentContext * self, guint8 * code, GumDarwinModuleResolver * resolver,
GumDarwinMapper * mapper);
static gboolean frida_convert_thread_state_for_task (mach_port_t task, thread_state_flavor_t flavor, gconstpointer in_state,
mach_msg_type_number_t in_state_count, gpointer out_state, mach_msg_type_number_t * out_state_count, GError ** error);
static mach_port_t frida_obtain_thread_port_for_thread_id (mach_port_t task, uint64_t thread_id);
static kern_return_t frida_get_thread_state (mach_port_t thread, thread_state_flavor_t flavor, gpointer state,
mach_msg_type_number_t * count);
@@ -2583,16 +2585,24 @@ static gboolean
frida_inject_instance_start_thread (FridaInjectInstance * self, GError ** error)
{
gboolean success = FALSE;
thread_state_t thread_state;
mach_msg_type_number_t thread_state_count;
kern_return_t kr;
const gchar * failed_operation;
FridaHelperContext * ctx = self->backend->context;
dispatch_source_t source;
kr = thread_create (self->task, &self->thread);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_create");
thread_state = g_alloca (self->thread_state_count * sizeof (natural_t));
thread_state_count = self->thread_state_count;
kr = frida_set_thread_state (self->thread, self->thread_state_flavor, self->thread_state_data, self->thread_state_count);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "set_thread_state");
if (!frida_convert_thread_state_for_task (self->task, self->thread_state_flavor, self->thread_state_data, self->thread_state_count,
thread_state, &thread_state_count, error))
{
return FALSE;
}
kr = thread_create_running (self->task, self->thread_state_flavor, thread_state, thread_state_count, &self->thread);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_create");
source = dispatch_source_create (DISPATCH_SOURCE_TYPE_MACH_SEND, self->thread, DISPATCH_MACH_SEND_DEAD, ctx->dispatch_queue);
self->thread_monitor_source = source;
@@ -2601,9 +2611,6 @@ frida_inject_instance_start_thread (FridaInjectInstance * self, GError ** error)
dispatch_source_set_event_handler_f (source, frida_inject_instance_on_mach_thread_dead);
dispatch_resume (source);
kr = thread_resume (self->thread);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_resume");
success = TRUE;
goto beach;
@@ -5072,6 +5079,52 @@ frida_agent_context_emit_arm64_pthread_stub_body (FridaAgentContext * self, Frid
#endif
static gboolean
frida_convert_thread_state_for_task (mach_port_t task, thread_state_flavor_t flavor, gconstpointer in_state,
mach_msg_type_number_t in_state_count, gpointer out_state, mach_msg_type_number_t * out_state_count,
GError ** error)
{
gboolean success = FALSE;
kern_return_t kr;
const gchar * failed_operation;
thread_act_array_t threads = NULL;
mach_msg_type_number_t thread_count = 0;
kr = task_threads (task, &threads, &thread_count);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "task_threads");
kr = frida_convert_thread_state (threads[0], FRIDA_CONVERT_THREAD_STATE_OUT, flavor, in_state, in_state_count,
out_state, out_state_count);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_convert_thread_state");
success = TRUE;
goto beach;
mach_failure:
{
g_set_error (error,
FRIDA_ERROR,
FRIDA_ERROR_NOT_SUPPORTED,
"Unexpected error while converting thread state for task (%s returned '%s')",
failed_operation, mach_error_string (kr));
goto beach;
}
beach:
{
mach_msg_type_number_t i;
if (threads != NULL)
{
for (i = 0; i != thread_count; i++)
mach_port_deallocate (mach_task_self (), threads[i]);
vm_deallocate (mach_task_self (), (vm_address_t) threads, thread_count * sizeof (thread_t));
}
return success;
}
}
static mach_port_t
frida_obtain_thread_port_for_thread_id (mach_port_t task, uint64_t thread_id)
{
+4 -4
View File
@@ -86,7 +86,7 @@ namespace Frida {
}
}
public class DroidyHostSessionProvider : Object, HostSessionProvider, ChannelProvider {
public class DroidyHostSessionProvider : Object, HostSessionProvider, HostChannelProvider {
public string id {
get { return device_details.serial; }
}
@@ -162,7 +162,7 @@ namespace Frida {
agent_session_detached (id, reason, crash);
}
public async IOStream open_channel (string address, Cancellable? cancellable = null) throws Error, IOError {
public async IOStream open_channel (string address, Cancellable? cancellable) throws Error, IOError {
if (address.contains (":")) {
Droidy.Client client = null;
try {
@@ -188,7 +188,7 @@ namespace Frida {
construct;
}
public weak ChannelProvider channel_provider {
public weak HostChannelProvider channel_provider {
get;
construct;
}
@@ -216,7 +216,7 @@ namespace Frida {
private const double MIN_SERVER_CHECK_INTERVAL = 5.0;
private const string GADGET_APP_ID = "re.frida.Gadget";
public DroidyHostSession (Droidy.DeviceDetails device_details, ChannelProvider channel_provider) {
public DroidyHostSession (Droidy.DeviceDetails device_details, HostChannelProvider channel_provider) {
Object (
device_details: device_details,
channel_provider: channel_provider
+2 -2
View File
@@ -37,12 +37,12 @@ def main(argv):
shutil.copy(agent, embedded_agent)
if agent_dbghelp_prefix is not None:
shutil.copy(agent_dbghelp_prefix / f"dbghelp-{flavor}.dll", embedded_dbghelp)
shutil.copy(agent_dbghelp_prefix / flavor / "dbghelp.dll", embedded_dbghelp)
else:
embedded_dbghelp.write_bytes(b"")
if agent_symsrv_prefix is not None:
shutil.copy(agent_symsrv_prefix / f"symsrv-{flavor}.dll", embedded_symsrv)
shutil.copy(agent_symsrv_prefix / flavor / "symsrv.dll", embedded_symsrv)
else:
embedded_symsrv.write_bytes(b"")
else:
+100 -1
View File
@@ -530,6 +530,7 @@ 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;
internal Device (DeviceManager? manager, string id, string name, HostSessionProviderKind kind, HostSessionProvider provider,
@@ -1228,7 +1229,7 @@ namespace Frida {
public async IOStream open_channel (string address, Cancellable? cancellable = null) throws Error, IOError {
check_open ();
var channel_provider = provider as ChannelProvider;
var channel_provider = provider as HostChannelProvider;
if (channel_provider == null)
throw new Error.NOT_SUPPORTED ("Channels are not supported by this device");
@@ -1249,6 +1250,38 @@ 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 service = yield service_provider.open_service (address, cancellable);
service.close.connect (on_service_closed);
services.add (service);
return service;
}
public Service open_service_sync (string address, Cancellable? cancellable = null) throws Error, IOError {
var task = create<OpenServiceTask> ();
task.address = address;
return task.execute (cancellable);
}
private class OpenServiceTask : DeviceTask<Service> {
public string address;
protected override async Service perform_operation () throws Error, IOError {
return yield parent.open_service (address, cancellable);
}
}
private void on_service_closed (Service service) {
services.remove (service);
}
public async void unpair (Cancellable? cancellable = null) throws Error, IOError {
check_open ();
@@ -1357,6 +1390,10 @@ 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 ();
@@ -1964,6 +2001,68 @@ namespace Frida {
}
}
public interface Service : Object {
public signal void close ();
public signal void message (Variant message);
public abstract bool is_closed ();
public abstract async void activate (Cancellable? cancellable = null) throws Error, IOError;
public void activate_sync (Cancellable? cancellable = null) throws Error, IOError {
create<ActivateTask> ().execute (cancellable);
}
private class ActivateTask : ServiceTask<void> {
protected override async void perform_operation () throws Error, IOError {
yield parent.activate (cancellable);
}
}
public abstract async void cancel (Cancellable? cancellable = null) throws IOError;
public void cancel_sync (Cancellable? cancellable = null) throws IOError {
try {
create<CancelTask> ().execute (cancellable);
} catch (Error e) {
assert_not_reached ();
}
}
private class CancelTask : ServiceTask<void> {
protected override async void perform_operation () throws IOError {
yield parent.cancel (cancellable);
}
}
public abstract async Variant request (Variant parameters, Cancellable? cancellable = null) throws Error, IOError;
public Variant request_sync (Variant parameters, Cancellable? cancellable = null) throws Error, IOError {
var task = create<RequestTask> () as RequestTask;
task.parameters = parameters;
return task.execute (cancellable);
}
private class RequestTask : ServiceTask<Variant> {
public Variant parameters;
protected override async Variant perform_operation () throws Error, IOError {
return yield parent.request (parameters, cancellable);
}
}
private T create<T> () {
return Object.new (typeof (T), parent: this);
}
private abstract class ServiceTask<T> : AsyncTask<T> {
public weak Service parent {
get;
construct;
}
}
}
public class Session : Object, AgentMessageSink {
public signal void detached (SessionDetachReason reason, Crash? crash);
+152 -150
View File
@@ -1,18 +1,18 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class DeviceInfoService : Object, AsyncInitable {
public ChannelProvider channel_provider {
public HostChannelProvider channel_provider {
get;
construct;
}
private DTXChannel channel;
private DeviceInfoService (ChannelProvider channel_provider) {
private DeviceInfoService (HostChannelProvider channel_provider) {
Object (channel_provider: channel_provider);
}
public static async DeviceInfoService open (ChannelProvider channel_provider, Cancellable? cancellable = null)
public static async DeviceInfoService open (HostChannelProvider channel_provider, Cancellable? cancellable = null)
throws Error, IOError {
var service = new DeviceInfoService (channel_provider);
@@ -74,21 +74,53 @@ namespace Frida.Fruity {
return "/private" + name;
return name;
}
public class ProcessInfo : Object {
public uint pid {
get;
set;
}
public string name {
get;
set;
}
public string real_app_name {
get;
set;
}
public bool is_application {
get;
set;
}
public bool foreground_running {
get;
set;
}
public DateTime? start_date {
get;
set;
}
}
}
public class ApplicationListingService : Object, AsyncInitable {
public ChannelProvider channel_provider {
public HostChannelProvider channel_provider {
get;
construct;
}
private DTXChannel channel;
private ApplicationListingService (ChannelProvider channel_provider) {
private ApplicationListingService (HostChannelProvider channel_provider) {
Object (channel_provider: channel_provider);
}
public static async ApplicationListingService open (ChannelProvider channel_provider, Cancellable? cancellable = null)
public static async ApplicationListingService open (HostChannelProvider channel_provider, Cancellable? cancellable = null)
throws Error, IOError {
var service = new ApplicationListingService (channel_provider);
@@ -178,21 +210,115 @@ namespace Frida.Fruity {
return result;
}
public class ApplicationInfo : Object {
public ApplicationType app_type {
get;
set;
}
public string display_name {
get;
set;
}
public string bundle_identifier {
get;
set;
}
public string bundle_path {
get;
set;
}
public string? version {
get;
set;
}
public bool placeholder {
get;
set;
}
public bool restricted {
get;
set;
}
public string? executable_name {
get;
set;
}
public string[]? app_extension_uuids {
get;
set;
}
public string? plugin_uuid {
get;
set;
}
public string? plugin_identifier {
get;
set;
}
public string? container_bundle_identifier {
get;
set;
}
public string? container_bundle_path {
get;
set;
}
}
public enum ApplicationType {
SYSTEM = 1,
USER,
PLUGIN_KIT;
public static ApplicationType from_nick (string nick) throws Error {
return Marshal.enum_from_nick<ApplicationType> (nick);
}
public string to_nick () {
return Marshal.enum_to_nick<ApplicationType> (this);
}
internal static ApplicationType from_dtx (string type) {
if (type == "System")
return SYSTEM;
if (type == "User")
return USER;
if (type == "PluginKit")
return PLUGIN_KIT;
assert_not_reached ();
}
}
}
public class ProcessControlService : Object, AsyncInitable {
public ChannelProvider channel_provider {
public HostChannelProvider channel_provider {
get;
construct;
}
private DTXChannel channel;
private ProcessControlService (ChannelProvider channel_provider) {
private ProcessControlService (HostChannelProvider channel_provider) {
Object (channel_provider: channel_provider);
}
public static async ProcessControlService open (ChannelProvider channel_provider, Cancellable? cancellable = null)
public static async ProcessControlService open (HostChannelProvider channel_provider, Cancellable? cancellable = null)
throws Error, IOError {
var service = new ProcessControlService (channel_provider);
@@ -220,132 +346,6 @@ namespace Frida.Fruity {
}
}
public class ProcessInfo : Object {
public uint pid {
get;
set;
}
public string name {
get;
set;
}
public string real_app_name {
get;
set;
}
public bool is_application {
get;
set;
}
public bool foreground_running {
get;
set;
}
public DateTime? start_date {
get;
set;
}
}
public class ApplicationInfo : Object {
public ApplicationType app_type {
get;
set;
}
public string display_name {
get;
set;
}
public string bundle_identifier {
get;
set;
}
public string bundle_path {
get;
set;
}
public string? version {
get;
set;
}
public bool placeholder {
get;
set;
}
public bool restricted {
get;
set;
}
public string? executable_name {
get;
set;
}
public string[]? app_extension_uuids {
get;
set;
}
public string? plugin_uuid {
get;
set;
}
public string? plugin_identifier {
get;
set;
}
public string? container_bundle_identifier {
get;
set;
}
public string? container_bundle_path {
get;
set;
}
}
public enum ApplicationType {
SYSTEM = 1,
USER,
PLUGIN_KIT;
public static ApplicationType from_nick (string nick) throws Error {
return Marshal.enum_from_nick<ApplicationType> (nick);
}
public string to_nick () {
return Marshal.enum_to_nick<ApplicationType> (this);
}
internal static ApplicationType from_dtx (string type) {
if (type == "System")
return SYSTEM;
if (type == "User")
return USER;
if (type == "PluginKit")
return PLUGIN_KIT;
assert_not_reached ();
}
}
public class DTXConnection : Object, DTXTransport {
public IOStream stream {
get;
@@ -363,7 +363,7 @@ namespace Frida.Fruity {
CLOSED
}
private static Gee.HashMap<ChannelProvider, Future<DTXConnection>> connections;
private static Gee.HashMap<HostChannelProvider, Future<DTXConnection>> connections;
private State _state = OPEN;
@@ -383,19 +383,21 @@ namespace Frida.Fruity {
private const uint32 DTX_FRAGMENT_MAGIC = 0x1f3d5b79U;
private const uint MAX_BUFFERED_COUNT = 100;
private const size_t MAX_BUFFERED_SIZE = 30 * 1024 * 1024;
private const size_t MAX_MESSAGE_SIZE = 1024 * 1024;
private const size_t MAX_MESSAGE_SIZE = 128 * 1024 * 1024;
private const size_t MAX_FRAGMENT_SIZE = 128 * 1024;
private const string REMOTESERVER_ENDPOINT_MODERN = "lockdown:com.apple.instruments.remoteserver.DVTSecureSocketProxy";
private const string REMOTESERVER_ENDPOINT_17PLUS = "lockdown:com.apple.instruments.dtservicehub";
private const string REMOTESERVER_ENDPOINT_14PLUS = "lockdown:com.apple.instruments.remoteserver.DVTSecureSocketProxy";
private const string REMOTESERVER_ENDPOINT_LEGACY = "lockdown:com.apple.instruments.remoteserver?tls=handshake-only";
private const string[] REMOTESERVER_ENDPOINT_CANDIDATES = {
REMOTESERVER_ENDPOINT_MODERN,
REMOTESERVER_ENDPOINT_17PLUS,
REMOTESERVER_ENDPOINT_14PLUS,
REMOTESERVER_ENDPOINT_LEGACY,
};
public static async DTXConnection obtain (ChannelProvider channel_provider, Cancellable? cancellable)
public static async DTXConnection obtain (HostChannelProvider channel_provider, Cancellable? cancellable)
throws Error, IOError {
if (connections == null)
connections = new Gee.HashMap<ChannelProvider, Future<DTXConnection>> ();
connections = new Gee.HashMap<HostChannelProvider, Future<DTXConnection>> ();
while (connections.has_key (channel_provider)) {
var future = connections[channel_provider];
@@ -442,7 +444,7 @@ namespace Frida.Fruity {
throw api_error;
}
public static async void close_all (ChannelProvider channel_provider, Cancellable? cancellable) throws IOError {
public static async void close_all (HostChannelProvider channel_provider, Cancellable? cancellable) throws IOError {
if (connections == null)
return;
@@ -705,7 +707,9 @@ namespace Frida.Fruity {
int32 channel_code = message.channel_code;
bool is_notification = false;
if (message.type == RESULT && channel_code < 0) {
if (message.type == INVOKE) {
channel_code = -channel_code;
} else if (message.type == RESULT && channel_code < 0) {
channel_code = -channel_code;
is_notification = true;
}
@@ -866,7 +870,7 @@ namespace Frida.Fruity {
public class DTXChannel : Object {
public signal void invocation (string method_name, DTXArgumentList args, DTXMessageTransportFlags transport_flags);
public signal void notification (NSDictionary dict);
public signal void notification (NSObject obj);
public signal void barrier ();
public int32 code {
@@ -1016,10 +1020,8 @@ namespace Frida.Fruity {
}
internal void handle_notification (DTXMessage message) throws Error {
NSDictionary? dict = NSKeyedArchive.decode (message.payload_data) as NSDictionary;
if (dict == null)
throw new Error.PROTOCOL ("Malformed notification payload");
notification (dict);
var payload = NSKeyedArchive.decode (message.payload_data);
notification (payload);
}
internal void handle_barrier (DTXMessage message) throws Error {
@@ -1062,7 +1064,7 @@ namespace Frida.Fruity {
}
public class DTXArgumentList {
private Value[] elements;
public Value[] elements;
private DTXArgumentList (owned Value[] elements) {
this.elements = (owned) elements;
@@ -1101,7 +1103,7 @@ namespace Frida.Fruity {
NSObject? obj = NSKeyedArchive.decode (buf);
if (obj != null) {
var gval = Value (Type.from_instance (obj));
gval.set_instance (obj);
gval.set_boxed (obj);
elements += (owned) gval;
} else {
var gval = Value (typeof (NSObject));
File diff suppressed because it is too large. Load diff
+1
View File
@@ -53,6 +53,7 @@ frida_fetch_dyld_symbols (char * output_buffer, const void * dyld_load_address)
frida_str_contains (name, "restartWithDyldInCache") ||
frida_str_equals (name, "_gProcessInfo") ||
frida_str_equals (name, "__ZN5dyld412gProcessInfoE") ||
frida_str_equals (name, "__ZL12sProcessInfo") ||
frida_str_contains (name, "launchWithClosure") ||
frida_str_contains (name, "initializeMainExecutable") ||
frida_str_contains (name, "registerThreadHelpers") ||
+64 -61
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruityInjector", gir_version = "1.0")]
namespace Frida.Fruity.Injector {
public static async GadgetDetails inject (owned Gum.DarwinModule module, LLDB.Client lldb, ChannelProvider channel_provider,
public static async GadgetDetails inject (owned Gum.DarwinModule module, LLDB.Client lldb, HostChannelProvider channel_provider,
Cancellable? cancellable) throws Error, IOError {
var session = new Session (module, lldb, channel_provider);
return yield session.run (cancellable);
@@ -32,7 +32,7 @@ namespace Frida.Fruity.Injector {
construct;
}
public ChannelProvider channel_provider {
public HostChannelProvider channel_provider {
get;
construct;
}
@@ -70,7 +70,7 @@ namespace Frida.Fruity.Injector {
private size_t module_size;
public Session (Gum.DarwinModule module, LLDB.Client lldb, ChannelProvider channel_provider) {
public Session (Gum.DarwinModule module, LLDB.Client lldb, HostChannelProvider channel_provider) {
Object (
module: module,
lldb: lldb,
@@ -837,9 +837,11 @@ namespace Frida.Fruity.Injector {
private async void ensure_libsystem_initialized_for_dyld_v4_and_above (uint64 libdyld_initialize,
Cancellable? cancellable) throws GLib.Error {
uint64? process_info_ptr = dyld_symbols["_gProcessInfo"];
uint64? process_info_ptr = dyld_symbols["__ZL12sProcessInfo"];
if (process_info_ptr == null)
process_info_ptr = dyld_symbols["__ZN5dyld412gProcessInfoE"];
if (process_info_ptr == null)
process_info_ptr = dyld_symbols["_gProcessInfo"];
GDB.Breakpoint init_breakpoint = yield lldb.add_breakpoint (SOFT, libdyld_initialize, 4, cancellable);
@@ -1181,68 +1183,69 @@ namespace Frida.Fruity.Injector {
private const uint8[] SYMBOL_FETCHER_CODE = {
0xff, 0x03, 0x02, 0xd1, 0xfc, 0x6f, 0x02, 0xa9, 0xfa, 0x67, 0x03, 0xa9, 0xf8, 0x5f, 0x04, 0xa9, 0xf6, 0x57, 0x05,
0xa9, 0xf4, 0x4f, 0x06, 0xa9, 0xfd, 0x7b, 0x07, 0xa9, 0xfd, 0xc3, 0x01, 0x91, 0xf4, 0x03, 0x01, 0xaa, 0xe0, 0x07,
0x00, 0xf9, 0x13, 0x00, 0x80, 0xd2, 0x19, 0x00, 0x80, 0xd2, 0x35, 0x80, 0x00, 0x91, 0x3a, 0x10, 0x40, 0xb9, 0xd6,
0x22, 0x00, 0x30, 0x1f, 0x20, 0x03, 0xd5, 0xd7, 0x22, 0x00, 0x10, 0x1f, 0x20, 0x03, 0xd5, 0x1a, 0x04, 0x00, 0x34,
0x00, 0xf9, 0x13, 0x00, 0x80, 0xd2, 0x19, 0x00, 0x80, 0xd2, 0x35, 0x80, 0x00, 0x91, 0x3a, 0x10, 0x40, 0xb9, 0x16,
0x00, 0x00, 0x90, 0xd6, 0xb2, 0x12, 0x91, 0x17, 0x00, 0x00, 0x90, 0xf7, 0xce, 0x12, 0x91, 0x1a, 0x04, 0x00, 0x34,
0xa8, 0x02, 0x40, 0xb9, 0x1f, 0x09, 0x00, 0x71, 0xa0, 0x01, 0x00, 0x54, 0x1f, 0x2d, 0x00, 0x71, 0xa0, 0x01, 0x00,
0x54, 0x1f, 0x65, 0x00, 0x71, 0x81, 0x01, 0x00, 0x54, 0xb8, 0x22, 0x00, 0x91, 0xe0, 0x03, 0x18, 0xaa, 0xe1, 0x03,
0x16, 0xaa, 0xa3, 0x00, 0x00, 0x94, 0x80, 0x01, 0x00, 0x34, 0xb3, 0xa2, 0x41, 0xa9, 0xe8, 0x0b, 0x00, 0xf9, 0x04,
0x16, 0xaa, 0xa5, 0x00, 0x00, 0x94, 0x80, 0x01, 0x00, 0x34, 0xb3, 0xa2, 0x41, 0xa9, 0xe8, 0x0b, 0x00, 0xf9, 0x04,
0x00, 0x00, 0x14, 0xfc, 0x03, 0x15, 0xaa, 0x02, 0x00, 0x00, 0x14, 0xfb, 0x03, 0x15, 0xaa, 0xa8, 0x06, 0x40, 0xb9,
0xb5, 0x02, 0x08, 0x8b, 0x5a, 0x07, 0x00, 0x51, 0x7a, 0xfd, 0xff, 0x35, 0x09, 0x00, 0x00, 0x14, 0xe0, 0x03, 0x18,
0xaa, 0xe1, 0x03, 0x17, 0xaa, 0x94, 0x00, 0x00, 0x94, 0x00, 0xff, 0xff, 0x34, 0xa8, 0x0e, 0x40, 0xf9, 0xa9, 0x16,
0xaa, 0xe1, 0x03, 0x17, 0xaa, 0x96, 0x00, 0x00, 0x94, 0x00, 0xff, 0xff, 0x34, 0xa8, 0x0e, 0x40, 0xf9, 0xa9, 0x16,
0x40, 0xf9, 0x19, 0x01, 0x09, 0xcb, 0xf4, 0xff, 0xff, 0x17, 0x88, 0x02, 0x13, 0xcb, 0x28, 0x03, 0x08, 0x8b, 0x89,
0x0b, 0x40, 0xb9, 0x13, 0x01, 0x09, 0x8b, 0x89, 0x13, 0x40, 0xb9, 0x19, 0x01, 0x09, 0x8b, 0x16, 0x17, 0x00, 0x10,
0x1f, 0x20, 0x03, 0xd5, 0xe8, 0x07, 0x40, 0xf9, 0xe8, 0x0f, 0x00, 0xf9, 0x35, 0x01, 0x80, 0x52, 0x78, 0x0b, 0x40,
0xb9, 0x68, 0x0f, 0x40, 0xb9, 0x1f, 0x03, 0x08, 0x6b, 0xc0, 0x09, 0x00, 0x54, 0xf7, 0x03, 0x18, 0x2a, 0xe8, 0xee,
0x7c, 0xd3, 0x68, 0x6a, 0x68, 0xb8, 0x3c, 0x03, 0x08, 0x8b, 0xe0, 0x03, 0x1c, 0xaa, 0xe1, 0x03, 0x16, 0xaa, 0x61,
0x00, 0x00, 0x94, 0x60, 0x06, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x41, 0x15, 0x00, 0x70, 0x1f, 0x20, 0x03, 0xd5,
0x5c, 0x00, 0x00, 0x94, 0xc0, 0x05, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x61, 0x15, 0x00, 0x50, 0x1f, 0x20, 0x03,
0xd5, 0x6f, 0x00, 0x00, 0x94, 0x20, 0x05, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x41, 0x15, 0x00, 0x10, 0x1f, 0x20,
0x03, 0xd5, 0x6a, 0x00, 0x00, 0x94, 0x80, 0x04, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x61, 0x15, 0x00, 0x50, 0x1f,
0x20, 0x03, 0xd5, 0x4d, 0x00, 0x00, 0x94, 0xe0, 0x03, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x61, 0x15, 0x00, 0x10,
0x1f, 0x20, 0x03, 0xd5, 0x48, 0x00, 0x00, 0x94, 0x40, 0x03, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x81, 0x15, 0x00,
0x30, 0x1f, 0x20, 0x03, 0xd5, 0x43, 0x00, 0x00, 0x94, 0xa0, 0x02, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x81, 0x15,
0x00, 0x70, 0x1f, 0x20, 0x03, 0xd5, 0x5e, 0x00, 0x00, 0x94, 0x00, 0x02, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x21,
0x15, 0x00, 0x70, 0x1f, 0x20, 0x03, 0xd5, 0x59, 0x00, 0x00, 0x94, 0x60, 0x01, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa,
0xc1, 0x14, 0x00, 0x70, 0x1f, 0x20, 0x03, 0xd5, 0x34, 0x00, 0x00, 0x94, 0xc0, 0x00, 0x00, 0x37, 0xe0, 0x03, 0x1c,
0xaa, 0xc1, 0x14, 0x00, 0x50, 0x1f, 0x20, 0x03, 0xd5, 0x2f, 0x00, 0x00, 0x94, 0x40, 0x02, 0x00, 0x34, 0xba, 0x00,
0x00, 0x34, 0xe8, 0x0f, 0x40, 0xf9, 0x49, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0x68,
0x12, 0x17, 0x8b, 0x08, 0x05, 0x40, 0xf9, 0x81, 0x02, 0x08, 0x8b, 0xe0, 0x63, 0x00, 0x91, 0x4d, 0x00, 0x00, 0x94,
0xe8, 0x0f, 0x40, 0xf9, 0x15, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0xe1, 0x03, 0x1c,
0xaa, 0x5e, 0x00, 0x00, 0x94, 0x5a, 0x07, 0x00, 0x11, 0x18, 0x07, 0x00, 0x11, 0xb1, 0xff, 0xff, 0x17, 0xe1, 0x23,
0x41, 0xa9, 0x49, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0x3e,
0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40, 0xf9, 0x29, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9,
0x21, 0x11, 0x00, 0x70, 0x1f, 0x20, 0x03, 0xd5, 0xe0, 0x63, 0x00, 0x91, 0x4d, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40,
0xf9, 0xe9, 0x07, 0x40, 0xf9, 0x00, 0x01, 0x09, 0xcb, 0x1f, 0x01, 0x00, 0x39, 0xfd, 0x7b, 0x47, 0xa9, 0xf4, 0x4f,
0x46, 0xa9, 0xf6, 0x57, 0x45, 0xa9, 0xf8, 0x5f, 0x44, 0xa9, 0xfa, 0x67, 0x43, 0xa9, 0xfc, 0x6f, 0x42, 0xa9, 0xff,
0x03, 0x02, 0x91, 0xc0, 0x03, 0x5f, 0xd6, 0xf6, 0x57, 0xbd, 0xa9, 0xf4, 0x4f, 0x01, 0xa9, 0xfd, 0x7b, 0x02, 0xa9,
0xfd, 0x83, 0x00, 0x91, 0xf4, 0x03, 0x01, 0xaa, 0xf3, 0x03, 0x00, 0xaa, 0x35, 0x00, 0x40, 0x39, 0x68, 0x02, 0x40,
0x39, 0x28, 0x01, 0x00, 0x34, 0x1f, 0x01, 0x15, 0x6b, 0xa1, 0x00, 0x00, 0x54, 0xe0, 0x03, 0x13, 0xaa, 0xe1, 0x03,
0x14, 0xaa, 0x13, 0x00, 0x00, 0x94, 0x80, 0x00, 0x00, 0x37, 0x73, 0x06, 0x00, 0x91, 0xf7, 0xff, 0xff, 0x17, 0x13,
0x00, 0x80, 0xd2, 0x7f, 0x02, 0x00, 0xf1, 0xe0, 0x07, 0x9f, 0x1a, 0xfd, 0x7b, 0x42, 0xa9, 0xf4, 0x4f, 0x41, 0xa9,
0xf6, 0x57, 0xc3, 0xa8, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x14, 0x40, 0x38, 0x29, 0x14, 0x40, 0x38, 0x1f, 0x01, 0x00,
0x71, 0x00, 0x11, 0x49, 0x7a, 0x80, 0xff, 0xff, 0x54, 0x1f, 0x01, 0x09, 0x6b, 0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03,
0x5f, 0xd6, 0x28, 0x00, 0x40, 0x39, 0xa8, 0x00, 0x00, 0x34, 0x21, 0x04, 0x00, 0x91, 0x09, 0x14, 0x40, 0x38, 0x3f,
0x01, 0x08, 0x6b, 0x60, 0xff, 0xff, 0x54, 0x1f, 0x01, 0x00, 0x71, 0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03, 0x5f, 0xd6,
0x09, 0x00, 0x80, 0x52, 0x08, 0x00, 0x40, 0xf9, 0x8a, 0x07, 0x80, 0x52, 0xab, 0x0a, 0x00, 0x10, 0x1f, 0x20, 0x03,
0xd5, 0x5f, 0x11, 0x00, 0x31, 0x80, 0x01, 0x00, 0x54, 0x2c, 0x24, 0xca, 0x9a, 0x8c, 0x0d, 0x00, 0x72, 0x2d, 0x01,
0x00, 0x12, 0xa0, 0x19, 0x40, 0x7a, 0x29, 0x15, 0x9f, 0x1a, 0x89, 0x00, 0x00, 0x36, 0x8c, 0x1d, 0x40, 0x92, 0x6c,
0x69, 0x6c, 0x38, 0x0c, 0x15, 0x00, 0x38, 0x4a, 0x11, 0x00, 0x51, 0xf4, 0xff, 0xff, 0x17, 0x69, 0x00, 0x00, 0x37,
0x09, 0x06, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0x08, 0x00, 0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x00, 0x40,
0xf9, 0x29, 0x00, 0x40, 0x39, 0x89, 0x00, 0x00, 0x34, 0x21, 0x04, 0x00, 0x91, 0x09, 0x15, 0x00, 0x38, 0xfc, 0xff,
0xff, 0x17, 0x08, 0x00, 0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0x6c, 0x69, 0x62, 0x64, 0x79, 0x6c, 0x64, 0x5f, 0x69,
0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x00, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x57, 0x69,
0x74, 0x68, 0x44, 0x79, 0x6c, 0x64, 0x49, 0x6e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x00, 0x5f, 0x67, 0x50, 0x72, 0x6f,
0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x00, 0x5f, 0x5f, 0x5a, 0x4e, 0x35, 0x64, 0x79, 0x6c, 0x64, 0x34,
0x31, 0x32, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x00, 0x6c, 0x61, 0x75,
0x6e, 0x63, 0x68, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x6f, 0x73, 0x75, 0x72, 0x65, 0x00, 0x69, 0x6e, 0x69, 0x74,
0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4d, 0x61, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c,
0x65, 0x00, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x48, 0x65, 0x6c,
0x70, 0x65, 0x72, 0x73, 0x00, 0x5f, 0x64, 0x6c, 0x6f, 0x70, 0x65, 0x6e, 0x00, 0x5f, 0x73, 0x74, 0x72, 0x63, 0x6d,
0x70, 0x00, 0x64, 0x6f, 0x4d, 0x6f, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x00, 0x64, 0x6f, 0x47, 0x65, 0x74, 0x44, 0x4f, 0x46, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00,
0x64, 0x79, 0x6c, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x5f, 0x5f,
0x4c, 0x49, 0x4e, 0x4b, 0x45, 0x44, 0x49, 0x54, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
0x0b, 0x40, 0xb9, 0x13, 0x01, 0x09, 0x8b, 0x89, 0x13, 0x40, 0xb9, 0x19, 0x01, 0x09, 0x8b, 0xe8, 0x07, 0x40, 0xf9,
0xe8, 0x0f, 0x00, 0xf9, 0x16, 0x00, 0x00, 0x90, 0xd6, 0x22, 0x0f, 0x91, 0x35, 0x01, 0x80, 0x52, 0x78, 0x0b, 0x40,
0xb9, 0x68, 0x0f, 0x40, 0xb9, 0x1f, 0x03, 0x08, 0x6b, 0x20, 0x0a, 0x00, 0x54, 0x77, 0x52, 0x38, 0x8b, 0xe8, 0x02,
0x40, 0xb9, 0x3c, 0x03, 0x08, 0x8b, 0xe0, 0x03, 0x1c, 0xaa, 0xe1, 0x03, 0x16, 0xaa, 0x65, 0x00, 0x00, 0x94, 0x00,
0x07, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x6c, 0x0f, 0x91, 0x60, 0x00, 0x00, 0x94,
0x60, 0x06, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0xc8, 0x0f, 0x91, 0x72, 0x00, 0x00,
0x94, 0xc0, 0x05, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x00, 0x10, 0x91, 0x6d, 0x00,
0x00, 0x94, 0x20, 0x05, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x68, 0x10, 0x91, 0x68,
0x00, 0x00, 0x94, 0x80, 0x04, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0xb4, 0x10, 0x91,
0x4c, 0x00, 0x00, 0x94, 0xe0, 0x03, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0xfc, 0x10,
0x91, 0x47, 0x00, 0x00, 0x94, 0x40, 0x03, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x60,
0x11, 0x91, 0x42, 0x00, 0x00, 0x94, 0xa0, 0x02, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21,
0xb8, 0x11, 0x91, 0x5c, 0x00, 0x00, 0x94, 0x00, 0x02, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90,
0x21, 0xd8, 0x11, 0x91, 0x57, 0x00, 0x00, 0x94, 0x60, 0x01, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00,
0x90, 0x21, 0xf8, 0x11, 0x91, 0x33, 0x00, 0x00, 0x94, 0xc0, 0x00, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00,
0x00, 0x90, 0x21, 0x44, 0x12, 0x91, 0x2e, 0x00, 0x00, 0x94, 0x20, 0x02, 0x00, 0x34, 0xba, 0x00, 0x00, 0x34, 0xe8,
0x0f, 0x40, 0xf9, 0x49, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe8, 0x06, 0x40, 0xf9,
0x81, 0x02, 0x08, 0x8b, 0xe0, 0x63, 0x00, 0x91, 0x4c, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40, 0xf9, 0x15, 0x15, 0x00,
0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0xe1, 0x03, 0x1c, 0xaa, 0x5d, 0x00, 0x00, 0x94, 0x5a, 0x07,
0x00, 0x11, 0x18, 0x07, 0x00, 0x11, 0xae, 0xff, 0xff, 0x17, 0xe1, 0x23, 0x41, 0xa9, 0x49, 0x01, 0x80, 0x52, 0x09,
0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0x3d, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40, 0xf9,
0x29, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0x01, 0x00, 0x00, 0x90, 0x21, 0x88, 0x12,
0x91, 0xe0, 0x63, 0x00, 0x91, 0x4c, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40, 0xf9, 0xe9, 0x07, 0x40, 0xf9, 0x00, 0x01,
0x09, 0xcb, 0x1f, 0x01, 0x00, 0x39, 0xfd, 0x7b, 0x47, 0xa9, 0xf4, 0x4f, 0x46, 0xa9, 0xf6, 0x57, 0x45, 0xa9, 0xf8,
0x5f, 0x44, 0xa9, 0xfa, 0x67, 0x43, 0xa9, 0xfc, 0x6f, 0x42, 0xa9, 0xff, 0x03, 0x02, 0x91, 0xc0, 0x03, 0x5f, 0xd6,
0xf6, 0x57, 0xbd, 0xa9, 0xf4, 0x4f, 0x01, 0xa9, 0xfd, 0x7b, 0x02, 0xa9, 0xfd, 0x83, 0x00, 0x91, 0xf3, 0x03, 0x01,
0xaa, 0xf4, 0x03, 0x00, 0xaa, 0x35, 0x00, 0x40, 0x39, 0x96, 0x02, 0x40, 0x39, 0x36, 0x01, 0x00, 0x34, 0xdf, 0x02,
0x15, 0x6b, 0xa1, 0x00, 0x00, 0x54, 0xe0, 0x03, 0x14, 0xaa, 0xe1, 0x03, 0x13, 0xaa, 0x12, 0x00, 0x00, 0x94, 0x60,
0x00, 0x00, 0x37, 0x94, 0x06, 0x00, 0x91, 0xf7, 0xff, 0xff, 0x17, 0xdf, 0x02, 0x00, 0x71, 0xe0, 0x07, 0x9f, 0x1a,
0xfd, 0x7b, 0x42, 0xa9, 0xf4, 0x4f, 0x41, 0xa9, 0xf6, 0x57, 0xc3, 0xa8, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x14, 0x40,
0x38, 0x29, 0x14, 0x40, 0x38, 0x1f, 0x01, 0x00, 0x71, 0x00, 0x11, 0x49, 0x7a, 0x80, 0xff, 0xff, 0x54, 0x1f, 0x01,
0x09, 0x6b, 0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03, 0x5f, 0xd6, 0x28, 0x00, 0x40, 0x39, 0xa8, 0x00, 0x00, 0x34, 0x21,
0x04, 0x00, 0x91, 0x09, 0x14, 0x40, 0x38, 0x3f, 0x01, 0x08, 0x6b, 0x60, 0xff, 0xff, 0x54, 0x1f, 0x01, 0x00, 0x71,
0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03, 0x5f, 0xd6, 0x09, 0x00, 0x80, 0x52, 0x08, 0x00, 0x40, 0xf9, 0x8a, 0x07, 0x80,
0x52, 0x0b, 0x00, 0x00, 0x90, 0x6b, 0x01, 0x13, 0x91, 0x5f, 0x11, 0x00, 0x31, 0x80, 0x01, 0x00, 0x54, 0x2c, 0x24,
0xca, 0x9a, 0x8c, 0x0d, 0x40, 0x92, 0x2d, 0x01, 0x00, 0x12, 0x9f, 0x01, 0x00, 0x71, 0xa0, 0x19, 0x40, 0x7a, 0x29,
0x15, 0x9f, 0x1a, 0x69, 0x00, 0x00, 0x36, 0x6c, 0x69, 0x6c, 0x38, 0x0c, 0x15, 0x00, 0x38, 0x4a, 0x11, 0x00, 0x51,
0xf4, 0xff, 0xff, 0x17, 0x69, 0x00, 0x00, 0x37, 0x09, 0x06, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0x08, 0x00, 0x00,
0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x00, 0x40, 0xf9, 0x29, 0x00, 0x40, 0x39, 0x89, 0x00, 0x00, 0x34, 0x21, 0x04,
0x00, 0x91, 0x09, 0x15, 0x00, 0x38, 0xfc, 0xff, 0xff, 0x17, 0x08, 0x00, 0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0x6c,
0x69, 0x62, 0x64, 0x79, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x00, 0x72,
0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x57, 0x69, 0x74, 0x68, 0x44, 0x79, 0x6c, 0x64, 0x49, 0x6e, 0x43, 0x61, 0x63,
0x68, 0x65, 0x00, 0x5f, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x00, 0x5f, 0x5f,
0x5a, 0x4e, 0x35, 0x64, 0x79, 0x6c, 0x64, 0x34, 0x31, 0x32, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49,
0x6e, 0x66, 0x6f, 0x45, 0x00, 0x5f, 0x5f, 0x5a, 0x4c, 0x31, 0x32, 0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
0x49, 0x6e, 0x66, 0x6f, 0x00, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x6f, 0x73,
0x75, 0x72, 0x65, 0x00, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4d, 0x61, 0x69, 0x6e, 0x45,
0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x54,
0x68, 0x72, 0x65, 0x61, 0x64, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x73, 0x00, 0x5f, 0x64, 0x6c, 0x6f, 0x70, 0x65,
0x6e, 0x00, 0x5f, 0x73, 0x74, 0x72, 0x63, 0x6d, 0x70, 0x00, 0x64, 0x6f, 0x4d, 0x6f, 0x64, 0x49, 0x6e, 0x69, 0x74,
0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x64, 0x6f, 0x47, 0x65, 0x74, 0x44, 0x4f, 0x46, 0x53,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x64, 0x79, 0x6c, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x5f,
0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x5f, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x45, 0x44, 0x49, 0x54, 0x00, 0x00, 0x00,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
};
private async SymbolSet resolve_symbols (SymbolQuery query, Cancellable? cancellable) throws GLib.Error {
+88
View File
@@ -0,0 +1,88 @@
namespace Frida {
using CoreFoundation;
using Darwin.XNU;
internal class IORegistry {
private MachPort main_port;
public static IORegistry open () throws Error {
MachPort port;
kern_check (Darwin.IOKit.main_port (MachPort.NULL, out port));
return new IORegistry (port);
}
private IORegistry (MachPort main_port) {
this.main_port = main_port;
}
public IOIterator<IORegistryEntry> matching_services (owned MutableDictionary matching_dict) throws Error {
Darwin.IOKit.IOIterator h;
kern_check (Darwin.IOKit.get_matching_services (main_port, matching_dict, out h));
return new IOIterator<IORegistryEntry> ((owned) h);
}
}
internal class IORegistryEntry : GLib.Object {
public IOObject io_object {
get;
construct;
}
internal IORegistryEntry (IOObject obj) {
GLib.Object (io_object: obj);
}
public MutableDictionary get_properties () throws Error {
MutableDictionary properties;
kern_check (unwrap ().create_cf_properties (out properties, null, 0));
return properties;
}
public string? get_string_property (string key) {
var v = (String) unwrap ().create_cf_property (String.make (key), null, 0);
return (v != null) ? v.to_string () : null;
}
public IORegistryEntry parent (string plane) throws Error {
Darwin.IOKit.IOObject h;
kern_check (unwrap ().get_parent_entry (plane, out h));
return new IORegistryEntry (new IOObject ((owned) h));
}
private unowned Darwin.IOKit.IORegistryEntry unwrap () {
return (Darwin.IOKit.IORegistryEntry) io_object.handle;
}
}
internal class IOIterator<T> {
private Darwin.IOKit.IOIterator handle;
internal IOIterator (owned Darwin.IOKit.IOIterator handle) {
this.handle = (owned) handle;
}
public IOIterator<T> iterator () {
return this;
}
public T? next_value () {
Darwin.IOKit.IOObject h = handle.next ();
if (h == Darwin.IOKit.IOObject.NULL)
return null;
return GLib.Object.new (typeof (T), io_object: new IOObject ((owned) h));
}
}
internal class IOObject {
internal Darwin.IOKit.IOObject handle;
internal IOObject (owned Darwin.IOKit.IOObject handle) {
this.handle = (owned) handle;
}
}
private void kern_check (KernReturn result) throws Error {
if (result != KernReturn.SUCCESS)
throw new Error.NOT_SUPPORTED ("%s", mach_error_string (result));
}
}
+174 -2
View File
@@ -23,6 +23,11 @@ namespace Frida.Fruity {
}
public class NSNumber : NSObject {
public Kind kind {
get;
private set;
}
public bool boolean {
get;
private set;
@@ -33,14 +38,44 @@ namespace Frida.Fruity {
private set;
}
public double number {
get;
private set;
}
public enum Kind {
BOOLEAN,
INTEGER,
FLOAT,
DOUBLE,
}
public NSNumber.from_boolean (bool val) {
kind = BOOLEAN;
boolean = val;
integer = val ? 1 : 0;
number = val ? 1.0 : 0.0;
}
public NSNumber.from_integer (int64 val) {
kind = INTEGER;
boolean = (val != 0) ? true : false;
integer = val;
number = val;
}
public NSNumber.from_float (float val) {
kind = FLOAT;
boolean = (val != 0.0f) ? true : false;
integer = (int64) val;
number = val;
}
public NSNumber.from_double (double val) {
kind = DOUBLE;
boolean = (val != 0.0) ? true : false;
integer = (int64) val;
number = val;
}
public override uint hash () {
@@ -51,7 +86,21 @@ namespace Frida.Fruity {
var other_number = other as NSNumber;
if (other_number == null)
return false;
return other_number.integer == integer;
if (other_number.kind != kind)
return false;
switch (kind) {
case BOOLEAN:
return other_number.boolean == boolean;
case INTEGER:
return other_number.integer == integer;
case FLOAT:
case DOUBLE:
return other_number.number == number;
}
return false;
}
public override string to_string () {
@@ -85,6 +134,32 @@ namespace Frida.Fruity {
}
}
public class NSData : NSObject {
public Bytes bytes {
get;
private set;
}
public NSData (Bytes bytes) {
this.bytes = bytes;
}
public override uint hash () {
return bytes.hash ();
}
public override bool is_equal_to (NSObject other) {
var other_data = other as NSData;
if (other_data == null)
return false;
return other_data.bytes.compare (bytes) == 0;
}
public override string to_string () {
return "NSData";
}
}
public class NSDictionary : NSObject {
public int size {
get {
@@ -198,6 +273,10 @@ namespace Frida.Fruity {
public NSArray (Gee.ArrayList<NSObject>? storage = null) {
this.storage = (storage != null) ? storage : new Gee.ArrayList<NSObject> (NSObject.equal_func);
}
public void add_object (NSObject obj) {
storage.add (obj);
}
}
public class NSDate : NSObject {
@@ -242,11 +321,23 @@ namespace Frida.Fruity {
}
}
public class DTTapMessage : NSObject {
public NSDictionary plist {
get;
private set;
}
public DTTapMessage (NSDictionary plist) {
this.plist = plist;
}
}
namespace NSKeyedArchive {
private Gee.HashMap<Type, EncodeFunc> encoders;
private Gee.HashMap<string, DecodeFunc> decoders;
private const string[] DICTIONARY_CLASS = { "NSDictionary", "NSObject" };
private const string[] ARRAY_CLASS = { "NSArray", "NSObject" };
[CCode (has_target = false)]
private delegate PlistUid EncodeFunc (NSObject instance, EncodingContext ctx);
@@ -319,9 +410,18 @@ namespace Frida.Fruity {
if (t == typeof (int64))
return new NSNumber.from_integer (val.get_int64 ());
if (t == typeof (float))
return new NSNumber.from_float (val.get_float ());
if (t == typeof (double))
return new NSNumber.from_double (val.get_double ());
if (t == typeof (string))
return new NSString (val.get_string ());
if (t == typeof (Bytes))
return new NSData ((Bytes) val.get_boxed ());
if (t == typeof (PlistDict)) {
var instance = (PlistDict) val.get_object ();
var klass = objects.get_dict ((int) instance.get_uid ("$class").uid);
@@ -354,6 +454,7 @@ namespace Frida.Fruity {
encoders[typeof (NSNumber)] = encode_number;
encoders[typeof (NSString)] = encode_string;
encoders[typeof (NSDictionary)] = encode_dictionary;
encoders[typeof (NSArray)] = encode_array;
}
private static void ensure_decoders_registered () {
@@ -365,11 +466,41 @@ namespace Frida.Fruity {
decoders["NSArray"] = decode_array;
decoders["NSDate"] = decode_date;
decoders["NSError"] = decode_error;
decoders["DTTapMessage"] = decode_tap_message;
decoders["DTSysmonTapMessage"] = decode_tap_message;
decoders["DTActivityTraceTapMessage"] = decode_tap_message;
decoders["DTTapStatusMessage"] = decode_tap_message;
decoders["DTTapHeartbeatMessage"] = decode_tap_message;
decoders["DTKTraceTapMessage"] = decode_tap_message;
}
private static PlistUid encode_number (NSObject instance, EncodingContext ctx) {
int64 val = ((NSNumber) instance).integer;
var n = (NSNumber) instance;
switch (n.kind) {
case BOOLEAN:
return encode_boolean (n.boolean, ctx);
case INTEGER:
return encode_integer (n.integer, ctx);
case FLOAT:
return encode_float (n.integer, ctx);
case DOUBLE:
return encode_double (n.integer, ctx);
}
assert_not_reached ();
}
private static PlistUid encode_boolean (bool val, EncodingContext ctx) {
var uid = ctx.find_existing_object (e => e.holds (typeof (bool)) && e.get_boolean () == val);
if (uid != null)
return uid;
var objects = ctx.objects;
uid = new PlistUid (objects.length);
objects.add_boolean (val);
return uid;
}
private static PlistUid encode_integer (int64 val, EncodingContext ctx) {
var uid = ctx.find_existing_object (e => e.holds (typeof (int64)) && e.get_int64 () == val);
if (uid != null)
return uid;
@@ -380,6 +511,28 @@ namespace Frida.Fruity {
return uid;
}
private static PlistUid encode_float (float val, EncodingContext ctx) {
var uid = ctx.find_existing_object (e => e.holds (typeof (float)) && e.get_float () == val);
if (uid != null)
return uid;
var objects = ctx.objects;
uid = new PlistUid (objects.length);
objects.add_float (val);
return uid;
}
private static PlistUid encode_double (double val, EncodingContext ctx) {
var uid = ctx.find_existing_object (e => e.holds (typeof (double)) && e.get_double () == val);
if (uid != null)
return uid;
var objects = ctx.objects;
uid = new PlistUid (objects.length);
objects.add_double (val);
return uid;
}
private static PlistUid encode_string (NSObject instance, EncodingContext ctx) {
string str = ((NSString) instance).str;
@@ -451,6 +604,21 @@ namespace Frida.Fruity {
}
}
private static PlistUid encode_array (NSObject instance, EncodingContext ctx) {
NSArray array = (NSArray) instance;
var object = new PlistDict ();
var uid = ctx.add_object (object);
var objs = new PlistArray ();
foreach (var element in array.elements)
objs.add_uid (encode_value (element, ctx));
object.set_array ("NS.objects", objs);
object.set_uid ("$class", ctx.get_class (ARRAY_CLASS));
return uid;
}
private static NSObject decode_array (PlistDict instance, DecodingContext ctx) throws Error, PlistError {
var objs = instance.get_array ("NS.objects");
@@ -486,6 +654,10 @@ namespace Frida.Fruity {
return new NSError (domain, code, (NSDictionary) user_info);
}
private static NSObject decode_tap_message (PlistDict instance, DecodingContext ctx) throws Error, PlistError {
return new DTTapMessage ((NSDictionary) decode_value (instance.get_uid ("DTTapMessagePlist"), ctx));
}
private class EncodingContext {
public PlistArray objects;
+12
View File
@@ -1573,6 +1573,12 @@ namespace Frida.Fruity {
if (t == typeof (int64))
return (uint) v.get_int64 ();
if (t == typeof (float))
return (uint) v.get_float ();
if (t == typeof (double))
return (uint) v.get_double ();
if (t == typeof (string))
return str_hash (v.get_string ());
@@ -1598,6 +1604,12 @@ namespace Frida.Fruity {
if (t == typeof (int64))
return a.get_int64 () == b.get_int64 ();
if (t == typeof (float))
return a.get_float () == b.get_float ();
if (t == typeof (double))
return a.get_double () == b.get_double ();
if (t == typeof (string))
return a.get_string () == b.get_string ();
+298
View File
@@ -0,0 +1,298 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
using Darwin.GCD;
using Darwin.DNSSD;
using Darwin.Net;
public class DarwinPairingBrowser : Object, PairingBrowser {
private MainContext main_context;
private DispatchQueue dispatch_queue = new DispatchQueue ("re.frida.fruity.browser-queue", DispatchQueueAttr.SERIAL);
private DNSService dns_connection;
private DNSService browse_session;
private TaskQueue task_queue;
private Gee.List<PairingServiceDetails> current_batch = new Gee.ArrayList<PairingServiceDetails> ();
construct {
main_context = MainContext.ref_thread_default ();
dispatch_queue.dispatch_async (() => {
DNSService.create_connection (out dns_connection);
dns_connection.set_dispatch_queue (dispatch_queue);
DNSService session = dns_connection;
DNSService.browse (ref session, PrivateFive | ShareConnection, 0, PAIRING_REGTYPE, PAIRING_DOMAIN,
on_browse_reply);
browse_session = session;
task_queue = new TaskQueue (this);
});
}
~DarwinPairingBrowser () {
dispatch_queue.dispatch_sync (() => {
browse_session.deallocate ();
dns_connection.deallocate ();
});
}
private void on_browse_reply (DNSService sd_ref, DNSService.Flags flags, uint32 interface_index,
DNSService.ErrorType error_code, string service_name, string regtype, string reply_domain) {
if (error_code != NoError)
return;
var interface_name_buf = new char[IFNAMSIZ];
unowned string interface_name = if_indextoname (interface_index, interface_name_buf);
var service = new DarwinPairingServiceDetails (service_name, interface_index, interface_name, task_queue);
current_batch.add (service);
if ((flags & DNSService.Flags.MoreComing) != 0)
return;
var services = current_batch;
current_batch = new Gee.ArrayList<PairingServiceDetails> ();
schedule_on_frida_thread (() => {
services_discovered (services.to_array ());
return Source.REMOVE;
});
}
private void schedule_on_frida_thread (owned SourceFunc function) {
var source = new IdleSource ();
source.set_callback ((owned) function);
source.attach (main_context);
}
private class TaskQueue : Object, DNSServiceProvider {
private weak DarwinPairingBrowser parent;
private DNSServiceTask? current = null;
private Gee.Deque<DNSServiceTask> pending = new Gee.ArrayQueue<DNSServiceTask> ();
public TaskQueue (DarwinPairingBrowser parent) {
this.parent = parent;
}
private async T with_dns_service<T> (DNSServiceTask task, Cancellable? cancellable) throws Error, IOError {
var promise = new Promise<Object> ();
task.set_data ("promise", promise);
pending.offer_tail (task);
maybe_start_next ();
return (T) yield promise.future.wait_async (cancellable);
}
private void maybe_start_next () {
if (current != null)
return;
DNSServiceTask? task = pending.poll_head ();
if (task == null)
return;
current = task;
parent.dispatch_queue.dispatch_async (() => {
current.dns_connection = parent.dns_connection;
current.on_complete = on_complete;
current.start ();
});
}
private void on_complete (Object? result, Error? error) {
parent.schedule_on_frida_thread (() => {
Promise<Object> promise = current.steal_data ("promise");
if (error != null)
promise.reject (error);
else
promise.resolve (result);
current = null;
maybe_start_next ();
return Source.REMOVE;
});
}
}
}
private interface DNSServiceProvider : Object {
public abstract async T with_dns_service<T> (DNSServiceTask task, Cancellable? cancellable) throws Error, IOError;
}
private abstract class DNSServiceTask : Object {
internal DNSService? dns_connection;
internal CompleteFunc? on_complete;
protected DNSService? session;
public delegate void CompleteFunc (Object? result, Error? error);
public abstract void start ();
protected void complete (Object? result, Error? error) {
if (session != null && session != dns_connection) {
session.deallocate ();
session = null;
}
on_complete (result, error);
on_complete = null;
}
}
public class DarwinPairingServiceDetails : Object, PairingServiceDetails {
public string name {
get { return _name; }
}
public uint interface_index {
get { return _interface_index; }
}
public string interface_name {
get { return _interface_name; }
}
private string _name;
private uint _interface_index;
private string _interface_name;
private DNSServiceProvider dns;
internal DarwinPairingServiceDetails (string name, uint interface_index, string interface_name, DNSServiceProvider dns) {
_name = name;
_interface_index = interface_index;
_interface_name = interface_name;
this.dns = dns;
}
public async Gee.List<PairingServiceHost> resolve (Cancellable? cancellable) throws Error, IOError {
var task = new ResolveTask (this);
return yield dns.with_dns_service (task, cancellable);
}
private class ResolveTask : DNSServiceTask {
private weak DarwinPairingServiceDetails parent;
private Gee.List<PairingServiceHost> hosts = new Gee.ArrayList<PairingServiceHost> ();
public ResolveTask (DarwinPairingServiceDetails parent) {
this.parent = parent;
}
public override void start () {
session = dns_connection;
DNSService.resolve (ref session, PrivateFive | ShareConnection, parent.interface_index, parent.name,
PAIRING_REGTYPE, PAIRING_DOMAIN, on_resolve_reply);
}
private void on_resolve_reply (DNSService sd_ref, DNSService.Flags flags, uint32 interface_index,
DNSService.ErrorType error_code, string fullname, string hosttarget, uint16 port,
uint8[] raw_txt_record) {
if (error_code != NoError) {
complete (null,
new Error.TRANSPORT ("Unable to resolve service '%s' on interface %s",
parent.name, parent.interface_name));
return;
}
var txt_record = new Gee.ArrayList<string> ();
size_t cursor = 0;
size_t remaining = raw_txt_record.length;
while (remaining != 0) {
size_t len = raw_txt_record[cursor];
cursor++;
remaining--;
if (len > remaining)
break;
unowned string raw_val = (string) raw_txt_record[cursor:cursor + len];
string val = raw_val.make_valid ((ssize_t) len);
txt_record.add (val);
cursor += len;
remaining -= len;
}
hosts.add (new DarwinPairingServiceHost (parent, hosttarget, uint16.from_big_endian (port), txt_record,
parent.dns));
if ((flags & DNSService.Flags.MoreComing) == 0)
complete (hosts, null);
}
}
}
public class DarwinPairingServiceHost : Object, PairingServiceHost {
public string name {
get { return _name; }
}
public uint16 port {
get { return _port; }
}
public Gee.List<string> txt_record {
get { return _txt_record; }
}
private string _name;
private uint16 _port;
private Gee.List<string> _txt_record;
private PairingServiceDetails service;
private DNSServiceProvider dns;
internal DarwinPairingServiceHost (PairingServiceDetails service, string name, uint16 port, Gee.List<string> txt_record,
DNSServiceProvider dns) {
_name = name;
_port = port;
_txt_record = txt_record;
this.service = service;
this.dns = dns;
}
public async Gee.List<InetSocketAddress> resolve (Cancellable? cancellable) throws Error, IOError {
var task = new ResolveTask (this);
return yield dns.with_dns_service (task, cancellable);
}
private class ResolveTask : DNSServiceTask {
private weak DarwinPairingServiceHost parent;
private Gee.List<InetSocketAddress> addresses = new Gee.ArrayList<InetSocketAddress> ();
public ResolveTask (DarwinPairingServiceHost parent) {
this.parent = parent;
}
public override void start () {
session = dns_connection;
DNSService.get_addr_info (ref session, PrivateFive | ShareConnection, parent.service.interface_index, IPv6,
parent.name, on_info_reply);
}
private void on_info_reply (DNSService sd_ref, DNSService.Flags flags, uint32 interface_index,
DNSService.ErrorType error_code, string hostname, void * address, uint32 ttl) {
if (error_code != NoError) {
complete (null,
new Error.TRANSPORT ("Unable to resolve host '%s' on interface %s",
parent.name, parent.service.interface_name));
return;
}
addresses.add ((InetSocketAddress) SocketAddress.from_native (address, sizeof (Posix.SockAddrIn6)));
if ((flags & DNSService.Flags.MoreComing) == 0)
complete (addresses, null);
}
}
}
}
+426
View File
@@ -0,0 +1,426 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public sealed class LinuxTunnelFinder : Object, TunnelFinder {
public async Tunnel? find (string udid, Cancellable? cancellable) throws Error, IOError {
NcmPeer? peer = yield locate_ncm_peer (udid, cancellable);
if (peer == null)
return null;
var bootstrap_disco = yield DiscoveryService.open (
yield peer.open_tcp_connection (58783, cancellable), cancellable);
var tunnel_service = bootstrap_disco.get_service ("com.apple.internal.dt.coredevice.untrusted.tunnelservice");
var pairing_transport = new XpcPairingTransport (yield peer.open_tcp_connection (tunnel_service.port, cancellable));
var pairing_service = yield PairingService.open (pairing_transport, cancellable);
TunnelConnection tc = yield pairing_service.open_tunnel (peer.address, cancellable);
var disco = yield DiscoveryService.open (yield tc.open_connection (tc.remote_rsd_port, cancellable), cancellable);
return new LinuxTunnel (tc, disco);
}
private static async NcmPeer? locate_ncm_peer (string udid, Cancellable? cancellable) throws Error, IOError {
var device_ifaddrs = new Gee.ArrayList<unowned Linux.Network.IfAddrs> ();
var fruit_finder = FruitFinder.make_default ();
string raw_udid = udid.replace ("-", "");
Linux.Network.IfAddrs ifaddrs;
Linux.Network.getifaddrs (out ifaddrs);
for (unowned Linux.Network.IfAddrs candidate = ifaddrs; candidate != null; candidate = candidate.ifa_next) {
if (candidate.ifa_addr.sa_family != Posix.AF_INET6)
continue;
string? candidate_udid = fruit_finder.udid_from_iface (candidate.ifa_name);
if (candidate_udid != raw_udid)
continue;
device_ifaddrs.add (candidate);
}
if (device_ifaddrs.is_empty)
return null;
var sockets = new Gee.ArrayList<Socket> ();
var sources = new Gee.ArrayList<Source> ();
var readable_sockets = new Gee.ArrayQueue<Socket> ();
bool timed_out = false;
bool waiting = false;
var remote_address = new InetSocketAddress.from_string ("ff02::fb", 5353);
var remoted_mdns_request = make_remoted_mdns_request ();
var main_context = MainContext.get_thread_default ();
foreach (unowned Linux.Network.IfAddrs ifaddr in device_ifaddrs) {
try {
var sock = new Socket (IPV6, DATAGRAM, UDP);
sock.bind (SocketAddress.from_native ((void *) ifaddr.ifa_addr, sizeof (Posix.SockAddrIn6)), false);
sock.send_to (remote_address, remoted_mdns_request.get_data (), cancellable);
var source = sock.create_source (IN, cancellable);
source.set_callback (() => {
readable_sockets.offer (sock);
if (waiting)
locate_ncm_peer.callback ();
return Source.REMOVE;
});
source.attach (main_context);
sockets.add (sock);
sources.add (source);
} catch (GLib.Error e) {
}
}
var timeout_source = new TimeoutSource.seconds (2);
timeout_source.set_callback (() => {
timed_out = true;
if (waiting)
locate_ncm_peer.callback ();
return Source.REMOVE;
});
timeout_source.attach (main_context);
sources.add (timeout_source);
Socket? sock;
while ((sock = readable_sockets.poll ()) == null && !timed_out) {
waiting = true;
yield;
waiting = false;
}
foreach (var source in sources)
source.destroy ();
if (sock == null && timed_out)
throw new Error.TIMED_OUT ("Unexpectedly timed out while waiting for mDNS reply");
InetSocketAddress sender;
try {
SocketAddress raw_sender;
var response_buf = new uint8[2048];
sock.receive_from (out raw_sender, response_buf, cancellable);
sender = (InetSocketAddress) raw_sender;
} catch (GLib.Error e) {
throw new Error.TRANSPORT ("%s", e.message);
}
return new NcmPeer ("%s%%%u".printf (sender.address.to_string (), sender.scope_id));
}
private static Bytes make_remoted_mdns_request () {
uint16 transaction_id = 0;
uint16 flags = 0;
uint16 num_questions = 1;
uint16 answer_rrs = 0;
uint16 authority_rrs = 0;
uint16 additional_rrs = 0;
string components[] = { "_remoted", "_tcp", "local" };
uint16 record_type = 12;
uint16 dns_class = 1;
return new BufferBuilder (BIG_ENDIAN)
.append_uint16 (transaction_id)
.append_uint16 (flags)
.append_uint16 (num_questions)
.append_uint16 (answer_rrs)
.append_uint16 (authority_rrs)
.append_uint16 (additional_rrs)
.append_uint8 ((uint8) components[0].length)
.append_string (components[0], StringTerminator.NONE)
.append_uint8 ((uint8) components[1].length)
.append_string (components[1], StringTerminator.NONE)
.append_uint8 ((uint8) components[2].length)
.append_string (components[2], StringTerminator.NUL)
.append_uint16 (record_type)
.append_uint16 (dns_class)
.build ();
}
private class NcmPeer {
public string address;
public class NcmPeer (string address) {
this.address = address;
}
public async IOStream open_tcp_connection (uint16 port, Cancellable? cancellable) throws Error, IOError {
SocketConnection connection;
try {
NetworkAddress service_address = NetworkAddress.parse (address, port);
var client = new SocketClient ();
connection = yield client.connect_async (service_address, cancellable);
} catch (GLib.Error e) {
throw new Error.TRANSPORT ("%s", e.message);
}
Tcp.enable_nodelay (connection.socket);
return connection;
}
}
}
private sealed class LinuxTunnel : Object, Tunnel {
public DiscoveryService discovery {
get {
return _discovery;
}
}
private TunnelConnection tunnel_connection;
private DiscoveryService _discovery;
public LinuxTunnel (TunnelConnection conn, DiscoveryService disco) {
tunnel_connection = conn;
_discovery = disco;
}
public async void close (Cancellable? cancellable) throws IOError {
tunnel_connection.cancel ();
}
public async IOStream open_tcp_connection (uint16 port, Cancellable? cancellable) throws Error, IOError {
return yield tunnel_connection.open_connection (port, cancellable);
}
}
public class LinuxFruitFinder : Object, FruitFinder {
public string? udid_from_iface (string ifname) throws Error {
var net = "/sys/class/net";
var directory = File.new_build_filename (net, ifname);
if (!directory.query_exists ())
return null;
try {
var info = directory.query_info ("standard::*", 0);
if (!info.get_is_symlink ())
return null;
var dev_path = Path.build_filename (net, info.get_symlink_target ());
var iface = File.new_build_filename (dev_path, "..", "..", "interface");
if (!iface.query_exists ())
return null;
var iface_stream = new DataInputStream (iface.read ());
string iface_name = iface_stream.read_line ();
if (iface_name != "NCM Control" && iface_name != "AppleUSBEthernet")
return null;
var serial = File.new_build_filename (dev_path, "..", "..", "..", "serial");
if (!serial.query_exists ())
return null;
var serial_stream = new DataInputStream (serial.read ());
return serial_stream.read_line ();
} catch (GLib.Error e) {
throw new Error.NOT_SUPPORTED ("%s", e.message);
}
}
}
public class LinuxPairingBrowser : Object, PairingBrowser {
private DBusConnection connection;
private AvahiServer server;
private AvahiServiceBrowser browser;
private Gee.List<PairingServiceDetails> current_batch = new Gee.ArrayList<PairingServiceDetails> ();
private Cancellable io_cancellable = new Cancellable ();
construct {
start.begin ();
}
private async void start () {
try {
connection = yield GLib.Bus.get (BusType.SYSTEM, io_cancellable);
server = yield connection.get_proxy (AVAHI_SERVICE_NAME, "/", DO_NOT_LOAD_PROPERTIES, io_cancellable);
GLib.ObjectPath browser_path = yield server.service_browser_prepare (-1, INET6, PAIRING_REGTYPE,
PAIRING_DOMAIN, 0, io_cancellable);
browser = yield connection.get_proxy (AVAHI_SERVICE_NAME, browser_path, DO_NOT_LOAD_PROPERTIES,
io_cancellable);
browser.item_new.connect (on_item_new);
browser.all_for_now.connect (on_all_for_now);
yield browser.start (io_cancellable);
} catch (GLib.Error e) {
printerr ("Oopsie: %s\n", e.message);
}
}
private void on_item_new (int interface_index, AvahiProtocol protocol, string name, string type, string domain, uint flags) {
char raw_interface_name[Linux.Network.INTERFACE_NAME_SIZE];
Linux.Network.if_indextoname (interface_index, (string) raw_interface_name);
unowned string interface_name = (string) raw_interface_name;
current_batch.add (new LinuxPairingServiceDetails (name, interface_index, interface_name, protocol, server));
}
private void on_all_for_now () {
services_discovered (current_batch.to_array ());
current_batch.clear ();
}
}
private class LinuxPairingServiceDetails : Object, PairingServiceDetails {
public string name {
get { return _name; }
}
public uint interface_index {
get { return _interface_index; }
}
public string interface_name {
get { return _interface_name; }
}
private string _name;
private uint _interface_index;
private string _interface_name;
private AvahiProtocol protocol;
private AvahiServer server;
internal LinuxPairingServiceDetails (string name, uint interface_index, string interface_name, AvahiProtocol protocol,
AvahiServer server) {
_name = name;
_interface_index = interface_index;
_interface_name = interface_name;
this.protocol = protocol;
this.server = server;
}
public async Gee.List<PairingServiceHost> resolve (Cancellable? cancellable) throws Error, IOError {
AvahiServiceResolver resolver;
try {
GLib.ObjectPath path = yield server.service_resolver_prepare ((int) interface_index, protocol, name,
PAIRING_REGTYPE, PAIRING_DOMAIN, INET6, 0, cancellable);
DBusConnection connection = ((DBusProxy) server).get_connection ();
resolver = yield connection.get_proxy (AVAHI_SERVICE_NAME, path, DO_NOT_LOAD_PROPERTIES, cancellable);
} catch (GLib.Error e) {
throw new Error.NOT_SUPPORTED ("%s", e.message);
}
var promise = new Promise<Gee.List<PairingServiceHost>> ();
var hosts = new Gee.ArrayList<PairingServiceHost> ();
resolver.found.connect ((interface_index, protocol, name, type, domain, host, address_protocol, address, port, txt,
flags) => {
var txt_record = new Gee.ArrayList<string> ();
var iter = new VariantIter (txt);
Variant? cur;
while ((cur = iter.next_value ()) != null) {
unowned string raw_val = (string) cur.get_data ();
string val = raw_val.make_valid ((ssize_t) cur.get_size ());
txt_record.add (val);
}
hosts.add (new LinuxPairingServiceHost (
host,
new InetSocketAddress.from_string (address, port),
port,
txt_record));
if (!promise.future.ready)
promise.resolve (hosts);
});
resolver.failure.connect (error => {
if (!promise.future.ready)
promise.reject (new Error.NOT_SUPPORTED ("%s", error));
});
try {
yield resolver.start (cancellable);
} catch (GLib.Error e) {
throw new Error.NOT_SUPPORTED ("%s", e.message);
}
return yield promise.future.wait_async (cancellable);
}
}
public class LinuxPairingServiceHost : Object, PairingServiceHost {
public string name {
get { return _name; }
}
public InetSocketAddress address {
get { return _address; }
}
public uint16 port {
get { return _port; }
}
public Gee.List<string> txt_record {
get { return _txt_record; }
}
private string _name;
private InetSocketAddress _address;
private uint16 _port;
private Gee.List<string> _txt_record;
internal LinuxPairingServiceHost (string name, InetSocketAddress address, uint16 port, Gee.List<string> txt_record) {
_name = name;
_address = address;
_port = port;
_txt_record = txt_record;
}
public async Gee.List<InetSocketAddress> resolve (Cancellable? cancellable) throws Error, IOError {
var result = new Gee.ArrayList<InetSocketAddress> ();
result.add (address);
return result;
}
}
private const string AVAHI_SERVICE_NAME = "org.freedesktop.Avahi";
[DBus (name = "org.freedesktop.Avahi.Server2")]
private interface AvahiServer : Object {
public abstract async GLib.ObjectPath service_browser_prepare (int interface_index, AvahiProtocol protocol, string type,
string domain, uint flags, Cancellable? cancellable) throws GLib.Error;
public abstract async GLib.ObjectPath service_resolver_prepare (int interface_index, AvahiProtocol protocol, string name,
string type, string domain, AvahiProtocol aprotocol, AvahiLookupFlags flags, Cancellable? cancellable)
throws GLib.Error;
}
[DBus (name = "org.freedesktop.Avahi.ServiceBrowser")]
private interface AvahiServiceBrowser : Object {
public signal void item_new (int interface_index, AvahiProtocol protocol, string name, string type, string domain,
uint flags);
public signal void item_remove (int interface_index, AvahiProtocol protocol, string name, string type, string domain,
uint flags);
public signal void failure (string error);
public signal void all_for_now ();
public signal void cache_exhausted ();
public abstract async void start (Cancellable? cancellable) throws GLib.Error;
public abstract async void free (Cancellable? cancellable) throws GLib.Error;
}
[DBus (name = "org.freedesktop.Avahi.ServiceResolver")]
private interface AvahiServiceResolver : Object {
public signal void found (int interface_index, AvahiProtocol protocol, string name, string type, string domain, string host,
AvahiProtocol address_protocol, string address, uint16 port, [DBus (signature = "aay")] Variant txt, uint flags);
public signal void failure (string error);
public abstract async void start (Cancellable? cancellable) throws GLib.Error;
public abstract async void free (Cancellable? cancellable) throws GLib.Error;
}
private enum AvahiProtocol {
INET,
INET6,
UNSPEC = -1,
}
[Flags]
private enum AvahiLookupFlags {
USE_WIDE_AREA = 1,
USE_MULTICAST = 2,
NO_TXT = 4,
NO_ADDRESS = 8,
}
}
+420
View File
@@ -0,0 +1,420 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
using Darwin.GCD;
using Darwin.IOKit;
public sealed class MacOSTunnelFinder : Object, TunnelFinder {
public async Tunnel? find (string udid, Cancellable? cancellable) throws Error, IOError {
var main_context = MainContext.ref_thread_default ();
var event_queue = new DispatchQueue ("re.frida.fruity.tunnel", DispatchQueueAttr.SERIAL);
Darwin.Xpc.Dictionary? device_info = null;
bool all_listed = false;
bool waiting = false;
var pairingd = XpcClient.make_for_mach_service ("com.apple.CoreDevice.remotepairingd", event_queue);
pairingd.notify["state"].connect ((obj, pspec) => {
if (waiting)
find.callback ();
});
pairingd.message.connect (obj => {
var reader = new XpcObjectReader (obj);
try {
reader.read_member ("mangledTypeName");
if (reader.get_string_value () == "RemotePairing.ServiceEvent") {
reader
.end_member ()
.read_member ("value");
if (reader.try_read_member ("deviceFound")) {
reader
.read_member ("_0")
.read_member ("deviceInfo")
.read_member ("udid");
if (reader.get_string_value () == udid) {
reader.end_member ();
device_info = (Darwin.Xpc.Dictionary) reader.current_object;
}
} else if (reader.has_member ("allCurrentDevicesListed")) {
all_listed = true;
}
}
} catch (Error e) {
}
var source = new IdleSource ();
source.set_callback (() => {
if (waiting)
find.callback ();
return Source.REMOVE;
});
source.attach (main_context);
});
var r = new PairingdRequest ("RemotePairing.BrowseRequest");
r.body.set_bool ("currentDevicesOnly", true);
yield pairingd.request (r.message, cancellable);
while (!all_listed && pairingd.state == OPEN) {
waiting = true;
yield;
waiting = false;
}
if (device_info == null) {
if (all_listed)
throw new Error.INVALID_ARGUMENT ("Device not found");
else
throw new Error.NOT_SUPPORTED ("Unexpectedly lost connection to remotepairingd");
}
var pairing_device = new XpcClient (device_info.create_connection ("endpoint"), event_queue);
var tunnel = new MacOSTunnel (pairing_device);
yield tunnel.attach (cancellable);
return tunnel;
}
}
private sealed class MacOSTunnel : Object, Tunnel {
public DiscoveryService discovery {
get {
return _discovery;
}
}
private XpcClient pairing_device;
private Darwin.Xpc.Object? assertion_identifier;
private InetAddress? tunnel_device_address;
private DiscoveryService? _discovery;
public MacOSTunnel (XpcClient pairing_device) {
this.pairing_device = pairing_device;
}
public async void close (Cancellable? cancellable) throws IOError {
var r = new PairingdRequest ("RemotePairing.ReleaseAssertionRequest");
r.body.set_value ("assertionIdentifier", assertion_identifier);
try {
yield pairing_device.request (r.message, cancellable);
} catch (Error e) {
}
}
public async void attach (Cancellable? cancellable) throws Error, IOError {
var r = new PairingdRequest ("RemotePairing.CreateAssertionCommand");
r.body.set_int64 ("flags", 0);
var response = yield pairing_device.request (r.message, cancellable);
var reader = new XpcObjectReader (response);
reader.read_member ("response");
assertion_identifier = reader
.read_member ("assertionIdentifier")
.get_object_value (Darwin.Xpc.Uuid.TYPE);
reader.end_member ();
string tunnel_ip_address = reader
.read_member ("info")
.read_member ("tunnelIPAddress")
.get_string_value ();
tunnel_device_address = new InetAddress.from_string (tunnel_ip_address);
_discovery = yield locate_discovery_service (tunnel_device_address, cancellable);
}
public async IOStream open_tcp_connection (uint16 port, Cancellable? cancellable) throws Error, IOError {
SocketConnection connection;
try {
var service_address = new InetSocketAddress (tunnel_device_address, port);
var client = new SocketClient ();
connection = yield client.connect_async (service_address, cancellable);
} catch (GLib.Error e) {
throw new Error.TRANSPORT ("%s", e.message);
}
Tcp.enable_nodelay (connection.socket);
return connection;
}
private static async DiscoveryService locate_discovery_service (InetAddress tunnel_device_address, Cancellable? cancellable)
throws Error, IOError {
var path_buf = new char[4096];
unowned string path = (string) path_buf;
foreach (var item in XNU.query_active_tcp_connections ()) {
if (item.family != IPV6)
continue;
if (!item.foreign_address.equal (tunnel_device_address))
continue;
if (Darwin.XNU.proc_pidpath (item.effective_pid, path_buf) <= 0)
continue;
if (path != "/usr/libexec/remoted")
continue;
try {
var connectable = new InetSocketAddress (tunnel_device_address, item.foreign_port);
var sc = new SocketClient ();
SocketConnection connection = yield sc.connect_async (connectable, cancellable);
Tcp.enable_nodelay (connection.socket);
return yield DiscoveryService.open (connection, cancellable);
} catch (GLib.Error e) {
}
}
throw new Error.NOT_SUPPORTED ("Unable to detect RSD port");
}
}
private class PairingdRequest {
public Darwin.Xpc.Dictionary message = new Darwin.Xpc.Dictionary ();
public Darwin.Xpc.Dictionary body = new Darwin.Xpc.Dictionary ();
public PairingdRequest (string name) {
message.set_string ("mangledTypeName", name);
message.set_value ("value", body);
}
}
public class MacOSFruitFinder : Object, FruitFinder {
public string? udid_from_iface (string ifname) throws Error {
var matching_dict = Darwin.IOKit.service_matching (Darwin.IOKit.ETHERNET_INTERFACE_CLASS);
if (matching_dict == null)
return null;
matching_dict.add (CoreFoundation.String.make (Darwin.IOKit.BSD_NAME_KEY), CoreFoundation.String.make (ifname));
var registry = IORegistry.open ();
foreach (var service in registry.matching_services (matching_dict)) {
var usb_serial = find_idevice (service.parent (Darwin.IOKit.IOSERVICE_PLANE));
if (usb_serial != null)
return usb_serial;
}
return null;
}
private string? find_idevice (IORegistryEntry service) throws Error {
if (service.get_string_property ("CFBundleIdentifier") == "com.apple.driver.usb.cdc.ncm")
return find_idevice (service.parent (Darwin.IOKit.IOSERVICE_PLANE));
var props = service.get_properties ();
var prod = props.get_string_value ("USB Product Name");
if (prod != "iPhone" && prod != "iPad")
return null;
return props.get_string_value ("USB Serial Number");
}
}
namespace XNU {
public PcbList query_active_tcp_connections () {
size_t size = 0;
Darwin.XNU.sysctlbyname ("net.inet.tcp.pcblist_n", null, &size);
var pcbs = new uint8[size];
Darwin.XNU.sysctlbyname ("net.inet.tcp.pcblist_n", pcbs, &size);
return new PcbList (pcbs);
}
public class PcbList {
private uint8[] pcbs;
internal PcbList (owned uint8[] pcbs) {
this.pcbs = (owned) pcbs;
}
public Iterator iterator () {
return new Iterator (this);
}
public class Iterator {
private PcbList list;
private InetItem * cursor;
internal Iterator (PcbList list) {
this.list = list;
var gen = (Darwin.XNU.InetPcbGeneration *) list.pcbs;
cursor = (InetItem *) ((uint8 *) list.pcbs + gen->length);
}
public Item? next_value () {
InetPcb * pcb = null;
while (true) {
if (cursor->length == 24)
return null;
switch (cursor->kind) {
case InetItemKind.PCB:
pcb = (InetPcb *) cursor;
break;
case InetItemKind.SOCKET:
var item = new Item (*pcb, *((InetSocket *) cursor));
advance ();
return item;
}
advance ();
}
}
private void advance () {
uint32 l = cursor->length;
if (l % 8 != 0)
l += 8 - (l % 8);
cursor = (InetItem *) ((uint8 *) cursor + l);
}
}
public class Item {
public SocketFamily family {
get {
return ((pcb.version_flag & Darwin.XNU.InetVersionFlags.IPV6) != 0)
? SocketFamily.IPV6
: SocketFamily.IPV4;
}
}
public InetAddress local_address {
get {
if (cached_local_address == null)
cached_local_address = parse_address (pcb.local_address);
return cached_local_address;
}
}
public uint16 local_port {
get {
return uint16.from_big_endian (pcb.local_port);
}
}
public InetAddress foreign_address {
get {
if (cached_foreign_address == null)
cached_foreign_address = parse_address (pcb.foreign_address);
return cached_foreign_address;
}
}
public uint16 foreign_port {
get {
return uint16.from_big_endian (pcb.foreign_port);
}
}
public int32 effective_pid {
get {
return sock.effective_pid;
}
}
private InetPcb pcb;
private InetSocket sock;
private InetAddress? cached_local_address;
private InetAddress? cached_foreign_address;
public Item (InetPcb pcb, InetSocket sock) {
this.pcb = pcb;
this.sock = sock;
}
private InetAddress parse_address (uint8[] bytes) {
if ((pcb.version_flag & Darwin.XNU.InetVersionFlags.IPV6) != 0)
return new InetAddress.from_bytes (bytes, IPV6);
var addr = (Darwin.XNU.InetAddr4in6 *) bytes;
return new InetAddress.from_bytes ((uint8[]) &addr->addr4.s_addr, IPV4);
}
}
}
[SimpleType]
public struct InetItem {
public uint32 length;
public uint32 kind;
}
public enum InetItemKind {
SOCKET = 0x001,
PCB = 0x010,
}
[SimpleType]
public struct InetPcb {
public uint32 length;
public uint32 kind;
public uint64 inpp;
public uint16 foreign_port;
public uint16 local_port;
public uint32 per_protocol_pcb_low;
public uint32 per_protocol_pcb_high;
public uint32 generation_count_low;
public uint32 generation_count_high;
public int flags;
public uint32 flow;
public uint8 version_flag;
public uint8 ip_ttl;
public uint8 ip_protocol;
public uint8 padding;
public uint8 foreign_address[16];
public uint8 local_address[16];
public InetDepend4 depend4;
public InetDepend6 depend6;
public uint32 flowhash;
public uint32 flags2;
}
[SimpleType]
public struct InetSocket {
public uint32 length;
public uint32 kind;
public uint64 so;
public int16 type;
public uint16 options_low;
public uint16 options_high;
public int16 linger;
public int16 state;
public uint16 pcb[4];
public uint16 protocol_low;
public uint16 protocol_high;
public uint16 family_low;
public uint16 family_high;
public int16 qlen;
public int16 incqlen;
public int16 qlimit;
public int16 timeo;
public uint16 error;
public int32 pgid;
public uint32 oobmark;
public uint32 uid;
public int32 last_pid;
public int32 effective_pid;
public uint64 gencnt;
public uint32 flags;
public uint32 flags1;
public int32 usecount;
public int32 retaincnt;
public uint32 filter_flags;
}
[SimpleType]
public struct InetDepend4 {
public uint8 ip_tos;
}
[SimpleType]
public struct InetDepend6 {
public uint8 hlim;
public int checksum;
public uint16 interface_index;
public int16 hops;
}
}
}
+4419
View File
File diff suppressed because it is too large. Load diff
+7 -3
View File
@@ -177,12 +177,16 @@ namespace Frida {
}
}
public interface ChannelProvider : Object {
public interface HostChannelProvider : Object {
public abstract async IOStream open_channel (string address, Cancellable? cancellable = null) throws Error, IOError;
}
public interface HostServiceProvider : Object {
public abstract async Service open_service (string address, Cancellable? cancellable = null) throws Error, IOError;
}
public interface Pairable : Object {
public abstract async void unpair (Cancellable? cancellable) throws Error, IOError;
public abstract async void unpair (Cancellable? cancellable = null) throws Error, IOError;
}
public interface HostSessionBackend : Object {
@@ -1537,7 +1541,7 @@ namespace Frida {
#if HAVE_FRUITY_BACKEND || HAVE_DROIDY_BACKEND
internal async DBusConnection establish_direct_connection (TransportBroker broker, AgentSessionId id,
ChannelProvider channel_provider, Cancellable? cancellable) throws Error, IOError {
HostChannelProvider channel_provider, Cancellable? cancellable) throws Error, IOError {
uint16 port;
string token;
try {
+40 -2
View File
@@ -470,8 +470,8 @@ if have_local_backend
agent_legacy,
agent_emulated_modern,
agent_emulated_legacy,
get_option('agent_dbghelp_prefix'),
get_option('agent_symsrv_prefix'),
gum_dep.get_variable('frida_dbghelp_prefix'),
gum_dep.get_variable('frida_symsrv_prefix'),
],
depends: agent_depends,
)
@@ -481,6 +481,7 @@ endif
if have_fruity_backend
backend_sources += [
'fruity' / 'fruity-host-session.vala',
'fruity' / 'xpc.vala',
'fruity' / 'dtx.vala',
'fruity' / 'lockdown.vala',
'fruity' / 'installation-proxy.vala',
@@ -492,6 +493,7 @@ if have_fruity_backend
'fruity' / 'plist.vala',
'fruity' / 'plist-service.vala',
]
if host_os_family == 'windows'
backend_sources += 'fruity' / 'fruity-host-session-windows.c'
elif host_os_family == 'darwin'
@@ -499,6 +501,41 @@ if have_fruity_backend
else
backend_sources += 'fruity' / 'fruity-host-session-unix.c'
endif
if host_os_family == 'darwin'
backend_sources += 'fruity' / 'xpc-darwin.vala'
endif
if host_os == 'macos'
backend_sources += [
'fruity' / 'xpc-macos.vala',
'fruity' / 'iokit.vala',
]
elif host_os == 'linux'
backend_sources += 'fruity' / 'xpc-linux.vala'
endif
backend_deps += openssl_dep
backend_vala_args += [
'--pkg=libnghttp2',
'--pkg=libngtcp2',
'--pkg=libngtcp2_crypto_quictls',
'--pkg=lwip',
'--pkg=openssl',
]
if host_os_family == 'darwin'
backend_vala_args += [
'--pkg=darwin-xnu',
'--pkg=darwin-iokit',
'--pkg=darwin-xpc',
'--pkg=darwin-gcd',
'--pkg=darwin-net',
'--pkg=darwin-dns-sd',
'--pkg=corefoundation',
]
endif
if host_os_family == 'linux'
backend_vala_args += '--pkg=linux'
endif
endif
if have_droidy_backend
@@ -556,6 +593,7 @@ core_deps += backend_deps_private
core_vala_args = [
backend_vala_args,
base_vala_args,
'--pkg=gio-2.0',
gio_platform_vala_args,
'--pkg=json-glib-1.0',
+1 -1
View File
@@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/frida/frida-gum.git
revision = 16.2.2
revision = 16.3.2
depth = 1
[provide]
+1 -1
View File
@@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/frida/libnice.git
revision = a0f43f0ea5755ce0374613b0a157be33a9f7d82e
revision = e12567b0a16a0c2eb5dfe5e0782baba8496772ff
depth = 1
[provide]
+8
View File
@@ -0,0 +1,8 @@
[wrap-git]
url = https://github.com/frida/lwip.git
revision = 9f64c40cac2e77eddf6b3913961fdd056d307716
depth = 1
[provide]
dependency_names = lwip
+8
View File
@@ -0,0 +1,8 @@
[wrap-git]
url = https://github.com/frida/ngtcp2.git
revision = cc5cf523615b7fa7a9340234c7eec3c3645ae969
depth = 1
[provide]
dependency_names = libngtcp2, libngtcp2_crypto_quictls
+1 -1
View File
@@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/frida/openssl.git
revision = 95d037b2acc432039da4f506d25b6a01577d8bc5
revision = ca4781aaf7910b623d3ae21c6a017e7e9ca6936c
depth = 1
[provide]
+51 -10
View File
@@ -60,6 +60,11 @@ namespace Frida.HostSessionTest {
var h = new Harness ((h) => Fruity.Manual.lockdown.begin (h as Harness));
h.run ();
});
GLib.Test.add_func ("/HostSession/Fruity/Manual/xpc", () => {
var h = new Harness ((h) => Fruity.Manual.xpc.begin (h as Harness));
h.run ();
});
#endif
#if HAVE_DROIDY_BACKEND
@@ -3517,16 +3522,17 @@ namespace Frida.HostSessionTest {
#endif
Variant? icon = prov.icon;
assert_nonnull (icon);
var dict = new VariantDict (icon);
int64 width, height;
assert_true (dict.lookup ("width", "x", out width));
assert_true (dict.lookup ("height", "x", out height));
assert_true (width == 16);
assert_true (height == 16);
VariantIter image;
assert_true (dict.lookup ("image", "ay", out image));
assert_true (image.n_children () == width * height * 4);
if (icon != null) {
var dict = new VariantDict (icon);
int64 width, height;
assert_true (dict.lookup ("width", "x", out width));
assert_true (dict.lookup ("height", "x", out height));
assert_true (width == 16);
assert_true (height == 16);
VariantIter image;
assert_true (dict.lookup ("image", "ay", out image));
assert_true (image.n_children () == width * height * 4);
}
try {
Cancellable? cancellable = null;
@@ -3741,6 +3747,41 @@ namespace Frida.HostSessionTest {
h.done ();
}
private static async void xpc (Harness h) {
if (!GLib.Test.slow ()) {
stdout.printf ("<skipping, run in slow mode with iOS device connected> ");
h.done ();
return;
}
var device_id = "<device-id>";
var device_manager = new DeviceManager ();
try {
var timer = new Timer ();
var device = yield device_manager.get_device_by_id (device_id);
printerr ("[*] Got device in %u ms\n", (uint) (timer.elapsed () * 1000.0));
timer.reset ();
var appservice = yield device.open_service ("xpc:com.apple.coredevice.appservice");
printerr ("[*] Opened service in %u ms\n", (uint) (timer.elapsed () * 1000.0));
var parameters = new HashTable<string, Variant> (str_hash, str_equal);
parameters["CoreDevice.featureIdentifier"] = "com.apple.coredevice.feature.listprocesses";
parameters["CoreDevice.action"] = new HashTable<string, Variant> (str_hash, str_equal);
parameters["CoreDevice.input"] = new HashTable<string, Variant> (str_hash, str_equal);
timer.reset ();
var response = yield appservice.request (parameters);
printerr ("[*] Made request in %u ms\n", (uint) (timer.elapsed () * 1000.0));
printerr ("Got response: %s\n", response.print (true));
} catch (GLib.Error e) {
printerr ("\nFAIL: %s\n\n", e.message);
}
h.done ();
}
}
namespace Plist {
+104
View File
@@ -0,0 +1,104 @@
[CCode (cheader_filename = "CoreFoundation/CFDictionary.h", gir_namespace = "Darwin", gir_version = "1.0")]
namespace CoreFoundation {
[Compact]
[CCode (cname = "struct __CFDictionary", ref_function = "CFRetain", unref_function = "CFRelease")]
public class Dictionary : Type {
[CCode (cname = "CFDictionaryGetCount")]
public Index count ();
[CCode (cname = "CFDictionaryGetValue")]
public void * @get (void * key);
public string get_string_value (string key) {
return ((String) @get (String.make (key))).to_string ();
}
}
[Compact]
[CCode (cname = "struct __CFDictionary", ref_function = "CFRetain", unref_function = "CFRelease")]
public class MutableDictionary : Dictionary {
[CCode (cname = "CFDictionaryRemoveAllValues")]
public void clear ();
[CCode (cname = "CFDictionaryAddValue")]
public void add (void * key, void * value);
[CCode (cname = "CFDictionaryRemoveValue")]
public void remove (void * key);
}
// TODO: Inherit CFTypeRef? CFStringRef vs __CFString
[Compact]
[CCode (cname = "const struct __CFString", ref_function = "CFRetain", unref_function = "CFRelease")]
public class String : Type {
public Index length {
get { return _length (); }
}
public static String make (string str) {
return from_cstring (null, str, StringEncoding.UTF8);
}
public string to_string () {
var max_length = max_size_for_encoding (length, StringEncoding.UTF8) + 1;
var buffer = new char[max_length];
to_cstring (buffer, max_length, StringEncoding.UTF8);
return (string) buffer;
}
[CCode (cname = "CFStringCreateWithCString")]
private static String from_cstring (Allocator? allocator, uint8 * c_str, StringEncoding encoding);
[CCode (cname = "CFStringGetCString")]
private bool to_cstring (uint8 * buffer, Index buffer_size, StringEncoding encoding);
[CCode (cname = "CFStringGetLength")]
private Index _length ();
[CCode (cname = "CFStringGetMaximumSizeForEncoding")]
private static Index max_size_for_encoding (Index length, StringEncoding encoding);
}
[CCode (cname = "CFStringEncoding", cprefix = "kCFStringEncoding", has_type_id = false)]
public enum StringEncoding {
MacRoman,
WindowsLatin1,
ISOLatin1,
NextStepLatin,
ASCII,
Unicode,
UTF8,
NonLossyASCII,
UTF16,
UTF16BE,
UTF16LE,
UTF32,
UTF32BE,
UTF32LE,
}
[Compact]
[CCode (cname = "const void", ref_function = "CFRetain", unref_function = "CFRelease")]
public class Type {
[CCode (cname = "CFShow")]
public void show ();
public string to_string () {
return description ().to_string ();
}
[CCode (cname = "CFCopyDescription")]
private String description ();
}
[Compact]
[CCode (cname = "CFAllocatorRef")]
public class Allocator {
[CCode (cname = "CFAllocatorGetDefault")]
public static Allocator get_default ();
}
[CCode (cname = "CFIndex", has_type_id = false)]
public struct Index : long {
}
}
+134
View File
@@ -0,0 +1,134 @@
[CCode (cheader_filename = "dns_sd.h", gir_namespace = "Darwin", gir_version = "1.0")]
namespace Darwin.DNSSD {
[CCode (cname = "DNSServiceRef", ref_function = "", unref_function = "")]
public class DNSService {
[CCode (cname = "DNSServiceCreateConnection")]
public static ErrorType create_connection (out DNSService service);
[CCode (cname = "DNSServiceRefDeallocate")]
public void deallocate ();
[CCode (cname = "DNSServiceSetDispatchQueue")]
public ErrorType set_dispatch_queue (Darwin.GCD.DispatchQueue queue);
[CCode (cname = "DNSServiceBrowse")]
public static ErrorType browse (ref DNSService sd_ref, Flags flags, uint32 interface_index, string regtype, string? domain,
BrowseReply callback);
[CCode (cname = "DNSServiceResolve")]
public static ErrorType resolve (ref DNSService sd_ref, Flags flags, uint32 interface_index, string name, string regtype,
string domain, ResolveReply callback);
[CCode (cname = "DNSServiceGetAddrInfo")]
public static ErrorType get_addr_info (ref DNSService sd_ref, Flags flags, uint32 interface_index, Protocol protocol,
string hostname, GetAddrInfoReply callback);
[CCode (cname = "DNSServiceBrowseReply")]
public delegate void BrowseReply (DNSService sd_ref, Flags flags, uint32 interface_index, ErrorType error_code,
string service_name, string regtype, string reply_domain);
[CCode (cname = "DNSServiceResolveReply")]
public delegate void ResolveReply (DNSService sd_ref, Flags flags, uint32 interface_index, ErrorType error_code,
string fullname, string hosttarget, uint16 port, [CCode (array_length_pos = 7.9, array_length_type = "uint16_t")] uint8[] txt_record);
[CCode (cname = "DNSServiceGetAddrInfoReply")]
public delegate void GetAddrInfoReply (DNSService sd_ref, Flags flags, uint32 interface_index, ErrorType error_code,
string hostname, void * address, uint32 ttl);
[CCode (cname = "DNSServiceErrorType", cprefix = "kDNSServiceErr_", has_type_id = false)]
public enum ErrorType {
NoError,
Unknown,
NoSuchName,
NoMemory,
BadParam,
BadReference,
BadState,
BadFlags,
Unsupported,
NotInitialized,
AlreadyRegistered,
NameConflict,
Invalid,
Firewall,
Incompatible,
BadInterfaceIndex,
Refused,
NoSuchRecord,
NoAuth,
NoSuchKey,
NATTraversal,
DoubleNAT,
BadTime,
BadSig,
BadKey,
Transient,
ServiceNotRunning,
NATPortMappingUnsupported,
NATPortMappingDisabled,
NoRouter,
PollingMode,
Timeout,
DefunctConnection,
PolicyDenied,
NotPermitted,
}
[CCode (cname = "DNSServiceFlags", cprefix = "kDNSServiceFlags", has_type_id = false)]
[Flags]
public enum Flags {
MoreComing,
QueueRequest,
AutoTrigger,
Add,
Default,
NoAutoRename,
Shared,
Unique,
BrowseDomains,
RegistrationDomains,
LongLivedQuery,
AllowRemoteQuery,
ForceMulticast,
Force,
KnownUnique,
ReturnIntermediates,
ShareConnection,
SuppressUnusable,
Timeout,
IncludeP2P,
WakeOnResolve,
BackgroundTrafficClass,
IncludeAWDL,
EnableDNSSEC,
Validate,
Secure,
Insecure,
Bogus,
Indeterminate,
UnicastResponse,
ValidateOptional,
WakeOnlyService,
ThresholdOne,
ThresholdFinder,
ThresholdReached,
PrivateOne,
PrivateTwo,
PrivateThree,
PrivateFour,
PrivateFive,
[CCode (cname = "kDNSServiceFlagAnsweredFromCache")]
AnsweredFromCache,
AllowExpiredAnswers,
ExpiredAnswer,
}
[CCode (cname = "DNSServiceProtocol", cprefix = "kDNSServiceProtocol_", has_type_id = false)]
public enum Protocol {
IPv4 = 0x01,
IPv6 = 0x02,
UDP = 0x10,
TCP = 0x20,
}
}
}
+30
View File
@@ -0,0 +1,30 @@
[CCode (cheader_filename = "dispatch/dispatch.h", gir_namespace = "Darwin", gir_version = "1.0")]
namespace Darwin.GCD {
[Compact]
[CCode (cname = "void", ref_function = "_frida_dispatch_retain", unref_function = "dispatch_release",
cheader_filename = "frida-darwin.h")]
public class DispatchQueue {
[CCode (cname = "dispatch_queue_create")]
public DispatchQueue (string label, DispatchQueueAttr attr);
[CCode (cname = "dispatch_async_f")]
public void dispatch_async ([CCode (delegate_target_pos = 0.9)] DispatchFunction work);
[CCode (cname = "dispatch_sync_f")]
public void dispatch_sync ([CCode (delegate_target_pos = 0.9)] DispatchFunction work);
}
[CCode (cname = "dispatch_function_t")]
public delegate void DispatchFunction ();
[Compact]
[CCode (cname = "dispatch_queue_attr_t", cprefix = "DISPATCH_QUEUE_")]
public class DispatchQueueAttr {
public static DispatchQueueAttr SERIAL;
public static DispatchQueueAttr SERIAL_INACTIVE;
public static DispatchQueueAttr CONCURRENT;
public static DispatchQueueAttr CONCURRENT_INACTIVE;
public static DispatchQueueAttr SERIAL_WITH_AUTORELEASE_POOL;
public static DispatchQueueAttr CONCURRENT_WITH_AUTORELEASE_POOL;
}
}
+58
View File
@@ -0,0 +1,58 @@
[CCode (cheader_filename = "IOKit/IOKitLib.h", gir_namespace = "Darwin", gir_version = "1.0")]
namespace Darwin.IOKit {
using CoreFoundation;
using Darwin.XNU;
[CCode (cname = "IOMasterPort")]
public KernReturn main_port (MachPort bootstrap_port, out MachPort main_port);
[CCode (cname = "IOServiceMatching")]
public MutableDictionary service_matching (string name);
[CCode (cname = "IOServiceGetMatchingServices")]
public KernReturn get_matching_services (MachPort main_port, owned MutableDictionary matching_dict,
out IOIterator iterator);
[CCode (cname = "kIOEthernetInterfaceClass", cheader_filename = "IOKit/network/IOEthernetInterface.h")]
public const string ETHERNET_INTERFACE_CLASS;
[CCode (cname = "kIOBSDNameKey", cheader_filename = "IOKit/IOBSD.h")]
public const string BSD_NAME_KEY;
[CCode (cname = "kIOServicePlane", cheader_filename = "IOKit/IOKitKeys.h")]
public const string IOSERVICE_PLANE;
[CCode (cname = "io_registry_entry_t", destroy_function = "IOObjectRelease", has_type_id = false)]
public struct IORegistryEntry : IOObject {
[CCode (cname = "IORegistryEntryCreateCFProperties")]
public KernReturn create_cf_properties (out MutableDictionary properties, Allocator? allocator, uint options);
[CCode (cname = "IORegistryEntryCreateCFProperty")]
public CoreFoundation.Type create_cf_property (String key, Allocator? allocator, uint options);
[CCode (cname = "IORegistryEntryGetParentEntry")]
public KernReturn get_parent_entry (string plane, out IOObject parent);
}
[CCode (cname = "io_iterator_t", destroy_function = "IOObjectRelease")]
public struct IOIterator : MachPort {
[CCode (cname = "IOIteratorReset")]
public void reset ();
[CCode (cname = "IOIteratorIsValid")]
public bool is_valid ();
[CCode (cname = "IOIteratorNext")]
public IOObject next ();
}
[CCode (cname = "io_service_t", destroy_function = "IOObjectRelease", has_type_id = false)]
public struct IOService : IOObject {
}
[CCode (cname = "io_object_t", destroy_function = "IOObjectRelease", has_type_id = false)]
public struct IOObject : MachPort {
[CCode (cname = "IO_OBJECT_NULL")]
public const IOObject NULL;
}
}
+6
View File
@@ -0,0 +1,6 @@
[CCode (cheader_filename = "net/if.h", lower_case_cprefix = "", gir_namespace = "Darwin", gir_version = "1.0")]
namespace Darwin.Net {
public const int IFNAMSIZ;
public unowned string? if_indextoname (uint ifindex, [CCode (array_length = false)] char[] ifname);
}
+104
View File
@@ -0,0 +1,104 @@
[CCode (lower_case_cprefix = "", gir_namespace = "Darwin", gir_version = "1.0")]
namespace Darwin.XNU {
[CCode (cname = "kern_return_t", cheader_filename = "mach/mach_error.h", cprefix = "KERN_", has_type_id = false)]
public enum KernReturn {
SUCCESS,
INVALID_ADDRESS,
PROTECTION_FAILURE,
NO_SPACE,
INVALID_ARGUMENT,
FAILURE,
RESOURCE_SHORTAGE,
NOT_RECEIVER,
NO_ACCESS,
MEMORY_FAILURE,
MEMORY_ERROR,
ALREADY_IN_SET,
NOT_IN_SET,
NAME_EXISTS,
ABORTED,
INVALID_NAME,
INVALID_TASK,
INVALID_RIGHT,
INVALID_VALUE,
UREFS_OVERFLOW,
INVALID_CAPABILITY,
RIGHT_EXISTS,
INVALID_HOST,
MEMORY_PRESENT,
MEMORY_DATA_MOVED,
MEMORY_RESTART_COPY,
INVALID_PROCESSOR_SET,
POLICY_LIMIT,
INVALID_POLICY,
INVALID_OBJECT,
ALREADY_WAITING,
DEFAULT_SET,
EXCEPTION_PROTECTED,
INVALID_LEDGER,
INVALID_MEMORY_CONTROL,
INVALID_SECURITY,
NOT_DEPRESSED,
TERMINATED,
LOCK_SET_DESTROYED,
LOCK_UNSTABLE,
LOCK_OWNED,
LOCK_OWNED_SELF,
SEMAPHORE_DESTROYED,
RPC_SERVER_TERMINATED,
RPC_TERMINATE_ORPHAN,
RPC_CONTINUE_ORPHAN,
NOT_SUPPORTED,
NODE_DOWN,
NOT_WAITING,
OPERATION_TIMED_OUT,
CODESIGN_ERROR,
POLICY_STATIC,
INSUFFICIENT_BUFFER_SIZE,
DENIED,
MISSING_KC,
INVALID_KC,
NOT_FOUND,
RETURN_MAX,
}
[CCode (cheader_filename = "mach/mach_error.h")]
public static unowned string mach_error_string (KernReturn kr);
[CCode (cname = "mach_port_t", has_type_id = false)]
public struct MachPort : uint {
[CCode (cname = "MACH_PORT_NULL")]
public const MachPort NULL;
}
[CCode (cheader_filename = "libproc.h")]
public int proc_pidpath (int pid, char[] buffer);
[CCode (cheader_filename = "sys/sysctl.h")]
public int sysctlbyname (string name, void * oldp, size_t * oldlenp, void * newp = null, size_t newlen = 0);
[CCode (cname = "struct xinpgen", cheader_filename = "netinet/in_pcb.h")]
public struct InetPcbGeneration {
[CCode (cname = "xig_len")]
public int32 length;
[CCode (cname = "xig_count")]
public uint count;
[CCode (cname = "xig_gen")]
public uint64 generation_count;
[CCode (cname = "xig_sogen")]
public uint64 socket_generation_count;
}
[CCode (cname = "struct in_addr_4in6", cheader_filename = "netinet/in_pcb.h")]
public struct InetAddr4in6 {
[CCode (cname = "ia46_addr4")]
public Posix.InAddr addr4;
}
[CCode (cprefix = "INP_", cheader_filename = "netinet/in_pcb.h")]
public enum InetVersionFlags {
IPV4,
IPV6,
V4MAPPEDV6,
}
}
+161
View File
@@ -0,0 +1,161 @@
[CCode (cheader_filename = "xpc/xpc.h", lower_case_cprefix = "xpc_", gir_namespace = "Darwin", gir_version = "1.0")]
namespace Darwin.Xpc {
[Compact]
[CCode (cname = "gpointer", ref_function = "xpc_retain", unref_function = "xpc_release")]
public class Connection {
public static Connection create (string? name, GCD.DispatchQueue targetq);
public static Connection create_mach_service (string? name, GCD.DispatchQueue targetq, uint64 flags = 0);
[CCode (cname = "_frida_xpc_connection_set_event_handler", cheader_filename = "frida-darwin.h")]
public void set_event_handler (Handler handler);
public void activate ();
public void cancel ();
public void send_message (Object message);
[CCode (cname = "_frida_xpc_connection_send_message_with_reply", cheader_filename = "frida-darwin.h")]
public void send_message_with_reply (Object message, GCD.DispatchQueue replyq, owned Handler handler);
}
[CCode (cname = "FridaXpcHandler")]
public delegate void Handler (Object object);
[Compact]
[CCode (cname = "gpointer", ref_function = "xpc_retain", unref_function = "xpc_release")]
public class Object {
public Type type {
[CCode (cname = "xpc_get_type")]
get;
}
[CCode (cname = "_frida_xpc_object_to_string", cheader_filename = "frida-darwin.h")]
public string to_string ();
}
[Compact]
[CCode (cname = "gpointer")]
public class Type {
public string name {
get;
}
}
[Compact]
[CCode (cname = "gpointer")]
public class Bool : Object {
[CCode (cname = "XPC_TYPE_BOOL")]
public static Type TYPE;
[CCode (cname = "xpc_bool_create")]
public Bool (bool val);
public bool get_value ();
}
[Compact]
[CCode (cname = "gpointer")]
public class Int64 : Object {
[CCode (cname = "XPC_TYPE_INT64")]
public static Type TYPE;
[CCode (cname = "xpc_int64_create")]
public Int64 (int64 val);
public int64 get_value ();
}
[Compact]
[CCode (cname = "gpointer")]
public class UInt64 : Object {
[CCode (cname = "XPC_TYPE_UINT64")]
public static Type TYPE;
[CCode (cname = "xpc_uint64_create")]
public UInt64 (uint64 val);
public uint64 get_value ();
}
[Compact]
[CCode (cname = "gpointer")]
public class String : Object {
[CCode (cname = "XPC_TYPE_STRING")]
public static Type TYPE;
[CCode (cname = "xpc_string_create")]
public String (string val);
public unowned string get_string_ptr ();
}
[Compact]
[CCode (cname = "gpointer")]
public class Uuid : Object {
[CCode (cname = "XPC_TYPE_UUID")]
public static Type TYPE;
[CCode (array_length = false)]
public unowned uint8[] get_bytes ();
}
[Compact]
[CCode (cname = "gpointer")]
public class Array : Object {
[CCode (cname = "XPC_TYPE_ARRAY")]
public static Type TYPE;
public size_t count {
get;
}
[CCode (cname = "xpc_array_create_empty")]
public Array ();
public unowned Object? get_value (size_t index);
public void set_value (size_t index, Object val);
}
[Compact]
[CCode (cname = "gpointer")]
public class Dictionary : Object {
[CCode (cname = "XPC_TYPE_DICTIONARY")]
public static Type TYPE;
[CCode (cname = "xpc_dictionary_create_empty")]
public Dictionary ();
public bool get_bool (string key);
public void set_bool (string key, bool val);
public int64 get_int64 (string key);
public void set_int64 (string key, int64 val);
public uint64 get_uint64 (string key);
public void set_uint64 (string key, uint64 val);
public unowned string? get_string (string key);
public void set_string (string key, string val);
public unowned Dictionary? get_dictionary (string key);
public unowned Object? get_value (string key);
public void set_value (string key, Object val);
[CCode (cname = "_frida_xpc_dictionary_apply", cheader_filename = "frida-darwin.h")]
public bool apply (DictionaryApplier applier);
public Connection? create_connection (string key);
}
[CCode (cname = "FridaXpcDictionaryApplier")]
public delegate bool DictionaryApplier (string key, Object val);
[Compact]
[CCode (cname = "gpointer")]
public class Error : Dictionary {
[CCode (cname = "XPC_TYPE_ERROR")]
public static Type TYPE;
public const string KEY_DESCRIPTION;
}
}
+358
View File
@@ -0,0 +1,358 @@
[CCode (cheader_filename = "nghttp2/nghttp2.h", cprefix = "nghttp2_", gir_namespace = "NGHttp2", gir_version = "1.0")]
namespace NGHttp2 {
[Compact]
[CCode (cname = "nghttp2_session", cprefix = "nghttp2_session_", free_function = "nghttp2_session_del")]
public class Session {
[CCode (cname = "nghttp2_session_client_new2")]
public static int make_client (out Session session, SessionCallbacks callbacks, void * user_data, Option? option = null);
[CCode (cname = "nghttp2_submit_settings")]
public int submit_settings (uint8 flags, SettingsEntry[] entries);
[CCode (cname = "nghttp2_submit_window_update")]
public int submit_window_update (uint8 flags, int32 stream_id, int32 window_size_increment);
public int set_local_window_size (uint8 flags, int32 stream_id, int32 window_size);
[CCode (cname = "nghttp2_submit_request")]
public int32 submit_request (PrioritySpec? pri_spec, NV[] nvs, DataProvider? data_prd, void * stream_user_data);
[CCode (cname = "nghttp2_submit_headers")]
public int32 submit_headers (uint8 flags, int32 stream_id, PrioritySpec? pri_spec, NV[] nvs, void * stream_user_data);
[CCode (cname = "nghttp2_submit_data")]
public int submit_data (uint8 flags, int32 stream_id, DataProvider data_prd);
public int send ();
public ssize_t mem_recv (uint8[] input);
public bool want_read ();
public bool want_write ();
public int consume_connection (size_t size);
}
[Compact]
[CCode (cname = "nghttp2_session_callbacks", cprefix = "nghttp2_session_callbacks_",
free_function = "nghttp2_session_callbacks_del")]
public class SessionCallbacks {
[CCode (cname = "nghttp2_session_callbacks_new")]
public static int make (out SessionCallbacks callbacks);
public void set_send_callback (SendCallback callback);
public void set_on_frame_recv_callback (OnFrameRecvCallback callback);
public void set_on_data_chunk_recv_callback (OnDataChunkRecvCallback callback);
public void set_before_frame_send_callback (BeforeFrameSendCallback callback);
public void set_on_frame_send_callback (OnFrameSendCallback callback);
public void set_on_frame_not_send_callback (OnFrameNotSendCallback callback);
public void set_on_stream_close_callback (OnStreamCloseCallback callback);
public void set_on_begin_frame_callback (OnBeginFrameCallback callback);
[CCode (cname = "nghttp2_session_callbacks_set_error_callback2")]
public void set_error_callback (ErrorCallback callback);
}
[CCode (cname = "nghttp2_send_callback", has_target = false)]
public delegate ssize_t SendCallback (Session session, [CCode (array_length_type = "size_t")] uint8[] data, int flags,
void * user_data);
[CCode (cname = "nghttp2_on_frame_recv_callback", has_target = false)]
public delegate int OnFrameRecvCallback (Session session, Frame frame, void * user_data);
[CCode (cname = "nghttp2_on_data_chunk_recv_callback", has_target = false)]
public delegate int OnDataChunkRecvCallback (Session session, uint8 flags, int32 stream_id,
[CCode (array_length_type = "size_t")] uint8[] data, void * user_data);
[CCode (cname = "nghttp2_before_frame_send_callback", has_target = false)]
public delegate int BeforeFrameSendCallback (Session session, Frame frame, void * user_data);
[CCode (cname = "nghttp2_on_frame_send_callback", has_target = false)]
public delegate int OnFrameSendCallback (Session session, Frame frame, void * user_data);
[CCode (cname = "nghttp2_on_frame_not_send_callback", has_target = false)]
public delegate int OnFrameNotSendCallback (Session session, Frame frame, ErrorCode lib_error_code, void * user_data);
[CCode (cname = "nghttp2_on_stream_close_callback", has_target = false)]
public delegate int OnStreamCloseCallback (Session session, int32 stream_id, uint32 error_code, void * user_data);
[CCode (cname = "nghttp2_on_begin_frame_callback", has_target = false)]
public delegate int OnBeginFrameCallback (Session session, FrameHd hd, void * user_data);
[CCode (cname = "nghttp2_error_callback2", has_target = false)]
public delegate int ErrorCallback (Session session, ErrorCode code, [CCode (array_length_type = "size_t")] char[] msg,
void * user_data);
[CCode (cname = "nghttp2_frame")]
public struct Frame {
public FrameHd hd;
public DataFrame data;
public HeadersFrame headers;
public PriorityFrame priority;
public RstStreamFrame rst_stream;
public SettingsFrame settings;
public PushPromiseFrame push_promise;
public PingFrame ping;
public GoawayFrame goaway;
public WindowUpdateFrame window_update;
public ExtensionFrame ext;
}
[CCode (cname = "nghttp2_frame_type", cprefix = "NGHTTP2_", has_type_id = false)]
public enum FrameType {
DATA,
HEADERS,
PRIORITY,
RST_STREAM,
SETTINGS,
PUSH_PROMISE,
PING,
GOAWAY,
WINDOW_UPDATE,
CONTINUATION,
ALTSVC,
ORIGIN,
PRIORITY_UPDATE,
}
[CCode (cname = "nghttp2_frame_hd")]
public struct FrameHd {
public size_t length;
public int32 stream_id;
public FrameType type;
public uint8 flags;
public uint8 reserved;
}
[CCode (cname = "nghttp2_data")]
public struct DataFrame {
public FrameHd hd;
public size_t padlen;
}
[CCode (cname = "nghttp2_headers")]
public struct HeadersFrame {
public FrameHd hd;
public size_t padlen;
public PrioritySpec pri_spec;
public NV * nva;
public size_t nvlen;
public HeadersCategory cat;
}
[CCode (cname = "nghttp2_headers_category", cprefix = "NGHTTP2_HCAT_", has_type_id = false)]
public enum HeadersCategory {
REQUEST,
RESPONSE,
PUSH_RESPONSE,
HEADERS,
}
[CCode (cname = "nghttp2_priority")]
public struct PriorityFrame {
public FrameHd hd;
public PrioritySpec pri_spec;
}
[CCode (cname = "nghttp2_rst_stream")]
public struct RstStreamFrame {
public FrameHd hd;
public uint32 error_code;
}
[CCode (cname = "nghttp2_settings")]
public struct SettingsFrame {
public FrameHd hd;
public size_t niv;
public SettingsEntry * iv;
}
[CCode (cname = "nghttp2_push_promise")]
public struct PushPromiseFrame {
public FrameHd hd;
public size_t padlen;
public NV * nva;
public size_t nvlen;
public int32 promised_stream_id;
public uint8 reserved;
}
[CCode (cname = "nghttp2_ping")]
public struct PingFrame {
public FrameHd hd;
public uint8[] opaque_data;
}
[CCode (cname = "nghttp2_goaway")]
public struct GoawayFrame {
public FrameHd hd;
public int32 last_stream_id;
public uint32 error_code;
public uint8 * opaque_data;
public size_t opaque_data_len;
public uint8 reserved;
}
[CCode (cname = "nghttp2_window_update")]
public struct WindowUpdateFrame {
public FrameHd hd;
public int32 window_size_increment;
public uint8 reserved;
}
[CCode (cname = "nghttp2_extension")]
public struct ExtensionFrame {
public FrameHd hd;
public void * payload;
}
[Compact]
[CCode (cname = "nghttp2_option", cprefix = "nghttp2_option_", free_function = "nghttp2_option_del")]
public class Option {
[CCode (cname = "nghttp2_option_new")]
public static int make (out Option option);
public void set_no_auto_window_update (bool val);
public void set_peer_max_concurrent_streams (uint32 val);
public void set_no_recv_client_magic (bool val);
public void set_no_http_messaging (bool val);
public void set_no_http_semantics (bool val);
public void set_max_reserved_remote_streams (uint32 val);
public void set_user_recv_extension_type (uint8 type);
public void set_builtin_recv_extension_type (uint8 type);
public void set_no_auto_ping_ack (bool val);
public void set_max_send_header_block_length (size_t val);
public void set_max_deflate_dynamic_table_size (size_t val);
public void set_no_closed_streams (bool val);
public void set_max_outbound_ack (size_t val);
public void set_max_settings (size_t val);
public void set_server_fallback_rfc7540_priorities (bool val);
public void set_no_rfc9113_leading_and_trailing_ws_validation (bool val);
}
[CCode (cname = "nghttp2_settings_entry")]
public struct SettingsEntry {
public SettingsId settings_id;
public uint32 value;
}
[CCode (cname = "nghttp2_settings_id", cprefix = "NGHTTP2_SETTINGS_", has_type_id = false)]
public enum SettingsId {
HEADER_TABLE_SIZE,
ENABLE_PUSH,
MAX_CONCURRENT_STREAMS,
INITIAL_WINDOW_SIZE,
MAX_FRAME_SIZE,
MAX_HEADER_LIST_SIZE,
ENABLE_CONNECT_PROTOCOL,
NO_RFC7540_PRIORITIES,
}
[CCode (cname = "nghttp2_priority_spec")]
public struct PrioritySpec {
public int32 stream_id;
public int32 weight;
public uint8 exclusive;
}
[CCode (cname = "nghttp2_nv")]
public struct NV {
public uint8 * name;
public uint8 * value;
public size_t namelen;
public size_t valuelen;
public NVFlag flags;
}
[CCode (cname = "nghttp2_nv_flag", cprefix = "NGHTTP2_NV_FLAG_", has_type_id = false)]
[Flags]
public enum NVFlag {
NONE,
NO_INDEX,
NO_COPY_NAME,
NO_COPY_VALUE,
}
[CCode (cname = "nghttp2_data_provider")]
public struct DataProvider {
public DataSource source;
public DataSourceReadCallback read_callback;
}
[CCode (cname = "nghttp2_data_source")]
public struct DataSource {
public void * ptr;
}
[CCode (cname = "nghttp2_data_source_read_callback", has_target = false)]
public delegate ssize_t DataSourceReadCallback (Session session, int32 stream_id,
[CCode (array_length_type = "size_t")] uint8[] buf, ref uint32 data_flags, DataSource source, void * user_data);
[CCode (cname = "nghttp2_strerror")]
public unowned string strerror (ssize_t result);
[CCode (cname = "nghttp2_error", cprefix = "NGHTTP2_ERR_", has_type_id = false)]
public enum ErrorCode {
INVALID_ARGUMENT,
BUFFER_ERROR,
UNSUPPORTED_VERSION,
WOULDBLOCK,
PROTO,
INVALID_FRAME,
EOF,
DEFERRED,
STREAM_ID_NOT_AVAILABLE,
STREAM_CLOSED,
STREAM_CLOSING,
STREAM_SHUT_WR,
INVALID_STREAM_ID,
INVALID_STREAM_STATE,
DEFERRED_DATA_EXIST,
START_STREAM_NOT_ALLOWED,
GOAWAY_ALREADY_SENT,
INVALID_HEADER_BLOCK,
INVALID_STATE,
TEMPORAL_CALLBACK_FAILURE,
FRAME_SIZE_ERROR,
HEADER_COMP,
FLOW_CONTROL,
INSUFF_BUFSIZE,
PAUSE,
TOO_MANY_INFLIGHT_SETTINGS,
PUSH_DISABLED,
DATA_EXIST,
SESSION_CLOSING,
HTTP_HEADER,
HTTP_MESSAGING,
REFUSED_STREAM,
INTERNAL,
CANCEL,
SETTINGS_EXPECTED,
TOO_MANY_SETTINGS,
FATAL,
NOMEM,
CALLBACK_FAILURE,
BAD_CLIENT_MAGIC,
FLOODED,
}
[CCode (cname = "nghttp2_flag", cprefix = "NGHTTP2_FLAG_", has_type_id = false)]
[Flags]
public enum Flag {
NONE,
END_STREAM,
END_HEADERS,
ACK,
PADDED,
PRIORITY,
}
[CCode (cname = "nghttp2_data_flag", cprefix = "NGHTTP2_DATA_FLAG_", has_type_id = false)]
[Flags]
public enum DataFlag {
NONE,
EOF,
NO_END_STREAM,
NO_COPY,
}
}
+535
View File
@@ -0,0 +1,535 @@
[CCode (cheader_filename = "ngtcp2/ngtcp2.h", lower_case_cprefix = "ngtcp2_", gir_namespace = "NGTcp2", gir_version = "1.0")]
namespace NGTcp2 {
[Compact]
[CCode (cname = "ngtcp2_conn", cprefix = "ngtcp2_conn_", free_function = "ngtcp2_conn_del")]
public class Connection {
[CCode (cname = "ngtcp2_conn_client_new")]
public static int make_client (out Connection conn, ConnectionID dcid, ConnectionID scid, Path path,
ProtocolVersion client_chosen_version, Callbacks callbacks, Settings settings, TransportParams params,
MemoryAllocator? mem, void * user_data);
public void set_tls_native_handle (void * tls_native_handle);
public void set_keep_alive_timeout (Duration timeout);
public Timestamp get_expiry ();
public int handle_expiry (Timestamp ts);
[CCode (cname = "ngtcp2_conn_read_pkt")]
public int read_packet (Path path, PacketInfo * pi, uint8[] pkt, Timestamp ts);
public int open_bidi_stream (out int64 stream_id, void * stream_user_data);
public ssize_t write_stream (Path * path, PacketInfo * pi, uint8[] dest, ssize_t * pdatalen, WriteStreamFlags flags,
int64 stream_id, uint8[]? data, Timestamp ts);
public ssize_t writev_stream (Path * path, PacketInfo * pi, uint8[] dest, ssize_t * pdatalen, WriteStreamFlags flags,
int64 stream_id, IOVector[] datav, Timestamp ts);
public ssize_t write_datagram (Path * path, PacketInfo * pi, uint8[] dest, int * paccepted, uint32 flags, uint64 dgram_id,
uint8[] data, Timestamp ts);
public ssize_t writev_datagram (Path * path, PacketInfo * pi, uint8[] dest, int * paccepted, uint32 flags, uint64 dgram_id,
IOVector[] datav, Timestamp ts);
public uint64 get_max_data_left ();
public uint64 get_max_stream_data_left (int64 stream_id);
}
public unowned string strerror (int liberr);
[CCode (cname = "int", cprefix = "NGTCP2_ERR_", has_type_id = false)]
public enum ErrorCode {
INVALID_ARGUMENT,
NOBUF,
PROTO,
INVALID_STATE,
ACK_FRAME,
STREAM_ID_BLOCKED,
STREAM_IN_USE,
STREAM_DATA_BLOCKED,
FLOW_CONTROL,
CONNECTION_ID_LIMIT,
STREAM_LIMIT,
FINAL_SIZE,
CRYPTO,
PKT_NUM_EXHAUSTED,
REQUIRED_TRANSPORT_PARAM,
MALFORMED_TRANSPORT_PARAM,
FRAME_ENCODING,
DECRYPT,
STREAM_SHUT_WR,
STREAM_NOT_FOUND,
STREAM_STATE,
RECV_VERSION_NEGOTIATION,
CLOSING,
DRAINING,
TRANSPORT_PARAM,
DISCARD_PKT,
CONN_ID_BLOCKED,
INTERNAL,
CRYPTO_BUFFER_EXCEEDED,
WRITE_MORE,
RETRY,
DROP_CONN,
AEAD_LIMIT_REACHED,
NO_VIABLE_PATH,
VERSION_NEGOTIATION,
HANDSHAKE_TIMEOUT,
VERSION_NEGOTIATION_FAILURE,
IDLE_CLOSE,
FATAL,
NOMEM,
CALLBACK_FAILURE,
}
[CCode (cname = "ngtcp2_cid", has_destroy_function = false)]
public struct ConnectionID {
public size_t datalen;
public uint8 data[MAX_CIDLEN];
}
[CCode (cname = "ngtcp2_connection_id_status_type", cprefix = "NGTCP2_CONNECTION_ID_STATUS_TYPE_", has_type_id = false)]
public enum ConnectionIdStatusType {
ACTIVATE,
DEACTIVATE,
}
[CCode (cname = "ngtcp2_path", has_destroy_function = false)]
public struct Path {
public Address local;
public Address remote;
public void * user_data;
}
[CCode (cname = "ngtcp2_path_validation_result", cprefix = "NGTCP2_PATH_VALIDATION_RESULT_", has_type_id = false)]
public enum PathValidationResult {
SUCCESS,
FAILURE,
ABORTED,
}
[CCode (cname = "uint32_t", cprefix = "NGTCP2_PROTO_VER_", has_type_id = false)]
public enum ProtocolVersion {
V1,
V2,
MIN,
MAX,
}
[CCode (cname = "ngtcp2_pkt_info", has_destroy_function = false)]
public struct PacketInfo {
public uint8 ecn;
}
[CCode (cname = "ngtcp2_pkt_hd", has_destroy_function = false)]
public struct PacketHeader {
public ConnectionID dcid;
public ConnectionID scid;
public int64 pkt_num;
[CCode (array_length_cname = "tokenlen")]
public uint8[]? token;
public size_t pkt_numlen;
public size_t len;
public uint32 version;
public uint8 type;
public uint8 flags;
}
[CCode (cname = "ngtcp2_pkt_stateless_reset", has_destroy_function = false)]
public struct PacketStatelessReset {
public uint8 stateless_reset_token[STATELESS_RESET_TOKENLEN];
[CCode (array_length_cname = "randlen")]
public uint8[] rand;
}
[Flags]
[CCode (cname = "uint32_t", cprefix = "NGTCP2_WRITE_STREAM_FLAG_", has_type_id = false)]
public enum WriteStreamFlags {
NONE,
MORE,
FIN,
}
[CCode (cname = "NGTCP2_MAX_CIDLEN")]
public const size_t MAX_CIDLEN;
[CCode (cname = "NGTCP2_MIN_INITIAL_DCIDLEN")]
public const size_t MIN_INITIAL_DCIDLEN;
[CCode (cname = "NGTCP2_STATELESS_RESET_TOKENLEN")]
public const size_t STATELESS_RESET_TOKENLEN;
[CCode (cname = "ngtcp2_vec", has_destroy_function = false)]
public struct IOVector {
[CCode (array_length_cname = "len")]
public unowned uint8[] base;
}
[CCode (cname = "ngtcp2_sa_family", cprefix = "NGTCP2_AF_", has_type_id = false)]
public enum SocketAddressFamily {
INET,
INET6,
}
[SimpleType]
[CCode (cname = "ngtcp2_in_port")]
public struct InternetPort : uint16 {
}
[CCode (cname = "ngtcp2_sockaddr", has_destroy_function = false)]
public struct SocketAddress {
public SocketAddressFamily sa_family;
public uint8 sa_data[14];
}
[CCode (cname = "ngtcp2_in_addr", has_destroy_function = false)]
public struct InternetAddress {
public uint32 s_addr;
}
[CCode (cname = "ngtcp2_sockaddr_in", has_destroy_function = false)]
public struct SocketAddressInternet {
public SocketAddressFamily sin_family;
public InternetPort sin_port;
public InternetAddress sin_addr;
public uint8 sin_zero[8];
}
[CCode (cname = "ngtcp2_in6_addr", has_destroy_function = false)]
public struct Internet6Address {
public uint8 in6_addr[16];
}
[CCode (cname = "ngtcp2_sockaddr_in6", has_destroy_function = false)]
public struct SocketAddressInternet6 {
public SocketAddressFamily sin6_family;
public InternetPort sin6_port;
public uint32 sin6_flowinfo;
public Internet6Address sin6_addr;
public uint32 sin6_scope_id;
}
[SimpleType]
[CCode (cname = "ngtcp2_socklen")]
public struct SocketLength : uint32 {
}
[CCode (cname = "ngtcp2_addr", has_destroy_function = false)]
public struct Address {
[CCode (array_length_cname = "addrlen")]
public uint8[] addr;
}
[CCode (cname = "ngtcp2_preferred_addr", has_destroy_function = false)]
public struct PreferredAddress {
public ConnectionID cid;
public SocketAddressInternet ipv4;
public SocketAddressInternet6 ipv6;
public uint8 ipv4_present;
public uint8 ipv6_present;
public uint8 stateless_reset_token[STATELESS_RESET_TOKENLEN];
}
[CCode (cname = "ngtcp2_version_info", has_destroy_function = false)]
public struct VersionInfo {
public uint32 chosen_version;
[CCode (array_length_cname = "available_versionslen")]
public uint8[] available_versions;
}
[CCode (cname = "ngtcp2_encryption_level", cprefix = "NGTCP2_ENCRYPTION_LEVEL_", has_type_id = false)]
public enum EncryptionLevel {
INITIAL,
HANDSHAKE,
1RTT,
0RTT,
}
[CCode (cname = "ngtcp2_token_type", cprefix = "NGTCP2_TOKEN_TYPE_", has_type_id = false)]
public enum TokenType {
UNKNOWN,
RETRY,
NEW_TOKEN,
}
[CCode (cname = "ngtcp2_rand_ctx", has_destroy_function = false)]
public struct RNGContext {
public void * native_handle;
}
[CCode (cname = "ngtcp2_crypto_aead", has_destroy_function = false)]
public struct CryptoAead {
public void * native_handle;
public size_t max_overhead;
}
[CCode (cname = "ngtcp2_crypto_cipher", has_destroy_function = false)]
public struct CryptoCipher {
public void * native_handle;
}
[CCode (cname = "ngtcp2_crypto_aead_ctx", has_destroy_function = false)]
public struct CryptoAeadCtx {
public void * native_handle;
}
[CCode (cname = "ngtcp2_crypto_cipher_ctx", has_destroy_function = false)]
public struct CryptoCipherCtx {
public void * native_handle;
}
[CCode (cname = "ngtcp2_cc_algo", cprefix = "NGTCP2_CC_ALGO_", has_type_id = false)]
public enum CongestionControlAlgorithm {
RENO,
CUBIC,
BBR,
}
[SimpleType]
[CCode (cname = "ngtcp2_tstamp")]
public struct Timestamp : uint64 {
}
[CCode (cname = "NGTCP2_SECONDS")]
public const uint64 SECONDS;
[CCode (cname = "NGTCP2_MILLISECONDS")]
public const uint64 MILLISECONDS;
[CCode (cname = "NGTCP2_MICROSECONDS")]
public const uint64 MICROSECONDS;
[CCode (cname = "NGTCP2_NANOSECONDS")]
public const uint64 NANOSECONDS;
[SimpleType]
[CCode (cname = "ngtcp2_duration")]
public struct Duration : uint64 {
}
[CCode (cname = "ngtcp2_callbacks", has_destroy_function = false)]
public struct Callbacks {
public ClientInitial? client_initial;
public RecvClientInitial? recv_client_initial;
public RecvCryptoData recv_crypto_data;
public HandshakeCompleted? handshake_completed;
public RecvVersionNegotiation? recv_version_negotiation;
public Encrypt encrypt;
public Decrypt decrypt;
public HpMask hp_mask;
public RecvStreamData? recv_stream_data;
public AckedStreamDataOffset? acked_stream_data_offset;
public StreamOpen? stream_open;
public StreamClose? stream_close;
public RecvStatelessReset? recv_stateless_reset;
public RecvRetry? recv_retry;
public ExtendMaxStreams? extend_max_local_streams_bidi;
public ExtendMaxStreams? extend_max_local_streams_uni;
public Rand? rand;
public GetNewConnectionId get_new_connection_id;
public RemoveConnectionId? remove_connection_id;
public UpdateKey update_key;
public PathValidation? path_validation;
public SelectPreferredAddr? select_preferred_addr;
public StreamReset? stream_reset;
public ExtendMaxStreams? extend_max_remote_streams_bidi;
public ExtendMaxStreams? extend_max_remote_streams_uni;
public ExtendMaxStreamData? extend_max_stream_data;
public ConnectionIdStatus? dcid_status;
public HandshakeConfirmed? handshake_confirmed;
public RecvNewToken? recv_new_token;
public DeleteCryptoAeadCtx delete_crypto_aead_ctx;
public DeleteCryptoCipherCtx delete_crypto_cipher_ctx;
public RecvDatagram? recv_datagram;
public AckDatagram? ack_datagram;
public LostDatagram? lost_datagram;
public GetPathChallengeData get_path_challenge_data;
public StreamStopSending? stream_stop_sending;
public VersionNegotiation version_negotiation;
public RecvKey recv_rx_key;
public RecvKey recv_tx_key;
public TlsEarlyDataRejected? tls_early_data_rejected;
}
[CCode (cname = "ngtcp2_client_initial", has_target = false)]
public delegate int ClientInitial (Connection conn, void * user_data);
[CCode (cname = "ngtcp2_recv_client_initial", has_target = false)]
public delegate int RecvClientInitial (Connection conn, ConnectionID dcid, void * user_data);
[CCode (cname = "ngtcp2_recv_crypto_data", has_target = false)]
public delegate int RecvCryptoData (Connection conn, EncryptionLevel encryption_level, uint64 offset,
[CCode (array_length_type = "size_t")] uint8[] data, void * user_data);
[CCode (cname = "ngtcp2_handshake_completed", has_target = false)]
public delegate int HandshakeCompleted (Connection conn, void * user_data);
[CCode (cname = "ngtcp2_recv_version_negotiation", has_target = false)]
public delegate int RecvVersionNegotiation (Connection conn, PacketHeader hd, [CCode (array_length_type = "size_t")] uint32[] sv,
void * user_data);
[CCode (cname = "ngtcp2_encrypt", has_target = false)]
public delegate int Encrypt ([CCode (array_length = false)] uint8[] dest, CryptoAead aead, CryptoAeadCtx aead_ctx,
[CCode (array_length_type = "size_t")] uint8[] plaintext,
[CCode (array_length_type = "size_t")] uint8[] nonce,
[CCode (array_length_type = "size_t")] uint8[] aad);
[CCode (cname = "ngtcp2_decrypt", has_target = false)]
public delegate int Decrypt ([CCode (array_length = false)] uint8[] dest, CryptoAead aead, CryptoAeadCtx aead_ctx,
[CCode (array_length_type = "size_t")] uint8[] ciphertext,
[CCode (array_length_type = "size_t")] uint8[] nonce,
[CCode (array_length_type = "size_t")] uint8[] aad);
[CCode (cname = "ngtcp2_hp_mask", has_target = false)]
public delegate int HpMask ([CCode (array_length = false)] uint8[] dest, CryptoCipher hp, CryptoCipherCtx hp_ctx,
[CCode (array_length = false)] uint8[] sample);
[CCode (cname = "ngtcp2_recv_stream_data", has_target = false)]
public delegate int RecvStreamData (Connection conn, uint32 flags, int64 stream_id, uint64 offset,
[CCode (array_length_type = "size_t")] uint8[] data, void * user_data, void * stream_user_data);
[CCode (cname = "ngtcp2_acked_stream_data_offset", has_target = false)]
public delegate int AckedStreamDataOffset (Connection conn, int64 stream_id, uint64 offset, uint64 datalen, void * user_data,
void * stream_user_data);
[CCode (cname = "ngtcp2_stream_open", has_target = false)]
public delegate int StreamOpen (Connection conn, int64 stream_id, void * user_data);
[CCode (cname = "ngtcp2_stream_close", has_target = false)]
public delegate int StreamClose (Connection conn, uint32 flags, int64 stream_id, uint64 app_error_code, void * user_data,
void * stream_user_data);
[CCode (cname = "ngtcp2_recv_stateless_reset", has_target = false)]
public delegate int RecvStatelessReset (Connection conn, PacketStatelessReset sr, void * user_data);
[CCode (cname = "ngtcp2_recv_retry", has_target = false)]
public delegate int RecvRetry (Connection conn, PacketHeader hd, void * user_data);
[CCode (cname = "ngtcp2_extend_max_streams", has_target = false)]
public delegate int ExtendMaxStreams (Connection conn, uint64 max_streams, void * user_data);
[CCode (cname = "ngtcp2_extend_max_stream_data", has_target = false)]
public delegate int ExtendMaxStreamData (Connection conn, int64 stream_id, uint64 max_data, void * user_data,
void * stream_user_data);
[CCode (cname = "ngtcp2_rand", has_target = false)]
public delegate void Rand ([CCode (array_length_type = "size_t")] uint8[] dest, RNGContext rand_ctx);
[CCode (cname = "ngtcp2_get_new_connection_id", has_target = false)]
public delegate int GetNewConnectionId (Connection conn, out ConnectionID cid, [CCode (array_length = false)] uint8[] token,
size_t cidlen, void * user_data);
[CCode (cname = "ngtcp2_remove_connection_id", has_target = false)]
public delegate int RemoveConnectionId (Connection conn, ConnectionID cid, void * user_data);
[CCode (cname = "ngtcp2_update_key", has_target = false)]
public delegate int UpdateKey (Connection conn,
[CCode (array_length = false)] uint8[] rx_secret,
[CCode (array_length = false)] uint8[] tx_secret,
CryptoAeadCtx rx_aead_ctx, [CCode (array_length = false)] uint8[] rx_iv,
CryptoAeadCtx tx_aead_ctx, [CCode (array_length = false)] uint8[] tx_iv,
[CCode (array_length_pos = 9.1)] uint8[] current_rx_secret,
[CCode (array_length_pos = 9.1)] uint8[] current_tx_secret,
void * user_data);
[CCode (cname = "ngtcp2_path_validation", has_target = false)]
public delegate int PathValidation (Connection conn, uint32 flags, Path path, Path old_path, PathValidationResult res,
void * user_data);
[CCode (cname = "ngtcp2_select_preferred_addr", has_target = false)]
public delegate int SelectPreferredAddr (Connection conn, Path dest, PreferredAddress paddr, void * user_data);
[CCode (cname = "ngtcp2_stream_reset", has_target = false)]
public delegate int StreamReset (Connection conn, int64 stream_id, uint64 final_size, uint64 app_error_code, void * user_data,
void * stream_user_data);
[CCode (cname = "ngtcp2_connection_id_status", has_target = false)]
public delegate int ConnectionIdStatus (Connection conn, ConnectionIdStatusType type, uint64 seq, ConnectionID cid,
[CCode (array_length = false)] uint8[] token, void * user_data);
[CCode (cname = "ngtcp2_handshake_confirmed", has_target = false)]
public delegate int HandshakeConfirmed (Connection conn, void * user_data);
[CCode (cname = "ngtcp2_recv_new_token", has_target = false)]
public delegate int RecvNewToken (Connection conn, [CCode (array_length_type = "size_t")] uint8[] token, void * user_data);
[CCode (cname = "ngtcp2_delete_crypto_aead_ctx", has_target = false)]
public delegate void DeleteCryptoAeadCtx (Connection conn, CryptoAeadCtx aead_ctx, void * user_data);
[CCode (cname = "ngtcp2_delete_crypto_cipher_ctx", has_target = false)]
public delegate void DeleteCryptoCipherCtx (Connection conn, CryptoCipherCtx cipher_ctx, void * user_data);
[CCode (cname = "ngtcp2_recv_datagram", has_target = false)]
public delegate int RecvDatagram (Connection conn, uint32 flags, [CCode (array_length_type = "size_t")] uint8[] data,
void * user_data);
[CCode (cname = "ngtcp2_ack_datagram", has_target = false)]
public delegate int AckDatagram (Connection conn, uint64 dgram_id, void * user_data);
[CCode (cname = "ngtcp2_lost_datagram", has_target = false)]
public delegate int LostDatagram (Connection conn, uint64 dgram_id, void * user_data);
[CCode (cname = "ngtcp2_get_path_challenge_data", has_target = false)]
public delegate int GetPathChallengeData (Connection conn, [CCode (array_length = false)] uint8[] data, void * user_data);
[CCode (cname = "ngtcp2_stream_stop_sending", has_target = false)]
public delegate int StreamStopSending (Connection conn, int64 stream_id, uint64 app_error_code, void * user_data,
void * stream_user_data);
[CCode (cname = "ngtcp2_version_negotiation", has_target = false)]
public delegate int VersionNegotiation (Connection conn, uint32 version, ConnectionID client_dcid, void * user_data);
[CCode (cname = "ngtcp2_recv_key", has_target = false)]
public delegate int RecvKey (Connection conn, EncryptionLevel level, void * user_data);
[CCode (cname = "ngtcp2_tls_early_data_rejected", has_target = false)]
public delegate int TlsEarlyDataRejected (Connection conn, void * user_data);
[CCode (cname = "ngtcp2_settings", has_destroy_function = false)]
public struct Settings {
[CCode (cname = "ngtcp2_settings_default")]
public Settings.make_default ();
public QlogWrite? qlog_write;
public CongestionControlAlgorithm cc_algo;
public Timestamp initial_ts;
public Duration initial_rtt;
public Printf? log_printf;
public size_t max_tx_udp_payload_size;
[CCode (array_length_cname = "tokenlen")]
public uint8[]? token;
public TokenType token_type;
public RNGContext rand_ctx;
public uint64 max_window;
public uint64 max_stream_window;
public size_t ack_thresh;
public bool no_tx_udp_payload_size_shaping;
public Duration handshake_timeout;
[CCode (array_length_cname = "preferred_versionslen")]
public ProtocolVersion[]? preferred_versions;
[CCode (array_length_cname = "available_versionslen")]
public ProtocolVersion[]? available_versions;
public uint32 original_version;
public bool no_pmtud;
public uint32 initial_pkt_num;
}
[CCode (cname = "ngtcp2_qlog_write", has_target = false)]
public delegate void QlogWrite (void * user_data, uint32 flags, [CCode (array_length_type = "size_t")] uint8[] data);
[CCode (cname = "ngtcp2_printf", has_target = false)]
public delegate void Printf (void * user_data, string format, ...);
[CCode (cname = "ngtcp2_transport_params", has_destroy_function = false)]
public struct TransportParams {
[CCode (cname = "ngtcp2_transport_params_default")]
public TransportParams.make_default ();
public PreferredAddress preferred_addr;
public ConnectionID original_dcid;
public ConnectionID initial_scid;
public ConnectionID retry_scid;
public uint64 initial_max_stream_data_bidi_local;
public uint64 initial_max_stream_data_bidi_remote;
public uint64 initial_max_stream_data_uni;
public uint64 initial_max_data;
public uint64 initial_max_streams_bidi;
public uint64 initial_max_streams_uni;
public Duration max_idle_timeout;
public uint64 max_udp_payload_size;
public uint64 active_connection_id_limit;
public uint64 ack_delay_exponent;
public Duration max_ack_delay;
public uint64 max_datagram_frame_size;
public bool stateless_reset_token_present;
public bool disable_active_migration;
public bool original_dcid_present;
public bool initial_scid_present;
public bool retry_scid_present;
public bool preferred_addr_present;
public uint8 stateless_reset_token[STATELESS_RESET_TOKENLEN];
public bool grease_quic_bit;
public VersionInfo version_info;
public bool version_info_present;
}
[CCode (cname = "ngtcp2_mem", has_destroy_function = false)]
public struct MemoryAllocator {
public void * user_data;
public Malloc malloc;
public Free free;
public Calloc calloc;
public Realloc realloc;
}
[CCode (cname = "ngtcp2_malloc", has_target = false)]
public delegate void * Malloc (size_t size, void * user_data);
[CCode (cname = "ngtcp2_free", has_target = false)]
public delegate void Free (void * ptr, void * user_data);
[CCode (cname = "ngtcp2_calloc", has_target = false)]
public delegate void * Calloc (size_t nmemb, size_t size, void * user_data);
[CCode (cname = "ngtcp2_realloc", has_target = false)]
public delegate void * Realloc (void * ptr, size_t size, void * user_data);
}
+28
View File
@@ -0,0 +1,28 @@
[CCode (cheader_filename = "ngtcp2/ngtcp2_crypto.h", lower_case_cprefix = "ngtcp2_crypto_", gir_namespace = "NGTcp2Crypto", gir_version = "1.0")]
namespace NGTcp2.Crypto {
[CCode (cheader_filename = "ngtcp2/ngtcp2_crypto_quictls.h")]
namespace Quictls {
public int configure_client_context (OpenSSL.SSLContext ssl_ctx);
}
[CCode (cname = "ngtcp2_crypto_conn_ref", has_destroy_function = false)]
public struct ConnectionRef {
public GetConnection get_conn;
public void * user_data;
}
[CCode (cname = "ngtcp2_crypto_get_conn", has_target = false)]
public delegate unowned Connection GetConnection (ConnectionRef conn_ref);
public ClientInitial client_initial_cb;
public RecvCryptoData recv_crypto_data_cb;
public Encrypt encrypt_cb;
public Decrypt decrypt_cb;
public HpMask hp_mask_cb;
public RecvRetry recv_retry_cb;
public UpdateKey update_key_cb;
public DeleteCryptoAeadCtx delete_crypto_aead_ctx_cb;
public DeleteCryptoCipherCtx delete_crypto_cipher_ctx_cb;
public GetPathChallengeData get_path_challenge_data_cb;
public VersionNegotiation version_negotiation_cb;
}
+193
View File
@@ -0,0 +1,193 @@
[CCode (gir_namespace = "LWIP", gir_version = "1.0")]
namespace LWIP {
[CCode (cheader_filename = "lwip/tcpip.h", lower_case_cprefix = "tcpip_")]
namespace Runtime {
public void init (InitDoneFunc init_done);
[CCode (cname = "tcpip_callback")]
public ErrorCode schedule (WorkFunc work);
[CCode (cname = "tcpip_init_done_fn")]
public delegate void InitDoneFunc ();
[CCode (cname = "tcpip_callback_fn")]
public delegate void WorkFunc ();
}
[CCode (cheader_filename = "lwip/netif.h", cname = "struct netif", cprefix = "netif_")]
public struct NetworkInterface {
public static void add_noaddr (ref NetworkInterface netif, void * state, NetworkInterfaceInitFunc init,
NetworkInterfaceInputFunc input = NetworkInterface.default_input_handler);
public void remove ();
public void set_up ();
public void set_down ();
public void ip6_addr_set (int8 addr_idx, IP6Address address);
public ErrorCode add_ip6_address (IP6Address address, int8 * chosen_index = null);
public void ip6_addr_set_state (int8 addr_index, IP6AddressState state);
[CCode (cname = "netif_input")]
public static ErrorCode default_input_handler (PacketBuffer pbuf, NetworkInterface netif);
public NetworkInterfaceInputFunc input;
public NetworkInterfaceOutputIP6Func output_ip6;
public void * state;
public uint16 mtu;
}
[CCode (cname = "netif_init_fn", has_target = false)]
public delegate ErrorCode NetworkInterfaceInitFunc (NetworkInterface netif);
[CCode (cname = "netif_input_fn", has_target = false)]
public delegate ErrorCode NetworkInterfaceInputFunc (PacketBuffer pbuf, NetworkInterface netif);
[CCode (cname = "netif_output_ip6_fn", has_target = false)]
public delegate ErrorCode NetworkInterfaceOutputIP6Func (NetworkInterface netif, PacketBuffer pbuf, IP6Address address);
[CCode (cheader_filename = "lwip/ip6_addr.h", cname = "ip6_addr_t", cprefix = "ip6_addr_")]
public struct IP6Address {
[CCode (cname = "ip6addr_aton")]
public static IP6Address parse (string str);
}
[Flags]
[CCode (cheader_filename = "lwip/ip6_addr.h", cname = "u8_t", cprefix = "IP6_ADDR_", has_type_id = false)]
public enum IP6AddressState {
INVALID,
TENTATIVE,
TENTATIVE_1,
TENTATIVE_2,
TENTATIVE_3,
TENTATIVE_4,
TENTATIVE_5,
TENTATIVE_6,
TENTATIVE_7,
VALID,
PREFERRED,
DEPRECATED,
DUPLICATED,
}
[CCode (cheader_filename = "lwip/ip_addr.h", cname = "u8_t", cprefix = "IPADDR_TYPE_", has_type_id = false)]
public enum IPAddressType {
V4,
V6,
ANY,
}
[Compact]
[CCode (cheader_filename = "lwip/pbuf.h", cname = "struct pbuf", cprefix = "pbuf_")]
public class PacketBuffer {
public static PacketBuffer alloc (Layer layer, uint16 length, Type type);
public PacketBuffer? next;
[CCode (array_length_cname = "len")]
public uint8[] payload;
public uint16 tot_len;
[CCode (array_length = false)]
public unowned uint8[] get_contiguous (uint8[] buffer, uint16 len, uint16 offset = 0);
public ErrorCode take (uint8[] data);
[CCode (cname = "pbuf_layer", cprefix = "PBUF_", has_type_id = false)]
public enum Layer {
TRANSPORT,
IP,
LINK,
RAW_TX,
RAW,
}
[CCode (cname = "pbuf_type", cprefix = "PBUF_", has_type_id = false)]
public enum Type {
RAM,
ROM,
REF,
POOL,
}
}
[Compact]
[CCode (cheader_filename = "lwip/tcp.h", cname = "struct tcp_pcb", cprefix = "tcp_")]
public class TcpPcb {
[CCode (cname = "tcp_new_ip_type")]
public static unowned TcpPcb make (IPAddressType type);
[CCode (cname = "tcp_arg")]
public void set_user_data (void * user_data);
[CCode (cname = "tcp_recv")]
public void set_recv_callback (RecvFunc f);
[CCode (cname = "tcp_sent")]
public void set_sent_callback (SentFunc f);
[CCode (cname = "tcp_err")]
public void set_error_callback (ErrorFunc f);
public void nagle_disable ();
public void nagle_enable ();
public void abort ();
public ErrorCode close ();
public ErrorCode shutdown (bool shut_rx, bool shut_tx);
public void bind_netif (NetworkInterface? netif);
public ErrorCode connect (IP6Address address, uint16 port, ConnectedFunc connected);
[CCode (cname = "tcp_recved")]
public void notify_received (uint16 len);
[CCode (cname = "tcp_sndbuf")]
public uint16 query_available_send_buffer_space ();
public ErrorCode write (uint8[] data, WriteFlags flags = 0);
public ErrorCode output ();
[CCode (cname = "tcp_recv_fn", has_target = false)]
public delegate ErrorCode RecvFunc (void * user_data, TcpPcb pcb, owned PacketBuffer? pbuf, ErrorCode err);
[CCode (cname = "tcp_sent_fn", has_target = false)]
public delegate ErrorCode SentFunc (void * user_data, TcpPcb pcb, uint16 len);
[CCode (cname = "tcp_err_fn", has_target = false)]
public delegate void ErrorFunc (void * user_data, ErrorCode err);
[CCode (cname = "tcp_connected_fn", has_target = false)]
public delegate ErrorCode ConnectedFunc (void * user_data, TcpPcb pcb, ErrorCode err);
[Flags]
[CCode (cname = "u8_t", cprefix = "TCP_WRITE_FLAG_", has_type_id = false)]
public enum WriteFlags {
COPY,
MORE,
}
}
[CCode (cheader_filename = "lwip/err.h", cname = "err_t", cprefix = "ERR_", lower_case_cprefix = "err_", has_type_id = false)]
public enum ErrorCode {
OK,
MEM,
BUF,
TIMEOUT,
RTE,
INPROGRESS,
VAL,
WOULDBLOCK,
USE,
ALREADY,
ISCONN,
CONN,
IF,
ABRT,
RST,
CLSD,
ARG;
public int to_errno ();
}
}
+500 -1
View File
@@ -1 +1,500 @@
// Placeholder to satisfy Meson assumptions.
[CCode (lower_case_cprefix = "OPENSSL_", gir_namespace = "OpenSSL", gir_version = "1.0")]
namespace OpenSSL {
[Compact]
[CCode (cname = "SSL_CTX", cprefix = "SSL_CTX_")]
public class SSLContext {
public SSLContext (SSLMethod meth);
[CCode (cname = "SSL_CTX_use_certificate")]
public int use_certificate (X509 cert);
[CCode (cname = "SSL_CTX_use_PrivateKey")]
public int use_private_key (Envelope.Key key);
}
[Compact]
[CCode (cname = "SSL", cprefix = "SSL_")]
public class SSL {
public SSL (SSLContext ctx);
public void set_app_data (void * data);
public void set_connect_state ();
public void set_accept_state ();
public int set_alpn_protos (uint8[] protos);
public void set_quic_transport_version (int version);
}
[Compact]
[CCode (cname = "SSL_METHOD", cprefix = "SSL_METHOD_", free_function = "")]
public class SSLMethod {
[CCode (cname = "TLS_method")]
public static unowned SSLMethod tls ();
[CCode (cname = "TLS_server_method")]
public static unowned SSLMethod tls_server ();
[CCode (cname = "TLS_client_method")]
public static unowned SSLMethod tls_client ();
[CCode (cname = "DTLS_method")]
public static unowned SSLMethod dtls ();
[CCode (cname = "DTLS_server_method")]
public static unowned SSLMethod dtls_server ();
[CCode (cname = "DTLS_client_method")]
public static unowned SSLMethod dtls_client ();
}
[CCode (lower_case_cprefix = "TLSEXT_TYPE_")]
namespace TLSExtensionType {
public const int quic_transport_parameters;
}
[Compact]
[CCode (cname = "X509", cprefix = "X509_")]
public class X509 {
public X509 ();
[CCode (cname = "X509_get_serialNumber")]
public unowned ASN1.Integer get_serial_number ();
[CCode (cname = "X509_getm_notBefore")]
public unowned ASN1.Time get_not_before ();
[CCode (cname = "X509_getm_notAfter")]
public unowned ASN1.Time get_not_after ();
public unowned Name get_subject_name ();
public int set_issuer_name (Name name);
public int set_pubkey (Envelope.Key key);
public int sign_ctx (Envelope.MessageDigestContext ctx);
[CCode (cname = "X509_get_X509_PUBKEY")]
public unowned X509PublicKey get_public_key ();
[CCode (cname = "i2d_X509_bio", instance_pos = 2)]
public int to_der (BasicIO sink);
[CCode (cname = "PEM_write_bio_X509", instance_pos = 2)]
public int to_pem (BasicIO sink);
[Compact]
[CCode (cname = "X509_NAME", cprefix = "X509_NAME_")]
public class Name {
public int add_entry_by_txt (string field, ASN1.MultiByteStringType type, uint8[] bytes, int loc = -1, int set = 0);
}
}
[Compact]
[CCode (cname = "X509_PUBKEY", cprefix = "X509_PUBKEY_", free_function = "")]
public class X509PublicKey {
[CCode (cname = "i2d_X509_PUBKEY_bio", instance_pos = 2)]
public int to_der (BasicIO sink);
[CCode (cname = "PEM_write_bio_X509_PUBKEY", instance_pos = 2)]
public int to_pem (BasicIO sink);
}
[Compact]
[CCode (cname = "BIO", cprefix = "BIO_")]
public class BasicIO {
public BasicIO (BasicIOMethod method);
[CCode (cname = "BIO_new_mem_buf")]
public BasicIO.from_static_memory_buffer (uint8[] buf);
public long get_mem_data ([CCode (array_length = false)] out unowned uint8[] data);
}
[Compact]
[CCode (cname = "BIO_METHOD", cprefix = "BIO_METHOD_", free_function = "")]
public class BasicIOMethod {
[CCode (cname = "BIO_s_mem")]
public static unowned BasicIOMethod memory ();
}
[CCode (cheader_filename = "openssl/asn1.h")]
namespace ASN1 {
[Compact]
[CCode (cname = "ASN1_INTEGER", cprefix = "ASN1_INTEGER_")]
public class Integer {
public int set_int64 (int64 v);
public int set_uint64 (uint64 v);
}
[Compact]
[CCode (cname = "ASN1_TIME", cprefix = "ASN1_TIME_")]
public class Time {
[CCode (cname = "X509_gmtime_adj")]
public unowned Time adjust (long delta);
}
[CCode (cname = "int", cprefix = "MBSTRING_", has_type_id = false)]
public enum MultiByteStringType {
UTF8,
[CCode (cname = "MBSTRING_ASC")]
ASCII,
}
}
[CCode (cheader_filename = "openssl/evp.h")]
namespace Envelope {
[Compact]
[CCode (cname = "EVP_PKEY_CTX", cprefix = "EVP_PKEY_", free_function = "EVP_PKEY_CTX_free")]
public class KeyContext {
[CCode (cname = "EVP_PKEY_CTX_new")]
public KeyContext.for_key (Key key, Engine? engine = null);
[CCode (cname = "EVP_PKEY_CTX_new_id")]
public KeyContext.for_key_type (KeyType type, Engine? engine = null);
public int keygen_init ();
public int keygen (ref Key pkey);
public int derive_init ();
public int derive_set_peer (Key peer);
public int derive ([CCode (array_length = false)] uint8[]? key, ref size_t keylen);
}
[Compact]
[CCode (cname = "EVP_PKEY", cprefix = "EVP_PKEY_", copy_function = "EVP_PKEY_dup")]
public class Key {
[CCode (cname = "d2i_PUBKEY_bio")]
public Key.from_der (BasicIO source, Key ** a = null);
[CCode (cname = "EVP_PKEY_new_raw_public_key")]
public Key.from_raw_public_key (KeyType type, Engine? engine, uint8[] pub);
[CCode (cname = "EVP_PKEY_new_raw_private_key")]
public Key.from_raw_private_key (KeyType type, Engine? engine, uint8[] priv);
public int get_raw_public_key ([CCode (array_length = false)] uint8[]? pub, ref size_t len);
public int get_raw_private_key ([CCode (array_length = false)] uint8[]? priv, ref size_t len);
[CCode (cname = "i2d_PUBKEY_bio", instance_pos = 2)]
public int to_der (BasicIO sink);
[CCode (cname = "PEM_write_bio_PUBKEY", instance_pos = 2)]
public int to_pem (BasicIO sink);
}
[Compact]
[CCode (cname = "EVP_PKEY_CTX", cprefix = "EVP_PKEY_CTX_")]
public class PublicKeyContext {
}
[CCode (cname = "int", cprefix = "EVP_PKEY_", has_type_id = false)]
public enum KeyType {
NONE,
RSA,
RSA2,
RSA_PSS,
DSA,
DSA1,
DSA2,
DSA3,
DSA4,
DH,
DHX,
EC,
SM2,
HMAC,
CMAC,
SCRYPT,
TLS1_PRF,
HKDF,
POLY1305,
SIPHASH,
X25519,
ED25519,
X448,
ED448,
KEYMGMT,
}
[Compact]
[CCode (cheader_filename = "openssl/kdf.h", cname = "EVP_KDF", cprefix = "EVP_KDF_")]
public class KeyDerivationFunction {
public static KeyDerivationFunction? fetch (LibraryContext? ctx, string algorithm, string? properties = null);
}
[Compact]
[CCode (cheader_filename = "openssl/kdf.h", cname = "EVP_KDF_CTX", cprefix = "EVP_KDF_",
free_function = "EVP_KDF_CTX_free")]
public class KeyDerivationContext {
[CCode (cname = "EVP_KDF_CTX_new")]
public KeyDerivationContext (KeyDerivationFunction kdf);
public int derive (uint8[] key, [CCode (array_length = false)] Param[] params);
}
[CCode (cheader_filename = "openssl/core_names.h", lower_case_cprefix = "OSSL_KDF_NAME_")]
namespace KeyDerivationAlgorithm {
public const string HKDF;
public const string TLS1_3_KDF;
public const string PBKDF1;
public const string PBKDF2;
public const string SCRYPT;
public const string SSHKDF;
public const string SSKDF;
public const string TLS1_PRF;
public const string X942KDF_ASN1;
public const string X942KDF_CONCAT;
public const string X963KDF;
public const string KBKDF;
public const string KRB5KDF;
}
[CCode (cheader_filename = "openssl/core_names.h", lower_case_cprefix = "OSSL_KDF_PARAM_")]
namespace KeyDerivationParameter {
public const string SECRET;
public const string KEY;
public const string SALT;
public const string PASSWORD;
public const string PREFIX;
public const string LABEL;
public const string DATA;
public const string DIGEST;
public const string CIPHER;
public const string MAC;
public const string MAC_SIZE;
public const string PROPERTIES;
public const string ITER;
public const string MODE;
public const string PKCS5;
public const string UKM;
public const string CEK_ALG;
public const string SCRYPT_N;
public const string SCRYPT_R;
public const string SCRYPT_P;
public const string SCRYPT_MAXMEM;
public const string INFO;
public const string SEED;
public const string SSHKDF_XCGHASH;
public const string SSHKDF_SESSION_ID;
public const string SSHKDF_TYPE;
public const string SIZE;
public const string CONSTANT;
public const string PKCS12_ID;
public const string KBKDF_USE_L;
public const string KBKDF_USE_SEPARATOR;
public const string X942_ACVPINFO;
public const string X942_PARTYUINFO;
public const string X942_PARTYVINFO;
public const string X942_SUPP_PUBINFO;
public const string X942_SUPP_PRIVINFO;
public const string X942_USE_KEYBITS;
}
[Compact]
[CCode (cname = "EVP_CIPHER_CTX", cprefix = "EVP_CIPHER_CTX_")]
public class CipherContext {
public CipherContext ();
public int reset ();
public int ctrl (CipherCtrlType type, int arg, void * ptr);
[CCode (cname = "EVP_EncryptInit")]
public int encrypt_init (Cipher cipher,
[CCode (array_length = false)] uint8[] key,
[CCode (array_length = false)] uint8[] iv);
[CCode (cname = "EVP_EncryptUpdate")]
public int encrypt_update ([CCode (array_length = false)] uint8[] output, ref int outlen, uint8[] input);
[CCode (cname = "EVP_EncryptFinal")]
public int encrypt_final ([CCode (array_length = false)] uint8[] output, ref int outlen);
[CCode (cname = "EVP_DecryptInit")]
public int decrypt_init (Cipher cipher,
[CCode (array_length = false)] uint8[] key,
[CCode (array_length = false)] uint8[] iv);
[CCode (cname = "EVP_DecryptUpdate")]
public int decrypt_update ([CCode (array_length = false)] uint8[] output, ref int outlen, uint8[] input);
[CCode (cname = "EVP_DecryptFinal")]
public int decrypt_final ([CCode (array_length = false)] uint8[] output, ref int outlen);
}
[Compact]
[CCode (cname = "EVP_CIPHER", cprefix = "EVP_CIPHER_")]
public class Cipher {
public static Cipher? fetch (LibraryContext? ctx, string algorithm, string? properties = null);
}
[CCode (cheader_filename = "openssl/evp.h", cname = "int", cprefix = "EVP_CTRL_", has_type_id = false)]
public enum CipherCtrlType {
INIT,
SET_KEY_LENGTH,
GET_RC2_KEY_BITS,
SET_RC2_KEY_BITS,
GET_RC5_ROUNDS,
SET_RC5_ROUNDS,
RAND_KEY,
PBE_PRF_NID,
COPY,
AEAD_SET_IVLEN,
AEAD_GET_TAG,
AEAD_SET_TAG,
AEAD_SET_IV_FIXED,
GCM_SET_IVLEN,
GCM_GET_TAG,
GCM_SET_TAG,
GCM_SET_IV_FIXED,
GCM_IV_GEN,
CCM_SET_IVLEN,
CCM_GET_TAG,
CCM_SET_TAG,
CCM_SET_IV_FIXED,
CCM_SET_L,
CCM_SET_MSGLEN,
AEAD_TLS1_AAD,
AEAD_SET_MAC_KEY,
GCM_SET_IV_INV,
TLS1_1_MULTIBLOCK_AAD,
TLS1_1_MULTIBLOCK_ENCRYPT,
TLS1_1_MULTIBLOCK_DECRYPT,
TLS1_1_MULTIBLOCK_MAX_BUFSIZE,
SSL3_MASTER_SECRET,
SET_SBOX,
SBOX_USED,
KEY_MESH,
BLOCK_PADDING_MODE,
SET_PIPELINE_OUTPUT_BUFS,
SET_PIPELINE_INPUT_BUFS,
SET_PIPELINE_INPUT_LENS,
GET_IVLEN,
SET_SPEED,
PROCESS_UNPROTECTED,
GET_WRAP_CIPHER,
TLSTREE,
}
[Compact]
[CCode (cname = "EVP_MD_CTX", cprefix = "EVP_MD_CTX_")]
public class MessageDigestContext {
public MessageDigestContext ();
[CCode (cname = "EVP_DigestSignInit")]
public int digest_sign_init (PublicKeyContext ** pctx, MessageDigest? type, Engine? engine = null, Key? key = null);
[CCode (cname = "EVP_DigestSignUpdate")]
public int digest_sign_update (uint8[] data);
[CCode (cname = "EVP_DigestSignFinal")]
public int digest_sign_final ([CCode (array_length = false)] uint8[]? sigret, ref size_t siglen);
[CCode (cname = "EVP_DigestSign")]
public int digest_sign ([CCode (array_length = false)] uint8[]? sigret, ref size_t siglen, uint8[] tbs);
}
[Compact]
[CCode (cname = "EVP_MD", cprefix = "EVP_MD_")]
public class MessageDigest {
public static MessageDigest fetch (LibraryContext? ctx, string algorithm, string? properties = null);
}
}
[Compact]
[CCode (cheader_filename = "openssl/engine.h", cname = "ENGINE")]
public class Engine {
}
[Compact]
[CCode (cheader_filename = "openssl/types.h", cname = "OSSL_LIB_CTX")]
public class LibraryContext {
}
[CCode (cheader_filename = "openssl/core.h", cname = "OSSL_PARAM", has_copy_function = false, has_destroy_function = false)]
public struct Param {
public unowned string? key;
public ParamDataType data_type;
[CCode (array_length_cname = "data_size")]
public unowned uint8[]? data;
public size_t return_size;
}
[CCode (cheader_filename = "openssl/core.h", cname = "guint", cprefix = "OSSL_PARAM_", has_type_id = false)]
public enum ParamDataType {
INTEGER,
UNSIGNED_INTEGER,
REAL,
UTF8_STRING,
OCTET_STRING,
UTF8_PTR,
OCTET_PTR,
}
[CCode (cheader_filename = "openssl/core.h", cname = "size_t", cprefix = "OSSL_PARAM_", has_type_id = false)]
public enum ParamReturnSize {
UNMODIFIED,
}
[CCode (cheader_filename = "openssl/objects.h", lower_case_cprefix = "SN_")]
namespace ShortName {
public const string sha256;
public const string sha384;
public const string sha512;
public const string chacha20_poly1305;
}
[CCode (cheader_filename = "openssl/rand.h")]
namespace Rng {
[CCode (cname = "RAND_bytes")]
public int generate (uint8[] buf);
}
[Compact]
[CCode (cname = "BN_CTX", cprefix = "BN_CTX_")]
public class BigNumberContext {
[CCode (cname = "BN_CTX_secure_new")]
public BigNumberContext.secure ();
}
[Compact]
[CCode (cname = "BIGNUM", cprefix = "BN_")]
public class BigNumber {
public BigNumber ();
[CCode (cname = "BN_native2bn")]
public BigNumber.from_native (uint8[] data, BigNumber * ret = null);
[CCode (cname = "BN_bin2bn")]
public BigNumber.from_big_endian (uint8[] data, BigNumber * ret = null);
public static BigNumber get_rfc2409_prime_768 (BigNumber * ret = null);
public static BigNumber get_rfc2409_prime_1024 (BigNumber * ret = null);
public static BigNumber get_rfc3526_prime_1536 (BigNumber * ret = null);
public static BigNumber get_rfc3526_prime_2048 (BigNumber * ret = null);
public static BigNumber get_rfc3526_prime_3072 (BigNumber * ret = null);
public static BigNumber get_rfc3526_prime_4096 (BigNumber * ret = null);
public static BigNumber get_rfc3526_prime_6144 (BigNumber * ret = null);
public static BigNumber get_rfc3526_prime_8192 (BigNumber * ret = null);
public bool is_zero ();
public static int add (BigNumber r, BigNumber a, BigNumber b);
public static int sub (BigNumber r, BigNumber a, BigNumber b);
public static int mul (BigNumber r, BigNumber a, BigNumber b, BigNumberContext ctx);
public static int mod (BigNumber rem, BigNumber m, BigNumber d, BigNumberContext ctx);
public static int mod_exp (BigNumber r, BigNumber a, BigNumber p, BigNumber m, BigNumberContext ctx);
public int num_bits ();
public int num_bytes ();
[CCode (cname = "BN_bn2bin")]
public int to_big_endian ([CCode (array_length = false)] uint8[] to);
[CCode (cname = "BN_bn2binpad")]
public int to_big_endian_padded (uint8[] to);
[CCode (cname = "BN_bn2dec")]
public char * to_string ();
[CCode (cname = "BN_bn2hex")]
public char * to_hex_string ();
}
[CCode (cheader_filename = "openssl/crypto.h", lower_case_cprefix = "CRYPTO_")]
namespace Crypto {
public int memcmp (void * a, void * b, size_t len);
}
[CCode (lower_case_cprefix = "ERR_")]
namespace Error {
public ulong get_error ();
public void error_string_n (ulong e, char[] buf);
}
public void free (void * addr);
}