static bool check_bytes(const ut8 *buf, ut64 length) { const ut8* buf_hdr = buf; ut16 cksum1, cksum2; if ((length & 0x8000) == 0x200) { buf_hdr += 0x200; } if (length < 0x8000) { return false; } //determine if ROM is headered, and add a 0x200 gap if so. cksum1 = r_read_le16 (buf_hdr + 0x7FDC); cksum2 = r_read_le16 (buf_hdr + 0x7FDE); if (cksum1 == (ut16)~cksum2) { return true; } if (length < 0xffee) { return false; } cksum1 = r_read_le16(buf_hdr + 0xFFDC); cksum2 = r_read_le16(buf_hdr + 0xFFDE); return (cksum1 == (ut16)~cksum2); }
// This function reads from the file buffer, // thus using endian-agnostic functions int cmp_segs(const void *a, const void *b) { const ut16 * const ma = (const ut16 * const)a; const ut16 * const mb = (const ut16 * const)b; if (!ma || !mb) { return 0; } return (int)(r_read_le16 (ma) - r_read_le16 (mb)); }
static void headers64(RBinFile *bf) { #define p bf->rbin->cb_printf const ut8 *buf = r_buf_get_at (bf->buf, 0, NULL); p ("0x00000000 ELF64 0x%08x\n", r_read_le32 (buf)); p ("0x00000010 Type 0x%04x\n", r_read_le16 (buf + 0x10)); p ("0x00000012 Machine 0x%04x\n", r_read_le16 (buf + 0x12)); p ("0x00000014 Version 0x%08x\n", r_read_le32 (buf + 0x14)); p ("0x00000018 Entrypoint 0x%08"PFMT64x"\n", r_read_le64 (buf + 0x18)); p ("0x00000020 PhOff 0x%08"PFMT64x"\n", r_read_le64 (buf + 0x20)); p ("0x00000028 ShOff 0x%08"PFMT64x"\n", r_read_le64 (buf + 0x28)); }
// This function reads from the file buffer, // thus using endian-agnostic functions void trv_segs (const void *seg, const void *segs) { const ut8 * const mseg = (const ut8 * const)seg; ut16 ** const msegs = (ut16 **)segs; if (mseg && msegs && *msegs) { r_write_le16(*msegs, r_read_le16(mseg)); *msegs = *msegs + 1; } }
// header starts at offset 0 and ends at offset 0x40 static SymbolsHeader parseHeader(RBuffer *buf) { ut8 b[64]; SymbolsHeader sh = { 0 }; (void)r_buf_read_at (buf, 0, b, sizeof (b)); sh.magic = r_read_le32 (b); sh.version = r_read_le32 (b + 4); sh.valid = sh.magic == 0xff01ff02; int i; for (i = 0; i < 16; i++) { sh.uuid[i] = b[24 + i]; } sh.unk0 = r_read_le16 (b + 0x28); sh.unk1 = r_read_le16 (b + 0x2c); // is slotsize + 1 :? sh.slotsize = r_read_le16 (b + 0x2e); sh.size = 0x40; return sh; }
R_API ut64 r_mem_get_num(const ut8 *b, int size) { // LITTLE ENDIAN is the default for streams switch (size) { case 1: return r_read_le8 (b); case 2: return r_read_le16 (b); case 4: return r_read_le32 (b); case 8: return r_read_le64 (b); } return 0LL; }
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; }
struct r_bin_mz_segment_t * r_bin_mz_get_segments(const struct r_bin_mz_obj_t *bin) { #if 0 int i; struct r_bin_mz_segment_t *ret; const MZ_image_relocation_entry * const relocs = bin->relocation_entries; const int num_relocs = bin->dos_header->num_relocs; eprintf ("cs 0x%x\n", bin->dos_header->cs); eprintf ("ss 0x%x\n", bin->dos_header->ss); for (i = 0; i < num_relocs; i++) { eprintf ("0x%08x segment 0x%08lx\n", relocs[i].offset, relocs[i].segment); // ut65 paddr = r_bin_mz_seg_to_paddr (bin, relocs[i].segment) + relocs[i].offset; // eprintf ("pa 0x%08llx\n", paddr); } btree_add (&tree, (void *)&first_segment, cmp_segs); /* Add segment address of stack segment if it's resides inside dos executable. */ if (r_bin_mz_seg_to_paddr (bin, stack_segment) < bin->dos_file_size) { btree_add (&tree, (void *)&stack_segment, cmp_segs); } return NULL; #endif #if 1 struct btree_node *tree; struct r_bin_mz_segment_t *ret; ut16 *segments, *curr_seg; int i, num_segs; ut64 paddr; const ut16 first_segment = 0; const ut16 stack_segment = bin->dos_header->ss; const MZ_image_relocation_entry * const relocs = bin->relocation_entries; const int num_relocs = bin->dos_header->num_relocs; const ut64 last_parag = ((bin->dos_file_size + 0xF) >> 4) - \ bin->dos_header->header_paragraphs; btree_init (&tree); for (i = 0; i < num_relocs; i++) { paddr = r_bin_mz_seg_to_paddr (bin, relocs[i].segment) + relocs[i].offset; if ((paddr + 2) < bin->dos_file_size) { curr_seg = (ut16 *)(bin->b->buf + paddr); /* Add segment only if it's located inside dos executable data */ if (r_read_le16 (curr_seg) <= last_parag) { btree_add (&tree, curr_seg, cmp_segs); } } } /* Add segment address of first segment to make sure that it will be added. If relocations empty or there isn't first segment in relocations.) */ btree_add (&tree, (void *)&first_segment, cmp_segs); /* Add segment address of stack segment if it's resides inside dos executable. */ if (r_bin_mz_seg_to_paddr (bin, stack_segment) < bin->dos_file_size) { btree_add (&tree, (void *)&stack_segment, cmp_segs); } if (!num_relocs) { btree_cleartree (tree, NULL); return NULL; } segments = calloc (1 + num_relocs, sizeof (*segments)); if (!segments) { eprintf ("Error: calloc (segments)\n"); btree_cleartree (tree, NULL); return NULL; } curr_seg = segments; btree_traverse (tree, 0, &curr_seg, trv_segs); num_segs = curr_seg - segments; ret = calloc (num_segs + 1, sizeof (struct r_bin_mz_segment_t)); if (!ret) { free (segments); btree_cleartree (tree, NULL); eprintf ("Error: calloc (struct r_bin_mz_segment_t)\n"); return NULL; } btree_cleartree (tree, NULL); ret[0].paddr = r_bin_mz_seg_to_paddr (bin, segments[0]); for (i = 1; i < num_segs; i++) { ret[i].paddr = r_bin_mz_seg_to_paddr (bin, segments[i]); ret[i - 1].size = ret[i].paddr - ret[i - 1].paddr; } ret[i - 1].size = bin->dos_file_size - ret[i - 1].paddr; ret[i].last = 1; free (segments); return ret; #endif }
/** * crc16 - compute the CRC-16 for the data buffer * @crc: previous CRC value * @buffer: data pointer * @len: number of bytes in the buffer * * Returns the updated CRC value. */ R_API ut16 r_hash_crc16(ut16 crc, ut8 const *buffer, ut64 len) { while (len--) { crc = crc16_byte (crc, *buffer++); } return r_read_le16 (&crc); }