Compare commits

..
Author SHA1 Message Date
Ole André Vadla Ravnås e0ada4a9ff [WIP] Toy around with a potential Softwall feature 2026-02-12 23:13:19 +01:00
82 changed files with 3034 additions and 9454 deletions

No files matched your search

+8 -19
View File
@@ -149,20 +149,9 @@ def setup(role: Role,
other_triplet: Optional[str] = None
extra_environ: dict[str, str] = {}
if host_os == "windows" and host_arch in {"x86_64", "x86"}:
if host_arch == "x86_64":
other_label = "x86"
other_kind = "legacy"
else:
other_label = "x86_64"
other_kind = "modern"
if host_config == "mingw":
have_toolchain, other_triplet = detect_mingw_toolchain_for(other_label)
else:
have_toolchain = True
other_triplet = None
if host_os == "windows" and host_arch == "x86_64" and host_config == "mingw":
other_label = "x86"
have_toolchain, other_triplet = detect_mingw_toolchain_for("x86")
elif host_os == "linux" and host_arch == "x86_64" and host_config is None:
other_label = "x86"
other_triplet = "i686-linux-gnu"
@@ -190,21 +179,21 @@ def setup(role: Role,
raise ToolchainNotFoundError(f"unable to locate toolchain for {other_triplet}")
missing.append(MissingFeature(other_label, other_triplet))
if host_os == "windows" and host_arch in {"x86_64", "x86"} and have_toolchain:
group = OutputGroup(other_label, other_triplet, extra_environ)
if host_os == "windows" and host_arch == "x86_64" and have_toolchain:
group = OutputGroup("x86", other_triplet, extra_environ)
outputs[group] = [
Output(identifier=f"helper_{other_kind}",
Output(identifier="helper_legacy",
name=HELPER_FILE_WINDOWS.name,
file=HELPER_FILE_WINDOWS,
target=HELPER_TARGET),
Output(identifier=f"agent_{other_kind}",
Output(identifier="agent_legacy",
name=AGENT_FILE_WINDOWS.name,
file=AGENT_FILE_WINDOWS,
target=AGENT_TARGET),
]
if "gadget" in components:
outputs[group] += [
Output(identifier=f"gadget_{other_kind}",
Output(identifier="gadget_legacy",
name=GADGET_FILE_WINDOWS.name,
file=GADGET_FILE_WINDOWS,
target=GADGET_TARGET),
-2
View File
@@ -51,8 +51,6 @@ void
_frida_agent_environment_deinit (void)
{
#ifndef HAVE_MUSL
frida_libc_shim_prepare_to_deinit ();
gum_shutdown ();
gio_shutdown ();
glib_shutdown ();
-14
View File
@@ -1,14 +0,0 @@
FRIDA_1.0 {
global:
frida_agent_main;
local:
*;
};
GLIBC_2.2.5 {
local:
fopen*;
fseeko*;
ftello*;
} FRIDA_1.0;
+1 -7
View File
@@ -28,13 +28,7 @@ if host_os_family == 'windows'
elif host_os_family == 'darwin'
extra_link_args += '-Wl,-exported_symbol,_frida_agent_main'
else
if libc == 'glibc'
symscript = 'frida-agent-glibc.version'
elif host_os == 'android'
symscript = 'frida-agent-android.version'
else
symscript = 'frida-agent.version'
endif
symscript = (host_os == 'android') ? 'frida-agent-android.version' : 'frida-agent.version'
extra_link_args += '-Wl,--version-script,' + meson.current_source_dir() / symscript
extra_link_depends += symscript
endif
+127 -262
View File
@@ -309,17 +309,8 @@ namespace Frida {
public sealed class Buffer : Object {
public Bytes bytes {
get {
if (_bytes == null)
_bytes = new Bytes.static (_data);
return _bytes;
}
}
public size_t size {
get {
return _data.length;
}
get;
construct;
}
public ByteOrder byte_order {
@@ -332,39 +323,20 @@ namespace Frida {
construct;
}
private Bytes? _bytes;
private unowned uint8[] _data;
private unowned uint8 * data;
private size_t size;
public Buffer (Bytes bytes, ByteOrder byte_order = HOST, uint pointer_size = (uint) sizeof (size_t)) {
Object (
bytes: bytes,
byte_order: byte_order,
pointer_size: pointer_size
);
reset_bytes (bytes);
}
public Buffer.from_data (uint8[] data, ByteOrder byte_order = HOST, uint pointer_size = (uint) sizeof (size_t)) {
Object (
byte_order: byte_order,
pointer_size: pointer_size
);
reset_data (data);
}
public void reset_bytes (Bytes bytes) {
_bytes = bytes;
_data = bytes.get_data ();
}
public void reset_data (uint8[] data) {
_bytes = null;
_data = data;
}
public unowned uint8[] peek_data () {
return _data;
construct {
data = bytes.get_data ();
size = bytes.get_size ();
}
public uint64 read_pointer (size_t offset) {
@@ -498,13 +470,17 @@ namespace Frida {
return *((double *) &bits);
}
public unowned string read_string (size_t offset) throws Error {
public string read_string (size_t offset) throws Error {
string * start = (string *) get_pointer (offset, sizeof (char));
size_t max_length = _data.length - offset;
size_t max_length = size - offset;
string * end = memchr (start, 0, max_length);
if (end == null)
throw new Error.PROTOCOL ("Missing null character");
return start;
size_t size = end - start;
string val = start->substring (0, (long) size);
if (!val.validate ())
throw new Error.PROTOCOL ("Invalid UTF-8 string");
return val;
}
[CCode (cname = "memchr", cheader_filename = "string.h")]
@@ -512,14 +488,17 @@ namespace Frida {
public string read_fixed_string (size_t offset, size_t size) throws Error {
string * start = (string *) get_pointer (offset, size);
size_t max_length = size_t.min (size, _data.length - offset);
size_t max_length = size_t.min (size, this.size - offset);
string * end = memchr (start, 0, max_length);
size_t n;
if (end != null)
n = end - start;
else
n = size;
return start->substring (0, (long) n);
string val = start->substring (0, (long) n);
if (!val.validate ())
throw new Error.PROTOCOL ("Invalid UTF-8 string");
return val;
}
public unowned Buffer write_string (size_t offset, string val) {
@@ -529,14 +508,9 @@ namespace Frida {
}
public Bytes read_bytes (size_t offset, size_t size) {
if (_bytes == null)
return make_bytes_with_owner ((uint8 *) _data + offset, _data.length - size, this);
return _bytes[offset:offset + size];
}
public unowned uint8[] read_data (size_t offset, size_t size) {
unowned uint8 * ptr = get_pointer (offset, size);
return ((uint8[]) ptr)[:size];
var data = new uint8[size + 1];
Memory.copy (data, get_pointer (offset, size), size);
return new Bytes.take ((owned) data);
}
public unowned Buffer write_bytes (size_t offset, Bytes bytes) {
@@ -547,49 +521,129 @@ namespace Frida {
private uint8 * get_pointer (size_t offset, size_t n) {
size_t minimum_size = offset + n;
assert (_data.length >= minimum_size);
return (uint8 *) _data + offset;
assert (size >= minimum_size);
return data + offset;
}
}
public sealed class BufferReader {
public Buffer buffer {
get;
}
public size_t offset {
get;
get {
return _offset;
}
}
public size_t available {
get {
return _size - _offset;
return buffer.bytes.get_size () - _offset;
}
}
private size_t _size;
private Buffer buffer;
private size_t _offset = 0;
public BufferReader (Buffer buffer) {
reset (buffer);
public BufferReader (Buffer buf) {
buffer = buf;
}
public void reset (Buffer buffer) {
_buffer = buffer;
_size = buffer.size;
_offset = 0;
public uint64 read_pointer () throws Error {
var pointer_size = buffer.pointer_size;
check_available (pointer_size);
var ptr = buffer.read_pointer (_offset);
_offset += pointer_size;
return ptr;
}
public void reset_at (Buffer buffer, size_t offset) throws Error {
_buffer = buffer;
_size = buffer.size;
seek (offset);
public int8 read_int8 () throws Error {
check_available (sizeof (int8));
var val = buffer.read_int8 (_offset);
_offset += sizeof (int8);
return val;
}
public unowned BufferReader seek (size_t offset) throws Error {
if (offset > _size)
throw new Error.PROTOCOL ("Malformed buffer: truncated");
_offset = offset;
return this;
public uint8 read_uint8 () throws Error {
check_available (sizeof (uint8));
var val = buffer.read_uint8 (_offset);
_offset += sizeof (uint8);
return val;
}
public int16 read_int16 () throws Error {
check_available (sizeof (int16));
var val = buffer.read_int16 (_offset);
_offset += sizeof (int16);
return val;
}
public uint16 read_uint16 () throws Error {
check_available (sizeof (uint16));
var val = buffer.read_uint16 (_offset);
_offset += sizeof (uint16);
return val;
}
public int32 read_int32 () throws Error {
check_available (sizeof (int32));
var val = buffer.read_int32 (_offset);
_offset += sizeof (int32);
return val;
}
public uint32 read_uint32 () throws Error {
check_available (sizeof (uint32));
var val = buffer.read_uint32 (_offset);
_offset += sizeof (uint32);
return val;
}
public int64 read_int64 () throws Error {
check_available (sizeof (int64));
var val = buffer.read_int64 (_offset);
_offset += sizeof (int64);
return val;
}
public uint64 read_uint64 () throws Error {
check_available (sizeof (uint64));
var val = buffer.read_uint64 (_offset);
_offset += sizeof (uint64);
return val;
}
public float read_float () throws Error {
check_available (sizeof (float));
var val = buffer.read_float (_offset);
_offset += sizeof (float);
return val;
}
public double read_double () throws Error {
check_available (sizeof (double));
var val = buffer.read_double (_offset);
_offset += sizeof (double);
return val;
}
public string read_string () throws Error {
check_available (1);
var val = buffer.read_string (_offset);
_offset += val.length + 1;
return val;
}
public string read_fixed_string (size_t size) throws Error {
check_available (size);
var val = buffer.read_fixed_string (_offset, size);
_offset += size;
return val;
}
public Bytes read_bytes (size_t size) throws Error {
check_available (size);
var val = buffer.bytes[_offset:_offset + size];
_offset += size;
return val;
}
public unowned BufferReader skip (size_t n) throws Error {
@@ -598,195 +652,6 @@ namespace Frida {
return this;
}
public unowned BufferReader align (size_t alignment) throws Error {
size_t mask = alignment - 1;
size_t rem = _offset & mask;
if (rem != 0)
skip (alignment - rem);
return this;
}
public uint64 peek_pointer () throws Error {
var pointer_size = _buffer.pointer_size;
check_available (pointer_size);
return _buffer.read_pointer (_offset);
}
public uint64 read_pointer () throws Error {
var pointer_size = _buffer.pointer_size;
check_available (pointer_size);
var ptr = _buffer.read_pointer (_offset);
_offset += pointer_size;
return ptr;
}
public int8 peek_int8 () throws Error {
check_available (sizeof (int8));
return _buffer.read_int8 (_offset);
}
public int8 read_int8 () throws Error {
check_available (sizeof (int8));
var val = _buffer.read_int8 (_offset);
_offset += sizeof (int8);
return val;
}
public uint8 peek_uint8 () throws Error {
check_available (sizeof (uint8));
return _buffer.read_uint8 (_offset);
}
public uint8 read_uint8 () throws Error {
check_available (sizeof (uint8));
var val = _buffer.read_uint8 (_offset);
_offset += sizeof (uint8);
return val;
}
public int16 peek_int16 () throws Error {
check_available (sizeof (int16));
return _buffer.read_int16 (_offset);
}
public int16 read_int16 () throws Error {
check_available (sizeof (int16));
var val = _buffer.read_int16 (_offset);
_offset += sizeof (int16);
return val;
}
public uint16 peek_uint16 () throws Error {
check_available (sizeof (uint16));
return _buffer.read_uint16 (_offset);
}
public uint16 read_uint16 () throws Error {
check_available (sizeof (uint16));
var val = _buffer.read_uint16 (_offset);
_offset += sizeof (uint16);
return val;
}
public int32 peek_int32 () throws Error {
check_available (sizeof (int32));
return _buffer.read_int32 (_offset);
}
public int32 read_int32 () throws Error {
check_available (sizeof (int32));
var val = _buffer.read_int32 (_offset);
_offset += sizeof (int32);
return val;
}
public uint32 peek_uint32 () throws Error {
check_available (sizeof (uint32));
return _buffer.read_uint32 (_offset);
}
public uint32 read_uint32 () throws Error {
check_available (sizeof (uint32));
var val = _buffer.read_uint32 (_offset);
_offset += sizeof (uint32);
return val;
}
public int64 peek_int64 () throws Error {
check_available (sizeof (int64));
return _buffer.read_int64 (_offset);
}
public int64 read_int64 () throws Error {
check_available (sizeof (int64));
var val = _buffer.read_int64 (_offset);
_offset += sizeof (int64);
return val;
}
public uint64 peek_uint64 () throws Error {
check_available (sizeof (uint64));
return _buffer.read_uint64 (_offset);
}
public uint64 read_uint64 () throws Error {
check_available (sizeof (uint64));
var val = _buffer.read_uint64 (_offset);
_offset += sizeof (uint64);
return val;
}
public float peek_float () throws Error {
check_available (sizeof (float));
return _buffer.read_float (_offset);
}
public float read_float () throws Error {
check_available (sizeof (float));
var val = _buffer.read_float (_offset);
_offset += sizeof (float);
return val;
}
public double peek_double () throws Error {
check_available (sizeof (double));
return _buffer.read_double (_offset);
}
public double read_double () throws Error {
check_available (sizeof (double));
var val = _buffer.read_double (_offset);
_offset += sizeof (double);
return val;
}
public unowned string peek_string () throws Error {
check_available (1);
return _buffer.read_string (_offset);
}
public unowned string read_string () throws Error {
check_available (1);
unowned string val = _buffer.read_string (_offset);
_offset += val.length + 1;
return val;
}
public string peek_fixed_string (size_t size) throws Error {
check_available (size);
return _buffer.read_fixed_string (_offset, size);
}
public string read_fixed_string (size_t size) throws Error {
check_available (size);
var val = _buffer.read_fixed_string (_offset, size);
_offset += size;
return val;
}
public unowned uint8[] peek_data (size_t size) throws Error {
check_available (size);
return _buffer.read_data (_offset, size);
}
public unowned uint8[] read_data (size_t size) throws Error {
check_available (size);
unowned uint8[] slice = _buffer.read_data (_offset, size);
_offset += size;
return slice;
}
public Bytes read_bytes (size_t size) throws Error {
check_available (size);
var val = _buffer.read_bytes (_offset, size);
_offset += size;
return val;
}
public unowned uint8[] read_remaining_data () throws Error {
return read_data (available);
}
private void check_available (size_t n) throws Error {
if (available < n)
throw new Error.PROTOCOL ("Malformed buffer: truncated");
+2 -12
View File
@@ -1,26 +1,18 @@
#ifndef __FRIDA_ATOMICS_H__
#define __FRIDA_ATOMICS_H__
#include <glib.h>
G_BEGIN_DECLS
#ifdef _MSC_VER
/* TODO: Add once needed. */
#else
typedef guint64 FridaAtomicU64 __attribute__ ((aligned (8)));
static inline guint64
frida_atomics_load_u64_acquire (volatile FridaAtomicU64 * p)
static inline guint64 frida_atomics_load_u64_acquire (volatile guint64 * p)
{
return __atomic_load_n (p, __ATOMIC_ACQUIRE);
}
static inline void
frida_atomics_store_u64_release (volatile FridaAtomicU64 * p, guint64 v)
static inline void frida_atomics_store_u64_release (volatile guint64 * p, guint64 v)
{
__atomic_store_n (p, v, __ATOMIC_RELEASE);
}
@@ -32,6 +24,4 @@ static inline guint32 frida_atomics_load_u32_acquire (volatile guint32 * p)
#endif
G_END_DECLS
#endif
+3 -3
View File
@@ -1,6 +1,6 @@
[CCode (cheader_filename = "frida-atomics.h")]
namespace Frida.Atomics {
public static uint64 load_u64_acquire (uint64 * p);
public static void store_u64_release (uint64 * p, uint64 v);
public static uint32 load_u32_acquire (uint32 * p);
public static uint64 load_u64_acquire (void * p);
public static void store_u64_release (void * p, uint64 v);
public static uint32 load_u32_acquire (void * p);
}
-4
View File
@@ -6,8 +6,6 @@
#include <glib.h>
#include <xpc/xpc.h>
G_BEGIN_DECLS
typedef void (* FridaXpcHandler) (xpc_object_t object, gpointer user_data);
typedef gboolean (* FridaXpcDictionaryApplier) (const gchar * key, xpc_object_t val, gpointer user_data);
@@ -19,8 +17,6 @@ void _frida_xpc_connection_send_message_with_reply (xpc_connection_t connection,
gchar * _frida_xpc_object_to_string (xpc_object_t object);
gboolean _frida_xpc_dictionary_apply (xpc_object_t dict, FridaXpcDictionaryApplier applier, gpointer user_data);
G_END_DECLS
#endif
#endif
-41
View File
@@ -1,41 +0,0 @@
#ifndef __FRIDA_JNI_H__
#define __FRIDA_JNI_H__
#include <jni.h>
G_BEGIN_DECLS
typedef jint (* JNIDestroyJavaVMFunc) (JavaVM *);
typedef jint (* JNIAttachCurrentThreadFunc) (JavaVM *, JNIEnv **, void *);
typedef jint (* JNIDetachCurrentThreadFunc) (JavaVM *);
typedef jint (* JNIGetEnvFunc) (JavaVM *, JNIEnv **, jint);
typedef jclass (* JNIFindClassFunc) (JNIEnv *, const char *);
typedef jthrowable (* JNIExceptionOccurredFunc) (JNIEnv *);
typedef void (* JNIExceptionDescribeFunc) (JNIEnv *);
typedef void (* JNIExceptionClearFunc) (JNIEnv *);
typedef jint (* JNIPushLocalFrameFunc) (JNIEnv *, jint);
typedef jobject (* JNIPopLocalFrameFunc) (JNIEnv *, jobject);
typedef jobject (* JNINewGlobalRefFunc) (JNIEnv *, jobject);
typedef void (* JNIDeleteGlobalRefFunc) (JNIEnv *, jobject);
typedef void (* JNIDeleteLocalRefFunc) (JNIEnv *, jobject);
typedef jobject (* JNINewObjectFunc) (JNIEnv *, jclass, jmethodID, ...);
typedef jclass (* JNIGetObjectClassFunc) (JNIEnv *, jobject);
typedef jmethodID (* JNIGetMethodIDFunc) (JNIEnv *, jclass, const char *, const char *);
typedef jobject (* JNICallObjectMethodFunc) (JNIEnv *, jobject, jmethodID, ...);
typedef jstring (* JNINewStringUTFFunc) (JNIEnv *, const char *);
typedef const char * (* JNIGetStringUTFCharsFunc) (JNIEnv *, jstring, jboolean *);
typedef void (* JNIReleaseStringUTFCharsFunc) (JNIEnv *, jstring, const char *);
typedef jboolean (* JNIExceptionCheckFunc) (JNIEnv *);
G_END_DECLS
#endif
+2 -14
View File
@@ -46,7 +46,7 @@ namespace Frida {
public extern unowned LinuxSyscallSignature[]? get_compat32_syscall_signatures ();
public struct LinuxSyscallSignature {
public int nr;
public uint nr;
public string name;
public uint8 nargs;
public LinuxSyscallArg args[6];
@@ -141,7 +141,7 @@ namespace Frida {
private char[] kernel_log_buf;
public static BpfObject open (string name, uint8[] blob) throws Error {
var log_buf = new char[128 * 1024];
var log_buf = new char[64 * 1024];
var opts = Libbpf.Object.OpenOpts ();
opts.sz = sizeof (Libbpf.Object.OpenOpts);
@@ -348,18 +348,6 @@ namespace Frida {
remove_raw ((uint8[]) &key);
}
public void update_u64_u8 (uint64 key, uint8 val) throws Error {
update_raw ((uint8[]) &key, (uint8[]) &val);
}
public void update_u64_u32 (uint64 key, uint32 val) throws Error {
update_raw ((uint8[]) &key, (uint8[]) &val);
}
public void remove_u64 (uint64 key) throws Error {
remove_raw ((uint8[]) &key);
}
public void foreach_percpu_value<T> (uint8[] key, PercpuValueFunc<T> func) throws Error {
var ncpus = check_libbpf_result (Libbpf.num_possible_cpus ());
var percpu_stride = round_up_8 (value_size);
-2
View File
@@ -15,8 +15,6 @@ base_sources = [
'buffer.vala',
'buffer-glue.c',
'value.vala',
'xnu-syscalls' / 'xnu-syscalls.vala',
'xnu-syscalls' / 'xnu-syscalls-glue.c',
]
extra_vala_args = []
+1 -12
View File
@@ -2170,10 +2170,7 @@ namespace Frida {
public static string enum_to_nick<T> (int val) {
var klass = (EnumClass) typeof (T).class_ref ();
unowned EnumValue? v = klass.get_value (val);
if (v == null)
return "unknown-0x%x".printf (val);
return v.value_nick;
return klass.get_value (val).value_nick;
}
}
@@ -2199,13 +2196,5 @@ namespace Frida {
uint64 b = val_b;
return a == b;
}
public uint bytes_hash (Bytes b) {
return b.hash ();
}
public static bool bytes_equal (Bytes a, Bytes b) {
return a.compare (b) == 0;
}
}
}
-4
View File
@@ -940,9 +940,6 @@ namespace Frida {
Memory.copy (buffer, recv_queue.data, n);
recv_queue.remove_range (0, (uint) n);
if (recv_queue.len == 0)
websocket.resume_input ();
update_pending_io ();
} else {
if (state == OPEN)
@@ -1009,7 +1006,6 @@ namespace Frida {
private void on_message (int type, Bytes message) {
with_state_lock (() => {
recv_queue.append (message.get_data ());
websocket.pause_input ();
update_pending_io ();
});
}
-860
View File
@@ -1,860 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations
import argparse
import re
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, List, Optional, Tuple
MAX_ARGS = 9
@dataclass(frozen=True)
class SyscallArg:
type: str
name: str
@dataclass(frozen=True)
class SyscallSignature:
name: str
args: Tuple[SyscallArg, ...]
MACH_TRAP_INDEXED_CALL_RE = re.compile(r"/\*\s*(?P<idx>\d+)\s*\*/\s*MACH_TRAP\s*\(")
MACH_TRAPS_IFNDEF_KERNEL_RE = re.compile(r"^\s*#ifndef\s+KERNEL\b", re.MULTILINE)
MACH_TRAPS_ELSE_KERNEL_RE = re.compile(r"^\s*#else\b.*\bKERNEL\b", re.MULTILINE)
USER_EXTERN_PROTO_RE = re.compile(
r"^\s*extern\s+(?P<ret>.+?)\s+(?P<fn>[A-Za-z_]\w*)\s*\((?P<args>.*?)\)\s*;",
re.MULTILINE | re.DOTALL,
)
KERNEL_STRUCT_RE = re.compile(
r"\bstruct\s+(?P<name>[A-Za-z_]\w*)\s*\{\s*(?P<body>.*?)\s*\}\s*;",
re.DOTALL,
)
KERNEL_TRAP_EXTERN_RE = re.compile(
r"^\s*(?:extern\s+)?(?P<ret>.+?)\s+(?P<fn>[A-Za-z_]\w*)\s*\(\s*struct\s+(?P<args_struct>[A-Za-z_]\w*)\s*\*\s*args\s*\)\s*;",
re.MULTILINE | re.DOTALL,
)
PAD_ARG_RE = re.compile(
r"\bPAD_ARG_\s*\(\s*(?P<ty>[^,]+?)\s*,\s*(?P<name>[^)]+?)\s*\)\s*;",
)
PLAIN_FIELD_RE = re.compile(r"^\s*(?P<ty>.+?)\s+(?P<name>[A-Za-z_]\w*)\s*;\s*$")
BSD_MASTER_ENTRY_RE = re.compile(
r"^\s*(?P<nr>\d+)\s+(?P<audit>\S+)\s+(?P<files>\S+)\s+\{\s*(?P<proto>[^}]+?)\s*\}\s*(?:\{.*\})?\s*$"
)
BSD_MASTER_PROTO_RE = re.compile(
r"^\s*(?P<ret>.+?)\s+(?P<fn>[A-Za-z_]\w*)\s*\((?P<args>.*)\)\s*(?P<attrs>.*)$",
re.DOTALL,
)
LINE_COMMENT_RE = re.compile(r"//.*$")
BLOCK_COMMENT_RE = re.compile(r"/\*[^*]*\*+(?:[^/*][^*]*\*+)*/")
TRAILING_ARRAY_SUFFIX_RE = re.compile(r"\[[^\]]*\]\s*$")
POINTER_SPACING_RE = re.compile(r"\s*\*\s*")
PARAM_NAME_RE = re.compile(r"[A-Za-z_]\w*$")
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("--kernel-tree", required=True)
ap.add_argument("--out-vala", required=True)
ap.add_argument("--out-c", required=True)
args = ap.parse_args()
kernel_tree = Path(args.kernel_tree).resolve()
if not kernel_tree.exists():
raise SystemExit(f"--kernel-tree does not exist: {kernel_tree}")
mach_numbers, mach_sigs = load_mach_traps(kernel_tree)
bsd_numbers, bsd_sigs = load_bsd_syscalls_master(kernel_tree)
vala = render_vala(
mach_numbers=mach_numbers,
bsd_numbers=bsd_numbers,
)
c_src = render_c_source(
mach_numbers=mach_numbers,
bsd_numbers=bsd_numbers,
mach_sigs=mach_sigs,
bsd_sigs=bsd_sigs,
)
out_vala = Path(args.out_vala)
out_c = Path(args.out_c)
out_vala.parent.mkdir(parents=True, exist_ok=True)
out_c.parent.mkdir(parents=True, exist_ok=True)
out_vala.write_text(vala, encoding="utf-8")
out_c.write_text(c_src, encoding="utf-8")
return 0
def load_mach_traps(
kernel_tree: Path,
) -> Tuple[Dict[int, str], Dict[str, SyscallSignature]]:
table_path = kernel_tree / "osfmk" / "kern" / "syscall_sw.c"
if not table_path.exists():
raise RuntimeError(f"Missing Mach trap table source: {table_path}")
header_path = kernel_tree / "osfmk" / "mach" / "mach_traps.h"
if not header_path.exists():
raise RuntimeError(f"Missing Mach traps header: {header_path}")
table_text = table_path.read_text(encoding="utf-8", errors="ignore")
trap_routines = parse_mach_trap_table(table_text, table_path)
header_text = header_path.read_text(encoding="utf-8", errors="ignore")
userspace_text, kernel_text = split_mach_traps_header(header_text, header_path)
userspace_protos = parse_userspace_mach_traps_prototypes(
userspace_text, header_path
)
kernel_argmap = parse_kernel_mach_traps_args(kernel_text, header_path)
numbers: Dict[int, str] = {}
sigs: Dict[str, SyscallSignature] = {}
for index, routine in trap_routines:
if routine == "kern_invalid":
continue
nr = -index
public_name = normalize_mach_name(routine)
if public_name == "":
raise RuntimeError(f"{table_path}: empty normalized name from {routine!r}")
if nr in numbers:
raise RuntimeError(f"{table_path}: duplicate mach trap number {nr}")
if public_name in sigs:
raise RuntimeError(
f"{table_path}: normalized Mach name collision for {public_name!r}"
)
args = resolve_mach_trap_signature(
routine=routine,
userspace_protos=userspace_protos,
kernel_argmap=kernel_argmap,
table_path=table_path,
)
if len(args) > MAX_ARGS:
raise RuntimeError(
f"{table_path}: trap {routine!r} has {len(args)} args; max supported is {MAX_ARGS}"
)
numbers[nr] = public_name
sigs[public_name] = SyscallSignature(name=public_name, args=tuple(args))
return numbers, sigs
def parse_mach_trap_table(text: str, path: Path) -> List[Tuple[int, str]]:
anchor = text.find("mach_trap_table")
if anchor == -1:
raise RuntimeError(f"{path}: mach_trap_table not found")
brace = text.find("{", anchor)
if brace == -1:
raise RuntimeError(f"{path}: mach_trap_table '{{' not found")
payload, _ = extract_brace_payload(text, brace, path)
by_index: Dict[int, str] = {}
off = 0
while True:
m = MACH_TRAP_INDEXED_CALL_RE.search(payload, off)
if m is None:
break
idx = int(m.group("idx"), 10)
open_paren = m.end(0) - 1
args_blob, end_off = extract_parentheses_payload(payload, open_paren, path)
parts = [
a.strip() for a in split_top_level_commas(args_blob) if a.strip() != ""
]
if len(parts) < 1:
raise RuntimeError(f"{path}: bad MACH_TRAP() entry: {args_blob!r}")
routine = parts[0]
prev = by_index.get(idx)
if prev is None:
by_index[idx] = routine
else:
if prev == routine:
pass
elif prev == "kern_invalid" and routine != "kern_invalid":
by_index[idx] = routine
elif routine == "kern_invalid" and prev != "kern_invalid":
pass
else:
raise RuntimeError(
f"{path}: conflicting MACH_TRAP entries for index {idx}: {prev!r} vs {routine!r}"
)
off = end_off
return sorted(by_index.items(), key=lambda kv: kv[0])
def split_mach_traps_header(text: str, path: Path) -> Tuple[str, str]:
m_start = MACH_TRAPS_IFNDEF_KERNEL_RE.search(text)
if m_start is None:
raise RuntimeError(f"{path}: missing '#ifndef KERNEL'")
m_else = MACH_TRAPS_ELSE_KERNEL_RE.search(text, m_start.end())
if m_else is None:
raise RuntimeError(f"{path}: missing '#else ... KERNEL ...'")
userspace = text[m_start.end():m_else.start()]
kernel = text[m_else.end():]
return userspace, kernel
def parse_userspace_mach_traps_prototypes(
userspace_text: str, path: Path
) -> Dict[str, Tuple[SyscallArg, ...]]:
protos: Dict[str, Tuple[SyscallArg, ...]] = {}
for m in USER_EXTERN_PROTO_RE.finditer(userspace_text):
fn = m.group("fn").strip()
args_blob = m.group("args").strip()
ret_blob = strip_c_comments(m.group("ret")).strip()
if ret_blob == "":
raise RuntimeError(f"{path}: empty return type for {fn!r}")
line_no = line_number_at_offset(userspace_text, m.start())
args = parse_c_param_list(args_blob, path, line_no)
cur = tuple(args)
prev = protos.get(fn)
if prev is not None and prev != cur:
raise RuntimeError(f"{path}:{line_no}: conflicting prototype for {fn!r}")
protos[fn] = cur
return protos
def parse_kernel_mach_traps_args(
kernel_text: str, path: Path
) -> Dict[str, Tuple[SyscallArg, ...]]:
text = strip_c_comments(kernel_text)
structs: Dict[str, str] = {}
for m in KERNEL_STRUCT_RE.finditer(text):
name = m.group("name").strip()
body = m.group("body")
structs[name] = body
fn_to_struct: Dict[str, str] = {}
for m in KERNEL_TRAP_EXTERN_RE.finditer(text):
fn = m.group("fn").strip()
args_struct = m.group("args_struct").strip()
fn_to_struct[fn] = args_struct
out: Dict[str, Tuple[SyscallArg, ...]] = {}
for fn, args_struct in fn_to_struct.items():
body = structs.get(args_struct)
if body is None:
continue
args = parse_mach_args_struct_body(body, path)
out[fn] = tuple(args)
return out
def parse_mach_args_struct_body(body: str, path: Path) -> List[SyscallArg]:
args: List[SyscallArg] = []
body = strip_c_comments(body)
for raw_ln in body.splitlines():
ln = raw_ln.strip()
if ln == "" or ln.startswith("#"):
continue
if "PAD_ARG_8" in ln:
continue
m = PAD_ARG_RE.search(ln)
if m is not None:
ty = normalize_whitespace(m.group("ty").strip())
name = normalize_whitespace(m.group("name").strip())
if ty == "" or name == "":
raise RuntimeError(f"{path}: bad PAD_ARG_ in args struct: {raw_ln!r}")
args.append(SyscallArg(type=ty, name=name))
continue
m = PLAIN_FIELD_RE.match(ln)
if m is not None:
ty = normalize_whitespace(m.group("ty").strip())
name = m.group("name").strip()
if ty == "" or name == "":
raise RuntimeError(f"{path}: bad field in args struct: {raw_ln!r}")
args.append(SyscallArg(type=ty, name=name))
continue
if len(args) == 1 and args[0].name == "dummy":
return []
return args
def resolve_mach_trap_signature(
*,
routine: str,
userspace_protos: Dict[str, Tuple[SyscallArg, ...]],
kernel_argmap: Dict[str, Tuple[SyscallArg, ...]],
table_path: Path,
) -> List[SyscallArg]:
def get_userspace(name: str) -> Optional[Tuple[SyscallArg, ...]]:
return userspace_protos.get(name)
def get_kernel(name: str) -> Optional[Tuple[SyscallArg, ...]]:
return kernel_argmap.get(name)
proto_args = get_userspace(routine)
if proto_args is None and routine.endswith("_trap"):
proto_args = get_userspace(routine[: -len("_trap")])
if proto_args is not None:
return list(proto_args)
proto_args = get_kernel(routine)
if proto_args is None and routine.endswith("_trap"):
proto_args = get_kernel(routine[: -len("_trap")])
if proto_args is None:
raise RuntimeError(
f"{table_path}: missing userspace prototype for {routine!r}, and no kernel extern(struct *_args *args) mapping found"
)
return list(proto_args)
def normalize_mach_name(routine: str) -> str:
if routine.startswith("_"):
routine = routine[1:]
if routine.startswith("kernelrpc_"):
routine = routine[len("kernelrpc_"):]
if routine.endswith("_trap"):
routine = routine[: -len("_trap")]
return routine
def load_bsd_syscalls_master(
kernel_tree: Path,
) -> Tuple[Dict[int, str], Dict[str, SyscallSignature]]:
path = kernel_tree / "bsd" / "kern" / "syscalls.master"
if not path.exists():
raise RuntimeError(f"Missing BSD master file: {path}")
numbers: Dict[int, str] = {}
sigs: Dict[str, SyscallSignature] = {}
lines = path.read_text(encoding="utf-8", errors="ignore").splitlines()
stack: List[bool] = []
active = True
for line_no, raw in enumerate(lines, start=1):
line = raw.rstrip("\n")
stripped = line.lstrip()
if (
stripped.startswith("#if ")
or stripped.startswith("#ifdef ")
or stripped.startswith("#ifndef ")
):
stack.append(active)
continue
if stripped.startswith("#else"):
if not stack:
raise RuntimeError(f"{path}:{line_no}: #else without #if")
active = False
continue
if stripped.startswith("#endif"):
if not stack:
raise RuntimeError(f"{path}:{line_no}: #endif without #if")
active = stack.pop()
continue
if not active:
continue
m = BSD_MASTER_ENTRY_RE.match(line)
if m is None:
continue
nr = int(m.group("nr"), 10)
proto_blob = strip_c_comments(m.group("proto")).strip()
mp = BSD_MASTER_PROTO_RE.match(proto_blob)
if mp is None:
raise RuntimeError(
f"{path}:{line_no}: cannot parse prototype: {proto_blob!r}"
)
fn = mp.group("fn").strip()
args_blob = mp.group("args").strip()
if fn in {"nosys", "enosys"}:
continue
public_name = normalize_bsd_name(fn)
if public_name == "":
raise RuntimeError(f"{path}:{line_no}: empty normalized name from {fn!r}")
if nr in numbers:
raise RuntimeError(f"{path}:{line_no}: duplicate syscall number {nr}")
if public_name in sigs:
raise RuntimeError(
f"{path}:{line_no}: duplicate syscall name {public_name!r}"
)
args = parse_c_param_list(args_blob, path, line_no)
if len(args) > MAX_ARGS:
raise RuntimeError(
f"{path}:{line_no}: syscall {public_name!r} has {len(args)} args; max supported is {MAX_ARGS}"
)
numbers[nr] = public_name
sigs[public_name] = SyscallSignature(name=public_name, args=tuple(args))
return numbers, sigs
def normalize_bsd_name(fn: str) -> str:
if fn.startswith("sys_"):
return fn[len("sys_"):]
if fn.startswith("__"):
return fn[2:]
return fn
def strip_c_comments(s: str) -> str:
s = LINE_COMMENT_RE.sub("", s)
while True:
new_s = BLOCK_COMMENT_RE.sub("", s)
if new_s == s:
break
s = new_s
return s
def split_top_level_commas(text: str) -> List[str]:
parts: List[str] = []
buf: List[str] = []
depth = 0
in_string = False
string_quote = ""
cursor = 0
while cursor < len(text):
ch = text[cursor]
if in_string:
buf.append(ch)
if ch == "\\" and cursor + 1 < len(text):
buf.append(text[cursor + 1])
cursor += 2
continue
if ch == string_quote:
in_string = False
cursor += 1
continue
if ch in ("'", '"'):
in_string = True
string_quote = ch
buf.append(ch)
cursor += 1
continue
if ch == "(":
depth += 1
elif ch == ")":
depth = max(0, depth - 1)
if ch == "," and depth == 0:
parts.append("".join(buf).strip())
buf = []
cursor += 1
continue
buf.append(ch)
cursor += 1
parts.append("".join(buf).strip())
return parts
def parse_c_param_list(args_blob: str, path: Path, line_no: int) -> List[SyscallArg]:
raw = strip_c_comments(args_blob).strip()
if raw == "" or raw == "void":
return []
raw_params = [p.strip() for p in split_top_level_commas(raw) if p.strip() != ""]
if len(raw_params) == 1 and raw_params[0] == "void":
return []
args: List[SyscallArg] = []
for idx, p in enumerate(raw_params):
ty, name = split_param_decl(p, path, line_no)
if name is None:
name = f"arg{idx}"
if ty == "user_addr_t" and name in {"attrname", "link", "path"}:
ty = "char *"
args.append(SyscallArg(type=ty, name=name))
return args
def split_param_decl(decl: str, path: Path, line_no: int) -> Tuple[str, Optional[str]]:
d = strip_c_comments(decl).strip()
if d == "" or d == "void":
raise RuntimeError(f"{path}:{line_no}: bad parameter decl: {decl!r}")
tokens = _tokenize_decl(d)
ty_tokens, name = _split_type_and_name(tokens)
ty = _format_type(ty_tokens)
if not ty:
raise RuntimeError(
f"{path}:{line_no}: cannot parse parameter type from {decl!r}"
)
return ty, _camel_to_snake(name) if name else None
def _tokenize_decl(s: str) -> list[str]:
out = []
for c in s:
out.append(" * " if c == "*" else c)
return "".join(out).split()
def _split_type_and_name(tokens: list[str]) -> Tuple[list[str], Optional[str]]:
if not tokens:
return [], None
last = tokens[-1]
if last == "*":
return tokens, None
stars, remainder = _split_leading_stars(last)
if stars:
if _is_identifier(remainder):
return tokens[:-1] + ["*"] * stars, remainder
return tokens, None
if _is_identifier(last):
return tokens[:-1], last
return tokens, None
def _format_type(tokens: list[str]) -> str:
formatted: list[str] = []
i = 0
while i < len(tokens):
if tokens[i] != "*":
formatted.append(tokens[i])
i += 1
continue
j = i
while j < len(tokens) and tokens[j] == "*":
j += 1
formatted.append("*" * (j - i))
i = j
return " ".join(formatted).strip()
def _split_leading_stars(token: str) -> Tuple[int, str]:
i = 0
while i < len(token) and token[i] == "*":
i += 1
return i, token[i:]
def _is_identifier(s: str) -> bool:
if not s:
return False
if not (s[0].isalpha() or s[0] == "_"):
return False
return all(c.isalnum() or c == "_" for c in s)
def _camel_to_snake(name: str) -> str:
out = []
for i, c in enumerate(name):
if (
c.isupper()
and i > 0
and (name[i - 1].islower() or (i + 1 < len(name) and name[i + 1].islower()))
):
out.append("_")
out.append(c.lower())
return "".join(out)
def normalize_whitespace(s: str) -> str:
return " ".join(s.split())
def line_number_at_offset(text: str, offset: int) -> int:
return text.count("\n", 0, offset) + 1
def extract_parentheses_payload(
text: str, open_paren_offset: int, path: Path
) -> Tuple[str, int]:
if (
open_paren_offset < 0
or open_paren_offset >= len(text)
or text[open_paren_offset] != "("
):
raise RuntimeError(f"{path}: expected '(' at offset {open_paren_offset}")
depth = 0
cursor = open_paren_offset
start = open_paren_offset + 1
in_string = False
string_quote = ""
while cursor < len(text):
ch = text[cursor]
if in_string:
if ch == "\\":
cursor += 2
continue
if ch == string_quote:
in_string = False
cursor += 1
continue
if ch in ("'", '"'):
in_string = True
string_quote = ch
cursor += 1
continue
if ch == "(":
depth += 1
elif ch == ")":
depth -= 1
if depth == 0:
return text[start:cursor], cursor + 1
cursor += 1
raise RuntimeError(f"{path}: unterminated parentheses payload")
def extract_brace_payload(
text: str, open_brace_offset: int, path: Path
) -> Tuple[str, int]:
if (
open_brace_offset < 0
or open_brace_offset >= len(text)
or text[open_brace_offset] != "{"
):
raise RuntimeError(f"{path}: expected '{{' at offset {open_brace_offset}")
depth = 0
cursor = open_brace_offset
start = open_brace_offset + 1
in_string = False
string_quote = ""
while cursor < len(text):
ch = text[cursor]
if in_string:
if ch == "\\":
cursor += 2
continue
if ch == string_quote:
in_string = False
cursor += 1
continue
if ch in ("'", '"'):
in_string = True
string_quote = ch
cursor += 1
continue
if ch == "{":
depth += 1
elif ch == "}":
depth -= 1
if depth == 0:
return text[start:cursor], cursor + 1
cursor += 1
raise RuntimeError(f"{path}: unterminated brace payload")
def render_vala(*, mach_numbers: Dict[int, str], bsd_numbers: Dict[int, str]) -> str:
out: List[str] = []
out += [
"// AUTO-GENERATED FILE. DO NOT EDIT.\n",
"\n",
"namespace Frida {\n",
"\tpublic extern unowned XnuSyscallSignature[] get_xnu_mach_traps ();\n",
"\tpublic extern unowned XnuSyscallSignature[] get_xnu_bsd_syscalls ();\n",
"\n",
"\tpublic struct XnuSyscallSignature {\n",
"\t\tpublic int nr;\n",
"\t\tpublic string name;\n",
"\t\tpublic uint8 nargs;\n",
f"\t\tpublic XnuSyscallArg args[{MAX_ARGS}];\n",
"\t}\n",
"\n",
"\tpublic struct XnuSyscallArg {\n",
"\t\tpublic string? type;\n",
"\t\tpublic string? name;\n",
"\t}\n",
"\n",
"\tpublic enum XnuMachTrap {\n",
]
for nr, name in sorted(mach_numbers.items(), key=lambda kv: kv[0], reverse=True):
out += [f"\t\t{name.upper()} = {nr},\n"]
out += [
"\t}\n",
"\n",
"\tpublic enum XnuBsdSyscall {\n",
]
for nr, name in sorted(bsd_numbers.items(), key=lambda kv: kv[0]):
out += [f"\t\t{name.upper()} = {nr},\n"]
out += [
"\t}\n",
"}\n",
]
return "".join(out)
def render_c_source(
*,
mach_numbers: Dict[int, str],
bsd_numbers: Dict[int, str],
mach_sigs: Dict[str, SyscallSignature],
bsd_sigs: Dict[str, SyscallSignature],
) -> str:
out: List[str] = []
out += [
"/* AUTO-GENERATED FILE. DO NOT EDIT. */\n",
"\n",
'#include "frida-base.h"\n',
"\n",
]
emit_c_signature_table(
out,
c_var="frida_xnu_mach_traps",
numbers=mach_numbers,
sigs=mach_sigs,
reverse=True,
)
emit_c_signature_table(
out,
c_var="frida_xnu_bsd_syscalls",
numbers=bsd_numbers,
sigs=bsd_sigs,
)
emit_c_table_getter(
out, c_func="frida_get_xnu_mach_traps", c_var="frida_xnu_mach_traps"
)
out += ["\n"]
emit_c_table_getter(
out, c_func="frida_get_xnu_bsd_syscalls", c_var="frida_xnu_bsd_syscalls"
)
return "".join(out)
def emit_c_signature_table(
out: List[str],
*,
c_var: str,
numbers: Dict[int, str],
sigs: Dict[str, SyscallSignature],
reverse: bool = False,
) -> None:
out += [
f"static const FridaXnuSyscallSignature {c_var}[] =\n",
"{\n",
]
for nr, name in sorted(numbers.items(), key=lambda kv: kv[0], reverse=reverse):
sig = sigs[name]
args_parts: List[str] = []
for a in sig.args:
args_parts += [f"{{ {c_escape(a.type)}, {c_escape(a.name)} }}"]
args_blob = ", ".join(args_parts)
if args_blob != "":
out += [
f" {{ {nr}, {c_escape(name)}, {len(sig.args)}, {{ {args_blob} }} }},\n"
]
else:
out += [f" {{ {nr}, {c_escape(name)}, 0, {{}} }},\n"]
out += [
"};\n",
"\n",
]
def emit_c_table_getter(out: List[str], *, c_func: str, c_var: str) -> None:
out += [
"FridaXnuSyscallSignature *\n",
f"{c_func} (int * len)\n",
"{\n",
" if (len != NULL)\n",
f" *len = G_N_ELEMENTS ({c_var});\n",
f" return (FridaXnuSyscallSignature *) {c_var};\n",
"}\n",
]
def c_escape(s: str) -> str:
return '"' + s.replace("\\", "\\\\").replace('"', '\\"') + '"'
if __name__ == "__main__":
raise SystemExit(main())
-542
View File
@@ -1,542 +0,0 @@
/* AUTO-GENERATED FILE. DO NOT EDIT. */
#include "frida-base.h"
static const FridaXnuSyscallSignature frida_xnu_mach_traps[] =
{
{ -10, "mach_vm_allocate", 4, { { "mach_port_name_t", "target" }, { "mach_vm_offset_t *", "addr" }, { "mach_vm_size_t", "size" }, { "int", "flags" } } },
{ -11, "mach_vm_purgable_control", 4, { { "mach_port_name_t", "target" }, { "mach_vm_offset_t", "address" }, { "vm_purgable_t", "control" }, { "int *", "state" } } },
{ -12, "mach_vm_deallocate", 3, { { "mach_port_name_t", "target" }, { "mach_vm_address_t", "address" }, { "mach_vm_size_t", "size" } } },
{ -13, "task_dyld_process_info_notify_get", 2, { { "mach_port_name_array_t", "names_addr" }, { "natural_t *", "names_count_addr" } } },
{ -14, "mach_vm_protect", 5, { { "mach_port_name_t", "target" }, { "mach_vm_address_t", "address" }, { "mach_vm_size_t", "size" }, { "boolean_t", "set_maximum" }, { "vm_prot_t", "new_protection" } } },
{ -15, "mach_vm_map", 6, { { "mach_port_name_t", "target" }, { "mach_vm_offset_t *", "address" }, { "mach_vm_size_t", "size" }, { "mach_vm_offset_t", "mask" }, { "int", "flags" }, { "vm_prot_t", "cur_protection" } } },
{ -16, "mach_port_allocate", 3, { { "mach_port_name_t", "target" }, { "mach_port_right_t", "right" }, { "mach_port_name_t *", "name" } } },
{ -18, "mach_port_deallocate", 2, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" } } },
{ -19, "mach_port_mod_refs", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_right_t", "right" }, { "mach_port_delta_t", "delta" } } },
{ -20, "mach_port_move_member", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "member" }, { "mach_port_name_t", "after" } } },
{ -21, "mach_port_insert_right", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_name_t", "poly" }, { "mach_msg_type_name_t", "poly_poly" } } },
{ -22, "mach_port_insert_member", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_name_t", "pset" } } },
{ -23, "mach_port_extract_member", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_name_t", "pset" } } },
{ -24, "mach_port_construct", 4, { { "mach_port_name_t", "target" }, { "mach_port_options_t *", "options" }, { "uint64_t", "context" }, { "mach_port_name_t *", "name" } } },
{ -25, "mach_port_destruct", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_delta_t", "srdelta" }, { "uint64_t", "guard" } } },
{ -26, "mach_reply_port", 0, {} },
{ -27, "thread_self", 0, {} },
{ -28, "task_self", 0, {} },
{ -29, "host_self", 0, {} },
{ -31, "mach_msg", 7, { { "mach_msg_header_t *", "msg" }, { "mach_msg_option_t", "option" }, { "mach_msg_size_t", "send_size" }, { "mach_msg_size_t", "rcv_size" }, { "mach_port_name_t", "rcv_name" }, { "mach_msg_timeout_t", "timeout" }, { "mach_port_name_t", "notify" } } },
{ -32, "mach_msg_overwrite", 9, { { "mach_msg_header_t *", "msg" }, { "mach_msg_option_t", "option" }, { "mach_msg_size_t", "send_size" }, { "mach_msg_size_t", "rcv_size" }, { "mach_port_name_t", "rcv_name" }, { "mach_msg_timeout_t", "timeout" }, { "mach_msg_priority_t", "priority" }, { "mach_msg_header_t *", "rcv_msg" }, { "mach_msg_size_t", "rcv_limit" } } },
{ -33, "semaphore_signal", 1, { { "mach_port_name_t", "signal_name" } } },
{ -34, "semaphore_signal_all", 1, { { "mach_port_name_t", "signal_name" } } },
{ -35, "semaphore_signal_thread", 2, { { "mach_port_name_t", "signal_name" }, { "mach_port_name_t", "thread_name" } } },
{ -36, "semaphore_wait", 1, { { "mach_port_name_t", "wait_name" } } },
{ -37, "semaphore_wait_signal", 2, { { "mach_port_name_t", "wait_name" }, { "mach_port_name_t", "signal_name" } } },
{ -38, "semaphore_timedwait", 3, { { "mach_port_name_t", "wait_name" }, { "unsigned int", "sec" }, { "clock_res_t", "nsec" } } },
{ -39, "semaphore_timedwait_signal", 4, { { "mach_port_name_t", "wait_name" }, { "mach_port_name_t", "signal_name" }, { "unsigned int", "sec" }, { "clock_res_t", "nsec" } } },
{ -40, "mach_port_get_attributes", 5, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_flavor_t", "flavor" }, { "mach_port_info_t", "port_info_out" }, { "mach_msg_type_number_t *", "port_info_out_cnt" } } },
{ -41, "mach_port_guard", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "uint64_t", "guard" }, { "boolean_t", "strict" } } },
{ -42, "mach_port_unguard", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "uint64_t", "guard" } } },
{ -43, "mach_generate_activity_id", 3, { { "mach_port_name_t", "target" }, { "int", "count" }, { "uint64_t *", "activity_id" } } },
{ -44, "task_name_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "tn" } } },
{ -45, "task_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
{ -46, "pid_for_task", 2, { { "mach_port_name_t", "t" }, { "int *", "x" } } },
{ -47, "mach_msg2", 8, { { "void *", "data" }, { "mach_msg_option64_t", "options" }, { "uint64_t", "msgh_bits_and_send_size" }, { "uint64_t", "msgh_remote_and_local_port" }, { "uint64_t", "msgh_voucher_and_id" }, { "uint64_t", "desc_count_and_rcv_name" }, { "uint64_t", "rcv_size_and_priority" }, { "uint64_t", "timeout" } } },
{ -48, "macx_swapon", 4, { { "uint64_t", "filename" }, { "int", "flags" }, { "int", "size" }, { "int", "priority" } } },
{ -49, "macx_swapoff", 2, { { "uint64_t", "filename" }, { "int", "flags" } } },
{ -50, "thread_get_special_reply_port", 0, {} },
{ -51, "macx_triggers", 4, { { "int", "hi_water" }, { "int", "low_water" }, { "int", "flags" }, { "mach_port_t", "alert_port" } } },
{ -52, "macx_backing_store_suspend", 1, { { "boolean_t", "suspend" } } },
{ -53, "macx_backing_store_recovery", 1, { { "int", "pid" } } },
{ -58, "pfz_exit", 0, {} },
{ -59, "swtch_pri", 1, { { "int", "pri" } } },
{ -60, "swtch", 0, {} },
{ -61, "thread_switch", 3, { { "mach_port_name_t", "thread_name" }, { "int", "option" }, { "mach_msg_timeout_t", "option_time" } } },
{ -62, "clock_sleep", 5, { { "mach_port_name_t", "clock_name" }, { "sleep_type_t", "sleep_type" }, { "int", "sleep_sec" }, { "int", "sleep_nsec" }, { "mach_timespec_t *", "wakeup_time" } } },
{ -63, "mach_vm_reclaim_update_kernel_accounting", 2, { { "mach_port_name_t", "target_tport" }, { "uint64_t *", "bytes_reclaimed" } } },
{ -70, "host_create_mach_voucher", 4, { { "mach_port_name_t", "host" }, { "mach_voucher_attr_raw_recipe_array_t", "recipes" }, { "int", "recipes_size" }, { "mach_port_name_t *", "voucher" } } },
{ -72, "mach_voucher_extract_attr_recipe", 4, { { "mach_port_name_t", "voucher_name" }, { "mach_voucher_attr_key_t", "key" }, { "mach_voucher_attr_raw_recipe_t", "recipe" }, { "mach_msg_type_number_t *", "recipe_size" } } },
{ -76, "mach_port_type", 3, { { "ipc_space_t", "task" }, { "mach_port_name_t", "name" }, { "mach_port_type_t *", "ptype" } } },
{ -77, "mach_port_request_notification", 7, { { "ipc_space_t", "task" }, { "mach_port_name_t", "name" }, { "mach_msg_id_t", "msgid" }, { "mach_port_mscount_t", "sync" }, { "mach_port_name_t", "notify" }, { "mach_msg_type_name_t", "notify_poly" }, { "mach_port_name_t *", "previous" } } },
{ -88, "exclaves_ctl", 8, { { "mach_port_name_t", "name" }, { "uint32_t", "operation_and_flags" }, { "uint64_t", "identifier" }, { "mach_vm_address_t", "buffer" }, { "mach_vm_size_t", "size" }, { "mach_vm_size_t", "size2" }, { "mach_vm_size_t", "offset" }, { "mach_vm_address_t", "status" } } },
{ -89, "mach_timebase_info", 1, { { "user_addr_t", "info" } } },
{ -90, "mach_wait_until", 1, { { "uint64_t", "deadline" } } },
{ -91, "mk_timer_create", 0, {} },
{ -92, "mk_timer_destroy", 1, { { "mach_port_name_t", "name" } } },
{ -93, "mk_timer_arm", 2, { { "mach_port_name_t", "name" }, { "uint64_t", "expire_time" } } },
{ -94, "mk_timer_cancel", 2, { { "mach_port_name_t", "name" }, { "user_addr_t", "result_time" } } },
{ -95, "mk_timer_arm_leeway", 4, { { "mach_port_name_t", "name" }, { "uint64_t", "mk_timer_flags" }, { "uint64_t", "expire_time" }, { "uint64_t", "mk_leeway" } } },
{ -96, "debug_control_port_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
{ -100, "iokit_user_client", 8, { { "void *", "userClientRef" }, { "uint32_t", "index" }, { "void *", "p1" }, { "void *", "p2" }, { "void *", "p3" }, { "void *", "p4" }, { "void *", "p5" }, { "void *", "p6" } } },
};
static const FridaXnuSyscallSignature frida_xnu_bsd_syscalls[] =
{
{ 1, "exit", 1, { { "int", "rval" } } },
{ 2, "fork", 0, {} },
{ 3, "read", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
{ 4, "write", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
{ 5, "open", 3, { { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
{ 6, "close", 1, { { "int", "fd" } } },
{ 7, "wait4", 4, { { "int", "pid" }, { "user_addr_t", "status" }, { "int", "options" }, { "user_addr_t", "rusage" } } },
{ 9, "link", 2, { { "char *", "path" }, { "char *", "link" } } },
{ 10, "unlink", 1, { { "char *", "path" } } },
{ 12, "chdir", 1, { { "char *", "path" } } },
{ 13, "fchdir", 1, { { "int", "fd" } } },
{ 14, "mknod", 3, { { "char *", "path" }, { "int", "mode" }, { "int", "dev" } } },
{ 15, "chmod", 2, { { "char *", "path" }, { "int", "mode" } } },
{ 16, "chown", 3, { { "char *", "path" }, { "int", "uid" }, { "int", "gid" } } },
{ 18, "getfsstat", 3, { { "user_addr_t", "buf" }, { "int", "bufsize" }, { "int", "flags" } } },
{ 20, "getpid", 0, {} },
{ 23, "setuid", 1, { { "uid_t", "uid" } } },
{ 24, "getuid", 0, {} },
{ 25, "geteuid", 0, {} },
{ 26, "ptrace", 4, { { "int", "req" }, { "pid_t", "pid" }, { "caddr_t", "addr" }, { "int", "data" } } },
{ 27, "recvmsg", 3, { { "int", "s" }, { "struct msghdr *", "msg" }, { "int", "flags" } } },
{ 28, "sendmsg", 3, { { "int", "s" }, { "caddr_t", "msg" }, { "int", "flags" } } },
{ 29, "recvfrom", 6, { { "int", "s" }, { "void *", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "struct sockaddr *", "from" }, { "int *", "fromlenaddr" } } },
{ 30, "accept", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t *", "anamelen" } } },
{ 31, "getpeername", 3, { { "int", "fdes" }, { "caddr_t", "asa" }, { "socklen_t *", "alen" } } },
{ 32, "getsockname", 3, { { "int", "fdes" }, { "caddr_t", "asa" }, { "socklen_t *", "alen" } } },
{ 33, "access", 2, { { "char *", "path" }, { "int", "flags" } } },
{ 34, "chflags", 2, { { "char *", "path" }, { "int", "flags" } } },
{ 35, "fchflags", 2, { { "int", "fd" }, { "int", "flags" } } },
{ 36, "sync", 0, {} },
{ 37, "kill", 3, { { "int", "pid" }, { "int", "signum" }, { "int", "posix" } } },
{ 38, "crossarch_trap", 1, { { "uint32_t", "name" } } },
{ 39, "getppid", 0, {} },
{ 41, "dup", 1, { { "u_int", "fd" } } },
{ 42, "pipe", 0, {} },
{ 43, "getegid", 0, {} },
{ 46, "sigaction", 3, { { "int", "signum" }, { "struct __sigaction *", "nsa" }, { "struct sigaction *", "osa" } } },
{ 47, "getgid", 0, {} },
{ 48, "sigprocmask", 3, { { "int", "how" }, { "user_addr_t", "mask" }, { "user_addr_t", "omask" } } },
{ 49, "getlogin", 2, { { "char *", "namebuf" }, { "u_int", "namelen" } } },
{ 50, "setlogin", 1, { { "char *", "namebuf" } } },
{ 51, "acct", 1, { { "char *", "path" } } },
{ 52, "sigpending", 1, { { "struct sigvec *", "osv" } } },
{ 53, "sigaltstack", 2, { { "struct sigaltstack *", "nss" }, { "struct sigaltstack *", "oss" } } },
{ 54, "ioctl", 3, { { "int", "fd" }, { "u_long", "com" }, { "caddr_t", "data" } } },
{ 55, "reboot", 2, { { "int", "opt" }, { "char *", "msg" } } },
{ 56, "revoke", 1, { { "char *", "path" } } },
{ 57, "symlink", 2, { { "char *", "path" }, { "char *", "link" } } },
{ 58, "readlink", 3, { { "char *", "path" }, { "char *", "buf" }, { "int", "count" } } },
{ 59, "execve", 3, { { "char *", "fname" }, { "char **", "argp" }, { "char **", "envp" } } },
{ 60, "umask", 1, { { "int", "newmask" } } },
{ 61, "chroot", 1, { { "char *", "path" } } },
{ 65, "msync", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "flags" } } },
{ 66, "vfork", 0, {} },
{ 67, "oslog_coproc_reg", 3, { { "const char *", "uuid" }, { "const char *", "file_path" }, { "size_t", "file_path_len" } } },
{ 68, "oslog_coproc", 7, { { "void *", "buff" }, { "uint64_t", "buff_len" }, { "uint32_t", "type" }, { "const char *", "uuid" }, { "uint64_t", "timestamp" }, { "uint32_t", "offset" }, { "uint32_t", "stream_log" } } },
{ 73, "munmap", 2, { { "caddr_ut", "addr" }, { "size_ut", "len" } } },
{ 74, "mprotect", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "prot" } } },
{ 75, "madvise", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "behav" } } },
{ 78, "mincore", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "user_addr_t", "vec" } } },
{ 79, "getgroups", 2, { { "u_int", "gidsetsize" }, { "gid_t *", "gidset" } } },
{ 80, "setgroups", 2, { { "u_int", "gidsetsize" }, { "gid_t *", "gidset" } } },
{ 81, "getpgrp", 0, {} },
{ 82, "setpgid", 2, { { "int", "pid" }, { "int", "pgid" } } },
{ 83, "setitimer", 3, { { "u_int", "which" }, { "struct itimerval *", "itv" }, { "struct itimerval *", "oitv" } } },
{ 85, "swapon", 0, {} },
{ 86, "getitimer", 2, { { "u_int", "which" }, { "struct itimerval *", "itv" } } },
{ 89, "getdtablesize", 0, {} },
{ 90, "dup2", 2, { { "u_int", "from" }, { "u_int", "to" } } },
{ 92, "fcntl", 3, { { "int", "fd" }, { "int", "cmd" }, { "long", "arg" } } },
{ 93, "select", 5, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "struct timeval *", "tv" } } },
{ 95, "fsync", 1, { { "int", "fd" } } },
{ 96, "setpriority", 3, { { "int", "which" }, { "id_t", "who" }, { "int", "prio" } } },
{ 97, "socket", 3, { { "int", "domain" }, { "int", "type" }, { "int", "protocol" } } },
{ 98, "connect", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t", "namelen" } } },
{ 100, "getpriority", 2, { { "int", "which" }, { "id_t", "who" } } },
{ 104, "bind", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t", "namelen" } } },
{ 105, "setsockopt", 5, { { "int", "s" }, { "int", "level" }, { "int", "name" }, { "caddr_t", "val" }, { "socklen_t", "valsize" } } },
{ 106, "listen", 2, { { "int", "s" }, { "int", "backlog" } } },
{ 111, "sigsuspend", 1, { { "sigset_t", "mask" } } },
{ 116, "gettimeofday", 3, { { "struct timeval *", "tp" }, { "struct timezone *", "tzp" }, { "uint64_t *", "mach_absolute_time" } } },
{ 117, "getrusage", 2, { { "int", "who" }, { "struct rusage *", "rusage" } } },
{ 118, "getsockopt", 5, { { "int", "s" }, { "int", "level" }, { "int", "name" }, { "caddr_t", "val" }, { "socklen_t *", "avalsize" } } },
{ 120, "readv", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
{ 121, "writev", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
{ 122, "settimeofday", 2, { { "struct timeval *", "tv" }, { "struct timezone *", "tzp" } } },
{ 123, "fchown", 3, { { "int", "fd" }, { "int", "uid" }, { "int", "gid" } } },
{ 124, "fchmod", 2, { { "int", "fd" }, { "int", "mode" } } },
{ 126, "setreuid", 2, { { "uid_t", "ruid" }, { "uid_t", "euid" } } },
{ 127, "setregid", 2, { { "gid_t", "rgid" }, { "gid_t", "egid" } } },
{ 128, "rename", 2, { { "char *", "from" }, { "char *", "to" } } },
{ 131, "flock", 2, { { "int", "fd" }, { "int", "how" } } },
{ 132, "mkfifo", 2, { { "char *", "path" }, { "int", "mode" } } },
{ 133, "sendto", 6, { { "int", "s" }, { "caddr_t", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "caddr_t", "to" }, { "socklen_t", "tolen" } } },
{ 134, "shutdown", 2, { { "int", "s" }, { "int", "how" } } },
{ 135, "socketpair", 4, { { "int", "domain" }, { "int", "type" }, { "int", "protocol" }, { "int *", "rsv" } } },
{ 136, "mkdir", 2, { { "char *", "path" }, { "int", "mode" } } },
{ 137, "rmdir", 1, { { "char *", "path" } } },
{ 138, "utimes", 2, { { "char *", "path" }, { "struct timeval *", "tptr" } } },
{ 139, "futimes", 2, { { "int", "fd" }, { "struct timeval *", "tptr" } } },
{ 140, "adjtime", 2, { { "struct timeval *", "delta" }, { "struct timeval *", "olddelta" } } },
{ 142, "gethostuuid", 2, { { "unsigned char *", "uuid_buf" }, { "const struct timespec *", "timeoutp" } } },
{ 147, "setsid", 0, {} },
{ 151, "getpgid", 1, { { "pid_t", "pid" } } },
{ 152, "setprivexec", 1, { { "int", "flag" } } },
{ 153, "pread", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
{ 154, "pwrite", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
{ 155, "nfssvc", 2, { { "int", "flag" }, { "caddr_t", "argp" } } },
{ 157, "statfs", 2, { { "char *", "path" }, { "struct statfs *", "buf" } } },
{ 158, "fstatfs", 2, { { "int", "fd" }, { "struct statfs *", "buf" } } },
{ 159, "unmount", 2, { { "char *", "path" }, { "int", "flags" } } },
{ 161, "getfh", 2, { { "char *", "fname" }, { "fhandle_t *", "fhp" } } },
{ 164, "funmount", 2, { { "int", "fd" }, { "int", "flags" } } },
{ 165, "quotactl", 4, { { "const char *", "path" }, { "int", "cmd" }, { "int", "uid" }, { "caddr_t", "arg" } } },
{ 167, "mount", 4, { { "char *", "type" }, { "char *", "path" }, { "int", "flags" }, { "caddr_t", "data" } } },
{ 169, "csops", 4, { { "pid_t", "pid" }, { "uint32_t", "ops" }, { "user_addr_t", "useraddr" }, { "user_size_t", "usersize" } } },
{ 170, "csops_audittoken", 5, { { "pid_t", "pid" }, { "uint32_t", "ops" }, { "user_addr_t", "useraddr" }, { "user_size_t", "usersize" }, { "user_addr_t", "uaudittoken" } } },
{ 173, "waitid", 4, { { "idtype_t", "idtype" }, { "id_t", "id" }, { "siginfo_t *", "infop" }, { "int", "options" } } },
{ 177, "kdebug_typefilter", 2, { { "void **", "addr" }, { "size_t *", "size" } } },
{ 178, "kdebug_trace_string", 3, { { "uint32_t", "debugid" }, { "uint64_t", "str_id" }, { "const char *", "str" } } },
{ 179, "kdebug_trace64", 5, { { "uint32_t", "code" }, { "uint64_t", "arg1" }, { "uint64_t", "arg2" }, { "uint64_t", "arg3" }, { "uint64_t", "arg4" } } },
{ 180, "kdebug_trace", 5, { { "uint32_t", "code" }, { "u_long", "arg1" }, { "u_long", "arg2" }, { "u_long", "arg3" }, { "u_long", "arg4" } } },
{ 181, "setgid", 1, { { "gid_t", "gid" } } },
{ 182, "setegid", 1, { { "gid_t", "egid" } } },
{ 183, "seteuid", 1, { { "uid_t", "euid" } } },
{ 184, "sigreturn", 3, { { "struct ucontext *", "uctx" }, { "int", "infostyle" }, { "user_addr_t", "token" } } },
{ 185, "panic_with_data", 5, { { "uuid_t", "uuid" }, { "void *", "addr" }, { "uint32_t", "len" }, { "uint32_t", "flags" }, { "const char *", "msg" } } },
{ 186, "thread_selfcounts", 3, { { "uint32_t", "kind" }, { "user_addr_t", "buf" }, { "user_size_t", "size" } } },
{ 187, "fdatasync", 1, { { "int", "fd" } } },
{ 188, "stat", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
{ 189, "fstat", 2, { { "int", "fd" }, { "user_addr_t", "ub" } } },
{ 190, "lstat", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
{ 191, "pathconf", 2, { { "char *", "path" }, { "int", "name" } } },
{ 192, "fpathconf", 2, { { "int", "fd" }, { "int", "name" } } },
{ 194, "getrlimit", 2, { { "u_int", "which" }, { "struct rlimit *", "rlp" } } },
{ 195, "setrlimit", 2, { { "u_int", "which" }, { "struct rlimit *", "rlp" } } },
{ 196, "getdirentries", 4, { { "int", "fd" }, { "char *", "buf" }, { "u_int", "count" }, { "long *", "basep" } } },
{ 197, "mmap", 6, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "prot" }, { "int", "flags" }, { "int", "fd" }, { "off_t", "pos" } } },
{ 199, "lseek", 3, { { "int", "fd" }, { "off_t", "offset" }, { "int", "whence" } } },
{ 200, "truncate", 2, { { "char *", "path" }, { "off_t", "length" } } },
{ 201, "ftruncate", 2, { { "int", "fd" }, { "off_t", "length" } } },
{ 202, "sysctl", 6, { { "int *", "name" }, { "u_int", "namelen" }, { "void *", "old" }, { "size_t *", "oldlenp" }, { "void *", "new" }, { "size_t", "newlen" } } },
{ 203, "mlock", 2, { { "caddr_ut", "addr" }, { "size_ut", "len" } } },
{ 204, "munlock", 2, { { "caddr_ut", "addr" }, { "size_ut", "len" } } },
{ 205, "undelete", 1, { { "char *", "path" } } },
{ 216, "open_dprotected_np", 5, { { "char *", "path" }, { "int", "flags" }, { "int", "class" }, { "int", "dpflags" }, { "int", "mode" } } },
{ 217, "fsgetpath_ext", 5, { { "user_addr_t", "buf" }, { "size_t", "bufsize" }, { "user_addr_t", "fsid" }, { "uint64_t", "objid" }, { "uint32_t", "options" } } },
{ 218, "openat_dprotected_np", 7, { { "int", "fd" }, { "char *", "path" }, { "int", "flags" }, { "int", "class" }, { "int", "dpflags" }, { "int", "mode" }, { "int", "authfd" } } },
{ 220, "getattrlist", 5, { { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
{ 221, "setattrlist", 5, { { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
{ 222, "getdirentriesattr", 8, { { "int", "fd" }, { "struct attrlist *", "alist" }, { "void *", "buffer" }, { "size_t", "buffersize" }, { "u_long *", "count" }, { "u_long *", "basep" }, { "u_long *", "newstate" }, { "u_long", "options" } } },
{ 223, "exchangedata", 3, { { "const char *", "path1" }, { "const char *", "path2" }, { "u_long", "options" } } },
{ 225, "searchfs", 6, { { "const char *", "path" }, { "struct fssearchblock *", "searchblock" }, { "uint32_t *", "nummatches" }, { "uint32_t", "scriptcode" }, { "uint32_t", "options" }, { "struct searchstate *", "state" } } },
{ 226, "delete", 1, { { "char *", "path" } } },
{ 227, "copyfile", 4, { { "char *", "from" }, { "char *", "to" }, { "int", "mode" }, { "int", "flags" } } },
{ 228, "fgetattrlist", 5, { { "int", "fd" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
{ 229, "fsetattrlist", 5, { { "int", "fd" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
{ 230, "poll", 3, { { "struct pollfd *", "fds" }, { "u_int", "nfds" }, { "int", "timeout" } } },
{ 234, "getxattr", 6, { { "char *", "path" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
{ 235, "fgetxattr", 6, { { "int", "fd" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
{ 236, "setxattr", 6, { { "char *", "path" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
{ 237, "fsetxattr", 6, { { "int", "fd" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
{ 238, "removexattr", 3, { { "char *", "path" }, { "char *", "attrname" }, { "int", "options" } } },
{ 239, "fremovexattr", 3, { { "int", "fd" }, { "char *", "attrname" }, { "int", "options" } } },
{ 240, "listxattr", 4, { { "char *", "path" }, { "user_addr_t", "namebuf" }, { "size_t", "bufsize" }, { "int", "options" } } },
{ 241, "flistxattr", 4, { { "int", "fd" }, { "user_addr_t", "namebuf" }, { "size_t", "bufsize" }, { "int", "options" } } },
{ 242, "fsctl", 4, { { "const char *", "path" }, { "u_long", "cmd" }, { "caddr_t", "data" }, { "u_int", "options" } } },
{ 243, "initgroups", 3, { { "u_int", "gidsetsize" }, { "gid_t *", "gidset" }, { "int", "gmuid" } } },
{ 244, "posix_spawn", 5, { { "pid_t *", "pid" }, { "const char *", "path" }, { "const struct _posix_spawn_args_desc *", "adesc" }, { "char **", "argv" }, { "char **", "envp" } } },
{ 245, "ffsctl", 4, { { "int", "fd" }, { "u_long", "cmd" }, { "caddr_t", "data" }, { "u_int", "options" } } },
{ 248, "fhopen", 2, { { "const struct fhandle *", "u_fhp" }, { "int", "flags" } } },
{ 250, "minherit", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "inherit" } } },
{ 251, "semsys", 5, { { "u_int", "which" }, { "int", "a2" }, { "int", "a3" }, { "int", "a4" }, { "int", "a5" } } },
{ 252, "msgsys", 5, { { "u_int", "which" }, { "int", "a2" }, { "int", "a3" }, { "int", "a4" }, { "int", "a5" } } },
{ 253, "shmsys", 4, { { "u_int", "which" }, { "int", "a2" }, { "int", "a3" }, { "int", "a4" } } },
{ 254, "semctl", 4, { { "int", "semid" }, { "int", "semnum" }, { "int", "cmd" }, { "semun_t", "arg" } } },
{ 255, "semget", 3, { { "key_t", "key" }, { "int", "nsems" }, { "int", "semflg" } } },
{ 256, "semop", 3, { { "int", "semid" }, { "struct sembuf *", "sops" }, { "int", "nsops" } } },
{ 258, "msgctl", 3, { { "int", "msqid" }, { "int", "cmd" }, { "struct msqid_ds *", "buf" } } },
{ 259, "msgget", 2, { { "key_t", "key" }, { "int", "msgflg" } } },
{ 260, "msgsnd", 4, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "int", "msgflg" } } },
{ 261, "msgrcv", 5, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "long", "msgtyp" }, { "int", "msgflg" } } },
{ 262, "shmat", 3, { { "int", "shmid" }, { "void *", "shmaddr" }, { "int", "shmflg" } } },
{ 263, "shmctl", 3, { { "int", "shmid" }, { "int", "cmd" }, { "struct shmid_ds *", "buf" } } },
{ 264, "shmdt", 1, { { "void *", "shmaddr" } } },
{ 265, "shmget", 3, { { "key_t", "key" }, { "size_t", "size" }, { "int", "shmflg" } } },
{ 266, "shm_open", 3, { { "const char *", "name" }, { "int", "oflag" }, { "int", "mode" } } },
{ 267, "shm_unlink", 1, { { "const char *", "name" } } },
{ 268, "sem_open", 4, { { "const char *", "name" }, { "int", "oflag" }, { "int", "mode" }, { "int", "value" } } },
{ 269, "sem_close", 1, { { "sem_t *", "sem" } } },
{ 270, "sem_unlink", 1, { { "const char *", "name" } } },
{ 271, "sem_wait", 1, { { "sem_t *", "sem" } } },
{ 272, "sem_trywait", 1, { { "sem_t *", "sem" } } },
{ 273, "sem_post", 1, { { "sem_t *", "sem" } } },
{ 274, "sysctlbyname", 6, { { "const char *", "name" }, { "size_t", "namelen" }, { "void *", "old" }, { "size_t *", "oldlenp" }, { "void *", "new" }, { "size_t", "newlen" } } },
{ 277, "open_extended", 6, { { "char *", "path" }, { "int", "flags" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
{ 278, "umask_extended", 2, { { "int", "newmask" }, { "user_addr_t", "xsecurity" } } },
{ 279, "stat_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 280, "lstat_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 281, "fstat_extended", 4, { { "int", "fd" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 282, "chmod_extended", 5, { { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
{ 283, "fchmod_extended", 5, { { "int", "fd" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
{ 284, "access_extended", 4, { { "user_addr_t", "entries" }, { "size_t", "size" }, { "user_addr_t", "results" }, { "uid_t", "uid" } } },
{ 285, "settid", 2, { { "uid_t", "uid" }, { "gid_t", "gid" } } },
{ 286, "gettid", 2, { { "uid_t *", "uidp" }, { "gid_t *", "gidp" } } },
{ 287, "setsgroups", 2, { { "int", "setlen" }, { "user_addr_t", "guidset" } } },
{ 288, "getsgroups", 2, { { "user_addr_t", "setlen" }, { "user_addr_t", "guidset" } } },
{ 289, "setwgroups", 2, { { "int", "setlen" }, { "user_addr_t", "guidset" } } },
{ 290, "getwgroups", 2, { { "user_addr_t", "setlen" }, { "user_addr_t", "guidset" } } },
{ 291, "mkfifo_extended", 5, { { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
{ 292, "mkdir_extended", 5, { { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
{ 293, "identitysvc", 2, { { "int", "opcode" }, { "user_addr_t", "message" } } },
{ 294, "shared_region_check_np", 1, { { "uint64_t *", "start_address" } } },
{ 296, "vm_pressure_monitor", 3, { { "int", "wait_for_pressure" }, { "int", "nsecs_monitored" }, { "uint32_t *", "pages_reclaimed" } } },
{ 297, "psynch_rw_longrdlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 298, "psynch_rw_yieldwrlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 299, "psynch_rw_downgrade", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 300, "psynch_rw_upgrade", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 301, "psynch_mutexwait", 5, { { "user_addr_t", "mutex" }, { "uint32_t", "mgen" }, { "uint32_t", "ugen" }, { "uint64_t", "tid" }, { "uint32_t", "flags" } } },
{ 302, "psynch_mutexdrop", 5, { { "user_addr_t", "mutex" }, { "uint32_t", "mgen" }, { "uint32_t", "ugen" }, { "uint64_t", "tid" }, { "uint32_t", "flags" } } },
{ 303, "psynch_cvbroad", 7, { { "user_addr_t", "cv" }, { "uint64_t", "cvlsgen" }, { "uint64_t", "cvudgen" }, { "uint32_t", "flags" }, { "user_addr_t", "mutex" }, { "uint64_t", "mugen" }, { "uint64_t", "tid" } } },
{ 304, "psynch_cvsignal", 8, { { "user_addr_t", "cv" }, { "uint64_t", "cvlsgen" }, { "uint32_t", "cvugen" }, { "int", "thread_port" }, { "user_addr_t", "mutex" }, { "uint64_t", "mugen" }, { "uint64_t", "tid" }, { "uint32_t", "flags" } } },
{ 305, "psynch_cvwait", 8, { { "user_addr_t", "cv" }, { "uint64_t", "cvlsgen" }, { "uint32_t", "cvugen" }, { "user_addr_t", "mutex" }, { "uint64_t", "mugen" }, { "uint32_t", "flags" }, { "int64_t", "sec" }, { "uint32_t", "nsec" } } },
{ 306, "psynch_rw_rdlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 307, "psynch_rw_wrlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 308, "psynch_rw_unlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 309, "psynch_rw_unlock2", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 310, "getsid", 1, { { "pid_t", "pid" } } },
{ 311, "settid_with_pid", 2, { { "pid_t", "pid" }, { "int", "assume" } } },
{ 312, "psynch_cvclrprepost", 7, { { "user_addr_t", "cv" }, { "uint32_t", "cvgen" }, { "uint32_t", "cvugen" }, { "uint32_t", "cvsgen" }, { "uint32_t", "prepocnt" }, { "uint32_t", "preposeq" }, { "uint32_t", "flags" } } },
{ 313, "aio_fsync", 2, { { "int", "op" }, { "user_addr_t", "aiocbp" } } },
{ 314, "aio_return", 1, { { "user_addr_t", "aiocbp" } } },
{ 315, "aio_suspend", 3, { { "user_addr_t", "aiocblist" }, { "int", "nent" }, { "user_addr_t", "timeoutp" } } },
{ 316, "aio_cancel", 2, { { "int", "fd" }, { "user_addr_t", "aiocbp" } } },
{ 317, "aio_error", 1, { { "user_addr_t", "aiocbp" } } },
{ 318, "aio_read", 1, { { "user_addr_t", "aiocbp" } } },
{ 319, "aio_write", 1, { { "user_addr_t", "aiocbp" } } },
{ 320, "lio_listio", 4, { { "int", "mode" }, { "user_addr_t", "aiocblist" }, { "int", "nent" }, { "user_addr_t", "sigp" } } },
{ 322, "iopolicysys", 2, { { "int", "cmd" }, { "void *", "arg" } } },
{ 323, "process_policy", 7, { { "int", "scope" }, { "int", "action" }, { "int", "policy" }, { "int", "policy_subtype" }, { "user_addr_t", "attrp" }, { "pid_t", "target_pid" }, { "uint64_t", "target_threadid" } } },
{ 324, "mlockall", 1, { { "int", "how" } } },
{ 325, "munlockall", 1, { { "int", "how" } } },
{ 327, "issetugid", 0, {} },
{ 328, "pthread_kill", 2, { { "int", "thread_port" }, { "int", "sig" } } },
{ 329, "pthread_sigmask", 3, { { "int", "how" }, { "user_addr_t", "set" }, { "user_addr_t", "oset" } } },
{ 330, "sigwait", 2, { { "user_addr_t", "set" }, { "user_addr_t", "sig" } } },
{ 331, "disable_threadsignal", 1, { { "int", "value" } } },
{ 332, "pthread_markcancel", 1, { { "int", "thread_port" } } },
{ 333, "pthread_canceled", 1, { { "int", "action" } } },
{ 334, "semwait_signal", 6, { { "int", "cond_sem" }, { "int", "mutex_sem" }, { "int", "timeout" }, { "int", "relative" }, { "int64_t", "tv_sec" }, { "int32_t", "tv_nsec" } } },
{ 336, "proc_info", 6, { { "int32_t", "callnum" }, { "int32_t", "pid" }, { "uint32_t", "flavor" }, { "uint64_t", "arg" }, { "user_addr_t", "buffer" }, { "int32_t", "buffersize" } } },
{ 337, "sendfile", 6, { { "int", "fd" }, { "int", "s" }, { "off_t", "offset" }, { "off_t *", "nbytes" }, { "struct sf_hdtr *", "hdtr" }, { "int", "flags" } } },
{ 338, "stat64", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
{ 339, "fstat64", 2, { { "int", "fd" }, { "user_addr_t", "ub" } } },
{ 340, "lstat64", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
{ 341, "stat64_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 342, "lstat64_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 343, "fstat64_extended", 4, { { "int", "fd" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 344, "getdirentries64", 4, { { "int", "fd" }, { "void *", "buf" }, { "user_size_t", "bufsize" }, { "off_t *", "position" } } },
{ 345, "statfs64", 2, { { "char *", "path" }, { "struct statfs64 *", "buf" } } },
{ 346, "fstatfs64", 2, { { "int", "fd" }, { "struct statfs64 *", "buf" } } },
{ 347, "getfsstat64", 3, { { "user_addr_t", "buf" }, { "int", "bufsize" }, { "int", "flags" } } },
{ 348, "pthread_chdir", 1, { { "char *", "path" } } },
{ 349, "pthread_fchdir", 1, { { "int", "fd" } } },
{ 350, "audit", 2, { { "void *", "record" }, { "int", "length" } } },
{ 351, "auditon", 3, { { "int", "cmd" }, { "void *", "data" }, { "int", "length" } } },
{ 353, "getauid", 1, { { "au_id_t *", "auid" } } },
{ 354, "setauid", 1, { { "au_id_t *", "auid" } } },
{ 357, "getaudit_addr", 2, { { "struct auditinfo_addr *", "auditinfo_addr" }, { "int", "length" } } },
{ 358, "setaudit_addr", 2, { { "struct auditinfo_addr *", "auditinfo_addr" }, { "int", "length" } } },
{ 359, "auditctl", 1, { { "char *", "path" } } },
{ 360, "bsdthread_create", 5, { { "user_addr_t", "func" }, { "user_addr_t", "func_arg" }, { "user_addr_t", "stack" }, { "user_addr_t", "pthread" }, { "uint32_t", "flags" } } },
{ 361, "bsdthread_terminate", 4, { { "user_addr_t", "stackaddr" }, { "size_t", "freesize" }, { "uint32_t", "port" }, { "user_addr_t", "sema_or_ulock" } } },
{ 362, "kqueue", 0, {} },
{ 363, "kevent", 6, { { "int", "fd" }, { "const struct kevent *", "changelist" }, { "int", "nchanges" }, { "struct kevent *", "eventlist" }, { "int", "nevents" }, { "const struct timespec *", "timeout" } } },
{ 364, "lchown", 3, { { "char *", "path" }, { "uid_t", "owner" }, { "gid_t", "group" } } },
{ 366, "bsdthread_register", 7, { { "user_addr_t", "threadstart" }, { "user_addr_t", "wqthread" }, { "uint32_t", "flags" }, { "user_addr_t", "stack_addr_hint" }, { "user_addr_t", "targetconc_ptr" }, { "uint32_t", "dispatchqueue_offset" }, { "uint32_t", "tsd_offset" } } },
{ 367, "workq_open", 0, {} },
{ 368, "workq_kernreturn", 4, { { "int", "options" }, { "user_addr_t", "item" }, { "int", "affinity" }, { "int", "prio" } } },
{ 369, "kevent64", 7, { { "int", "fd" }, { "const struct kevent64_s *", "changelist" }, { "int", "nchanges" }, { "struct kevent64_s *", "eventlist" }, { "int", "nevents" }, { "unsigned int", "flags" }, { "const struct timespec *", "timeout" } } },
{ 372, "thread_selfid", 0, {} },
{ 373, "ledger", 4, { { "int", "cmd" }, { "caddr_t", "arg1" }, { "caddr_t", "arg2" }, { "caddr_t", "arg3" } } },
{ 374, "kevent_qos", 8, { { "int", "fd" }, { "const struct kevent_qos_s *", "changelist" }, { "int", "nchanges" }, { "struct kevent_qos_s *", "eventlist" }, { "int", "nevents" }, { "void *", "data_out" }, { "size_t *", "data_available" }, { "unsigned int", "flags" } } },
{ 375, "kevent_id", 8, { { "uint64_t", "id" }, { "const struct kevent_qos_s *", "changelist" }, { "int", "nchanges" }, { "struct kevent_qos_s *", "eventlist" }, { "int", "nevents" }, { "void *", "data_out" }, { "size_t *", "data_available" }, { "unsigned int", "flags" } } },
{ 380, "mac_execve", 4, { { "char *", "fname" }, { "char **", "argp" }, { "char **", "envp" }, { "struct mac *", "mac_p" } } },
{ 381, "mac_syscall", 3, { { "char *", "policy" }, { "int", "call" }, { "user_addr_t", "arg" } } },
{ 382, "mac_get_file", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
{ 383, "mac_set_file", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
{ 384, "mac_get_link", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
{ 385, "mac_set_link", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
{ 386, "mac_get_proc", 1, { { "struct mac *", "mac_p" } } },
{ 387, "mac_set_proc", 1, { { "struct mac *", "mac_p" } } },
{ 388, "mac_get_fd", 2, { { "int", "fd" }, { "struct mac *", "mac_p" } } },
{ 389, "mac_set_fd", 2, { { "int", "fd" }, { "struct mac *", "mac_p" } } },
{ 390, "mac_get_pid", 2, { { "pid_t", "pid" }, { "struct mac *", "mac_p" } } },
{ 394, "pselect", 6, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "const struct timespec *", "ts" }, { "const struct sigset_t *", "mask" } } },
{ 395, "pselect_nocancel", 6, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "const struct timespec *", "ts" }, { "const struct sigset_t *", "mask" } } },
{ 396, "read_nocancel", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
{ 397, "write_nocancel", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
{ 398, "open_nocancel", 3, { { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
{ 399, "close_nocancel", 1, { { "int", "fd" } } },
{ 400, "wait4_nocancel", 4, { { "int", "pid" }, { "user_addr_t", "status" }, { "int", "options" }, { "user_addr_t", "rusage" } } },
{ 401, "recvmsg_nocancel", 3, { { "int", "s" }, { "struct msghdr *", "msg" }, { "int", "flags" } } },
{ 402, "sendmsg_nocancel", 3, { { "int", "s" }, { "caddr_t", "msg" }, { "int", "flags" } } },
{ 403, "recvfrom_nocancel", 6, { { "int", "s" }, { "void *", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "struct sockaddr *", "from" }, { "int *", "fromlenaddr" } } },
{ 404, "accept_nocancel", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t *", "anamelen" } } },
{ 405, "msync_nocancel", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "flags" } } },
{ 406, "fcntl_nocancel", 3, { { "int", "fd" }, { "int", "cmd" }, { "long", "arg" } } },
{ 407, "select_nocancel", 5, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "struct timeval *", "tv" } } },
{ 408, "fsync_nocancel", 1, { { "int", "fd" } } },
{ 409, "connect_nocancel", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t", "namelen" } } },
{ 410, "sigsuspend_nocancel", 1, { { "sigset_t", "mask" } } },
{ 411, "readv_nocancel", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
{ 412, "writev_nocancel", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
{ 413, "sendto_nocancel", 6, { { "int", "s" }, { "caddr_t", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "caddr_t", "to" }, { "socklen_t", "tolen" } } },
{ 414, "pread_nocancel", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
{ 415, "pwrite_nocancel", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
{ 416, "waitid_nocancel", 4, { { "idtype_t", "idtype" }, { "id_t", "id" }, { "siginfo_t *", "infop" }, { "int", "options" } } },
{ 417, "poll_nocancel", 3, { { "struct pollfd *", "fds" }, { "u_int", "nfds" }, { "int", "timeout" } } },
{ 418, "msgsnd_nocancel", 4, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "int", "msgflg" } } },
{ 419, "msgrcv_nocancel", 5, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "long", "msgtyp" }, { "int", "msgflg" } } },
{ 420, "sem_wait_nocancel", 1, { { "sem_t *", "sem" } } },
{ 421, "aio_suspend_nocancel", 3, { { "user_addr_t", "aiocblist" }, { "int", "nent" }, { "user_addr_t", "timeoutp" } } },
{ 422, "sigwait_nocancel", 2, { { "user_addr_t", "set" }, { "user_addr_t", "sig" } } },
{ 423, "semwait_signal_nocancel", 6, { { "int", "cond_sem" }, { "int", "mutex_sem" }, { "int", "timeout" }, { "int", "relative" }, { "int64_t", "tv_sec" }, { "int32_t", "tv_nsec" } } },
{ 424, "mac_mount", 5, { { "char *", "type" }, { "char *", "path" }, { "int", "flags" }, { "caddr_t", "data" }, { "struct mac *", "mac_p" } } },
{ 425, "mac_get_mount", 2, { { "char *", "path" }, { "struct mac *", "mac_p" } } },
{ 426, "mac_getfsstat", 5, { { "user_addr_t", "buf" }, { "int", "bufsize" }, { "user_addr_t", "mac" }, { "int", "macsize" }, { "int", "flags" } } },
{ 427, "fsgetpath", 4, { { "user_addr_t", "buf" }, { "size_t", "bufsize" }, { "user_addr_t", "fsid" }, { "uint64_t", "objid" } } },
{ 428, "audit_session_self", 0, {} },
{ 429, "audit_session_join", 1, { { "mach_port_name_t", "port" } } },
{ 430, "fileport_makeport", 2, { { "int", "fd" }, { "user_addr_t", "portnamep" } } },
{ 431, "fileport_makefd", 1, { { "mach_port_name_t", "port" } } },
{ 432, "audit_session_port", 2, { { "au_asid_t", "asid" }, { "user_addr_t", "portnamep" } } },
{ 433, "pid_suspend", 1, { { "int", "pid" } } },
{ 434, "pid_resume", 1, { { "int", "pid" } } },
{ 435, "pid_hibernate", 1, { { "int", "pid" } } },
{ 436, "pid_shutdown_sockets", 2, { { "int", "pid" }, { "int", "level" } } },
{ 439, "kas_info", 3, { { "int", "selector" }, { "void *", "value" }, { "size_t *", "size" } } },
{ 440, "memorystatus_control", 5, { { "uint32_t", "command" }, { "int32_t", "pid" }, { "uint32_t", "flags" }, { "user_addr_t", "buffer" }, { "size_t", "buffersize" } } },
{ 441, "guarded_open_np", 5, { { "char *", "path" }, { "const guardid_t *", "guard" }, { "u_int", "guardflags" }, { "int", "flags" }, { "int", "mode" } } },
{ 442, "guarded_close_np", 2, { { "int", "fd" }, { "const guardid_t *", "guard" } } },
{ 443, "guarded_kqueue_np", 2, { { "const guardid_t *", "guard" }, { "u_int", "guardflags" } } },
{ 444, "change_fdguard_np", 6, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "u_int", "guardflags" }, { "const guardid_t *", "nguard" }, { "u_int", "nguardflags" }, { "int *", "fdflagsp" } } },
{ 445, "usrctl", 1, { { "uint32_t", "flags" } } },
{ 446, "proc_rlimit_control", 3, { { "pid_t", "pid" }, { "int", "flavor" }, { "void *", "arg" } } },
{ 447, "connectx", 8, { { "int", "socket" }, { "const sa_endpoints_t *", "endpoints" }, { "sae_associd_t", "associd" }, { "unsigned int", "flags" }, { "const struct iovec *", "iov" }, { "unsigned int", "iovcnt" }, { "size_t *", "len" }, { "sae_connid_t *", "connid" } } },
{ 448, "disconnectx", 3, { { "int", "s" }, { "sae_associd_t", "aid" }, { "sae_connid_t", "cid" } } },
{ 449, "peeloff", 2, { { "int", "s" }, { "sae_associd_t", "aid" } } },
{ 450, "socket_delegate", 4, { { "int", "domain" }, { "int", "type" }, { "int", "protocol" }, { "pid_t", "epid" } } },
{ 451, "telemetry", 6, { { "uint64_t", "cmd" }, { "uint64_t", "deadline" }, { "uint64_t", "interval" }, { "uint64_t", "leeway" }, { "uint64_t", "arg4" }, { "uint64_t", "arg5" } } },
{ 452, "proc_uuid_policy", 4, { { "uint32_t", "operation" }, { "uuid_t", "uuid" }, { "size_t", "uuidlen" }, { "uint32_t", "flags" } } },
{ 453, "memorystatus_get_level", 1, { { "user_addr_t", "level" } } },
{ 454, "system_override", 2, { { "uint64_t", "timeout" }, { "uint64_t", "flags" } } },
{ 455, "vfs_purge", 0, {} },
{ 456, "sfi_ctl", 4, { { "uint32_t", "operation" }, { "uint32_t", "sfi_class" }, { "uint64_t", "time" }, { "uint64_t *", "out_time" } } },
{ 457, "sfi_pidctl", 4, { { "uint32_t", "operation" }, { "pid_t", "pid" }, { "uint32_t", "sfi_flags" }, { "uint32_t *", "out_sfi_flags" } } },
{ 458, "coalition", 3, { { "uint32_t", "operation" }, { "uint64_t *", "cid" }, { "uint32_t", "flags" } } },
{ 459, "coalition_info", 4, { { "uint32_t", "flavor" }, { "uint64_t *", "cid" }, { "void *", "buffer" }, { "size_t *", "bufsize" } } },
{ 460, "necp_match_policy", 3, { { "uint8_t *", "parameters" }, { "size_t", "parameters_size" }, { "struct necp_aggregate_result *", "returned_result" } } },
{ 461, "getattrlistbulk", 5, { { "int", "dirfd" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "uint64_t", "options" } } },
{ 462, "clonefileat", 5, { { "int", "src_dirfd" }, { "user_addr_t", "src" }, { "int", "dst_dirfd" }, { "user_addr_t", "dst" }, { "uint32_t", "flags" } } },
{ 463, "openat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
{ 464, "openat_nocancel", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
{ 465, "renameat", 4, { { "int", "fromfd" }, { "char *", "from" }, { "int", "tofd" }, { "char *", "to" } } },
{ 466, "faccessat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "amode" }, { "int", "flag" } } },
{ 467, "fchmodat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" }, { "int", "flag" } } },
{ 468, "fchownat", 5, { { "int", "fd" }, { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "flag" } } },
{ 469, "fstatat", 4, { { "int", "fd" }, { "char *", "path" }, { "user_addr_t", "ub" }, { "int", "flag" } } },
{ 470, "fstatat64", 4, { { "int", "fd" }, { "char *", "path" }, { "user_addr_t", "ub" }, { "int", "flag" } } },
{ 471, "linkat", 5, { { "int", "fd1" }, { "char *", "path" }, { "int", "fd2" }, { "char *", "link" }, { "int", "flag" } } },
{ 472, "unlinkat", 3, { { "int", "fd" }, { "char *", "path" }, { "int", "flag" } } },
{ 473, "readlinkat", 4, { { "int", "fd" }, { "char *", "path" }, { "user_addr_t", "buf" }, { "size_t", "bufsize" } } },
{ 474, "symlinkat", 3, { { "user_addr_t *", "path1" }, { "int", "fd" }, { "user_addr_t", "path2" } } },
{ 475, "mkdirat", 3, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" } } },
{ 476, "getattrlistat", 6, { { "int", "fd" }, { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
{ 477, "proc_trace_log", 2, { { "pid_t", "pid" }, { "uint64_t", "uniqueid" } } },
{ 478, "bsdthread_ctl", 4, { { "user_addr_t", "cmd" }, { "user_addr_t", "arg1" }, { "user_addr_t", "arg2" }, { "user_addr_t", "arg3" } } },
{ 479, "openbyid_np", 3, { { "user_addr_t", "fsid" }, { "user_addr_t", "objid" }, { "int", "oflags" } } },
{ 480, "recvmsg_x", 4, { { "int", "s" }, { "struct msghdr_x *", "msgp" }, { "u_int", "cnt" }, { "int", "flags" } } },
{ 481, "sendmsg_x", 4, { { "int", "s" }, { "struct msghdr_x *", "msgp" }, { "u_int", "cnt" }, { "int", "flags" } } },
{ 482, "thread_selfusage", 0, {} },
{ 483, "csrctl", 3, { { "uint32_t", "op" }, { "user_addr_t", "useraddr" }, { "user_addr_t", "usersize" } } },
{ 484, "guarded_open_dprotected_np", 7, { { "char *", "path" }, { "const guardid_t *", "guard" }, { "u_int", "guardflags" }, { "int", "flags" }, { "int", "dpclass" }, { "int", "dpflags" }, { "int", "mode" } } },
{ 485, "guarded_write_np", 4, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
{ 486, "guarded_pwrite_np", 5, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
{ 487, "guarded_writev_np", 4, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" } } },
{ 488, "renameatx_np", 5, { { "int", "fromfd" }, { "char *", "from" }, { "int", "tofd" }, { "char *", "to" }, { "u_int", "flags" } } },
{ 489, "mremap_encrypted", 5, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "uint32_t", "cryptid" }, { "uint32_t", "cputype" }, { "uint32_t", "cpusubtype" } } },
{ 490, "netagent_trigger", 2, { { "uuid_t", "agent_uuid" }, { "size_t", "agent_uuidlen" } } },
{ 491, "stack_snapshot_with_config", 3, { { "int", "stackshot_config_version" }, { "user_addr_t", "stackshot_config" }, { "size_t", "stackshot_config_size" } } },
{ 492, "microstackshot", 3, { { "user_addr_t", "tracebuf" }, { "uint32_t", "tracebuf_size" }, { "uint32_t", "flags" } } },
{ 493, "grab_pgo_data", 4, { { "user_addr_t", "uuid" }, { "int", "flags" }, { "user_addr_t", "buffer" }, { "user_ssize_t", "size" } } },
{ 494, "persona", 6, { { "uint32_t", "operation" }, { "uint32_t", "flags" }, { "struct kpersona_info *", "info" }, { "uid_t *", "id" }, { "size_t *", "idlen" }, { "char *", "path" } } },
{ 496, "mach_eventlink_signal", 2, { { "mach_port_name_t", "eventlink_port" }, { "uint64_t", "signal_count" } } },
{ 497, "mach_eventlink_wait_until", 5, { { "mach_port_name_t", "eventlink_port" }, { "uint64_t", "wait_count" }, { "uint64_t", "deadline" }, { "uint32_t", "clock_id" }, { "uint32_t", "option" } } },
{ 498, "mach_eventlink_signal_wait_until", 6, { { "mach_port_name_t", "eventlink_port" }, { "uint64_t", "wait_count" }, { "uint64_t", "signal_count" }, { "uint64_t", "deadline" }, { "uint32_t", "clock_id" }, { "uint32_t", "option" } } },
{ 499, "work_interval_ctl", 4, { { "uint32_t", "operation" }, { "uint64_t", "work_interval_id" }, { "void *", "arg" }, { "size_t", "len" } } },
{ 500, "getentropy", 2, { { "void *", "buffer" }, { "size_t", "size" } } },
{ 502, "necp_client_action", 6, { { "int", "necp_fd" }, { "uint32_t", "action" }, { "uuid_t", "client_id" }, { "size_t", "client_id_len" }, { "uint8_t *", "buffer" }, { "size_t", "buffer_size" } } },
{ 503, "nexus_open", 2, { { "struct nxctl_init *", "init" }, { "uint32_t", "init_len" } } },
{ 504, "nexus_register", 5, { { "int", "ctl" }, { "struct nxprov_reg *", "reg" }, { "uint32_t", "reg_len" }, { "uuid_t *", "prov_uuid" }, { "uint32_t", "prov_uuid_len" } } },
{ 505, "nexus_deregister", 3, { { "int", "ctl" }, { "uuid_t", "prov_uuid" }, { "uint32_t", "prov_uuid_len" } } },
{ 506, "nexus_create", 5, { { "int", "ctl" }, { "uuid_t", "prov_uuid" }, { "uint32_t", "prov_uuid_len" }, { "uuid_t *", "nx_uuid" }, { "uint32_t", "nx_uuid_len" } } },
{ 507, "nexus_destroy", 3, { { "int", "ctl" }, { "uuid_t", "nx_uuid" }, { "uint32_t", "nx_uuid_len" } } },
{ 508, "nexus_get_opt", 4, { { "int", "ctl" }, { "uint32_t", "opt" }, { "void *", "aoptval" }, { "uint32_t *", "aoptlen" } } },
{ 509, "nexus_set_opt", 4, { { "int", "ctl" }, { "uint32_t", "opt" }, { "const void *", "aoptval" }, { "uint32_t", "optlen" } } },
{ 510, "channel_open", 2, { { "struct ch_init *", "init" }, { "uint32_t", "init_len" } } },
{ 511, "channel_get_info", 3, { { "int", "c" }, { "struct ch_info *", "cinfo" }, { "uint32_t", "cinfolen" } } },
{ 512, "channel_sync", 3, { { "int", "c" }, { "int", "mode" }, { "int", "flags" } } },
{ 513, "channel_get_opt", 4, { { "int", "c" }, { "uint32_t", "opt" }, { "void *", "aoptval" }, { "uint32_t *", "aoptlen" } } },
{ 514, "channel_set_opt", 4, { { "int", "c" }, { "uint32_t", "opt" }, { "const void *", "aoptval" }, { "uint32_t", "optlen" } } },
{ 515, "ulock_wait", 4, { { "uint32_t", "operation" }, { "void *", "addr" }, { "uint64_t", "value" }, { "uint32_t", "timeout" } } },
{ 516, "ulock_wake", 3, { { "uint32_t", "operation" }, { "void *", "addr" }, { "uint64_t", "wake_value" } } },
{ 517, "fclonefileat", 4, { { "int", "src_fd" }, { "int", "dst_dirfd" }, { "user_addr_t", "dst" }, { "uint32_t", "flags" } } },
{ 518, "fs_snapshot", 6, { { "uint32_t", "op" }, { "int", "dirfd" }, { "user_addr_t", "name1" }, { "user_addr_t", "name2" }, { "user_addr_t", "data" }, { "uint32_t", "flags" } } },
{ 520, "terminate_with_payload", 7, { { "int", "pid" }, { "uint32_t", "reason_namespace" }, { "uint64_t", "reason_code" }, { "void *", "payload" }, { "uint32_t", "payload_size" }, { "const char *", "reason_string" }, { "uint64_t", "reason_flags" } } },
{ 521, "abort_with_payload", 6, { { "uint32_t", "reason_namespace" }, { "uint64_t", "reason_code" }, { "void *", "payload" }, { "uint32_t", "payload_size" }, { "const char *", "reason_string" }, { "uint64_t", "reason_flags" } } },
{ 523, "necp_session_action", 6, { { "int", "necp_fd" }, { "uint32_t", "action" }, { "uint8_t *", "in_buffer" }, { "size_t", "in_buffer_length" }, { "uint8_t *", "out_buffer" }, { "size_t", "out_buffer_length" } } },
{ 524, "setattrlistat", 6, { { "int", "fd" }, { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "uint32_t", "options" } } },
{ 525, "net_qos_guideline", 2, { { "struct net_qos_param *", "param" }, { "uint32_t", "param_len" } } },
{ 526, "fmount", 4, { { "const char *", "type" }, { "int", "fd" }, { "int", "flags" }, { "void *", "data" } } },
{ 527, "ntp_adjtime", 1, { { "struct timex *", "tp" } } },
{ 528, "ntp_gettime", 1, { { "struct ntptimeval *", "ntvp" } } },
{ 529, "os_fault_with_payload", 6, { { "uint32_t", "reason_namespace" }, { "uint64_t", "reason_code" }, { "void *", "payload" }, { "uint32_t", "payload_size" }, { "const char *", "reason_string" }, { "uint64_t", "reason_flags" } } },
{ 530, "kqueue_workloop_ctl", 4, { { "user_addr_t", "cmd" }, { "uint64_t", "options" }, { "user_addr_t", "addr" }, { "size_t", "sz" } } },
{ 531, "mach_bridge_remote_time", 1, { { "uint64_t", "local_timestamp" } } },
{ 532, "coalition_ledger", 4, { { "uint32_t", "operation" }, { "uint64_t *", "cid" }, { "void *", "buffer" }, { "size_t *", "bufsize" } } },
{ 533, "log_data", 4, { { "unsigned int", "tag" }, { "unsigned int", "flags" }, { "void *", "buffer" }, { "unsigned int", "size" } } },
{ 534, "memorystatus_available_memory", 0, {} },
{ 535, "objc_bp_assist_cfg_np", 2, { { "uint64_t", "adr" }, { "uint64_t", "ctl" } } },
{ 536, "shared_region_map_and_slide_2_np", 4, { { "uint32_t", "files_count" }, { "const struct shared_file_np *", "files" }, { "uint32_t", "mappings_count" }, { "const shared_file_mapping_slide_np_ut *", "mappings_u" } } },
{ 537, "pivot_root", 2, { { "const char *", "new_rootfs_path_before" }, { "const char *", "old_rootfs_path_after" } } },
{ 538, "task_inspect_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
{ 539, "task_read_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
{ 540, "preadv", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
{ 541, "pwritev", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
{ 542, "preadv_nocancel", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
{ 543, "pwritev_nocancel", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
{ 544, "ulock_wait2", 5, { { "uint32_t", "operation" }, { "void *", "addr" }, { "uint64_t", "value" }, { "uint64_t", "timeout" }, { "uint64_t", "value2" } } },
{ 545, "proc_info_extended_id", 8, { { "int32_t", "callnum" }, { "int32_t", "pid" }, { "uint32_t", "flavor" }, { "uint32_t", "flags" }, { "uint64_t", "ext_id" }, { "uint64_t", "arg" }, { "user_addr_t", "buffer" }, { "int32_t", "buffersize" } } },
{ 546, "tracker_action", 3, { { "int", "action" }, { "char *", "buffer" }, { "size_t", "buffer_size" } } },
{ 547, "debug_syscall_reject", 1, { { "uint64_t", "packed_selectors" } } },
{ 548, "debug_syscall_reject_config", 3, { { "uint64_t", "packed_selectors1" }, { "uint64_t", "packed_selectors2" }, { "uint64_t", "flags" } } },
{ 549, "graftdmg", 4, { { "int", "dmg_fd" }, { "const char *", "mountdir" }, { "uint32_t", "graft_type" }, { "graftdmg_args_un *", "gda" } } },
{ 550, "map_with_linking_np", 4, { { "void *", "regions" }, { "uint32_t", "region_count" }, { "void *", "link_info" }, { "uint32_t", "link_info_size" } } },
{ 551, "freadlink", 3, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "bufsize" } } },
{ 552, "record_system_event", 4, { { "uint32_t", "type" }, { "uint32_t", "subsystem" }, { "const char *", "event" }, { "const char *", "payload" } } },
{ 553, "mkfifoat", 3, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" } } },
{ 554, "mknodat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" }, { "int", "dev" } } },
{ 555, "ungraftdmg", 2, { { "const char *", "mountdir" }, { "uint64_t", "flags" } } },
{ 556, "coalition_policy_set", 3, { { "uint64_t", "cid" }, { "uint32_t", "flavor" }, { "uint32_t", "value" } } },
{ 557, "coalition_policy_get", 2, { { "uint64_t", "cid" }, { "uint32_t", "flavor" } } },
};
FridaXnuSyscallSignature *
frida_get_xnu_mach_traps (int * len)
{
if (len != NULL)
*len = G_N_ELEMENTS (frida_xnu_mach_traps);
return (FridaXnuSyscallSignature *) frida_xnu_mach_traps;
}
FridaXnuSyscallSignature *
frida_get_xnu_bsd_syscalls (int * len)
{
if (len != NULL)
*len = G_N_ELEMENTS (frida_xnu_bsd_syscalls);
return (FridaXnuSyscallSignature *) frida_xnu_bsd_syscalls;
}
-539
View File
@@ -1,539 +0,0 @@
// AUTO-GENERATED FILE. DO NOT EDIT.
namespace Frida {
public extern unowned XnuSyscallSignature[] get_xnu_mach_traps ();
public extern unowned XnuSyscallSignature[] get_xnu_bsd_syscalls ();
public struct XnuSyscallSignature {
public int nr;
public string name;
public uint8 nargs;
public XnuSyscallArg args[9];
}
public struct XnuSyscallArg {
public string? type;
public string? name;
}
public enum XnuMachTrap {
MACH_VM_ALLOCATE = -10,
MACH_VM_PURGABLE_CONTROL = -11,
MACH_VM_DEALLOCATE = -12,
TASK_DYLD_PROCESS_INFO_NOTIFY_GET = -13,
MACH_VM_PROTECT = -14,
MACH_VM_MAP = -15,
MACH_PORT_ALLOCATE = -16,
MACH_PORT_DEALLOCATE = -18,
MACH_PORT_MOD_REFS = -19,
MACH_PORT_MOVE_MEMBER = -20,
MACH_PORT_INSERT_RIGHT = -21,
MACH_PORT_INSERT_MEMBER = -22,
MACH_PORT_EXTRACT_MEMBER = -23,
MACH_PORT_CONSTRUCT = -24,
MACH_PORT_DESTRUCT = -25,
MACH_REPLY_PORT = -26,
THREAD_SELF = -27,
TASK_SELF = -28,
HOST_SELF = -29,
MACH_MSG = -31,
MACH_MSG_OVERWRITE = -32,
SEMAPHORE_SIGNAL = -33,
SEMAPHORE_SIGNAL_ALL = -34,
SEMAPHORE_SIGNAL_THREAD = -35,
SEMAPHORE_WAIT = -36,
SEMAPHORE_WAIT_SIGNAL = -37,
SEMAPHORE_TIMEDWAIT = -38,
SEMAPHORE_TIMEDWAIT_SIGNAL = -39,
MACH_PORT_GET_ATTRIBUTES = -40,
MACH_PORT_GUARD = -41,
MACH_PORT_UNGUARD = -42,
MACH_GENERATE_ACTIVITY_ID = -43,
TASK_NAME_FOR_PID = -44,
TASK_FOR_PID = -45,
PID_FOR_TASK = -46,
MACH_MSG2 = -47,
MACX_SWAPON = -48,
MACX_SWAPOFF = -49,
THREAD_GET_SPECIAL_REPLY_PORT = -50,
MACX_TRIGGERS = -51,
MACX_BACKING_STORE_SUSPEND = -52,
MACX_BACKING_STORE_RECOVERY = -53,
PFZ_EXIT = -58,
SWTCH_PRI = -59,
SWTCH = -60,
THREAD_SWITCH = -61,
CLOCK_SLEEP = -62,
MACH_VM_RECLAIM_UPDATE_KERNEL_ACCOUNTING = -63,
HOST_CREATE_MACH_VOUCHER = -70,
MACH_VOUCHER_EXTRACT_ATTR_RECIPE = -72,
MACH_PORT_TYPE = -76,
MACH_PORT_REQUEST_NOTIFICATION = -77,
EXCLAVES_CTL = -88,
MACH_TIMEBASE_INFO = -89,
MACH_WAIT_UNTIL = -90,
MK_TIMER_CREATE = -91,
MK_TIMER_DESTROY = -92,
MK_TIMER_ARM = -93,
MK_TIMER_CANCEL = -94,
MK_TIMER_ARM_LEEWAY = -95,
DEBUG_CONTROL_PORT_FOR_PID = -96,
IOKIT_USER_CLIENT = -100,
}
public enum XnuBsdSyscall {
EXIT = 1,
FORK = 2,
READ = 3,
WRITE = 4,
OPEN = 5,
CLOSE = 6,
WAIT4 = 7,
LINK = 9,
UNLINK = 10,
CHDIR = 12,
FCHDIR = 13,
MKNOD = 14,
CHMOD = 15,
CHOWN = 16,
GETFSSTAT = 18,
GETPID = 20,
SETUID = 23,
GETUID = 24,
GETEUID = 25,
PTRACE = 26,
RECVMSG = 27,
SENDMSG = 28,
RECVFROM = 29,
ACCEPT = 30,
GETPEERNAME = 31,
GETSOCKNAME = 32,
ACCESS = 33,
CHFLAGS = 34,
FCHFLAGS = 35,
SYNC = 36,
KILL = 37,
CROSSARCH_TRAP = 38,
GETPPID = 39,
DUP = 41,
PIPE = 42,
GETEGID = 43,
SIGACTION = 46,
GETGID = 47,
SIGPROCMASK = 48,
GETLOGIN = 49,
SETLOGIN = 50,
ACCT = 51,
SIGPENDING = 52,
SIGALTSTACK = 53,
IOCTL = 54,
REBOOT = 55,
REVOKE = 56,
SYMLINK = 57,
READLINK = 58,
EXECVE = 59,
UMASK = 60,
CHROOT = 61,
MSYNC = 65,
VFORK = 66,
OSLOG_COPROC_REG = 67,
OSLOG_COPROC = 68,
MUNMAP = 73,
MPROTECT = 74,
MADVISE = 75,
MINCORE = 78,
GETGROUPS = 79,
SETGROUPS = 80,
GETPGRP = 81,
SETPGID = 82,
SETITIMER = 83,
SWAPON = 85,
GETITIMER = 86,
GETDTABLESIZE = 89,
DUP2 = 90,
FCNTL = 92,
SELECT = 93,
FSYNC = 95,
SETPRIORITY = 96,
SOCKET = 97,
CONNECT = 98,
GETPRIORITY = 100,
BIND = 104,
SETSOCKOPT = 105,
LISTEN = 106,
SIGSUSPEND = 111,
GETTIMEOFDAY = 116,
GETRUSAGE = 117,
GETSOCKOPT = 118,
READV = 120,
WRITEV = 121,
SETTIMEOFDAY = 122,
FCHOWN = 123,
FCHMOD = 124,
SETREUID = 126,
SETREGID = 127,
RENAME = 128,
FLOCK = 131,
MKFIFO = 132,
SENDTO = 133,
SHUTDOWN = 134,
SOCKETPAIR = 135,
MKDIR = 136,
RMDIR = 137,
UTIMES = 138,
FUTIMES = 139,
ADJTIME = 140,
GETHOSTUUID = 142,
SETSID = 147,
GETPGID = 151,
SETPRIVEXEC = 152,
PREAD = 153,
PWRITE = 154,
NFSSVC = 155,
STATFS = 157,
FSTATFS = 158,
UNMOUNT = 159,
GETFH = 161,
FUNMOUNT = 164,
QUOTACTL = 165,
MOUNT = 167,
CSOPS = 169,
CSOPS_AUDITTOKEN = 170,
WAITID = 173,
KDEBUG_TYPEFILTER = 177,
KDEBUG_TRACE_STRING = 178,
KDEBUG_TRACE64 = 179,
KDEBUG_TRACE = 180,
SETGID = 181,
SETEGID = 182,
SETEUID = 183,
SIGRETURN = 184,
PANIC_WITH_DATA = 185,
THREAD_SELFCOUNTS = 186,
FDATASYNC = 187,
STAT = 188,
FSTAT = 189,
LSTAT = 190,
PATHCONF = 191,
FPATHCONF = 192,
GETRLIMIT = 194,
SETRLIMIT = 195,
GETDIRENTRIES = 196,
MMAP = 197,
LSEEK = 199,
TRUNCATE = 200,
FTRUNCATE = 201,
SYSCTL = 202,
MLOCK = 203,
MUNLOCK = 204,
UNDELETE = 205,
OPEN_DPROTECTED_NP = 216,
FSGETPATH_EXT = 217,
OPENAT_DPROTECTED_NP = 218,
GETATTRLIST = 220,
SETATTRLIST = 221,
GETDIRENTRIESATTR = 222,
EXCHANGEDATA = 223,
SEARCHFS = 225,
DELETE = 226,
COPYFILE = 227,
FGETATTRLIST = 228,
FSETATTRLIST = 229,
POLL = 230,
GETXATTR = 234,
FGETXATTR = 235,
SETXATTR = 236,
FSETXATTR = 237,
REMOVEXATTR = 238,
FREMOVEXATTR = 239,
LISTXATTR = 240,
FLISTXATTR = 241,
FSCTL = 242,
INITGROUPS = 243,
POSIX_SPAWN = 244,
FFSCTL = 245,
FHOPEN = 248,
MINHERIT = 250,
SEMSYS = 251,
MSGSYS = 252,
SHMSYS = 253,
SEMCTL = 254,
SEMGET = 255,
SEMOP = 256,
MSGCTL = 258,
MSGGET = 259,
MSGSND = 260,
MSGRCV = 261,
SHMAT = 262,
SHMCTL = 263,
SHMDT = 264,
SHMGET = 265,
SHM_OPEN = 266,
SHM_UNLINK = 267,
SEM_OPEN = 268,
SEM_CLOSE = 269,
SEM_UNLINK = 270,
SEM_WAIT = 271,
SEM_TRYWAIT = 272,
SEM_POST = 273,
SYSCTLBYNAME = 274,
OPEN_EXTENDED = 277,
UMASK_EXTENDED = 278,
STAT_EXTENDED = 279,
LSTAT_EXTENDED = 280,
FSTAT_EXTENDED = 281,
CHMOD_EXTENDED = 282,
FCHMOD_EXTENDED = 283,
ACCESS_EXTENDED = 284,
SETTID = 285,
GETTID = 286,
SETSGROUPS = 287,
GETSGROUPS = 288,
SETWGROUPS = 289,
GETWGROUPS = 290,
MKFIFO_EXTENDED = 291,
MKDIR_EXTENDED = 292,
IDENTITYSVC = 293,
SHARED_REGION_CHECK_NP = 294,
VM_PRESSURE_MONITOR = 296,
PSYNCH_RW_LONGRDLOCK = 297,
PSYNCH_RW_YIELDWRLOCK = 298,
PSYNCH_RW_DOWNGRADE = 299,
PSYNCH_RW_UPGRADE = 300,
PSYNCH_MUTEXWAIT = 301,
PSYNCH_MUTEXDROP = 302,
PSYNCH_CVBROAD = 303,
PSYNCH_CVSIGNAL = 304,
PSYNCH_CVWAIT = 305,
PSYNCH_RW_RDLOCK = 306,
PSYNCH_RW_WRLOCK = 307,
PSYNCH_RW_UNLOCK = 308,
PSYNCH_RW_UNLOCK2 = 309,
GETSID = 310,
SETTID_WITH_PID = 311,
PSYNCH_CVCLRPREPOST = 312,
AIO_FSYNC = 313,
AIO_RETURN = 314,
AIO_SUSPEND = 315,
AIO_CANCEL = 316,
AIO_ERROR = 317,
AIO_READ = 318,
AIO_WRITE = 319,
LIO_LISTIO = 320,
IOPOLICYSYS = 322,
PROCESS_POLICY = 323,
MLOCKALL = 324,
MUNLOCKALL = 325,
ISSETUGID = 327,
PTHREAD_KILL = 328,
PTHREAD_SIGMASK = 329,
SIGWAIT = 330,
DISABLE_THREADSIGNAL = 331,
PTHREAD_MARKCANCEL = 332,
PTHREAD_CANCELED = 333,
SEMWAIT_SIGNAL = 334,
PROC_INFO = 336,
SENDFILE = 337,
STAT64 = 338,
FSTAT64 = 339,
LSTAT64 = 340,
STAT64_EXTENDED = 341,
LSTAT64_EXTENDED = 342,
FSTAT64_EXTENDED = 343,
GETDIRENTRIES64 = 344,
STATFS64 = 345,
FSTATFS64 = 346,
GETFSSTAT64 = 347,
PTHREAD_CHDIR = 348,
PTHREAD_FCHDIR = 349,
AUDIT = 350,
AUDITON = 351,
GETAUID = 353,
SETAUID = 354,
GETAUDIT_ADDR = 357,
SETAUDIT_ADDR = 358,
AUDITCTL = 359,
BSDTHREAD_CREATE = 360,
BSDTHREAD_TERMINATE = 361,
KQUEUE = 362,
KEVENT = 363,
LCHOWN = 364,
BSDTHREAD_REGISTER = 366,
WORKQ_OPEN = 367,
WORKQ_KERNRETURN = 368,
KEVENT64 = 369,
THREAD_SELFID = 372,
LEDGER = 373,
KEVENT_QOS = 374,
KEVENT_ID = 375,
MAC_EXECVE = 380,
MAC_SYSCALL = 381,
MAC_GET_FILE = 382,
MAC_SET_FILE = 383,
MAC_GET_LINK = 384,
MAC_SET_LINK = 385,
MAC_GET_PROC = 386,
MAC_SET_PROC = 387,
MAC_GET_FD = 388,
MAC_SET_FD = 389,
MAC_GET_PID = 390,
PSELECT = 394,
PSELECT_NOCANCEL = 395,
READ_NOCANCEL = 396,
WRITE_NOCANCEL = 397,
OPEN_NOCANCEL = 398,
CLOSE_NOCANCEL = 399,
WAIT4_NOCANCEL = 400,
RECVMSG_NOCANCEL = 401,
SENDMSG_NOCANCEL = 402,
RECVFROM_NOCANCEL = 403,
ACCEPT_NOCANCEL = 404,
MSYNC_NOCANCEL = 405,
FCNTL_NOCANCEL = 406,
SELECT_NOCANCEL = 407,
FSYNC_NOCANCEL = 408,
CONNECT_NOCANCEL = 409,
SIGSUSPEND_NOCANCEL = 410,
READV_NOCANCEL = 411,
WRITEV_NOCANCEL = 412,
SENDTO_NOCANCEL = 413,
PREAD_NOCANCEL = 414,
PWRITE_NOCANCEL = 415,
WAITID_NOCANCEL = 416,
POLL_NOCANCEL = 417,
MSGSND_NOCANCEL = 418,
MSGRCV_NOCANCEL = 419,
SEM_WAIT_NOCANCEL = 420,
AIO_SUSPEND_NOCANCEL = 421,
SIGWAIT_NOCANCEL = 422,
SEMWAIT_SIGNAL_NOCANCEL = 423,
MAC_MOUNT = 424,
MAC_GET_MOUNT = 425,
MAC_GETFSSTAT = 426,
FSGETPATH = 427,
AUDIT_SESSION_SELF = 428,
AUDIT_SESSION_JOIN = 429,
FILEPORT_MAKEPORT = 430,
FILEPORT_MAKEFD = 431,
AUDIT_SESSION_PORT = 432,
PID_SUSPEND = 433,
PID_RESUME = 434,
PID_HIBERNATE = 435,
PID_SHUTDOWN_SOCKETS = 436,
KAS_INFO = 439,
MEMORYSTATUS_CONTROL = 440,
GUARDED_OPEN_NP = 441,
GUARDED_CLOSE_NP = 442,
GUARDED_KQUEUE_NP = 443,
CHANGE_FDGUARD_NP = 444,
USRCTL = 445,
PROC_RLIMIT_CONTROL = 446,
CONNECTX = 447,
DISCONNECTX = 448,
PEELOFF = 449,
SOCKET_DELEGATE = 450,
TELEMETRY = 451,
PROC_UUID_POLICY = 452,
MEMORYSTATUS_GET_LEVEL = 453,
SYSTEM_OVERRIDE = 454,
VFS_PURGE = 455,
SFI_CTL = 456,
SFI_PIDCTL = 457,
COALITION = 458,
COALITION_INFO = 459,
NECP_MATCH_POLICY = 460,
GETATTRLISTBULK = 461,
CLONEFILEAT = 462,
OPENAT = 463,
OPENAT_NOCANCEL = 464,
RENAMEAT = 465,
FACCESSAT = 466,
FCHMODAT = 467,
FCHOWNAT = 468,
FSTATAT = 469,
FSTATAT64 = 470,
LINKAT = 471,
UNLINKAT = 472,
READLINKAT = 473,
SYMLINKAT = 474,
MKDIRAT = 475,
GETATTRLISTAT = 476,
PROC_TRACE_LOG = 477,
BSDTHREAD_CTL = 478,
OPENBYID_NP = 479,
RECVMSG_X = 480,
SENDMSG_X = 481,
THREAD_SELFUSAGE = 482,
CSRCTL = 483,
GUARDED_OPEN_DPROTECTED_NP = 484,
GUARDED_WRITE_NP = 485,
GUARDED_PWRITE_NP = 486,
GUARDED_WRITEV_NP = 487,
RENAMEATX_NP = 488,
MREMAP_ENCRYPTED = 489,
NETAGENT_TRIGGER = 490,
STACK_SNAPSHOT_WITH_CONFIG = 491,
MICROSTACKSHOT = 492,
GRAB_PGO_DATA = 493,
PERSONA = 494,
MACH_EVENTLINK_SIGNAL = 496,
MACH_EVENTLINK_WAIT_UNTIL = 497,
MACH_EVENTLINK_SIGNAL_WAIT_UNTIL = 498,
WORK_INTERVAL_CTL = 499,
GETENTROPY = 500,
NECP_CLIENT_ACTION = 502,
NEXUS_OPEN = 503,
NEXUS_REGISTER = 504,
NEXUS_DEREGISTER = 505,
NEXUS_CREATE = 506,
NEXUS_DESTROY = 507,
NEXUS_GET_OPT = 508,
NEXUS_SET_OPT = 509,
CHANNEL_OPEN = 510,
CHANNEL_GET_INFO = 511,
CHANNEL_SYNC = 512,
CHANNEL_GET_OPT = 513,
CHANNEL_SET_OPT = 514,
ULOCK_WAIT = 515,
ULOCK_WAKE = 516,
FCLONEFILEAT = 517,
FS_SNAPSHOT = 518,
TERMINATE_WITH_PAYLOAD = 520,
ABORT_WITH_PAYLOAD = 521,
NECP_SESSION_ACTION = 523,
SETATTRLISTAT = 524,
NET_QOS_GUIDELINE = 525,
FMOUNT = 526,
NTP_ADJTIME = 527,
NTP_GETTIME = 528,
OS_FAULT_WITH_PAYLOAD = 529,
KQUEUE_WORKLOOP_CTL = 530,
MACH_BRIDGE_REMOTE_TIME = 531,
COALITION_LEDGER = 532,
LOG_DATA = 533,
MEMORYSTATUS_AVAILABLE_MEMORY = 534,
OBJC_BP_ASSIST_CFG_NP = 535,
SHARED_REGION_MAP_AND_SLIDE_2_NP = 536,
PIVOT_ROOT = 537,
TASK_INSPECT_FOR_PID = 538,
TASK_READ_FOR_PID = 539,
PREADV = 540,
PWRITEV = 541,
PREADV_NOCANCEL = 542,
PWRITEV_NOCANCEL = 543,
ULOCK_WAIT2 = 544,
PROC_INFO_EXTENDED_ID = 545,
TRACKER_ACTION = 546,
DEBUG_SYSCALL_REJECT = 547,
DEBUG_SYSCALL_REJECT_CONFIG = 548,
GRAFTDMG = 549,
MAP_WITH_LINKING_NP = 550,
FREADLINK = 551,
RECORD_SYSTEM_EVENT = 552,
MKFIFOAT = 553,
MKNODAT = 554,
UNGRAFTDMG = 555,
COALITION_POLICY_SET = 556,
COALITION_POLICY_GET = 557,
}
}
-11
View File
@@ -1,11 +0,0 @@
FRIDA_1.0 {
local:
*;
};
GLIBC_2.2.5 {
local:
fopen*;
fseeko*;
ftello*;
} FRIDA_1.0;
-2
View File
@@ -118,8 +118,6 @@ frida_gadget_environment_deinit (void)
g_assert (worker_loop != NULL);
frida_libc_shim_prepare_to_deinit ();
source = g_idle_source_new ();
g_source_set_priority (source, G_PRIORITY_LOW);
g_source_set_callback (source, stop_worker_loop, NULL, NULL);
+1 -1
View File
@@ -45,7 +45,7 @@ elif host_os_family == 'darwin'
extra_link_args += '-Wl,-exported_symbols_list,' + meson.current_source_dir() / symlist
extra_link_depends += symlist
else
symscript = (libc == 'glibc') ? 'frida-gadget-glibc.version' : 'frida-gadget.version'
symscript = 'frida-gadget.version'
extra_link_args += '-Wl,--version-script,' + meson.current_source_dir() / symscript
extra_link_depends += symscript
endif
+20 -304
View File
@@ -10,7 +10,6 @@
# include <assert.h>
# include <fcntl.h>
# include <unistd.h>
# include <wchar.h>
#endif
#if defined (HAVE_DARWIN)
# include <sys/attr.h>
@@ -26,44 +25,21 @@
#undef feof
#undef ferror
#undef fgetwc
#undef fopen
#undef fopen64
#undef fputwc
#undef fseek
#undef fseeko
#undef fseeko64
#undef ftell
#undef ftello
#undef ftello64
#undef getc
#undef getc_unlocked
#undef getwc
#undef memcpy
#undef putc
#undef putchar
#undef putwc
#undef snprintf
#undef sprintf
#undef stderr
#undef stdin
#undef stdout
#undef ungetc
#undef ungetwc
#undef vsnprintf
#ifdef HAVE_MUSL
# define FRIDA_STDIO_OPAQUE_FILE 1
#endif
static gboolean frida_deinit_expected = FALSE;
void
frida_libc_shim_prepare_to_deinit (void)
{
frida_deinit_expected = TRUE;
}
#if defined (HAVE_WINDOWS) || defined (HAVE_ASAN)
void
@@ -94,9 +70,6 @@ __attribute__ ((destructor)) static
void
frida_libc_shim_deinit (void)
{
if (!frida_deinit_expected)
return;
# ifdef HAVE_ASAN
gum_deinit ();
# else
@@ -169,8 +142,8 @@ struct _FridaFile
size_t wcap;
size_t wlen;
guint8 ungot_buf[8];
guint ungot_len;
int ungot;
gboolean has_ungot;
};
struct _FridaFileHandle
@@ -198,10 +171,6 @@ struct _FridaDir
#endif
static FILE * frida_fopen_impl (const char * pathname, const char * mode);
static int frida_fseek_impl (FILE * stream, off_t offset, int whence);
static off_t frida_ftell_impl (FILE * stream);
static void frida_stdio_register_stream (FILE * stream);
static void frida_stdio_unregister_stream (FILE * stream);
#ifdef HAVE_FRIDA_DIR
@@ -224,8 +193,6 @@ static void frida_parse_fopen_mode (const char * mode, int * oflags);
static int frida_write_formatted_to_fd (int fd, const char * format, va_list args);
static gboolean frida_utf8_expected_len (guint8 first, guint * out_len);
#ifdef HAVE_FRIDA_DIR
static FridaDir * frida_dir_get_impl (DIR * dirp);
static DIR * frida_dir_wrap (FridaDir * impl);
@@ -350,9 +317,6 @@ frida_libc_shim_deinit (void)
fflush (NULL);
if (!frida_deinit_expected)
return;
G_LOCK (frida_stdio);
g_hash_table_iter_init (&iter, frida_streams);
@@ -675,34 +639,8 @@ asprintf_l (char ** ret, locale_t loc, const char * format, ...)
#endif
#ifdef HAVE_GLIBC
G_GNUC_INTERNAL FILE *
frida_fopen_glibc_225 (const char * pathname, const char * mode)
{
return frida_fopen_impl (pathname, mode);
}
__asm__ (".symver frida_fopen_glibc_225,fopen@@GLIBC_2.2.5");
G_GNUC_INTERNAL FILE *
frida_fopen64_glibc_225 (const char * pathname, const char * mode)
{
return frida_fopen_impl (pathname, mode);
}
__asm__ (".symver frida_fopen64_glibc_225,fopen64@@GLIBC_2.2.5");
#else
G_GNUC_INTERNAL FILE *
fopen (const char * pathname, const char * mode)
{
return frida_fopen_impl (pathname, mode);
}
#endif
static FILE *
frida_fopen_impl (const char * pathname, const char * mode)
{
FILE * result;
int oflags, fd;
@@ -863,8 +801,11 @@ getc_unlocked (FILE * stream)
f = frida_file_get_impl (stream);
if (f->ungot_len != 0)
return f->ungot_buf[--f->ungot_len];
if (f->has_ungot)
{
f->has_ungot = FALSE;
return f->ungot;
}
if (f->buf_mode == _IONBF)
{
@@ -905,58 +846,6 @@ getc (FILE * stream)
return getc_unlocked (stream);
}
G_GNUC_INTERNAL wint_t
getwc (FILE * stream)
{
return fgetwc (stream);
}
G_GNUC_INTERNAL wint_t
fgetwc (FILE * stream)
{
char bytes[4];
guint need, have;
int c;
gunichar ch;
c = getc_unlocked (stream);
if (c == EOF)
return WEOF;
bytes[0] = c;
if (!frida_utf8_expected_len (bytes[0], &need))
{
errno = EILSEQ;
frida_file_get_impl (stream)->err = errno;
return WEOF;
}
have = 1;
while (have != need)
{
c = getc_unlocked (stream);
if (c == EOF)
{
errno = EILSEQ;
frida_file_get_impl (stream)->err = errno;
return WEOF;
}
bytes[have++] = c;
}
ch = g_utf8_get_char_validated (bytes, (gssize) need);
if (ch == (gunichar) -1 || ch == (gunichar) -2)
{
errno = EILSEQ;
frida_file_get_impl (stream)->err = errno;
return WEOF;
}
return (wint_t) ch;
}
G_GNUC_INTERNAL int
ungetc (int c, FILE * stream)
{
@@ -967,46 +856,16 @@ ungetc (int c, FILE * stream)
if (c == EOF)
return EOF;
if (f->ungot_len == G_N_ELEMENTS (f->ungot_buf))
if (f->has_ungot)
return EOF;
f->ungot_buf[f->ungot_len++] = c;
f->ungot = c;
f->has_ungot = TRUE;
f->eof = FALSE;
return c;
}
G_GNUC_INTERNAL wint_t
ungetwc (wint_t wc, FILE * stream)
{
FridaFile * f;
char tmp[4];
int len;
int i;
if (wc == WEOF)
return WEOF;
f = frida_file_get_impl (stream);
len = g_unichar_to_utf8 ((gunichar) wc, tmp);
if (len <= 0 || len > 4)
{
errno = EILSEQ;
f->err = errno;
return WEOF;
}
if (f->ungot_len + len > G_N_ELEMENTS (f->ungot_buf))
return WEOF;
for (i = 0; i != len; i++)
f->ungot_buf[f->ungot_len++] = tmp[i];
f->eof = FALSE;
return wc;
}
G_GNUC_INTERNAL size_t
fread (void * ptr, size_t size, size_t nmemb, FILE * stream)
{
@@ -1025,9 +884,10 @@ fread (void * ptr, size_t size, size_t nmemb, FILE * stream)
while (got != want)
{
if (f->ungot_len != 0)
if (f->has_ungot)
{
out[got++] = f->ungot_buf[--f->ungot_len];
out[got++] = (guint8) f->ungot;
f->has_ungot = FALSE;
continue;
}
@@ -1146,12 +1006,6 @@ fwrite (const void * ptr, size_t size, size_t nmemb, FILE * stream)
return off / size;
}
G_GNUC_INTERNAL int
putc (int c, FILE * stream)
{
return fputc (c, stream);
}
G_GNUC_INTERNAL int
fputc (int c, FILE * stream)
{
@@ -1165,37 +1019,6 @@ fputc (int c, FILE * stream)
return ch;
}
G_GNUC_INTERNAL wint_t
putwc (wchar_t wc, FILE * stream)
{
return fputwc (wc, stream);
}
G_GNUC_INTERNAL wint_t
fputwc (wchar_t wc, FILE * stream)
{
char tmp[4];
int len;
size_t n;
if (wc == WEOF)
return WEOF;
len = g_unichar_to_utf8 ((gunichar) wc, tmp);
if (len <= 0 || len > 4)
{
errno = EILSEQ;
frida_file_get_impl (stream)->err = errno;
return WEOF;
}
n = fwrite (tmp, 1, len, stream);
if (n != len)
return WEOF;
return (wint_t) wc;
}
G_GNUC_INTERNAL int
fputs (const char * s, FILE * stream)
{
@@ -1239,84 +1062,6 @@ fgets (char * s, int size, FILE * stream)
G_GNUC_INTERNAL int
fseek (FILE * stream, long offset, int whence)
{
return frida_fseek_impl (stream, (off_t) offset, whence);
}
G_GNUC_INTERNAL long
ftell (FILE * stream)
{
off_t pos = frida_ftell_impl (stream);
if (pos == (off_t) -1)
return -1;
return (long) pos;
}
#ifdef HAVE_GLIBC
G_GNUC_INTERNAL int
frida_fseeko_glibc_225 (FILE * stream, off_t offset, int whence)
{
return frida_fseek_impl (stream, offset, whence);
}
__asm__ (".symver frida_fseeko_glibc_225,fseeko@@GLIBC_2.2.5");
G_GNUC_INTERNAL int
frida_fseeko64_glibc_225 (FILE * stream, off_t offset, int whence)
{
return frida_fseek_impl (stream, offset, whence);
}
__asm__ (".symver frida_fseeko64_glibc_225,fseeko64@@GLIBC_2.2.5");
G_GNUC_INTERNAL off_t
frida_ftello_glibc_225 (FILE * stream)
{
return frida_ftell_impl (stream);
}
__asm__ (".symver frida_ftello_glibc_225,ftello@@GLIBC_2.2.5");
G_GNUC_INTERNAL off_t
frida_ftello64_glibc_225 (FILE * stream)
{
return frida_ftell_impl (stream);
}
__asm__ (".symver frida_ftello64_glibc_225,ftello64@@GLIBC_2.2.5");
#else
G_GNUC_INTERNAL int
fseeko (FILE * stream, off_t offset, int whence)
{
return frida_fseek_impl (stream, offset, whence);
}
G_GNUC_INTERNAL off_t
ftello (FILE * stream)
{
return frida_ftell_impl (stream);
}
# ifndef HAVE_QNX
G_GNUC_INTERNAL int
fseeko64 (FILE * stream, off_t offset, int whence)
{
return frida_fseek_impl (stream, offset, whence);
}
G_GNUC_INTERNAL off_t
ftello64 (FILE * stream)
{
return frida_ftell_impl (stream);
}
# endif
#endif
static int
frida_fseek_impl (FILE * stream, off_t offset, int whence)
{
FridaFile * f;
off_t r;
@@ -1328,10 +1073,10 @@ frida_fseek_impl (FILE * stream, off_t offset, int whence)
f->rpos = 0;
f->rlen = 0;
f->ungot_len = 0;
f->has_ungot = FALSE;
f->eof = FALSE;
r = frida_lseek_nointr (f->fd, offset, whence);
r = frida_lseek_nointr (f->fd, (off_t) offset, whence);
if (r == (off_t) -1)
{
f->err = errno;
@@ -1341,8 +1086,8 @@ frida_fseek_impl (FILE * stream, off_t offset, int whence)
return 0;
}
static off_t
frida_ftell_impl (FILE * stream)
G_GNUC_INTERNAL long
ftell (FILE * stream)
{
FridaFile * f;
off_t pos;
@@ -1359,9 +1104,10 @@ frida_ftell_impl (FILE * stream)
if (f->buf_mode != _IONBF)
pos -= (off_t) (f->rlen - f->rpos);
pos -= f->ungot_len;
if (f->has_ungot)
pos -= 1;
return pos;
return (long) pos;
}
G_GNUC_INTERNAL void
@@ -2120,36 +1866,6 @@ beach:
}
}
static gboolean
frida_utf8_expected_len (guint8 first, guint * out_len)
{
if (first < 0x80)
{
*out_len = 1;
return TRUE;
}
if ((first & 0xe0) == 0xc0)
{
*out_len = 2;
return TRUE;
}
if ((first & 0xf0) == 0xe0)
{
*out_len = 3;
return TRUE;
}
if ((first & 0xf8) == 0xf0)
{
*out_len = 4;
return TRUE;
}
return FALSE;
}
#ifdef HAVE_FRIDA_DIR
static FridaDir *
-1
View File
@@ -1,5 +1,4 @@
namespace Frida {
public extern void libc_shim_prepare_to_deinit ();
#if DARWIN
public extern void libc_shim_deinit ();
#endif
-4
View File
@@ -302,10 +302,6 @@ if host_os == 'linux'
endif
cdata.set('HAVE_' + libc.to_upper(), 1)
vala_flags += '--define=' + libc.to_upper()
elif host_os == 'android'
libc = 'bionic'
else
libc = 'other'
endif
if get_option('b_sanitize') == 'address'
+1 -1
Submodule releng updated: 852c527081...7ed66fe687.
+1 -1
View File
@@ -11,7 +11,7 @@ helper.dex: build/frida-helper.jar
$<
mv build/classes.dex $@
build/frida-helper.jar: re/frida/Helper.java re/frida/HelperBackend.java
build/frida-helper.jar: re/frida/Helper.java
javac \
-cp .:$(android_jar) \
-bootclasspath $(android_jar) \
+71 -87
View File
@@ -1,12 +1,66 @@
namespace Frida {
public sealed class AndroidHelperClient : Object {
public AndroidHelperTransport transport {
public sealed class AndroidHelperClient : Object, AsyncInitable {
public signal void closed ();
public IOStream stream {
get;
construct;
}
public AndroidHelperClient (AndroidHelperTransport transport) {
Object (transport: transport);
private BufferedInputStream input;
private OutputStream output;
private Cancellable io_cancellable = new Cancellable ();
private State state = CLOSED;
private Gee.Queue<Request> pending_requests = new Gee.ArrayQueue<Request> ();
private ByteArray pending_output = new ByteArray ();
private bool writing = false;
private enum State {
CLOSED,
OPEN
}
private const uint32 MAX_RESPONSE_SIZE = 100 * 1024 * 1024;
public AndroidHelperClient (IOStream stream) {
Object (stream: stream);
}
construct {
input = (BufferedInputStream) Object.new (typeof (BufferedInputStream),
"base-stream", stream.get_input_stream (),
"close-base-stream", false,
"buffer-size", 128 * 1024);
output = stream.get_output_stream ();
state = OPEN;
process_incoming_responses.begin ();
}
public async void close (Cancellable? cancellable) throws IOError {
io_cancellable.cancel ();
var source = new IdleSource ();
source.set_callback (close.callback);
source.attach (MainContext.get_thread_default ());
yield;
try {
yield stream.close_async (Priority.DEFAULT, cancellable);
} catch (IOError e) {
}
ensure_closed ();
}
private void ensure_closed () {
if (state == CLOSED)
return;
state = CLOSED;
closed ();
}
public async HostApplicationInfo get_frontmost_application (FrontmostQueryOptions options,
@@ -18,7 +72,7 @@ namespace Frida {
.add_string_value (options.scope.to_nick ())
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
if (response.is_null ())
return HostApplicationInfo.empty ();
@@ -73,7 +127,7 @@ namespace Frida {
.add_string_value (options.scope.to_nick ())
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
Json.Reader reader = new Json.Reader (response);
@@ -139,7 +193,7 @@ namespace Frida {
.add_string_value (options.scope.to_nick ())
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
Json.Reader reader = new Json.Reader (response);
@@ -193,7 +247,7 @@ namespace Frida {
.add_int_value (uid)
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
var r = new Json.Reader (response);
parse_envelope_or_throw (r);
@@ -263,7 +317,7 @@ namespace Frida {
.add_int_value (uid)
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
var r = new Json.Reader (response);
parse_envelope_or_throw (r);
@@ -277,7 +331,7 @@ namespace Frida {
.add_int_value ((int) pid)
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
var r = new Json.Reader (response);
parse_envelope_or_throw (r);
@@ -289,13 +343,6 @@ namespace Frida {
return r.get_boolean_value ();
}
private async void request_ok (Json.Builder stanza, Cancellable? cancellable) throws Error, IOError {
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
var r = new Json.Reader (response);
parse_envelope_or_throw (r);
}
private void parse_envelope_or_throw (Json.Reader r) throws Error {
r.read_element (0);
string? kind = r.get_string_value ();
@@ -405,76 +452,6 @@ namespace Frida {
throw new Error.PROTOCOL ("Unexpected JSON type: %s", type.name ());
}
}
public interface AndroidHelperTransport : Object {
public abstract async void close (Cancellable? cancellable) throws IOError;
public abstract async Json.Node request (Json.Node stanza, Cancellable? cancellable) throws Error, IOError;
}
public sealed class AndroidHelperStreamTransport : Object, AndroidHelperTransport {
public signal void closed ();
public IOStream stream {
get;
construct;
}
private BufferedInputStream input;
private OutputStream output;
private Cancellable io_cancellable = new Cancellable ();
private State state = CLOSED;
private Gee.Queue<Request> pending_requests = new Gee.ArrayQueue<Request> ();
private ByteArray pending_output = new ByteArray ();
private bool writing = false;
private enum State {
CLOSED,
OPEN
}
private const uint32 MAX_RESPONSE_SIZE = 100 * 1024 * 1024;
public AndroidHelperStreamTransport (IOStream stream) {
Object (stream: stream);
}
construct {
input = (BufferedInputStream) Object.new (typeof (BufferedInputStream),
"base-stream", stream.get_input_stream (),
"close-base-stream", false,
"buffer-size", 128 * 1024);
output = stream.get_output_stream ();
state = OPEN;
process_incoming_responses.begin ();
}
public async void close (Cancellable? cancellable) throws IOError {
io_cancellable.cancel ();
var source = new IdleSource ();
source.set_callback (close.callback);
source.attach (MainContext.get_thread_default ());
yield;
try {
yield stream.close_async (Priority.DEFAULT, cancellable);
} catch (IOError e) {
}
ensure_closed ();
}
private void ensure_closed () {
if (state == CLOSED)
return;
state = CLOSED;
closed ();
}
public async Json.Node request (Json.Node stanza, Cancellable? cancellable) throws Error, IOError {
if (state == CLOSED)
@@ -510,6 +487,13 @@ namespace Frida {
return r.response;
}
private async void request_ok (Json.Builder stanza, Cancellable? cancellable) throws Error, IOError {
Json.Node response = yield request (stanza.get_root (), cancellable);
var r = new Json.Reader (response);
parse_envelope_or_throw (r);
}
private void write_request (Json.Node request) {
string request_str = Json.to_string (request, false);
uint8[] request_data = request_str.data;
Binary file not shown.
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-2
View File
@@ -519,8 +519,6 @@ def function_is_public(name):
"check_kernel_version",
"get_syscall_signatures",
"get_compat32_syscall_signatures",
"get_xnu_mach_traps",
"get_xnu_bsd_syscalls",
"make_stdio_pipes",
"make_stdio_pipe",
}
+4 -4
View File
@@ -33,7 +33,7 @@
"@frida/url": "^1.0.2",
"@frida/util": "^1.0.3",
"@frida/vm": "^2.0.0",
"@types/frida-gum": "19.0.2",
"@types/frida-gum": "19.0.1",
"@types/node": "18.19.103",
"frida-fs": "7.0.0"
}
@@ -248,9 +248,9 @@
"license": "MIT"
},
"node_modules/@types/frida-gum": {
"version": "19.0.2",
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.2.tgz",
"integrity": "sha512-oh/f1r8dIMDWBoziXP3geIJ8ga/siU32MuifBztGsDglOKbHrhS0E3z0Dab0MIe3UFzC4Bvz/GRHfin2LDE8BQ==",
"version": "19.0.1",
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.1.tgz",
"integrity": "sha512-mp8BpWWkQFJH86ZN5uXZuDiA7KY/+jDknrw0a06x0/+F5ucPwctHrCuV6iT+LLCp/GyICc36ssedF33B1WoLsw==",
"license": "MIT"
},
"node_modules/@types/node": {
+1 -1
View File
@@ -29,7 +29,7 @@
"@frida/url": "^1.0.2",
"@frida/util": "^1.0.3",
"@frida/vm": "^2.0.0",
"@types/frida-gum": "19.0.2",
"@types/frida-gum": "19.0.1",
"@types/node": "18.19.103",
"frida-fs": "7.0.0"
}
+12 -16
View File
@@ -444,7 +444,6 @@ static void frida_set_nth_hardware_breakpoint (gpointer state, guint n, GumAddre
static void frida_set_hardware_single_step (gpointer debug_state, GumDarwinUnifiedThreadState * thread_state, gboolean enabled, GumCpuType cpu_type);
static gboolean frida_is_hardware_breakpoint_support_working (void);
static gboolean frida_find_restart_with_dyld_in_cache (const GumDarwinSymbolDetails * details, gpointer user_data);
static GumAddress frida_find_run_initializers_call (mach_port_t task, GumCpuType cpu_type, GumAddress start);
static GHashTable * frida_find_modinit_strcmp_checks (mach_port_t task, GumDarwinModule * dyld);
static GumAddress frida_find_function_end (mach_port_t task, GumCpuType cpu_type, GumAddress start, gsize max_size);
@@ -2108,8 +2107,18 @@ _frida_darwin_helper_backend_prepare_spawn_instance_for_injection (FridaDarwinHe
frida_spawn_instance_set_nth_breakpoint (instance, i++, sim_notify_address, FRIDA_BREAKPOINT_REPEAT_ALWAYS);
if (instance->dyld_flavor == FRIDA_DYLD_V4_PLUS)
{
GumAddress restart_with_dyld_in_cache = 0;
gum_darwin_module_enumerate_symbols (dyld, frida_find_restart_with_dyld_in_cache, &restart_with_dyld_in_cache);
GumAddress restart_with_dyld_in_cache = gum_darwin_module_resolve_symbol_address (dyld,
"__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN6mach_o6HeaderEPK15DyldSharedCachePv");
if (restart_with_dyld_in_cache == 0)
{
restart_with_dyld_in_cache = gum_darwin_module_resolve_symbol_address (dyld,
"__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN5dyld39MachOFileEPK15DyldSharedCachePv");
}
if (restart_with_dyld_in_cache == 0)
{
restart_with_dyld_in_cache = gum_darwin_module_resolve_symbol_address (dyld,
"__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN5dyld39MachOFileEPv");
}
if (restart_with_dyld_in_cache != 0)
frida_spawn_instance_set_nth_breakpoint (instance, i++, restart_with_dyld_in_cache, FRIDA_BREAKPOINT_REPEAT_NEVER);
}
@@ -5433,19 +5442,6 @@ frida_is_hardware_breakpoint_support_working (void)
#endif
}
static gboolean
frida_find_restart_with_dyld_in_cache (const GumDarwinSymbolDetails * details, gpointer user_data)
{
if (strstr (details->name, "restartWithDyldInCache") != NULL)
{
GumAddress * restart_with_dyld_in_cache = user_data;
*restart_with_dyld_in_cache = details->address;
return FALSE;
}
return TRUE;
}
static GumAddress
frida_find_run_initializers_call (mach_port_t task, GumCpuType cpu_type, GumAddress start)
{
+6 -9
View File
@@ -290,9 +290,8 @@ namespace Frida {
if (helper_client_request != null) {
AndroidHelperClient? helper = yield try_get_helper_client (cancellable);
if (helper != null) {
var transport = (AndroidHelperStreamTransport) helper.transport;
on_helper_stream_transport_closed (transport);
yield transport.close (cancellable);
on_helper_client_closed (helper);
yield helper.close (cancellable);
}
}
@@ -1061,10 +1060,8 @@ namespace Frida {
throw e;
}
var transport = new AndroidHelperStreamTransport (client.stream);
transport.closed.connect (on_helper_stream_transport_closed);
var helper = new AndroidHelperClient (transport);
var helper = new AndroidHelperClient (client.stream);
helper.closed.connect (on_helper_client_closed);
helper_shell = shell;
@@ -1083,8 +1080,8 @@ namespace Frida {
}
}
private void on_helper_stream_transport_closed (AndroidHelperStreamTransport transport) {
transport.closed.disconnect (on_helper_stream_transport_closed);
private void on_helper_client_closed (AndroidHelperClient helper) {
helper.closed.disconnect (on_helper_client_closed);
helper_client_request = null;
if (helper_shell != null) {
-401
View File
@@ -1,401 +0,0 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class CsSignature : Object {
public uint32 version;
public uint32 pid;
public uint32 stuff;
public uint32 flags;
public Gee.List<CsSigOwner> owners = new Gee.ArrayList<CsSigOwner> ();
private CsSegIndexEntry[]? seg_index = null;
private uint32 seg_index_gen = 0;
private struct CsSegIndexEntry {
public uint64 start;
public uint64 end;
public unowned CsSigOwner owner;
}
public void apply_refresh (CsSignature fresh, uint32 gen) {
foreach (var cur in owners) {
if (cur.mapped_gen_end != 0)
continue;
bool still_present = false;
foreach (var f in fresh.owners) {
if (cur.uuid.compare (f.uuid) == 0) {
still_present = true;
break;
}
}
if (!still_present)
cur.mapped_gen_end = gen;
}
foreach (var f in fresh.owners) {
CsSigOwner? cur = null;
foreach (var existing in owners) {
if (existing.uuid.compare (f.uuid) == 0) {
cur = existing;
break;
}
}
if (cur == null) {
f.mapped_gen_start = gen;
f.mapped_gen_end = 0;
owners.add (f);
} else {
uint32 start = cur.mapped_gen_start;
uint32 end = cur.mapped_gen_end;
cur.path = f.path;
cur.image_base = f.image_base;
cur.image_end = f.image_end;
cur.segments = f.segments;
cur.version = f.version;
cur.mapped_gen_start = start;
cur.mapped_gen_end = end;
}
}
invalidate_index ();
}
public void note_unmapped_uuid (Bytes uuid, uint32 gen) {
foreach (var o in owners) {
if (o.mapped_gen_end != 0)
continue;
if (o.uuid.compare (uuid) == 0) {
o.mapped_gen_end = gen;
invalidate_index ();
return;
}
}
}
public void resolve_addresses (uint32 gen, uint64[] addrs, AddressResolved on_symbol, ModulesReady on_modules) {
ensure_index (gen);
var used_owner_to_mod = new Gee.HashMap<CsSigOwner, uint32> ();
var module_list = new Gee.ArrayList<CsSigOwner> ();
foreach (var addr in addrs) {
CsSigOwner? owner;
uint32 rel;
if (!try_resolve (addr, out owner, out rel)) {
on_symbol (addr, uint32.MAX, 0);
continue;
}
uint32 mod_idx;
if (!used_owner_to_mod.has_key (owner)) {
mod_idx = (uint32) module_list.size;
used_owner_to_mod[owner] = mod_idx;
module_list.add (owner);
} else {
mod_idx = used_owner_to_mod[owner];
}
on_symbol (addr, mod_idx, rel);
}
on_modules (module_list);
}
public delegate void AddressResolved (uint64 addr, uint32 module_index, uint32 rel);
public delegate void ModulesReady (Gee.List<CsSigOwner> modules);
private void ensure_index (uint32 gen) {
if (seg_index != null && seg_index_gen == gen)
return;
var tmp = new Array<CsSegIndexEntry> (false, false);
foreach (var owner in owners) {
if (!owner_is_mapped_at (owner, gen))
continue;
foreach (var seg in owner.segments) {
if (seg.name == "__PAGEZERO")
continue;
tmp.append_val (CsSegIndexEntry () {
start = seg.vmaddr,
end = seg.vmaddr + seg.vmsize,
owner = owner,
});
}
}
tmp.sort ((a, b) => {
if (a.start < b.start)
return -1;
if (a.start > b.start)
return 1;
return 0;
});
seg_index = tmp.steal ();
seg_index_gen = gen;
}
private void invalidate_index () {
seg_index = null;
seg_index_gen = 0;
}
private bool try_resolve (uint64 addr, out CsSigOwner? owner, out uint32 rel) {
owner = null;
rel = 0;
int n = seg_index.length;
if (n == 0)
return false;
int lo = 0;
int hi = n - 1;
int best = -1;
while (lo <= hi) {
int mid = lo + ((hi - lo) / 2);
if (seg_index[mid].start <= addr) {
best = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
if (best == -1)
return false;
for (int i = best; i >= 0; i--) {
var e = seg_index[i];
if (e.start > addr)
continue;
if (addr < e.end) {
owner = e.owner;
rel = (uint32) (addr - owner.image_base);
return true;
}
}
return false;
}
private static bool owner_is_mapped_at (CsSigOwner owner, uint32 gen) {
if (gen < owner.mapped_gen_start)
return false;
uint32 end = owner.mapped_gen_end;
if (end == 0)
return true;
return gen < end;
}
}
public class CsSigOwner : Object {
public Bytes uuid;
public uint32 a;
public uint32 flags;
public uint64 load_timestamp;
public uint64 unload_timestamp;
public uint32 cpu_type;
public uint32 cpu_subtype;
public string path;
public uint64 image_base;
public uint64 image_end;
public Gee.List<CsSigSegment> segments = new Gee.ArrayList<CsSigSegment> ();
public string? version;
public uint32 mapped_gen_start = 1;
public uint32 mapped_gen_end = 0;
}
public class CsSigSegment {
public string name;
public uint64 vmaddr;
public uint64 vmsize;
}
public sealed class CsSignatureParser : Object {
private Buffer buf;
private BufferReader r;
public CsSignatureParser (Bytes blob) {
buf = new Buffer (blob, LITTLE_ENDIAN, 8);
r = new BufferReader (buf);
}
public CsSignature parse () throws Error {
uint32 magic = r.read_uint32 ();
uint32 version = r.read_uint32 ();
uint32 pid = r.read_uint32 ();
uint32 stuff = r.read_uint32 ();
uint32 flags = r.read_uint32 ();
uint32 owner_count = r.read_uint32 ();
if (magic != 0xff01ff02u)
throw new Error.PROTOCOL ("Bad signature magic 0x%08x", magic);
var sig = new CsSignature ();
sig.version = version;
sig.pid = pid;
sig.stuff = stuff;
sig.flags = flags;
for (uint32 i = 0; i != owner_count; i++)
sig.owners.add (parse_owner ());
decode_optional_data (sig);
return sig;
}
private CsSigOwner parse_owner () throws Error {
var o = new CsSigOwner ();
o.uuid = r.read_bytes (16);
o.a = r.read_uint32 ();
o.flags = r.read_uint32 () & 0x7fffffff;
o.load_timestamp = r.read_uint64 ();
o.unload_timestamp = r.read_uint64 ();
o.cpu_type = r.read_uint32 ();
o.cpu_subtype = r.read_uint32 ();
uint32 nsegs = r.read_uint32 ();
uint32 str_len = r.read_uint32 ();
o.path = r.read_fixed_string (str_len);
for (uint32 i = 0; i != nsegs; i++) {
var s = new CsSigSegment ();
s.name = r.read_fixed_string (16);
s.vmaddr = r.read_uint64 ();
s.vmsize = r.read_uint64 ();
o.segments.add (s);
}
o.segments.sort ((a, b) => {
if (a.vmaddr < b.vmaddr)
return -1;
if (a.vmaddr > b.vmaddr)
return 1;
return 0;
});
uint64 image_base = uint64.MAX;
uint64 image_end = 0;
foreach (var seg in o.segments) {
if (seg.name != "__PAGEZERO" && seg.vmaddr < image_base)
image_base = seg.vmaddr;
uint64 seg_end = seg.vmaddr + seg.vmsize;
if (seg_end > image_end)
image_end = seg_end;
}
o.image_base = image_base;
o.image_end = image_end;
return o;
}
private void decode_optional_data (CsSignature sig) throws Error {
if (r.available < 8)
return;
size_t start = r.offset;
uint64 hdr = r.read_uint64 ();
uint32 magic = (uint32) (hdr & 0xffffffffu);
uint32 sel = (uint32) (hdr >> 32);
if (magic != 0x00c0ffeeu) {
r.seek (start);
return;
}
if (sel == 2) {
if (r.available < 0x18)
throw new Error.PROTOCOL ("Optional v2 truncated");
r.skip (0x18);
return;
}
if (sel == 3) {
skip_optional_v3 ();
return;
}
if (sel != 4)
return;
size_t v3_start = r.offset;
uint32 count = skip_optional_v3 ();
size_t table_end = v3_start + 0x38 + (size_t) count * 0x60;
if (table_end + 4 > buf.size)
throw new Error.PROTOCOL ("Optional v4 truncated");
r.seek (table_end);
uint32 strings_size = r.read_uint32 ();
size_t strings_start = r.offset;
size_t strings_end = strings_start + (size_t) strings_size;
if (strings_end > buf.size)
throw new Error.PROTOCOL ("Optional v4 strings overrun");
r.seek (strings_start);
for (int i = 0; i < sig.owners.size; i++) {
if (r.offset >= strings_end)
throw new Error.PROTOCOL ("Optional v4 strings truncated");
sig.owners[i].version = r.read_string ();
}
r.seek (v3_start + 0x3c + (size_t) count * 0x60 + (size_t) strings_size);
}
private uint32 skip_optional_v3 () throws Error {
if (r.available < 0x38)
throw new Error.PROTOCOL ("Optional v3 truncated");
size_t base_offset = r.offset;
r.skip (0x30);
r.read_uint8 ();
r.skip (3);
uint32 count = r.read_uint32 ();
size_t total = 0x38 + (size_t) count * 0x60;
if (base_offset + total > buf.size)
throw new Error.PROTOCOL ("Optional v3 overrun");
r.seek (base_offset + total);
return count;
}
}
}
+2 -2
View File
@@ -50,8 +50,8 @@ namespace Frida.Fruity {
if (rr.key.klass != IN)
throw new Error.PROTOCOL ("Expected an AAAA record of class IN");
var subreader = new DnsPacketReader (rr.data);
unowned uint8[] raw_address = subreader.reader.read_data (16);
var address = new InetAddress.from_bytes (raw_address, IPV6);
var raw_address = subreader.reader.read_bytes (16);
var address = new InetAddress.from_bytes (raw_address.get_data (), IPV6);
return new DnsAaaaRecord () {
key = rr.key,
ttl = rr.ttl,
+30 -787
View File
@@ -69,20 +69,6 @@ namespace Frida.Fruity {
return result;
}
public async CsSignature query_symbolicator_signature (uint pid, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (pid))
.append_object (new NSString (""));
var response = yield channel.invoke ("symbolicatorSignatureForPid:trackingSelector:", args, cancellable);
NSData? data = response as NSData;
if (data == null)
throw new Error.PROTOCOL ("Malformed response");
var parser = new CsSignatureParser (data.bytes);
return parser.parse ();
}
private static string resolve_real_app_name (string name) {
if (name.has_prefix ("/var/"))
return "/private" + name;
@@ -321,8 +307,6 @@ namespace Frida.Fruity {
}
public sealed class ProcessControlService : Object, AsyncInitable {
public signal void process_terminated (uint pid, int exit_code, int crashing_signal);
public HostChannelProvider channel_provider {
get;
construct;
@@ -351,746 +335,15 @@ namespace Frida.Fruity {
var connection = yield DTXConnection.obtain (channel_provider, cancellable);
channel = connection.make_channel ("com.apple.instruments.server.services.processcontrol");
channel.invocation.connect (on_invocation);
return true;
}
public async uint process_identifier_for_bundle_identifier (string bundle_id, Cancellable? cancellable = null)
throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSString (bundle_id));
var response = yield channel.invoke ("processIdentifierForBundleIdentifier:", args, cancellable);
NSNumber? pid = response as NSNumber;
if (pid == null)
throw new Error.PROTOCOL ("Malformed response");
return (uint) pid.integer;
}
public async bool is_pid_debuggable (uint pid, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (pid));
var response = yield channel.invoke ("isPidDebuggable:", args, cancellable);
NSNumber? is_debuggable = response as NSNumber;
if (is_debuggable == null)
throw new Error.PROTOCOL ("Malformed response");
return is_debuggable.boolean;
}
public async void start_observing_pid (uint pid, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (pid));
yield channel.invoke ("startObservingPid:", args, cancellable);
}
public async void stop_observing_pid (uint pid, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (pid));
yield channel.invoke ("stopObservingPid:", args, cancellable);
}
public async uint launch (string bundle_id, LaunchOptions? options = null, Cancellable? cancellable = null)
throws Error, IOError {
var opts = options;
if (opts == null)
opts = new LaunchOptions ();
var args_val = new NSArray ();
foreach (unowned string arg in opts.arguments)
args_val.add_object (new NSString (arg));
var env_val = new NSDictionary ();
foreach (unowned string entry in opts.environment) {
string[] tokens = entry.split ("=", 2);
if (tokens.length != 2)
throw new Error.INVALID_ARGUMENT ("Invalid environment variable entry: %s", entry);
env_val.set_value (tokens[0], new NSString (tokens[1]));
}
var opts_val = new NSDictionary ();
opts_val.set_value ("StartSuspendedKey", new NSNumber.from_boolean (opts.launch_mode == SUSPENDED));
opts_val.set_value ("KillExisting", new NSNumber.from_boolean (opts.existing_instance_policy == KILL));
// TODO: Support CaptureOutput + iODestinationKey
var dtx_args = new DTXArgumentListBuilder ()
.append_object (new NSString (""))
.append_object (new NSString (bundle_id))
.append_object (env_val)
.append_object (args_val)
.append_object (opts_val);
var response = yield channel.invoke (
"launchSuspendedProcessWithDevicePath:bundleIdentifier:environment:arguments:options:",
dtx_args, cancellable);
NSNumber? pid = response as NSNumber;
if (pid == null)
throw new Error.PROTOCOL ("Malformed response");
return (uint) pid.integer;
}
public async void kill (uint pid, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (pid));
yield channel.invoke ("killPid:", args, cancellable);
}
public async void send_signal (uint pid, uint sig, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (sig))
.append_object (new NSNumber.from_integer (pid));
yield channel.invoke ("sendSignal:toPid:", args, cancellable);
}
private void on_invocation (string method_name, DTXArgumentList args, DTXMessageTransportFlags transport_flags) {
if (method_name == "processWithPID:terminatedWithExitCode:orCrashingSignal:") {
if (args.elements.length != 3)
return;
uint pid;
if (!try_parse_int (args.elements[0], out pid))
return;
int exit_code = -1;
int crashing_signal = -1;
if (!try_parse_int (args.elements[1], out exit_code)) {
if (!try_parse_int (args.elements[2], out crashing_signal))
return;
}
process_terminated (pid, exit_code, crashing_signal);
}
}
private bool try_parse_int (Value v, out int i) {
i = -1;
if (!v.holds (typeof (NSNumber)))
return false;
i = (int) ((NSNumber) v.get_object ()).integer;
return true;
}
}
public sealed class LaunchOptions : Object {
public string[] arguments {
get;
set;
default = {};
}
public string[] environment {
get;
set;
default = {};
}
public LaunchMode launch_mode {
get;
set;
default = LaunchMode.NORMAL;
}
public ExistingInstancePolicy existing_instance_policy {
get;
set;
default = ExistingInstancePolicy.KEEP;
}
}
public enum LaunchMode {
NORMAL,
SUSPENDED
}
public enum ExistingInstancePolicy {
KEEP,
KILL
}
public sealed class CoreProfileService : Object, AsyncInitable {
public signal void stackshot (Bytes blob);
public signal void kperfdata (Bytes blob);
public HostChannelProvider channel_provider {
get;
construct;
}
private DTXChannel channel;
private CoreProfileService (HostChannelProvider channel_provider) {
Object (channel_provider: channel_provider);
}
public static async CoreProfileService open (HostChannelProvider channel_provider, Cancellable? cancellable = null)
throws Error, IOError {
var service = new CoreProfileService (channel_provider);
try {
yield service.init_async (Priority.DEFAULT, cancellable);
} catch (GLib.Error e) {
throw_api_error (e);
}
return service;
}
private async bool init_async (int io_priority, Cancellable? cancellable) throws Error, IOError {
var connection = yield DTXConnection.obtain (channel_provider, cancellable);
channel = connection.make_channel ("com.apple.instruments.server.services.coreprofilesessiontap");
channel.notification.connect (on_notification);
channel.data.connect (on_data);
return true;
}
public async void set_config (KtraceConfig config, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (config.encode ());
yield channel.invoke ("setConfig:", args, cancellable);
}
public async void start (Cancellable? cancellable = null) throws Error, IOError {
yield channel.invoke ("start", null, cancellable);
}
public async void stop (Cancellable? cancellable = null) throws Error, IOError {
yield channel.invoke ("stop", null, cancellable);
}
private void on_notification (NSObject obj) {
// printerr ("on_notification(): %s\n", obj.to_string ());
}
private void on_data (Bytes blob) {
if (Kcdata.is_stackshot (blob))
stackshot (blob);
else
kperfdata (blob);
}
}
public abstract class TapConfig : Object {
public TapRecordingMode buffer_mode {
get {
return _buffer_mode;
}
set {
_buffer_mode = value;
if (value != POLLED)
_polling_interval = 0;
}
}
public uint64 polling_interval {
get;
set;
default = 500;
}
public uint64 window_size {
get;
set;
default = 0;
}
public bool spool_to_disk_when_possible {
get;
set;
default = false;
}
public bool discard_heartbeats_when_possible {
get;
set;
default = false;
}
private TapRecordingMode _buffer_mode = POLLED;
internal virtual NSDictionary encode () {
var dict = new NSDictionary ();
dict.set_value ("bm", new NSNumber.from_integer (_buffer_mode));
if (_polling_interval != 0)
dict.set_value ("ur", new NSNumber.from_integer ((int64) _polling_interval));
if (_window_size != 0)
dict.set_value ("ws", new NSNumber.from_integer ((int64) _window_size));
if (_spool_to_disk_when_possible)
dict.set_value ("s2d", new NSNumber.from_boolean (true));
if (_discard_heartbeats_when_possible)
dict.set_value ("nohb", new NSNumber.from_boolean (true));
return dict;
}
}
public enum TapRecordingMode {
POLLED,
IMMEDIATE,
WINDOWED,
}
public sealed class KtraceConfig : TapConfig {
public bool can_use_raw_ktrace_file {
get;
set;
default = false;
}
public KtraceRecordingPriority recording_priority {
get;
set;
default = FOREGROUND;
}
public uint collection_interval {
get;
set;
default = 0;
}
public uint64 buffer_size_override {
get;
set;
default = 0;
}
public uint64 buffer_size_override_clamping {
get;
set;
default = 0;
}
public NSDictionary? provider_options {
get;
set;
default = null;
}
private Gee.List<KtraceTapTriggerConfig> trigger_configs = new Gee.ArrayList<KtraceTapTriggerConfig> ();
public void add_trigger_config (KtraceTapTriggerConfig tc) {
trigger_configs.add (tc);
}
internal override NSDictionary encode () {
var dict = base.encode ();
if (can_use_raw_ktrace_file)
dict.set_value ("curkt", new NSNumber.from_boolean (true));
dict.set_value ("rp", new NSNumber.from_integer (_recording_priority));
if (_collection_interval != 0)
dict.set_value ("kco", new NSNumber.from_integer (_collection_interval));
if (_buffer_size_override != 0)
dict.set_value ("bso", new NSNumber.from_integer ((int64) _buffer_size_override));
if (_buffer_size_override_clamping != 0)
dict.set_value ("bsoc", new NSNumber.from_integer ((int64) _buffer_size_override_clamping));
if (_provider_options != null)
dict.set_value ("po", _provider_options);
var tc = new NSArray ();
foreach (var cfg in trigger_configs)
tc.add_object (cfg.encode ());
dict.set_value ("tc", tc);
return dict;
}
}
public enum KtraceRecordingPriority {
BACKGROUND = 10,
FOREGROUND = 100,
}
public sealed class KtraceTapTriggerConfig : Object {
public KtraceTapTriggerKind kind {
get;
construct;
}
public KdebugCodeSet? filter {
get;
set;
}
public bool is_all_processes {
get {
return included_pids == null;
}
set {
if (value)
included_pids = null;
else
ensure_included_pids ();
}
}
public uint callstack_frame_depth {
get;
set;
default = 0;
}
public KtraceTapActions actions {
get;
default = new KtraceTapActions ();
}
private Gee.Set<uint>? included_pids = null;
public KtraceTapTriggerConfig (KtraceTapTriggerKind kind) {
Object (kind: kind);
}
public void include_pid (uint pid) {
ensure_included_pids ().add (pid);
}
private unowned Gee.Set<uint> ensure_included_pids () {
if (included_pids == null)
included_pids = new Gee.HashSet<uint> ();
return included_pids;
}
internal NSDictionary encode () {
var dict = new NSDictionary ();
dict.set_value ("uuid", new NSString (Uuid.string_random ().up ()));
dict.set_value ("tk", new NSNumber.from_integer (_kind));
if (_filter != null) {
dict.set_value ("kdf", new NSString (_filter.legacy_xml));
dict.set_value ("kdf2", _filter.kdebug_codes);
}
if (included_pids != null) {
var pf = new NSArray ();
foreach (var pid in included_pids)
pf.add_object (new NSNumber.from_integer (pid));
dict.set_value ("pf", pf);
}
if (_callstack_frame_depth != 0)
dict.set_value ("csd", new NSNumber.from_integer (_callstack_frame_depth));
var actions = _actions.items;
if (!actions.is_empty) {
var arr = new NSArray ();
foreach (var action in actions)
arr.add_object (action.encode ());
dict.set_value ("ta", arr);
}
return dict;
}
}
public enum KtraceTapTriggerKind {
TIME = 1,
PMI,
KDEBUG,
}
public sealed class KtraceTapActions : Object {
internal Gee.List<KtraceTapAction> items = new Gee.ArrayList<KtraceTapAction> ();
public unowned KtraceTapActions add (KtraceTapAction action) {
items.add (action);
return this;
}
public unowned KtraceTapActions add_stack_collection (KtraceTapStackCollectionMode mode) {
items.add (new KtraceTapStackCollectionAction (mode));
return this;
}
public unowned KtraceTapActions add_baseline () {
items.add (new KtraceTapAction0 ());
items.add (new KtraceTapAction2 ());
return this;
}
public unowned KtraceTapActions add_pmc_event (string event_name, string counter_name, uint32 extra = 0) {
items.add (new KtraceTapAddPmcEventAction (event_name, counter_name, extra));
return this;
}
public unowned KtraceTapActions add_kdebug_codeset (KdebugCodeSet codeset) {
items.add (new KtraceTapAddKdebugCodeSetAction (codeset.kdebug_codes));
return this;
}
public unowned KtraceTapActions add_kdebug_legacy_backtrace_filter () {
items.add (new KtraceTapKdebugBacktraceFilterAction ());
return this;
}
}
public enum KtraceTapActionKind {
ACTION0,
STACK_COLLECTION,
ACTION2,
KDEBUG_BACKTRACE_FILTER,
ADD_PMC_EVENT,
ADD_KDEBUG_CODESET,
}
public abstract class KtraceTapAction : Object {
public abstract KtraceTapActionKind kind {
get;
}
internal abstract NSArray encode ();
}
public sealed class KtraceTapAction0 : KtraceTapAction {
public override KtraceTapActionKind kind {
get {
return ACTION0;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
return a;
}
}
public sealed class KtraceTapAction2 : KtraceTapAction {
public override KtraceTapActionKind kind {
get {
return ACTION2;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
return a;
}
}
public sealed class KtraceTapStackCollectionAction : KtraceTapAction {
public KtraceTapStackCollectionMode mode {
get {
return _mode;
}
set {
_mode = value;
}
}
private KtraceTapStackCollectionMode _mode;
public KtraceTapStackCollectionAction (KtraceTapStackCollectionMode mode) {
_mode = mode;
}
public override KtraceTapActionKind kind {
get {
return STACK_COLLECTION;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
a.add_object (new NSNumber.from_boolean ((_mode & KtraceTapStackCollectionMode.USER) != 0));
a.add_object (new NSNumber.from_boolean ((_mode & KtraceTapStackCollectionMode.KERNEL) != 0));
return a;
}
}
[Flags]
public enum KtraceTapStackCollectionMode {
NONE = 0,
USER = (1 << 0),
KERNEL = (1 << 1),
}
public sealed class KtraceTapKdebugBacktraceFilterAction : KtraceTapAction {
public override KtraceTapActionKind kind {
get {
return KDEBUG_BACKTRACE_FILTER;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
return a;
}
}
public sealed class KtraceTapAddPmcEventAction : KtraceTapAction {
public string event_name {
get {
return _event_name;
}
set {
_event_name = value;
}
}
public string counter_name {
get {
return _counter_name;
}
set {
_counter_name = value;
}
}
public uint32 extra {
get {
return _extra;
}
set {
_extra = value;
}
}
private string _event_name;
private string _counter_name;
private uint32 _extra;
public KtraceTapAddPmcEventAction (string event_name, string counter_name, uint32 extra = 0) {
_event_name = event_name;
_counter_name = counter_name;
_extra = extra;
}
public override KtraceTapActionKind kind {
get {
return ADD_PMC_EVENT;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
a.add_object (new NSString (_event_name));
a.add_object (new NSString (_counter_name));
a.add_object (new NSNumber.from_integer (_extra));
return a;
}
}
public sealed class KtraceTapAddKdebugCodeSetAction : KtraceTapAction {
public NSSet codes {
get {
return _codes;
}
set {
_codes = value;
}
}
private NSSet _codes;
public KtraceTapAddKdebugCodeSetAction (NSSet codes) {
_codes = codes;
}
public override KtraceTapActionKind kind {
get {
return ADD_KDEBUG_CODESET;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
a.add_object (_codes);
return a;
}
}
public sealed class KdebugCodeSet : Object {
public string legacy_xml {
owned get {
var xml = new StringBuilder.sized (256);
xml.append ("<events>");
foreach (var c in codes) {
var kc = KdebugCode (c);
xml.append ("<event type=\"KDebug\" class=\"");
var klass = kc.klass;
if (klass == ANY)
xml.append_c ('*');
else
xml.append_printf ("%u", klass);
xml.append ("\" subclass=\"");
var subclass = kc.subclass;
if (subclass == KDEBUG_SUBCLASS_ANY)
xml.append_c ('*');
else
xml.append_printf ("%u", subclass);
xml.append ("\" code=\"");
uint code = kc.code;
if (code == KDEBUG_CODE_ANY)
xml.append_c ('*');
else
xml.append_printf ("%u", code);
xml.append ("\"/>");
}
xml.append ("</events>");
return xml.str;
}
}
public NSSet kdebug_codes {
get {
if (_kdebug_codes == null) {
_kdebug_codes = new NSSet ();
foreach (var c in codes)
_kdebug_codes.add_object (new NSNumber.from_integer (c));
}
return _kdebug_codes;
}
}
private Gee.Set<uint> codes = new Gee.HashSet<uint> ();
private NSSet _kdebug_codes = null;
public KdebugCodeSet copy () {
var s = new KdebugCodeSet ();
s.codes.add_all (codes);
s._kdebug_codes = _kdebug_codes;
return s;
}
public unowned KdebugCodeSet add (KdebugCode code) {
codes.add (code.raw);
_kdebug_codes = null;
return this;
}
}
public sealed class DTXConnection : Object, DTXTransport {
@@ -1120,6 +373,7 @@ namespace Frida.Fruity {
private Gee.HashMap<uint32, Gee.ArrayList<Fragment>> fragments = new Gee.HashMap<uint32, Gee.ArrayList<Fragment>> ();
private uint32 next_fragment_identifier = 1;
private size_t total_buffered = 0;
private Gee.ArrayQueue<Bytes> pending_writes = new Gee.ArrayQueue<Bytes> ();
private DTXControlChannel control_channel;
@@ -1127,6 +381,8 @@ namespace Frida.Fruity {
private int32 next_channel_code = 1;
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 = 128 * 1024 * 1024;
private const size_t MAX_FRAGMENT_SIZE = 128 * 1024;
private const string REMOTESERVER_ENDPOINT_17PLUS = "lockdown:com.apple.instruments.dtservicehub";
@@ -1310,6 +566,8 @@ namespace Frida.Fruity {
Gee.ArrayList<Fragment> entries = fragments[fragment.identifier];
if (entries == null) {
if (fragments.size == MAX_BUFFERED_COUNT)
throw new Error.PROTOCOL ("Total buffered count exceeds maximum");
if (fragment.index != 0)
throw new Error.PROTOCOL ("Expected first fragment to have index of zero");
fragment.data_size = 0;
@@ -1327,6 +585,10 @@ namespace Frida.Fruity {
first_fragment.data_size += (uint32) size;
if (first_fragment.data_size > MAX_MESSAGE_SIZE)
throw new Error.PROTOCOL ("Message size exceeds maximum");
total_buffered += size;
if (total_buffered > MAX_BUFFERED_SIZE)
throw new Error.PROTOCOL ("Total buffered size exceeds maximum");
}
if (entries.size == fragment.count) {
@@ -1352,6 +614,7 @@ namespace Frida.Fruity {
}
fragments.unset (fragment.identifier);
total_buffered -= message.length;
process_message (message, first_fragment);
}
@@ -1451,37 +714,33 @@ namespace Frida.Fruity {
message.payload_data = raw_message[payload_start_offset:payload_end_offset];
int32 channel_code = message.channel_code;
if ((message.conversation_index % 2) == 0)
bool is_notification = false;
if (message.type == INVOKE) {
channel_code = -channel_code;
bool is_notification = message.conversation_index == 0;
} else if (message.type == RESULT && channel_code < 0) {
channel_code = -channel_code;
is_notification = true;
}
var channel = channels[channel_code];
if (channel == null)
return;
switch (message.type) {
case DISPATCH:
channel.handle_dispatch (message);
case INVOKE:
channel.handle_invoke (message);
break;
case OK:
case OBJECT:
case RESULT:
case ERROR:
if (is_notification)
channel.handle_notification (message);
else
channel.handle_response (message);
break;
case DATA:
channel.handle_data (message);
break;
case BARRIER:
channel.handle_barrier (message);
break;
case PRIMITIVE:
case COMPRESSED:
case PROXIED_MESSAGE:
throw new Error.PROTOCOL ("Unsupported message type: %s", message.type.to_string ());
}
}
@@ -1596,8 +855,7 @@ namespace Frida.Fruity {
public void notify_of_published_capabilities () throws Error {
var capabilities = new NSDictionary ();
capabilities.set_value ("com.apple.private.DTXConnection", new NSNumber.from_integer (1));
capabilities.set_value ("com.apple.instruments.client.processcontrol.capability.terminationCallback",
new NSNumber.from_integer (1));
capabilities.set_value ("com.apple.private.DTXBlockCompression", new NSNumber.from_integer (2));
var args = new DTXArgumentListBuilder ()
.append_object (capabilities);
@@ -1621,7 +879,6 @@ namespace Frida.Fruity {
public class DTXChannel : Object {
public signal void invocation (string method_name, DTXArgumentList args, DTXMessageTransportFlags transport_flags);
public signal void notification (NSObject obj);
public signal void data (Bytes blob);
public signal void barrier ();
public int32 code {
@@ -1678,7 +935,7 @@ namespace Frida.Fruity {
check_open ();
var message = DTXMessage ();
message.type = DISPATCH;
message.type = INVOKE;
message.channel_code = code;
message.transport_flags = EXPECTS_REPLY;
@@ -1708,7 +965,7 @@ namespace Frida.Fruity {
check_open ();
var message = DTXMessage ();
message.type = DISPATCH;
message.type = INVOKE;
message.channel_code = code;
message.transport_flags = NONE;
@@ -1725,10 +982,10 @@ namespace Frida.Fruity {
transport.send_message (message, out identifier);
}
internal void handle_dispatch (DTXMessage message) throws Error {
internal void handle_invoke (DTXMessage message) throws Error {
NSString? method_name = NSKeyedArchive.decode (message.payload_data) as NSString;
if (method_name == null)
throw new Error.PROTOCOL ("Malformed dispatch payload");
throw new Error.PROTOCOL ("Malformed invocation payload");
var args = DTXArgumentList.parse (message.aux_data);
@@ -1742,7 +999,7 @@ namespace Frida.Fruity {
case OK:
request.resolve (null);
break;
case OBJECT:
case RESULT:
request.resolve (NSKeyedArchive.decode (message.payload_data));
break;
case ERROR: {
@@ -1780,10 +1037,6 @@ namespace Frida.Fruity {
notification (payload);
}
internal void handle_data (DTXMessage message) throws Error {
data (new Bytes (message.payload_data));
}
internal void handle_barrier (DTXMessage message) throws Error {
barrier ();
}
@@ -1800,15 +1053,11 @@ namespace Frida.Fruity {
}
public enum DTXMessageType {
OK,
DATA,
DISPATCH,
OBJECT,
ERROR,
BARRIER,
PRIMITIVE,
COMPRESSED,
PROXIED_MESSAGE,
OK = 0,
INVOKE = 2,
RESULT = 3,
ERROR = 4,
BARRIER = 5
}
public struct DTXMessage {
@@ -1862,12 +1111,6 @@ namespace Frida.Fruity {
}
case BUFFER: {
size_t size = reader.read_uint32 ();
if (size == 0) {
var gval = Value (typeof (NSObject));
elements += (owned) gval;
break;
}
unowned uint8[] buf = reader.read_byte_array (size);
NSObject? obj = NSKeyedArchive.decode (buf);
File diff suppressed because it is too large. Load diff
-558
View File
@@ -1,558 +0,0 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity.Kcdata {
public struct ItemHeader {
public ItemType type;
public uint32 size;
public uint64 flags;
}
public enum ItemType {
INVALID = 0x000u,
STRING_DESC = 0x001u,
UINT32_DESC = 0x002u,
UINT64_DESC = 0x003u,
INT32_DESC = 0x004u,
INT64_DESC = 0x005u,
BINDATA_DESC = 0x006u,
ARRAY = 0x011u,
TYPEDEFINTION = 0x012u,
CONTAINER_BEGIN = 0x013u,
CONTAINER_END = 0x014u,
ARRAY_PAD0 = 0x020u,
ARRAY_PAD1 = 0x021u,
ARRAY_PAD2 = 0x022u,
ARRAY_PAD3 = 0x023u,
ARRAY_PAD4 = 0x024u,
ARRAY_PAD5 = 0x025u,
ARRAY_PAD6 = 0x026u,
ARRAY_PAD7 = 0x027u,
ARRAY_PAD8 = 0x028u,
ARRAY_PAD9 = 0x029u,
ARRAY_PADa = 0x02au,
ARRAY_PADb = 0x02bu,
ARRAY_PADc = 0x02cu,
ARRAY_PADd = 0x02du,
ARRAY_PADe = 0x02eu,
ARRAY_PADf = 0x02fu,
LIBRARY_LOADINFO = 0x030u,
LIBRARY_LOADINFO64 = 0x031u,
TIMEBASE = 0x032u,
MACH_ABSOLUTE_TIME = 0x033u,
TIMEVAL = 0x034u,
USECS_SINCE_EPOCH = 0x035u,
PID = 0x036u,
PROCNAME = 0x037u,
NESTED_KCDATA = 0x038u,
LIBRARY_AOTINFO = 0x039u,
TASK_CRASHINFO_EXTMODINFO = 0x801u,
TASK_CRASHINFO_BSDINFOWITHUNIQID = 0x802u,
TASK_CRASHINFO_TASKDYLD_INFO = 0x803u,
TASK_CRASHINFO_UUID = 0x804u,
TASK_CRASHINFO_PID = 0x805u,
TASK_CRASHINFO_PPID = 0x806u,
TASK_CRASHINFO_RUSAGE = 0x807u,
TASK_CRASHINFO_RUSAGE_INFO = 0x808u,
TASK_CRASHINFO_PROC_NAME = 0x809u,
TASK_CRASHINFO_PROC_STARTTIME = 0x80Bu,
TASK_CRASHINFO_USERSTACK = 0x80Cu,
TASK_CRASHINFO_ARGSLEN = 0x80Du,
TASK_CRASHINFO_EXCEPTION_CODES = 0x80Eu,
TASK_CRASHINFO_PROC_PATH = 0x80Fu,
TASK_CRASHINFO_PROC_CSFLAGS = 0x810u,
TASK_CRASHINFO_PROC_STATUS = 0x811u,
TASK_CRASHINFO_UID = 0x812u,
TASK_CRASHINFO_GID = 0x813u,
TASK_CRASHINFO_PROC_ARGC = 0x814u,
TASK_CRASHINFO_PROC_FLAGS = 0x815u,
TASK_CRASHINFO_CPUTYPE = 0x816u,
TASK_CRASHINFO_WORKQUEUEINFO = 0x817u,
TASK_CRASHINFO_RESPONSIBLE_PID = 0x818u,
TASK_CRASHINFO_DIRTY_FLAGS = 0x819u,
TASK_CRASHINFO_CRASHED_THREADID = 0x81Au,
TASK_CRASHINFO_COALITION_ID = 0x81Bu,
TASK_CRASHINFO_UDATA_PTRS = 0x81Cu,
TASK_CRASHINFO_MEMORY_LIMIT = 0x81Du,
TASK_CRASHINFO_LEDGER_INTERNAL = 0x81Eu,
TASK_CRASHINFO_LEDGER_INTERNAL_COMPRESSED = 0x81Fu,
TASK_CRASHINFO_LEDGER_IOKIT_MAPPED = 0x820u,
TASK_CRASHINFO_LEDGER_ALTERNATE_ACCOUNTING = 0x821u,
TASK_CRASHINFO_LEDGER_ALTERNATE_ACCOUNTING_COMPRESSED = 0x822u,
TASK_CRASHINFO_LEDGER_PURGEABLE_NONVOLATILE = 0x823u,
TASK_CRASHINFO_LEDGER_PURGEABLE_NONVOLATILE_COMPRESSED = 0x824u,
TASK_CRASHINFO_LEDGER_PAGE_TABLE = 0x825u,
TASK_CRASHINFO_LEDGER_PHYS_FOOTPRINT = 0x826u,
TASK_CRASHINFO_LEDGER_PHYS_FOOTPRINT_LIFETIME_MAX = 0x827u,
TASK_CRASHINFO_LEDGER_NETWORK_NONVOLATILE = 0x828u,
TASK_CRASHINFO_LEDGER_NETWORK_NONVOLATILE_COMPRESSED = 0x829u,
TASK_CRASHINFO_LEDGER_WIRED_MEM = 0x82Au,
TASK_CRASHINFO_PROC_PERSONA_ID = 0x82Bu,
TASK_CRASHINFO_MEMORY_LIMIT_INCREASE = 0x82Cu,
TASK_CRASHINFO_LEDGER_TAGGED_FOOTPRINT = 0x82Du,
TASK_CRASHINFO_LEDGER_TAGGED_FOOTPRINT_COMPRESSED = 0x82Eu,
TASK_CRASHINFO_LEDGER_MEDIA_FOOTPRINT = 0x82Fu,
TASK_CRASHINFO_LEDGER_MEDIA_FOOTPRINT_COMPRESSED = 0x830u,
TASK_CRASHINFO_LEDGER_GRAPHICS_FOOTPRINT = 0x831u,
TASK_CRASHINFO_LEDGER_GRAPHICS_FOOTPRINT_COMPRESSED = 0x832u,
TASK_CRASHINFO_LEDGER_NEURAL_FOOTPRINT = 0x833u,
TASK_CRASHINFO_LEDGER_NEURAL_FOOTPRINT_COMPRESSED = 0x834u,
TASK_CRASHINFO_MEMORYSTATUS_EFFECTIVE_PRIORITY = 0x835u,
TASK_CRASHINFO_KERNEL_TRIAGE_INFO_V1 = 0x836u,
TASK_CRASHINFO_TASK_IS_CORPSE_FORK = 0x837u,
TASK_CRASHINFO_EXCEPTION_TYPE = 0x838u,
TASK_CRASHINFO_CRASH_COUNT = 0x839u,
TASK_CRASHINFO_THROTTLE_TIMEOUT = 0x83Au,
TASK_CRASHINFO_CS_SIGNING_ID = 0x83Bu,
TASK_CRASHINFO_CS_TEAM_ID = 0x83Cu,
TASK_CRASHINFO_CS_VALIDATION_CATEGORY = 0x83Du,
TASK_CRASHINFO_CS_TRUST_LEVEL = 0x83Eu,
TASK_CRASHINFO_PROC_CPUTYPE = 0x83Fu,
TASK_CRASHINFO_JIT_ADDRESS_RANGE = 0x840u,
TASK_CRASHINFO_MB = 0x841u,
TASK_CRASHINFO_CS_AUXILIARY_INFO = 0x842u,
TASK_CRASHINFO_RLIM_CORE = 0x843u,
TASK_CRASHINFO_CORE_ALLOWED = 0x844u,
TASK_CRASHINFO_TASK_SECURITY_CONFIG = 0x845u,
STACKSHOT_IOSTATS = 0x901u,
STACKSHOT_GLOBAL_MEM_STATS = 0x902u,
STACKSHOT_CONTAINER_TASK = 0x903u,
STACKSHOT_CONTAINER_THREAD = 0x904u,
STACKSHOT_TASK_SNAPSHOT = 0x905u,
STACKSHOT_THREAD_SNAPSHOT = 0x906u,
STACKSHOT_DONATING_PIDS = 0x907u,
STACKSHOT_SHAREDCACHE_LOADINFO = 0x908u,
STACKSHOT_THREAD_NAME = 0x909u,
STACKSHOT_KERN_STACKFRAME = 0x90Au,
STACKSHOT_KERN_STACKFRAME64 = 0x90Bu,
STACKSHOT_USER_STACKFRAME = 0x90Cu,
STACKSHOT_USER_STACKFRAME64 = 0x90Du,
STACKSHOT_BOOTARGS = 0x90Eu,
STACKSHOT_OSVERSION = 0x90Fu,
STACKSHOT_KERN_PAGE_SIZE = 0x910u,
STACKSHOT_JETSAM_LEVEL = 0x911u,
STACKSHOT_DELTA_SINCE_TIMESTAMP = 0x912u,
STACKSHOT_KERN_STACKLR = 0x913u,
STACKSHOT_KERN_STACKLR64 = 0x914u,
STACKSHOT_USER_STACKLR = 0x915u,
STACKSHOT_USER_STACKLR64 = 0x916u,
STACKSHOT_NONRUNNABLE_TIDS = 0x917u,
STACKSHOT_NONRUNNABLE_TASKS = 0x918u,
STACKSHOT_CPU_TIMES = 0x919u,
STACKSHOT_STACKSHOT_DURATION = 0x91au,
STACKSHOT_STACKSHOT_FAULT_STATS = 0x91bu,
STACKSHOT_KERNELCACHE_LOADINFO = 0x91cu,
STACKSHOT_THREAD_WAITINFO = 0x91du,
STACKSHOT_THREAD_GROUP_SNAPSHOT = 0x91eu,
STACKSHOT_THREAD_GROUP = 0x91fu,
STACKSHOT_JETSAM_COALITION_SNAPSHOT = 0x920u,
STACKSHOT_JETSAM_COALITION = 0x921u,
STACKSHOT_THREAD_POLICY_VERSION = 0x922u,
STACKSHOT_INSTRS_CYCLES = 0x923u,
STACKSHOT_USER_STACKTOP = 0x924u,
STACKSHOT_ASID = 0x925u,
STACKSHOT_PAGE_TABLES = 0x926u,
STACKSHOT_SYS_SHAREDCACHE_LAYOUT = 0x927u,
STACKSHOT_THREAD_DISPATCH_QUEUE_LABEL = 0x928u,
STACKSHOT_THREAD_TURNSTILEINFO = 0x929u,
STACKSHOT_TASK_CPU_ARCHITECTURE = 0x92au,
STACKSHOT_LATENCY_INFO = 0x92bu,
STACKSHOT_LATENCY_INFO_TASK = 0x92cu,
STACKSHOT_LATENCY_INFO_THREAD = 0x92du,
STACKSHOT_LOADINFO64_TEXT_EXEC = 0x92eu,
STACKSHOT_AOTCACHE_LOADINFO = 0x92fu,
STACKSHOT_TRANSITIONING_TASK_SNAPSHOT = 0x930u,
STACKSHOT_CONTAINER_TRANSITIONING_TASK = 0x931u,
STACKSHOT_USER_ASYNC_START_INDEX = 0x932u,
STACKSHOT_USER_ASYNC_STACKLR64 = 0x933u,
STACKSHOT_CONTAINER_PORTLABEL = 0x934u,
STACKSHOT_PORTLABEL = 0x935u,
STACKSHOT_PORTLABEL_NAME = 0x936u,
STACKSHOT_DYLD_COMPACTINFO = 0x937u,
STACKSHOT_SUSPENSION_INFO = 0x938u,
STACKSHOT_SUSPENSION_SOURCE = 0x939u,
STACKSHOT_TASK_DELTA_SNAPSHOT = 0x940u,
STACKSHOT_THREAD_DELTA_SNAPSHOT = 0x941u,
STACKSHOT_CONTAINER_SHAREDCACHE = 0x942u,
STACKSHOT_SHAREDCACHE_INFO = 0x943u,
STACKSHOT_SHAREDCACHE_AOTINFO = 0x944u,
STACKSHOT_SHAREDCACHE_ID = 0x945u,
STACKSHOT_CODESIGNING_INFO = 0x946u,
STACKSHOT_OS_BUILD_VERSION = 0x947u,
STACKSHOT_KERN_EXCLAVES_THREADINFO = 0x948u,
STACKSHOT_CONTAINER_EXCLAVES = 0x949u,
STACKSHOT_CONTAINER_EXCLAVE_SCRESULT = 0x94au,
STACKSHOT_EXCLAVE_SCRESULT_INFO = 0x94bu,
STACKSHOT_CONTAINER_EXCLAVE_IPCSTACKENTRY = 0x94cu,
STACKSHOT_EXCLAVE_IPCSTACKENTRY_INFO = 0x94du,
STACKSHOT_EXCLAVE_IPCSTACKENTRY_ECSTACK = 0x94eu,
STACKSHOT_CONTAINER_EXCLAVE_ADDRESSSPACE = 0x94fu,
STACKSHOT_EXCLAVE_ADDRESSSPACE_INFO = 0x950u,
STACKSHOT_EXCLAVE_ADDRESSSPACE_NAME = 0x951u,
STACKSHOT_CONTAINER_EXCLAVE_TEXTLAYOUT = 0x952u,
STACKSHOT_EXCLAVE_TEXTLAYOUT_INFO = 0x953u,
STACKSHOT_EXCLAVE_TEXTLAYOUT_SEGMENTS = 0x954u,
STACKSHOT_KERN_EXCLAVES_CRASH_THREADINFO = 0x955u,
STACKSHOT_LATENCY_INFO_CPU = 0x956u,
STACKSHOT_TASK_EXEC_META = 0x957u,
STACKSHOT_TASK_MEMORYSTATUS = 0x958u,
STACKSHOT_LATENCY_INFO_BUFFER = 0x95au,
TASK_BTINFO_PID = 0xA01u,
TASK_BTINFO_PPID = 0xA02u,
TASK_BTINFO_PROC_NAME = 0xA03u,
TASK_BTINFO_PROC_PATH = 0xA04u,
TASK_BTINFO_UID = 0xA05u,
TASK_BTINFO_GID = 0xA06u,
TASK_BTINFO_PROC_FLAGS = 0xA07u,
TASK_BTINFO_CPUTYPE = 0xA08u,
TASK_BTINFO_EXCEPTION_CODES = 0xA09u,
TASK_BTINFO_EXCEPTION_TYPE = 0xA0Au,
TASK_BTINFO_RUSAGE_INFO = 0xA0Bu,
TASK_BTINFO_COALITION_ID = 0xA0Cu,
TASK_BTINFO_CRASH_COUNT = 0xA0Du,
TASK_BTINFO_THROTTLE_TIMEOUT = 0xA0Eu,
TASK_BTINFO_THREAD_ID = 0xA20u,
TASK_BTINFO_THREAD_NAME = 0xA21u,
TASK_BTINFO_THREAD_STATE = 0xA22u,
TASK_BTINFO_THREAD_EXCEPTION_STATE = 0xA23u,
TASK_BTINFO_BACKTRACE = 0xA24u,
TASK_BTINFO_BACKTRACE64 = 0xA25u,
TASK_BTINFO_ASYNC_BACKTRACE64 = 0xA26u,
TASK_BTINFO_ASYNC_START_INDEX = 0xA27u,
TASK_BTINFO_PLATFORM = 0xA28u,
TASK_BTINFO_SC_LOADINFO = 0xA29u,
TASK_BTINFO_SC_LOADINFO64 = 0xA2Au,
TASK_BTINFO_FLAGS = 0xAFFu,
BUFFER_BEGIN_XNUPOST_CONFIG = 0x1e21c09fu,
BUFFER_BEGIN_COMPRESSED = 0x434f4d50u,
BUFFER_BEGIN_BTINFO = 0x46414E47u,
BUFFER_BEGIN_STACKSHOT = 0x59a25807u,
BUFFER_BEGIN_OS_REASON = 0x53A20900u,
BUFFER_BEGIN_DELTA_STACKSHOT = 0xDE17A59Au,
BUFFER_BEGIN_CRASHINFO = 0xDEADF157u,
BUFFER_END = 0xF19158EDu;
public string to_nick () {
return Marshal.enum_to_nick<ItemType> (this);
}
}
[Flags]
public enum StackshotFlagsLow {
GET_DQ = (1U << 0),
SAVE_LOADINFO = (1U << 1),
GET_GLOBAL_MEM_STATS = (1U << 2),
SAVE_KEXT_LOADINFO = (1U << 3),
ACTIVE_KERNEL_THREADS_ONLY = (1U << 8),
GET_BOOT_PROFILE = (1U << 9),
DO_COMPRESS = (1U << 10),
SAVE_IMP_DONATION_PIDS = (1U << 13),
SAVE_IN_KERNEL_BUFFER = (1U << 14),
RETRIEVE_EXISTING_BUFFER = (1U << 15),
KCDATA_FORMAT = (1U << 16),
ENABLE_BT_FAULTING = (1U << 17),
COLLECT_DELTA_SNAPSHOT = (1U << 18),
COLLECT_SHAREDCACHE_LAYOUT = (1U << 19),
TRYLOCK = (1U << 20),
ENABLE_UUID_FAULTING = (1U << 21),
FROM_PANIC = (1U << 22),
NO_IO_STATS = (1U << 23),
THREAD_WAITINFO = (1U << 24),
THREAD_GROUP = (1U << 25),
SAVE_JETSAM_COALITIONS = (1U << 26),
INSTRS_CYCLES = (1U << 27),
ASID = (1U << 28),
PAGE_TABLES = (1U << 29),
DISABLE_LATENCY_INFO = (1U << 30),
SAVE_DYLD_COMPACTINFO = (1U << 31)
}
[Flags]
public enum StackshotFlagsHigh {
INCLUDE_DRIVER_THREADS_IN_KERNEL = (1U << 0),
EXCLAVES = (1U << 1),
SKIP_EXCLAVES = (1U << 2),
}
public const size_t TASK_SNAPSHOT_PID_OFFSET = 84;
public static bool is_stackshot (Bytes bytes) {
if (bytes.get_size () < 16)
return false;
var type = (ItemType) uint32.from_little_endian (*((uint32 *) bytes.get_data ()));
switch (type) {
case ItemType.BUFFER_BEGIN_STACKSHOT:
case ItemType.BUFFER_BEGIN_DELTA_STACKSHOT:
case ItemType.BUFFER_BEGIN_COMPRESSED:
return true;
default:
return false;
}
}
public sealed class Reader : Object {
private Buffer buf;
private BufferReader r;
private Buffer payload_buf;
private BufferReader payload_r;
private BufferReader scan_r;
private Array<uint64> scan_container_ids = new Array<uint64> ();
[Compact]
private struct Scope {
public size_t end_item_offset;
public uint64 end_id;
}
private Array<Scope> scopes = new Array<Scope> ();
private size_t current_end_item_offset;
private const size_t HEADER_SIZE = 16;
private const size_t ALIGNMENT_SIZE = 16;
public Reader (Bytes bytes) {
buf = new Buffer (bytes, LITTLE_ENDIAN);
r = new BufferReader (buf);
payload_buf = new Buffer.from_data ((uint8[]) null, buf.byte_order, buf.pointer_size);
payload_r = new BufferReader (payload_buf);
scan_r = new BufferReader (buf);
current_end_item_offset = buf.bytes.get_size ();
}
public enum VisitResult {
CONTINUE,
STOP
}
public VisitResult for_each (ItemVisitor visitor) throws Error {
ItemHeader h;
unowned BufferReader p;
while (read_item (out h, out p)) {
if (visitor (h, p) == VisitResult.STOP)
return VisitResult.STOP;
}
return VisitResult.CONTINUE;
}
public delegate VisitResult ItemVisitor (ItemHeader h, BufferReader payload) throws Error;
public VisitResult for_each_container (ItemType want_container_type, ScopeVisitor visitor) throws Error {
ItemHeader h;
unowned BufferReader p;
while (read_item (out h, out p)) {
if (h.type != ItemType.CONTAINER_BEGIN)
continue;
var ctype = (ItemType) p.read_uint32 ();
var id = h.flags;
if (ctype != want_container_type) {
skip_container_body (id);
continue;
}
enter_container_body (id);
var result = visitor (this);
leave_container ();
if (result == VisitResult.STOP)
return VisitResult.STOP;
}
return VisitResult.CONTINUE;
}
public delegate VisitResult ScopeVisitor (Reader r) throws Error;
public unowned BufferReader get_first (ItemType type) throws Error {
unowned BufferReader result = null;
for_each ((h, p) => {
if (h.type != type)
return VisitResult.CONTINUE;
result = p;
return VisitResult.STOP;
});
if (result == null)
throw new Error.PROTOCOL ("Missing item: %s", type.to_nick ());
return result;
}
private bool read_item (out ItemHeader h, out unowned BufferReader payload) throws Error {
if (r.available == 0 || r.offset == current_end_item_offset) {
h = ItemHeader ();
payload = null;
return false;
}
h = read_header ();
payload = read_payload (h);
return true;
}
private ItemHeader read_header () throws Error {
if (r.available < HEADER_SIZE)
throw new Error.PROTOCOL ("KCDATA truncated at %zu (need header, avail=%zu)", r.offset, r.available);
var item_start = r.offset;
var h = read_item_header_fields (r);
var avail_payload = current_end_item_offset - r.offset;
var avail = size_t.min (r.available, avail_payload);
if (h.size > avail) {
throw new Error.PROTOCOL ("KCDATA truncated at %zu (type=0x%x size=%u avail=%zu)", item_start,
(uint32) h.type, h.size, avail);
}
return h;
}
private unowned BufferReader read_payload (ItemHeader h) throws Error {
unowned uint8[] payload = r.read_data (h.size);
payload_buf.reset_data (payload);
payload_r.reset (payload_buf);
r.align (ALIGNMENT_SIZE);
return payload_r;
}
private void enter_container_body (uint64 id) throws Error {
var body_start = r.offset;
size_t end_item_offset;
find_container_end (body_start, id, out end_item_offset);
var s = Scope ();
s.end_item_offset = end_item_offset;
s.end_id = id;
scopes.append_val (s);
current_end_item_offset = end_item_offset;
}
private void leave_container () throws Error {
var s = scopes.index (scopes.length - 1);
scopes.set_size (scopes.length - 1);
consume_container_end_at (s.end_item_offset, s.end_id);
if (scopes.length == 0)
current_end_item_offset = buf.bytes.get_size ();
else {
var parent = scopes.index (scopes.length - 1);
current_end_item_offset = parent.end_item_offset;
}
}
private void skip_container_body (uint64 id) throws Error {
var body_start = r.offset;
size_t end_item_offset;
find_container_end (body_start, id, out end_item_offset);
consume_container_end_at (end_item_offset, id);
}
private void consume_container_end_at (size_t end_item_offset, uint64 id) throws Error {
if (r.offset != end_item_offset)
r.seek (end_item_offset);
if (r.available < HEADER_SIZE)
throw new Error.PROTOCOL ("KCDATA truncated at %zu (need header, avail=%zu)", r.offset, r.available);
var item_start = r.offset;
var h = read_item_header_fields (r);
if (h.type != ItemType.CONTAINER_END || h.flags != id) {
throw new Error.PROTOCOL ("Malformed container end at %zu (want id=0x%016" + uint64.FORMAT_MODIFIER + "x)",
item_start, id);
}
if (h.size > r.available) {
throw new Error.PROTOCOL ("KCDATA truncated at %zu (type=0x%x size=%u avail=%zu)", item_start,
(uint32) h.type, h.size, r.available);
}
r.skip (h.size);
r.align (ALIGNMENT_SIZE);
}
private void find_container_end (size_t body_start, uint64 id, out size_t end_item_offset) throws Error {
scan_container_ids.set_size (0);
scan_r.seek (body_start);
while (true) {
if (scan_r.available < HEADER_SIZE) {
throw new Error.PROTOCOL ("KCDATA truncated at %zu (need header, avail=%zu)",
scan_r.offset, scan_r.available);
}
var item_start = scan_r.offset;
var h = read_item_header_fields (scan_r);
if (h.size > scan_r.available) {
throw new Error.PROTOCOL ("KCDATA truncated at %zu (type=0x%x size=%u avail=%zu)", item_start,
(uint32) h.type, h.size, scan_r.available);
}
scan_r.skip (h.size);
scan_r.align (ALIGNMENT_SIZE);
if (h.type == ItemType.CONTAINER_BEGIN) {
scan_container_ids.append_val (h.flags);
continue;
}
if (h.type == ItemType.CONTAINER_END) {
if (scan_container_ids.length != 0) {
var top = scan_container_ids.remove_index (scan_container_ids.length - 1);
if (top != h.flags) {
throw new Error.PROTOCOL ("Malformed container nesting at %zu (id=0x%016" +
uint64.FORMAT_MODIFIER + "x)", item_start, h.flags);
}
} else {
if (h.flags != id) {
throw new Error.PROTOCOL ("Malformed container end at %zu (id=0x%016" +
uint64.FORMAT_MODIFIER + "x)", item_start, h.flags);
}
end_item_offset = item_start;
return;
}
}
}
}
private ItemHeader read_item_header_fields (BufferReader r) throws Error {
var h = ItemHeader ();
h.type = (ItemType) r.read_uint32 ();
h.size = r.read_uint32 ();
h.flags = r.read_uint64 ();
return h;
}
}
}
-220
View File
@@ -1,220 +0,0 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public enum KdebugClass {
MACH = 1,
FSYSTEM = 3,
BSD = 4,
TRACE = 7,
DYLD = 31,
PERF = 37,
ANY = 0xff;
public string to_nick () {
return Marshal.enum_to_nick<KdebugClass> (this);
}
}
public enum KdebugMachSubclass {
EXCP_SC = 12,
}
public enum KdebugFsystemSubclass {
FSRW = 1,
DKRW,
FSVN,
FSLOOOKUP,
JOURNAL,
IOCTL,
BOOTCACHE,
HFS,
APFS,
SMB,
MOUNT,
EXFAT = 14,
MSDOS,
ACFS,
THROTTLE,
DECMP,
VFS,
LIVEFS,
NFS;
public string to_nick () {
return Marshal.enum_to_nick<KdebugFsystemSubclass> (this);
}
}
public enum KdebugFsystemFsrwEvent {
LOOKUP = 36,
LOOKUP_DONE = 39;
public string to_nick () {
return Marshal.enum_to_nick<KdebugFsystemFsrwEvent> (this);
}
}
public enum KdebugBsdSubclass {
EXCP_SC = 12,
}
public enum KdebugTraceSubclass {
DATA,
STRING,
INFO;
public string to_nick () {
return Marshal.enum_to_nick<KdebugTraceSubclass> (this);
}
}
public enum KdebugTraceDataEvent {
NEWTHREAD = 1,
EXEC,
THREAD_TERMINATE,
THREAD_TERMINATE_PID;
public string to_nick () {
return Marshal.enum_to_nick<KdebugTraceDataEvent> (this);
}
}
public enum KdebugTraceStringEvent {
GLOBAL,
NEWTHREAD,
EXEC,
PROC_EXIT,
THREADNAME,
THREADNAME_PREV;
public string to_nick () {
return Marshal.enum_to_nick<KdebugTraceStringEvent> (this);
}
}
public enum KdebugDyldSubclass {
UUID = 5,
}
public enum KdebugDyldUuidEvent {
MAP_A,
MAP_B,
MAP_32_A,
MAP_32_B,
MAP_32_C,
UNMAP_A,
UNMAP_B,
UNMAP_32_A,
UNMAP_32_B,
UNMAP_32_C,
SHARED_CACHE_A,
SHARED_CACHE_B,
SHARED_CACHE_32_A,
SHARED_CACHE_32_B,
SHARED_CACHE_32_C,
AOT_MAP_A,
AOT_MAP_B;
public string to_nick () {
return Marshal.enum_to_nick<KdebugDyldUuidEvent> (this);
}
}
public enum KdebugPerfSubclass {
GENERIC,
THREADINFO,
CALLSTACK,
TIMER,
PET,
AST,
KPC,
KDBG,
TASK,
LAZY,
MEMINFO;
public string to_nick () {
return Marshal.enum_to_nick<KdebugPerfSubclass> (this);
}
}
public enum KdebugPerfCallstackEvent {
KSAMPLE,
UPEND,
USAMPLE,
KDATA,
UDATA,
KHDR,
UHDR,
ERROR,
BACKTRACE,
LOG,
EXHDR,
EXDATA,
EXSTACKHDR,
EXSTACK,
KEXOFFSET;
public string to_nick () {
return Marshal.enum_to_nick<KdebugPerfCallstackEvent> (this);
}
}
public const uint8 KDEBUG_SUBCLASS_ANY = 0xff;
public const uint16 KDEBUG_CODE_ANY = 0x3fff;
public enum KdebugFunctionQualifier {
NONE,
START,
END;
public string to_nick () {
return Marshal.enum_to_nick<KdebugFunctionQualifier> (this);
}
}
public struct KdebugCode {
public uint32 raw;
public KdebugCode (uint32 raw) {
this.raw = raw;
}
public KdebugCode.from_parts (
KdebugClass klass,
uint8 subclass = KDEBUG_SUBCLASS_ANY,
uint16 code = KDEBUG_CODE_ANY,
KdebugFunctionQualifier func_qual = NONE) {
raw =
(((uint32) klass & 0xff) << 24) |
(((uint32) subclass & 0xff) << 16) |
(((uint32) code & 0x3fff) << 2) |
((uint32) func_qual & 0x3);
}
public KdebugClass klass {
get {
return (KdebugClass) ((raw >> 24) & 0xff);
}
}
public uint8 subclass {
get {
return (uint8) ((raw >> 16) & 0xff);
}
}
public uint16 code {
get {
return (uint16) ((raw >> 2) & 0x3fff);
}
}
public KdebugFunctionQualifier func_qual {
get {
return (KdebugFunctionQualifier) (raw & 0x3);
}
}
}
}
+8 -190
View File
@@ -9,20 +9,8 @@ namespace Frida.Fruity {
return other == this;
}
public string to_string (uint level = 0) {
var s = new StringBuilder.sized (256);
append_indent (s, level);
append_content (s, level);
return s.str;
}
protected virtual void append_content (StringBuilder s, uint level) {
s.append ("NSObject {}");
}
protected void append_indent (StringBuilder s, uint level) {
for (uint i = 0; i != level; i++)
s.append (" ");
public virtual string to_string () {
return "NSObject";
}
public static uint hash_func (NSObject val) {
@@ -115,19 +103,8 @@ namespace Frida.Fruity {
return false;
}
protected override void append_content (StringBuilder s, uint level) {
switch (kind) {
case BOOLEAN:
s.append (boolean ? "true" : "false");
break;
case INTEGER:
s.append_printf ("%" + int64.FORMAT, integer);
break;
case FLOAT:
case DOUBLE:
s.append_printf ("%f", number);
break;
}
public override string to_string () {
return integer.to_string ();
}
}
@@ -152,11 +129,8 @@ namespace Frida.Fruity {
return other_string.str == str;
}
protected override void append_content (StringBuilder s, uint level) {
s
.append_c ('"')
.append (str.replace ("\"", "\\\""))
.append_c ('"');
public override string to_string () {
return str;
}
}
@@ -181,8 +155,8 @@ namespace Frida.Fruity {
return other_data.bytes.compare (bytes) == 0;
}
protected override void append_content (StringBuilder s, uint level) {
s.append_printf ("NSData { size = %" + size_t.FORMAT + " }", bytes.get_size ());
public override string to_string () {
return "NSData";
}
}
@@ -245,25 +219,6 @@ namespace Frida.Fruity {
public void set_value (string key, NSObject val) {
storage[key] = val;
}
protected override void append_content (StringBuilder s, uint level) {
if (storage.size == 0) {
s.append ("{}");
return;
}
s.append ("{\n");
foreach (var e in entries) {
append_indent (s, level + 1);
s
.append (e.key)
.append (": ");
e.value.append_content (s, level + 1);
s.append (",\n");
}
append_indent (s, level);
s.append_c ('}');
}
}
public sealed class NSDictionaryRaw : NSObject {
@@ -298,24 +253,6 @@ namespace Frida.Fruity {
? storage
: new Gee.HashMap<NSObject, NSObject> (NSObject.hash_func, NSObject.equal_func);
}
protected override void append_content (StringBuilder s, uint level) {
if (storage.size == 0) {
s.append ("{}");
return;
}
s.append ("{\n");
foreach (var e in entries) {
append_indent (s, level + 1);
e.key.append_content (s, level + 1);
s.append (": ");
e.value.append_content (s, level + 1);
s.append (",\n");
}
append_indent (s, level);
s.append_c ('}');
}
}
public sealed class NSArray : NSObject {
@@ -340,56 +277,6 @@ namespace Frida.Fruity {
public void add_object (NSObject obj) {
storage.add (obj);
}
protected override void append_content (StringBuilder s, uint level) {
if (storage.size == 0) {
s.append ("[]");
return;
}
s.append ("[\n");
foreach (var e in elements) {
append_indent (s, level + 1);
e.append_content (s, level + 1);
s.append (",\n");
}
append_indent (s, level);
s.append_c (']');
}
}
public sealed class NSSet : NSObject {
public Gee.Iterable<NSObject> items {
owned get {
return storage;
}
}
private Gee.HashSet<NSObject> storage;
public NSSet (Gee.HashSet<NSObject>? storage = null) {
this.storage = (storage != null) ? storage : new Gee.HashSet<NSObject> (NSObject.hash_func);
}
public void add_object (NSObject obj) {
storage.add (obj);
}
protected override void append_content (StringBuilder s, uint level) {
if (storage.size == 0) {
s.append ("{}");
return;
}
s.append ("{\n");
foreach (var e in items) {
append_indent (s, level + 1);
e.append_content (s, level + 1);
s.append (",\n");
}
append_indent (s, level);
s.append_c ('}');
}
}
public sealed class NSDate : NSObject {
@@ -409,10 +296,6 @@ namespace Frida.Fruity {
return new DateTime.from_unix_utc (MAC_EPOCH_DELTA_FROM_UNIX + whole_seconds)
.add_seconds (time - (double) whole_seconds);
}
protected override void append_content (StringBuilder s, uint level) {
s.append_printf ("NSDate { time = %f }", time);
}
}
public sealed class NSError : NSObject {
@@ -436,35 +319,6 @@ namespace Frida.Fruity {
this.code = code;
this.user_info = user_info;
}
protected override void append_content (StringBuilder s, uint level) {
s.append ("NSError { domain = ");
domain.append_content (s, level);
s.append_printf (", code = %" + uint64.FORMAT_MODIFIER + "d, user_info = ", code);
if (user_info.size == 0) {
user_info.append_content (s, level);
s.append (" }");
return;
}
s.append ("{\n");
append_indent (s, level + 1);
s.append ("domain: ");
domain.append_content (s, level + 1);
s.append (",\n");
append_indent (s, level + 1);
s.append_printf ("code: %" + uint64.FORMAT_MODIFIER + "d,\n", code);
append_indent (s, level + 1);
s.append ("user_info: ");
user_info.append_content (s, level + 1);
s.append_c ('\n');
append_indent (s, level);
s.append_c ('}');
}
}
public sealed class DTTapMessage : NSObject {
@@ -476,25 +330,6 @@ namespace Frida.Fruity {
public DTTapMessage (NSDictionary plist) {
this.plist = plist;
}
protected override void append_content (StringBuilder s, uint level) {
if (plist.size == 0) {
s.append ("DTTapMessage { plist: ");
plist.append_content (s, level);
s.append (" }");
return;
}
s.append ("DTTapMessage {\n");
append_indent (s, level + 1);
s.append ("plist: ");
plist.append_content (s, level + 1);
s.append_c ('\n');
append_indent (s, level);
s.append_c ('}');
}
}
namespace NSKeyedArchive {
@@ -503,7 +338,6 @@ namespace Frida.Fruity {
private const string[] DICTIONARY_CLASS = { "NSDictionary", "NSObject" };
private const string[] ARRAY_CLASS = { "NSArray", "NSObject" };
private const string[] SET_CLASS = { "NSSet", "NSObject" };
[CCode (has_target = false)]
private delegate PlistUid EncodeFunc (NSObject instance, EncodingContext ctx);
@@ -621,7 +455,6 @@ namespace Frida.Fruity {
encoders[typeof (NSString)] = encode_string;
encoders[typeof (NSDictionary)] = encode_dictionary;
encoders[typeof (NSArray)] = encode_array;
encoders[typeof (NSSet)] = encode_set;
}
private static void ensure_decoders_registered () {
@@ -786,21 +619,6 @@ namespace Frida.Fruity {
return uid;
}
private static PlistUid encode_set (NSObject instance, EncodingContext ctx) {
NSSet set = (NSSet) instance;
var object = new PlistDict ();
var uid = ctx.add_object (object);
var objs = new PlistArray ();
foreach (var element in set.items)
objs.add_uid (encode_value (element, ctx));
object.set_array ("NS.objects", objs);
object.set_uid ("$class", ctx.get_class (SET_CLASS));
return uid;
}
private static NSObject decode_array (PlistDict instance, DecodingContext ctx) throws Error, PlistError {
var objs = instance.get_array ("NS.objects");
-180
View File
@@ -1,180 +0,0 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public delegate void KperfdataRecordVisitor (KdBuf rec) throws Error;
public sealed class KperfdataStreamParser : Object {
private ByteArray stash = new ByteArray ();
private size_t cursor = 0;
private bool have_header = false;
private uint32 thread_count = 0;
private size_t records_offset = 0;
private const uint32 RAW_VERSION2 = 0x55aa0200u;
private const size_t HEADER_FIXED_SIZE = 0x120;
private const size_t THREADMAP_ENTRY_SIZE = 0x20;
private const size_t PAGE_SIZE = 0x1000;
private const size_t KD_BUF_SIZE = 0x40;
public void reset () {
stash.set_size (0);
cursor = 0;
have_header = false;
thread_count = 0;
records_offset = 0;
}
public void push (Bytes chunk, KperfdataRecordVisitor visitor) throws Error {
stash.append (chunk.get_data ());
var stash_bytes = new Bytes.static (stash.data);
parse_bytes (stash_bytes, visitor);
compact ();
}
private void parse_bytes (Bytes bytes, KperfdataRecordVisitor visitor) throws Error {
var buf = new Frida.Buffer (bytes, LITTLE_ENDIAN);
var r = new Frida.BufferReader (buf);
while (true) {
if (!have_header) {
if (r.available < 8)
return;
size_t header_start = r.offset;
uint32 magic = r.read_uint32 ();
if (magic != RAW_VERSION2)
throw new Error.PROTOCOL ("Unknown kperfdata magic 0x%x", magic);
thread_count = r.read_uint32 ();
uint64 threadmaps_size_64 = thread_count * THREADMAP_ENTRY_SIZE;
size_t header_size = (size_t) (HEADER_FIXED_SIZE + threadmaps_size_64);
size_t aligned = align_up (header_size, PAGE_SIZE);
records_offset = aligned;
if ((r.offset - 8) != header_start)
throw new Error.PROTOCOL ("Internal offset bookkeeping error");
if ((stash.len - header_start) < records_offset) {
r.skip (header_start - r.offset);
return;
}
cursor = header_start + records_offset;
have_header = true;
r.skip (cursor - r.offset);
continue;
}
if (r.offset < cursor) {
if ((cursor - r.offset) > r.available)
return;
r.skip (cursor - r.offset);
}
if (r.available < KD_BUF_SIZE)
return;
KdBuf rec = KdBuf ();
rec.timestamp = r.read_uint64 ();
rec.arg1 = r.read_uint64 ();
rec.arg2 = r.read_uint64 ();
rec.arg3 = r.read_uint64 ();
rec.arg4 = r.read_uint64 ();
rec.arg5 = r.read_uint64 ();
rec.debugid = r.read_uint32 ();
rec.cpuid = r.read_uint32 ();
rec.unused = r.read_uint64 ();
visitor (rec);
cursor = r.offset;
}
}
private void compact () {
if (cursor == 0)
return;
if (cursor >= stash.len) {
stash.set_size (0);
cursor = 0;
return;
}
size_t remaining = stash.len - cursor;
Memory.move (stash.data, (uint8 *) stash.data + cursor, remaining);
stash.set_size ((uint) remaining);
cursor = 0;
}
private static size_t align_up (size_t val, size_t alignment) {
size_t mask = alignment - 1;
return (val + mask) & ~mask;
}
}
public struct KdBuf {
public uint64 timestamp;
public uint64 arg1;
public uint64 arg2;
public uint64 arg3;
public uint64 arg4;
public uint64 arg5;
public uint32 debugid;
public uint32 cpuid;
public uint64 unused;
public KdebugCode kcode {
get {
return KdebugCode (debugid);
}
}
public string to_string () {
var kc = kcode;
return (
"ts=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "arg1=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "arg2=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "arg3=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "arg4=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "arg5=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "debugid=0x%08x "
+ "klass=%s subclass=%u code=%u func=%s "
+ "cpuid=%u "
+ "unused=0x%" + uint64.FORMAT_MODIFIER + "x"
).printf (
timestamp,
arg1,
arg2,
arg3,
arg4,
arg5,
debugid,
kc.klass.to_nick (),
kc.subclass,
kc.code,
kc.func_qual.to_nick (),
cpuid,
unused
);
}
}
}
+29 -19
View File
@@ -36,6 +36,8 @@ namespace Frida.Fruity {
private uint16 ndp_fixed_header_size;
private VirtualNetworkStack? _netstack;
private Gee.Queue<Bytes> pending_input = new Gee.ArrayQueue<Bytes> ();
private bool input_flush_scheduled = false;
private Gee.Queue<Bytes> pending_output = new Gee.ArrayQueue<Bytes> ();
private size_t out_in_flight_count = 0;
private size_t out_in_flight_bytes = 0;
@@ -182,20 +184,8 @@ namespace Frida.Fruity {
}
try {
var datagrams = new Gee.ArrayList<Bytes> ();
while (true) {
var request = pending.peek ();
if (request == null)
break;
if (!datagrams.is_empty && !request.future.ready)
break;
var frame = yield pending.poll ().future.wait_async (io_cancellable);
datagrams.add_all (handle_ncm_frame (frame));
}
yield _netstack.handle_incoming_datagrams (datagrams);
var frame = yield pending.poll ().future.wait_async (io_cancellable);
handle_ncm_frame (frame);
} catch (GLib.Error e) {
return;
}
@@ -218,7 +208,7 @@ namespace Frida.Fruity {
}
}
private Gee.List<Bytes> handle_ncm_frame (Bytes frame) throws GLib.Error {
private void handle_ncm_frame (Bytes frame) throws GLib.Error {
var input = new DataInputStream (new MemoryInputStream.from_bytes (frame));
input.byte_order = LITTLE_ENDIAN;
@@ -232,8 +222,6 @@ namespace Frida.Fruity {
input.skip (6);
var ndp_index = input.read_uint16 ();
var datagrams = new Gee.ArrayList<Bytes> ();
do {
input.seek (ndp_index, SET);
input.read_all (raw_signature[:4], out bytes_read);
@@ -262,13 +250,35 @@ namespace Frida.Fruity {
notify_property ("remote-ipv6-address");
}
datagrams.add (datagram);
on_incoming_datagram (datagram);
}
ndp_index = next_ndp_index;
} while (ndp_index != 0);
}
return datagrams;
private void on_incoming_datagram (Bytes datagram) {
pending_input.offer (datagram);
if (!input_flush_scheduled) {
var source = new IdleSource ();
source.set_callback (() => {
input_flush_scheduled = false;
flush_pending_input ();
return Source.REMOVE;
});
source.attach (MainContext.get_thread_default ());
input_flush_scheduled = true;
}
}
private void flush_pending_input () {
var datagrams = pending_input;
pending_input = new Gee.ArrayQueue<Bytes> ();
try {
_netstack.handle_incoming_datagrams (datagrams);
} catch (Error e) {
}
}
private void on_netif_outgoing_datagrams (Gee.Collection<Bytes> datagrams) {
+6 -21
View File
@@ -283,14 +283,14 @@ namespace Frida.Fruity {
return new Ipv6UdpSocket (this);
}
public async void handle_incoming_datagrams (Gee.Collection<Bytes> datagrams) throws Error {
LWIP.ErrorCode err = OK;
public void handle_incoming_datagrams (Gee.Collection<Bytes> datagrams) throws Error {
check_started ();
schedule_on_lwip_thread (() => {
check (perform_on_lwip_thread (() => {
begin_output ();
LWIP.ErrorCode err = OK;
foreach (var d in datagrams) {
var pbuf = LWIP.PacketBuffer.alloc (RAW, (uint16) d.get_size (), POOL);
pbuf.take (d.get_data ());
@@ -304,14 +304,8 @@ namespace Frida.Fruity {
end_output ();
schedule_on_frida_thread (handle_incoming_datagrams.callback);
return err;
});
yield;
check (err);
}));
}
private static LWIP.ErrorCode on_netif_link_output (LWIP.NetworkInterface handle, LWIP.PacketBuffer pbuf) {
@@ -365,15 +359,6 @@ namespace Frida.Fruity {
}
internal LWIP.ErrorCode perform_on_lwip_thread (owned WorkFunc work) {
var req = submit_work ((owned) work);
return req.join ();
}
internal void schedule_on_lwip_thread (owned WorkFunc work) {
submit_work ((owned) work);
}
private Request submit_work (owned WorkFunc work) {
var req = new Request ((owned) work);
if (Thread.self<bool> () == lwip_thread) {
@@ -384,7 +369,7 @@ namespace Frida.Fruity {
LWIP.Runtime.schedule (perform_next_request);
}
return req;
return req.join ();
}
private void perform_next_request () {
+41 -51
View File
@@ -2044,6 +2044,8 @@ namespace Frida.Fruity {
private BufferedInputStream input;
private OutputStream output;
private Gee.Queue<Bytes> pending_input = new Gee.ArrayQueue<Bytes> ();
private bool input_flush_scheduled = false;
private Gee.Queue<Bytes> pending_output = new Gee.ArrayQueue<Bytes> ();
private bool writing = false;
@@ -2145,39 +2147,8 @@ namespace Frida.Fruity {
private async void process_incoming_messages () {
try {
while (true) {
var pending_input = new Gee.ArrayQueue<Bytes> ();
while (true) {
var size = peek_datagram_size ();
if (size == -1)
break;
var datagram = new uint8[size];
input.read (datagram, io_cancellable);
pending_input.offer (new Bytes.take ((owned) datagram));
}
if (pending_input.size != 0) {
try {
yield _tunnel_netstack.handle_incoming_datagrams (pending_input);
} catch (Error e) {
}
var source = new IdleSource ();
source.set_callback (process_incoming_messages.callback);
source.attach (MainContext.get_thread_default ());
yield;
}
ssize_t n;
try {
n = yield input.fill_async (-1, Priority.DEFAULT, io_cancellable);
} catch (GLib.Error e) {
throw new Error.TRANSPORT ("Connection closed");
}
if (n == 0)
throw new Error.TRANSPORT ("Connection closed");
var datagram = yield read_datagram (io_cancellable);
on_incoming_datagram (datagram);
}
} catch (GLib.Error e) {
}
@@ -2202,6 +2173,30 @@ namespace Frida.Fruity {
closed ();
}
private void on_incoming_datagram (Bytes datagram) {
pending_input.offer (datagram);
if (!input_flush_scheduled) {
var source = new IdleSource ();
source.set_callback (() => {
input_flush_scheduled = false;
flush_pending_input ();
return Source.REMOVE;
});
source.attach (MainContext.get_thread_default ());
input_flush_scheduled = true;
}
}
private void flush_pending_input () {
var datagrams = pending_input;
pending_input = new Gee.ArrayQueue<Bytes> ();
try {
_tunnel_netstack.handle_incoming_datagrams (datagrams);
} catch (Error e) {
}
}
private void post (Bytes datagram) {
var batch = new Gee.ArrayList<Bytes> ();
batch.add (datagram);
@@ -2274,21 +2269,24 @@ namespace Frida.Fruity {
return new JsonObjectReader (json);
}
private ssize_t peek_datagram_size () {
ssize_t header_size = 40;
private async Bytes read_datagram (Cancellable? cancellable) throws Error, IOError {
size_t header_size = 40;
if (input.get_available () < header_size)
return -1;
yield fill_until_n_bytes_available (header_size, cancellable);
uint16 payload_size = 0;
unowned uint8[] size_buf = ((uint8[]) &payload_size)[:2];
input.peek (size_buf, 4);
payload_size = uint16.from_big_endian (payload_size);
ssize_t full_size = header_size + payload_size;
size_t full_size = header_size + payload_size;
if (input.get_available () < full_size)
return -1;
yield fill_until_n_bytes_available (full_size, cancellable);
return full_size;
var datagram = new uint8[full_size];
input.read (datagram, cancellable);
return new Bytes.take ((owned) datagram);
}
private async void fill_until_n_bytes_available (size_t minimum, Cancellable? cancellable) throws Error, IOError {
@@ -2369,7 +2367,6 @@ namespace Frida.Fruity {
private Gee.Map<int64?, Stream> streams = new Gee.HashMap<int64?, Stream> (Numeric.int64_hash, Numeric.int64_equal);
private Gee.Queue<Bytes> pending_input = new Gee.ArrayQueue<Bytes> ();
private bool input_flush_scheduled = false;
private bool input_flush_happening = false;
private Gee.Queue<Bytes> pending_output = new Gee.ArrayQueue<Bytes> ();
private DatagramBasedSource? rx_source;
@@ -2845,7 +2842,7 @@ namespace Frida.Fruity {
var source = new IdleSource ();
source.set_callback (() => {
input_flush_scheduled = false;
flush_pending_input.begin ();
flush_pending_input ();
return Source.REMOVE;
});
source.attach (MainContext.get_thread_default ());
@@ -2855,20 +2852,13 @@ namespace Frida.Fruity {
return 0;
}
private async void flush_pending_input () {
if (input_flush_happening)
return;
input_flush_happening = true;
private void flush_pending_input () {
var datagrams = pending_input;
pending_input = new Gee.ArrayQueue<Bytes> ();
try {
yield _tunnel_netstack.handle_incoming_datagrams (datagrams);
} catch (GLib.Error e) {
_tunnel_netstack.handle_incoming_datagrams (datagrams);
} catch (Error e) {
}
input_flush_happening = false;
}
private static void on_rand (uint8[] dest, NGTcp2.RNGContext rand_ctx) {
+13 -17
View File
@@ -813,23 +813,22 @@ namespace Frida {
private const uint64 SOCK_CLOEXEC = 0x80000;
private sealed class InjectSession : SeizeSession {
private static ProcMapsSnapshot.Mapping local_libc;
private static ProcMapsSoEntry local_libc;
private static uint64 mmap_offset;
private static uint64 munmap_offset;
private static string fallback_ld;
private static string fallback_libc;
private static ProcMapsSnapshot.Mapping? local_android_ld;
private static ProcMapsSoEntry? local_android_ld;
static construct {
var libc = Gum.Process.get_libc_module ();
uint local_pid = Posix.getpid ();
var local_maps = ProcMapsSnapshot.from_pid (local_pid);
local_libc = local_maps.find_module_by_path (libc.path);
local_libc = ProcMapsSoEntry.find_by_path (local_pid, libc.path);
assert (local_libc != null);
mmap_offset = (uint64) (uintptr) libc.find_export_by_name ("mmap") - local_libc.start;
munmap_offset = (uint64) (uintptr) libc.find_export_by_name ("munmap") - local_libc.start;
mmap_offset = (uint64) (uintptr) libc.find_export_by_name ("mmap") - local_libc.base_address;
munmap_offset = (uint64) (uintptr) libc.find_export_by_name ("munmap") - local_libc.base_address;
try {
var program = new Gum.ElfModule.from_file ("/proc/self/exe");
@@ -847,7 +846,7 @@ namespace Frida {
}
#if ANDROID
local_android_ld = local_maps.find_module_by_path (fallback_ld);
local_android_ld = ProcMapsSoEntry.find_by_path (local_pid, fallback_ld);
#endif
}
@@ -1052,10 +1051,9 @@ namespace Frida {
uint64 allocation_base = 0;
size_t allocation_size = size_t.max (bootstrapper_size, loader_size) + stack_size;
var remote_maps = ProcMapsSnapshot.from_pid (pid);
var remote_libc = remote_maps.find_module_by_path (local_libc.path);
uint64 remote_mmap = 0;
uint64 remote_munmap = 0;
ProcMapsSoEntry? remote_libc = ProcMapsSoEntry.find_by_path (pid, local_libc.path);
#if ANDROID
bool same_libc = remote_libc != null
&& remote_libc.device.major == local_libc.device.major
@@ -1068,8 +1066,8 @@ namespace Frida {
&& remote_libc.path == local_libc.path;
#endif
if (same_libc) {
remote_mmap = remote_libc.start + mmap_offset;
remote_munmap = remote_libc.start + munmap_offset;
remote_mmap = remote_libc.base_address + mmap_offset;
remote_munmap = remote_libc.base_address + munmap_offset;
}
if (remote_mmap != 0) {
@@ -1167,9 +1165,7 @@ namespace Frida {
result.context.libc = &result.libc;
if (result.context.rtld_flavor == ANDROID && result.libc.dlopen == null) {
if (restart_after_libc_load)
remote_maps = ProcMapsSnapshot.from_pid (pid);
var remote_ld = remote_maps.find_mapping ((uintptr) result.context.rtld_base);
ProcMapsSoEntry? remote_ld = ProcMapsSoEntry.find_by_address (pid, (uintptr) result.context.rtld_base);
bool same_ld = remote_ld != null && local_android_ld != null
&& remote_ld.device.equals (local_android_ld.device)
&& remote_ld.inode == local_android_ld.inode;
@@ -1221,9 +1217,9 @@ namespace Frida {
}
}
private static void * rebase_pointer (uintptr local_ptr, ProcMapsSnapshot.Mapping local, ProcMapsSnapshot.Mapping remote) {
var offset = local_ptr - local.start;
return (void *) (remote.start + offset);
private static void * rebase_pointer (uintptr local_ptr, ProcMapsSoEntry local_module, ProcMapsSoEntry remote_module) {
var offset = local_ptr - local_module.base_address;
return (void *) (remote_module.base_address + offset);
}
private static string make_fallback_address () {
+9 -11
View File
@@ -19,7 +19,7 @@ endif
ifdef FRIDA_HOST
host_machine := $(FRIDA_HOST)
else
host_machine := $(shell basename $$(ls -1 $(BUILDDIR)/*/frida-linux-*.txt | tail -1) | cut -d"." -f1 | cut -d"-" -f2-)
host_machine := $(shell basename $$(ls -1 $(BUILDDIR)/frida-linux-*.txt | tail -1) | cut -d"." -f1 | cut -d"-" -f2-)
endif
host_arch := $(shell echo $(host_machine) | cut -d"-" -f2)
@@ -34,6 +34,7 @@ native_outdir := $(artifacts_dir)/native/$(host_arch)
bpf_outdir := $(artifacts_dir)/bpf
bpf_noarch_progs := \
activity-sampler \
softwall \
$(NULL)
bpf_arch_progs := \
syscall-tracer \
@@ -49,11 +50,11 @@ bpf_arch_pairs := \
build-native: ext/linux/tools/include/nolibc/nolibc.h
rm -rf build
$(MESON) setup --prefix /usr --cross-file $(crossfile) -Db_lto=true build
DESTDIR=$(abspath build/dist) $(MESON) install -C build
for f in build/dist/usr/share/frida-helpers/*; do \
install -m644 $$f $(native_outdir)/; \
done
$(MESON) setup --cross-file $(crossfile) -Db_lto=true build
$(MESON) compile -C build
install -m644 build/bootstrapper.bin $(native_outdir)/bootstrapper.bin
install -m644 build/loader.bin $(native_outdir)/loader.bin
[ -f build/zymbiote.bin ] && install -m644 build/zymbiote.bin $(native_outdir)/zymbiote.bin || true
bpf_targets :=
bpf_obj := $(build_dir)/module.o
@@ -66,8 +67,6 @@ linux_uapi_arch = $(strip \
$(if $(filter arm armbe,$1),arm, \
$(if $(filter arm64 arm64be,$1),arm64, \
$(if $(filter mips mipsel mips64 mips64el,$1),mips,unknown)))))
has_compat32 = $(strip \
$(if $(filter x86_64 arm64 arm64be,$(1)),1,))
kernel_headers_stamp = $(kernel_headers_dir)/$(1)/.stamp
kernel_headers_for = $(call kernel_headers_stamp,$(call linux_uapi_arch,$(1)))
@@ -97,7 +96,6 @@ define bpf_compile
$(BPF_CLANG) \
-target $(1) \
-D__TARGET_ARCH_$(2) \
$(if $(call has_compat32,$(3)),-DFRIDA_HAS_COMPAT32=1,) \
-O2 -g \
-I$(build_dir) \
-I$(libbpf_devel_dir) \
@@ -116,7 +114,7 @@ bpf_targets += $(foreach p,$(bpf_noarch_progs),$(bpf_outdir)/noarch-$(1)/$(p).el
$(bpf_outdir)/noarch-$(1)/%.elf: %.bpf.c $(call kernel_headers_stamp,$(noarch_uapi_arch)) $(libbpf_devel_dir)
$$(call recreate_build_dir)
$$(call bpf_compile,$(2),$(noarch_uapi_arch),noarch)
$$(call bpf_compile,$(2),$(noarch_uapi_arch))
endef
define declare_bpf_arch
@@ -142,7 +140,7 @@ $(bpf_outdir)/$(1)/%.elf: %.bpf.c $(call kernel_headers_for,$(1)) $(libbpf_devel
{ print } \
' frida-linux-syscalls.h > frida-linux-syscalls.h.tmp && \
mv frida-linux-syscalls.h.tmp frida-linux-syscalls.h
$$(call bpf_compile,$(2),$$(call linux_uapi_arch,$(1)),$(1))
$$(call bpf_compile,$(2),$$(call linux_uapi_arch,$(1)))
endef
pair_abi = $(word 1,$(subst :, ,$1))
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-1
View File
@@ -6,7 +6,6 @@ SECTIONS {
KEEP(*(.text.entrypoint))
*(.text*)
*(.rodata*)
*(.data*)
}
.dynstr : { *(.dynstr) }
+5 -1
View File
@@ -94,10 +94,14 @@ if host_machine.system() == 'android'
endif
zymbiote = shared_module('zymbiote', ['zymbiote.c'],
name_prefix: '',
name_suffix: 'elf',
c_args: zymbiote_flags + extra_flags,
link_args: extra_link_args,
link_depends: [helper_lds],
)
custom_target('zymbiote-bin',
input: [zymbiote],
output: ['zymbiote.bin'],
command: [objcopy, objcopy_flags, '@INPUT0@', '@OUTPUT0@'],
install_dir: 'share' / 'frida-helpers',
install: true,
)
+3 -7
View File
@@ -16,6 +16,7 @@ CURRENT_FILE="${BASH_SOURCE[0]}"
HELPERS_DIR="$(cd "$(dirname "$CURRENT_FILE")" && pwd)"
FRIDA_CORE_DIR="$(cd "$HELPERS_DIR/../../.." && pwd)"
RELENG_DIR="$FRIDA_CORE_DIR/releng"
BUILD_DIR="$FRIDA_CORE_DIR/build"
RELATIVE_TO_FRIDA_CORE_DIR=$(realpath --relative-to="$FRIDA_CORE_DIR" "$CURRENT_FILE")
TMP_MESON_DIR=$(mktemp -d)
@@ -85,14 +86,9 @@ build_arch () {
cd "$FRIDA_CORE_DIR"
builddir=build/$FRIDA_HOST
rm -rf "$builddir"
mkdir -p "$builddir"
pushd "$builddir"
../../configure --host="$XTOOLS_HOST" "${EXTRA_FLAGS[@]}"
popd
rm -rf "$BUILD_DIR"
# Note that $XTOOLS_HOST is set by the container.
./configure --host="$XTOOLS_HOST" "${EXTRA_FLAGS[@]}"
make -C src/linux/helpers
}
+275
View File
@@ -0,0 +1,275 @@
#include <stdbool.h>
#include <stdint.h>
#include <linux/bpf.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#define MAX_TARGET_TGIDS 4096
#define MAX_TARGET_UIDS 256
#define MAX_RULES 4096
#define MAX_INODE_INDEX 8192
#define MAX_AUDIT_EVENTS (1 << 20)
typedef struct _Event Event;
typedef __u16 EventType;
typedef struct _AuditEvent AuditEvent;
typedef struct _InodeKey InodeKey;
typedef struct _FileOpenRule FileOpenRule;
typedef struct _Stats Stats;
struct _Event
{
__u64 time_ns;
__u32 tgid;
__u32 tid;
EventType type;
__u16 _pad0;
};
enum _EventType
{
EVENT_TYPE_AUDIT
};
struct _AuditEvent
{
Event parent;
__u32 rule_id;
__u32 _pad0;
};
struct _InodeKey
{
__u64 dev;
__u64 ino;
};
struct _FileOpenRule
{
__u64 dev;
__u64 ino;
__s32 errno_neg;
__u32 _pad0;
};
struct _Stats
{
__u64 emitted_events;
__u64 emitted_bytes;
__u64 dropped_events;
__u64 dropped_bytes;
};
struct
{
__uint (type, BPF_MAP_TYPE_HASH);
__uint (max_entries, MAX_TARGET_TGIDS);
__type (key, __u32);
__type (value, __u8);
}
target_tgids SEC (".maps");
struct
{
__uint (type, BPF_MAP_TYPE_HASH);
__uint (max_entries, MAX_TARGET_UIDS);
__type (key, __u32);
__type (value, __u8);
}
target_uids SEC (".maps");
struct
{
__uint (type, BPF_MAP_TYPE_HASH);
__uint (max_entries, MAX_RULES);
__type (key, __u32);
__type (value, FileOpenRule);
}
rules_by_id SEC (".maps");
struct
{
__uint (type, BPF_MAP_TYPE_HASH);
__uint (max_entries, MAX_INODE_INDEX);
__type (key, InodeKey);
__type (value, __u32);
}
inode_index SEC (".maps");
struct
{
__uint (type, BPF_MAP_TYPE_RINGBUF);
__uint (max_entries, MAX_AUDIT_EVENTS);
}
audit_events SEC (".maps");
struct
{
__uint (type, BPF_MAP_TYPE_PERCPU_ARRAY);
__uint (max_entries, 1);
__type (key, __u32);
__type (value, Stats);
}
stats SEC (".maps");
typedef __u32 dev_t;
struct super_block
{
dev_t s_dev;
} __attribute__ ((preserve_access_index));
struct inode
{
struct super_block * i_sb;
unsigned long i_ino;
} __attribute__ ((preserve_access_index));
struct file
{
struct inode * f_inode;
} __attribute__ ((preserve_access_index));
static bool should_enforce_current (__u32 * out_tgid, __u32 * out_tid);
static Stats * get_ringbuf_stats (void);
static void note_emit (Stats * stats, __u64 bytes);
static void note_drop (Stats * stats, __u64 wanted_bytes);
static AuditEvent * reserve_audit_event (void);
static bool get_file_inode_key (struct file * file, InodeKey * out_key);
SEC ("lsm/file_open")
int
BPF_PROG (on_file_open, struct file * file)
{
__u32 tgid, tid;
if (!should_enforce_current (&tgid, &tid))
return 0;
InodeKey key;
if (!get_file_inode_key (file, &key))
return 0;
__u32 * rule_id = bpf_map_lookup_elem (&inode_index, &key);
if (rule_id == NULL)
return 0;
FileOpenRule * rule = bpf_map_lookup_elem (&rules_by_id, rule_id);
if (rule == NULL)
return 0;
AuditEvent * ev = reserve_audit_event ();
if (ev != NULL)
{
ev->parent.time_ns = bpf_ktime_get_ns ();
ev->parent.tgid = tgid;
ev->parent.tid = tid;
ev->parent.type = EVENT_TYPE_AUDIT;
ev->rule_id = *rule_id;
ev->_pad0 = 0;
bpf_ringbuf_submit (ev, 0);
}
return rule->errno_neg;
}
static bool
should_enforce_current (__u32 * out_tgid, __u32 * out_tid)
{
__u64 pid_tgid = bpf_get_current_pid_tgid ();
__u32 tgid = pid_tgid >> 32;
__u32 tid = (__u32) pid_tgid;
*out_tgid = tgid;
*out_tid = tid;
__u8 * tgid_enabled = bpf_map_lookup_elem (&target_tgids, &tgid);
if (tgid_enabled != NULL)
return true;
__u64 uid_gid = bpf_get_current_uid_gid ();
__u32 uid = (__u32) uid_gid;
__u8 * uid_enabled = bpf_map_lookup_elem (&target_uids, &uid);
if (uid_enabled != NULL)
return true;
return false;
}
static bool
get_file_inode_key (struct file * file, InodeKey * out_key)
{
if (file == NULL)
return false;
struct inode * inode = BPF_CORE_READ (file, f_inode);
if (inode == NULL)
return false;
out_key->dev = BPF_CORE_READ (inode, i_sb, s_dev);
out_key->ino = BPF_CORE_READ (inode, i_ino);
return true;
}
static AuditEvent *
reserve_audit_event (void)
{
void * event = bpf_ringbuf_reserve (&audit_events, sizeof (AuditEvent), 0);
Stats * stats = get_ringbuf_stats ();
if (event != NULL)
note_emit (stats, sizeof (AuditEvent));
else
note_drop (stats, sizeof (AuditEvent));
return (AuditEvent *) event;
}
static Stats *
get_ringbuf_stats (void)
{
__u32 key = 0;
return bpf_map_lookup_elem (&stats, &key);
}
static void
note_emit (Stats * stats, __u64 bytes)
{
if (stats == NULL)
return;
stats->emitted_events++;
stats->emitted_bytes += bytes;
}
static void
note_drop (Stats * stats, __u64 wanted_bytes)
{
if (stats == NULL)
return;
stats->dropped_events++;
stats->dropped_bytes += wanted_bytes;
}
char LICENSE[] SEC ("license") = "Dual BSD/GPL";
+136 -166
View File
@@ -13,13 +13,12 @@
#define MAX_TARGET_TGIDS 4096
#define MAX_TARGET_UIDS 256
#define MAX_EXCLUDED_SYSCALLS 1024
#define MAX_MAP_STATES 8192
#define MAX_STACK_ENTRIES 16384
#define MAX_INFLIGHT_COPIES 4096
#define MAX_STACK_DEPTH 16
#define MAX_PATH_DEPTH 18
#define MAX_PATH_DEPTH 20
#define MAX_PATH 256
#define MAX_STAT 512
#define MAX_SOCK 128
@@ -27,14 +26,6 @@
#define SYSCALL_NARGS 6
#ifdef FRIDA_HAS_COMPAT32
# if defined (__TARGET_ARCH_x86)
# define FRIDA_TIF_COMPAT32 29
# elif defined (__TARGET_ARCH_arm64)
# define FRIDA_TIF_COMPAT32 22
# endif
#endif
typedef struct _Event Event;
typedef __u16 EventType;
@@ -62,7 +53,6 @@ typedef struct _MapCreateEvent MapCreateEvent;
typedef struct _MapDestroyRangeEvent MapDestroyRangeEvent;
typedef struct _ProcessState ProcessState;
typedef __u32 Abi;
typedef struct _Inflight Inflight;
typedef struct _Stats Stats;
typedef struct _BufBuilder BufBuilder;
@@ -93,8 +83,7 @@ struct _AttachmentHeader
{
AttachmentType type;
__u16 arg_index;
__u16 capacity;
__u16 size;
__u32 len;
};
enum _AttachmentType
@@ -245,17 +234,10 @@ struct _MapDestroyRangeEvent
struct _ProcessState
{
Abi abi;
__u8 abi;
__u32 map_gen;
};
enum _Abi
{
ABI_INVALID,
ABI_NATIVE,
ABI_COMPAT32,
};
struct _Inflight
{
__s32 syscall_nr;
@@ -344,15 +326,6 @@ struct
}
target_uids SEC (".maps");
struct
{
__uint (type, BPF_MAP_TYPE_HASH);
__uint (max_entries, MAX_EXCLUDED_SYSCALLS);
__type (key, __u64);
__type (value, __u8);
}
excluded_syscalls SEC (".maps");
struct
{
__uint (type, BPF_MAP_TYPE_RINGBUF);
@@ -428,16 +401,6 @@ struct trace_event_raw_sys_exit
typedef __u32 dev_t;
struct thread_info
{
unsigned long flags;
} __attribute__ ((preserve_access_index));
struct task_struct
{
struct thread_info thread_info;
} __attribute__ ((preserve_access_index));
struct super_block
{
dev_t s_dev;
@@ -501,9 +464,18 @@ struct vm_area_struct
} __attribute__ ((preserve_access_index));
static bool should_trace_current (__u32 * out_tgid, __u32 * out_tid);
static Abi get_current_abi (void);
static bool syscall_is_excluded (Abi abi, __s32 nr);
static __u64 make_excluded_key (Abi abi, __s32 nr);
static SyscallEnterEventNone * reserve_enter_none (void);
static SyscallEnterEventTimespec * reserve_enter_timespec (void);
static SyscallEnterEventPath * reserve_enter_path (void);
static SyscallEnterEventPath2 * reserve_enter_path2 (void);
static SyscallEnterEventPath3 * reserve_enter_path3 (void);
static SyscallEnterEventSock * reserve_enter_sock (void);
static SyscallExitEventNone * reserve_exit_none (void);
static SyscallExitEventStrOut * reserve_exit_str_out (void);
static SyscallExitEventStatOut * reserve_exit_stat_out (void);
static SyscallExitEventSockOut * reserve_exit_sock_out (void);
static void * reserve_syscall_event (__u64 size);
@@ -511,8 +483,8 @@ static void fill_syscall_event (SyscallEvent * e, EventType type, __u32 tgid, __
void * ctx);
static void fill_enter_args (__u64 args[SYSCALL_NARGS], struct trace_event_raw_sys_enter * ctx);
static void write_attach_str_arg (AttachmentHeader * h, __u16 arg_index, __u8 * dst, __u32 dst_cap, const void * user_str);
static void write_attach_bytes_arg (AttachmentHeader * h, __u16 arg_index, __u8 * dst, __u32 dst_cap,
static __u16 write_attach_str_arg (AttachmentHeader * h, __u16 arg_index, __u8 * dst, __u32 dst_cap, const void * user_str);
static __u16 write_attach_bytes_arg (AttachmentHeader * h, __u16 arg_index, __u8 * dst, __u32 dst_cap,
const void * user_src, __u32 n);
static __u16 write_attach_dentry_path (AttachmentHeader * h, __u16 arg_index, __u8 * dst, __u32 dst_cap, struct file * file);
@@ -520,7 +492,7 @@ static void maybe_schedule_str_out_copy (__u32 tid, __s32 nr, __u16 arg_index, _
static void maybe_schedule_stat_out_copy (__u32 tid, __s32 nr, __u16 arg_index, __u64 user_ptr, __u32 len);
static void maybe_schedule_sock_out_copy (__u32 tid, __s32 nr, __u16 arg_index, __u64 user_ptr, __u64 user_len_ptr, __u32 max_len);
static bool ensure_process_state (__u32 tgid, __u32 tid, Abi abi, __u32 * out_map_gen);
static __u32 ensure_map_gen (__u32 tgid, __u32 tid);
static __u32 bump_map_gen (__u32 tgid);
static bool emit_need_snapshot (__u32 tgid, __u32 tid);
@@ -548,22 +520,15 @@ on_sys_enter (struct trace_event_raw_sys_enter * ctx)
if (!should_trace_current (&tgid, &tid))
return 0;
Abi abi = get_current_abi ();
__s32 nr = (__s32) ctx->id;
if (syscall_is_excluded (abi, nr))
return 0;
__u32 map_gen;
if (!ensure_process_state (tgid, tid, abi, &map_gen))
return 0;
__u32 map_gen = ensure_map_gen (tgid, tid);
if (nr == FRIDA_LINUX_SYSCALL_OPENAT ||
nr == FRIDA_LINUX_SYSCALL_FACCESSAT ||
nr == FRIDA_LINUX_SYSCALL_STATFS ||
nr == FRIDA_LINUX_SYSCALL_READLINKAT)
{
SyscallEnterEventPath * ev = reserve_syscall_event (sizeof (SyscallEnterEventPath));
SyscallEnterEventPath * ev = reserve_enter_path ();
if (ev == NULL)
return 0;
@@ -597,7 +562,7 @@ on_sys_enter (struct trace_event_raw_sys_enter * ctx)
#endif
nr == FRIDA_LINUX_SYSCALL_STATX)
{
SyscallEnterEventPath * ev = reserve_syscall_event (sizeof (SyscallEnterEventPath));
SyscallEnterEventPath * ev = reserve_enter_path ();
if (ev == NULL)
return 0;
@@ -629,7 +594,7 @@ on_sys_enter (struct trace_event_raw_sys_enter * ctx)
nr == FRIDA_LINUX_SYSCALL_FSTAT ||
nr == FRIDA_LINUX_SYSCALL_STATMOUNT)
{
SyscallEnterEventNone * ev = reserve_syscall_event (sizeof (SyscallEnterEventNone));
SyscallEnterEventNone * ev = reserve_enter_none ();
if (ev == NULL)
return 0;
@@ -674,7 +639,7 @@ on_sys_enter (struct trace_event_raw_sys_enter * ctx)
#endif
nr == FRIDA_LINUX_SYSCALL_SYMLINKAT)
{
SyscallEnterEventPath2 * ev = reserve_syscall_event (sizeof (SyscallEnterEventPath2));
SyscallEnterEventPath2 * ev = reserve_enter_path2 ();
if (ev == NULL)
return 0;
@@ -729,7 +694,7 @@ on_sys_enter (struct trace_event_raw_sys_enter * ctx)
if (nr == FRIDA_LINUX_SYSCALL_MOUNT)
{
SyscallEnterEventPath3 * ev = reserve_syscall_event (sizeof (SyscallEnterEventPath3));
SyscallEnterEventPath3 * ev = reserve_enter_path3 ();
if (ev == NULL)
return 0;
@@ -749,7 +714,7 @@ on_sys_enter (struct trace_event_raw_sys_enter * ctx)
if (nr == FRIDA_LINUX_SYSCALL_NANOSLEEP ||
nr == FRIDA_LINUX_SYSCALL_CLOCK_NANOSLEEP)
{
SyscallEnterEventTimespec * ev = reserve_syscall_event (sizeof (SyscallEnterEventTimespec));
SyscallEnterEventTimespec * ev = reserve_enter_timespec ();
if (ev == NULL)
return 0;
@@ -791,7 +756,7 @@ on_sys_enter (struct trace_event_raw_sys_enter * ctx)
nr == FRIDA_LINUX_SYSCALL_BIND ||
nr == FRIDA_LINUX_SYSCALL_SENDTO)
{
SyscallEnterEventSock * ev = reserve_syscall_event (sizeof (SyscallEnterEventSock));
SyscallEnterEventSock * ev = reserve_enter_sock ();
if (ev == NULL)
return 0;
@@ -828,7 +793,7 @@ on_sys_enter (struct trace_event_raw_sys_enter * ctx)
nr == FRIDA_LINUX_SYSCALL_GETPEERNAME ||
nr == FRIDA_LINUX_SYSCALL_RECVFROM)
{
SyscallEnterEventNone * ev = reserve_syscall_event (sizeof (SyscallEnterEventNone));
SyscallEnterEventNone * ev = reserve_enter_none ();
if (ev == NULL)
return 0;
@@ -849,7 +814,7 @@ on_sys_enter (struct trace_event_raw_sys_enter * ctx)
}
{
SyscallEnterEventNone * ev = reserve_syscall_event (sizeof (SyscallEnterEventNone));
SyscallEnterEventNone * ev = reserve_enter_none ();
if (ev == NULL)
return 0;
@@ -869,20 +834,13 @@ on_sys_exit (struct trace_event_raw_sys_exit * ctx)
if (!should_trace_current (&tgid, &tid))
return 0;
Abi abi = get_current_abi ();
__s32 nr = (__s32) ctx->id;
if (syscall_is_excluded (abi, nr))
return 0;
__u32 map_gen;
if (!ensure_process_state (tgid, tid, abi, &map_gen))
return 0;
__u32 map_gen = ensure_map_gen (tgid, tid);
Inflight * in = bpf_map_lookup_elem (&inflight, &tid);
if (in != NULL && in->kind == INFLIGHT_KIND_STR_OUT_COPY && in->syscall_nr == nr)
{
SyscallExitEventStrOut * ev = reserve_syscall_event (sizeof (SyscallExitEventStrOut));
SyscallExitEventStrOut * ev = reserve_exit_str_out ();
if (ev == NULL)
return 0;
@@ -893,22 +851,30 @@ on_sys_exit (struct trace_event_raw_sys_exit * ctx)
long n = ctx->ret;
if (n > 0)
{
__u32 size = (__u32) n;
if (size > in->u.str_out_copy.max_len)
size = in->u.str_out_copy.max_len;
if (size >= MAX_PATH)
size = MAX_PATH - 1;
size &= MAX_PATH - 1;
barrier_var (size);
__u32 maxn = in->u.str_out_copy.max_len;
if (maxn > MAX_PATH - 1)
maxn = MAX_PATH - 1;
__u32 to_copy = (__u32) n;
if (to_copy > maxn)
to_copy = maxn;
ev->attach.type = ATTACHMENT_STRING;
ev->attach.arg_index = in->u.str_out_copy.arg_index;
ev->attach.capacity = MAX_PATH;
ev->attach.size = size + 1;
if (size > 0)
bpf_probe_read_user (&ev->data[0], size, (void *) in->u.str_out_copy.user_ptr);
ev->data[size] = '\0';
if (to_copy == (MAX_PATH - 1))
{
ev->attach.len = (MAX_PATH - 1) + 1;
bpf_probe_read_user (&ev->data[0], MAX_PATH - 1, (void *) in->u.str_out_copy.user_ptr);
ev->data[MAX_PATH - 1] = '\0';
}
else
{
ev->attach.len = to_copy + 1;
if (to_copy != 0)
bpf_probe_read_user (&ev->data[0], to_copy, (void *) in->u.str_out_copy.user_ptr);
ev->data[to_copy] = '\0';
}
ev->parent.parent.parent.attachment_count = 1;
}
@@ -921,7 +887,7 @@ on_sys_exit (struct trace_event_raw_sys_exit * ctx)
if (in != NULL && in->kind == INFLIGHT_KIND_STAT_OUT_COPY && in->syscall_nr == nr)
{
SyscallExitEventStatOut * ev = reserve_syscall_event (sizeof (SyscallExitEventStatOut));
SyscallExitEventStatOut * ev = reserve_exit_stat_out ();
if (ev == NULL)
return 0;
@@ -961,20 +927,10 @@ on_sys_exit (struct trace_event_raw_sys_exit * ctx)
ev->attach.type = ATTACHMENT_BYTES;
ev->attach.arg_index = in->u.stat_out_copy.arg_index;
ev->attach.capacity = MAX_STAT;
ev->attach.len = to_copy;
if (to_copy == MAX_STAT)
{
ev->attach.size = MAX_STAT;
bpf_probe_read_user (&ev->data[0], MAX_STAT, (void *) in->u.stat_out_copy.user_ptr);
}
else
{
ev->attach.size = to_copy;
if (to_copy != 0)
bpf_probe_read_user (&ev->data[0], to_copy, (void *) in->u.stat_out_copy.user_ptr);
}
if (to_copy != 0)
bpf_probe_read_user (&ev->data[0], to_copy, (void *) in->u.stat_out_copy.user_ptr);
ev->parent.parent.parent.attachment_count = 1;
}
@@ -987,7 +943,7 @@ on_sys_exit (struct trace_event_raw_sys_exit * ctx)
if (in != NULL && in->kind == INFLIGHT_KIND_SOCK_OUT_COPY && in->syscall_nr == nr)
{
SyscallExitEventSockOut * ev = reserve_syscall_event (sizeof (SyscallExitEventSockOut));
SyscallExitEventSockOut * ev = reserve_exit_sock_out ();
if (ev == NULL)
return 0;
@@ -1032,8 +988,7 @@ on_sys_exit (struct trace_event_raw_sys_exit * ctx)
ev->attach.type = ATTACHMENT_BYTES;
ev->attach.arg_index = in->u.sock_out_copy.arg_index;
ev->attach.capacity = MAX_SOCK;
ev->attach.size = to_copy;
ev->attach.len = to_copy;
if (to_copy != 0)
bpf_probe_read_user (&ev->data[0], to_copy, (void *) in->u.sock_out_copy.user_ptr);
@@ -1048,7 +1003,7 @@ on_sys_exit (struct trace_event_raw_sys_exit * ctx)
}
{
SyscallExitEventNone * ev = reserve_syscall_event (sizeof (SyscallExitEventNone));
SyscallExitEventNone * ev = reserve_exit_none ();
if (ev == NULL)
return 0;
@@ -1170,34 +1125,67 @@ should_trace_current (__u32 * out_tgid, __u32 * out_tid)
return false;
}
static Abi
get_current_abi (void)
static SyscallEnterEventNone *
reserve_enter_none (void)
{
#ifdef FRIDA_TIF_COMPAT32
struct task_struct * task = bpf_get_current_task_btf ();
unsigned long flags = BPF_CORE_READ (task, thread_info.flags);
if (flags & (1UL << FRIDA_TIF_COMPAT32))
return ABI_COMPAT32;
#endif
return ABI_NATIVE;
return reserve_syscall_event (sizeof (SyscallEnterEventNone));
}
static bool
syscall_is_excluded (Abi abi, __s32 nr)
static SyscallEnterEventTimespec *
reserve_enter_timespec (void)
{
__u64 k = make_excluded_key (abi, nr);
return bpf_map_lookup_elem (&excluded_syscalls, &k) != NULL;
return reserve_syscall_event (sizeof (SyscallEnterEventTimespec));
}
static __u64
make_excluded_key (Abi abi, __s32 nr)
static SyscallEnterEventPath *
reserve_enter_path (void)
{
return ((__u64) abi << 32) | (__u32) nr;
return reserve_syscall_event (sizeof (SyscallEnterEventPath));
}
static __always_inline void *
static SyscallEnterEventPath2 *
reserve_enter_path2 (void)
{
return reserve_syscall_event (sizeof (SyscallEnterEventPath2));
}
static SyscallEnterEventPath3 *
reserve_enter_path3 (void)
{
return reserve_syscall_event (sizeof (SyscallEnterEventPath3));
}
static SyscallEnterEventSock *
reserve_enter_sock (void)
{
return reserve_syscall_event (sizeof (SyscallEnterEventSock));
}
static SyscallExitEventNone *
reserve_exit_none (void)
{
return reserve_syscall_event (sizeof (SyscallExitEventNone));
}
static SyscallExitEventStrOut *
reserve_exit_str_out (void)
{
return reserve_syscall_event (sizeof (SyscallExitEventStrOut));
}
static SyscallExitEventStatOut *
reserve_exit_stat_out (void)
{
return reserve_syscall_event (sizeof (SyscallExitEventStatOut));
}
static SyscallExitEventSockOut *
reserve_exit_sock_out (void)
{
return reserve_syscall_event (sizeof (SyscallExitEventSockOut));
}
static void *
reserve_syscall_event (__u64 size)
{
void * event = bpf_ringbuf_reserve (&syscall_events, size, 0);
@@ -1237,35 +1225,30 @@ fill_enter_args (__u64 args[SYSCALL_NARGS], struct trace_event_raw_sys_enter * c
args[5] = (__u64) ctx->args[5];
}
static void
static __u16
write_attach_str_arg (AttachmentHeader * h, __u16 arg_index, __u8 * dst, __u32 dst_cap, const void * user_str)
{
h->type = ATTACHMENT_STRING;
h->arg_index = arg_index;
h->capacity = dst_cap;
h->len = 0;
long r = bpf_probe_read_user_str (dst, dst_cap, user_str);
if (r >= 1)
{
h->size = r;
}
else
{
h->size = 1;
dst[0] = '\0';
}
__u32 used = (r > 0) ? (__u32) r : 0;
h->len = used;
return (__u16) used;
}
static void
static __u16
write_attach_bytes_arg (AttachmentHeader * h, __u16 arg_index, __u8 * dst, __u32 dst_cap, const void * user_src, __u32 n)
{
h->type = ATTACHMENT_BYTES;
h->arg_index = arg_index;
h->capacity = dst_cap;
if (n == 0)
{
h->size = 0;
return;
h->len = 0;
return 0;
}
if (n > dst_cap)
@@ -1273,7 +1256,9 @@ write_attach_bytes_arg (AttachmentHeader * h, __u16 arg_index, __u8 * dst, __u32
bpf_probe_read_user (dst, n, user_src);
h->size = n;
h->len = n;
return (__u16) n;
}
static __u16
@@ -1283,8 +1268,7 @@ write_attach_dentry_path (AttachmentHeader * h, __u16 arg_index, __u8 * dst, __u
h->type = ATTACHMENT_STRING;
h->arg_index = arg_index;
h->capacity = dst_cap;
h->size = 0;
h->len = 0;
__u32 key = 0;
ScratchArea * sa = bpf_map_lookup_elem (&scratch_area, &key);
@@ -1375,21 +1359,8 @@ write_attach_dentry_path (AttachmentHeader * h, __u16 arg_index, __u8 * dst, __u
break;
}
{
__u32 pos = b->pos;
if (pos >= MAX_BUF_BUILDER_SIZE - 1)
{
b->buf[MAX_BUF_BUILDER_SIZE - 1] = '\0';
}
else
{
pos &= (MAX_BUF_BUILDER_SIZE - 2);
barrier_var (pos);
b->buf[pos] = '\0';
b->pos = pos + 1;
}
}
if (!bb_putc (b, '\0'))
b->buf[MAX_BUF_BUILDER_SIZE - 1] = '\0';
flush:
n = b->pos;
@@ -1399,14 +1370,14 @@ flush:
if (n != 0)
bpf_probe_read_kernel (dst, n, b->buf);
h->size = n;
h->len = n;
return (__u16) n;
}
static void
maybe_schedule_str_out_copy (__u32 tid, __s32 nr, __u16 arg_index, __u64 user_ptr, __u32 max_len)
{
Inflight v = {};
Inflight v;
v.syscall_nr = nr;
v.kind = INFLIGHT_KIND_STR_OUT_COPY;
@@ -1425,7 +1396,7 @@ maybe_schedule_str_out_copy (__u32 tid, __s32 nr, __u16 arg_index, __u64 user_pt
static void
maybe_schedule_stat_out_copy (__u32 tid, __s32 nr, __u16 arg_index, __u64 user_ptr, __u32 len)
{
Inflight v = {};
Inflight v;
v.syscall_nr = nr;
v.kind = INFLIGHT_KIND_STAT_OUT_COPY;
@@ -1444,7 +1415,7 @@ maybe_schedule_stat_out_copy (__u32 tid, __s32 nr, __u16 arg_index, __u64 user_p
static void
maybe_schedule_sock_out_copy (__u32 tid, __s32 nr, __u16 arg_index, __u64 user_ptr, __u64 user_len_ptr, __u32 max_len)
{
Inflight v = {};
Inflight v;
v.syscall_nr = nr;
v.kind = INFLIGHT_KIND_SOCK_OUT_COPY;
@@ -1461,15 +1432,15 @@ maybe_schedule_sock_out_copy (__u32 tid, __s32 nr, __u16 arg_index, __u64 user_p
bpf_map_update_elem (&inflight, &tid, &v, BPF_ANY);
}
static bool
ensure_process_state (__u32 tgid, __u32 tid, Abi abi, __u32 * out_map_gen)
static __u32
ensure_map_gen (__u32 tgid, __u32 tid)
{
ProcessState * st = bpf_map_lookup_elem (&process_states, &tgid);
if (st == NULL)
{
ProcessState init = {};
ProcessState init;
init.abi = abi;
init.abi = 0;
init.map_gen = 0;
long r = bpf_map_update_elem (&process_states, &tgid, &init, BPF_NOEXIST);
@@ -1482,17 +1453,16 @@ ensure_process_state (__u32 tgid, __u32 tid, Abi abi, __u32 * out_map_gen)
else
{
bpf_map_delete_elem (&process_states, &tgid);
return false;
return 0;
}
}
st = bpf_map_lookup_elem (&process_states, &tgid);
if (st == NULL)
return false;
return 0;
}
*out_map_gen = st->map_gen;
return true;
return st->map_gen;
}
static __u32
+95 -167
View File
@@ -2,28 +2,18 @@
#include <jni.h>
#include <signal.h>
#include <stdbool.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/un.h>
typedef struct _ZymbioteContext ZymbioteContext;
typedef struct _FridaApi FridaApi;
struct _ZymbioteContext
struct _FridaApi
{
char socket_path[64];
char name[64];
void * payload_base;
size_t payload_size;
size_t payload_original_protection;
char * package_name;
int (* original_setcontext) (uid_t uid, bool is_system_server, const char * seinfo, const char * name);
void ** art_method_slot;
void (* original_set_argv0) (JNIEnv * env, jobject clazz, jstring name);
int (* mprotect) (void * addr, size_t len, int prot);
char * (* strdup) (const char * s);
void (* free) (void * ptr);
int (* socket) (int domain, int type, int protocol);
int (* connect) (int sockfd, const struct sockaddr * addr, socklen_t addrlen);
int * (* __errno) (void);
@@ -35,17 +25,12 @@ struct _ZymbioteContext
int (* raise) (int sig);
};
ZymbioteContext zymbiote =
static volatile const FridaApi frida =
{
.socket_path = "/frida-zymbiote-00000000000000000000000000000000",
.name = "/frida-zymbiote-00000000000000000000000000000000",
};
int frida_zymbiote_replacement_setargv0 (JNIEnv * env, jobject clazz, jstring name);
int frida_zymbiote_replacement_setcontext (uid_t uid, bool is_system_server, const char * seinfo, const char * name);
static void frida_wait_for_permission_to_resume (const char * package_name, bool * revert_now);
static int frida_stop_and_return_from_setargv0 (JNIEnv * env, jobject clazz, jstring name);
static int frida_stop_and_return (JNIEnv * env, jobject clazz, jstring name);
static int frida_get_errno (void);
@@ -57,71 +42,19 @@ static ssize_t frida_recv (int sockfd, void * buf, size_t len, int flags);
__attribute__ ((section (".text.entrypoint")))
__attribute__ ((visibility ("default")))
int
frida_zymbiote_replacement_setcontext (uid_t uid, bool is_system_server, const char * seinfo, const char * name)
{
int res;
res = zymbiote.original_setcontext (uid, is_system_server, seinfo, name);
if (res == -1)
return -1;
if (zymbiote.package_name == NULL)
{
zymbiote.mprotect (zymbiote.payload_base, zymbiote.payload_size, PROT_READ | PROT_WRITE | PROT_EXEC);
zymbiote.package_name = zymbiote.strdup (name);
}
return res;
}
__attribute__ ((section (".text.entrypoint")))
__attribute__ ((visibility ("default")))
int
frida_zymbiote_replacement_setargv0 (JNIEnv * env, jobject clazz, jstring name)
{
const char * name_utf8;
bool revert_now;
zymbiote.original_set_argv0 (env, clazz, name);
if (zymbiote.package_name != NULL)
name_utf8 = zymbiote.package_name;
else
name_utf8 = (*env)->GetStringUTFChars (env, name, NULL);
frida_wait_for_permission_to_resume (name_utf8, &revert_now);
if (zymbiote.package_name != NULL)
{
zymbiote.free (zymbiote.package_name);
zymbiote.package_name = NULL;
zymbiote.mprotect (zymbiote.payload_base, zymbiote.payload_size, zymbiote.payload_original_protection);
}
else
{
(*env)->ReleaseStringUTFChars (env, name, name_utf8);
}
if (revert_now)
{
__attribute__ ((musttail))
return frida_stop_and_return_from_setargv0 (env, clazz, name);
}
return 0;
}
static void
frida_wait_for_permission_to_resume (const char * package_name, bool * revert_now)
frida_zymbiote_replacement_set_argv0 (JNIEnv * env, jobject clazz, jstring name)
{
bool success = false;
int fd;
struct sockaddr_un addr;
socklen_t addrlen;
unsigned int name_len;
*revert_now = false;
*frida.art_method_slot = frida.original_set_argv0;
fd = zymbiote.socket (AF_UNIX, SOCK_STREAM, 0);
frida.original_set_argv0 (env, clazz, name);
fd = frida.socket (AF_UNIX, SOCK_STREAM, 0);
if (fd == -1)
goto beach;
@@ -129,15 +62,15 @@ frida_wait_for_permission_to_resume (const char * package_name, bool * revert_no
addr.sun_path[0] = '\0';
name_len = 0;
for (unsigned int i = 0; i != sizeof (zymbiote.socket_path); i++)
for (unsigned int i = 0; i != sizeof (frida.name); i++)
{
if (zymbiote.socket_path[i] == '\0')
if (frida.name[i] == '\0')
break;
if (1u + i >= sizeof (addr.sun_path))
break;
addr.sun_path[1u + i] = zymbiote.socket_path[i];
addr.sun_path[1u + i] = frida.name[i];
name_len++;
}
@@ -147,6 +80,7 @@ frida_wait_for_permission_to_resume (const char * package_name, bool * revert_no
goto beach;
{
const char * name_utf8;
struct
{
uint32_t pid;
@@ -155,21 +89,25 @@ frida_wait_for_permission_to_resume (const char * package_name, bool * revert_no
} header;
struct iovec iov[2];
header.pid = zymbiote.getpid ();
header.ppid = zymbiote.getppid ();
name_utf8 = (*env)->GetStringUTFChars (env, name, NULL);
header.pid = frida.getpid ();
header.ppid = frida.getppid ();
header.package_name_len = 0;
while (package_name[header.package_name_len] != '\0')
while (name_utf8[header.package_name_len] != '\0')
header.package_name_len++;
iov[0].iov_base = &header;
iov[0].iov_len = sizeof (header);
iov[1].iov_base = (void *) package_name;
iov[1].iov_base = (void *) name_utf8;
iov[1].iov_len = header.package_name_len;
if (!frida_sendmsg_all (fd, iov, 2, MSG_NOSIGNAL))
goto beach;
(*env)->ReleaseStringUTFChars (env, name, name_utf8);
}
{
@@ -179,96 +117,86 @@ frida_wait_for_permission_to_resume (const char * package_name, bool * revert_no
goto beach;
}
*revert_now = true;
success = true;
beach:
if (fd != -1)
zymbiote.close (fd);
frida.close (fd);
if (success)
{
__attribute__ ((musttail))
return frida_stop_and_return (env, clazz, name);
}
return 0;
}
#if defined (__i386__)
# define FRIDA_TAILCALL_TO_RAISE_SIGSTOP() \
__asm__ __volatile__ ( \
"movl $%c[sig], 4(%%esp)\n" \
\
"call 1f\n" \
"1: pop %%eax\n" \
\
"addl $(zymbiote-1b), %%eax\n" \
"movl %c[raise_off](%%eax), %%eax\n" \
\
"jmp *%%eax\n" \
: \
: [sig] "i" (SIGSTOP), \
[raise_off] "i" (offsetof (ZymbioteContext, raise)) \
: "eax", "memory" \
)
#elif defined (__x86_64__)
# define FRIDA_TAILCALL_TO_RAISE_SIGSTOP() \
__asm__ __volatile__ ( \
"mov $%c[sig], %%edi\n" \
\
"leaq zymbiote(%%rip), %%r11\n" \
"movq %c[raise_off](%%r11), %%r11\n" \
\
"jmp *%%r11\n" \
: \
: [sig] "i" (SIGSTOP), \
[raise_off] "i" (offsetof (ZymbioteContext, raise)) \
: "r11", "rdi", "memory" \
)
#elif defined (__arm__)
# define FRIDA_TAILCALL_TO_RAISE_SIGSTOP() \
__asm__ __volatile__ ( \
"mov r0, %[sig]\n" \
\
"adr r12, zymbiote\n" \
"ldr r12, [r12, %[raise_off]]\n" \
\
"bx r12\n" \
: \
: [sig] "i" (SIGSTOP), \
[raise_off] "i" (offsetof (ZymbioteContext, raise)) \
: "r12", "memory" \
)
#elif defined (__aarch64__)
# define FRIDA_TAILCALL_TO_RAISE_SIGSTOP() \
__asm__ __volatile__ ( \
"mov w0, #%[sig]\n" \
\
"adrp x16, zymbiote\n" \
"add x16, x16, :lo12:zymbiote\n" \
"ldr x16, [x16, %[raise_off]]\n" \
\
"br x16\n" \
: \
: [sig] "i" (SIGSTOP), \
[raise_off] "i" (offsetof (ZymbioteContext, raise)) \
: "x16", "memory" \
)
#else
# error Unsupported architecture
#endif
__attribute__ ((naked, noinline))
static int
frida_stop_and_return_from_setargv0 (JNIEnv * env, jobject clazz, jstring name)
frida_stop_and_return (JNIEnv * env, jobject clazz, jstring name)
{
FRIDA_TAILCALL_TO_RAISE_SIGSTOP ();
#if defined (__i386__)
__asm__ __volatile__ (
"movl $%c[sig], 4(%%esp)\n"
"call 1f\n"
"1: pop %%eax\n"
"addl $(frida-1b), %%eax\n"
"movl %c[raise_off](%%eax), %%eax\n"
"jmp *%%eax\n"
:
: [sig] "i" (SIGSTOP),
[raise_off] "i" (offsetof (FridaApi, raise))
: "eax", "memory");
#elif defined (__x86_64__)
__asm__ __volatile__ (
"mov $%c[sig], %%edi\n"
"leaq frida(%%rip), %%r11\n"
"movq %c[raise_off](%%r11), %%r11\n"
"jmp *%%r11\n"
:
: [sig] "i" (SIGSTOP),
[raise_off] "i" (offsetof (FridaApi, raise))
: "r11", "rdi", "memory");
#elif defined (__arm__)
__asm__ __volatile__ (
"mov r0, %[sig]\n"
"adr r12, frida\n"
"ldr r12, [r12, %[raise_off]]\n"
"bx r12\n"
:
: [sig] "i" (SIGSTOP),
[raise_off] "i" (offsetof (FridaApi, raise))
: "r12", "memory");
#elif defined (__aarch64__)
__asm__ __volatile__ (
"mov w0, #%[sig]\n"
"adrp x16, frida\n"
"add x16, x16, :lo12:frida\n"
"ldr x16, [x16, %[raise_off]]\n"
"br x16\n"
:
: [sig] "i" (SIGSTOP),
[raise_off] "i" (offsetof (FridaApi, raise))
: "x16", "memory");
#else
# error Unsupported architecture
#endif
}
static int
frida_get_errno (void)
{
return *zymbiote.__errno ();
return *frida.__errno ();
}
static int
@@ -276,7 +204,7 @@ frida_connect (int sockfd, const struct sockaddr * addr, socklen_t addrlen)
{
for (;;)
{
if (zymbiote.connect (sockfd, addr, addrlen) == 0)
if (frida.connect (sockfd, addr, addrlen) == 0)
return 0;
if (frida_get_errno () == EINTR)
@@ -291,7 +219,7 @@ frida_sendmsg (int sockfd, const struct msghdr * msg, int flags)
{
for (;;)
{
ssize_t n = zymbiote.sendmsg (sockfd, msg, flags);
ssize_t n = frida.sendmsg (sockfd, msg, flags);
if (n != -1)
return n;
@@ -355,7 +283,7 @@ frida_recv (int sockfd, void * buf, size_t len, int flags)
{
for (;;)
{
ssize_t n = zymbiote.recv (sockfd, buf, len, flags);
ssize_t n = frida.recv (sockfd, buf, len, flags);
if (n != -1)
return n;
File diff suppressed because it is too large. Load diff
+71 -100
View File
@@ -8,42 +8,27 @@ namespace Frida {
private Gee.List<Mapping> maps = new Gee.ArrayList<Mapping> ();
private const uint64 VM_READ = 1;
private const uint64 VM_WRITE = 2;
private const uint64 VM_EXEC = 4;
private const uint64 VM_SHARED = 8;
public class Mapping {
public uint64 start;
public uint64 end;
public size_t size {
get {
return (size_t) (end - start);
}
}
public uint64 file_offset;
public bool readable;
public bool writable;
public bool executable;
public bool shared;
public DevId device;
public uint64 inode;
public string path;
public string module_id;
public uint32 start_gen;
public uint32 end_gen;
}
public static ProcMapsSnapshot from_pid (uint32 pid) {
public static ProcMapsSnapshot from_pid (uint32 pid) throws Error {
var snap = new ProcMapsSnapshot ();
snap.build_from_pid (pid);
return snap;
}
private void build_from_pid (uint32 pid) {
private void build_from_pid (uint32 pid) throws Error {
maps.clear ();
var it = ProcMapsIter.for_pid (pid);
@@ -55,16 +40,10 @@ namespace Frida {
m.end = it.end_address;
m.file_offset = it.file_offset;
string flags = it.flags;
m.readable = flags[0] == 'r';
m.writable = flags[1] == 'w';
m.executable = flags[2] == 'x';
m.shared = flags[3] == 's';
m.device = it.device;
m.inode = it.inode;
m.path = normalize_path (it.path);
m.module_id = normalize_module_id (it.path);
m.start_gen = 1;
m.end_gen = 0;
@@ -73,26 +52,17 @@ namespace Frida {
}
}
public void apply_create (uint32 new_gen, uint64 start, uint64 end, uint64 file_offset, uint64 vm_flags, DevId device,
uint64 inode, string path) {
public void apply_create (uint32 new_gen, uint64 start, uint64 end, uint64 file_offset, DevId device, uint64 inode,
string module_id) {
end_range_at_gen (start, end, new_gen);
var m = new Mapping ();
m.start = start;
m.end = end;
m.file_offset = file_offset;
m.readable = (vm_flags & VM_READ) != 0;
m.writable = (vm_flags & VM_WRITE) != 0;
m.executable = (vm_flags & VM_EXEC) != 0;
m.shared = (vm_flags & VM_SHARED) != 0;
m.device = device;
m.inode = inode;
m.path = path;
m.module_id = module_id;
m.start_gen = new_gen;
m.end_gen = 0;
@@ -138,7 +108,7 @@ namespace Frida {
dead.file_offset = m.file_offset;
dead.device = m.device;
dead.inode = m.inode;
dead.path = m.path;
dead.module_id = m.module_id;
dead.start_gen = m.start_gen;
dead.end_gen = gen;
@@ -158,7 +128,7 @@ namespace Frida {
dead.file_offset = m.file_offset + (start - m.start);
dead.device = m.device;
dead.inode = m.inode;
dead.path = m.path;
dead.module_id = m.module_id;
dead.start_gen = m.start_gen;
dead.end_gen = gen;
@@ -176,7 +146,7 @@ namespace Frida {
dead.file_offset = m.file_offset + (start - m.start);
dead.device = m.device;
dead.inode = m.inode;
dead.path = m.path;
dead.module_id = m.module_id;
dead.start_gen = m.start_gen;
dead.end_gen = gen;
@@ -186,7 +156,7 @@ namespace Frida {
right.file_offset = m.file_offset + (end - m.start);
right.device = m.device;
right.inode = m.inode;
right.path = m.path;
right.module_id = m.module_id;
right.start_gen = m.start_gen;
right.end_gen = 0;
@@ -198,21 +168,13 @@ namespace Frida {
}
}
private static string normalize_path (string path) {
private static string normalize_module_id (string path) {
const string suffix = " (deleted)";
if (path.has_suffix (suffix))
return path.substring (0, path.length - suffix.length);
return path;
}
public Gee.Iterator<Mapping> iterator () {
return maps.iterator ();
}
public Mapping? find_mapping (uint64 addr) {
return find_mapping_at_gen (addr, gen);
}
public Mapping? find_mapping_at_gen (uint64 addr, uint32 gen) {
int lo = 0;
int hi = maps.size - 1;
@@ -262,83 +224,92 @@ namespace Frida {
bool not_ended = m.end_gen == 0 || gen < m.end_gen;
return started && not_ended;
}
}
public Mapping? find_module_by_path (string path) {
return find_module_by_path_at_gen (path, gen);
public class ProcMapsSoEntry {
public uint64 base_address;
public string path;
public DevId device;
public uint64 inode;
private ProcMapsSoEntry (uint64 base_address, string path, DevId device, uint64 inode) {
this.base_address = base_address;
this.path = path;
this.device = device;
this.inode = inode;
}
public Mapping? find_module_by_path_at_gen (string path, uint32 at_gen) {
Mapping? best_base = null;
int best_score = int.MIN;
public static ProcMapsSoEntry? find_by_address (uint pid, uint64 address) {
var iter = ProcMapsIter.for_pid (pid);
while (iter.next ()) {
uint64 start = iter.start_address;
uint64 end = iter.end_address;
if (address >= start && address < end)
return new ProcMapsSoEntry (start, iter.path, iter.device, iter.inode);
}
Mapping? cur_base = null;
uint cur_total = 0;
uint cur_exec = 0;
return null;
}
public static ProcMapsSoEntry? find_by_path (uint pid, string path) {
var candidates = new Gee.ArrayList<Candidate> ();
Candidate? latest_candidate = null;
var iter = ProcMapsIter.for_pid (pid);
#if ANDROID
unowned string libc_path = Gum.Process.get_libc_module ().path;
#endif
for (int i = 0; i < maps.size; i++) {
var m = maps[i];
if (!mapping_alive_at (m, at_gen))
while (iter.next ()) {
string current_path = iter.path;
if (current_path == "[page size compat]")
continue;
unowned string mp = m.path;
if (mp == "[page size compat]")
continue;
if (mp != path) {
consider_candidate (ref best_base, ref best_score, cur_base, cur_total, cur_exec);
cur_base = null;
cur_total = 0;
cur_exec = 0;
if (current_path != path) {
latest_candidate = null;
continue;
}
string flags = iter.flags;
#if ANDROID
if (mp == libc_path && m.shared)
if (current_path == libc_path && flags[3] == 's')
continue;
#endif
if (m.file_offset == 0) {
consider_candidate (ref best_base, ref best_score, cur_base, cur_total, cur_exec);
cur_base = m;
cur_total = 0;
cur_exec = 0;
if (iter.file_offset == 0) {
latest_candidate = new Candidate () {
entry = new ProcMapsSoEntry (iter.start_address, current_path, iter.device, iter.inode),
total_ranges = 0,
executable_ranges = 0,
};
candidates.add (latest_candidate);
}
if (cur_base != null) {
cur_total++;
if (m.executable)
cur_exec++;
if (latest_candidate != null) {
latest_candidate.total_ranges++;
if (flags[2] == 'x')
latest_candidate.executable_ranges++;
}
}
consider_candidate (ref best_base, ref best_score, cur_base, cur_total, cur_exec);
candidates.sort ((a, b) => b.score () - a.score ());
return best_base;
if (candidates.is_empty)
return null;
return candidates.first ().entry;
}
private static void consider_candidate (ref Mapping? best_base, ref int best_score, Mapping? candidate_base, uint total,
uint exec) {
if (candidate_base == null)
return;
private class Candidate {
public ProcMapsSoEntry entry;
public uint total_ranges;
public uint executable_ranges;
int score = score_candidate (total, exec);
if (score > best_score) {
best_score = score;
best_base = candidate_base;
public int score () {
int result = (int) total_ranges;
if (executable_ranges == 0)
result = -result;
return result;
}
}
private static int score_candidate (uint total, uint exec) {
int score = (int) total;
if (exec == 0)
score = -score;
return score;
}
}
public sealed class ProcMapsIter {
+298
View File
@@ -0,0 +1,298 @@
public sealed class Frida.Softwall : Object {
public signal void events_available ();
public State state {
get {
return _state;
}
}
public enum State {
STOPPED,
STARTED,
}
private State _state = STOPPED;
private BpfMap? target_tgids;
private BpfMap? target_uids;
private BpfMap? rules_by_id;
private BpfMap? inode_index;
private BpfMap? stats;
private BpfRingbufReader? events_reader;
private IOChannel? events_channel;
private Source? events_source;
private Gee.Collection<BpfLink> links = new Gee.ArrayList<BpfLink> ();
private uint32 next_rule_id = 1;
protected override void dispose () {
stop ();
base.dispose ();
}
public void start () throws Error {
assert (state == STOPPED);
var obj = BpfObject.open ("softwall.elf", Frida.Data.HelperBackend.get_softwall_elf_blob ().data);
target_tgids = obj.maps.get_by_name ("target_tgids");
target_uids = obj.maps.get_by_name ("target_uids");
rules_by_id = obj.maps.get_by_name ("rules_by_id");
inode_index = obj.maps.get_by_name ("inode_index");
var events = obj.maps.get_by_name ("audit_events");
stats = obj.maps.get_by_name ("stats");
obj.prepare ();
events_reader = new BpfRingbufReader (events);
obj.load ();
foreach (var program in obj.programs) {
var link = program.attach ();
links.add (link);
}
events_channel = new IOChannel.unix_new (events.fd);
arm_events_watch ();
_state = STARTED;
}
public void stop () {
events_source?.destroy ();
events_source = null;
events_channel = null;
events_reader = null;
links.clear ();
stats = null;
inode_index = null;
rules_by_id = null;
target_uids = null;
target_tgids = null;
next_rule_id = 1;
_state = STOPPED;
}
public void add_target_tgid (uint tgid) throws Error {
target_tgids.update_u32_u8 (tgid, 1);
}
public void remove_target_tgid (uint tgid) throws Error {
target_tgids.remove_u32 (tgid);
}
public void add_target_uid (uint uid) throws Error {
target_uids.update_u32_u8 (uid, 1);
}
public void remove_target_uid (uint uid) throws Error {
target_uids.remove_u32 (uid);
}
public enum Action {
DENY,
NOT_FOUND,
}
public uint32 add_file_open_rule (string path, Action action) throws Error {
assert (state == STARTED);
uint64 dev, ino;
resolve_path_to_inode (path, out dev, out ino);
var id = next_rule_id++;
var errno_neg = map_action_to_errno (action);
var rule = FileOpenRule ();
rule.dev = dev;
rule.ino = ino;
rule.errno_neg = errno_neg;
rule._pad0 = 0;
rules_by_id.update_raw ((uint8[]) &id, (uint8[]) &rule);
var key = InodeKey ();
key.dev = dev;
key.ino = ino;
inode_index.update_raw ((uint8[]) &key, (uint8[]) &id);
return id;
}
public void remove_rule (uint32 id) throws Error {
assert (state == STARTED);
var rule = FileOpenRule ();
try {
rules_by_id.lookup_raw ((uint8[]) &id, (uint8[]) &rule);
} catch (Error e) {
throw new Error.INVALID_ARGUMENT ("Unknown rule id: %u".printf (id));
}
var key = InodeKey ();
key.dev = rule.dev;
key.ino = rule.ino;
try {
inode_index.remove_raw ((uint8[]) &key);
} catch (Error e) {
}
rules_by_id.remove_u32 (id);
}
public DrainStatus drain_events (AuditEventHandler on_event) {
var status = events_reader.drain (payload => {
assert (payload.length >= sizeof (AuditEvent));
var e = (AuditEvent *) payload;
return (on_event (e) == CONTINUE)
? BpfRingbufReader.RecordAction.CONTINUE
: BpfRingbufReader.RecordAction.STOP;
});
if (status == DRAINED)
arm_events_watch ();
return (status == DRAINED)
? DrainStatus.DRAINED
: DrainStatus.STOPPED;
}
public enum DrainStatus {
DRAINED,
STOPPED,
}
public delegate EventFlow AuditEventHandler (AuditEvent * ev);
public enum EventFlow {
CONTINUE,
STOP,
}
private void arm_events_watch () {
if (events_source != null)
return;
var src = new IOSource (events_channel, IOCondition.IN);
var state = new AuditEventsWatchState (this);
src.set_callback (state.on_ready);
src.attach (MainContext.get_thread_default ());
events_source = src;
}
private class AuditEventsWatchState : Object {
public unowned Softwall wall;
public AuditEventsWatchState (Softwall wall) {
this.wall = wall;
}
public bool on_ready (IOChannel ch, IOCondition cond) {
wall.on_events_readable ();
return Source.REMOVE;
}
}
private void on_events_readable () {
events_source?.destroy ();
events_source = null;
events_available ();
}
public Stats read_stats () throws Error {
Stats total = Stats ();
uint32 key = 0;
stats.foreach_percpu_value<Stats?> ((uint8[]) &key, (cpu, s) => {
total.emitted_events += s.emitted_events;
total.emitted_bytes += s.emitted_bytes;
total.dropped_events += s.dropped_events;
total.dropped_bytes += s.dropped_bytes;
});
return total;
}
private static int32 map_action_to_errno (Action action) {
switch (action) {
case Action.NOT_FOUND:
return -Posix.ENOENT;
case Action.DENY:
default:
return -Posix.EACCES;
}
}
private static void resolve_path_to_inode (string path, out uint64 dev, out uint64 ino) throws Error {
Posix.Stat st;
if (Posix.stat (path, out st) != 0)
throw new Error.INVALID_ARGUMENT ("Unable to stat path: %s", path);
dev = (uint64) st.st_dev;
ino = (uint64) st.st_ino;
}
public struct Event {
public uint64 time_ns;
public uint32 tgid;
public uint32 tid;
public uint16 type;
public uint16 _pad0;
}
public enum EventType {
AUDIT
}
public struct AuditEvent {
public Event parent;
public uint32 rule_id;
public uint32 _pad0;
}
public struct InodeKey {
public uint64 dev;
public uint64 ino;
}
private struct FileOpenRule {
public uint64 dev;
public uint64 ino;
public int32 errno_neg;
public uint32 _pad0;
}
public struct Stats {
public uint64 emitted_events;
public uint64 emitted_bytes;
public uint64 dropped_events;
public uint64 dropped_bytes;
}
}
+7 -9
View File
@@ -12,7 +12,6 @@ public sealed class Frida.SymbolResolver : Object {
public uint64 end;
public uint64 file_offset;
public uint64 vm_flags;
public DevId device;
public uint64 inode;
public string? path;
@@ -35,12 +34,12 @@ public sealed class Frida.SymbolResolver : Object {
}
uint mod_idx;
if (!used_index.has_key (m.path)) {
if (!used_index.has_key (m.module_id)) {
mod_idx = used_modules.size;
used_index[m.path] = mod_idx;
used_modules.add (m.path);
used_index[m.module_id] = mod_idx;
used_modules.add (m.module_id);
} else {
mod_idx = used_index[m.path];
mod_idx = used_index[m.module_id];
}
uint64 rel64 = (addr - m.start) + m.file_offset;
@@ -93,7 +92,6 @@ public sealed class Frida.SymbolResolver : Object {
ev.start = start;
ev.end = end;
ev.file_offset = file_offset;
ev.vm_flags = vm_flags;
ev.device = device;
ev.inode = inode;
ev.path = path;
@@ -145,8 +143,8 @@ public sealed class Frida.SymbolResolver : Object {
q.unset (next_gen);
if (ev.is_create) {
string path = make_path (ev.device, ev.inode, ev.path);
snap.apply_create (next_gen, ev.start, ev.end, ev.file_offset, ev.vm_flags, ev.device, ev.inode, path);
string module_id = make_module_id (ev.device, ev.inode, ev.path);
snap.apply_create (next_gen, ev.start, ev.end, ev.file_offset, ev.device, ev.inode, module_id);
} else {
snap.apply_destroy_range (next_gen, ev.start, ev.end);
}
@@ -161,7 +159,7 @@ public sealed class Frida.SymbolResolver : Object {
cache.clear ();
}
private static string make_path (DevId device, uint64 inode, string? path) {
private static string make_module_id (DevId device, uint64 inode, string? path) {
if (path != null)
return path;
+20 -12
View File
@@ -21,7 +21,6 @@ public sealed class Frida.SyscallTracer : Object {
private BpfMap? target_tgids;
private BpfMap? target_uids;
private BpfMap? excluded_syscalls;
private BpfRingbufReader? syscall_events_reader;
private IOChannel? syscall_events_channel;
@@ -52,7 +51,6 @@ public sealed class Frida.SyscallTracer : Object {
target_tgids = obj.maps.get_by_name ("target_tgids");
target_uids = obj.maps.get_by_name ("target_uids");
excluded_syscalls = obj.maps.get_by_name ("excluded_syscalls");
var syscall_events = obj.maps.get_by_name ("syscall_events");
var map_events = obj.maps.get_by_name ("map_events");
stacks = obj.maps.get_by_name ("stacks");
@@ -96,7 +94,6 @@ public sealed class Frida.SyscallTracer : Object {
stats = null;
process_states = null;
stacks = null;
excluded_syscalls = null;
target_uids = null;
target_tgids = null;
@@ -119,11 +116,6 @@ public sealed class Frida.SyscallTracer : Object {
target_uids.remove_u32 (uid);
}
public void exclude_syscall (Abi abi, uint nr) throws Error {
uint64 key = ((uint64) abi << 32) | (uint64) nr;
excluded_syscalls.update_u64_u8 (key, 1);
}
public DrainStatus drain_events (SyscallEventHandler on_event) {
var status = syscall_events_reader.drain (payload => {
assert (payload.length >= sizeof (SyscallEvent));
@@ -234,7 +226,7 @@ public sealed class Frida.SyscallTracer : Object {
resolver.refresh_snapshot (ev->tgid);
var s = ProcessState ();
process_states.lookup_raw ((uint8[]) &ev->tgid, (uint8[]) &s);
s.abi = compute_abi_from_pid (ev->tgid);
s.map_gen = 1;
process_states.update_raw ((uint8[]) &ev->tgid, (uint8[]) &s);
} catch (GLib.Error e) {
@@ -290,6 +282,23 @@ public sealed class Frida.SyscallTracer : Object {
}
}
private static Abi compute_abi_from_pid (uint32 tgid) {
#if X86_64 || ARM64
try {
var cpu = Gum.Linux.cpu_type_from_pid ((Posix.pid_t) tgid);
#if X86_64
return (cpu == IA32) ? Abi.COMPAT32 : Abi.NATIVE;
#elif ARM64
return (cpu == ARM) ? Abi.COMPAT32 : Abi.NATIVE;
#endif
} catch (Gum.Error e) {
return NATIVE;
}
#else
return NATIVE;
#endif
}
public struct Event {
public uint64 time_ns;
public uint32 tgid;
@@ -312,8 +321,7 @@ public sealed class Frida.SyscallTracer : Object {
public struct AttachmentHeader {
public uint16 type;
public uint16 arg_index;
public uint16 capacity;
public uint16 size;
public uint32 len;
}
public enum AttachmentType {
@@ -366,7 +374,7 @@ public sealed class Frida.SyscallTracer : Object {
}
private struct ProcessState {
public uint32 abi;
public uint8 abi;
public uint32 map_gen;
}
+9 -15
View File
@@ -38,10 +38,10 @@ if host_os == 'android' or have_droidy_backend
input: [
'android.resources',
android_helper_dex,
fs.copyfile(helpers_native_prefix / 'x86' / 'zymbiote.elf', 'zymbiote-x86.elf'),
fs.copyfile(helpers_native_prefix / 'x86_64' / 'zymbiote.elf', 'zymbiote-x86_64.elf'),
fs.copyfile(helpers_native_prefix / 'arm' / 'zymbiote.elf', 'zymbiote-arm.elf'),
fs.copyfile(helpers_native_prefix / 'arm64' / 'zymbiote.elf', 'zymbiote-arm64.elf'),
fs.copyfile(helpers_native_prefix / 'x86' / 'zymbiote.bin', 'zymbiote-x86.bin'),
fs.copyfile(helpers_native_prefix / 'x86_64' / 'zymbiote.bin', 'zymbiote-x86_64.bin'),
fs.copyfile(helpers_native_prefix / 'arm' / 'zymbiote.bin', 'zymbiote-arm.bin'),
fs.copyfile(helpers_native_prefix / 'arm64' / 'zymbiote.bin', 'zymbiote-arm64.bin'),
],
output: [
'frida-data-android.vapi',
@@ -321,12 +321,7 @@ if have_local_backend
]
if host_os == 'android'
backend_vala_args_private += [
'--pkg=frida-gum-android-1.0',
'--pkg=android',
'--pkg=jni',
frida_selinux_vala_args,
]
backend_vala_args_private += frida_selinux_vala_args
backend_libs += frida_selinux
backend_deps += frida_selinux_dep
endif
@@ -338,6 +333,7 @@ if have_local_backend
'linux' / 'frida-helper-types.vala',
'linux' / 'activity-sampler.vala',
'linux' / 'syscall-tracer.vala',
'linux' / 'softwall.vala',
'linux' / 'symbol-resolver.vala',
'linux' / 'proc-maps.vala',
]
@@ -367,8 +363,9 @@ if have_local_backend
'linux' / 'frida-helper-backend.resources',
helpers_native_dir / 'bootstrapper.bin',
helpers_native_dir / 'loader.bin',
helpers_bpf_noarch_dir / 'activity-sampler.elf',
helpers_bpf_noarch_dir / 'activity-sampler.elf',
helpers_bpf_arch_dir / 'syscall-tracer.elf',
helpers_bpf_noarch_dir / 'softwall.elf',
],
output: [
'frida-data-helper-backend.vapi',
@@ -384,6 +381,7 @@ if have_local_backend
'@INPUT2@',
'@INPUT3@',
'@INPUT4@',
'@INPUT5@',
],
)
helper_backend_sources += [helper_backend_data]
@@ -575,10 +573,6 @@ if have_fruity_backend
'fruity' / 'plist.vala',
'fruity' / 'plist-service.vala',
'fruity' / 'opack.vala',
'fruity' / 'kcdata.vala',
'fruity' / 'kdebug.vala',
'fruity' / 'kperfdata.vala',
'fruity' / 'cs-signature.vala',
'fruity' / 'network-stack.vala',
'fruity' / 'usb.vala',
'fruity' / 'ncm.vala',
+1 -1
View File
@@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/frida/frida-gum.git
revision = 17.8.0
revision = bda339b66655f29b5e82277b68235addfbd8fac7
depth = 1
[provide]
+12 -12
View File
@@ -1764,9 +1764,9 @@ namespace Frida.HostSessionTest {
Variant? icon = prov.icon;
assert_nonnull (icon);
var dict = new VariantDict (icon);
uint16 width, height;
assert_true (dict.lookup ("width", "q", out width));
assert_true (dict.lookup ("height", "q", out height));
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;
@@ -3296,9 +3296,9 @@ namespace Frida.HostSessionTest {
Variant? icon = prov.icon;
assert_nonnull (icon);
var dict = new VariantDict (icon);
uint16 width, height;
assert_true (dict.lookup ("width", "q", out width));
assert_true (dict.lookup ("height", "q", out height));
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;
@@ -3572,9 +3572,9 @@ namespace Frida.HostSessionTest {
Variant? icon = prov.icon;
if (icon != null) {
var dict = new VariantDict (icon);
uint16 width, height;
assert_true (dict.lookup ("width", "q", out width));
assert_true (dict.lookup ("height", "q", out height));
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;
@@ -4231,9 +4231,9 @@ namespace Frida.HostSessionTest {
Variant? icon = prov.icon;
assert_nonnull (icon);
var dict = new VariantDict (icon);
uint16 width, height;
assert_true (dict.lookup ("width", "q", out width));
assert_true (dict.lookup ("height", "q", out height));
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;
-74
View File
@@ -1,74 +0,0 @@
[CCode (cprefix = "android_", gir_namespace = "Android", gir_version = "1.0")]
namespace Android {
[Compact]
[CCode (cheader_filename = "dlfcn.h", cname = "void", free_function = "dlclose")]
public class Module {
[CCode (cname = "dlopen")]
public static Module? open (string filename, DlOpenFlags flags);
[CCode (cheader_filename = "android/dlext.h", cname = "android_dlopen_ext")]
public static Module? open_ext (string filename, DlOpenFlags flags, DlExtInfo info);
[CCode (cname = "dlsym")]
public void * symbol (string name);
[CCode (cname = "dlerror")]
public static unowned string? get_last_error ();
}
[CCode (cheader_filename = "dlfcn.h", cname = "dlsym")]
public void * dlsym (void * handle, string symbol);
[Flags]
[CCode (cheader_filename = "dlfcn.h", cname = "int", cprefix = "RTLD_", has_type_id = false)]
public enum DlOpenFlags {
LOCAL,
LAZY,
NOW,
NOLOAD,
GLOBAL,
NODELETE,
}
[CCode (cheader_filename = "dlfcn.h", cname = "RTLD_DEFAULT")]
public void * RTLD_DEFAULT;
[CCode (cheader_filename = "dlfcn.h", cname = "RTLD_NEXT")]
public void * RTLD_NEXT;
[Flags]
[CCode (cheader_filename = "android/dlext.h", cprefix = "ANDROID_DLEXT_", has_type_id = false)]
public enum DlExtFlags {
RESERVED_ADDRESS,
RESERVED_ADDRESS_HINT,
WRITE_RELRO,
USE_RELRO,
USE_LIBRARY_FD,
USE_LIBRARY_FD_OFFSET,
FORCE_LOAD,
USE_NAMESPACE,
RESERVED_ADDRESS_RECURSIVE,
}
[CCode (cheader_filename = "android/dlext.h", cname = "android_dlextinfo", has_type_id = false)]
public struct DlExtInfo {
public DlExtFlags flags;
public void * reserved_addr;
public size_t reserved_size;
public int relro_fd;
public int library_fd;
public int64 library_fd_offset;
public Namespace * library_namespace;
}
[CCode (cheader_filename = "android/dlext.h", cname = "struct android_namespace_t", has_type_id = false)]
public struct Namespace {
}
[CCode (cheader_filename = "signal.h", cname = "NSIG")]
public const int NSIG;
}
-189
View File
@@ -1,189 +0,0 @@
[CCode (cheader_filename = "frida-jni.h", gir_namespace = "Jni", gir_version = "1.0")]
namespace JNI {
public const int VERSION_1_1;
public const int VERSION_1_2;
public const int VERSION_1_4;
public const int VERSION_1_6;
[CCode (cname = "jint", cprefix = "JNI_", has_type_id = false)]
public enum Result {
OK,
ERR,
EDETACHED,
EVERSION,
ENOMEM,
EEXIST,
EINVAL,
}
[CCode (cname = "JavaVMInitArgs", has_destroy_function = false)]
public struct VMInitArgs {
public int version;
[CCode (array_length_cname = "nOptions")]
public VMOption[] options;
[CCode (cname = "ignoreUnrecognized")]
public bool ignore_unrecognized;
}
[CCode (cname = "JavaVMOption", has_destroy_function = false)]
public struct VMOption {
[CCode (cname = "optionString")]
public string option_string;
[CCode (cname = "extraInfo")]
public void * extra_info;
}
[CCode (cname = "JavaVMAttachArgs", has_destroy_function = false)]
public struct VMAttachArgs {
public int version;
public string? name;
public ObjectRef * group;
}
[CCode (cname = "jobject", has_type_id = false)]
public struct ObjectRef {}
[CCode (cname = "jclass", has_type_id = false)]
public struct ClassRef {}
[CCode (cname = "jstring", has_type_id = false)]
public struct StringRef {}
[CCode (cname = "jboolean", has_type_id = false)]
public enum Boolean {
FALSE = 0,
TRUE = 1,
}
[CCode (cname = "jthrowable", has_type_id = false)]
public struct ThrowableRef {}
[CCode (cname = "jmethodID", has_type_id = false)]
public struct MethodID {}
[CCode (cname = "struct JNIInvokeInterface")]
public class InvokeInterface {
[CCode (cname = "DestroyJavaVM")]
public DestroyJavaVMFunc destroy_java_vm;
[CCode (cname = "AttachCurrentThread")]
public AttachCurrentThreadFunc attach_current_thread;
[CCode (cname = "DetachCurrentThread")]
public DetachCurrentThreadFunc detach_current_thread;
[CCode (cname = "GetEnv")]
public GetEnvFunc get_env;
[CCode (cname = "AttachCurrentThreadAsDaemon")]
public AttachCurrentThreadFunc attach_current_thread_as_daemon;
}
[CCode (has_target = false)]
public delegate Result DestroyJavaVMFunc (InvokeInterface ** vm);
[CCode (has_target = false)]
public delegate Result AttachCurrentThreadFunc (InvokeInterface ** vm, out NativeInterface ** env, VMAttachArgs * args);
[CCode (has_target = false)]
public delegate Result DetachCurrentThreadFunc (InvokeInterface ** vm);
[CCode (has_target = false)]
public delegate Result GetEnvFunc (InvokeInterface ** vm, out NativeInterface ** env, int version);
[CCode (cname = "struct JNINativeInterface")]
public class NativeInterface {
[CCode (cname = "FindClass")]
public FindClassFunc find_class;
[CCode (cname = "ExceptionOccurred")]
public ExceptionOccurredFunc exception_occurred;
[CCode (cname = "ExceptionClear")]
public ExceptionClearFunc exception_clear;
[CCode (cname = "PushLocalFrame")]
public PushLocalFrameFunc push_local_frame;
[CCode (cname = "PopLocalFrame")]
public PopLocalFrameFunc pop_local_frame;
[CCode (cname = "NewGlobalRef")]
public NewGlobalRefFunc new_global_ref;
[CCode (cname = "DeleteGlobalRef")]
public DeleteGlobalRefFunc delete_global_ref;
[CCode (cname = "DeleteLocalRef")]
public DeleteLocalRefFunc delete_local_ref;
[CCode (cname = "NewObject")]
public NewObjectFunc new_object;
[CCode (cname = "GetObjectClass")]
public GetObjectClassFunc get_object_class;
[CCode (cname = "GetMethodID")]
public GetMethodIDFunc get_method_id;
[CCode (cname = "CallObjectMethod")]
public CallObjectMethodFunc call_object_method;
[CCode (cname = "NewStringUTF")]
public NewStringUTFFunc new_string_utf;
[CCode (cname = "GetStringUTFChars")]
public GetStringUTFCharsFunc get_string_utf_chars;
[CCode (cname = "ReleaseStringUTFChars")]
public ReleaseStringUTFCharsFunc release_string_utf_chars;
}
[CCode (has_target = false)]
public delegate ClassRef * FindClassFunc (NativeInterface ** env, string name);
[CCode (has_target = false)]
public delegate ThrowableRef * ExceptionOccurredFunc (NativeInterface ** env);
[CCode (has_target = false)]
public delegate void ExceptionClearFunc (NativeInterface ** env);
[CCode (has_target = false)]
public delegate Result PushLocalFrameFunc (NativeInterface ** env, int capacity);
[CCode (has_target = false)]
public delegate ObjectRef * PopLocalFrameFunc (NativeInterface ** env, ObjectRef * result);
[CCode (has_target = false)]
public delegate ObjectRef * NewGlobalRefFunc (NativeInterface ** env, ObjectRef * obj);
[CCode (has_target = false)]
public delegate void DeleteGlobalRefFunc (NativeInterface ** env, ObjectRef * obj);
[CCode (has_target = false)]
public delegate void DeleteLocalRefFunc (NativeInterface ** env, ObjectRef * obj);
[CCode (has_target = false)]
public delegate ObjectRef * NewObjectFunc (NativeInterface ** env, ClassRef * klass, MethodID * method, ...);
[CCode (has_target = false)]
public delegate ClassRef * GetObjectClassFunc (NativeInterface ** env, ObjectRef * obj);
[CCode (has_target = false)]
public delegate MethodID * GetMethodIDFunc (NativeInterface ** env, ClassRef * klass, string name, string sig);
[CCode (has_target = false)]
public delegate ObjectRef * CallObjectMethodFunc (NativeInterface ** env, ObjectRef * obj, MethodID * method, ...);
[CCode (has_target = false)]
public delegate StringRef * NewStringUTFFunc (NativeInterface ** env, string utf8);
[CCode (has_target = false)]
public delegate unowned string GetStringUTFCharsFunc (NativeInterface ** env, StringRef * str, out Boolean is_copy = null);
[CCode (has_target = false)]
public delegate void ReleaseStringUTFCharsFunc (NativeInterface ** env, StringRef * str, string chars);
}