Skip to content

Commit

Permalink
[WIP] Wire up some more
Browse files Browse the repository at this point in the history
Co-authored-by: Håvard Sørbø <[email protected]>
  • Loading branch information
oleavr and hsorbo committed Sep 19, 2023
1 parent 38890d6 commit 33d8d0a
Showing 1 changed file with 155 additions and 113 deletions.
268 changes: 155 additions & 113 deletions gum/gumswiftapiresolver.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ static void gum_module_metadata_collect_method (GumModuleMetadata * self,
const GumTypeContextDescriptor * holder);
static gboolean gum_module_metadata_collect_export (
const GumExportDetails * details, gpointer user_data);
static void gum_module_metadata_maybe_ingest_thunk (GumModuleMetadata * self,
const gchar * name, GumAddress address);
static gchar * gum_extract_class_name (const gchar * full_name);
static const gchar * gum_find_character_backwards (const gchar * starting_point,
char needle, const gchar * start);
Expand Down Expand Up @@ -616,22 +618,10 @@ gum_module_metadata_collect_class (GumModuleMetadata * self,
methods = GUM_ALIGN ((const GumMethodDescriptor *) (vth + 1),
GumMethodDescriptor);

#if 0
g_printerr ("\n=== %s\n",
(const char *) gum_resolve_relative_direct_ptr (&type->name));
#endif

for (i = 0; i != vth->vtable_size; i++)
{
const GumMethodDescriptor * method = &methods[i];

#if 0
g_printerr ("\tvtable[%u]: flags=0x%08x impl=%p\n",
i,
method->flags,
gum_resolve_relative_direct_ptr (&method->impl));
#endif

gum_module_metadata_collect_method (self, method, i, type);
}

Expand Down Expand Up @@ -726,7 +716,6 @@ gum_module_metadata_collect_method (GumModuleMetadata * self,
break;
}

//g_printerr ("\t\tTODO\n");
break;
}
}
Expand All @@ -741,13 +730,7 @@ gum_module_metadata_collect_method (GumModuleMetadata * self,
if (vtable != NULL)
{
if (vtable_index < vtable->len)
{
func.name = g_strdup (g_ptr_array_index (vtable, vtable_index));
#if 0
if (func.name != NULL)
g_printerr ("\t\t<matched with: %s>\n", func.name);
#endif
}
}
}

Expand Down Expand Up @@ -779,136 +762,195 @@ gum_module_metadata_collect_export (const GumExportDetails * details,
GumFunctionMetadata func;

if (details->type != GUM_EXPORT_FUNCTION)
return TRUE;
goto skip;

len = self->resolver->demangle (details->name, name, sizeof (name));
if (len == 0)
return TRUE;
goto skip;

func.name = g_strdup (name);
func.address = details->address;
g_array_append_val (self->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_module_metadata_maybe_ingest_thunk (self, func.name, func.address);

skip:
return TRUE;
}

static void
gum_module_metadata_maybe_ingest_thunk (GumModuleMetadata * self,
const gchar * name,
GumAddress address)
{
csh capstone;
const uint8_t * code;
size_t size;
cs_insn * insn;
gint vtable_index, vtable_offsets[18];
gboolean end_of_thunk;
guint i;

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);
if (!g_str_has_prefix (name, "dispatch thunk of "))
return;

code = GSIZE_TO_POINTER (details->address);
size = 256;
address = details->address;
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);

insn = cs_malloc (capstone);
code = GSIZE_TO_POINTER (address);
size = 256;

gboolean should_log = FALSE; //strstr (func.name, "CoreDevice.RemoteDevice") != NULL;
insn = cs_malloc (capstone);

