Initial objc support, visual 'i' with cursor and 'wow'

Some more fortunes
Initial support for Objective-C
New command 'wow' to fill block with cyclic hex value
Visual 'i' when cursor enabled uses 'wow'
This commit is contained in:
pancake 2012-11-07 04:25:42 +01:00
parent 2ac70dd5e8
commit ea8dc25221
21 changed files with 231 additions and 36 deletions

View File

@ -104,7 +104,7 @@ Excellent; we can attack in any direction!
Better than an eel in the ass
radare build farm beats the facebook one
Thank you for using radare. Have a nice night!
your r2 was built 20h ago. TOO OLD
Your r2 was built 20h ago. TOO OLD
Enable the PAGER with e scr.pager=less -R
Use e asm.offset=true to show offsets as in the 16bit segment addressing mode
The '?' command can be used to evaluate math expressions. Like this: '? (0x34+22)*4'
@ -115,3 +115,9 @@ Connection lost with the license server, your r2 session will terminate soon.
I swear i didn't knew she had only 8bits!
Set e bin.dwarf=true to load dwarf information at startup
Rename a function using the 'afr newname @ offset' command
You can redefine descriptive commands in the hud file and using the V_ command
Use -j in rabin2 to get the information of the binary in JSON format
this is amazing..
use rarun2 to launch your programs with a predefined environment
You are probably using an old version of r2, go checkout the git!
Run your own r2 scripts in awk using the r2awk program

View File

@ -17,5 +17,6 @@ include ${STATIC_BIN_XTR_PLUGINS}
STATIC_OBJS=$(addprefix $(LTOP)/bin/p/, $(STATIC_OBJ))
OBJS=bin.o bin_meta.o bin_write.o demangle.o dwarf.o
OBJS+=mangling/cxx/cp-demangle.o ${STATIC_OBJS}
OBJS+=mangling/objc.o
include $(TOP)/libr/rules.mk

View File

