Disassembling some more Dalvik

This commit is contained in:
Pierre Pronchery 2011-04-23 21:06:48 +00:00
parent a4c030b500
commit 5e227be104
4 changed files with 58 additions and 39 deletions

View File

@ -449,7 +449,8 @@ int arch_decode(Arch * arch)
if(arch->plugin->decode == NULL) if(arch->plugin->decode == NULL)
return -error_set_code(1, "%s: %s", arch->plugin->name, return -error_set_code(1, "%s: %s", arch->plugin->name,
"Disassembly not supported"); "Disassembly not supported");
for(offset = 0; arch->plugin->decode(arch->plugin, &call) == 0; for(offset = arch->buffer_pos;
arch->plugin->decode(arch->plugin, &call) == 0;
offset = arch->buffer_pos) offset = arch->buffer_pos)
_decode_print(offset, &call); _decode_print(offset, &call);
return 0; return 0;

View File

@ -17,11 +17,22 @@
#include <System.h> #include <System.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "Asm.h" #include "Asm.h"
/* Dalvik */ /* Dalvik */
/* private */ /* private */
/* types */
typedef struct _DalvikDecode
{
ArchPlugin * plugin;
ArchInstructionCall * call;
uint8_t u8;
} DalvikDecode;
/* constants */ /* constants */
/* register sizes */ /* register sizes */
#define REG(name, size, id) REG_ ## name ## _size = size, #define REG(name, size, id) REG_ ## name ## _size = size,
@ -123,20 +134,21 @@ static int _dalvik_write(ArchPlugin * plugin, ArchInstruction * instruction,
/* dalvik_decode */ /* dalvik_decode */
static int _decode_immediate(ArchPlugin * plugin, ArchInstructionCall * call, static int _decode_immediate(DalvikDecode * dd, size_t i);
size_t i); static int _decode_operand(DalvikDecode * dd, size_t i);
static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call, static int _decode_register(DalvikDecode * dd, size_t i);
size_t i);
static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call,
size_t i);
static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call) static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call)
{ {
DalvikDecode dd;
ArchPluginHelper * helper = plugin->helper; ArchPluginHelper * helper = plugin->helper;
uint8_t u8; uint8_t u8;
ArchInstruction * ai; ArchInstruction * ai;
size_t i; size_t i;
memset(&dd, 0, sizeof(dd));
dd.plugin = plugin;
dd.call = call;
/* FIXME detect end of input */ /* FIXME detect end of input */
if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8)) if(helper->read(helper->arch, &u8, sizeof(u8)) != sizeof(u8))
return -1; return -1;
@ -152,23 +164,25 @@ static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call)
call->operands[1].type = ai->op2; call->operands[1].type = ai->op2;
call->operands[2].type = ai->op3; call->operands[2].type = ai->op3;
for(i = 0; AO_GET_TYPE(call->operands[i].type) != 0; i++) for(i = 0; AO_GET_TYPE(call->operands[i].type) != 0; i++)
if(_decode_operand(plugin, call, i) != 0) if(_decode_operand(&dd, i) != 0)
return -1; return -1;
call->operands_cnt = i; call->operands_cnt = i;
return 0; return 0;
} }
static int _decode_immediate(ArchPlugin * plugin, ArchInstructionCall * call, static int _decode_immediate(DalvikDecode * dd, size_t i)
size_t i)
{ {
ArchPluginHelper * helper = plugin->helper; ArchPluginHelper * helper = dd->plugin->helper;
ArchOperand * ao = &call->operands[i]; ArchOperand * ao = &dd->call->operands[i];
uint8_t u8; uint8_t u8;
uint16_t u16; uint16_t u16;
uint32_t u32; uint32_t u32;
switch(AO_GET_SIZE(call->operands[i].type)) switch(AO_GET_SIZE(dd->call->operands[i].type))
{ {
case 4:
ao->value.immediate.value = dd->u8 & 0xf;
break;
case 8: case 8:
if(helper->read(helper->arch, &u8, sizeof(u8)) if(helper->read(helper->arch, &u8, sizeof(u8))
!= sizeof(u8)) != sizeof(u8))
@ -194,36 +208,41 @@ static int _decode_immediate(ArchPlugin * plugin, ArchInstructionCall * call,
return 0; return 0;
} }
static int _decode_operand(ArchPlugin * plugin, ArchInstructionCall * call, static int _decode_operand(DalvikDecode * dd, size_t i)
size_t i)
{ {
switch(AO_GET_TYPE(call->operands[i].type)) switch(AO_GET_TYPE(dd->call->operands[i].type))
{ {
case AOT_IMMEDIATE: case AOT_IMMEDIATE:
return _decode_immediate(plugin, call, i); return _decode_immediate(dd, i);
case AOT_REGISTER: case AOT_REGISTER:
return _decode_register(plugin, call, i); return _decode_register(dd, i);
default: default:
return -1; return -1;
} }
return 0; return 0;
} }
static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call, static int _decode_register(DalvikDecode * dd, size_t i)
size_t i)
{ {
ArchPluginHelper * helper = plugin->helper; ArchPluginHelper * helper = dd->plugin->helper;
uint32_t id; uint32_t id;
uint8_t u8; uint8_t u8;
uint16_t u16; uint16_t u16;
ArchRegister * ar; ArchRegister * ar;
if(AO_GET_FLAGS(call->operands[i].type) & AOF_IMPLICIT) if(AO_GET_FLAGS(dd->call->operands[i].type) & AOF_IMPLICIT)
id = AO_GET_VALUE(call->operands[i].type); id = AO_GET_VALUE(dd->call->operands[i].type);
else if(AO_GET_FLAGS(call->operands[i].type) & AOF_DALVIK_REGSIZE) else if(AO_GET_FLAGS(dd->call->operands[i].type) & AOF_DALVIK_REGSIZE)
{ {
switch(AO_GET_VALUE(call->operands[i].type)) switch(AO_GET_VALUE(dd->call->operands[i].type))
{ {
case 4:
if(helper->read(helper->arch, &u8, sizeof(u8))
!= sizeof(u8))
return -1;
id = u8 >> 4;
dd->u8 = u8;
break;
case 8: case 8:
if(helper->read(helper->arch, &u8, sizeof(u8)) if(helper->read(helper->arch, &u8, sizeof(u8))
!= sizeof(u8)) != sizeof(u8))
@ -236,8 +255,6 @@ static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call,
return -1; return -1;
id = _htol16(u16); id = _htol16(u16);
break; break;
case 4:
/* FIXME implement */
default: default:
return -1; return -1;
} }
@ -246,6 +263,6 @@ static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call,
return -1; return -1;
if((ar = helper->get_register_by_id_size(helper->arch, id, 32)) == NULL) if((ar = helper->get_register_by_id_size(helper->arch, id, 32)) == NULL)
return -1; return -1;
call->operands[i].value._register.name = ar->name; dd->call->operands[i].value._register.name = ar->name;
return 0; return 0;
} }

View File

@ -26,9 +26,11 @@
#define AOF_DALVIK_REGSIZE 0x2 #define AOF_DALVIK_REGSIZE 0x2
#define OP_v0 AO_REGISTER(AOF_IMPLICIT, 32, REG_v0_id) #define OP_v0 AO_REGISTER(AOF_IMPLICIT, 32, REG_v0_id)
#define OP_REGISTER AO_REGISTER(0, 32, 0) #define OP_REGISTER AO_REGISTER(0, 32, 0)
#define OP_REG4 AO_REGISTER(AOF_DALVIK_REGSIZE, 32, 4)
#define OP_REG8 AO_REGISTER(AOF_DALVIK_REGSIZE, 32, 8) #define OP_REG8 AO_REGISTER(AOF_DALVIK_REGSIZE, 32, 8)
/* immediate values */ /* immediate values */
#define OP_U4 AO_IMMEDIATE(0, 0, 4)
#define OP_U8 AO_IMMEDIATE(0, 0, 8) #define OP_U8 AO_IMMEDIATE(0, 0, 8)
#define OP_U16 AO_IMMEDIATE(0, 0, 16) #define OP_U16 AO_IMMEDIATE(0, 0, 16)
#define OP_U32 AO_IMMEDIATE(0, 0, 32) #define OP_U32 AO_IMMEDIATE(0, 0, 32)
@ -83,9 +85,7 @@
{ "cmpl-double", 0x2f, OP1F, OP_REGISTER, OP_REGISTER, OP_REGISTER }, { "cmpl-double", 0x2f, OP1F, OP_REGISTER, OP_REGISTER, OP_REGISTER },
{ "cmpl-float", 0x2d, OP1F, OP_REGISTER, OP_REGISTER, OP_REGISTER }, { "cmpl-float", 0x2d, OP1F, OP_REGISTER, OP_REGISTER, OP_REGISTER },
{ "const", 0x14, OP1F, OP_REGISTER, OP_U32, AOT_NONE }, { "const", 0x14, OP1F, OP_REGISTER, OP_U32, AOT_NONE },
#if 1 /* XXX really implement */ { "const/4", 0x12, OP1F, OP_REG4, OP_U4, AOT_NONE },
{ "const/4", 0x12, OP1F, OP_v0, OP_U8, AOT_NONE },
#endif
{ "const/16", 0x13, OP1F, OP_REGISTER, OP_U16, AOT_NONE }, { "const/16", 0x13, OP1F, OP_REGISTER, OP_U16, AOT_NONE },
{ "const/high16", 0x15, OP1F, OP_REGISTER, OP_U16, AOT_NONE }, { "const/high16", 0x15, OP1F, OP_REGISTER, OP_U16, AOT_NONE },
{ "const-class", 0x1c, OP1F, OP_REGISTER, OP_U16, AOT_NONE }, { "const-class", 0x1c, OP1F, OP_REGISTER, OP_U16, AOT_NONE },
@ -271,13 +271,13 @@
{ "shr-long/2addr", 0xc4, OP1F, OP_v0, OP_REGISTER, AOT_NONE }, { "shr-long/2addr", 0xc4, OP1F, OP_v0, OP_REGISTER, AOT_NONE },
{ "sparse-switch", 0x2c, OP1F, OP_REGISTER, OP_U32, AOT_NONE }, { "sparse-switch", 0x2c, OP1F, OP_REGISTER, OP_U32, AOT_NONE },
#endif #endif
{ "sput", 0x67, OP1F, OP_REGISTER, OP_U16, AOT_NONE }, { "sput", 0x67, OP1F, OP_REG8, OP_U16, AOT_NONE },
{ "sput-boolean", 0x6a, OP1F, OP_REGISTER, OP_U16, AOT_NONE }, { "sput-boolean", 0x6a, OP1F, OP_REG8, OP_U16, AOT_NONE },
{ "sput-byte", 0x6b, OP1F, OP_REGISTER, OP_U16, AOT_NONE }, { "sput-byte", 0x6b, OP1F, OP_REG8, OP_U16, AOT_NONE },
{ "sput-char", 0x6c, OP1F, OP_REGISTER, OP_U16, AOT_NONE }, { "sput-char", 0x6c, OP1F, OP_REG8, OP_U16, AOT_NONE },
{ "sput-object", 0x69, OP1F, OP_REGISTER, OP_U16, AOT_NONE }, { "sput-object", 0x69, OP1F, OP_REG8, OP_U16, AOT_NONE },
{ "sput-short", 0x6d, OP1F, OP_REGISTER, OP_U16, AOT_NONE }, { "sput-short", 0x6d, OP1F, OP_REG8, OP_U16, AOT_NONE },
{ "sput-wide", 0x68, OP1F, OP_REGISTER, OP_U16, AOT_NONE }, { "sput-wide", 0x68, OP1F, OP_REG8, OP_U16, AOT_NONE },
{ "sub-double", 0xac, OP1F, OP_REGISTER, OP_REGISTER, OP_REGISTER }, { "sub-double", 0xac, OP1F, OP_REGISTER, OP_REGISTER, OP_REGISTER },
{ "sub-double/2addr", 0xcc, OP1F, OP_v0, OP_REGISTER, AOT_NONE }, { "sub-double/2addr", 0xcc, OP1F, OP_v0, OP_REGISTER, AOT_NONE },
{ "sub-float", 0xa7, OP1F, OP_REGISTER, OP_REGISTER, OP_REGISTER }, { "sub-float", 0xa7, OP1F, OP_REGISTER, OP_REGISTER, OP_REGISTER },

View File

@ -162,7 +162,8 @@ static int _decode_file_callback(void * priv, char const * section,
Code * code = priv; Code * code = priv;
if(section != NULL) if(section != NULL)
printf("%s%s:\n\n", "\nDisassembly of section ", section); printf("%s%s:\n", "\nDisassembly of section ", section);
putchar('\n');
return arch_decode_at(code->arch, offset, size, base); return arch_decode_at(code->arch, offset, size, base);
} }