* Initial implementation of rabin2 -c

- Allow to create tiny binaries with r_bin
  - ATM only MACH0 format for x86-32 is supported
  $ ./rabin2 -a x86_32 -c mach0:31c040682a00000081ec04000000cd80 a.out
* Rename r_bin_set_arch{idx} to r_bin_select{idx}
  - New API r_bin_create and r_bin_use_arch()
This commit is contained in:
pancake 2011-07-25 21:10:25 +02:00
parent 1c1a307edc
commit 8d06dd2f02
8 changed files with 318 additions and 54 deletions

View file

@ -33,6 +33,7 @@
#define ACTION_EXTRACT 0x1000
#define ACTION_RELOCS 0x2000
#define ACTION_LISTARCHS 0x4000
#define ACTION_CREATE 0x8000
static struct r_lib_t *l;
static struct r_bin_t *bin = NULL;
@ -42,36 +43,38 @@ static int va = R_FALSE;
static ut64 gbaddr = 0LL;
static char* file = NULL;
static char* output = "out";
static char* create = NULL;
static ut64 at = 0LL;
static char *name = NULL;
static int rabin_show_help() {
printf ("rabin2 [options] [file]\n"
" -A List archs\n"
" -a [arch_bits] Set arch\n"
" -f [str] Select sub-bin named str\n"
" -b [addr] Override baddr\n"
" -e Entrypoint\n"
" -M Main\n"
" -i Imports (symbols imported from libraries)\n"
" -s Symbols (exports)\n"
" -S Sections\n"
" -z Strings\n"
" -I Binary info\n"
" -H Header fields\n"
" -l Linked libraries\n"
" -R Relocations\n"
" -O [str] Write/Extract operations (str=help for help)\n"
" -o [str] Output file/folder for write operations (out by default)\n"
" -r radare output\n"
" -v Use vaddr in radare output\n"
" -m [addr] Show source line at addr\n"
" -L List supported bin plugins\n"
" -@ [addr] Show section, symbol or import at addr\n"
" -n [str] Show section, symbol or import named str\n"
" -x Extract bins contained in file\n"
" -V Show version information\n"
" -h This help\n");
" -A list archs\n"
" -a [arch_bits] set arch\n"
" -b [addr] override baddr\n"
" -c [fmt:C:D] create [fmt] binary with Code and Data hexpairs (see -a)\n"
" -e entrypoint\n"
" -f [str] select sub-bin named str\n"
" -i imports (symbols imported from libraries)\n"
" -s symbols (exports)\n"
" -S sections\n"
" -M main (show address of main symbol)\n"
" -z strings\n"
" -I binary info\n"
" -H header fields\n"
" -l linked libraries\n"
" -R relocations\n"
" -O [str] write/extract operations (str=help for help)\n"
" -o [str] output file/folder for write operations (out by default)\n"
" -r radare output\n"
" -v use vaddr in radare output\n"
" -m [addr] show source line at addr\n"
" -L list supported bin plugins\n"
" -@ [addr] show section, symbol or import at addr\n"
" -n [str] show section, symbol or import named str\n"
" -x extract bins contained in file\n"
" -V show version information\n"
" -h this help\n");
return 1;
}
@ -105,13 +108,13 @@ static int rabin_show_entrypoints() {
static int rabin_show_main() {
RBinAddr *binmain;
ut64 baddr = gbaddr?gbaddr:r_bin_get_baddr (bin);
ut64 baddr = gbaddr? gbaddr: r_bin_get_baddr (bin);
if ((binmain = r_bin_get_sym (bin, R_BIN_SYM_MAIN)) == NULL)
return R_FALSE;
if (rad) {
printf ("fs symbols\n");
printf ("f main @ 0x%08"PFMT64x"\n", va?baddr+binmain->rva:binmain->offset);
printf ("f main @ 0x%08"PFMT64x"\n", va? baddr+binmain->rva: binmain->offset);
} else {
eprintf ("[Main]\n");
printf ("addr=0x%08"PFMT64x" off=0x%08"PFMT64x"\n",
@ -127,7 +130,7 @@ static int rabin_extract(int all) {
// XXX: Wrong for w32 (/)
if (all) {
for (i=0; i<bin->narch; i++) {
r_bin_set_archidx (bin, i);
r_bin_select_idx (bin, i);
if (bin->curarch.info == NULL) {
eprintf ("No extract info found.\n");
} else {
@ -199,18 +202,22 @@ static int rabin_show_relocs() {
if ((relocs = r_bin_get_relocs (bin)) == NULL)
return R_FALSE;
if (rad) printf ("fs relocs\n");
else eprintf ("[Relocations]\n");
r_list_foreach (relocs, iter, reloc) {
if (rad) printf ("f reloc.%s @ 0x%08"PFMT64x"\n", reloc->name, va?baddr+reloc->rva:reloc->offset);
else printf ("sym=%02i addr=0x%08"PFMT64x" off=0x%08"PFMT64x" type=0x%08x %s\n",
if (rad) {
printf ("fs relocs\n");
r_list_foreach (relocs, iter, reloc) {
printf ("f reloc.%s @ 0x%08"PFMT64x"\n", reloc->name, va?baddr+reloc->rva:reloc->offset);
i++;
}
} else {
eprintf ("[Relocations]\n");
r_list_foreach (relocs, iter, reloc) {
printf ("sym=%02i addr=0x%08"PFMT64x" off=0x%08"PFMT64x" type=0x%08x %s\n",
reloc->sym, baddr+reloc->rva, reloc->offset, reloc->type, reloc->name);
i++;
i++;
}
eprintf ("\n%i relocations\n", i);
}
if (!rad) eprintf ("\n%i relocations\n", i);
return R_TRUE;
}
@ -665,7 +672,7 @@ int main(int argc, char **argv) {
r_lib_opendir (l, LIBDIR"/radare2/");
}
while ((c = getopt (argc, argv, "Af:a:B:b:Mm:n:@:VisSzIHelRwO:o:rvLhx")) != -1) {
while ((c = getopt (argc, argv, "Af:a:B:b:c:Mm:n:@:VisSzIHelRwO:o:rvLhx")) != -1) {
switch(c) {
case 'A':
action |= ACTION_LISTARCHS;
@ -673,6 +680,10 @@ int main(int argc, char **argv) {
case 'a':
if (optarg) arch = strdup (optarg);
break;
case 'c':
action = ACTION_CREATE;
create = strdup (optarg);
break;
case 'f':
if (optarg) arch_name = strdup (optarg);
break;
@ -759,10 +770,6 @@ int main(int argc, char **argv) {
if (action == ACTION_HELP || action == ACTION_UNK || file == NULL)
return rabin_show_help ();
if (!r_bin_load (bin, file, R_FALSE) && !r_bin_load (bin, file, R_TRUE)) {
eprintf ("r_bin: Cannot open '%s'\n", file);
return 1;
}
if (arch) {
char *ptr;
ptr = strchr (arch, '_');
@ -771,8 +778,48 @@ int main(int argc, char **argv) {
bits = r_num_math (NULL, ptr+1);
}
}
if (action & ACTION_CREATE) {
RBuffer *b;
int datalen, codelen;
ut8 *data = NULL, *code = NULL;
char *p2, *p = strchr (create, ':');
if (!p) {
eprintf ("Invalid format for -c flag. Use 'format:codehexpair:datahexpair'\n");
return 1;
}
*p++ = 0;
p2 = strchr (p, ':');
if (p2) {
// has data
*p2++ = 0;
data = malloc (strlen (p2));
datalen = r_hex_str2bin (p2, data);
}
code = malloc (strlen (p));
codelen = r_hex_str2bin (p, code);
if (!arch) arch = "x86";
if (!bits) bits = 32;
if (!r_bin_use_arch (bin, arch, bits, create)) {
eprintf ("Cannot set arch\n");
return 1;
}
b = r_bin_create (bin, code, codelen, data, datalen);
if (b) {
if (r_file_dump (file, b->buf, b->length))
eprintf ("dumped %d bytes in '%s'\n", b->length, file);
else eprintf ("error dumping into a.out\n");
r_buf_free (b);
} else eprintf ("Cannot create binary for this format '%s'.\n", create);
r_bin_free (bin);
return 0;
}
if (!r_bin_load (bin, file, R_FALSE) && !r_bin_load (bin, file, R_TRUE)) {
eprintf ("r_bin: Cannot open '%s'\n", file);
return 1;
}
if (action & ACTION_LISTARCHS && (arch || bits || arch_name)) {
if (!r_bin_set_arch (bin, arch, bits, arch_name)) {
if (!r_bin_select (bin, arch, bits, arch_name)) {
r_bin_list_archs (bin);
free (arch);
r_bin_free (bin);

View file

@ -357,10 +357,26 @@ R_API RBin* r_bin_new() {
return bin;
}
R_API int r_bin_set_arch(RBin *bin, const char *arch, int bits, const char *name) {
// TODO: handle ARCH and BITS
R_API int r_bin_use_arch(RBin *bin, const char *arch, int bits, const char *name) {
struct list_head *pos;
list_for_each_prev(pos, &bin->bins) {
RBinPlugin *h = list_entry (pos, RBinPlugin, list);
if (!strcmp (name, h->name)) {
bin->curarch.curplugin = h;
// TODO: set bits and name
return R_TRUE;
}
}
return R_FALSE;
}
// TODO: rename to r_bin_select
R_API int r_bin_select(RBin *bin, const char *arch, int bits, const char *name) {
int i;
for (i = 0; i < bin->narch; i++) {
r_bin_set_archidx (bin, i);
r_bin_select_idx (bin, i);
if (!bin->curarch.info || !bin->curarch.file ||
(arch && !strstr (bin->curarch.info->arch, arch)) ||
(bits && bits != bin->curarch.info->bits) ||
@ -371,7 +387,8 @@ R_API int r_bin_set_arch(RBin *bin, const char *arch, int bits, const char *name
return R_FALSE;
}
R_API int r_bin_set_archidx(RBin *bin, int idx) {
// TODO: rename to r_bin_select_idx
R_API int r_bin_select_idx(RBin *bin, int idx) {
r_bin_free_items (bin);
if (r_bin_extract (bin, idx))
return r_bin_init_items (bin, R_FALSE);
@ -381,7 +398,7 @@ R_API int r_bin_set_archidx(RBin *bin, int idx) {
R_API void r_bin_list_archs(RBin *bin) {
int i;
for (i = 0; i < bin->narch; i++)
if (r_bin_set_archidx (bin, i) && bin->curarch.info)
if (r_bin_select_idx (bin, i) && bin->curarch.info)
printf ("%03i %s %s_%i (%s)\n", i, bin->curarch.file,
bin->curarch.info->arch, bin->curarch.info->bits,
bin->curarch.info->machine);
@ -403,6 +420,13 @@ R_API void r_bin_bind (RBin *bin, RBinBind *b) {
b->get_offset = getoffset;
}
R_API RBuffer *r_bin_create (RBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen) {
RBinArch *a = &bin->curarch;
if (a && a->curplugin && a->curplugin->create)
return a->curplugin->create (bin, code, codelen, data, datalen);
return NULL;
}
R_API RBinObj *r_bin_get_object(RBin *bin, int flags) {
int i;
RBinObj *obj = R_NEW (RBinObj);

View file

@ -190,6 +190,154 @@ static int check(RBinArch *arch) {
return R_FALSE;
}
#if 0
typedef struct r_bin_create_t {
int arch;
ut8 *code;
int codelen;
ut8 *data;
int datalen;
} RBinCreate;
#endif
static RBuffer* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data, int datalen) {
ut32 filesize, codeva, datava;
ut32 ncmds, cmdsize, magiclen, headerlen;
ut32 p_codefsz, p_codeva, p_codesz, p_codepa;
ut32 p_datafsz, p_datava, p_datasz, p_datapa;
ut32 p_cmdsize, p_entry, p_tmp;
ut32 baddr = 0x1000;
RBuffer *buf = r_buf_new ();
#define B(x,y) r_buf_append_bytes(buf,(const ut8*)x,y)
#define D(x) r_buf_append_ut32(buf,x)
#define Z(x) r_buf_append_nbytes(buf,x)
#define W(x,y,z) r_buf_write_at(buf,x,(const ut8*)y,z)
#define WZ(x,y) p_tmp=buf->length;Z(x);W(p_tmp,y,strlen(y))
/* MACH0 HEADER */
B ("\xce\xfa\xed\xfe", 4); // header
D (7); // cpu type (x86)
D (3); // subtype (i386-all)
D (2); // filetype (executable)
if (data && datalen>0) {
ncmds = 3;
cmdsize = 0;
} else {
ncmds = 2;
cmdsize = 0;
}
/* COMMANDS */
D (ncmds); // ncmds
p_cmdsize = buf->length;
D (-1); // cmdsize
D (0); // flags
magiclen = buf->length;
/* TEXT SEGMENT */
D (1); // cmd.LC_SEGMENT
D (124); // sizeof (cmd)
WZ (16, "__TEXT");
D (baddr); // vmaddr
D (0x1000); // vmsize XXX
D (0); // fileoff
p_codefsz = buf->length;
D (-1); // filesize
D (7); // maxprot
D (5); // initprot
D (1); // nsects
D (0); // flags
WZ (16, "__text");
WZ (16, "__TEXT");
p_codeva = buf->length; // virtual address
D (-1);
p_codesz = buf->length; // size of code (end-start)
D (-1);
p_codepa = buf->length; // code - baddr
D (-1); //_start-0x1000);
D (2); // align
D (0); // reloff
D (0); // nrelocs
D (0); // flags
D (0); // reserved
D (0);
if (data && datalen>0) {
/* DATA SEGMENT */
D (1); // cmd.LC_SEGMENT
D (124); // sizeof (cmd)
p_tmp = buf->length;
Z (16);
W (p_tmp, "__TEXT", 6); // segment name
D (0x2000); // vmaddr
D (0x1000); // vmsize
D (0); // fileoff
p_datafsz = buf->length;
D (-1); // filesize
D (6); // maxprot
D (6); // initprot
D (1); // nsects
D (0); // flags
WZ (16, "__data");
WZ (16, "__DATA");
p_datava = buf->length;
D (-1);
p_datasz = buf->length;
D (-1);
p_datapa = buf->length;
D (-1); //_start-0x1000);
D (2); // align
D (0); // reloff
D (0); // nrelocs
D (0); // flags
D (0); // reserved
D (0);
}
/* THREAD STATE */
D (5); // LC_UNIXTHREAD
D (80); // sizeof (cmd)
D (1); // i386-thread-state
D (16); // thread-state-count
p_entry = buf->length + (10*sizeof (ut32));
Z (16 * sizeof (ut32));
headerlen = buf->length - magiclen;
codeva = buf->length + baddr;
datava = buf->length + codelen + baddr;
W (p_entry, &codeva, 4); // set PC
/* fill header variables */
W (p_cmdsize, &headerlen, 4);
filesize = magiclen + headerlen + codelen + datalen;
// TEXT SEGMENT //
W (p_codefsz, &filesize, 4);
W (p_codeva, &codeva, 4);
W (p_codesz, &codelen, 4);
p_tmp = codeva - baddr;
W (p_codepa, &p_tmp, 4);
B (code, codelen);
if (data && datalen>0) {
/* append data */
W (p_datafsz, &filesize, 4);
W (p_datava, &datava, 4);
W (p_datasz, &datalen, 4);
p_tmp = datava - baddr;
W (p_datapa, &p_tmp, 4);
B (data, datalen);
}
return buf;
}
struct r_bin_plugin_t r_bin_plugin_mach0 = {
.name = "mach0",
.desc = "mach0 bin plugin",
@ -211,6 +359,7 @@ struct r_bin_plugin_t r_bin_plugin_mach0 = {
.relocs = NULL,
.meta = NULL,
.write = NULL,
.create = &create,
};
#ifndef CORELIB

View file

@ -7,7 +7,7 @@ LIBS+=${DL_LIBS}
LDPATH=-L.. -L../../util
LDPATH+=-lr_util
all: test_meta${EXT_EXE} rpathdel${EXT_EXE}
all: test_meta${EXT_EXE} rpathdel${EXT_EXE} test_create${EXT_EXE}
test_meta${EXT_EXE}: test_meta.o
${CC} test_meta.o ${LDPATH} ${LDFLAGS} -o test_meta${EXT_EXE}
@ -15,6 +15,9 @@ test_meta${EXT_EXE}: test_meta.o
rpathdel${EXT_EXE}: rpathdel.o
${CC} rpathdel.o ${LDPATH} ${LDFLAGS} -o rpathdel${EXT_EXE}
test_create${EXT_EXE}: test_create.o
${CC} test_create.o ${LDPATH} ${LDFLAGS} -o test_create${EXT_EXE}
myclean:
rm -f test_meta${EXT_EXE} test_meta.o rpathdel${EXT_EXE} rpathdel.o

22
libr/bin/t/test_create.c Normal file
View file

@ -0,0 +1,22 @@
#include <r_bin.h>
int main () {
#define _BUFFER_SIZE 64
unsigned char code[64] = {
0x31, 0xc0, 0x40, 0x68, 0x2a, 0x00, 0x00, 0x00, 0x81, 0xec, 0x04,
0x00, 0x00, 0x00, 0xcd, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
RBuffer *b;
RBin *bin = r_bin_new ();
if (!r_bin_use_arch (bin, "x86", 32, "mach0")) {
eprintf ("Cannot set arch\n");
return 1;
}
b = r_bin_create (bin, code, _BUFFER_SIZE, NULL, 0);
if (b) {
if (r_file_dump ("a.out", b->buf, b->length))
eprintf ("dumped %d bytes in a.out\n", b->length);
else eprintf ("error dumping into a.out\n");
} else eprintf ("So fucking oops\n");
r_bin_free (bin);
r_buf_free (b);
}

View file

@ -104,6 +104,7 @@ typedef struct r_bin_plugin_t {
struct r_bin_meta_t *meta;
struct r_bin_write_t *write;
int (*get_offset)(RBinArch *arch, int type, int idx);
RBuffer* (*create)(RBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen);
struct list_head list; // TODO deprecate!!!
} RBinPlugin;
@ -253,10 +254,12 @@ R_API int r_bin_has_dbg_linenums (RBin *bin);
R_API int r_bin_has_dbg_syms (RBin *bin);
R_API int r_bin_has_dbg_relocs (RBin *bin);
R_API RBin* r_bin_new();
R_API int r_bin_set_arch(RBin *bin, const char *arch, int bits, const char *name);
R_API int r_bin_set_archidx(RBin *bin, int idx);
R_API int r_bin_use_arch(RBin *bin, const char *arch, int bits, const char *name);
R_API int r_bin_select(RBin *bin, const char *arch, int bits, const char *name);
R_API int r_bin_select_idx(RBin *bin, int idx);
R_API void r_bin_list_archs(RBin *bin);
R_API void r_bin_set_user_ptr(RBin *bin, void *user);
R_API RBuffer *r_bin_create (RBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen);
/* bin_meta.c */
R_API int r_bin_meta_get_line(RBin *bin, ut64 addr, char *file, int len, int *line);
R_API char *r_bin_meta_get_source_line(RBin *bin, ut64 addr);

View file

@ -192,6 +192,8 @@ R_API RBuffer *r_buf_new();
R_API int r_buf_set_bits(RBuffer *b, int bitoff, int bitsize, ut64 value);
R_API int r_buf_set_bytes(RBuffer *b, ut8 *buf, int length);
R_API int r_buf_append_bytes(RBuffer *b, const ut8 *buf, int length);
R_API int r_buf_append_nbytes(RBuffer *b, int length);
R_API int r_buf_append_ut32(RBuffer *b, ut32 n);
R_API int r_buf_prepend_bytes(RBuffer *b, const ut8 *buf, int length);
R_API char *r_buf_to_string(RBuffer *b);
R_API int r_buf_read_at(RBuffer *b, ut64 addr, ut8 *buf, int len);

View file

@ -14,10 +14,8 @@ struct r_class_t {
#define r_buf_init(x) r_buf_class->init
#endif
R_API struct r_buf_t *r_buf_new() {
RBuffer *b;
b = R_NEW (RBuffer);
R_API RBuffer *r_buf_new() {
RBuffer *b = R_NEW (RBuffer);
if (b) {
b->buf = NULL;
b->length = 0;
@ -67,6 +65,22 @@ R_API int r_buf_append_bytes(RBuffer *b, const ut8 *buf, int length) {
return R_TRUE;
}
R_API int r_buf_append_nbytes(RBuffer *b, int length) {
if (!(b->buf = realloc (b->buf, b->length+length)))
return R_FALSE;
memset (b->buf+b->length, 0, length);
b->length += length;
return R_TRUE;
}
R_API int r_buf_append_ut32(RBuffer *b, ut32 n) {
if (!(b->buf = realloc (b->buf, b->length+sizeof (n))))
return R_FALSE;
memcpy (b->buf+b->length, &n, sizeof (n));
b->length += sizeof (n);
return R_TRUE;
}
static int r_buf_cpy(RBuffer *b, ut64 addr, ut8 *dst, const ut8 *src, int len, int write) {
int end;
addr = (addr==R_BUF_CUR)? b->cur: addr-b->base;