if (should_log)
{
g_printerr ("\n=== %s (%s+0x%" G_GINT64_MODIFIER "x)\n",
func.name + strlen ("dispatch thunk of "),
self->name,
details->address - self->base_address);
}
vtable_index = -1;
for (i = 0; i != G_N_ELEMENTS (vtable_offsets); i++)
vtable_offsets[i] = -1;
end_of_thunk = FALSE;

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); */
while (vtable_index == -1 && !end_of_thunk &&
cs_disasm_iter (capstone, &code, &size, &address, insn))
{
const cs_arm64_op * ops = insn->detail->arm64.operands;

#define GUM_REG_IS_TRACKED(reg) (reg >= ARM64_REG_X0 && reg <= ARM64_REG_X17)
#define GUM_REG_INDEX(reg) (reg - ARM64_REG_X0)

switch (insn->id)
switch (insn->id)
{
case ARM64_INS_LDR:
{
case ARM64_INS_LDR:
{
arm64_op_mem * src = &insn->detail->arm64.operands[1].mem;
arm64_reg dst = ops[0].reg;
const arm64_op_mem * src = &ops[1].mem;

/*
* ldr x3, [x16, #0xd0]!
* ...
* braa x3, x16
*/
if (src->base == ARM64_REG_X16)
vtable_index = src->disp / sizeof (gpointer);
if (GUM_REG_IS_TRACKED (dst))
{
gint offset;

break;
if (!(src->base == ARM64_REG_X20 && src->disp == 0))
{
/*
* ldr x3, [x16, #0xd0]!
* ...
* braa x3, x16
*/
vtable_offsets[GUM_REG_INDEX (dst)] = src->disp;
}
}
case ARM64_INS_MOV:

break;
}
case ARM64_INS_MOV:
{
arm64_reg dst = ops[0].reg;
const cs_arm64_op * src = &ops[1];

/*
* mov x17, #0x3b0
* add x16, x16, x17
* ldr x7, [x16]
* ...
* braa x7, x16
*/
if (src->type == ARM64_OP_IMM && GUM_REG_IS_TRACKED (dst))
vtable_offsets[GUM_REG_INDEX (dst)] = src->imm;

break;
}
case ARM64_INS_ADD:
{
arm64_reg dst = ops[0].reg;
arm64_reg left = ops[1].reg;
const cs_arm64_op * right = &ops[2];
gint offset;

if (left == dst)
{
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)
if (right->type == ARM64_OP_REG &&
GUM_REG_IS_TRACKED (right->reg) &&
(offset = vtable_offsets[GUM_REG_INDEX (right->reg)]) != -1)
{
vtable_index = src->imm / sizeof (gpointer);
vtable_index = offset / sizeof (gpointer);
}

break;
if (right->type == ARM64_OP_IMM)
{
vtable_index = right->imm / sizeof (gpointer);
}
}
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;

break;
}
}
case ARM64_INS_BR:
case ARM64_INS_BRAA:
case ARM64_INS_BRAAZ:
case ARM64_INS_BRAB:
case ARM64_INS_BRABZ:
case ARM64_INS_BLR:
case ARM64_INS_BLRAA:
case ARM64_INS_BLRAAZ:
case ARM64_INS_BLRAB:
case ARM64_INS_BLRABZ:
{
arm64_reg target = ops[0].reg;
gint offset;

cs_free (insn, 1);
switch (insn->id)
{
case ARM64_INS_BR:
case ARM64_INS_BRAA:
case ARM64_INS_BRAAZ:
case ARM64_INS_BRAB:
case ARM64_INS_BRABZ:
end_of_thunk = TRUE;
break;
default:
break;
}

cs_close (&capstone);
if (GUM_REG_IS_TRACKED (target) &&
(offset = vtable_offsets[GUM_REG_INDEX (target)]) != -1)
{
vtable_index = offset / sizeof (gpointer);
}

if (vtable_index != -1)
{
const gchar * full_name;
gchar * class_name;
GPtrArray * vtable;
break;
}
case ARM64_INS_RET:
case ARM64_INS_RETAA:
case ARM64_INS_RETAB:
end_of_thunk = TRUE;
break;
}
}

full_name = func.name + strlen ("dispatch thunk of ");
class_name = gum_extract_class_name (full_name);
cs_free (insn, 1);

vtable = g_hash_table_lookup (self->vtables, class_name);
if (vtable == NULL)
{
vtable = g_ptr_array_new_full (64, g_free);
g_hash_table_insert (self->vtables, g_steal_pointer (&class_name), vtable);
}
cs_close (&capstone);

if (vtable_index >= vtable->len)
g_ptr_array_set_size (vtable, vtable_index + 1);
g_free (g_ptr_array_index (vtable, vtable_index));
g_ptr_array_index (vtable, vtable_index) = g_strdup (full_name);
if (vtable_index != -1)
{
const gchar * full_name;
gchar * class_name;
GPtrArray * vtable;

//g_printerr (" => SUCCESS, class_name=\"%s\", vtable_index=%d\n", class_name, vtable_index);
full_name = name + strlen ("dispatch thunk of ");
class_name = gum_extract_class_name (full_name);

g_free (class_name);
}
else
vtable = g_hash_table_lookup (self->vtables, class_name);
if (vtable == NULL)
{
if (should_log)
g_printerr (" => FAILURE, vtable_index not determined\n");
vtable = g_ptr_array_new_full (64, g_free);
g_hash_table_insert (self->vtables, g_steal_pointer (&class_name), vtable);
}
}

return TRUE;
if (vtable_index >= vtable->len)
g_ptr_array_set_size (vtable, vtable_index + 1);
g_free (g_ptr_array_index (vtable, vtable_index));
g_ptr_array_index (vtable, vtable_index) = g_strdup (full_name);

g_free (class_name);
}
}

static gchar *
Expand Down

0 comments on commit 33d8d0a

Please sign in to comment.