mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-13 18:32:56 +00:00
fixing bflt code trying to prevent futures crashes
This commit is contained in:
parent
c70c8f78ee
commit
1ec97d9c89
@ -18,7 +18,7 @@ RBinAddr *r_bflt_get_entry(struct r_bin_bflt_obj *bin) {
|
||||
static int bflt_init_hdr (struct r_bin_bflt_obj *bin) {
|
||||
struct bflt_hdr *p_hdr;
|
||||
ut8 bhdr[BFLT_HDR_SIZE] = {0};
|
||||
int i, len;
|
||||
int len, i = 0;
|
||||
|
||||
len = r_buf_read_at (bin->b, 0, bhdr, BFLT_HDR_SIZE);
|
||||
if (len < 1) {
|
||||
@ -54,14 +54,15 @@ static int bflt_init_hdr (struct r_bin_bflt_obj *bin) {
|
||||
goto fail;
|
||||
}
|
||||
bin->hdr = p_hdr;
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static int r_bin_bflt_init (struct r_bin_bflt_obj *obj, RBuffer *buf) {
|
||||
obj->b = r_buf_new ();
|
||||
static int r_bin_bflt_init(struct r_bin_bflt_obj *obj, RBuffer *buf) {
|
||||
if (!(obj->b = r_buf_new ())) {
|
||||
return false;
|
||||
}
|
||||
obj->size = buf->length;
|
||||
obj->endian = false;
|
||||
obj->reloc_table = NULL;
|
||||
|
@ -7,7 +7,8 @@
|
||||
|
||||
#include "bflt/bflt.h"
|
||||
|
||||
static void *load_bytes(RBinFile *arch, const ut8 *buf, ut64 sz, ut64 loaddr, Sdb *sdb) {
|
||||
static void *load_bytes(RBinFile *arch, const ut8 *buf, ut64 sz, ut64 loaddr,
|
||||
Sdb *sdb) {
|
||||
struct r_bin_bflt_obj *res;
|
||||
RBuffer *tbuf = NULL;
|
||||
|
||||
@ -25,7 +26,8 @@ static int load(RBinFile *arch) {
|
||||
const ut8 *bytes = r_buf_buffer (arch->buf);
|
||||
ut64 sz = r_buf_size (arch->buf);
|
||||
|
||||
arch->o->bin_obj = load_bytes (arch, bytes, sz, arch->o->loadaddr, arch->sdb);
|
||||
arch->o->bin_obj =
|
||||
load_bytes (arch, bytes, sz, arch->o->loadaddr, arch->sdb);
|
||||
return arch->o->bin_obj ? true : false;
|
||||
}
|
||||
|
||||
@ -45,41 +47,34 @@ static RList *entries(RBinFile *arch) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __patch_reloc (RBuffer *buf, ut32 addr_to_patch, ut32 data_offset) {
|
||||
static void __patch_reloc(RBuffer *buf, ut32 addr_to_patch, ut32 data_offset) {
|
||||
ut32 val = data_offset;
|
||||
r_buf_write_at (buf, addr_to_patch, (void *)&val, 4);
|
||||
}
|
||||
|
||||
static int search_old_relocation (struct reloc_struct_t *reloc_table, ut32 addr_to_patch, int n_reloc) {
|
||||
static int search_old_relocation(struct reloc_struct_t *reloc_table,
|
||||
ut32 addr_to_patch, int n_reloc) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_reloc; i++) {
|
||||
if (addr_to_patch == reloc_table[i].data_offset) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static RList *patch_relocs(RBin *b) {
|
||||
struct r_bin_bflt_obj *bin;
|
||||
RList *list;
|
||||
struct r_bin_bflt_obj *bin = NULL;
|
||||
RList *list = NULL;
|
||||
RBinObject *obj;
|
||||
RIO *io;
|
||||
int i;
|
||||
|
||||
list = r_list_new ();
|
||||
if (!list) {
|
||||
int i = 0;
|
||||
if (!b || !b->iob.io || !b->iob.io->desc) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
io = b->iob.get_io (&b->iob);
|
||||
if (!io || !io->desc) {
|
||||
return NULL;
|
||||
}
|
||||
if (!io->cached) {
|
||||
eprintf ("Warning: please run r2 with -e io.cache=true to patch relocations\n");
|
||||
if (!b->iob.io->cached) {
|
||||
eprintf (
|
||||
"Warning: please run r2 with -e io.cache=true to patch "
|
||||
"relocations\n");
|
||||
return list;
|
||||
}
|
||||
|
||||
@ -88,12 +83,15 @@ static RList *patch_relocs(RBin *b) {
|
||||
return NULL;
|
||||
}
|
||||
bin = obj->bin_obj;
|
||||
|
||||
list = r_list_newf ((RListFree)free);
|
||||
if (!list) {
|
||||
return NULL;
|
||||
}
|
||||
if (bin->got_table) {
|
||||
struct reloc_struct_t *got_table = bin->got_table;
|
||||
for (i = 0; i < bin->n_got; i++) {
|
||||
__patch_reloc (bin->b, got_table[i].addr_to_patch,
|
||||
got_table[i].data_offset);
|
||||
got_table[i].data_offset);
|
||||
RBinReloc *reloc = R_NEW0 (RBinReloc);
|
||||
if (reloc) {
|
||||
reloc->type = R_BIN_RELOC_32;
|
||||
@ -128,20 +126,24 @@ static RList *patch_relocs(RBin *b) {
|
||||
}
|
||||
R_FREE (bin->reloc_table);
|
||||
}
|
||||
|
||||
RIOBind *iob = &b->iob;
|
||||
iob->write_at (iob->io, bin->b->base, bin->b->buf, bin->b->length);
|
||||
|
||||
b->iob.write_at (b->iob.io, bin->b->base, bin->b->buf, bin->b->length);
|
||||
return list;
|
||||
}
|
||||
|
||||
static int get_ngot_entries(struct r_bin_bflt_obj *obj) {
|
||||
ut32 data_size = obj->hdr->data_end - obj->hdr->data_start;
|
||||
int i, n_got;
|
||||
|
||||
int i = 0, n_got = 0;
|
||||
if (data_size > obj->size) {
|
||||
return 0;
|
||||
}
|
||||
for (i = 0, n_got = 0; i < data_size ; i+= 4, n_got++) {
|
||||
ut32 entry;
|
||||
int len = r_buf_read_at (obj->b, obj->hdr->data_start + i, (ut8 *)&entry, sizeof (ut32));
|
||||
ut32 entry, offset = obj->hdr->data_start;
|
||||
if (offset + i + sizeof (ut32) > obj->size ||
|
||||
offset + i + sizeof (ut32) < offset) {
|
||||
return 0;
|
||||
}
|
||||
int len = r_buf_read_at (obj->b, offset + i, (ut8 *)&entry,
|
||||
sizeof (ut32));
|
||||
if (len != sizeof (ut32)) {
|
||||
return 0;
|
||||
}
|
||||
@ -149,28 +151,33 @@ static int get_ngot_entries(struct r_bin_bflt_obj *obj) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return n_got;
|
||||
}
|
||||
|
||||
static RList *relocs(RBinFile *arch) {
|
||||
struct r_bin_bflt_obj *obj = (struct r_bin_bflt_obj*)arch->o->bin_obj;
|
||||
RList *list = r_list_new ();
|
||||
int i, len;
|
||||
|
||||
RList *list = r_list_newf ((RListFree)free);
|
||||
int i, len, n_got, amount;
|
||||
if (!list || !obj) {
|
||||
r_list_free (list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (obj->hdr->flags & FLAT_FLAG_GOTPIC) {
|
||||
int n_got = get_ngot_entries (obj);
|
||||
n_got = get_ngot_entries (obj);
|
||||
if (n_got) {
|
||||
amount = n_got * sizeof (ut32);
|
||||
if (amount < n_got || amount > UT32_MAX) {
|
||||
goto out_error;
|
||||
}
|
||||
struct reloc_struct_t *got_table = calloc (1, n_got * sizeof (ut32));
|
||||
if (got_table) {
|
||||
ut32 offset = 0;
|
||||
for (i = 0; i < n_got ; offset +=4, i++) {
|
||||
for (i = 0; i < n_got ; offset += 4, i++) {
|
||||
ut32 got_entry;
|
||||
if (obj->hdr->data_start + offset + 4 > obj->size ||
|
||||
obj->hdr->data_start + offset + 4 < offset) {
|
||||
break;
|
||||
}
|
||||
len = r_buf_read_at (obj->b, obj->hdr->data_start + offset,
|
||||
(ut8 *)&got_entry, sizeof (ut32));
|
||||
if (!VALID_GOT_ENTRY (got_entry)) {
|
||||
@ -188,39 +195,58 @@ static RList *relocs(RBinFile *arch) {
|
||||
|
||||
if (obj->hdr->reloc_count > 0) {
|
||||
int n_reloc = obj->hdr->reloc_count;
|
||||
ut32 *reloc_pointer_table = calloc (n_reloc, sizeof (ut32));
|
||||
if (!reloc_pointer_table) {
|
||||
goto out;
|
||||
|
||||
amount = n_reloc * sizeof (struct reloc_struct_t);
|
||||
if (amount < n_reloc || amount > UT32_MAX) {
|
||||
goto out_error;
|
||||
}
|
||||
struct reloc_struct_t *reloc_table = calloc (1, amount + 1);
|
||||
if (!reloc_table) {
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
struct reloc_struct_t *reloc_table = calloc (n_reloc, sizeof (struct reloc_struct_t));
|
||||
if (!reloc_table) {
|
||||
goto out;
|
||||
amount = n_reloc * sizeof (ut32);
|
||||
if (amount < n_reloc || amount > UT32_MAX) {
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
len = r_buf_read_at (obj->b, obj->hdr->reloc_start, (ut8 *)reloc_pointer_table, n_reloc * sizeof (ut32));
|
||||
if (len != n_reloc * sizeof (ut32)) {
|
||||
goto out;
|
||||
ut32 *reloc_pointer_table = calloc (1, amount + 1);
|
||||
if (!reloc_pointer_table) {
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
if (obj->hdr->reloc_start + amount > obj->size ||
|
||||
obj->hdr->reloc_start + amount < amount) {
|
||||
goto out_error;
|
||||
}
|
||||
len = r_buf_read_at (obj->b, obj->hdr->reloc_start,
|
||||
(ut8 *)reloc_pointer_table,
|
||||
amount);
|
||||
if (len != amount) {
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < obj->hdr->reloc_count; i++) {
|
||||
ut32 reloc_offset = r_swap_ut32 (reloc_pointer_table[i]) + BFLT_HDR_SIZE;
|
||||
|
||||
if (reloc_offset < obj->hdr->bss_end) {
|
||||
ut32 reloc_fixed;
|
||||
ut32 reloc_data_offset;
|
||||
|
||||
len = r_buf_read_at (obj->b, reloc_offset, (ut8 *)&reloc_fixed, sizeof (ut32));
|
||||
//XXX it doesn't take endian as consideration when swapping
|
||||
ut32 reloc_offset =
|
||||
r_swap_ut32 (reloc_pointer_table[i]) +
|
||||
BFLT_HDR_SIZE;
|
||||
|
||||
if (reloc_offset < obj->hdr->bss_end && reloc_offset < obj->size) {
|
||||
ut32 reloc_fixed, reloc_data_offset;
|
||||
if (reloc_offset + sizeof (ut32) > obj->size ||
|
||||
reloc_offset + sizeof (ut32) < reloc_offset) {
|
||||
goto out_error;
|
||||
}
|
||||
len = r_buf_read_at (obj->b, reloc_offset,
|
||||
(ut8 *)&reloc_fixed,
|
||||
sizeof (ut32));
|
||||
if (len != sizeof (ut32)) {
|
||||
eprintf ("problem while reading relocation entries\n");
|
||||
goto out;
|
||||
goto out_error;
|
||||
}
|
||||
reloc_data_offset = r_swap_ut32 (reloc_fixed) + BFLT_HDR_SIZE;
|
||||
|
||||
reloc_table[i].addr_to_patch = reloc_offset;
|
||||
reloc_table[i].data_offset = reloc_data_offset;
|
||||
|
||||
|
||||
RBinReloc *reloc = R_NEW0 (RBinReloc);
|
||||
if (reloc) {
|
||||
reloc->type = R_BIN_RELOC_32;
|
||||
@ -233,16 +259,20 @@ static RList *relocs(RBinFile *arch) {
|
||||
free (reloc_pointer_table);
|
||||
obj->reloc_table = reloc_table;
|
||||
}
|
||||
|
||||
out:
|
||||
return list;
|
||||
out_error:
|
||||
r_list_free (list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static RBinInfo *info(RBinFile *arch) {
|
||||
struct r_bin_bflt_obj *obj = (struct r_bin_bflt_obj*)arch->o->bin_obj;
|
||||
RBinInfo *info = R_NEW0 (RBinInfo);
|
||||
|
||||
if (!info) {
|
||||
struct r_bin_bflt_obj *obj = NULL;
|
||||
RBinInfo *info = NULL;
|
||||
if (!arch || !arch->o || !arch->o->bin_obj) {
|
||||
return NULL;
|
||||
}
|
||||
obj = (struct r_bin_bflt_obj*)arch->o->bin_obj;
|
||||
if (!(info = R_NEW0 (RBinInfo))) {
|
||||
return NULL;
|
||||
}
|
||||
info->file = arch->file ? strdup (arch->file) : NULL;
|
||||
@ -257,7 +287,6 @@ static RBinInfo *info(RBinFile *arch) {
|
||||
info->has_va = false;
|
||||
info->dbg_info = 0;
|
||||
info->machine = strdup ("unknown");
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user