Fix dalvik<->dex class and method name resolutions

This commit is contained in:
pancake 2015-04-12 05:08:15 +02:00
parent 120a9c4b29
commit acd5e4b999
8 changed files with 108 additions and 37 deletions

View File

@ -8,9 +8,7 @@
#include "../../asm/arch/dalvik/opcode.h"
static int dalvik_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
int sz = 1;
sz = dalvik_opcodes[data[0]].len;
int sz = dalvik_opcodes[data[0]].len;
if (op == NULL)
return sz;
@ -274,12 +272,20 @@ static int dalvik_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int l
case 0xb8: // invokestatic
case 0xb6: // invokevirtual
case 0x6e: // invoke-virtual
case 0xef: // execute-inline/range
case 0xf0: // invoke-object-init-range
case 0xf9: // invoke-virtual-quick/range
case 0xfb: // invoke-super-quick/range
{
ut32 vB = (data[3]<<8) | data[2];
op->jump = anal->binb.get_offset (
anal->binb.bin, 'm', vB);
op->fail = addr + sz;
op->type = R_ANAL_OP_TYPE_CALL;
}
break;
case 0x27: // throw
case 0xee: // execute-inline
case 0xef: // execute-inline/range
case 0xed: // throw-verification-error
op->type = R_ANAL_OP_TYPE_SWI;
break;

View File