@ -75,23 +75,23 @@ static int is_data_section(RBinArch *a, RBinSection *s) {
}
static RList* get_strings(RBinArch *a, int min) {
RBinSection *section;
RListIter *iter;
RList *ret;
int count = 0;
if (!(ret = r_list_new ())) {
RListIter *iter;
RBinSection *section;
RList *ret = r_list_new ();
if (!ret) {
eprintf ("Error allocating array\n");
return NULL;
}
ret->free = free;
if (a->o->sections) {
r_list_foreach (a->o->sections, iter, section) {
if (is_data_section (a, section)) {
count ++;
count++;
get_strings_range (a, ret, min,
section->offset, section->offset+section->size, section->rva);
section->offset,
section->offset+section->size,
section->rva);
}
}
}
@ -100,6 +100,14 @@ static RList* get_strings(RBinArch *a, int min) {
return ret;
}
// public api?
static void load_languages(RBin *bin) {
/* load objc information if available */
if (r_bin_lang_objc (bin->cur.o))
eprintf ("ObjectiveC information loaded\n");
/* TODO : do the same for dex, java and c++ name demangling? */
}
static int r_bin_init_items(RBin *bin, int dummy) {
int i;
RListIter *it;
@ -136,6 +144,9 @@ static int r_bin_init_items(RBin *bin, int dummy) {
if (cp->symbols) o->symbols = cp->symbols (a);
if (cp->classes) o->classes = cp->classes (a);
if (cp->lines) o->lines = cp->lines (a);
load_languages (bin);
return R_TRUE;
}

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2011-2012 pancake<@nopcode.org> */
/* radare - LGPL - Copyright 2011-2012 - pancake */
#include <r_bin.h>
#include <cxx/demangle.h>
@ -8,6 +8,7 @@ R_API char *r_bin_demangle_java(const char *str) {
RBuffer *buf;
const char *w = NULL;
int n = 0;
char *ret;
const char *ptr;
int is_array = 0;
int is_ret = 0;
@ -66,11 +67,9 @@ R_API char *r_bin_demangle_java(const char *str) {
w = NULL;
str++;
}
{
char *ret = r_buf_to_string (buf);
r_buf_free (buf);
return ret;
}
ret = r_buf_to_string (buf);
r_buf_free (buf);
return ret;
}
R_API char *r_bin_demangle_cxx(const char *str) {
@ -80,6 +79,111 @@ R_API char *r_bin_demangle_cxx(const char *str) {
return out;
}
R_API char *r_bin_demangle_objc(RBinObject *o, const char *sym) {
char *ret = NULL;
char *clas = NULL;
char *name = NULL;
char *args = NULL;
int i, nargs = 0;
const char *type = NULL;
/* classes */
if (!strncmp (sym, "_OBJC_Class_", 12)) {
ret = malloc (10+strlen (sym));
sprintf (ret, "class %s", sym+12);
if (o) {
RBinClass *c = R_NEW0 (RBinClass);
c->name = strdup (sym+12);
r_list_append (o->classes, c);
}
return ret;
} else
if (!strncmp (sym, "_OBJC_CLASS_$_", 14)) {
ret = malloc (10+strlen (sym));
sprintf (ret, "class %s", sym+14);
if (o) {
RBinClass *c = R_NEW0 (RBinClass);
c->name = strdup (sym+14);
r_list_append (o->classes, c);
}
return ret;
} else
/* fields */
if (!strncmp (sym, "_OBJC_IVAR_$_", 13)) {
char *p;
clas = strdup (sym+13);
p = strchr (clas, '.');
type = "field";
if (p) {
*p = 0;
name = p+1;
} else name = NULL;
} else
/* methods */
if (sym[1] == '[') { // apple style
if (sym[0] == '+') type = "static";
else if (sym[0] == '-') type = "public";
if (type) {
clas = strdup (sym+2);
name = strchr (clas, ' ');
if (name) *name++ = 0;
for (i=0;name[i];i++) {
if (name[i]==']') {
name[i] = 0;
} else
if (name[i]==':') {
nargs++;
name[i] = 0;
}
}
}
} else
if (sym[0]=='_' && sym[2]=='_') { // gnu style
clas = strdup (sym+3);
args = strstr (clas, "__");
if (!args) {
free (clas);
return NULL;
}
*args = 0;
name = strdup (args+2);
args = NULL;
for (i=0; name[i]; i++) {
if (name[i]=='_') {
name[i] = 0;
nargs++;
}
}
if (sym[1] == 'i') { // instance method
type = "public";
} else if (sym[1] == 'c') { // static method
type = "static";
}
}
if (type) {
if (!strcmp (type, "field")) {
ret = malloc (strlen (type)+strlen (name)+32);
sprintf (ret, "field int %s::%s", clas, name);
} else {
if (nargs) {
const char *arg = "int";
args = malloc (((strlen (arg)+4) * nargs)+1);
args[0] = 0;
for(i=0;i<nargs; i++) {
strcat (args, arg);
if (i+1<nargs)
strcat (args, ", ");
}
} else args = strdup ("");
ret = malloc (strlen (type)+strlen (name)+
strlen(clas)+strlen(args)+15);
sprintf (ret, "%s int %s::%s(%s)", type, clas, name, args);
}
}
free (clas);
free (args);
return ret;
}
R_API int r_bin_demangle_type (const char *str) {
// XXX: add
return R_BIN_NM_CXX;

29
libr/bin/mangling/objc.c Normal file
View File

@ -0,0 +1,29 @@
/* radare - LGPL - Copyright 2012 - pancake */
#include <r_bin.h>
R_API int r_bin_lang_objc(RBinObject *o) {
RListIter *iter;
RBinSymbol *sym;
int hasobjc = R_FALSE;
char *dsym;
const char *ft = o->info->rclass;
if (!ft || (!strstr (ft, "mach") && !strstr (ft, "elf")))
return 0;
r_list_foreach (o->symbols, iter, sym) {
if (!hasobjc)
if (!strncmp (sym->name, "_OBJC_", 6))
hasobjc = R_TRUE;
dsym = r_bin_demangle_objc (o, sym->name);
if (dsym) {
// Add type
free (dsym);
}
}
if (hasobjc)
o->info->lang = "objc";
// create class members and set method names
// iterate on symbols to conscruct class/methods
return hasobjc;
}

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2009-2011 nibble<.ds@gmail.com> */
/* radare - LGPL - Copyright 2009-2011 - nibble */
#include <r_types.h>
#include <r_util.h>

View File

@ -44,6 +44,7 @@ static RBinInfo * info(RBinArch *arch) {
strncpy (ret->subsystem, "any", R_BIN_SIZEOF_STRINGS);
strncpy (ret->machine, "Dalvik VM", R_BIN_SIZEOF_STRINGS);
strncpy (ret->arch, "dalvik", R_BIN_SIZEOF_STRINGS);
ret->lang = "java";
ret->bits = 32;
ret->big_endian = 0;
ret->dbg_info = 1 | 4 | 8; /* Stripped | LineNums | Syms */

View File

@ -217,6 +217,7 @@ static RBinInfo* info(RBinArch *arch) {
if(!(ret = R_NEW (RBinInfo)))
return NULL;
memset (ret, '\0', sizeof (RBinInfo));
ret->lang = "C";
strncpy (ret->file, arch->file, R_BIN_SIZEOF_STRINGS);
if ((str = Elf_(r_bin_elf_get_rpath)(arch->bin_obj))) {
strncpy (ret->rpath, str, R_BIN_SIZEOF_STRINGS);

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2009-2012 nibble<.ds@gmail.com> */
/* radare - LGPL - Copyright 2009-2012 - nibble */
#define R_BIN_ELF64 1
#include "bin_elf.c"

View File

@ -58,6 +58,7 @@ static RBinInfo* info(RBinArch *arch) {
if (!(ret = R_NEW (RBinInfo)))
return NULL;
memset (ret, '\0', sizeof (RBinInfo));
ret->lang = NULL;
strncpy (ret->file, arch->file, R_BIN_SIZEOF_STRINGS-1);
strncpy (ret->rpath, "NONE", R_BIN_SIZEOF_STRINGS-1);
strncpy (ret->type, "fs", sizeof (ret->type)-1); // asm.arch

View File

@ -113,6 +113,7 @@ static RBinInfo* info(RBinArch *arch) {
if (!(ret = R_NEW (RBinInfo)))
return NULL;
memset (ret, '\0', sizeof (RBinInfo));
ret->lang = "java";
strncpy (ret->file, arch->file, R_BIN_SIZEOF_STRINGS-1);
strncpy (ret->rpath, "NONE", R_BIN_SIZEOF_STRINGS-1);
strncpy (ret->type, "JAVA CLASS", R_BIN_SIZEOF_STRINGS-1);

View File

@ -148,6 +148,7 @@ static RBinInfo* info(RBinArch *arch) {
RBinInfo *ret = R_NEW0 (RBinInfo);
if (!ret) return NULL;
ret->lang = "c";
strncpy (ret->file, arch->file, R_BIN_SIZEOF_STRINGS);
strncpy (ret->rpath, "NONE", R_BIN_SIZEOF_STRINGS);
if ((str = MACH0_(r_bin_mach0_get_class) (arch->bin_obj))) {

View File

@ -146,9 +146,8 @@ static RBinInfo* info(RBinArch *arch) {
eprintf ("NRELOCS: %x\n", exe->num_relocs);
eprintf ("RELOC : %x\n", exe->reloc_table_offset);
eprintf ("CHKSUM : %x\n", exe->checksum);
if ((ret = R_NEW (RBinInfo)) == NULL)
if ((ret = R_NEW0 (RBinInfo)) == NULL)
return NULL;
memset(ret, '\0', sizeof (RBinInfo));
strncpy (ret->file, arch->file, R_BIN_SIZEOF_STRINGS);
strncpy (ret->rpath, "NONE", R_BIN_SIZEOF_STRINGS);
strncpy (ret->bclass, "NONE", R_BIN_SIZEOF_STRINGS);

View File

@ -142,9 +142,8 @@ static RBinInfo* info(RBinArch *arch) {
if (!(bina = r_bin_p9_get_arch (arch->buf->buf, &bits, &big_endian)))
return NULL;
if ((ret = R_NEW (RBinInfo)) == NULL)
if ((ret = R_NEW0 (RBinInfo)) == NULL)
return NULL;
memset (ret, '\0', sizeof (RBinInfo));
strncpy (ret->file, arch->file, R_BIN_SIZEOF_STRINGS);
strncpy (ret->rpath, "NONE", R_BIN_SIZEOF_STRINGS);
strncpy (ret->bclass, "program", R_BIN_SIZEOF_STRINGS);

View File

@ -164,18 +164,15 @@ static RList* libs(RBinArch *arch) {
static RBinInfo* info(RBinArch *arch) {
char *str;
RBinInfo *ret = NULL;
if((ret = R_NEW (RBinInfo)) == NULL)
return NULL;
memset(ret, '\0', sizeof (RBinInfo));
RBinInfo *ret = R_NEW0 (RBinInfo);
if (!ret) return NULL;
strncpy (ret->file, arch->file, R_BIN_SIZEOF_STRINGS);
strncpy (ret->rpath, "NONE", R_BIN_SIZEOF_STRINGS);
if ((str = PE_(r_bin_pe_get_class) (arch->bin_obj))) {
strncpy (ret->bclass, str, R_BIN_SIZEOF_STRINGS);
free (str);
}
strncpy(ret->rclass, "pe", R_BIN_SIZEOF_STRINGS);
strncpy (ret->rclass, "pe", R_BIN_SIZEOF_STRINGS);
if ((str = PE_(r_bin_pe_get_os) (arch->bin_obj))) {
strncpy (ret->os, str, R_BIN_SIZEOF_STRINGS);
free (str);

View File

@ -86,6 +86,7 @@ static int bin_info (RCore *r, int mode) {
"\"machine\":\"%s\","
"\"arch\":\"%s\","
"\"os\":\"%s\","
"\"lang\":\"%s\","
"\"va\":%s,"
"\"bits\":%d,"
"\"stripped\":%s,"
@ -99,6 +100,7 @@ static int bin_info (RCore *r, int mode) {
info->machine,
info->arch,
info->os,
info->lang?info->lang:"",
info->has_va? "true": "false",
info->bits,
r_str_bool (R_BIN_DBG_STRIPPED (info->dbg_info)),
@ -159,6 +161,7 @@ static int bin_info (RCore *r, int mode) {
"HasVA=%s\n"
"RootClass=%s\n"
"Class=%s\n"
"Language=%s\n"
"Arch=%s %i\n"
"Machine=%s\n"
"OS=%s\n"
@ -171,9 +174,9 @@ static int bin_info (RCore *r, int mode) {
"Relocs=%s\n"
"RPath=%s\n",
info->file, info->type, r_str_bool (info->has_va),
info->rclass, info->bclass,
info->rclass, info->bclass, info->lang?info->lang:"unknown",
info->arch, info->bits, info->machine, info->os,
info->subsystem,
info->subsystem,
r_str_bool (info->big_endian),
r_str_bool (R_BIN_DBG_STRIPPED (info->dbg_info)),
r_str_bool (R_BIN_DBG_STATIC (info->dbg_info)),
@ -541,6 +544,15 @@ static int bin_sections (RCore *r, int mode, ut64 baddr, int va, ut64 at, const
}
r_cons_printf ("]");
} else
if ((mode & R_CORE_BIN_SIMPLE)) {
r_list_foreach (sections, iter, section) {
r_cons_printf ("0x%"PFMT64x" 0x%"PFMT64x" %s %s\n",
baddr+section->rva,
baddr+section->rva+section->size,
r_str_rwx_i (section->srwx),
section->name);
}
} else
if ((mode & R_CORE_BIN_SET)) {
r_flag_space_set (r->flags, "sections");
r_list_foreach (sections, iter, section) {

View File

@ -6,6 +6,7 @@ static int cmd_info(void *data, const char *input) {
int va = core->io->va || core->io->debug;
int mode = (input[1]=='*')?R_CORE_BIN_RADARE:R_CORE_BIN_PRINT;
if (input[1]=='j') mode = R_CORE_BIN_JSON;
if (input[1]=='q') mode = R_CORE_BIN_SIMPLE;
switch (*input) {
case 'o':
if (input[1]==' ')
@ -56,8 +57,12 @@ static int cmd_info(void *data, const char *input) {
break;
case '?':
r_cons_printf (
"Usage: i[aeiIsSz]* ; get info from opened file\n"
"NOTE: Append a '*' to get the output in radare commands\n"
"Usage: i[aeciIsosSz][jq*] ; get info from opened file\n"
"Output mode:\n"
" '*' output in radare commands\n"
" 'j' output in json\n"
" 'q' simple quiet output\n"
"Actions:\n"
" io [file] ; load info from given file (or last opened)\n"
" ia ; show all info (imports, exports, sections..)\n"
" ic ; list classes\n"

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2009-2012 // pancake<nopcode.org> */
/* radare - LGPL - Copyright 2009-2012 - pancake */
/* TODO: simplify using r_write */
static int cmd_write(void *data, const char *input) {
@ -332,6 +332,7 @@ static int cmd_write(void *data, const char *input) {
case 'm':
case 'd':
case 'o':
case 'w':
if (input[2]!=' ') {
r_cons_printf ("Usage: 'wo%c 00 11 22'\n", input[1]);
return 0;
@ -356,6 +357,7 @@ static int cmd_write(void *data, const char *input) {
" wox 0x0203 ; xor cur block with 0203\n"
" woa 02 03 ; add [0203][0203][...] to curblk\n"
"Supported operations:\n"
" wow == write looped value\n"
" woa += addition\n"
" wos -= substraction\n"
" wom *= multiply\n"

View File

@ -71,6 +71,7 @@ R_API int r_core_write_op(RCore *core, const char *arg, char op) {
case 'a': buf[i] += str[j]; break;
case 's': buf[i] -= str[j]; break;
case 'm': buf[i] *= str[j]; break;
case 'w': buf[i] = str[j]; break;
case 'd': buf[i] = (str[j])? buf[i] / str[j]: 0; break;
case 'r': buf[i] >>= str[j]; break;
case 'l': buf[i] <<= str[j]; break;

View File

@ -297,6 +297,12 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
r_cons_show_cursor (R_TRUE);
r_cons_flush ();
r_cons_set_raw (0);
if (core->print->cur_enabled) {
strcpy (buf, "wow ");
r_line_set_prompt ("insert string: ");
if (r_cons_fgets (buf+4, sizeof (buf)-3, 0, NULL) <0)
buf[0]='\0';
} else
if (core->print->col==2) {
strcpy (buf, "w ");
r_line_set_prompt ("insert string: ");
@ -309,9 +315,20 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
buf[0]='\0';
}
if (*buf) {
if (curset) r_core_seek (core, core->offset + cursor, 0);
r_core_cmd (core, buf, 1);
if (curset) r_core_seek (core, core->offset - cursor, 1);
if (core->print->cur_enabled) {
char *p = strdup (buf);
int cur = core->print->cur;
if (cur>=core->blocksize)
cur = core->print->cur-1;
sprintf (buf, "%s @ $$+%i:%i", p, cursor<ocursor?
cursor:ocursor, R_ABS (ocursor-cursor)+1);
r_core_cmd (core, buf, 0);
free (p);
} else {
if (curset) r_core_seek (core, core->offset + cursor, 0);
r_core_cmd (core, buf, 1);
if (curset) r_core_seek (core, core->offset - cursor, 1);
}
}
r_cons_set_raw (1);
r_cons_show_cursor (R_FALSE);
@ -747,11 +764,13 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
" x show xrefs to seek between them\n"
" sS step / step over\n"
//" n/N seek next/previous block\n"
" i/a insert hex (i) or assemble code (a)\n"
" e edit eval configuration variables\n"
" t track flags (browse symbols, functions..)\n"
" T browse anal info and comments\n"
" v visual code analysis menu\n"
" V view graph using cmd.graph (agv?)\n"
" M walk the mounted filesystems\n"
" f/F set/unset flag\n"
" n/N seek next/prev function/flag/hit (scr.nkey)\n"
" b/B toggle breakpoint / automatic block size\n"
@ -759,7 +778,7 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
" yY copy and paste selection\n"
" mK/'K mark/go to Key (any key)\n"
" M show mount points\n"
" _ enter hud mode\n"
" _ enter the hud\n"
" / in cursor mode search in current block\n"
" :cmd run radare command\n"
" ;[-]cmt add/remove comment\n"

View File

@ -60,6 +60,7 @@ typedef struct r_bin_info_t {
char os[R_BIN_SIZEOF_STRINGS];
char subsystem[R_BIN_SIZEOF_STRINGS];
char rpath[R_BIN_SIZEOF_STRINGS];
const char *lang;
int bits;
int has_va;
int big_endian;
@ -250,10 +251,14 @@ R_API int r_bin_load(RBin *bin, const char *file, int dummy);
R_API RBinObject *r_bin_get_object(RBin *bin, int flags);
R_API ut64 r_bin_get_baddr(RBin *bin);
R_API RBinAddr* r_bin_get_sym(RBin *bin, int sym);
R_API char* r_bin_demangle(RBin *bin, const char *str);
R_API int r_bin_demangle_type (const char *str);
R_API char *r_bin_demangle_java(const char *str);
R_API char *r_bin_demangle_cxx(const char *str);
R_API char *r_bin_demangle_objc(RBinObject *a, const char *sym);
R_API int r_bin_lang_objc(RBinObject *a);
R_API RList* r_bin_get_entries(RBin *bin);
R_API RList* r_bin_get_fields(RBin *bin);
R_API RList* r_bin_get_imports(RBin *bin);