// TODO: move somewhere else R_API RAsmOp *r_core_disassemble (RCore *core, ut64 addr) { int delta; ut8 buf[128]; static RBuffer *b = NULL; // XXX: never freed and non-thread safe. move to RCore RAsmOp *op; if (b == NULL) { b = r_buf_new (); if (!r_core_read_at (core, addr, buf, sizeof (buf))) return NULL; b->base = addr; r_buf_set_bytes (b, buf, sizeof (buf)); } else { if ((addr < b->base) || addr > (b->base+b->length-32)) { if (!r_core_read_at (core, addr, buf, sizeof (buf))) return NULL; b->base = addr; r_buf_set_bytes (b, buf, sizeof (buf)); } } delta = addr - b->base; op = R_NEW (RAsmOp); r_asm_set_pc (core->assembler, addr); if (r_asm_disassemble (core->assembler, op, b->buf+delta, b->length)<1) { free (op); return NULL; } return op; }
int r_io_zip_slurp_file(RIOZipFileObj *zfo) { int res = R_FALSE; struct zip_stat sb; struct zip_file *zFile = NULL; struct zip * zipArch ; if (!zfo) return res; zipArch = r_io_zip_open_archive ( zfo->archivename, zfo->flags, zfo->mode, zfo->rw); //eprintf("Slurping file"); if (zipArch && zfo && zfo->entry != -1) { zFile = zip_fopen_index (zipArch, zfo->entry, 0); if (!zfo->b) zfo->b = r_buf_new (); zip_stat_init (&sb); if (zFile && zfo->b && !zip_stat_index(zipArch, zfo->entry, 0, &sb) ) { ut8 *buf = malloc (sb.size); memset (buf, 0, sb.size); if (buf) { zip_fread (zFile, buf, sb.size); r_buf_set_bytes (zfo->b, buf, sb.size); res = zfo->opened = R_TRUE; free (buf); } } zip_fclose (zFile); } zip_close (zipArch); return res; }
static int r_io_zip_slurp_file(RIOZipFileObj *zfo) { struct zip_file *zFile = NULL; struct zip *zipArch; struct zip_stat sb; bool res = false; if (!zfo) { return res; } zipArch = r_io_zip_open_archive ( zfo->archivename, zfo->perm, zfo->mode, zfo->rw); if (zipArch && zfo && zfo->entry != -1) { zFile = zip_fopen_index (zipArch, zfo->entry, 0); if (!zfo->b) { zfo->b = r_buf_new (); } zip_stat_init (&sb); if (zFile && zfo->b && !zip_stat_index (zipArch, zfo->entry, 0, &sb)) { ut8 *buf = malloc (sb.size); memset (buf, 0, sb.size); if (buf) { zip_fread (zFile, buf, sb.size); r_buf_set_bytes (zfo->b, buf, sb.size); res = true; zfo->opened = true; free (buf); } } zip_fclose (zFile); } zip_close (zipArch); return res; }
R_API RBuffer *r_buf_new_with_bytes (const ut8 *bytes, ut64 len) { RBuffer *b = r_buf_new (); if (b && bytes && (len > 0 && len != UT64_MAX)) { r_buf_set_bytes (b, bytes, len); } return b; }
R_API int r_core_yank_set (RCore *core, ut64 addr, const ut8 *buf, ut32 len) { //free (core->yank_buf); if (buf && len) { r_buf_set_bytes (core->yank_buf, buf, len); core->yank_buf->base = addr; return R_TRUE; } return R_FALSE; }
static void * load_bytes(RBinFile *arch, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb) { if (!buf || !sz || sz == UT64_MAX) { return NULL; } RBuffer *tbuf = r_buf_new(); r_buf_set_bytes (tbuf, buf, sz); void *res = r_bin_coff_new_buf (tbuf, arch->rbin->verbose); r_buf_free (tbuf); return res; }
static void * load_bytes(const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb){ void *res = NULL; RBuffer *tbuf = NULL; if (!buf || sz == 0 || sz == UT64_MAX) return NULL; tbuf = r_buf_new (); r_buf_set_bytes (tbuf, buf, sz); res = r_bin_dex_new_buf (tbuf); r_buf_free (tbuf); return res; }
static RBuffer *build (REgg *egg) { RBuffer *buf = r_buf_new (); const ut8 *sc = NULL; int cd = 0; char *port = r_egg_option_get (egg, "port"); //TODO: char *udp = r_egg_option_get (egg, "udp"); switch (egg->os) { case R_EGG_OS_OSX: case R_EGG_OS_DARWIN: switch (egg->arch) { case R_SYS_ARCH_X86: if (suid) { sc = x86_osx_suid_binsh; cd = 7+36; } else { sc = x86_osx_binsh; cd = 36; } case R_SYS_ARCH_ARM: // TODO break; } break; case R_EGG_OS_LINUX: if (suid) eprintf ("no suid for this platform\n"); suid = 0; switch (egg->arch) { case R_SYS_ARCH_X86: switch (egg->bits) { case 32: sc = x86_linux_binsh; break; case 64: sc = x86_64_linux_binsh; break; default: eprintf ("Unsupportted\n"); } break; case R_SYS_ARCH_ARM: sc = arm_linux_binsh; break; } break; default: eprintf ("unsupported os %x\n", egg->os); break; } if (sc) { r_buf_set_bytes (buf, sc, strlen ((const char *)sc)); if (shell && *shell) { if (cd) r_buf_write_at (buf, cd, (const ut8*)shell, strlen (shell)+1); else eprintf ("Cannot set shell\n"); } } free (suid); free (shell); return buf; }
struct r_bin_mz_obj_t* r_bin_mz_new_buf(const struct r_buf_t *buf) { struct r_bin_mz_obj_t *bin = R_NEW0 (struct r_bin_mz_obj_t); if (!bin) { return NULL; } bin->b = r_buf_new (); bin->size = buf->length; if (!r_buf_set_bytes (bin->b, buf->buf, bin->size)){ return r_bin_mz_free (bin); } return r_bin_mz_init (bin) ? bin : r_bin_mz_free (bin); }
static void * load_bytes(const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb){ void *res = NULL; RBuffer *tbuf = NULL; struct r_bin_java_obj_t* bin_obj = NULL; if (!buf || sz == 0 || sz == UT64_MAX) return NULL; tbuf = r_buf_new(); r_buf_set_bytes (tbuf, buf, sz); res = bin_obj = r_bin_java_new_buf (tbuf, loadaddr, sdb); add_bin_obj_to_sdb (bin_obj); r_buf_free (tbuf); return res; }
struct r_bin_te_obj_t* r_bin_te_new_buf(struct r_buf_t *buf) { struct r_bin_te_obj_t *bin = R_NEW0 (struct r_bin_te_obj_t); if (!bin) return NULL; bin->kv = sdb_new0 (); bin->b = r_buf_new (); bin->size = buf->length; if (!r_buf_set_bytes (bin->b, buf->buf, bin->size)){ return r_bin_te_free(bin); } if (!r_bin_te_init(bin)) return r_bin_te_free(bin); return bin; }
static void * load_bytes(RBinFile *arch, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb) { const struct r_bin_mz_obj_t *res = NULL; RBuffer *tbuf = NULL; if (!buf || sz == 0 || sz == UT64_MAX) return NULL; tbuf = r_buf_new (); r_buf_set_bytes (tbuf, buf, sz); res = r_bin_mz_new_buf (tbuf); if (res) sdb_ns_set (sdb, "info", res->kv); r_buf_free (tbuf); return (void *)res; }
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)))) 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)) return r_bin_dyldcache_free(bin); if (!r_bin_dyldcache_init(bin)) return r_bin_dyldcache_free(bin); return bin; }
RBinJavaObj* r_bin_java_new(const char* file) { ut8 *buf; RBinJavaObj *bin = R_NEW0 (RBinJavaObj); bin->file = file; if (!(buf = (ut8*)r_file_slurp (file, &bin->size))) return r_bin_java_free (bin); bin->b = r_buf_new (); if (!r_buf_set_bytes (bin->b, buf, bin->size)) return r_bin_java_free (bin); free (buf); if (!javasm_init (bin)) return r_bin_java_free (bin); return bin; }
static int r_bin_coff_init(struct r_bin_coff_obj *obj, RBuffer *buf) { obj->b = r_buf_new (); obj->size = buf->length; if (!r_buf_set_bytes (obj->b, buf->buf, obj->size)){ r_buf_free (obj->b); return false; } r_bin_coff_init_hdr(obj); r_bin_coff_init_opt_hdr(obj); r_bin_coff_init_scn_hdr(obj); r_bin_coff_init_symtable(obj); return true; }
static void * load_bytes(RBinFile *arch, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb){ RBuffer *tbuf = NULL; RRarBinObj *res = NULL; if (!buf || sz == 0 || sz == UT64_MAX) { return NULL; } res = R_NEW0 (RRarBinObj); tbuf = r_buf_new (); r_buf_set_bytes (tbuf, buf, sz); res->buf = tbuf; res->kv = sdb; res->loadaddr = loadaddr; return res; }
struct r_bin_te_obj_t* r_bin_te_new(const char* file) { ut8 *buf; struct r_bin_te_obj_t *bin = R_NEW0 (struct r_bin_te_obj_t); if (!bin) return NULL; bin->file = file; if (!(buf = (ut8*)r_file_slurp(file, &bin->size))) return r_bin_te_free(bin); bin->b = r_buf_new (); if (!r_buf_set_bytes (bin->b, buf, bin->size)) return r_bin_te_free(bin); free (buf); if (!r_bin_te_init(bin)) return r_bin_te_free(bin); return bin; }
struct r_bin_dyldcache_obj_t* r_bin_dyldcache_new(const char* file) { struct r_bin_dyldcache_obj_t *bin; ut8 *buf; if (!(bin = malloc (sizeof (struct r_bin_dyldcache_obj_t)))) return NULL; memset (bin, 0, sizeof (struct r_bin_dyldcache_obj_t)); bin->file = file; if (!(buf = (ut8*)r_file_slurp(file, &bin->size))) return r_bin_dyldcache_free(bin); bin->b = r_buf_new(); if (!r_buf_set_bytes(bin->b, buf, bin->size)) return r_bin_dyldcache_free(bin); free (buf); if (!r_bin_dyldcache_init(bin)) return r_bin_dyldcache_free(bin); return bin; }
static void *load_bytes(RBinFile *bf, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb){ struct r_bin_java_obj_t *bin_obj = NULL; RBuffer *tbuf = NULL; void *res = NULL; if (!buf || sz == 0 || sz == UT64_MAX) { return NULL; } tbuf = r_buf_new (); r_buf_set_bytes (tbuf, buf, sz); res = bin_obj = r_bin_java_new_buf (tbuf, loadaddr, sdb); add_bin_obj_to_sdb (bin_obj); if (bf && bf->file) { bin_obj->file = strdup (bf->file); } r_buf_free (tbuf); return res; }
struct r_bin_dex_obj_t* r_bin_dex_new_buf(RBuffer *buf) { struct r_bin_dex_obj_t *bin = R_NEW0 (struct r_bin_dex_obj_t);; if (!bin) return NULL; bin->size = buf->length; bin->b = r_buf_new (); if (!r_buf_set_bytes (bin->b, buf->buf, bin->size)){ r_buf_free (bin->b); free (bin); return NULL; } // XXX: use r_buf_getc() // XXX: this is not endian safe /* header */ r_buf_read_at (bin->b, 0, (ut8*)&bin->header, sizeof (struct dex_header_t)); /* strings */ bin->strings = (ut32 *) malloc (bin->header.strings_size * sizeof (ut32) + 1); r_buf_read_at (bin->b, bin->header.strings_offset, (ut8*)bin->strings, bin->header.strings_size * sizeof (ut32)); /* classes */ bin->classes = (struct dex_class_t *) malloc (bin->header.class_size * sizeof (struct dex_class_t) + 1); r_buf_read_at (bin->b, bin->header.class_offset, (ut8*)bin->classes, bin->header.class_size * sizeof (struct dex_class_t)); //{ ut8 *b = (ut8*)&bin->methods; eprintf ("CLASS %02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]); } /* methods */ bin->methods = (struct dex_method_t *) calloc (bin->header.method_size * sizeof (struct dex_method_t) + 1, 1); r_buf_read_at (bin->b, bin->header.method_offset, (ut8*)bin->methods, bin->header.method_size * sizeof (struct dex_method_t)); /* types */ bin->types = (struct dex_type_t *) calloc (bin->header.types_size * sizeof (struct dex_type_t) + 1, 1); r_buf_read_at (bin->b, bin->header.types_offset, (ut8*)bin->types, bin->header.types_size * sizeof (struct dex_type_t)); /* fields */ bin->fields = (struct dex_field_t *) calloc (bin->header.fields_size * sizeof (struct dex_field_t) + 1, 1); r_buf_read_at (bin->b, bin->header.fields_offset, (ut8*)bin->fields, bin->header.fields_size * sizeof (struct dex_field_t)); return bin; }
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; obj->got_table = NULL; obj->n_got = 0; obj->hdr = NULL; if(!r_buf_set_bytes (obj->b, buf->buf, obj->size)) { r_buf_free (obj->b); return false; } if (!bflt_init_hdr (obj)) { return false; } return true; }
struct r_bin_mz_obj_t* r_bin_mz_new(const char* file) { const ut8 *buf; struct r_bin_mz_obj_t *bin = R_NEW0 (struct r_bin_mz_obj_t); if (!bin) { return NULL; } bin->file = file; if (!(buf = (ut8*)r_file_slurp (file, &bin->size))) { return r_bin_mz_free (bin); } bin->b = r_buf_new (); if (!r_buf_set_bytes (bin->b, buf, bin->size)) { free ((void *)buf); return r_bin_mz_free (bin); } free ((void *)buf); if (!r_bin_mz_init (bin)) { return r_bin_mz_free (bin); } return bin; }
struct r_bin_dex_obj_t* r_bin_dex_new_buf(RBuffer *buf) { struct r_bin_dex_obj_t *bin = R_NEW0 (struct r_bin_dex_obj_t); if (!bin) { goto fail; } bin->size = buf->length; bin->b = r_buf_new (); if (!r_buf_set_bytes (bin->b, buf->buf, bin->size)) { goto fail; } // XXX: this is not endian safe // XXX: no need to dup all data!! just pointers to the bin->b // XXX: return value not checked /* header */ //r_buf_read_at (bin->b, 0, (ut8*)&bin->header, sizeof (struct dex_header_t)); if (bin->size < sizeof(struct dex_header_t)) goto fail; bin->header = (*(struct dex_header_t*)bin->b->buf); /* strings */ //eprintf ("strings size: %d\n", bin->header.strings_size); #define STRINGS_SIZE ((bin->header.strings_size+1)*sizeof(ut32)) bin->strings = (ut32 *) calloc (bin->header.strings_size + 1, sizeof (ut32)); if (!bin->strings) { goto fail; } if (bin->header.strings_size > bin->size) { free (bin->strings); goto fail; } r_buf_read_at (bin->b, bin->header.strings_offset, (ut8*)bin->strings, bin->header.strings_size * sizeof (ut32)); /* classes */ int classes_size = bin->header.class_size * sizeof (struct dex_class_t); if (bin->header.class_offset + classes_size >= bin->size) { classes_size = bin->size - bin->header.class_offset; } if (classes_size<0) { classes_size = 0; } bin->header.class_size = classes_size / sizeof (struct dex_class_t); bin->classes = (struct dex_class_t *) malloc (classes_size); r_buf_read_at (bin->b, bin->header.class_offset, (ut8*)bin->classes, classes_size); //{ ut8 *b = (ut8*)&bin->methods; eprintf ("CLASS %02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]); } /* methods */ int methods_size = bin->header.method_size * sizeof (struct dex_method_t); if (bin->header.method_offset + methods_size >= bin->size) { methods_size = bin->size - bin->header.method_offset; } if (methods_size < 0) { methods_size = 0; } bin->header.method_size = methods_size / sizeof (struct dex_method_t); bin->methods = (struct dex_method_t *) calloc (methods_size, 1); r_buf_read_at (bin->b, bin->header.method_offset, (ut8*)bin->methods, methods_size); /* types */ int types_size = bin->header.types_size * sizeof (struct dex_type_t); if (bin->header.types_offset + types_size >= bin->size) { types_size = bin->size - bin->header.types_offset; } if (types_size < 0) { types_size = 0; } bin->header.types_size = types_size / sizeof (struct dex_type_t); bin->types = (struct dex_type_t *) calloc (types_size, 1); r_buf_read_at (bin->b, bin->header.types_offset, (ut8*)bin->types, types_size); /* fields */ int fields_size = bin->header.fields_size * sizeof (struct dex_type_t); if (bin->header.fields_offset + fields_size >= bin->size) { fields_size = bin->size - bin->header.fields_offset; } if (fields_size<0) { fields_size = 0; } bin->header.fields_size = fields_size / sizeof (struct dex_field_t); bin->fields = (struct dex_field_t *) calloc (fields_size, 1); r_buf_read_at (bin->b, bin->header.fields_offset, (ut8*)bin->fields, fields_size); return bin; fail: if (bin) { r_buf_free (bin->b); free (bin); } return NULL; }
RBinDexObj *r_bin_dex_new_buf(RBuffer *buf) { RBinDexObj *bin = R_NEW0 (RBinDexObj); int i; ut8 *bufptr; struct dex_header_t *dexhdr; if (!bin) { goto fail; } bin->size = buf->length; bin->b = r_buf_new (); if (!r_buf_set_bytes (bin->b, buf->buf, bin->size)) { goto fail; } /* header */ if (bin->size < sizeof (struct dex_header_t)) { goto fail; } bufptr = bin->b->buf; dexhdr = &bin->header; //check boundaries of bufptr if (bin->size < 112) { goto fail; } memcpy (&dexhdr->magic, bufptr, 8); dexhdr->checksum = r_read_le32 (bufptr + 8); memcpy (&dexhdr->signature, bufptr + 12, 20); dexhdr->size = r_read_le32 (bufptr + 32); dexhdr->header_size = r_read_le32 (bufptr + 36); dexhdr->endian = r_read_le32 (bufptr + 40); // TODO: this offsets and size will be used for checking, // so they should be checked. Check overlap, < 0, > bin.size dexhdr->linksection_size = r_read_le32 (bufptr + 44); dexhdr->linksection_offset = r_read_le32 (bufptr + 48); dexhdr->map_offset = r_read_le32 (bufptr + 52); dexhdr->strings_size = r_read_le32 (bufptr + 56); dexhdr->strings_offset = r_read_le32 (bufptr + 60); dexhdr->types_size = r_read_le32 (bufptr + 64); dexhdr->types_offset = r_read_le32 (bufptr + 68); dexhdr->prototypes_size = r_read_le32 (bufptr + 72); dexhdr->prototypes_offset = r_read_le32 (bufptr + 76); dexhdr->fields_size = r_read_le32 (bufptr + 80); dexhdr->fields_offset = r_read_le32 (bufptr + 84); dexhdr->method_size = r_read_le32 (bufptr + 88); dexhdr->method_offset = r_read_le32 (bufptr + 92); dexhdr->class_size = r_read_le32 (bufptr + 96); dexhdr->class_offset = r_read_le32 (bufptr + 100); dexhdr->data_size = r_read_le32 (bufptr + 104); dexhdr->data_offset = r_read_le32 (bufptr + 108); /* strings */ #define STRINGS_SIZE ((dexhdr->strings_size + 1) * sizeof (ut32)) bin->strings = (ut32 *) calloc (dexhdr->strings_size + 1, sizeof (ut32)); if (!bin->strings) { goto fail; } if (dexhdr->strings_size > bin->size) { free (bin->strings); goto fail; } for (i = 0; i < dexhdr->strings_size; i++) { ut64 offset = dexhdr->strings_offset + i * sizeof (ut32); //make sure we can read from bufptr without oob if (offset + 4 > bin->size) { free (bin->strings); goto fail; } bin->strings[i] = r_read_le32 (bufptr + offset); } /* classes */ // TODO: not sure about if that is needed int classes_size = dexhdr->class_size * DEX_CLASS_SIZE; if (dexhdr->class_offset + classes_size >= bin->size) { classes_size = bin->size - dexhdr->class_offset; } if (classes_size < 0) { classes_size = 0; } dexhdr->class_size = classes_size / DEX_CLASS_SIZE; bin->classes = (struct dex_class_t *) calloc (dexhdr->class_size, sizeof (struct dex_class_t)); for (i = 0; i < dexhdr->class_size; i++) { ut64 offset = dexhdr->class_offset + i * DEX_CLASS_SIZE; if (offset + 32 > bin->size) { free (bin->strings); free (bin->classes); goto fail; } bin->classes[i].class_id = r_read_le32 (bufptr + offset + 0); bin->classes[i].access_flags = r_read_le32 (bufptr + offset + 4); bin->classes[i].super_class = r_read_le32 (bufptr + offset + 8); bin->classes[i].interfaces_offset = r_read_le32 (bufptr + offset + 12); bin->classes[i].source_file = r_read_le32 (bufptr + offset + 16); bin->classes[i].anotations_offset = r_read_le32 (bufptr + offset + 20); bin->classes[i].class_data_offset = r_read_le32 (bufptr + offset + 24); bin->classes[i].static_values_offset = r_read_le32 (bufptr + offset + 28); } /* methods */ int methods_size = dexhdr->method_size * sizeof (struct dex_method_t); if (dexhdr->method_offset + methods_size >= bin->size) { methods_size = bin->size - dexhdr->method_offset; } if (methods_size < 0) { methods_size = 0; } dexhdr->method_size = methods_size / sizeof (struct dex_method_t); bin->methods = (struct dex_method_t *) calloc (methods_size + 1, 1); for (i = 0; i < dexhdr->method_size; i++) { ut64 offset = dexhdr->method_offset + i * sizeof (struct dex_method_t); if (offset + 8 > bin->size) { free (bin->strings); free (bin->classes); free (bin->methods); goto fail; } bin->methods[i].class_id = r_read_le16 (bufptr + offset + 0); bin->methods[i].proto_id = r_read_le16 (bufptr + offset + 2); bin->methods[i].name_id = r_read_le32 (bufptr + offset + 4); } /* types */ int types_size = dexhdr->types_size * sizeof (struct dex_type_t); if (dexhdr->types_offset + types_size >= bin->size) { types_size = bin->size - dexhdr->types_offset; } if (types_size < 0) { types_size = 0; } dexhdr->types_size = types_size / sizeof (struct dex_type_t); bin->types = (struct dex_type_t *) calloc (types_size + 1, 1); for (i = 0; i < dexhdr->types_size; i++) { ut64 offset = dexhdr->types_offset + i * sizeof (struct dex_type_t); if (offset + 4 > bin->size) { free (bin->strings); free (bin->classes); free (bin->methods); free (bin->types); goto fail; } bin->types[i].descriptor_id = r_read_le32 (bufptr + offset); } /* fields */ int fields_size = dexhdr->fields_size * sizeof (struct dex_field_t); if (dexhdr->fields_offset + fields_size >= bin->size) { fields_size = bin->size - dexhdr->fields_offset; } if (fields_size < 0) { fields_size = 0; } dexhdr->fields_size = fields_size / sizeof (struct dex_field_t); bin->fields = (struct dex_field_t *) calloc (fields_size + 1, 1); for (i = 0; i < dexhdr->fields_size; i++) { ut64 offset = dexhdr->fields_offset + i * sizeof (struct dex_field_t); if (offset + 8 > bin->size) { free (bin->strings); free (bin->classes); free (bin->methods); free (bin->types); free (bin->fields); goto fail; } bin->fields[i].class_id = r_read_le16 (bufptr + offset + 0); bin->fields[i].type_id = r_read_le16 (bufptr + offset + 2); bin->fields[i].name_id = r_read_le32 (bufptr + offset + 4); } /* proto */ int protos_size = dexhdr->prototypes_size * sizeof (struct dex_proto_t); if (dexhdr->prototypes_offset + protos_size >= bin->size) { protos_size = bin->size - dexhdr->prototypes_offset; } if (protos_size < 1) { dexhdr->prototypes_size = 0; return bin; } dexhdr->prototypes_size = protos_size / sizeof (struct dex_proto_t); bin->protos = (struct dex_proto_t *) calloc (protos_size, 1); for (i = 0; i < dexhdr->prototypes_size; i++) { ut64 offset = dexhdr->prototypes_offset + i * sizeof (struct dex_proto_t); if (offset + 12 > bin->size) { free (bin->strings); free (bin->classes); free (bin->methods); free (bin->types); free (bin->fields); free (bin->protos); goto fail; } bin->protos[i].shorty_id = r_read_le32 (bufptr + offset + 0); bin->protos[i].return_type_id = r_read_le32 (bufptr + offset + 4); bin->protos[i].parameters_off = r_read_le32 (bufptr + offset + 8); } return bin; fail: if (bin) { r_buf_free (bin->b); free (bin); } 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) { struct r_bin_dyldcache_lib_t *ret = NULL; struct mach_header *mh; RBuffer* dbuf; ut64 curoffset, liboff, libla, libpath, linkedit_offset; ut8 *data, *cmdptr; char *libname; int cmd, libsz = 0; if (bin->nlibs < 0 || idx < 0 || idx > bin->nlibs) return NULL; *nlib = bin->nlibs; ret = R_NEW0 (struct r_bin_dyldcache_lib_t); if (!ret) { perror ("malloc (ret)"); return NULL; } curoffset = bin->hdr.startaddr+idx*32; libla = *(ut64*)(bin->b->buf+curoffset); liboff = libla - *(ut64*)&bin->b->buf[bin->hdr.baseaddroff]; if (liboff > bin->size) { eprintf ("Corrupted file\n"); free (ret); return NULL; } ret->offset = liboff; libpath = *(ut64*)(bin->b->buf+curoffset + 24); /* Locate lib hdr in cache */ data = bin->b->buf+liboff; mh = (struct mach_header *)data; /* Check it is mach-o */ if (mh->magic != 0xfeedface) { eprintf ("Not mach-o\n"); free (ret); return NULL; } /* Write mach-o hdr */ if (!(dbuf = r_buf_new ())) { eprintf ("new (dbuf)\n"); free (ret); return NULL; } r_buf_set_bytes (dbuf, data, sizeof (struct mach_header)); cmdptr = data + sizeof(struct mach_header); /* Write load commands */ for (cmd = 0; cmd < mh->ncmds; cmd++) { struct load_command *lc = (struct load_command *)cmdptr; cmdptr += lc->cmdsize; r_buf_append_bytes (dbuf, (ut8*)lc, lc->cmdsize); } /* Write segments */ for (cmd = linkedit_offset = 0, cmdptr = data + sizeof (struct mach_header); cmd < mh->ncmds; cmd++) { struct load_command *lc = (struct load_command *)cmdptr; cmdptr += lc->cmdsize; switch (lc->cmd) { case LC_SEGMENT: { /* Write segment and patch offset */ struct segment_command *seg = (struct segment_command *)lc; int t = seg->filesize; if (seg->fileoff+seg->filesize > bin->b->length) t = bin->b->length - seg->fileoff; r_buf_append_bytes (dbuf, bin->b->buf+seg->fileoff, t); r_bin_dyldcache_apply_patch (dbuf, dbuf->length, (ut64)((size_t)&seg->fileoff - (size_t)data)); /* Patch section offsets */ int sect_offset = seg->fileoff - libsz; libsz = dbuf->length; if (!strcmp(seg->segname, "__LINKEDIT")) linkedit_offset = sect_offset; if (seg->nsects > 0) { struct section *sects = (struct section *)((ut8 *)seg + sizeof(struct segment_command)); int nsect; for (nsect = 0; nsect < seg->nsects; nsect++) { if (sects[nsect].offset > libsz) { r_bin_dyldcache_apply_patch (dbuf, sects[nsect].offset - sect_offset, (ut64)((size_t)§s[nsect].offset - (size_t)data)); } } } } break; case LC_SYMTAB: { struct symtab_command *st = (struct symtab_command *)lc; NZ_OFFSET (st->symoff); NZ_OFFSET (st->stroff); } break; case LC_DYSYMTAB: { struct dysymtab_command *st = (struct dysymtab_command *)lc; NZ_OFFSET (st->tocoff); NZ_OFFSET (st->modtaboff); NZ_OFFSET (st->extrefsymoff); NZ_OFFSET (st->indirectsymoff); NZ_OFFSET (st->extreloff); NZ_OFFSET (st->locreloff); } break; case LC_DYLD_INFO: case LC_DYLD_INFO_ONLY: { struct dyld_info_command *st = (struct dyld_info_command *)lc; NZ_OFFSET (st->rebase_off); NZ_OFFSET (st->bind_off); NZ_OFFSET (st->weak_bind_off); NZ_OFFSET (st->lazy_bind_off); NZ_OFFSET (st->export_off); } break; } } /* Fill r_bin_dyldcache_lib_t ret */ ret->b = dbuf; libname = (char*)(bin->b->buf+libpath); strncpy (ret->path, libname, sizeof (ret->path)-1); ret->size = libsz; return ret; }
static RBuffer *build (REgg *egg) { RBuffer *buf, *sc; ut8 aux[32], nkey; const char *default_key = DEFAULT_XOR_KEY; char *key = r_egg_option_get (egg, "key"); int i; if (!key || !*key) { free (key); key = strdup (default_key); eprintf ("XOR key not provided. Using (%s) as the key\n", key); } nkey = r_num_math (NULL, key); if (nkey == 0) { eprintf ("Invalid key (%s)\n", key); free (key); return false; } if (nkey != (nkey & 0xff)) { nkey &= 0xff; eprintf ("xor key wrapped to (%d)\n", nkey); } if (r_buf_size (egg->bin) > 240) { // XXX eprintf ("shellcode is too long :(\n"); free (key); return NULL; } sc = egg->bin; // hack if (!r_buf_size (sc)) { eprintf ("No shellcode found!\n"); free (key); return NULL; } for (i = 0; i<r_buf_size (sc); i++) { // eprintf ("%02x -> %02x\n", sc->buf[i], sc->buf[i] ^nkey); if ((r_buf_read8_at (sc, i) ^ nkey)==0) { eprintf ("This xor key generates null bytes. Try again.\n"); free (key); return NULL; } } buf = r_buf_new (); sc = r_buf_new (); // TODO: alphanumeric? :D // This is the x86-32/64 xor encoder r_buf_append_buf (sc, egg->bin); if (egg->arch == R_SYS_ARCH_X86) { #define STUBLEN 18 ut8 stub[STUBLEN] = "\xe8\xff\xff\xff\xff" // call $$+4 "\xc1" // ffc1 = inc ecx "\x5e" // pop esi "\x48\x83\xc6\x0d" // add rsi, xx ... 64bit // loop0: "\x30\x1e" // xor [esi], bl "\x48\xff\xc6" // inc rsi "\xe2\xf9"; // loop loop0 // ecx = length aux[0] = 0x6a; // push length aux[1] = r_buf_size (sc); aux[2] = 0x59; // pop ecx // ebx = key aux[3] = 0x6a; // push key aux[4] = nkey; aux[5] = 0x5b; // pop ebx r_buf_set_bytes (buf, aux, 6); r_buf_append_bytes (buf, stub, STUBLEN); for (i = 0; i<r_buf_size (sc); i++) { ut8 v = r_buf_read8_at (sc, i) ^ nkey; r_buf_write_at (sc, i, &v, sizeof (v)); } r_buf_append_buf (buf, sc); } r_buf_free (sc); free (key); return buf; }
static RBuffer *build (REgg *egg) { RBuffer *buf, *sc; ut8 aux[32], nkey; int i; char *key = r_egg_option_get (egg, "key"); if (!key || !*key) { eprintf ("Invalid key (null)\n"); return R_FALSE; } nkey = r_num_math (NULL, key); if (nkey == 0) { eprintf ("Invalid key (%s)\n", key); return R_FALSE; } if (nkey != (nkey & 0xff)) { nkey &= 0xff; eprintf ("xor key wrapped to (%d)\n", nkey); } if (egg->bin->length > 240) { // XXX eprintf ("shellcode is too long :(\n"); return NULL; } sc = egg->bin; // hack for (i = 0; i<sc->length; i++) { // eprintf ("%02x -> %02x\n", sc->buf[i], sc->buf[i] ^nkey); if ((sc->buf[i]^nkey)==0) { eprintf ("This xor key generates null bytes. Try again.\n"); return NULL; } } buf = r_buf_new (); sc = r_buf_new (); // TODO: alphanumeric? :D // This is the x86-32/64 xor encoder r_buf_append_buf (sc, egg->bin); if (egg->arch == R_SYS_ARCH_X86) { #define STUBLEN 18 ut8 stub[STUBLEN] = "\xe8\xff\xff\xff\xff" // call $$+4 "\xc1" // ffc1 = inc ecx "\x5e" // pop esi "\x48\x83\xc6\x0d" // add rsi, xx ... 64bit // loop0: "\x30\x1e" // xor [esi], bl "\x48\xff\xc6" // inc rsi "\xe2\xf9"; // loop loop0 // ecx = length aux[0] = 0x6a; // push length aux[1] = sc->length; aux[2] = 0x59; // pop ecx // ebx = key aux[3] = 0x6a; // push key aux[4] = nkey; aux[5] = 0x5b; // pop ebx r_buf_set_bytes (buf, aux, 6); r_buf_append_bytes (buf, stub, STUBLEN); for (i = 0; i<sc->length; i++) { // eprintf ("%02x -> %02x\n", sc->buf[i], sc->buf[i] ^nkey); sc->buf[i]^=nkey; } r_buf_append_buf (buf, sc); } r_buf_free (sc); return buf; }