@ -337,16 +337,17 @@ static int dalvik_disassemble (RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
vC = (buf[5]<<8) | buf[4];
if (buf[0] == 0x25) { // filled-new-array/range
offset = R_ASM_GET_OFFSET(a, 'c', vB);
if (offset == -1)
if (offset == UT64_MAX)
sprintf (str, " {v%i..v%i}, class+%i", vC, vC+vA-1, vB);
else
sprintf (str, " {v%i..v%i}, 0x%"PFMT64x, vC, vC+vA-1, offset);
} else {
offset = R_ASM_GET_OFFSET(a, 'm', vB);
if (offset == -1)
if (offset == UT64_MAX)
sprintf (str, " {v%i..v%i}, method+%i", vC, vC+vA-1, vB);
else
else {
sprintf (str, " {v%i..v%i}, 0x%"PFMT64x, vC, vC+vA-1, offset);
}
}
strasm = r_str_concat (strasm, str);
break;
@ -374,16 +375,18 @@ static int dalvik_disassemble (RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
strasm = r_str_concat (strasm, str);
if (buf[0] == 0x24) { // filled-new-array
offset = R_ASM_GET_OFFSET(a, 'c', vB);
if (offset == -1)
if (offset == UT64_MAX) {
sprintf (str, ", class+%i", vB);
else
} else {
sprintf (str, ", 0x%"PFMT64x" ; 0x%x", offset, vB);
}
} else {
offset = R_ASM_GET_OFFSET(a, 'm', vB);
if (offset == -1)
if (offset == UT64_MAX) {
sprintf (str, ", method+%i", vB);
else
} else {
sprintf (str, ", 0x%"PFMT64x" ; 0x%x", offset, vB);
}
}
strasm = r_str_concat (strasm, str);

View File

@ -6,4 +6,5 @@ TARGET_DALVIK=asm_dalvik.${EXT_SO}
ALL_TARGETS+=${TARGET_DALVIK}
${TARGET_DALVIK}: ${OBJ_DALVIK}
${CC} $(call libname,asm_dalvik) ${LDFLAGS} -I../arch/dalvik ${CFLAGS} -o asm_dalvik.${EXT_SO} ${OBJ_DALVIK}
${CC} $(call libname,asm_dalvik) ${LDFLAGS} \
-I../arch/dalvik ${CFLAGS} -o asm_dalvik.${EXT_SO} ${OBJ_DALVIK}

View File

@ -1612,11 +1612,9 @@ R_API RBinObject *r_bin_get_object(RBin *bin) {
return o;
}
R_API RList* /*<RBinClass>*/r_bin_get_classes(RBin *bin) {
RBinObject *o = r_bin_cur_object (bin);
if (o)
return o->classes;
if (o) return o->classes;
return NULL;
}
@ -1626,7 +1624,6 @@ R_API RBinClass *r_bin_class_new (RBinFile *binfile, const char *name, const cha
RBinClass *c;
if (!o)
return NULL;
list = o->classes;
if (!name) return NULL;
c = r_bin_class_get (binfile, name);

View File

@ -16,6 +16,8 @@
#define dprintf if (0)eprintf
#endif
static Sdb *mdb= NULL;
static int check(RBinFile *arch);
static int check_bytes(const ut8 *buf, ut64 length);
@ -233,7 +235,7 @@ static char *getstr (RBinDexObj *bin, int idx) {
buf2 = r_uleb128 (buf, sizeof (buf), &len);
uleblen = (size_t)(buf2 - buf);
if (len>0 && len < R_BIN_SIZEOF_STRINGS) {
char *str = malloc (len+1);
char *str = calloc (1, len+1);
if (!str) return NULL;
r_buf_read_at (bin->b, (bin->strings[idx])+uleblen,
(ut8*)str, len); //uleblen);
@ -253,7 +255,15 @@ static char *get_string (RBinDexObj *bin, int cid, int idx) {
return NULL;
c_name = getstr (bin, cid);
m_name = getstr (bin, idx);
res = r_str_newf ("%s.%s", c_name, m_name);
if (c_name && *c_name==',') {
res = r_str_newf ("%s", m_name);
} else {
if (c_name && m_name) {
res = r_str_newf ("%s.%s", c_name, m_name);
} else {
res = r_str_newf ("UNKNOWN");
}
}
free (c_name);
free (m_name);
return res;
@ -273,6 +283,18 @@ static char *dex_method_name (RBinDexObj *bin, int idx) {
return get_string (bin, cid, tid);
}
static char *dex_class_name_byid (RBinDexObj *bin, int cid) {
int tid;
if (!bin || !bin->types)
return NULL;
//cid = c->super_class;
if (cid<0 || cid >= bin->header.types_size)
return NULL;
tid = bin->types [cid].descriptor_id;
//int sid = bin->strings[tid];
return get_string (bin, cid, tid);
}
static char *dex_class_name (RBinDexObj *bin, RBinDexClass *c) {
int cid, tid;
if (!bin || !c || !bin->types)
@ -451,6 +473,11 @@ encoded_catch_handler_list handlers
#endif
sym->paddr += 0x10;
r_list_append (bin->methods_list, sym);
/* cache in sdb */
if (!mdb) {
mdb = sdb_new0 ();
}
sdb_num_set (mdb, sdb_fmt(0, "method.%d", MI), sym->paddr, 0);
} else {
//r_list_append (bin->methods_list, sym);
// XXX memleak sym
@ -564,6 +591,7 @@ static RList* methods (RBinFile *arch) {
return bin->methods_list;
}
// wtf?
static void __r_bin_class_free(RBinClass *p) {
r_bin_class_free (p);
}
@ -571,11 +599,11 @@ static void __r_bin_class_free(RBinClass *p) {
static RList* classes (RBinFile *arch) {
struct r_bin_dex_obj_t *bin = (struct r_bin_dex_obj_t *) arch->o->bin_obj;
struct dex_class_t entry;
const int len = 100;
RList *ret = NULL;
char *name = NULL;
RBinClass *class;
int i;
const int len = 100;
char *name = NULL;
if (bin->header.class_size>bin->size) {
eprintf ("Too many classes %d\n", bin->header.class_size);
@ -585,10 +613,9 @@ static RList* classes (RBinFile *arch) {
return NULL;
ret->free = (RListFree)__r_bin_class_free;
for (i = 0; i < bin->header.class_size; i++) {
ut64 class_addr = (ut64) bin->header.class_offset + (sizeof (struct dex_class_t)*i);
// ETOOSLOW
r_buf_read_at (bin->b, (ut64) bin->header.class_offset
+ (sizeof (struct dex_class_t)*i), (ut8*)&entry,
sizeof (struct dex_class_t));
r_buf_read_at (bin->b, class_addr, (ut8*)&entry, sizeof (struct dex_class_t));
// TODO: implement sections.. each section specifies a class boundary
{
free (name);
@ -614,10 +641,12 @@ static RList* classes (RBinFile *arch) {
class = R_NEW0 (RBinClass);
// get source file name (ClassName.java)
// TODO: use RConstr here
class->name = strdup (name[0]<0x41? name+1: name);
class->index = entry.class_id;
//class->name = strdup (name[0]<0x41? name+1: name);
class->name = dex_class_name_byid (bin, entry.class_id);
class->index = entry.class_id + bin->header.class_offset;
// find reference to this class instance
//class->addr = class_addr;
r_list_append (ret, class);
dprintf ("class.%s=%d\n", name[0]==12?name+1:name, entry.class_id);
dprintf ("# access_flags = %x;\n", entry.access_flags);
dprintf ("# super_class = %d;\n", entry.super_class);
@ -651,16 +680,36 @@ static RList* entries(RBinFile *arch) {
return ret;
}
//TODO
static ut64 offset_of_method_idx(RBinFile *arch, struct r_bin_dex_obj_t *dex, int idx) {
int off = dex->header.method_offset +idx;
//(sizeof (struct dex_method_t)*idx);
const char *name = dex_method_name (dex, idx);
//eprintf ("idx=%d off=%d (%s)\n", idx, off, name);
//off = sdb_num_get (mdb, name, NULL);
off = sdb_num_get (mdb, sdb_fmt(0, "method.%d", idx), 0);
//p = r_uleb128 (p, p_end-p, &MI);
// READ CODE
return off;
}
//TODO must return ut64 imho
static int getoffset (RBinFile *arch, int type, int idx) {
struct r_bin_dex_obj_t *dex = arch->o->bin_obj;
switch (type) {
case 'm': // methods
if (dex->header.method_size > idx)
return dex->header.method_offset +
(sizeof (struct dex_method_t)*idx);
//if (dex->header.method_size > idx)
// return offset_of_method_idx (arch, dex, idx);
return offset_of_method_idx (arch, dex, idx);
break;
case 'c': // class
if (dex->header.class_size > idx) {
int off = dex->header.class_offset +idx;
//(sizeof (struct dex_class_t)*idx);
//const char *name = dex_class_name_byid (dex, idx);
//eprintf ("idx=%d off=%d (%s)\n", idx, off, name);
//p = r_uleb128 (p, p_end-p, &MI);
return off;
}
break;
case 'f': // fields
if (dex->header.fields_size > idx)

View File

@ -1449,19 +1449,30 @@ static int bin_classes (RCore *r, int mode) {
iter->p?",":"", c->name, c->index);
}
r_cons_printf ("]");
} else
if (mode & R_CORE_BIN_SIMPLE) {
} else if (mode & R_CORE_BIN_SIMPLE) {
r_list_foreach (cs, iter, c) {
r_cons_printf ("0x%08"PFMT64x" %s %s\n",
c->index, c->name, c->super?c->super:"");
}
} else
if (mode & R_CORE_BIN_SET) {
} else if (mode & R_CORE_BIN_SET) {
// Nothing to set.
} else {
r_flag_space_set (r->flags, "classes");
r_list_foreach (cs, iter, c) {
char str[R_FLAG_NAME_SIZE+1];
char *name = strdup (c->name);
ut64 addr = c->index; //c->addr? c->addr : c->index;
r_name_filter (name, 0);
snprintf (str, R_FLAG_NAME_SIZE, "class.%s", name);
r_flag_set (r->flags, str, addr, 1, 0);
}
} else {
r_cons_printf ("fs classes\n");
r_list_foreach (cs, iter, c) {
char *name = strdup (c->name);
ut64 addr = c->index; //c->addr? c->addr : c->index;
r_name_filter (name, 0);
if (mode) {
r_cons_printf ("f class.%s @ %d\n", c->name, c->index);
r_cons_printf ("f class.%s @ 0x%"PFMT64x"\n", name, addr);
if (c->super)
r_cons_printf ("f super.%s.%s @ %d\n", c->name, c->super, c->index);
r_list_foreach (c->methods, iter2, methname) {
@ -1476,6 +1487,7 @@ static int bin_classes (RCore *r, int mode) {
}
}
// TODO: show belonging methods and fields
free (name);
}
}
return R_TRUE;
@ -1538,7 +1550,8 @@ static void bin_mem_print (RList *mems, int perms, int depth) {
if (mem) {
for (i=0; i < depth; i++)
r_cons_printf (" ");
r_cons_printf ("%8s addr=0x%016"PFMT64x" size=%6d perms=[%s]\n", mem->name, mem->addr, mem->size, r_str_rwx_i (mem->perms & perms));
r_cons_printf ("%8s addr=0x%016"PFMT64x" size=%6d perms=[%s]\n",
mem->name, mem->addr, mem->size, r_str_rwx_i (mem->perms & perms));
if (mem->mirrors)
bin_mem_print (mem->mirrors, (mem->perms & perms), (depth + 1)); //sorry, but anything else would be inefficient
}

View File

@ -970,6 +970,7 @@ eprintf ("++ EFL = 0x%08x %d\n", ctx.EFlags, r_offsetof (CONTEXT, EFlags));
unsigned int inferior_thread_count = 0;
R_DEBUG_REG_T *regs = (R_DEBUG_REG_T*)buf;
unsigned int gp_count = R_DEBUG_STATE_SZ; //sizeof (R_DEBUG_REG_T);
int tid = dbg->tid;
#if 0
// if uncommented, it will break x86-32 debugging from x86-64 (ios simulator f.ex)

View File

@ -274,6 +274,7 @@ typedef struct r_bin_class_t {
char *super;
char *visibility_str;
int index;
//ut64 addr;
RList *methods; // <RBinSymbol>
RList *fields; // <RBinField>
int visibility;