diff --git a/gum/gumswiftapiresolver.c b/gum/gumswiftapiresolver.c index f9ec2a87d..f41d364e9 100644 --- a/gum/gumswiftapiresolver.c +++ b/gum/gumswiftapiresolver.c @@ -20,6 +20,7 @@ #include "gummodulemap.h" #include "gumprocess.h" +#include #include #define GUM_DESCRIPTOR_FLAGS_KIND(flags) \ @@ -736,6 +737,95 @@ gum_module_metadata_collect_export (const GumExportDetails * details, func.address = details->address; g_array_append_val (module->functions, func); + if (g_str_has_prefix (func.name, "dispatch thunk of ")) + { + csh capstone; + const uint8_t * code; + size_t size; + uint64_t address; + cs_insn * insn; + gint vtable_index; + gboolean end_of_block; + + gum_cs_arch_register_native (); + cs_open (GUM_DEFAULT_CS_ARCH, GUM_DEFAULT_CS_MODE, &capstone); + cs_option (capstone, CS_OPT_DETAIL, CS_OPT_ON); + + code = GSIZE_TO_POINTER (details->address); + size = 256; + address = details->address; + + insn = cs_malloc (capstone); + + g_printerr ("\n=== %s\n", func.name + strlen ("dispatch thunk of ")); + + vtable_index = -1; + end_of_block = FALSE; + while (vtable_index == -1 && !end_of_block && + cs_disasm_iter (capstone, &code, &size, &address, insn)) + { + /* g_printerr ("%s %s\n", insn->mnemonic, insn->op_str); */ + + switch (insn->id) + { + case ARM64_INS_LDR: + { + arm64_op_mem * src = &insn->detail->arm64.operands[1].mem; + + /* + * ldr x3, [x16, #0xd0]! + * ... + * braa x3, x16 + */ + if (src->base == ARM64_REG_X16) + vtable_index = src->disp / sizeof (gpointer); + + break; + } + case ARM64_INS_MOV: + { + cs_arm64_op * dst = &insn->detail->arm64.operands[0]; + cs_arm64_op * src = &insn->detail->arm64.operands[1]; + + /* + * mov x17, #0x3b0 + * add x16, x16, x17 + * ldr x7, [x16] + * ... + * braa x7, x16 + */ + if (dst->reg == ARM64_REG_X17 && src->type == ARM64_OP_IMM) + { + vtable_index = src->imm / sizeof (gpointer); + } + + break; + } + case ARM64_INS_BR: + case ARM64_INS_BRAA: + case ARM64_INS_BRAAZ: + case ARM64_INS_RET: + case ARM64_INS_RETAA: + case ARM64_INS_RETAB: + end_of_block = TRUE; + break; + } + } + + cs_free (insn, 1); + + cs_close (&capstone); + + if (vtable_index != -1) + { + g_printerr (" => SUCCESS, vtable_index=%d\n", vtable_index); + } + else + { + g_printerr (" => FAILURE, vtable_index not determined\n"); + } + } + return TRUE; } diff --git a/tests/core/apiresolver.c b/tests/core/apiresolver.c index 70f8fc713..7bb38cf0f 100644 --- a/tests/core/apiresolver.c +++ b/tests/core/apiresolver.c @@ -261,13 +261,15 @@ TESTCASE (swift_method_can_be_resolved) g_printerr (">>>\n"); gum_api_resolver_enumerate_matches (fixture->resolver, - "*CoreDevice!*RemoteDevice*", resolve_method_impl, &address, &error); + //"*!*", resolve_method_impl, &address, &error); + "*CoreDevice!*RemoteDevice.*", resolve_method_impl, &address, &error); + //"*CoreDevice!*RemoteDevice*createRSDDevice*", resolve_method_impl, &address, &error); //"*CoreDevice!*RSDDeviceInfo*", resolve_method_impl, &address, &error); //"*hello*!*", resolve_method_impl, &address, &error); g_printerr ("<<<\n"); g_assert_no_error (error); -#if 0 +#if 1 g_printerr ("Waiting for debugger in PID %u...\n", getpid ()); while (!gum_process_is_debugger_attached ()) { @@ -282,7 +284,8 @@ resolve_method_impl (const GumApiDetails * details, { GumAddress * address = user_data; - g_printerr ("Found: %s\n", details->name); + g_printerr ("Found: %s at %p\n", details->name, + GSIZE_TO_POINTER (details->address)); *address = details->address; //return FALSE;