Permalink
Browse files

Fix #12374 - oobread crash in truncated dyldcache ##bin

  • Loading branch information...
radare committed Dec 3, 2018
1 parent c28a9ed commit 4e98402f09a0ef0bb8559a33a4c1988c54938eaf
Showing with 35 additions and 12 deletions.
  1. +35 −12 libr/bin/format/mach0/dyldcache.c
@@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2010-2016 - nibble, pancake */
/* radare - LGPL - Copyright 2010-2018 - nibble, pancake */

#include <stdio.h>
#include <r_types.h>
@@ -21,6 +21,23 @@ static int r_bin_dyldcache_apply_patch (struct r_buf_t* buf, ut32 data, ut64 off

#define NZ_OFFSET(x) if((x) > 0) r_bin_dyldcache_apply_patch (dbuf, (x) - linkedit_offset, (ut64)((size_t)&(x) - (size_t)data))

// make it public in util/buf.c ?
static ut64 r_buf_read64le (RBuffer *buf, ut64 off) {
ut8 data[8] = {0};
r_buf_read_at (buf, off, data, 8);
return r_read_le64 (data);
}

static char *r_buf_read_string (RBuffer *buf, ut64 addr, int len) {
ut8 *data = malloc (len);
if (data) {
r_buf_read_at (buf, addr, data, len);
data[len-1] = 0;
return data;
}
return NULL;
}

/* TODO: Needs more testing and ERROR HANDLING */
struct r_bin_dyldcache_lib_t *r_bin_dyldcache_extract(struct r_bin_dyldcache_obj_t* bin, int idx, int *nlib) {
ut64 liboff, linkedit_offset;
@@ -47,34 +64,41 @@ struct r_bin_dyldcache_lib_t *r_bin_dyldcache_extract(struct r_bin_dyldcache_obj
*nlib = bin->nlibs;
ret = R_NEW0 (struct r_bin_dyldcache_lib_t);
if (!ret) {
perror ("malloc (ret)");
return NULL;
}
if (bin->hdr.startaddr > bin->size) {
eprintf ("corrupted dyldcache");
free (ret);
return NULL;
}

if (bin->hdr.startaddr > bin->size || bin->hdr.baseaddroff > bin->size) {
eprintf ("corrupted dyldcache");
free (ret);
return NULL;
}
image_infos = (struct dyld_cache_image_info*) (bin->b->buf + bin->hdr.startaddr);
dyld_vmbase = *(ut64 *)(bin->b->buf + bin->hdr.baseaddroff);
int sz = bin->nlibs * sizeof (struct dyld_cache_image_info);
image_infos = malloc (sz); //(struct dyld_cache_image_info*) (bin->b->buf + bin->hdr.startaddr);
if (!image_infos) {
free (ret);
return NULL;
}
r_buf_read_at (bin->b, bin->hdr.startaddr, (ut8*)image_infos, sz);
dyld_vmbase = r_buf_read64le (bin->b, bin->hdr.baseaddroff);
liboff = image_infos[idx].address - dyld_vmbase;
if (liboff > bin->size) {
eprintf ("Corrupted file\n");
free (ret);
return NULL;
}
ret->offset = liboff;
if (image_infos[idx].pathFileOffset > bin->size) {
eprintf ("corrupted file\n");
int pfo = image_infos[idx].pathFileOffset;
if (pfo < 0 || pfo > bin->size) {
eprintf ("corrupted file: pathFileOffset > bin->size (%d)\n", pfo);
free (ret);
return NULL;
}
libname = (char *)(bin->b->buf + image_infos[idx].pathFileOffset);
libname = r_buf_read_string (bin->b, pfo, 64);
/* Locate lib hdr in cache */
data = bin->b->buf + liboff;
mh = (struct mach_header *)data;
@@ -224,16 +248,15 @@ struct r_bin_dyldcache_obj_t* r_bin_dyldcache_new(const char* file) {
}

struct r_bin_dyldcache_obj_t* r_bin_dyldcache_from_bytes_new(const ut8* buf, ut64 size) {
struct r_bin_dyldcache_obj_t *bin;
if (!(bin = malloc (sizeof (struct r_bin_dyldcache_obj_t)))) {
struct r_bin_dyldcache_obj_t *bin = R_NEW0 (struct r_bin_dyldcache_obj_t);
if (!bin) {
return NULL;
}
memset (bin, 0, sizeof (struct r_bin_dyldcache_obj_t));
if (!buf) {
return r_bin_dyldcache_free (bin);
}
bin->b = r_buf_new();
if (!r_buf_set_bytes (bin->b, buf, size)) {
bin->b = r_buf_new ();
if (!bin->b || !r_buf_set_bytes (bin->b, buf, size)) {
return r_bin_dyldcache_free (bin);
}
if (!r_bin_dyldcache_init (bin)) {

0 comments on commit 4e98402

Please sign in to comment.