* Fix push immediate opcode analysis in basic x86 analysis

* Import simple arm assembler
* Some fixes for the brainfuck disassembler plugin
This commit is contained in:
pancake 2010-09-08 19:49:34 +02:00
parent 3455c738df
commit 183dffcd6b
13 changed files with 265 additions and 41 deletions

1
TODO
View file

@ -10,6 +10,7 @@ Questions
=========
* Merge r_vm into r_anal ?
* Merge r_vm into r_parse ?
* Add rabin2 .! calls into r_core api? r_core_rabin_import(core, "rIs") ?
0.6 RELEASE
===========

View file

@ -206,7 +206,7 @@ int main(int argc, char *argv[])
return 0;
}
if (!r_asm_set_bits (a, bits))
eprintf ("cannot set bits (triying with 32)\n");
eprintf ("WARNING: cannot set asm backend to %d bits\n", bits);
if (file) {
char *content;

View file

@ -1,12 +1,12 @@
Do you want to perform more than one search at a time? '> /k0 keyword1', '> /k1 keyword2' and '> /r 0-1'
Debugger commands are prefixed with '!' because they are accessed via the io plugin system() hook
Isn't your disassembly pretty enought? Try changing values with 'eval asm.'
Isn't your disassembly pretty enought? Try changing values with 'e asm.'
Did you setup your ~/.radarerc today?
You can mark an offset in visual mode with the cursor and the ',' key. Later press '.' to go back
You can debug a program from the graph view (ag command) using standard radare commands
Before entering a 'call' you can identify the arguments passed to it using the 'pm xxi' command
Use the '[' and ']' keys in visual mode to adjust the screen width (scr.width)
Choose your architecture by typing: 'eval asm.arch=ppc' (or arm, java, m68k, intel, intel16 or intel64)
Choose your architecture by typing: 'e asm.arch=ppc' (or arm, java, m68k, intel, intel16 or intel64)
Move between your search hits in visual mode using the 'f' and 'F' keys
Run python scripts with the python hack plugin. ('H python <filename>' command)
Run LUA scripts with the lua hack plugin. ('H lua <filename>' command)
@ -49,29 +49,29 @@ Walk inside your seek history with the 'u' command (undo), and 'U' for redo
Use hasher to calculate hashes of portion blocks of a file
Use zoom.byte=entropy and press 'z' in visual mode to zoom out to see the entropy of the whole file
Use zoom.byte=printable in zoom mode (z key in visual mode) to find strings
Set colors to your screen with 'eval scr.color=true'
Set colors to your screen with 'e scr.color=true'
Press 'C' in visual mode to toggle colors
Trace the register changes when debugging with trace.cmtregs
Move the comments to the right changing their margin with eval asm.cmtmargin
Move the comments to the right changing their margin with e asm.cmtmargin
Execute a command on the visual prompt with cmd.vprompt
Reduce the delta where flag resolving by address is used with cfg.delta
Disable these messages with eval cfg.fortunes=false in your ~/.radarerc
Show offsets in graphs with 'eval graph.offset = true'
Disable these messages with e cfg.fortunes=false in your ~/.radarerc
Show offsets in graphs with 'e graph.offset = true'
Follow a flag in disassembly view (avoids to disasemble out of the visibility of the flag) with asm.follow
Execute a command every time a breakpoint is hitted with 'eval cmd.bp = !my-program'
Disassemble in intel syntax with eval asm.syntax = intel
Execute a command every time a breakpoint is hitted with 'e cmd.bp = !my-program'
Disassemble in intel syntax with e asm.syntax = intel
Change the UID of the debugged process with child.uid (requires root)
Enable full backtrace with dbg.fullbt
Manually modify the DRX registers of the child process with '!dr' command
What do you want to debug today?
Sniff your favorite libusb-based application with LD_PRELOAD=/usr/lib/libusbsniff.so ./your-program
Use '!rsc spcc' to parse structures in memory using C programs
Find cp850 strings with 'eval cfg.encoding=cp850' and '/s'
Find cp850 strings with 'e cfg.encoding=cp850' and '/s'
Enhace your graphs by increasing the size of the block and graph.depth eval variable
Control the height of the terminal on serial consoles with eval scr.height
Use eval file.id=true and eval file.flag=true in your ~/.radarerc to get symbols, strings, .. when loading
Disassemble unsupported architectures with external objdump defined in eval asm.objdump. Use 'pd' command.
Emulate the base address of a file with eval file.baddr
Control the height of the terminal on serial consoles with e scr.height
Use e file.id=true and e file.flag=true in your ~/.radarerc to get symbols, strings, .. when loading
Disassemble unsupported architectures with external objdump defined in e asm.objdump. Use 'pd' command.
Emulate the base address of a file with e file.baddr
Dump the class header information with 'javasm -c <file.class>'. Plugind by radare if file.id=true
Use gradare if you prefer simple frontend for gui users
Feedback, bug reports, patches, ideas are welcome to the mailing list at radare.nopcode.org

View file

@ -295,6 +295,12 @@ static int myaop(RAnal *anal, RAnalOp *aop, ut64 addr, const ut8 *data, int len)
aop->ref = 0; // TODO value of register here! get_offset
aop->stackptr = 4;
break;
case 0x6a: // push $7
aop->type = R_ANAL_OP_TYPE_PUSH;
aop->ref = buf[1];
aop->stackptr = 4;
break;
break;
case 0x5a:
case 0x5b:
case 0x5c:

216
libr/asm/arch/arm/armass.c Normal file
View file

@ -0,0 +1,216 @@
/* radare - LGPL - Copyright 2010 pancake<@nopcode.org> */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
int o;
char op[32];
char *a0, *a1, *a2;
} ArmOpcode;
typedef struct {
const char *name;
int code;
int type;
} ArmOp;
enum {
TYPE_MOV = 1,
TYPE_TST = 2,
TYPE_SWI = 3,
TYPE_BRA = 4,
TYPE_ARI = 5,
};
static ArmOp ops[] = {
{ "adc", 0xa000, TYPE_ARI },
{ "adcs", 0xb000, TYPE_ARI },
{ "add", 0x8000, TYPE_ARI },
{ "adds", 0x9000, TYPE_ARI },
{ "sub", 0x4000, TYPE_ARI },
{ "subs", 0x5000, TYPE_ARI },
{ "sbc", 0xc000, TYPE_ARI },
{ "sbcs", 0xd000, TYPE_ARI },
{ "rsb", 0x6000, TYPE_ARI },
{ "rsbs", 0x7000, TYPE_ARI },
{ "rsc", 0xe000, TYPE_ARI },
{ "rscs", 0xf000, TYPE_ARI },
{ "bl", 0xb, TYPE_BRA },
{ "bx", 0xb, TYPE_BRA },
{ "b", 0xa, TYPE_BRA },
{ "str", 0x4, TYPE_MOV },
{ "mov", 0x3, TYPE_MOV },
{ "mvn", 0, TYPE_MOV },
{ "svc", 0xf, TYPE_SWI }, // ???
{ "and", 0x0, TYPE_TST },
{ "ands", 0x1000, TYPE_TST },
{ "eor", 0x2000, TYPE_TST },
{ "eors", 0x3000, TYPE_TST },
{ "orr", 0x0, TYPE_TST },
{ "bic", 0x0, TYPE_TST },
{ "cmp", 0x0, TYPE_TST },
{ "cmn", 0x0, TYPE_TST },
{ "teq", 0x0, TYPE_TST },
{ "tst", 0xe1, TYPE_TST },
NULL
};
static int getnum(const char *str) {
while (str&&(*str=='$'||*str=='#'))
str++;
if (*str=='0'&&str[1]=='x') {
int x;
if(sscanf(str+2, "%x", &x))
return x;
}
return atoi(str);
}
static int getreg(const char *str) {
if (!str)
return 0;
if (!strcmp(str, "pc"))
return 15;
if (!strcmp(str, "lr"))
return 14;
if (!strcmp(str, "sp"))
return 13;
if (!strcmp(str, "ip"))
return 12;
if (!strcmp(str, "fp"))
return 11;
if (!strcmp(str, "sl"))
return 10;
if (*str=='r')
return atoi (str+1);
return 0; // XXX
}
static int getshift(const char *str) {
if(!str) return 0;
while (str&&*str&&!atoi(str))
str++;
return atoi(str)/2;
}
static void arm_opcode_parse(ArmOpcode *ao, const char *str) {
memset (ao, 0, sizeof (ArmOpcode));
strncpy (ao->op, str, sizeof(ao->op));
ao->a0 = strchr (ao->op, ' ');
if (ao->a0) {
*ao->a0 = 0;
ao->a1 = strchr (++ao->a0, ',');
if (ao->a1) {
*ao->a1 = 0;
ao->a2 = strchr (++ao->a1, ',');
if (ao->a2) {
*ao->a2 = 0;
ao->a2++;
}
}
}
while (ao->a0&&*ao->a0==' ') ao->a0++;
while (ao->a1&&*ao->a1==' ') ao->a1++;
while (ao->a2&&*ao->a2==' ') ao->a2++;
}
static int arm_opcode_cond(ArmOpcode *ao, int delta) {
const char *conds[] = {
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt", "gt", "le", "al", "nv", 0
};
int i, cond = 14; // 'always' is default
char *c = ao->op+delta;
for(i=0;conds[i];i++) {
if (!strcmp(c, conds[i])) {
cond = i;
break;
}
}
ao->o |= cond<<4;
}
static int arm_opcode_name(ArmOpcode *ao) {
int i;
for (i=0;ops[i].name;i++) {
if (!memcmp(ao->op, ops[i].name, strlen (ops[i].name))) {
ao->o = (ops[i].code);//<<24;
arm_opcode_cond(ao, strlen(ops[i].name));
switch(ops[i].type) {
case TYPE_BRA:
// XXX: Needs to calc (eip-off-8)>>2
ao->o |= getnum(ao->a0)<<24;
break;
case TYPE_SWI:
ao->o |= getnum(ao->a0)<<24;
break;
case TYPE_ARI:
ao->o |= getreg(ao->a0)<<20;
ao->o |= getreg(ao->a1)<<8;
ao->o |= getreg(ao->a2)<<24;
break;
case TYPE_MOV:
ao->o |= getreg(ao->a0)<<20;
ao->o |= getnum(ao->a1)<<24;
break;
case TYPE_TST:
ao->o |= getreg(ao->a0)<<20;
ao->o |= getreg(ao->a1)<<24;
ao->o |= getshift(ao->a2)<<16; // shift
break;
}
return 1;
}
}
return 0;
}
// XXX: check endian stuff
int armass_assemble(const char *str) {
ArmOpcode aop = {0};
arm_opcode_parse (&aop, str);
if (!arm_opcode_name (&aop)) {
printf ("Unknown opcode\n");
return -1;
}
////printf ("PARSE (%s) (%s)(%s)(%s)\n", aop.op, aop.a0, aop.a1, aop.a2);
return aop.o;
}
#ifdef MAIN
void display(const char *str) {
char cmd[32];
int op = armass_assemble(str);
printf("%08x %s\n", op, str);
snprintf(cmd, sizeof(cmd), "rasm2 -d -a arm %08x", op);
system(cmd);
}
main() {
#if 0
display("mov r0, 33");
display("mov r1, 33");
display("movne r0, 33");
display("tst r0, r1, lsl #2");
display("svc 0x80");
display("sub r3, r1, r2");
display("add r0, r1, r2");
display("mov fp, 0");
#endif
display("str r0, 33");
display("bx 33");
#if 0
display("b 0x123");
display("bl 0x123");
display("blt 0x123"); // XXX: not supported
#endif
}
#endif

