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; }
static void * load_bytes(RBinFile *bf, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb) { const struct r_bin_mz_obj_t *res = NULL; RBuffer *tbuf = NULL; if (!buf || !sz || 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; }
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_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; }
/* inspired in http://www.phreedom.org/solar/code/tinype/tiny.97/tiny.asm */ static RBuffer* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data, int datalen) { 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) D (I_MAGIC); // i386 only atm D (codelen); D (datalen); D (4096); // bss D (0); // syms D (8*4); // entry D (4096); // spsz D (4096); // pcsz B (code, codelen); if (datalen>0) B (data, datalen); return buf; }
R_API RBuffer *r_buf_new_file(const char *file, bool newFile) { const int mode = 0644; int flags = O_RDWR; if (newFile) { flags |= O_CREAT; } int fd = r_sandbox_open (file, flags, mode); if (fd != -1) { RBuffer *b = r_buf_new (); if (!b) { r_sandbox_close (fd); return NULL; } b->fd = fd; return b; } return NULL; /* we just freed b, don't return it */ }
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; }
int r_io_zip_slurp_file(RIOZipFileObj *zip_file_obj) { struct zip_file *zFile = NULL; int result = R_FALSE; struct zip * zipArch = r_io_zip_open_archive(zip_file_obj->archivename, zip_file_obj->flags, zip_file_obj->mode, zip_file_obj->rw); struct zip_stat sb; //eprintf("Slurping file"); if (zip_file_obj && zip_file_obj->entry != -1) { zFile = zip_fopen_index(zipArch, zip_file_obj->entry, 0); if (!zip_file_obj->b) { zip_file_obj->b = r_buf_new(); } zip_stat_init(&sb); if (zFile && zip_file_obj->b && !zip_stat_index(zipArch, zip_file_obj->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(zip_file_obj->b, buf, sb.size); zip_file_obj->opened = 1; result = R_TRUE; } if (buf) free(buf); } if (zFile) { zip_fclose(zFile); } } if (zipArch) zip_close(zipArch); return result; }
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* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data, int datalen) { ut32 filesize, codeva, datava; ut32 ncmds, cmdsize, magiclen; ut32 p_codefsz = 0, p_codeva = 0, p_codesz = 0, p_codepa = 0; ut32 p_datafsz = 0, p_datava = 0, p_datasz = 0, p_datapa = 0; ut32 p_cmdsize = 0, p_entry = 0, p_tmp = 0; ut32 baddr = 0x1000; int is_arm = !strcmp (bin->curarch.info->arch, "arm"); RBuffer *buf = r_buf_new (); if (bin->curarch.info->bits == 64) { eprintf ("TODO: Please use mach064 instead of mach0\n"); return 0; } #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 if (is_arm) { D (12); // cpu type (arm) D (3); // subtype (all?) } else { /* x86-32 */ 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) if (is_arm) { /* arm */ D (1); // i386-thread-state D (17); // thread-state-count p_entry = buf->length + (16*sizeof (ut32)); Z (17 * sizeof (ut32)); // mach0-arm has one byte more } else { /* x86-32 */ D (1); // i386-thread-state D (16); // thread-state-count p_entry = buf->length + (10*sizeof (ut32)); Z (16 * sizeof (ut32)); } cmdsize = 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, &cmdsize, 4); filesize = magiclen + cmdsize + 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; }
static RBuffer* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data, int datalen, RBinArchOptions *opt) { ut32 filesize, code_va, code_pa, phoff; ut32 p_start, p_phoff, p_phdr; ut32 p_ehdrsz, p_phdrsz; ut16 ehdrsz, phdrsz; ut32 p_vaddr, p_paddr, p_fs, p_fs2; ut32 baddr; int is_arm = 0; RBuffer *buf = r_buf_new (); r_return_val_if_fail (bin && opt && opt->arch, NULL); is_arm = !strcmp (opt->arch, "arm"); // XXX: hardcoded if (is_arm) { baddr = 0x40000; } else { baddr = 0x8048000; } #define B(x,y) r_buf_append_bytes(buf,(const ut8*)(x),y) #define D(x) r_buf_append_ut32(buf,x) #define H(x) r_buf_append_ut16(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=r_buf_size (buf);Z(x);W(p_tmp,y,strlen(y)) B ("\x7F" "ELF" "\x01\x01\x01\x00", 8); Z (8); H (2); // ET_EXEC if (is_arm) { H (40); // e_machne = EM_ARM } else { H (3); // e_machne = EM_I386 } D (1); p_start = r_buf_size (buf); D (-1); // _start p_phoff = r_buf_size (buf); D (-1); // phoff -- program headers offset D (0); // shoff -- section headers offset D (0); // flags p_ehdrsz = r_buf_size (buf); H (-1); // ehdrsz p_phdrsz = r_buf_size (buf); H (-1); // phdrsz H (1); H (0); H (0); H (0); // phdr: p_phdr = r_buf_size (buf); D (1); D (0); p_vaddr = r_buf_size (buf); D (-1); // vaddr = $$ p_paddr = r_buf_size (buf); D (-1); // paddr = $$ p_fs = r_buf_size (buf); D (-1); // filesize p_fs2 = r_buf_size (buf); D (-1); // filesize D (5); // flags D (0x1000); // align ehdrsz = p_phdr; phdrsz = r_buf_size (buf) - p_phdr; code_pa = r_buf_size (buf); code_va = code_pa + baddr; phoff = 0x34;//p_phdr ; filesize = code_pa + codelen + datalen; W (p_start, &code_va, 4); W (p_phoff, &phoff, 4); W (p_ehdrsz, &ehdrsz, 2); W (p_phdrsz, &phdrsz, 2); code_va = baddr; // hack W (p_vaddr, &code_va, 4); code_pa = baddr; // hack W (p_paddr, &code_pa, 4); W (p_fs, &filesize, 4); W (p_fs2, &filesize, 4); B (code, codelen); if (data && datalen > 0) { //ut32 data_section = buf->length; eprintf ("Warning: DATA section not support for ELF yet\n"); B (data, datalen); } 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; }
R_API RBuffer *r_buf_new_sparse() { RBuffer *b = r_buf_new (); b->sparse = r_list_newf ((RListFree)free); return b; }
/* 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; }
R_API int r_core_patch (RCore *core, const char *patch) { char *p, *p2, *q, str[200], tmp[64]; ut64 noff = 0LL; FILE *fd = r_sandbox_fopen (patch, "r"); if (fd==NULL) { eprintf ("Cannot open patch file\n"); return 1; } while (!feof (fd)) { fgets (str, sizeof (str), fd); if (*str=='#' || *str=='\n' || *str=='\r') continue; if (*str==':') { r_core_cmd0 (core, str+1); continue; } if (*str=='.' || *str=='!') { r_core_cmd0 (core, str); continue; } p = strchr (str+1, ' '); if (p) { *p = 0; for (++p; *p==' '; p++); // XXX: skipsspaces here switch (*p) { case '{': { char *s, *off = strdup (str); RBuffer *b = r_buf_new (); while (!feof (fd)) { fgets (str, sizeof (str), fd); if (*str=='}') break; if ((q=strstr (str, "${"))) { char *end = strchr (q+2,'}'); if (end) { *q = *end = 0; noff = r_num_math (core->num, q+2); r_buf_append_bytes (b, (const ut8*)str, strlen (str)); snprintf (tmp, sizeof (tmp), "0x%08"PFMT64x, noff); r_buf_append_bytes (b, (const ut8*)tmp, strlen (tmp)); r_buf_append_bytes (b, (const ut8*)end+1, strlen (end+1)); } } else r_buf_append_bytes (b, (const ut8*)str, strlen (str)); } s = r_buf_to_string (b); r_egg_load (core->egg, s, 0); free (s); r_egg_compile (core->egg); r_egg_assemble (core->egg); r_buf_free (b); b = r_egg_get_bin (core->egg); if (strcmp (off, "+")) noff = r_num_math (core->num, off); r_core_write_at (core, noff, b->buf, b->length); noff += b->length; r_buf_free (b); free (off); } break; case '"': p2 = strchr (p+1,'"'); if (p2) *p2=0; r_core_cmdf (core, "s %s", str); r_core_cmdf (core, "\"w %s\"", p+1); break; case ':': r_core_cmdf (core, "s %s", str); r_core_cmdf (core, "wa %s", p); break; default: r_core_cmdf (core, "s %s", str); r_core_cmdf (core, "wx %s", p); break; } } } fclose (fd); return 0; }
// http://code.google.com/p/smali/wiki/TypesMethodsAndFields R_API char *r_bin_demangle_java(const char *str) { const char *w = NULL; int is_array = 0; const char *ptr; int is_ret = 0; int wlen = 0; RBuffer *buf; int n = 0; char *ret; ptr = strchr (str, '('); if (!ptr) return NULL; buf = r_buf_new (); if (!buf) return NULL; r_buf_append_bytes (buf, (const ut8*)str, (int)(size_t)(ptr-str)); r_buf_append_bytes (buf, (const ut8*)" (", 2); while (*str) { switch (*str) { case ')': is_ret = 1; break; case '[': is_array = 1; break; case 'L': str++; ptr = strchr (str, ';'); if (ptr) { w = str; wlen = (int)(size_t)(ptr-str); } str = ptr; break; case 'I': w = "int"; wlen = 3; break; case 'C': w = "char"; wlen = 4; break; case 'B': w = "byte"; wlen = 4; break; case 'V': w = "void"; wlen = 4; break; case 'J': w = "long"; wlen = 4; break; case 'F': w = "float"; wlen = 5; break; case 'S': w = "short"; wlen = 5; break; case 'D': w = "double"; wlen = 6; break; case 'Z': w = "boolean"; wlen = 7; break; } if (w) { if (is_ret) { r_buf_prepend_bytes (buf, (const ut8*)" ", 1); r_buf_prepend_bytes (buf, (const ut8*)w, wlen); r_buf_append_bytes (buf, (const ut8*)")", 1); break; } else { if (n++>0) r_buf_append_bytes (buf, (const ut8*)", ", 2); r_buf_append_bytes (buf, (const ut8*)w, wlen); } if (is_array) { r_buf_append_bytes (buf, (const ut8*)"[]", 2); is_array = 0; } } w = NULL; if (!str) break; str++; } ret = r_buf_to_string (buf); r_buf_free (buf); return ret; }
static RBuffer* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data, int datalen) { const bool use_pagezero = true; const bool use_main = true; const bool use_dylinker = true; const bool use_libsystem = true; const bool use_linkedit = true; ut64 filesize, codeva, datava; ut32 ncmds, magiclen, headerlen; ut64 p_codefsz=0, p_codeva=0, p_codesz=0, p_codepa=0; ut64 p_datafsz=0, p_datava=0, p_datasz=0, p_datapa=0; ut64 p_cmdsize=0, p_entry=0, p_tmp=0; ut64 baddr = 0x100001000LL; // TODO: baddr must be overriden with -b 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 Q(x) r_buf_append_ut64(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 */ // 32bit B ("\xce\xfa\xed\xfe", 4); // header B ("\xcf\xfa\xed\xfe", 4); // header D (7 | 0x01000000); // cpu type (x86) | ABI64 //D (3); // subtype (i386-all) D(0x80000003); // x86-64 subtype D (2); // filetype (executable) ncmds = (data && datalen>0)? 3: 2; if (use_pagezero) { ncmds++; } if (use_dylinker) { ncmds++; if (use_linkedit) { ncmds += 3; } if (use_libsystem) { ncmds++; } } /* COMMANDS */ D (ncmds); // ncmds p_cmdsize = buf->length; D (-1); // headsize // cmdsize? D (0);//0x85); // flags D (0); // reserved -- only found in x86-64 magiclen = buf->length; if (use_pagezero) { /* PAGEZERO */ D (0x19); // cmd.LC_SEGMENT D (72); // sizeof (cmd) WZ (16, "__PAGEZERO"); Q (0); // vmaddr Q (0x1000); // vmsize XXX Q (0); // fileoff Q (0); // filesize D (0); // maxprot D (0); // initprot D (0); // nsects D (0); // flags } /* TEXT SEGMENT */ D (0x19); // cmd.LC_SEGMENT_64 //D (124+16+8); // sizeof (cmd) D (124+28); // sizeof (cmd) WZ (16, "__TEXT"); Q (baddr); // vmaddr Q (0x1000); // vmsize XXX Q (0); // fileoff p_codefsz = buf->length; Q (-1); // filesize D (7); // maxprot D (5); // initprot D (1); // nsects D (0); // flags // define section WZ (16, "__text"); WZ (16, "__TEXT"); p_codeva = buf->length; // virtual address Q (-1); p_codesz = buf->length; // size of code (end-start) Q (-1); p_codepa = buf->length; // code - baddr D (-1); // offset, _start-0x1000); D (2); // align D (0); // reloff D (0); // nrelocs D (0); // flags D (0); // reserved1 D (0); // reserved2 D (0); // reserved3 if (data && datalen>0) { /* DATA SEGMENT */ D (0x19); // cmd.LC_SEGMENT_64 D (124+28); // sizeof (cmd) p_tmp = buf->length; Z (16); W (p_tmp, "__TEXT", 6); // segment name //XXX must be vmaddr+baddr Q (0x2000); // vmaddr //XXX must be vmaddr+baddr Q (0x1000); // vmsize Q (0); // fileoff p_datafsz = buf->length; Q (-1); // filesize D (6); // maxprot D (6); // initprot D (1); // nsects D (0); // flags WZ (16, "__data"); WZ (16, "__DATA"); p_datava = buf->length; Q (-1); p_datasz = buf->length; Q (-1); p_datapa = buf->length; D (-1); //_start-0x1000); D (2); // align D (0); // reloff D (0); // nrelocs D (0); // flags D (0); // reserved1 D (0); // reserved2 D (0); // reserved3 } if (use_dylinker) { if (use_linkedit) { /* LINKEDIT */ D (0x19); // cmd.LC_SEGMENT D (72); // sizeof (cmd) WZ (16, "__LINKEDIT"); Q (0x3000); // vmaddr Q (0x00001000); // vmsize XXX Q (0x1000); // fileoff Q (0); // filesize D (7); // maxprot D (3); // initprot D (0); // nsects D (0); // flags /* LC_SYMTAB */ D (2); // cmd.LC_SYMTAB D (24); // sizeof (cmd) D (0x1000); // symtab offset D (0); // symtab size D (0x1000); // strtab offset D (0); // strtab size /* LC_DYSYMTAB */ D (0xb); // cmd.LC_DYSYMTAB D (80); // sizeof (cmd) Z (18 * sizeof (ut32)); // empty } const char *dyld = "/usr/lib/dyld"; const int dyld_len = strlen (dyld) + 1; D(0xe); /* LC_DYLINKER */ D((4 * 3) + dyld_len); D(dyld_len - 2); WZ(dyld_len, dyld); // path if (use_libsystem) { /* add libSystem at least ... */ const char *lib = "/usr/lib/libSystem.B.dylib"; const int lib_len = strlen (lib) + 1; D (0xc); /* LC_LOAD_DYLIB */ D (24 + lib_len); // cmdsize D (24); // offset where the lib string start D (0x2); D (0x1); D (0x1); WZ (lib_len, lib); } } if (use_main) { /* LC_MAIN */ D (0x80000028); // cmd.LC_MAIN D (24); // sizeof (cmd) D (baddr); // entryoff D (0); // stacksize D (0); // ??? D (0); // ??? } else { #define STATESIZE (21*sizeof (ut64)) /* THREAD STATE */ D (5); // LC_UNIXTHREAD D (184); // sizeof (cmd) D (4); // 1=i386, 4=x86_64 D (42); // thread-state-count p_entry = buf->length + (16*sizeof (ut64)); Z (STATESIZE); } WZ (4096 - buf->length, ""); headerlen = buf->length - magiclen; codeva = buf->length + baddr; datava = buf->length + codelen + baddr; if (p_entry != 0) { W (p_entry, &codeva, 8); // set PC } /* fill header variables */ W (p_cmdsize, &headerlen, 4); filesize = magiclen + headerlen + codelen + datalen; // TEXT SEGMENT // W (p_codefsz, &filesize, 8); W (p_codefsz-16, &filesize, 8); // vmsize = filesize W (p_codeva, &codeva, 8); { ut64 clen = codelen; W (p_codesz, &clen, 8); } p_tmp = codeva - baddr; W (p_codepa, &p_tmp, 8); B (code, codelen); if (data && datalen>0) { /* append data */ W (p_datafsz, &filesize, 8); W (p_datava, &datava, 8); W (p_datasz, &datalen, 8); p_tmp = datava - baddr; W (p_datapa, &p_tmp, 8); B (data, datalen); } return buf; }
static RBuffer* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data, int datalen) { ut32 filesize, code_va, code_pa, phoff; ut32 p_start, p_phoff, p_phdr; ut32 p_ehdrsz, p_phdrsz; ut16 ehdrsz, phdrsz; ut32 p_vaddr, p_paddr, p_fs, p_fs2; ut32 baddr = 0x8048000; 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 H(x) r_buf_append_ut16(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)) B ("\x7F" "CGC" "\x01\x01\x01\x43", 8); Z (8); H (2); // ET_EXEC H (3); // e_machne = EM_I386 D (1); p_start = buf->length; D (-1); // _start p_phoff = buf->length; D (-1); // phoff -- program headers offset D (0); // shoff -- section headers offset D (0); // flags p_ehdrsz = buf->length; H (-1); // ehdrsz p_phdrsz = buf->length; H (-1); // phdrsz H (1); H (0); H (0); H (0); // phdr: p_phdr = buf->length; D (1); D (0); p_vaddr = buf->length; D (-1); // vaddr = $$ p_paddr = buf->length; D (-1); // paddr = $$ p_fs = buf->length; D (-1); // filesize p_fs2 = buf->length; D (-1); // filesize D (5); // flags D (0x1000); // align ehdrsz = p_phdr; phdrsz = buf->length - p_phdr; code_pa = buf->length; code_va = code_pa + baddr; phoff = 0x34;//p_phdr ; filesize = code_pa + codelen + datalen; W (p_start, &code_va, 4); W (p_phoff, &phoff, 4); W (p_ehdrsz, &ehdrsz, 2); W (p_phdrsz, &phdrsz, 2); code_va = baddr; // hack W (p_vaddr, &code_va, 4); code_pa = baddr; // hack W (p_paddr, &code_pa, 4); W (p_fs, &filesize, 4); W (p_fs2, &filesize, 4); B (code, codelen); if (data && datalen>0) { //ut32 data_section = buf->length; eprintf ("Warning: DATA section not support for ELF yet\n"); B (data, datalen); } return buf; }
/* inspired in http://www.phreedom.org/solar/code/tinype/tiny.97/tiny.asm */ static RBuffer* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data, int datalen) { RBuffer *buf = r_buf_new (); return buf; }
R_API RBuffer *r_buf_new_with_bytes (const ut8 *bytes, ut64 len) { RBuffer *b = r_buf_new (); if (bytes && (len > 0 && len != UT64_MAX)) r_buf_set_bytes (b, bytes, len); return b; }
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; }
static RBuffer* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data, int datalen) { ut64 filesize, codeva, datava; ut32 ncmds, magiclen, headerlen; ut64 p_codefsz=0, p_codeva=0, p_codesz=0, p_codepa=0; ut64 p_datafsz=0, p_datava=0, p_datasz=0, p_datapa=0; ut64 p_cmdsize=0, p_entry=0, p_tmp=0; ut64 baddr = 0x100001000LL; // TODO: baddr must be overriden with -b 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 Q(x) r_buf_append_ut64(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 */ // 32bit B ("\xce\xfa\xed\xfe", 4); // header B ("\xcf\xfa\xed\xfe", 4); // header D (7 | 0x01000000); // cpu type (x86) | ABI64 //D (3); // subtype (i386-all) D(0x80000003); // unknown subtype issue D (2); // filetype (executable) ncmds = (data && datalen>0)? 3: 2; /* COMMANDS */ D (ncmds); // ncmds p_cmdsize = buf->length; D (-1); // headsize // cmdsize? D (0);//0x85); // flags D (0); // reserved -- only found in x86-64 magiclen = buf->length; /* TEXT SEGMENT */ D (0x19); // cmd.LC_SEGMENT_64 //D (124+16+8); // sizeof (cmd) D (124+28); // sizeof (cmd) WZ (16, "__TEXT"); Q (baddr); // vmaddr Q (0x1000); // vmsize XXX Q (0); // fileoff p_codefsz = buf->length; Q (-1); // filesize D (7); // maxprot D (5); // initprot D (1); // nsects D (0); // flags // define section WZ (16, "__text"); WZ (16, "__TEXT"); p_codeva = buf->length; // virtual address Q (-1); p_codesz = buf->length; // size of code (end-start) Q (-1); p_codepa = buf->length; // code - baddr D (-1); // offset, _start-0x1000); D (2); // align D (0); // reloff D (0); // nrelocs D (0); // flags D (0); // reserved1 D (0); // reserved2 D (0); // reserved3 if (data && datalen>0) { /* DATA SEGMENT */ D (0x19); // cmd.LC_SEGMENT_64 D (124+28); // sizeof (cmd) p_tmp = buf->length; Z (16); W (p_tmp, "__TEXT", 6); // segment name //XXX must be vmaddr+baddr Q (0x2000); // vmaddr //XXX must be vmaddr+baddr Q (0x1000); // vmsize Q (0); // fileoff p_datafsz = buf->length; Q (-1); // filesize D (6); // maxprot D (6); // initprot D (1); // nsects D (0); // flags WZ (16, "__data"); WZ (16, "__DATA"); p_datava = buf->length; Q (-1); p_datasz = buf->length; Q (-1); p_datapa = buf->length; D (-1); //_start-0x1000); D (2); // align D (0); // reloff D (0); // nrelocs D (0); // flags D (0); // reserved1 D (0); // reserved2 D (0); // reserved3 } #define STATESIZE (21*sizeof (ut64)) /* THREAD STATE */ D (5); // LC_UNIXTHREAD D (184); // sizeof (cmd) D (4); // 1=i386, 4=x86_64 D (42); // thread-state-count p_entry = buf->length + (16*sizeof (ut64)); Z (STATESIZE); headerlen = buf->length - magiclen; codeva = buf->length + baddr; datava = buf->length + codelen + baddr; W (p_entry, &codeva, 8); // set PC /* fill header variables */ W (p_cmdsize, &headerlen, 4); filesize = magiclen + headerlen + codelen + datalen; // TEXT SEGMENT // W (p_codefsz, &filesize, 8); W (p_codeva, &codeva, 8); { ut64 clen = codelen; W (p_codesz, &clen, 8); } p_tmp = codeva - baddr; W (p_codepa, &p_tmp, 8); B (code, codelen); if (data && datalen>0) { /* append data */ W (p_datafsz, &filesize, 8); W (p_datava, &datava, 8); W (p_datasz, &datalen, 8); p_tmp = datava - baddr; W (p_datapa, &p_tmp, 8); B (data, datalen); } return buf; }
static RBuffer* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data, int datalen, RBinArchOptions *opt) { ut32 p_start, p_phoff, p_phdr; ut32 p_vaddr, p_paddr, p_fs, p_fs2; ut32 p_ehdrsz, p_phdrsz; ut64 filesize, code_va, code_pa, phoff; ut16 ehdrsz, phdrsz; ut64 baddr = 0x400000LL; RBuffer *buf = r_buf_new (); #define B(x,y) r_buf_append_bytes(buf,(const ut8*)(x),y) #define Q(x) r_buf_append_ut64(buf,x) #define D(x) r_buf_append_ut32(buf,x) #define H(x) r_buf_append_ut16(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) /* Ehdr */ B ("\x7F" "ELF" "\x02\x01\x01\x00", 8); // e_ident (ei_class = ELFCLASS64) Z (8); H (2); // e_type = ET_EXEC H (62); // e_machine = EM_X86_64 D (1); // e_version = EV_CURRENT p_start = r_buf_size (buf); Q (-1); // e_entry = 0xFFFFFFFF p_phoff = r_buf_size (buf); Q (-1); // e_phoff = 0xFFFFFFFF Q (0); // e_shoff = 0xFFFFFFFF D (0); // e_flags p_ehdrsz = r_buf_size (buf); H (-1); // e_ehsize = 0xFFFFFFFF p_phdrsz = r_buf_size (buf); H (-1); // e_phentsize = 0xFFFFFFFF H (1); // e_phnum H (0); // e_shentsize H (0); // e_shnum H (0); // e_shstrndx /* Phdr */ p_phdr = r_buf_size (buf); D (1); // p_type D (5); // p_flags = PF_R | PF_X Q (0); // p_offset p_vaddr = r_buf_size (buf); Q (-1); // p_vaddr = 0xFFFFFFFF p_paddr = r_buf_size (buf); Q (-1); // p_paddr = 0xFFFFFFFF p_fs = r_buf_size (buf); Q (-1); // p_filesz p_fs2 = r_buf_size (buf); Q (-1); // p_memsz Q (0x200000); // p_align /* Calc fields */ ehdrsz = p_phdr; phdrsz = r_buf_size (buf) - p_phdr; code_pa = r_buf_size (buf); code_va = code_pa + baddr; phoff = p_phdr; filesize = code_pa + codelen + datalen; /* Write fields */ W (p_start, &code_va, 8); W (p_phoff, &phoff, 8); W (p_ehdrsz, &ehdrsz, 2); W (p_phdrsz, &phdrsz, 2); W (p_fs, &filesize, 8); W (p_fs2, &filesize, 8); W (p_vaddr, &baddr, 8); W (p_paddr, &baddr, 8); /* Append code */ B (code, codelen); if (data && datalen>0) { eprintf ("Warning: DATA section not support for ELF yet\n"); B (data, datalen); } return buf; }
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; }