mirror of
https://github.com/radareorg/r2unity.git
synced 2026-11-08 01:08:44 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
540e6ffb16 | ||
|
|
2b0320c64f | ||
|
|
51701f2fb9 | ||
|
|
5bac14c42e | ||
|
|
7420757a62 | ||
|
|
71f2189d84 |
No files matched your search
+1
-1
@@ -1,7 +1,7 @@
|
||||
project(
|
||||
'r2unity',
|
||||
'c',
|
||||
version: '1.2.0',
|
||||
version: '1.2.2',
|
||||
default_options: [
|
||||
'c_std=c99',
|
||||
'warning_level=2',
|
||||
|
||||
+3
-1
@@ -282,7 +282,9 @@ bool r2unity_find_method_pointers_elf(R2UnityMetadata *meta, const char *path, c
|
||||
};
|
||||
size_t section_count = 0;
|
||||
R2UnityNativeSection *sections = elf_sections (&e, §ion_count);
|
||||
bool ok = r2unity_native_run_view (meta, &view, sections, section_count, options, result);
|
||||
view.sections = sections;
|
||||
view.section_count = section_count;
|
||||
bool ok = r2unity_native_resolve (meta, &view, NULL, options, result);
|
||||
R_FREE (sections);
|
||||
elf_free (&e);
|
||||
return ok;
|
||||
|
||||
+4
-1
@@ -140,6 +140,7 @@ static R2UnityNativeSection *macho_sections(MachO *mo, size_t *count) {
|
||||
for (size_t i = 0; i < mo->nsegs; i++) {
|
||||
const MachSeg *s = &mo->segs[i];
|
||||
ut64 vsize = s->vmsize? s->vmsize: s->filesize;
|
||||
out[i].name = s->name;
|
||||
out[i].vaddr = s->vmaddr;
|
||||
out[i].vsize = vsize;
|
||||
out[i].size = R_MIN (s->filesize, vsize);
|
||||
@@ -169,7 +170,9 @@ bool r2unity_find_method_pointers_macho(R2UnityMetadata *meta, const char *path,
|
||||
};
|
||||
size_t section_count = 0;
|
||||
R2UnityNativeSection *sections = macho_sections (&mo, §ion_count);
|
||||
bool ok = r2unity_native_run_view (meta, &view, sections, section_count, options, result);
|
||||
view.sections = sections;
|
||||
view.section_count = section_count;
|
||||
bool ok = r2unity_native_resolve (meta, &view, NULL, options, result);
|
||||
R_FREE (sections);
|
||||
macho_free (&mo);
|
||||
return ok;
|
||||
|
||||
+607
-190
File diff suppressed because it is too large.
Load diff
@@ -14,9 +14,12 @@ typedef struct {
|
||||
ut64 base_vaddr;
|
||||
ut64 text_lo;
|
||||
ut64 text_hi;
|
||||
const struct r2unity_native_section_t *sections;
|
||||
size_t section_count;
|
||||
} R2UnityNativeView;
|
||||
|
||||
typedef struct {
|
||||
typedef struct r2unity_native_section_t {
|
||||
const char *name;
|
||||
ut64 vaddr;
|
||||
ut64 vsize;
|
||||
ut64 size;
|
||||
@@ -24,12 +27,7 @@ typedef struct {
|
||||
bool is_data;
|
||||
} R2UnityNativeSection;
|
||||
|
||||
bool r2unity_native_parse_code_registration(R2UnityMetadata *meta, R2UnityNativeView *view, ut64 code_registration_va, R2UnityNativeSource source, R2UnityNativeResult *result);
|
||||
ut64 r2unity_native_resolve_override(const R2UnityNativeOptions *options, const char *const *names);
|
||||
bool r2unity_native_result_has_ptrs(const R2UnityNativeResult *result);
|
||||
void r2unity_native_take_heuristic_result(R2UnityNativeResult *result, ut64 *method_ptrs, int ptr_size);
|
||||
bool r2unity_native_scan_sections(R2UnityMetadata *meta, R2UnityNativeView *view, const R2UnityNativeSection *sections, size_t section_count, R2UnityNativeResult *result);
|
||||
bool r2unity_native_run_view(R2UnityMetadata *meta, R2UnityNativeView *view, const R2UnityNativeSection *sections, size_t section_count, const R2UnityNativeOptions *options, R2UnityNativeResult *result);
|
||||
bool r2unity_native_resolve(R2UnityMetadata *meta, R2UnityNativeView *view, RBinFile *bf, const R2UnityNativeOptions *options, R2UnityNativeResult *result);
|
||||
bool r2unity_find_method_pointers_elf(R2UnityMetadata *meta, const char *path, const R2UnityNativeOptions *options, R2UnityNativeResult *result);
|
||||
bool r2unity_find_method_pointers_macho(R2UnityMetadata *meta, const char *path, const R2UnityNativeOptions *options, R2UnityNativeResult *result);
|
||||
bool r2unity_find_method_pointers_pe(R2UnityMetadata *meta, const char *path, const R2UnityNativeOptions *options, R2UnityNativeResult *result);
|
||||
|
||||
+4
-1
@@ -146,6 +146,7 @@ static R2UnityNativeSection *pe_sections(PeImg *pe, size_t *count) {
|
||||
for (size_t i = 0; i < pe->nsecs; i++) {
|
||||
const PeSec *s = &pe->secs[i];
|
||||
ut64 vsize = s->vsize? s->vsize: s->filesize;
|
||||
out[i].name = s->name;
|
||||
out[i].vaddr = s->vaddr;
|
||||
out[i].vsize = vsize;
|
||||
out[i].size = R_MIN (s->filesize, vsize);
|
||||
@@ -175,7 +176,9 @@ bool r2unity_find_method_pointers_pe(R2UnityMetadata *meta, const char *path, co
|
||||
};
|
||||
size_t section_count = 0;
|
||||
R2UnityNativeSection *sections = pe_sections (&pe, §ion_count);
|
||||
bool ok = r2unity_native_run_view (meta, &view, sections, section_count, options, result);
|
||||
view.sections = sections;
|
||||
view.section_count = section_count;
|
||||
bool ok = r2unity_native_resolve (meta, &view, NULL, options, result);
|
||||
R_FREE (sections);
|
||||
pe_free (&pe);
|
||||
return ok;
|
||||
|
||||
+27
-5
@@ -3,8 +3,10 @@
|
||||
|
||||
#include <r_util.h>
|
||||
|
||||
struct r_bin_t;
|
||||
struct r_bin_file_t;
|
||||
#if !defined(R2_BIN_H) && !defined(R2_BIN_DWARF_H)
|
||||
typedef struct r_bin_t RBin;
|
||||
typedef struct r_bin_file_t RBinFile;
|
||||
#endif
|
||||
|
||||
#define IL2CPP_MAGIC 0xFAB11BAF
|
||||
#define R2UNITY_METADATA_BASE_SECTION_COUNT 31
|
||||
@@ -170,8 +172,7 @@ typedef struct {
|
||||
enum {
|
||||
R2U_INTEROP_PINVOKE = 1, /* managed -> native, [DllImport] */
|
||||
R2U_INTEROP_REVERSE_PINVOKE = 2, /* native -> managed, [MonoPInvokeCallback] */
|
||||
R2U_INTEROP_UNMANAGED_ONLY = 3, /* [UnmanagedCallersOnly] (.NET 5+) */
|
||||
R2U_INTEROP_INTEROP_DATA = 4 /* Il2CppInteropData entry (opaque) */
|
||||
R2U_INTEROP_UNMANAGED_ONLY = 3 /* [UnmanagedCallersOnly] (.NET 5+) */
|
||||
};
|
||||
|
||||
/* A single P/Invoke or reverse-P/Invoke entry.
|
||||
@@ -209,6 +210,24 @@ typedef enum {
|
||||
R2U_NATIVE_SOURCE_HEURISTIC
|
||||
} R2UnityNativeSource;
|
||||
|
||||
typedef enum {
|
||||
R2U_NATIVE_TABLE_REVERSE_PINVOKE_WRAPPERS,
|
||||
R2U_NATIVE_TABLE_GENERIC_METHOD_POINTERS,
|
||||
R2U_NATIVE_TABLE_GENERIC_ADJUSTOR_THUNKS,
|
||||
R2U_NATIVE_TABLE_INVOKER_POINTERS,
|
||||
R2U_NATIVE_TABLE_UNRESOLVED_VIRTUAL_CALL_POINTERS,
|
||||
R2U_NATIVE_TABLE_UNRESOLVED_INSTANCE_CALL_POINTERS,
|
||||
R2U_NATIVE_TABLE_UNRESOLVED_STATIC_CALL_POINTERS,
|
||||
R2U_NATIVE_TABLE_INTEROP_DATA,
|
||||
R2U_NATIVE_TABLE_WINDOWS_RUNTIME_FACTORY_TABLE,
|
||||
R2U_NATIVE_TABLE_COUNT
|
||||
} R2UnityNativeTableId;
|
||||
|
||||
typedef struct {
|
||||
ut64 va;
|
||||
ut64 count;
|
||||
} R2UnityNativeTable;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
ut64 va;
|
||||
@@ -230,6 +249,7 @@ typedef struct {
|
||||
ut64 metadata_registration_va;
|
||||
ut64 method_pointers_va;
|
||||
ut64 code_gen_modules_va;
|
||||
R2UnityNativeTable tables[R2U_NATIVE_TABLE_COUNT];
|
||||
int ptr_size;
|
||||
} R2UnityNativeResult;
|
||||
|
||||
@@ -255,6 +275,7 @@ R_API R2UnityInterop *r2unity_enumerate_pinvokes(R2UnityMetadata *meta, size_t *
|
||||
* Returns methods tagged with [MonoPInvokeCallback] or [UnmanagedCallersOnly].
|
||||
* Pre-v29 metadata returns NULL (attribute ctor args live in generator stubs). */
|
||||
R_API R2UnityInterop *r2unity_enumerate_reverse_pinvokes(R2UnityMetadata *meta, size_t *count);
|
||||
R_API bool r2unity_enrich_reverse_pinvokes_native(R2UnityMetadata *meta, const char *path, const R2UnityNativeOptions *options, R2UnityInterop **items, size_t *count);
|
||||
R_API void r2unity_free_interop(R2UnityInterop *items, size_t count);
|
||||
R_API char *r2unity_sbom_tostring(R2UnityMetadata *meta, const char *exe_path, const char *metadata_path, R2UnitySbomFormat format);
|
||||
R_API const char *r2unity_unity_range_from_wire(int wire);
|
||||
@@ -264,12 +285,13 @@ R_API ut64 r2unity_metadata_section_entry_size(R2UnityMetadata *meta, R2UMetadat
|
||||
R_API ut64 r2unity_metadata_section_count(R2UnityMetadata *meta, R2UMetadataSectionId id);
|
||||
R_API ut64 r2unity_metadata_header_size(R2UnityMetadata *meta);
|
||||
R_API const char *r2unity_native_source_name(R2UnityNativeSource source);
|
||||
R_API const char *r2unity_native_table_name(R2UnityNativeTableId id);
|
||||
R_API const char *const *r2unity_native_code_registration_names(void);
|
||||
R_API const char *const *r2unity_native_metadata_registration_names(void);
|
||||
R_API void r2unity_native_result_fini(R2UnityNativeResult *result);
|
||||
R_API bool r2unity_find_method_pointers(R2UnityMetadata *meta, const char *path, const R2UnityNativeOptions *options, R2UnityNativeResult *result);
|
||||
R_API bool r2unity_find_method_pointers_simple(R2UnityMetadata *meta, const char *path, const R2UnityNativeOptions *options, R2UnityNativeResult *result);
|
||||
R_API bool r2unity_find_method_pointers_rbin(R2UnityMetadata *meta, struct r_bin_t *bin, struct r_bin_file_t *bf, const R2UnityNativeOptions *options, R2UnityNativeResult *result);
|
||||
R_API bool r2unity_find_method_pointers_rbin(R2UnityMetadata *meta, RBin *bin, RBinFile *bf, const R2UnityNativeOptions *options, R2UnityNativeResult *result);
|
||||
|
||||
/* Companion-file discovery.
|
||||
*
|
||||
|
||||
+61
-21
@@ -150,6 +150,18 @@ static void pj_native_result(PJ *pj, const R2UnityNativeResult *native) {
|
||||
pj_kn (pj, "metadata_registration", native? native->metadata_registration_va: 0);
|
||||
pj_kn (pj, "method_pointers", native? native->method_pointers_va: 0);
|
||||
pj_kn (pj, "code_gen_modules", native? native->code_gen_modules_va: 0);
|
||||
pj_ko (pj, "native_tables");
|
||||
for (R2UnityNativeTableId i = 0; i < R2U_NATIVE_TABLE_COUNT; i++) {
|
||||
const R2UnityNativeTable *table = native? &native->tables[i]: NULL;
|
||||
if (!table || !table->va) {
|
||||
continue;
|
||||
}
|
||||
pj_ko (pj, r2unity_native_table_name (i));
|
||||
pj_kn (pj, "count", table->count);
|
||||
pj_kn (pj, "va", table->va);
|
||||
pj_end (pj);
|
||||
}
|
||||
pj_end (pj);
|
||||
}
|
||||
|
||||
static void print_native_comment(const R2UnityNativeResult *native) {
|
||||
@@ -265,8 +277,36 @@ static int interop_cmp(const void *a, const void *b) {
|
||||
return strcmp (xn, yn);
|
||||
}
|
||||
|
||||
static int emit_pinvokes(R2UnityMetadata *meta, const char *exe_path, bool is_json, bool is_r2, bool quiet) {
|
||||
(void)exe_path;
|
||||
static char *interop_flag_name(const char *prefix, const R2UnityInterop *it) {
|
||||
char *name = it->image_name && *it->image_name
|
||||
? r_str_newf ("%s.%s.%s", prefix, it->image_name, it->name)
|
||||
: r_str_newf ("%s.%s", prefix, it->name);
|
||||
if (name) {
|
||||
r_name_filter (name, -1);
|
||||
if (!r_name_check (name)) {
|
||||
R_FREE (name);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static void print_interop_wrapper_flag(const char *name, ut64 wrapper_va) {
|
||||
if (wrapper_va && name) {
|
||||
printf ("'@0x%" PFMT64x "'f %s\n", wrapper_va, name);
|
||||
printf ("'@0x%" PFMT64x "'af+ $$ %s\n", wrapper_va, name);
|
||||
}
|
||||
}
|
||||
|
||||
static void json_interop_wrapper(FILE *f, const R2UnityInterop *it) {
|
||||
if (it->wrapper_va) {
|
||||
fprintf (f, ",\"wrapper_va\":\"0x%" PFMT64x "\"", it->wrapper_va);
|
||||
}
|
||||
if (it->wrapper_index != UINT32_MAX) {
|
||||
fprintf (f, ",\"wrapper_index\":%u", it->wrapper_index);
|
||||
}
|
||||
}
|
||||
|
||||
static int emit_pinvokes(R2UnityMetadata *meta, bool is_json, bool is_r2, bool quiet) {
|
||||
size_t n = 0;
|
||||
R2UnityInterop *items = r2unity_enumerate_pinvokes (meta, &n);
|
||||
if (items && n > 1) {
|
||||
@@ -309,18 +349,16 @@ static int emit_pinvokes(R2UnityMetadata *meta, const char *exe_path, bool is_js
|
||||
if (!it->name) {
|
||||
continue;
|
||||
}
|
||||
char buf[1024];
|
||||
if (it->image_name && *it->image_name) {
|
||||
snprintf (buf, sizeof (buf), "sym.unity.%s.%s", it->image_name, it->name);
|
||||
} else {
|
||||
snprintf (buf, sizeof (buf), "sym.unity.%s", it->name);
|
||||
char *name = interop_flag_name ("sym.unity", it);
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
r_name_filter (buf, -1);
|
||||
if (it->dll_name) {
|
||||
printf ("# PInvoke %s -> %s!%s\n", buf, it->dll_name, it->entry_name? it->entry_name: it->name);
|
||||
printf ("# PInvoke %s -> %s!%s\n", name, it->dll_name, it->entry_name? it->entry_name: it->name);
|
||||
} else {
|
||||
printf ("# PInvoke %s -> <unresolved>\n", buf);
|
||||
printf ("# PInvoke %s -> <unresolved>\n", name);
|
||||
}
|
||||
free (name);
|
||||
}
|
||||
} else {
|
||||
if (!quiet) {
|
||||
@@ -356,10 +394,12 @@ static const char *interop_kind_label(uint8_t kind) {
|
||||
}
|
||||
}
|
||||
|
||||
static int emit_reverse_pinvokes(R2UnityMetadata *meta, const char *exe_path, bool is_json, bool is_r2, bool quiet) {
|
||||
(void)exe_path;
|
||||
static int emit_reverse_pinvokes(R2UnityMetadata *meta, const char *exe_path, const R2UnityNativeOptions *native, bool is_json, bool is_r2, bool quiet) {
|
||||
size_t n = 0;
|
||||
R2UnityInterop *items = r2unity_enumerate_reverse_pinvokes (meta, &n);
|
||||
if (exe_path && *exe_path) {
|
||||
r2unity_enrich_reverse_pinvokes_native (meta, exe_path, native, &items, &n);
|
||||
}
|
||||
if (items && n > 1) {
|
||||
qsort (items, n, sizeof (R2UnityInterop), interop_cmp);
|
||||
}
|
||||
@@ -377,6 +417,7 @@ static int emit_reverse_pinvokes(R2UnityMetadata *meta, const char *exe_path, bo
|
||||
fprintf (f, "\",\"method\":\"");
|
||||
json_escape (f, it->name? it->name: "");
|
||||
fprintf (f, "\",\"token\":\"0x%08x\",\"flags\":\"0x%04x\",\"iflags\":\"0x%04x\",\"attribute\":\"%s\",\"confidence\":%u", it->token, it->flags, it->iflags, interop_kind_label (it->kind), (unsigned)it->confidence);
|
||||
json_interop_wrapper (f, it);
|
||||
fputc ('}', f);
|
||||
}
|
||||
fprintf (f, "]}\n");
|
||||
@@ -386,14 +427,13 @@ static int emit_reverse_pinvokes(R2UnityMetadata *meta, const char *exe_path, bo
|
||||
if (!it->name) {
|
||||
continue;
|
||||
}
|
||||
char buf[1024];
|
||||
if (it->image_name && *it->image_name) {
|
||||
snprintf (buf, sizeof (buf), "sym.unity.reverse.%s.%s", it->image_name, it->name);
|
||||
} else {
|
||||
snprintf (buf, sizeof (buf), "sym.unity.reverse.%s", it->name);
|
||||
char *name = interop_flag_name ("sym.unity.reverse", it);
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
r_name_filter (buf, -1);
|
||||
printf ("# ReversePInvoke %s [%s]\n", buf, interop_kind_label (it->kind));
|
||||
printf ("# ReversePInvoke %s [%s]\n", name, interop_kind_label (it->kind));
|
||||
print_interop_wrapper_flag (name, it->wrapper_va);
|
||||
free (name);
|
||||
}
|
||||
} else {
|
||||
if (!quiet) {
|
||||
@@ -1083,8 +1123,8 @@ int main(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
int rc = reverse_pinvokes
|
||||
? emit_reverse_pinvokes (meta, exe_path, json_one_line, r2_script, quiet)
|
||||
: emit_pinvokes (meta, exe_path, json_one_line, r2_script, quiet);
|
||||
? emit_reverse_pinvokes (meta, exe_path, &native_options, json_one_line, r2_script, quiet)
|
||||
: emit_pinvokes (meta, json_one_line, r2_script, quiet);
|
||||
r2unity_free_metadata (meta);
|
||||
r_unref (buf);
|
||||
free_symbol_overrides (&symbol_overrides);
|
||||
|
||||
+126
-11
@@ -6,6 +6,8 @@
|
||||
#include <r_lib.h>
|
||||
#include "../lib/lib.h"
|
||||
|
||||
#define R2UNITY_NATIVE_TARGET_LIMIT 0x10000
|
||||
|
||||
// clang-format off
|
||||
static const char *g_help_msg[] = {
|
||||
"Usage:", "r2unity[-subcmd]", " Unity IL2CPP analyzer",
|
||||
@@ -14,7 +16,7 @@ static const char *g_help_msg[] = {
|
||||
"r2unity-c", "[*j]", "enumerate classes, inheritance, methods, and fields",
|
||||
"r2unity-D", "", "auto-detect companion files from current binary path",
|
||||
"r2unity-i", "[j]", "summary (metadata version, type/method counts)",
|
||||
"r2unity-s", "[*j]", "apply/list managed method symbols as flags + comments",
|
||||
"r2unity-s", "[*j]", "apply/list managed/native symbols as flags + comments",
|
||||
"r2unity-z", "[j]", "list managed string literals",
|
||||
"r2unity-P", "[*j]", "list P/Invoke (managed -> native)",
|
||||
"r2unity-R", "[*j]", "list reverse-P/Invoke (native -> managed)",
|
||||
@@ -163,6 +165,18 @@ static void pj_native_result(PJ *pj, const R2UnityNativeResult *result) {
|
||||
pj_kn (pj, "metadata_registration", result? result->metadata_registration_va: 0);
|
||||
pj_kn (pj, "method_pointers", result? result->method_pointers_va: 0);
|
||||
pj_kn (pj, "code_gen_modules", result? result->code_gen_modules_va: 0);
|
||||
pj_ko (pj, "native_tables");
|
||||
for (R2UnityNativeTableId i = 0; i < R2U_NATIVE_TABLE_COUNT; i++) {
|
||||
const R2UnityNativeTable *table = result? &result->tables[i]: NULL;
|
||||
if (!table || !table->va) {
|
||||
continue;
|
||||
}
|
||||
pj_ko (pj, r2unity_native_table_name (i));
|
||||
pj_kn (pj, "count", table->count);
|
||||
pj_kn (pj, "va", table->va);
|
||||
pj_end (pj);
|
||||
}
|
||||
pj_end (pj);
|
||||
}
|
||||
|
||||
static void print_native_result(RCore *core, const R2UnityNativeResult *result) {
|
||||
@@ -175,6 +189,54 @@ static void print_native_result(RCore *core, const R2UnityNativeResult *result)
|
||||
result? result->code_gen_modules_va: 0);
|
||||
}
|
||||
|
||||
static void native_flag(RCore *core, bool print, const char *name, ut64 addr, ut32 size) {
|
||||
if (print) {
|
||||
r_cons_printf (core->cons, "'@0x%08"PFMT64x"'f %s %u\n", addr, name, size);
|
||||
} else {
|
||||
r_flag_set (core->flags, name, addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_native_tables(RCore *core, const R2UnityNativeResult *result, bool print) {
|
||||
int ptr_size = result->ptr_size == 4? 4: 8;
|
||||
for (R2UnityNativeTableId i = 0; i < R2U_NATIVE_TABLE_COUNT; i++) {
|
||||
const R2UnityNativeTable *table = &result->tables[i];
|
||||
if (!table->va) {
|
||||
continue;
|
||||
}
|
||||
const char *name = r2unity_native_table_name (i);
|
||||
ut32 size = (ut32)R_MIN ((ut64)UT32_MAX, R_MAX ((ut64)1, table->count * ptr_size));
|
||||
char flag[128];
|
||||
snprintf (flag, sizeof (flag), "r2unity.table.%s", name);
|
||||
native_flag (core, print, flag, table->va, size);
|
||||
ut64 count = R_MIN (table->count, (ut64)R2UNITY_NATIVE_TARGET_LIMIT);
|
||||
if (i >= R2U_NATIVE_TABLE_INTEROP_DATA || !count) {
|
||||
continue;
|
||||
}
|
||||
int len = (int)(count * ptr_size);
|
||||
ut8 *buf = malloc (len);
|
||||
if (!buf || !r_io_read_at (core->io, table->va, buf, len)) {
|
||||
free (buf);
|
||||
continue;
|
||||
}
|
||||
for (ut64 j = 0; j < count; j++) {
|
||||
const ut8 *p = buf + j * ptr_size;
|
||||
ut64 addr = (ptr_size == 8? r_read_le64 (p): (ut64)r_read_le32 (p)) & ~(ut64)1;
|
||||
if (addr <= 0x1000 || !r_io_is_valid_offset (core->io, addr, R_PERM_X)) {
|
||||
continue;
|
||||
}
|
||||
snprintf (flag, sizeof (flag), "sym.r2unity.%s.%" PFMT64u, name, j);
|
||||
native_flag (core, print, flag, addr, 1);
|
||||
if (print) {
|
||||
r_cons_printf (core->cons, "'@0x%08" PFMT64x "'af+ $$ %s\n", addr, flag);
|
||||
} else if (core->anal && !r_anal_get_function_at (core->anal, addr)) {
|
||||
r_anal_create_function (core->anal, flag, addr, R_ANAL_FCN_TYPE_FCN, NULL);
|
||||
}
|
||||
}
|
||||
free (buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Resolve (and on first use, cache into the eval vars) the metadata path for
|
||||
* the current session. Returns a pointer owned by the RConfig, or NULL. */
|
||||
static const char *resolve_metadata_path(RCore *core) {
|
||||
@@ -373,6 +435,12 @@ static bool find_method_pointers(RCore *core, R2UnityMetadata *meta, const char
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool enrich_reverse_pinvokes_native(RCore *core, R2UnityMetadata *meta, const char *path, R2UnityInterop **items, size_t *count) {
|
||||
R2UnityNativeOptions opts = { 0 };
|
||||
native_options_from_core (core, &opts);
|
||||
return path && *path && r2unity_enrich_reverse_pinvokes_native (meta, path, &opts, items, count);
|
||||
}
|
||||
|
||||
static int type_definition_for_type_index(const Il2CppTypeDefinition *types, size_t type_count, int32_t type_index) {
|
||||
if (type_index >= 0) {
|
||||
for (size_t i = 0; i < type_count; i++) {
|
||||
@@ -786,6 +854,9 @@ static int cmd_symbols(RCore *core, char mode) {
|
||||
print_native_result (core, &native_result);
|
||||
}
|
||||
|
||||
if (mode != 'j') {
|
||||
apply_native_tables (core, &native_result, mode == '*');
|
||||
}
|
||||
ut64 applied = 0, listed = 0;
|
||||
for (size_t j = 0; j < method_count; j++) {
|
||||
Il2CppMethodDefinition *m = &methods[j];
|
||||
@@ -982,6 +1053,35 @@ static const char *interop_kind_label(uint8_t kind) {
|
||||
}
|
||||
}
|
||||
|
||||
static void pj_interop_wrapper(PJ *pj, const R2UnityInterop *it) {
|
||||
if (it->wrapper_va) {
|
||||
pj_kn (pj, "wrapper_va", it->wrapper_va);
|
||||
}
|
||||
if (it->wrapper_index != UINT32_MAX) {
|
||||
pj_kn (pj, "wrapper_index", it->wrapper_index);
|
||||
}
|
||||
}
|
||||
|
||||
static char *interop_flag_name(const char *prefix, const R2UnityInterop *it) {
|
||||
char *name = it->image_name && *it->image_name
|
||||
? r_str_newf ("%s.%s.%s", prefix, it->image_name, it->name)
|
||||
: r_str_newf ("%s.%s", prefix, it->name);
|
||||
if (name) {
|
||||
r_name_filter (name, -1);
|
||||
if (!r_name_check (name)) {
|
||||
R_FREE (name);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static void print_interop_wrapper_flag(RCore *core, const char *name, ut64 wrapper_va) {
|
||||
if (wrapper_va && name) {
|
||||
r_cons_printf (core->cons, "'@0x%" PFMT64x "'f %s\n", wrapper_va, name);
|
||||
r_cons_printf (core->cons, "'@0x%" PFMT64x "'af+ $$ %s\n", wrapper_va, name);
|
||||
}
|
||||
}
|
||||
|
||||
static int cmd_interop(RCore *core, bool reverse, char mode) {
|
||||
RBuffer *buf = NULL;
|
||||
R2UnityMetadata *meta = open_metadata (core, &buf);
|
||||
@@ -992,6 +1092,12 @@ static int cmd_interop(RCore *core, bool reverse, char mode) {
|
||||
R2UnityInterop *items = reverse
|
||||
? r2unity_enumerate_reverse_pinvokes (meta, &n)
|
||||
: r2unity_enumerate_pinvokes (meta, &n);
|
||||
if (reverse) {
|
||||
const char *lib = resolve_library_path (core);
|
||||
if (lib) {
|
||||
enrich_reverse_pinvokes_native (core, meta, lib, &items, &n);
|
||||
}
|
||||
}
|
||||
if (items && n > 1) {
|
||||
qsort (items, n, sizeof (R2UnityInterop), interop_cmp);
|
||||
}
|
||||
@@ -1022,6 +1128,7 @@ static int cmd_interop(RCore *core, bool reverse, char mode) {
|
||||
pj_kn (pj, "flags", (ut64)it->flags);
|
||||
pj_kn (pj, "iflags", (ut64)it->iflags);
|
||||
pj_kn (pj, "confidence", (ut64)it->confidence);
|
||||
pj_interop_wrapper (pj, it);
|
||||
if (reverse) {
|
||||
pj_ks (pj, "attribute", interop_kind_label (it->kind));
|
||||
} else {
|
||||
@@ -1039,27 +1146,35 @@ static int cmd_interop(RCore *core, bool reverse, char mode) {
|
||||
pj_end (pj);
|
||||
} else if (mode == '*') {
|
||||
if (it->name) {
|
||||
char flag_buf[1024];
|
||||
const char *prefix = reverse? "sym.unity.reverse": "sym.unity";
|
||||
if (it->image_name && *it->image_name) {
|
||||
snprintf (flag_buf, sizeof (flag_buf), "%s.%s.%s", prefix, it->image_name, it->name);
|
||||
} else {
|
||||
snprintf (flag_buf, sizeof (flag_buf), "%s.%s", prefix, it->name);
|
||||
char *name = interop_flag_name (prefix, it);
|
||||
if (!name) {
|
||||
free (attrs);
|
||||
continue;
|
||||
}
|
||||
r_name_filter (flag_buf, -1);
|
||||
if (reverse) {
|
||||
r_cons_printf (core->cons, "# ReversePInvoke %s [%s]\n", flag_buf, interop_kind_label (it->kind));
|
||||
r_cons_printf (core->cons, "# ReversePInvoke %s [%s]\n", name, interop_kind_label (it->kind));
|
||||
} else if (it->dll_name) {
|
||||
r_cons_printf (core->cons, "# PInvoke %s -> %s!%s\n", flag_buf, it->dll_name, it->entry_name? it->entry_name: it->name);
|
||||
r_cons_printf (core->cons, "# PInvoke %s -> %s!%s\n", name, it->dll_name, it->entry_name? it->entry_name: it->name);
|
||||
} else {
|
||||
r_cons_printf (core->cons, "# PInvoke %s -> <unresolved>\n", flag_buf);
|
||||
r_cons_printf (core->cons, "# PInvoke %s -> <unresolved>\n", name);
|
||||
}
|
||||
if (reverse) {
|
||||
print_interop_wrapper_flag (core, name, it->wrapper_va);
|
||||
}
|
||||
free (name);
|
||||
}
|
||||
} else {
|
||||
if (reverse) {
|
||||
r_cons_printf (core->cons, "%s\t%s\t%s\t%s\t%u\n", it->image_name? it->image_name: "", it->name? it->name: "", interop_kind_label (it->kind), *attrs? attrs: "-", (unsigned)it->confidence);
|
||||
} else {
|
||||
r_cons_printf (core->cons, "%s\t%s\t%s\t%s\t%s\t%u\n", it->image_name? it->image_name: "", it->name? it->name: "", it->dll_name? it->dll_name: "<unresolved>", it->entry_name? it->entry_name: "<default>", *attrs? attrs: "-", (unsigned)it->confidence);
|
||||
r_cons_printf (core->cons, "%s\t%s\t%s\t%s\t%s\t%u\n",
|
||||
it->image_name? it->image_name: "",
|
||||
it->name? it->name: "",
|
||||
it->dll_name? it->dll_name: "<unresolved>",
|
||||
it->entry_name? it->entry_name: "<default>",
|
||||
*attrs? attrs: "-",
|
||||
(unsigned)it->confidence);
|
||||
}
|
||||
}
|
||||
free (attrs);
|
||||
|
||||
Reference in new issue
Block a user