View file

@ -1,5 +1,6 @@
OBJ_ARM=asm_arm.o
OBJ_ARM+=../arch/arm/gnu/arm-dis.o
OBJ_ARM+=../arch/arm/armass.o
STATIC_OBJ+=${OBJ_ARM}
TARGET_ARM=asm_arm.${EXT_SO}

View file

@ -4,6 +4,7 @@
#include <stdarg.h>
#include <string.h>
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
@ -79,6 +80,15 @@ static int disassemble(struct r_asm_t *a, struct r_asm_aop_t *aop, ut8 *buf, ut6
return aop->inst_len;
}
int armass_assemble(const char *str);
static int assemble(RAsm *a, RAsmAop *aop, const char *buf) {
int op = armass_assemble(buf);
if (op==-1)
return -1;
r_mem_copyendian (aop->buf, &op, 4, a->big_endian);
return (a->bits/8);
}
RAsmPlugin r_asm_plugin_arm = {
.name = "arm",
.arch = "arm",
@ -87,7 +97,7 @@ RAsmPlugin r_asm_plugin_arm = {
.init = NULL,
.fini = NULL,
.disassemble = &disassemble,
.assemble = NULL
.assemble = &assemble
};
#ifndef CORELIB

View file

@ -1,4 +1,4 @@
/* radare - GPL3 - Copyright 2009 pancake <youterm.com> - nibble<.ds@gmail.com> */
/* radare - GPL3 - Copyright 2009-2010 pancake <youterm.com> - nibble<.ds@gmail.com> */
#include <stdio.h>
#include <string.h>
@ -8,8 +8,7 @@
#include <r_asm.h>
static int disassemble(struct r_asm_t *a, struct r_asm_aop_t *aop, ut8 *buf, ut64 len)
{
static int disassemble(struct r_asm_t *a, struct r_asm_aop_t *aop, ut8 *buf, ut64 len) {
int i;
char *buf_cp, *b;
@ -64,9 +63,9 @@ static int disassemble(struct r_asm_t *a, struct r_asm_aop_t *aop, ut8 *buf, ut6
RAsmPlugin r_asm_plugin_bf = {
.name = "bf",
.arch = "brainfuck",
.bits = (int[]){ 8, 0 },
.desc = "BF disassembly plugin",
.arch = "bf",
.bits = (int[]){ 8, 16, 32, 0 }, // dummy
.desc = "Brainfuck disassembly plugin",
.init = NULL,
.fini = NULL,
.disassemble = &disassemble,

View file

@ -1,4 +1,4 @@
/* radare - GPL3 - Copyright 2009 nibble<.ds@gmail.com> */
/* radare - GPL3 - Copyright 2009-2010 pancake<nopcode.org> nibble<.ds@gmail.com> */
#include <stdio.h>
#include <string.h>
@ -36,13 +36,9 @@ static int assemble(struct r_asm_t *a, struct r_asm_aop_t *aop, const char *buf)
}
}
}
aop->inst_len = Assemble((char*)buf, a->pc, &asm_obj, oattempt, oconstsize, aop->buf_err);
if (aop->inst_len < 0)
aop->inst_len = 0;
aop->inst_len = R_MAX (0, Assemble((char*)buf, a->pc, &asm_obj, oattempt, oconstsize, aop->buf_err));
if (aop->inst_len > 0)
memcpy(aop->buf, asm_obj.code, aop->inst_len<=R_ASM_BUFSIZE?aop->inst_len:R_ASM_BUFSIZE);
memcpy (aop->buf, asm_obj.code, R_MIN(aop->inst_len, R_ASM_BUFSIZE));
return aop->inst_len;
}

View file

@ -1389,11 +1389,10 @@ static int cmd_print(void *data, const char *input) {
int l, len = core->blocksize;
ut32 tbs = core->blocksize;
/* XXX: This is only for pd/pD ??? */
/* XXX: pd must change bs too */
/* TODO: Change also blocksize for 'pd'.. */
if (input[0] && input[1]) {
l = (int) r_num_math (core->num, input+2);
// exceptions are: disasm and memoryfmt */
/* except disasm and memoryfmt (pd, pm) */
if (input[0] != 'd' && input[0] != 'm') {
if (l>0) len = l;
if (l>tbs) r_core_block_size (core, l);

View file

@ -539,10 +539,9 @@ reaccept:
//pipe_stdout_to_tmp_file((char*)&buf, (char*)ptr+5);
strcpy((char*)buf, "/tmp/.out");
pipefd = r_cons_pipe_open ((const char *)buf, 0);
eprintf("SYSTEM(%s)\n", ptr+6);
//eprintf("SYSTEM(%s)\n", ptr+6);
system((const char*)ptr+6);
r_cons_pipe_close (pipefd);
{
FILE *fd = fopen((char*)buf, "r");
i = 0;

View file

@ -3,11 +3,7 @@
#include "r_core.h"
#include "r_socket.h"
/* TODO: Move inside r_core */
static const int endian = 0;
//static int rtr_n = 0;
//static struct rtr_host_t rtr_host[RTR_MAX_HOSTS];
#define endian core->assembler->big_endian
#define rtr_n core->rtr_n
#define rtr_host core->rtr_host
@ -77,7 +73,7 @@ R_API void r_core_rtr_add(RCore *core, const char *_input) {
char input[1024], *host = NULL, *file = NULL, *ptr = NULL, buf[1024];
int proto, port, fd, i;
strncpy (input, _input, 1020);
strncpy (input, _input, sizeof (input)-4);
/* Parse uri */
if ((ptr = strstr(input, "tcp://"))) {
proto = RTR_PROT_TCP;
@ -127,7 +123,7 @@ R_API void r_core_rtr_add(RCore *core, const char *_input) {
/* read */
eprintf ("waiting... "); fflush(stdout);
r_socket_read (fd, (ut8*)buf, 5);
r_mem_copyendian ((ut8 *)&i, (ut8*)buf+1, 4, endian);
r_mem_copyendian ((ut8 *)&i, (ut8*)buf+1, 4, core->assembler->big_endian);
if (buf[0] != (char)(RTR_RAP_OPEN|RTR_RAP_REPLY) || i<= 0) {
eprintf ("Error: Wrong reply\n");
return;

View file

@ -46,10 +46,11 @@ R_API int r_syscall_setup(RSyscall *ctx, const char *arch, const char *os) {
if (!strcmp (arch, "arm")) {
if (!strcmp (os, "linux"))
ctx->sysptr = syscalls_linux_arm;
else
if (!strcmp (os, "macos") || !strcmp (os, "darwin"))
ctx->sysptr = syscalls_darwin_arm;
else {
eprintf ("r_syscall_setup: Unknown arch '%s'\n", arch);
eprintf ("r_syscall_setup: Unknown OS '%s'\n", os);
return R_FALSE;
}
} else