static void OLE_parse_summary(FILE *file, const uint32_t *fat, const unsigned int fat_entries, const struct OLE_HDR *header, const unsigned int ministream_block, const unsigned int ministream_size, const unsigned int block, const unsigned int len, const char **ext, char **title, time_t *file_time) { unsigned char *summary=NULL; if(len < 48 || len>1024*1024) return ; if(len < le32(header->miniSectorCutoff)) { if(le32(header->csectMiniFat)!=0 && ministream_size > 0 && ministream_size < 1024*1024) { const unsigned int mini_fat_entries=(le32(header->csectMiniFat) << le16(header->uSectorShift)) / 4; uint32_t *minifat; unsigned char *ministream; if((minifat=OLE_load_MiniFAT(file, header, fat, fat_entries))==NULL) return ; ministream=(unsigned char *)OLE_read_stream(file, fat, fat_entries, le16(header->uSectorShift), ministream_block, ministream_size); if(ministream != NULL) { summary=(unsigned char*)OLE_read_ministream(ministream, minifat, mini_fat_entries, le16(header->uMiniSectorShift), block, len, ministream_size); free(ministream); } free(minifat); } } else summary=(unsigned char *)OLE_read_stream(file, fat, fat_entries, le16(header->uSectorShift), block, len); if(summary!=NULL) { OLE_parse_summary_aux(summary, len, ext, title, file_time); free(summary); } }
static int header_check_qbb(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) { const struct qbb_header *hdr0=(const struct qbb_header*)buffer; uint64_t data_size=0; unsigned int i=0; if(buffer[0x0e]!=0x45 || buffer[0x0f]!=0x86) return 0; while(i+sizeof(struct qbb_header02) < buffer_size) { const struct qbb_header *hdr=(const struct qbb_header*)&buffer[i]; if(le16(hdr->magic)!=0x8645) break; if(le16(hdr->type)==2) { const struct qbb_header02 *hdr2=(const struct qbb_header02 *)hdr; data_size=le32(hdr2->size); } #ifdef DEBUG_QBB log_info("i=0x%x size=0x%lx len=0x%x\n", i, sizeof(struct qbb_header), le16(hdr->data_len)); #endif i+=sizeof(struct qbb_header)+le16(hdr->data_len); } #ifdef DEBUG_QBB log_info("i=0x%x data_size=0x%lx\n", i, (long unsigned)data_size); #endif if(data_size==0) return 0; reset_file_recovery(file_recovery_new); file_recovery_new->calculated_file_size=data_size+i; if(le16(hdr0->unk1)==1) file_recovery_new->extension="qbmb"; else file_recovery_new->extension=file_hint_qbb.extension; file_recovery_new->data_check=&data_check_size; file_recovery_new->file_check=&file_check_size; file_recovery_new->file_rename=&file_rename_qbb; return 1; }
static unsigned int tiff_le_read(const void *val, const unsigned int type) { switch(type) { case 1: return *((const uint8_t*)val); case 3: return le16(*((const uint16_t*)val)); case 4: return le32(*((const uint32_t*)val)); default: return 0; } }
static int header_check_cab(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) { const struct cab_header *cab_hdr=(const struct cab_header*)buffer; if(le16(cab_hdr->cab_version)==0x0103 && le32(cab_hdr->filesize) >= sizeof(struct cab_header)) { reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_cab.extension; file_recovery_new->calculated_file_size=(uint64_t)le32(cab_hdr->filesize); file_recovery_new->data_check=&data_check_size; file_recovery_new->file_check=&file_check_size; return 1; } return 0; }
static const char *find_tag_from_tiff_header_le_aux(const TIFFHeader *tiff, const unsigned int tiff_size, const unsigned int tag, const char**potential_error, const struct ifd_header *hdr) { const TIFFDirEntry *tmp; unsigned int i; unsigned int nbr_fields; /* Bound checking */ if((const char*)(hdr) <= (const char*)tiff || (const char*)(hdr+1) > (const char*)tiff+tiff_size) return NULL; nbr_fields=le16(hdr->nbr_fields); for(i=0, tmp=&hdr->ifd; i < nbr_fields && (const char*)(tmp+1) <= (const char*)tiff+tiff_size; i++, tmp++) { if(le16(tmp->tdir_type) > 18 && (*potential_error==NULL || *potential_error > (const char*)&tmp->tdir_type+1)) { *potential_error = (const char*)&tmp->tdir_type+1; } if(le16(tmp->tdir_tag)==tag) return (const char*)tiff+le32(tmp->tdir_offset); } return NULL; }
static int header_check_mft(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) { const struct ntfs_mft_record *mft_rec=(const struct ntfs_mft_record *)buffer; const unsigned int usa_ofs = le16(mft_rec->usa_ofs); const unsigned int usa_count = le16(mft_rec->usa_count); const unsigned int attrs_offset = le16(mft_rec->attrs_offset); const unsigned int bytes_in_use = le32(mft_rec->bytes_in_use); const unsigned int bytes_allocated = le32(mft_rec->bytes_allocated); if(!(memcmp(buffer,"FILE",4)==0 && usa_ofs+usa_count <= attrs_offset && 42 <= attrs_offset && attrs_offset%8==0 && attrs_offset < bytes_in_use && bytes_in_use <= bytes_allocated)) return 0; reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_mft.extension; file_recovery_new->calculated_file_size=bytes_allocated; file_recovery_new->data_check=&data_check_size; file_recovery_new->file_check=&file_check_size; file_recovery_new->file_rename=&file_rename_mft; return 1; }
static int test_rfs4(const disk_t *disk_car, const struct reiser4_master_sb *sb, const partition_t *partition, const int verbose) { if (memcmp(sb->magic,REISERFS4_SUPER_MAGIC,sizeof(REISERFS4_SUPER_MAGIC)) != 0) return 1; if(verbose>0) log_info("\nReiserFS Marker at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset)); /* * sanity checks. */ if (le16(sb->blocksize) != 4096) return (1); /* if a value > 4096 become legal, the code will break while reading the filesystem size (read out of bound) */ return 0; }
static int set_rfs_info(const struct reiserfs_super_block *sb, partition_t *partition) { partition->fsname[0]='\0'; partition->blocksize=le16(sb->s_blocksize); switch(partition->upart_type) { case UP_RFS: snprintf(partition->info, sizeof(partition->info), "ReiserFS 3.5 with standard journal blocksize=%u", partition->blocksize); break; case UP_RFS2: snprintf(partition->info, sizeof(partition->info), "ReiserFS 3.6 with standard journal blocksize=%u", partition->blocksize); set_part_name(partition,(const char*)sb->s_label,16); break; case UP_RFS3: if(le16(sb->sb_version)==1) snprintf(partition->info, sizeof(partition->info), "ReiserFS 3.5 with non standard journal blocksize=%u", partition->blocksize); else if(le16(sb->sb_version)==2) snprintf(partition->info, sizeof(partition->info), "ReiserFS 3.6 with non standard journal blocksize=%u", partition->blocksize); else snprintf(partition->info, sizeof(partition->info), "ReiserFS 3.? with non standard journal blocksize=%u", partition->blocksize); set_part_name(partition,(const char*)sb->s_label,16); break; default: partition->info[0]='\0'; return 1; } if (le16(sb->s_state) == REISERFS_ERROR_FS) { strcat(partition->info,", need recovery"); } return 0; }
static void file_check_xm(file_recovery_t *fr) { uint16_t patterns, instrs; fr->file_size = 0; fr->offset_error=0; fr->offset_ok=0; if (fseek(fr->handle, 70, SEEK_SET) == -1) return; if (fread(&patterns, 2, 1, fr->handle) != 1) return; if (fread(&instrs, 2, 1, fr->handle) != 1) return; instrs = le16(instrs); patterns = le16(patterns); log_debug("xm: %u patterns, %u instruments\n", patterns, instrs); /* Skip flags + tempo + bmp + table */ if (fseek(fr->handle, 2+2+2+256, SEEK_CUR) == -1) return; fr->file_size = 336; /* Parse patterns and next instruments */ if (parse_patterns(fr, patterns) < 0 || parse_instruments(fr, instrs) < 0) { log_debug("xm: lost sync at pos %li\n", ftell(fr->handle)); fr->offset_error = fr->file_size; fr->file_size = 0; return; } /* ModPlug may insert additional data but it is of little relevance */ }
static void set_rfs_info(const struct reiserfs_super_block *sb, partition_t *partition) { partition->fsname[0]='\0'; partition->blocksize=le16(sb->s_blocksize); if (memcmp(sb->s_magic,REISERFS_SUPER_MAGIC,sizeof(REISERFS_SUPER_MAGIC)) == 0) { partition->upart_type = UP_RFS; snprintf(partition->info, sizeof(partition->info), "ReiserFS 3.5 with standard journal blocksize=%u", partition->blocksize); } else if(memcmp(sb->s_magic,REISERFS2_SUPER_MAGIC,sizeof(REISERFS2_SUPER_MAGIC)) == 0) { partition->upart_type = UP_RFS2; snprintf(partition->info, sizeof(partition->info), "ReiserFS 3.6 with standard journal blocksize=%u", partition->blocksize); set_part_name(partition,(const char*)sb->s_label,16); } else if(memcmp(sb->s_magic,REISERFS3_SUPER_MAGIC,sizeof(REISERFS3_SUPER_MAGIC)) == 0) { partition->upart_type = UP_RFS3; if(le16(sb->sb_version)==1) snprintf(partition->info, sizeof(partition->info), "ReiserFS 3.5 with non standard journal blocksize=%u", partition->blocksize); else if(le16(sb->sb_version)==2) snprintf(partition->info, sizeof(partition->info), "ReiserFS 3.6 with non standard journal blocksize=%u", partition->blocksize); else snprintf(partition->info, sizeof(partition->info), "ReiserFS 3.? with non standard journal blocksize=%u", partition->blocksize); set_part_name(partition,(const char*)sb->s_label,16); } if(le16(sb->s_state) == REISERFS_ERROR_FS) { strcat(partition->info,", need recovery"); } }
static int test_rfs(const disk_t *disk_car, const struct reiserfs_super_block *sb, partition_t *partition, const int verbose) { if (memcmp(sb->s_magic,REISERFS_SUPER_MAGIC,sizeof(REISERFS_SUPER_MAGIC)) == 0) { partition->upart_type = UP_RFS; } else if(memcmp(sb->s_magic,REISERFS2_SUPER_MAGIC,sizeof(REISERFS2_SUPER_MAGIC)) == 0) { partition->upart_type = UP_RFS2; } else if(memcmp(sb->s_magic,REISERFS3_SUPER_MAGIC,sizeof(REISERFS3_SUPER_MAGIC)) == 0) { partition->upart_type = UP_RFS3; } else return 1; if(verbose>0) log_info("\nReiserFS Marker at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset), offset2head(disk_car,partition->part_offset), offset2sector(disk_car,partition->part_offset)); /* * sanity checks. */ if (le32(sb->s_block_count) < le32(sb->s_free_blocks)) return (1); if (le32(sb->s_block_count) < REISERFS_MIN_BLOCK_AMOUNT) return (1); if ((le16(sb->s_state) != REISERFS_VALID_FS) && (le16(sb->s_state) != REISERFS_ERROR_FS)) return (1); if (le16(sb->s_oid_maxsize) % 2!=0) /* must be even */ return (1); if (le16(sb->s_oid_maxsize) < le16(sb->s_oid_cursize)) return (1); if ((le16(sb->s_blocksize) != 4096) && (le16(sb->s_blocksize) != 8192)) return (1); return 0; }
static void file_rename_ext(file_recovery_t *file_recovery) { unsigned char buffer[512]; char buffer_cluster[32]; FILE *file; const struct ext2_super_block *sb=(const struct ext2_super_block *)&buffer; int buffer_size; unsigned long int block_nr; if((file=fopen(file_recovery->filename, "rb"))==NULL) return; buffer_size=fread(buffer, 1, sizeof(buffer), file); fclose(file); if(buffer_size!=sizeof(buffer)) return; block_nr=(le32(sb->s_first_data_block)+le16(sb->s_block_group_nr)*le32(sb->s_blocks_per_group)); sprintf(buffer_cluster, "sb_%lu", block_nr); file_rename(file_recovery, buffer_cluster, strlen(buffer_cluster), 0, NULL, 1); }
int recover_sun_i386(disk_t *disk_car, const sun_partition_i386 *sunlabel, partition_t *partition,const int verbose, const int dump_ind) { if(test_sun_i386(disk_car, sunlabel, partition, verbose)!=0) return 1; if(verbose>0 || dump_ind!=0) { log_info("\nrecover_sun\n"); if(dump_ind!=0) { dump_log(sunlabel,sizeof(*sunlabel)); } } partition->part_size=(uint64_t)le32(sunlabel->partitions[2].num_sectors) * le16(sunlabel->sector_size); set_sun_info_i386(partition); partition->part_type_i386 = P_SUN; partition->part_type_gpt=GPT_ENT_TYPE_SOLARIS_ROOT; return 0; }
static int zip_parse_end_central_dir(file_recovery_t *fr) { struct { uint16_t number_disk; /** Number of this disk */ uint16_t number_disk2; /** Number in the central dir */ uint16_t total_number_disk; /** Total number of entries in this disk */ uint16_t total_number_disk2; /** Total number of entries in the central dir */ uint32_t size; /** Size of the central directory */ uint32_t offset; /** Offset of start of central directory */ uint16_t comment_length; /** Comment length */ } __attribute__ ((__packed__)) dir; if (fread(&dir, sizeof(dir), 1, fr->handle) != 1) { #ifdef DEBUG_ZIP log_trace("zip: Unexpected EOF reading header of zip_parse_end_central_dir\n"); #endif return -1; } fr->file_size += sizeof(dir); if (dir.comment_length) { const uint16_t len = le16(dir.comment_length); #ifdef HAVE_FSEEKO if (fseeko(fr->handle, len, SEEK_CUR) == -1) #else if (fseek(fr->handle, len, SEEK_CUR) == -1) #endif { #ifdef DEBUG_ZIP log_trace("zip: Unexpected EOF in end_central_dir: expected %u bytes\n", len); #endif return -1; } fr->file_size += len; #ifdef DEBUG_ZIP log_trace("zip: Comment of length %u\n", len); #endif } return 0; }
static int get_geometry_from_nonembr(const unsigned char *buffer, const int verbose, CHSgeometry_t *geometry) { { /* Ugly hack to get geometry from FAT and NTFS */ const struct fat_boot_sector *fat_header=(const struct fat_boot_sector *)buffer; if(le16(fat_header->marker)==0xAA55) { if(le16(fat_header->secs_track)>0 && le16(fat_header->secs_track)<=63 && le16(fat_header->heads)>0 && le16(fat_header->heads)<=255 && fat_sector_size(fat_header)>0 && fat_sector_size(fat_header)%512==0) { geometry->sectors_per_head=le16(fat_header->secs_track); geometry->heads_per_cylinder=le16(fat_header->heads); geometry->bytes_per_sector=fat_sector_size(fat_header); } } } return 0; }
static int test_LVM(disk_t *disk_car, const pv_disk_t *pv, const partition_t *partition, const int verbose, const int dump_ind) { if ((memcmp((const char *)pv->id,LVM_ID,sizeof(pv->id)) == 0) && (le16(pv->version) == 1 || le16(pv->version) == 2)) { uint32_t size; if(verbose>0 || dump_ind!=0) { log_info("\nLVM magic value at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset)); } if(dump_ind!=0) { /* There is a little offset ... */ dump_log(pv,DEFAULT_SECTOR_SIZE); } if (le32(pv->pv_size) > LVM_MAX_SIZE) return (1); if (le32(pv->pv_status) != 0 && le32(pv->pv_status) != PV_ACTIVE) return (1); if (le32(pv->pv_allocatable) != 0 && le32(pv->pv_allocatable) != PV_ALLOCATABLE) return (1); if (le32(pv->lv_cur) > MAX_LV) return (1); if (strlen((const char *)pv->vg_name) > NAME_LEN / 2) return (1); size = le32(pv->pe_size) / LVM_MIN_PE_SIZE * LVM_MIN_PE_SIZE; if ((le32(pv->pe_size) != size) || (le32(pv->pe_size) < LVM_MIN_PE_SIZE) || (le32(pv->pe_size) > LVM_MAX_PE_SIZE)) return (1); if (le32(pv->pe_total) > ( pv->pe_on_disk.size / sizeof ( disk_pe_t))) return (1); if (le32(pv->pe_allocated) > le32(pv->pe_total)) return (1); return 0; } return 1; }
const char *find_tag_from_tiff_header_le(const TIFFHeader *tiff, const unsigned int tiff_size, const unsigned int tag, const char**potential_error) { const struct ifd_header *ifd0; const struct ifd_header *exififd; const uint32_t *tiff_next_diroff; if(tiff_size < sizeof(TIFFHeader)) return NULL; if(tiff_size < le32(tiff->tiff_diroff)+sizeof(TIFFDirEntry)) return NULL; ifd0=(const struct ifd_header *)((const char*)tiff + le32(tiff->tiff_diroff)); /* Bound checking */ if((const char*)ifd0 < (const char*)tiff || (const char*)(ifd0+1) > (const char*)tiff + tiff_size) return NULL; { const char *tmp=find_tag_from_tiff_header_le_aux(tiff, tiff_size, tag, potential_error, ifd0); if(tmp) return tmp; } exififd=(const struct ifd_header *)find_tag_from_tiff_header_le_aux(tiff, tiff_size, TIFFTAG_EXIFIFD, potential_error, ifd0); if(exififd!=NULL) { /* Exif */ const char *tmp=find_tag_from_tiff_header_le_aux(tiff, tiff_size, tag, potential_error, exififd); if(tmp) return tmp; } tiff_next_diroff=(const uint32_t *)(&ifd0->ifd + le16(ifd0->nbr_fields)); if( (const char *)tiff_next_diroff >= (const char *)tiff && (const char *)(tiff_next_diroff + 1) < (const char*)tiff + tiff_size && le32(*tiff_next_diroff)>0) { /* IFD1 */ const struct ifd_header *ifd1=(const struct ifd_header*)((const char *)tiff+le32(*tiff_next_diroff)); return find_tag_from_tiff_header_le_aux(tiff, tiff_size, tag, potential_error, ifd1); } return NULL; }
static data_check_t psd_skip_color_mode(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery) { const struct psd_file_header *psd=(const struct psd_file_header *)&buffer[buffer_size/2]; psd_image_data_size_max=(uint64_t)le16(psd->channels) * le32(psd->height) * le32(psd->width) * le16(psd->depth) / 8; #ifdef DEBUG_PSD log_info("psd_image_data_size_max %lu\n", (long unsigned)psd_image_data_size_max); #endif while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size && file_recovery->calculated_file_size + 16 < file_recovery->file_size + buffer_size/2) { const unsigned int i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2; const unsigned int l=get_be32(buffer, i)+4; #ifdef DEBUG_PSD log_info("Color mode at 0x%lx\n", (long unsigned)(l + file_recovery->calculated_file_size)); #endif if(l<4) return DC_STOP; file_recovery->calculated_file_size+=l; file_recovery->data_check=&psd_skip_image_resources; return psd_skip_image_resources(buffer, buffer_size, file_recovery); } return DC_CONTINUE; }
static int header_check_ext2_sb(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) { const struct ext2_super_block *sb=(const struct ext2_super_block *)buffer; if(le16(sb->s_magic)!=EXT2_SUPER_MAGIC) return 0; if (le32(sb->s_free_blocks_count) >= le32(sb->s_blocks_count)) return 0; if (le32(sb->s_free_inodes_count) >= le32(sb->s_inodes_count)) return 0; if (le16(sb->s_errors)!=0 && (le16(sb->s_errors) != EXT2_ERRORS_CONTINUE) && (le16(sb->s_errors) != EXT2_ERRORS_RO) && (le16(sb->s_errors) != EXT2_ERRORS_PANIC)) return 0; if ((le16(sb->s_state) & ~(EXT2_VALID_FS | EXT2_ERROR_FS))!=0) return 0; if (le32(sb->s_blocks_count) == 0) /* reject empty filesystem */ return 0; if(le32(sb->s_log_block_size)>2) /* block size max = 4096, can be 8192 on alpha */ return 0; reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_ext2_sb.extension; return 1; }
static int header_check_fat(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) { const struct fat_boot_sector *fat_header=(const struct fat_boot_sector *)buffer; uint64_t start_fat1,start_data,part_size; unsigned long int no_of_cluster,fat_length,fat_length_calc; if(!(le16(fat_header->marker)==0xAA55 && (fat_header->ignored[0]==0xeb || fat_header->ignored[0]==0xe9) && (fat_header->fats==1 || fat_header->fats==2))) return 0; /* Obviously not a FAT */ if(!((fat_header->ignored[0]==0xeb && fat_header->ignored[2]==0x90)||fat_header->ignored[0]==0xe9)) return 0; if(fat_sector_size(fat_header)==0 || fat_sector_size(fat_header)%512!=0) return 0; switch(fat_header->sectors_per_cluster) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: break; default: return 0; } if(fat_header->fats!=1 && fat_header->fats!=2) return 0; if(fat_header->media!=0xF0 && fat_header->media<0xF8) return 0; fat_length=le16(fat_header->fat_length)>0?le16(fat_header->fat_length):le32(fat_header->fat32_length); part_size=(sectors(fat_header)>0?sectors(fat_header):le32(fat_header->total_sect)); start_fat1=le16(fat_header->reserved); start_data=start_fat1+fat_header->fats*fat_length+(get_dir_entries(fat_header)*32+fat_sector_size(fat_header)-1)/fat_sector_size(fat_header); no_of_cluster=(part_size-start_data)/fat_header->sectors_per_cluster; if(no_of_cluster<4085) { /* FAT12 */ if((get_dir_entries(fat_header)==0)||(get_dir_entries(fat_header)%16!=0)) return 0; if((le16(fat_header->fat_length)>256)||(le16(fat_header->fat_length)==0)) return 0; fat_length_calc=((no_of_cluster+2+fat_sector_size(fat_header)*2/3-1)*3/2/fat_sector_size(fat_header)); } else if(no_of_cluster<65525) { /* FAT16 */ if(le16(fat_header->fat_length)==0) return 0; if((get_dir_entries(fat_header)==0)||(get_dir_entries(fat_header)%16!=0)) return 0; fat_length_calc=((no_of_cluster+2+fat_sector_size(fat_header)/2-1)*2/fat_sector_size(fat_header)); } else { /* FAT32 */ if(sectors(fat_header)!=0) return 0; if(get_dir_entries(fat_header)!=0) return 0; if((le32(fat_header->root_cluster)<2) ||(le32(fat_header->root_cluster)>=2+no_of_cluster)) return 0; fat_length_calc=((no_of_cluster+2+fat_sector_size(fat_header)/4-1)*4/fat_sector_size(fat_header)); } if(fat_length<fat_length_calc) return 0; reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_fat.extension; file_recovery_new->calculated_file_size=(uint64_t) (sectors(fat_header)>0?sectors(fat_header):le32(fat_header->total_sect)) * fat_sector_size(fat_header); file_recovery_new->data_check=&data_check_size; file_recovery_new->file_check=&file_check_size; return 1; }
Sint16 File::read16le() { return le16(read<Sint16>()); }
// Load an ELF file and prepare it for flashing int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) { FILE *fd = NULL; Elf32_Ehdr ehdr; Elf32_Phdr *phdrs = NULL; int num_phdrs; int res; fd = fopen(name, "rb"); if (!fd) { fprintf(stderr, "Could not open file '%s': ", name); perror(NULL); goto fail; } fprintf(stderr, "Loading ELF file '%s'...\n", name); if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) { fprintf(stderr, "Error while reading ELF file header\n"); goto fail; } if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident)) || le32(ehdr.e_version) != 1) { fprintf(stderr, "Not an ELF file or wrong ELF type\n"); goto fail; } if (le16(ehdr.e_type) != ET_EXEC) { fprintf(stderr, "ELF is not executable\n"); goto fail; } if (le16(ehdr.e_machine) != EM_ARM) { fprintf(stderr, "Wrong ELF architecture\n"); goto fail; } if (!ehdr.e_phnum || !ehdr.e_phoff) { fprintf(stderr, "ELF has no PHDRs\n"); goto fail; } if (le16(ehdr.e_phentsize) != sizeof(Elf32_Phdr)) { // could be a structure padding issue... fprintf(stderr, "Either the ELF file or this code is made of fail\n"); goto fail; } num_phdrs = le16(ehdr.e_phnum); phdrs = malloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr)); if (!phdrs) { fprintf(stderr, "Out of memory\n"); goto fail; } if (fseek(fd, le32(ehdr.e_phoff), SEEK_SET) < 0) { fprintf(stderr, "Error while reading ELF PHDRs\n"); goto fail; } if (fread(phdrs, sizeof(Elf32_Phdr), num_phdrs, fd) != num_phdrs) { fprintf(stderr, "Error while reading ELF PHDRs\n"); goto fail; } res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs); if (res < 0) goto fail; res = check_segs(ctx, can_write_bl); if (res < 0) goto fail; free(phdrs); fclose(fd); ctx->filename = name; return 0; fail: if (phdrs) free(phdrs); if (fd) fclose(fd); flash_free(ctx); return -1; }
int main(int argc, char **argv) { struct FSE_ucode code, *ucode = &code; int i, size, reg, val, mask; u8 msg[5]; msg[0] = 0x05; msg[1] = 0x46; msg[2] = 0x36; msg[3] = 0x26; msg[4] = 0x16; /* create a script */ FSE_init(ucode); FSE_write(ucode, 0x12345678, 0xdeadbeef); FSE_write(ucode, 0x12345678, 0xef); FSE_wait(ucode, 0x12345678, 0x0f0f0f0f, 0xdeadbeef); FSE_mask(ucode, 0x12345678, 0x0f0f0f0f, 0xdeadbeef); FSE_delay_ns(ucode, 9999999); FSE_send_msg(ucode, 5, msg); FSE_fini(ucode); /* print the generated code */ printf("encoded program: ucode->len = %i bytes", ucode->len); for (i = 0; i < ucode->len; i++) { if (i % 16 == 0) printf("\n%08x: ", i); printf("%01x ", ucode->ptr.u08[i]); } printf("\n\n"); /* decode */ printf("decode program:\n"); i = 0; while (i < ucode->len) { u8 opcode = le8(ucode->ptr.u08, &i); printf("opcode = 0x%02x\n", opcode); switch (opcode) { case 0x00: printf("FSE_delay(0x%08x 0x%08x)\n",le32(ucode->ptr.u08, &i), le32(ucode->ptr.u08, &i)); break; case 0x01: printf("FSE_delay(0x%04x)\n",le16(ucode->ptr.u08, &i)); break; case 0x02: printf("FSE_delay_ns(0x%04x)\n",le16(ucode->ptr.u08, &i)); break; case 0x10: reg = le32(ucode->ptr.u08, &i); val = le32(ucode->ptr.u08, &i); printf("FSE_write(0x%08x, 0x%08x);\n", reg, val); break; case 0x11: reg = le32(ucode->ptr.u08, &i); val = le8(ucode->ptr.u08, &i); printf("FSE_write(0x%08x, 0x%02x);\n", reg, val); break; case 0x12: reg = le32(ucode->ptr.u08, &i); mask = le32(ucode->ptr.u08, &i); val = le32(ucode->ptr.u08, &i); printf("FSE_mask(0x%08x, 0x%08x, 0x%08x);\n",reg, mask, val); break; case 0x13: reg = le32(ucode->ptr.u08, &i); mask = le32(ucode->ptr.u08, &i); val = le32(ucode->ptr.u08, &i); printf("FSE_wait(0x%08x, 0x%08x, 0x%08x);\n", reg, mask, val); break; case 0x20: size = le16(ucode->ptr.u08, &i); printf("FSE_send_msg(%d", size); while(size) { printf(",0x%02x", le8(ucode->ptr.u08, &i)); size--; } printf(")\n"); break; case 0xff: printf("exit\n"); break; default: printf("unknown opcode %1x\n", opcode); break; } } return 0; }
unsigned int fat_get_cluster_from_entry(const struct msdos_dir_entry *entry) { return (((unsigned long int)le16(entry->starthi))<<16) | le16(entry->start); }
int ext2_gfun(disk_desc *d, g_module *m) { struct ext2fs_sb *sb, *sparesb; int psize, bsize = 1024; s64_t ls, ofs; dos_part_entry *pt = &m->m_part; byte_t *ubuf, *sbuf; m->m_guess = GM_NO; sb = (struct ext2fs_sb *)(d->d_sbuf + SUPERBLOCK_OFFSET); if (sb->s_magic != le16(EXT2_SUPER_MAGIC)) return (1); /* * first some plausability checks. */ if (sb->s_free_blocks_count >= sb->s_blocks_count) return (1); if (sb->s_free_inodes_count >= sb->s_inodes_count) return (1); if (sb->s_errors && (sb->s_errors != EXT2_ERRORS_CONTINUE) && (sb->s_errors != EXT2_ERRORS_RO) && (sb->s_errors != EXT2_ERRORS_PANIC)) return (1); if (sb->s_state & ~(EXT2_VALID_FS | EXT2_ERROR_FS)) return (1); /* * empty filesystems seem unlikely to me. */ if (sb->s_blocks_count == 0) return (1); /* * yet they also shouldn't be too large. */ if (d->d_nsecs) { ls = sb->s_blocks_count; ls *= bsize; ls /= d->d_ssize; ls += d->d_nsb; if (ls > d->d_nsecs) return (1); } /* * ext2fs supports 1024, 2048 and 4096b blocks. */ switch (sb->s_log_block_size) { case BSIZE_1024: bsize = 1024; break; case BSIZE_2048: bsize = 2048; break; case BSIZE_4096: bsize = 4096; break; default: return (1); } /* * current mount count shouldn't be greater than max+20 * but ext3 usually has s_max_mnt_count==-1 */ if ((sb->s_max_mnt_count != -1) && (sb->s_mnt_count > sb->s_max_mnt_count + 20)) return (1); /* * up to here this looks like a valid ext2 sb, now try to read * the first spare super block to be sure. */ if ((ls = l64tell(d->d_fd)) == -1) pr(FATAL, "ext2: cannot seek: %s", strerror(errno)); ls /= d->d_ssize; ls -= d->d_nsb; ls *= d->d_ssize; ofs = sb->s_blocks_per_group + sb->s_first_data_block; ofs *= bsize; if (l64seek(d->d_fd, ofs - ls, SEEK_CUR) == -1) pr(FATAL, "ext2: cannot seek: %s", strerror(errno)); psize = getpagesize(); ubuf = alloc(SUPERBLOCK_SIZE + psize); sbuf = align(ubuf, psize); if (read(d->d_fd, sbuf, SUPERBLOCK_SIZE) != SUPERBLOCK_SIZE) pr(FATAL, "ext2: cannot read spare super block"); sparesb = (struct ext2fs_sb *)sbuf; /* * test only some values of the spare sb. */ if (sparesb->s_magic != le16(EXT2_SUPER_MAGIC)) goto out; if (sparesb->s_log_block_size != sb->s_log_block_size) goto out; /* * seems ok. */ m->m_guess = GM_YES; pt->p_typ = 0x83; pt->p_start = d->d_nsb; pt->p_size = bsize / d->d_ssize; pt->p_size *= sb->s_blocks_count; out: free((void *)ubuf); return (1); }
static void file_rename_doc(const char *old_filename) { const char *ext=NULL; char *title=NULL; FILE *file; unsigned char buffer_header[512]; uint32_t *fat; const struct OLE_HDR *header=(const struct OLE_HDR*)&buffer_header; time_t file_time=0; unsigned int fat_entries; if(strstr(old_filename, ".sdd")!=NULL) ext="sdd"; if((file=fopen(old_filename, "rb"))==NULL) return; #ifdef DEBUG_OLE log_info("file_rename_doc(%s)\n", old_filename); #endif /*reads first sector including OLE header */ if(my_fseek(file, 0, SEEK_SET) < 0 || fread(&buffer_header, sizeof(buffer_header), 1, file) != 1) { fclose(file); return ; } /* Sanity check */ if(le32(header->num_FAT_blocks)==0 || le32(header->num_extra_FAT_blocks)>50 || le32(header->num_FAT_blocks)>109+le32(header->num_extra_FAT_blocks)*((1<<le16(header->uSectorShift))-1)) { fclose(file); return ; } if((fat=OLE_load_FAT(file, header))==NULL) { fclose(file); return ; } fat_entries=(le32(header->num_FAT_blocks)==0 ? 109: (le32(header->num_FAT_blocks)<<le16(header->uSectorShift))/4); { unsigned int ministream_block=0; unsigned int ministream_size=0; unsigned int block; unsigned int i; /* FFFFFFFE = ENDOFCHAIN * Use a loop count i to avoid endless loop */ #ifdef DEBUG_OLE log_info("file_rename_doc root_start_block=%u, fat_entries=%u\n", le32(header->root_start_block), fat_entries); #endif for(block=le32(header->root_start_block), i=0; block<fat_entries && block!=0xFFFFFFFE && i<fat_entries; block=le32(fat[block]), i++) { struct OLE_DIR *dir_entries; if(my_fseek(file, (1+block)<<le16(header->uSectorShift), SEEK_SET)<0) { free(fat); fclose(file); free(title); return ; } dir_entries=(struct OLE_DIR *)MALLOC(1<<le16(header->uSectorShift)); if(fread(dir_entries, 1<<le16(header->uSectorShift), 1, file)!=1) { free(fat); free(dir_entries); fclose(file); free(title); return ; } #ifdef DEBUG_OLE log_info("Root Directory block=%u (0x%x)\n", block, block); #endif { unsigned int sid; const struct OLE_DIR *dir_entry=dir_entries; if(i==0) { ministream_block=le32(dir_entry->start_block); ministream_size=le32(dir_entry->size); } for(sid=0, dir_entry=dir_entries; sid<(1<<le16(header->uSectorShift))/sizeof(struct OLE_DIR); sid++,dir_entry++) { if(dir_entry->type!=NO_ENTRY) { const char SummaryInformation[40]= { 0x05, '\0', 'S', '\0', 'u', '\0', 'm', '\0', 'm', '\0', 'a', '\0', 'r', '\0', 'y', '\0', 'I', '\0', 'n', '\0', 'f', '\0', 'o', '\0', 'r', '\0', 'm', '\0', 'a', '\0', 't', '\0', 'i', '\0', 'o', '\0', 'n', '\0', '\0', '\0' }; #ifdef DEBUG_OLE unsigned int j; for(j=0;j<64 && j<le16(dir_entry->namsiz) && dir_entry->name[j]!='\0';j+=2) { log_info("%c",dir_entry->name[j]); } log_info(" type %u", dir_entry->type); log_info(" Flags=%s", (dir_entry->bflags==0?"Red":"Black")); log_info(" sector %u (%u bytes)\n", (unsigned int)le32(dir_entry->start_block), (unsigned int)le32(dir_entry->size)); #endif switch(le16(dir_entry->namsiz)) { case 12: /* 3ds max */ if(memcmp(dir_entry->name, "S\0c\0e\0n\0e\0\0\0",12)==0) ext="max"; /* Licom AlphaCAM */ else if(memcmp(dir_entry->name,"L\0i\0c\0o\0m\0\0\0",12)==0) ext="amb"; break; case 16: if(sid==1 && memcmp(dir_entry->name, "d\0o\0c\0.\0d\0e\0t\0\0\0", 16)==0) ext="psmodel"; /* Windows Sticky Notes */ else if(sid==1 && memcmp(dir_entry->name, "V\0e\0r\0s\0i\0o\0n\0\0\0", 16)==0) ext="snt"; break; case 18: /* MS Excel * Note: Microsoft Works Spreadsheet contains the same signature */ if(ext==NULL && memcmp(dir_entry->name, "W\0o\0r\0k\0b\0o\0o\0k\0\0\0",18)==0) ext="xls"; /* Microsoft Works .wps */ else if(memcmp(dir_entry->name,"C\0O\0N\0T\0E\0N\0T\0S\0\0\0",18)==0) ext="wps"; break; case 20: /* Page Maker */ if(memcmp(&dir_entry->name, "P\0a\0g\0e\0M\0a\0k\0e\0r\0\0\0", 20)==0) ext="p65"; break; case 22: /* SigmaPlot .jnb */ if(memcmp(dir_entry->name, "J\0N\0B\0V\0e\0r\0s\0i\0o\0n\0\0", 22)==0) ext="jnb"; break; case 24: /* HP Photosmart Photo Printing Album */ if(memcmp(dir_entry->name,"I\0m\0a\0g\0e\0s\0S\0t\0o\0r\0e\0\0\0",24)==0) ext="albm"; break; case 28: /* Microsoft Works Spreadsheet or Chart */ if(memcmp(dir_entry->name,"W\0k\0s\0S\0S\0W\0o\0r\0k\0B\0o\0o\0k\0\0\0",28)==0) ext="xlr"; /* Visio */ else if(memcmp(dir_entry->name,"V\0i\0s\0i\0o\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0",28)==0) ext="vsd"; /* SolidWorks */ else if(memcmp(&dir_entry->name, "s\0w\0X\0m\0l\0C\0o\0n\0t\0e\0n\0t\0s\0\0\0", 28)==0) { #ifdef DJGPP ext="sld"; #else ext="sldprt"; #endif } break; case 32: if(memcmp(dir_entry->name, "m\0a\0n\0i\0f\0e\0s\0t\0.\0c\0a\0m\0x\0m\0l\0\0\0",32)==0) ext="camrec"; break; case 34: if(memcmp(dir_entry->name, "S\0t\0a\0r\0C\0a\0l\0c\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0",34)==0) ext="sdc"; break; case 36: /* sda=StarDraw, sdd=StarImpress */ if((ext==NULL || strcmp(ext,"sdd")!=0) && memcmp(dir_entry->name, "S\0t\0a\0r\0D\0r\0a\0w\0D\0o\0c\0u\0m\0e\0n\0t\0003\0\0\0", 36)==0) ext="sda"; else if(memcmp(dir_entry->name, "f\0i\0l\0e\0_\0C\0O\0M\0P\0A\0N\0Y\0_\0F\0I\0L\0E\0\0\0", 36)==0) ext="qbb"; break; case 38: /* Quattro Pro spreadsheet */ if(memcmp(dir_entry->name, "N\0a\0t\0i\0v\0e\0C\0o\0n\0t\0e\0n\0t\0_\0M\0A\0I\0N\0\0\0", 38)==0) ext="qpw"; else if(memcmp(dir_entry->name, "S\0t\0a\0r\0W\0r\0i\0t\0e\0r\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0", 38)==0) ext="sdw"; break; case 40: if(memcmp(dir_entry->name, SummaryInformation, 40)==0) { OLE_parse_summary(file, fat, fat_entries, header, ministream_block, ministream_size, le32(dir_entry->start_block), le32(dir_entry->size), &ext, &title, &file_time); } else if(memcmp(dir_entry->name,"P\0o\0w\0e\0r\0P\0o\0i\0n\0t\0 \0D\0o\0c\0u\0m\0e\0n\0t\0\0\0", 40)==0) ext="ppt"; /* Outlook */ else if(memcmp(dir_entry->name,"_\0_\0n\0a\0m\0e\0i\0d\0_\0v\0e\0r\0s\0i\0o\0n\0001\0.\0000\0\0\0",40)==0) ext="msg"; break; case 46: if(memcmp(dir_entry->name, "I\0S\0o\0l\0i\0d\0W\0o\0r\0k\0s\0I\0n\0f\0o\0r\0m\0a\0t\0i\0o\0n\0\0\0", 46)==0) { #ifdef DJGPP ext="sld"; #else ext="sldprt"; #endif } break; case 56: /* Wilcom ES Software */ if(memcmp(dir_entry->name, WilcomDesignInformationDDD, 56)==0) ext="emb"; break; } if(sid==1 && le16(dir_entry->namsiz) >=6 && memcmp(dir_entry->name, "D\0g\0n", 6)==0) ext="dgn"; #ifdef DEBUG_OLE if(ext!=NULL) log_info("Found %s %u\n", ext, le16(dir_entry->namsiz)); #endif } } } free(dir_entries); } } free(fat); fclose(file); if(file_time!=0 && file_time!=(time_t)-1) set_date(old_filename, file_time, file_time); if(title!=NULL) { file_rename(old_filename, (const unsigned char*)title, strlen(title), 0, ext, 1); free(title); } else file_rename(old_filename, NULL, 0, 0, ext, 1); }
static void file_check_doc(file_recovery_t *file_recovery) { unsigned char buffer_header[512]; uint64_t doc_file_size; uint32_t *fat; unsigned long int i; unsigned int freesect_count=0; const struct OLE_HDR *header=(const struct OLE_HDR*)&buffer_header; const uint64_t doc_file_size_org=file_recovery->file_size; file_recovery->file_size=0; /*reads first sector including OLE header */ if(my_fseek(file_recovery->handle, 0, SEEK_SET) < 0 || fread(&buffer_header, sizeof(buffer_header), 1, file_recovery->handle) != 1) return ; #ifdef DEBUG_OLE log_info("file_check_doc %s\n", file_recovery->filename); log_trace("sector size %u\n",1<<le16(header->uSectorShift)); log_trace("num_FAT_blocks %u\n",le32(header->num_FAT_blocks)); log_trace("num_extra_FAT_blocks %u\n",le32(header->num_extra_FAT_blocks)); #endif /* Sanity check */ if(le32(header->num_FAT_blocks)==0 || le32(header->num_extra_FAT_blocks)>50 || le32(header->num_FAT_blocks)>109+le32(header->num_extra_FAT_blocks)*((1<<le16(header->uSectorShift))-1)) return ; if((fat=OLE_load_FAT(file_recovery->handle, header))==NULL) { #ifdef DEBUG_OLE log_info("OLE_load_FAT failed\n"); #endif return ; } /* Search how many entries are not used at the end of the FAT */ for(i=(le32(header->num_FAT_blocks)<<le16(header->uSectorShift))/4-1; i>0 && le32(fat[i])==0xFFFFFFFF; i--) freesect_count++; doc_file_size=((1+(le32(header->num_FAT_blocks)<<le16(header->uSectorShift))/4-freesect_count)<<le16(header->uSectorShift)); if(doc_file_size > doc_file_size_org) { #ifdef DEBUG_OLE log_info("doc_file_size=(1+(%u<<%u)/4-%u)<<%u\n", le32(header->num_FAT_blocks), le16(header->uSectorShift), freesect_count, le16(header->uSectorShift)); log_info("doc_file_size %llu > doc_file_size_org %llu\n", (unsigned long long)doc_file_size, (unsigned long long)doc_file_size_org); #endif free(fat); return ; } #ifdef DEBUG_OLE log_trace("==> size : %llu\n", (long long unsigned)doc_file_size); #endif { unsigned int block; const unsigned int fat_entries=(le32(header->num_FAT_blocks)==0 ? 109: (le32(header->num_FAT_blocks)<<le16(header->uSectorShift))/4); #ifdef DEBUG_OLE log_info("root_start_block=%u, fat_entries=%u\n", le32(header->root_start_block), fat_entries); #endif /* FFFFFFFE = ENDOFCHAIN * Use a loop count i to avoid endless loop */ for(block=le32(header->root_start_block), i=0; block!=0xFFFFFFFE && i<fat_entries; block=le32(fat[block]), i++) { struct OLE_DIR *dir_entries; #ifdef DEBUG_OLE log_info("read block %u\n", block); #endif if(!(block < fat_entries)) { free(fat); return ; } if(my_fseek(file_recovery->handle, (1+block)<<le16(header->uSectorShift), SEEK_SET)<0) { #ifdef DEBUG_OLE log_info("fseek failed\n"); #endif free(fat); return ; } dir_entries=(struct OLE_DIR *)MALLOC(1<<le16(header->uSectorShift)); if(fread(dir_entries, (1<<le16(header->uSectorShift)), 1, file_recovery->handle)!=1) { #ifdef DEBUG_OLE log_info("fread failed\n"); #endif free(dir_entries); free(fat); return ; } { unsigned int sid; struct OLE_DIR *dir_entry; for(sid=0, dir_entry=dir_entries; sid<(1<<le16(header->uSectorShift))/sizeof(struct OLE_DIR) && dir_entry->type!=NO_ENTRY; sid++,dir_entry++) { if(le32(dir_entry->start_block) > 0 && le32(dir_entry->size) > 0 && ((le32(dir_entry->size) >= le32(header->miniSectorCutoff) && le32(dir_entry->start_block) > fat_entries) || le32(dir_entry->size) > doc_file_size)) { #ifdef DEBUG_OLE log_info("error at sid %u\n", sid); #endif free(dir_entries); free(fat); return ; } } } free(dir_entries); } } free(fat); file_recovery->file_size=doc_file_size; }
static int header_check_doc(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) { const struct OLE_HDR *header=(const struct OLE_HDR *)buffer; if(memcmp(buffer,doc_header,sizeof(doc_header))!=0) return 0; /* Check for Little Endian */ if(le16(header->uByteOrder)!=0xFFFE) return 0; if(le16(header->uDllVersion)!=3 && le16(header->uDllVersion)!=4) return 0; if(le16(header->reserved)!=0 || le32(header->reserved1)!=0) return 0; if(le16(header->uMiniSectorShift)!=6) return 0; if(le16(header->uDllVersion)==3 && le16(header->uSectorShift)!=9) return 0; /* max and qbb file have uSectorShift=12 */ if(le16(header->uDllVersion)==4 && le16(header->uSectorShift)!=12) return 0; if(le16(header->uDllVersion)==3 && le32(header->csectDir)!=0) return 0; /* max file have csectDir=1 * qbb file have csectDir=4 */ if(le16(header->uDllVersion)==4 && le32(header->csectDir)==0) return 0; /* num_FAT_blocks=109+num_extra_FAT_blocks*(512-1); maximum file size is 512+(num_FAT_blocks*128)*512, about 1.6GB */ if(le32(header->num_FAT_blocks)==0 || le32(header->num_extra_FAT_blocks)>50 || le32(header->num_FAT_blocks)>109+le32(header->num_extra_FAT_blocks)*((1<<le16(header->uSectorShift))-1)) return 0; reset_file_recovery(file_recovery_new); file_recovery_new->file_check=&file_check_doc; file_recovery_new->file_rename=&file_rename_doc; file_recovery_new->extension=ole_get_file_extension(buffer, buffer_size); if(file_recovery_new->extension!=NULL) { if(strcmp(file_recovery_new->extension,"sda")==0) { if(td_memmem(buffer,buffer_size,"StarImpress",11)!=NULL) file_recovery_new->extension="sdd"; } else if(strcmp(file_recovery_new->extension,"wps")==0) { /* Distinguish between MS Works .wps and MS Publisher .pub */ if(td_memmem(buffer,buffer_size,"Microsoft Publisher",19)!=NULL) file_recovery_new->extension="pub"; } return 1; } if(td_memmem(buffer,buffer_size,"WordDocument",12)!=NULL) { file_recovery_new->extension="doc"; } else if(td_memmem(buffer,buffer_size,"StarDraw",8)!=NULL) { file_recovery_new->extension="sda"; } else if(td_memmem(buffer,buffer_size,"StarCalc",8)!=NULL) { file_recovery_new->extension="sdc"; } else if(td_memmem(buffer,buffer_size,"StarImpress",11)!=NULL) { file_recovery_new->extension="sdd"; } else if(td_memmem(buffer,buffer_size,"Worksheet",9)!=NULL || td_memmem(buffer,buffer_size,"Book",4)!=NULL || td_memmem(buffer,buffer_size,"Workbook",8)!=NULL || td_memmem(buffer,buffer_size,"Calc",4)!=NULL) { file_recovery_new->extension="xls"; } else if(td_memmem(buffer,buffer_size,"Power",5)!=NULL) { file_recovery_new->extension="ppt"; } else if(td_memmem(buffer,buffer_size,"AccessObjSiteData",17)!=NULL) { file_recovery_new->extension="mdb"; } else if(td_memmem(buffer,buffer_size,"Visio",5)!=NULL) { file_recovery_new->extension="vsd"; } else if(td_memmem(buffer,buffer_size,"SfxDocument",11)!=NULL) { file_recovery_new->extension="sdw"; } else if(td_memmem(buffer,buffer_size,"CPicPage",8)!=NULL) { /* Flash Project File */ file_recovery_new->extension="fla"; } else if(td_memmem(buffer,buffer_size,"Microsoft Publisher",19)!=NULL) { /* Publisher */ file_recovery_new->extension="pub"; } else if(td_memmem(buffer, buffer_size, "Microsoft Works Database", 24)!=NULL || td_memmem( buffer, buffer_size, "MSWorksDBDoc", 12)!=NULL) { /* Microsoft Works .wdb */ file_recovery_new->extension="wdb"; } else if(td_memmem(buffer,buffer_size,"MetaStock",9)!=NULL) { /* MetaStock */ file_recovery_new->extension="mws"; } else file_recovery_new->extension=file_hint_doc.extension; return 1; }
static const char *ole_get_file_extension(const unsigned char *buffer, const unsigned int buffer_size) { const struct OLE_HDR *header=(const struct OLE_HDR *)buffer; const uint32_t *fat; unsigned int fat_entries; unsigned int block; unsigned int i; if(buffer_size<512) return NULL; if(le32(header->num_FAT_blocks)==0) { fat=(const uint32_t *)(header+1); fat_entries=109; } else { const uint32_t *fati=(const uint32_t *)(header+1); const unsigned int fat_offset=(1+le32(fati[0])) << le16(header->uSectorShift); fat=(const uint32_t *)&buffer[fat_offset]; fat_entries=(le32(header->num_FAT_blocks) << le16(header->uSectorShift))/4; if(fat_offset>buffer_size) fat_entries=0; else if(fat_offset+fat_entries>buffer_size) fat_entries=buffer_size-fat_offset; } /* FFFFFFFE = ENDOFCHAIN * Use a loop count i to avoid endless loop */ #ifdef DEBUG_OLE log_info("ole_get_file_extension root_start_block=%u, fat_entries=%u\n", le32(header->root_start_block), fat_entries); #endif for(block=le32(header->root_start_block), i=0; block<fat_entries && block!=0xFFFFFFFE && i<fat_entries; block=le32(fat[block]), i++) { const unsigned int offset_root_dir=(1+block)<<le16(header->uSectorShift); #ifdef DEBUG_OLE log_info("Root Directory block=%u (0x%x)\n", block, block); #endif if(offset_root_dir>buffer_size-512) return NULL; { unsigned int sid; const struct OLE_DIR *dir_entry; const char *ext=NULL; int is_db=0; for(sid=0,dir_entry=(const struct OLE_DIR *)&buffer[offset_root_dir]; sid<512/sizeof(struct OLE_DIR) && dir_entry->type!=NO_ENTRY; sid++,dir_entry++) { #ifdef DEBUG_OLE unsigned int j; for(j=0;j<64 && j<le16(dir_entry->namsiz) && dir_entry->name[j]!='\0';j+=2) { log_info("%c",dir_entry->name[j]); } for(;j<64;j+=2) log_info(" "); log_info(" type %u", dir_entry->type); log_info(" Flags=%s", (dir_entry->bflags==0?"Red ":"Black")); log_info(" sector %u (%u bytes)\n", (unsigned int)le32(dir_entry->start_block), (unsigned int)le32(dir_entry->size)); #endif if(sid==1 && memcmp(&dir_entry->name, "1\0\0\0", 4)==0) is_db++; else if(sid==2 && (memcmp(&dir_entry->name, "2\0\0\0", 4)==0 || memcmp(&dir_entry->name, "C\0a\0t\0a\0l\0o\0g\0", 14)==0)) is_db++; switch(le16(dir_entry->namsiz)) { case 12: /* 3ds max */ if(memcmp(dir_entry->name, "S\0c\0e\0n\0e\0\0\0",12)==0) return "max"; /* Licom AlphaCAM */ else if(memcmp(dir_entry->name,"L\0i\0c\0o\0m\0\0\0",12)==0) return "amb"; break; case 18: /* MS Excel * Note: Microsoft Works Spreadsheet contains the same signature */ if(memcmp(dir_entry->name, "W\0o\0r\0k\0b\0o\0o\0k\0\0\0",18)==0) ext="xls"; /* Microsoft Works .wps */ else if(memcmp(dir_entry->name,"C\0O\0N\0T\0E\0N\0T\0S\0\0\0",18)==0) return "wps"; break; case 20: /* Page Maker */ if(memcmp(&dir_entry->name, "P\0a\0g\0e\0M\0a\0k\0e\0r\0\0\0", 20)==0) return "p65"; break; case 22: /* SigmaPlot .jnb */ if(memcmp(dir_entry->name, "J\0N\0B\0V\0e\0r\0s\0i\0o\0n\0\0", 22)==0) return "jnb"; break; case 24: /* HP Photosmart Photo Printing Album */ if(memcmp(dir_entry->name,"I\0m\0a\0g\0e\0s\0S\0t\0o\0r\0e\0\0\0",24)==0) return "albm"; break; case 28: /* Microsoft Works Spreadsheet or Chart */ if(memcmp(dir_entry->name,"W\0k\0s\0S\0S\0W\0o\0r\0k\0B\0o\0o\0k\0\0\0",28)==0) return "xlr"; /* Visio */ else if(memcmp(dir_entry->name,"V\0i\0s\0i\0o\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0",28)==0) return "vsd"; /* SolidWorks */ else if(memcmp(&dir_entry->name,"s\0w\0X\0m\0l\0C\0o\0n\0t\0e\0n\0t\0s\0\0\0",28)==0) { #ifdef DJGPP return "sld"; #else return "sldprt"; #endif } break; case 34: if(memcmp(dir_entry->name, "S\0t\0a\0r\0C\0a\0l\0c\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0",34)==0) return "sdc"; break; case 36: if(memcmp(dir_entry->name, "S\0t\0a\0r\0D\0r\0a\0w\0D\0o\0c\0u\0m\0e\0n\0t\0003\0\0\0", 36)==0) return "sda"; break; case 38: /* Quattro Pro spreadsheet */ if(memcmp(dir_entry->name, "N\0a\0t\0i\0v\0e\0C\0o\0n\0t\0e\0n\0t\0_\0M\0A\0I\0N\0\0\0", 38)==0) return "qpw"; else if(memcmp(dir_entry->name, "S\0t\0a\0r\0W\0r\0i\0t\0e\0r\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0", 38)==0) return "sdw"; break; case 40: if(memcmp(dir_entry->name,"P\0o\0w\0e\0r\0P\0o\0i\0n\0t\0 \0D\0o\0c\0u\0m\0e\0n\0t\0\0\0", 40)==0) return "ppt"; /* Outlook */ else if(memcmp(dir_entry->name,"_\0_\0n\0a\0m\0e\0i\0d\0_\0v\0e\0r\0s\0i\0o\0n\0001\0.\0000\0\0\0",40)==0) return "msg"; break; case 46: if(memcmp(dir_entry->name, "I\0S\0o\0l\0i\0d\0W\0o\0r\0k\0s\0I\0n\0f\0o\0r\0m\0a\0t\0i\0o\0n\0\0\0", 46)==0) { #ifdef DJGPP return "sld"; #else return "sldprt"; #endif } break; case 56: /* Wilcom ES Software */ if(memcmp(dir_entry->name, WilcomDesignInformationDDD, 56)==0) return "emb"; break; } if(sid==1 && memcmp(&dir_entry->name, "D\0g\0n", 6)==0) return "dgn"; } if(ext!=NULL) return ext; /* Thumbs.db */ if(is_db==2) return "db"; } } #ifdef DEBUG_OLE log_info("Root Directory end\n"); #endif return NULL; }
void ldpe(Biobuf *f, char *pkg, int64 len, char *pn) { char *name; int32 base; int i, j, l, numaux; PeObj *obj; PeSect *sect, *rsect; IMAGE_SECTION_HEADER sh; uchar symbuf[18]; Sym *s; Reloc *r, *rp; PeSym *sym; USED(len); USED(pkg); if(debug['v']) Bprint(&bso, "%5.2f ldpe %s\n", cputime(), pn); sect = nil; version++; base = Boffset(f); obj = mal(sizeof *obj); obj->f = f; obj->base = base; obj->name = pn; // read header if(Bread(f, &obj->fh, sizeof obj->fh) != sizeof obj->fh) goto bad; // load section list obj->sect = mal(obj->fh.NumberOfSections*sizeof obj->sect[0]); obj->nsect = obj->fh.NumberOfSections; for(i=0; i < obj->fh.NumberOfSections; i++) { if(Bread(f, &obj->sect[i].sh, sizeof sh) != sizeof sh) goto bad; obj->sect[i].size = obj->sect[i].sh.SizeOfRawData; obj->sect[i].name = (char*)obj->sect[i].sh.Name; // TODO return error if found .cormeta } // load string table Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0); if(Bread(f, &l, sizeof l) != sizeof l) goto bad; obj->snames = mal(l); Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0); if(Bread(f, obj->snames, l) != l) goto bad; // read symbols obj->pesym = mal(obj->fh.NumberOfSymbols*sizeof obj->pesym[0]); obj->npesym = obj->fh.NumberOfSymbols; Bseek(f, base+obj->fh.PointerToSymbolTable, 0); for(i=0; i<obj->fh.NumberOfSymbols; i+=numaux+1) { Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*i, 0); if(Bread(f, symbuf, sizeof symbuf) != sizeof symbuf) goto bad; if((symbuf[0] == 0) && (symbuf[1] == 0) && (symbuf[2] == 0) && (symbuf[3] == 0)) { l = le32(&symbuf[4]); obj->pesym[i].name = (char*)&obj->snames[l]; } else { // sym name length <= 8 obj->pesym[i].name = mal(9); strncpy(obj->pesym[i].name, (char*)symbuf, 8); obj->pesym[i].name[8] = 0; } obj->pesym[i].value = le32(&symbuf[8]); obj->pesym[i].sectnum = le16(&symbuf[12]); obj->pesym[i].sclass = symbuf[16]; obj->pesym[i].aux = symbuf[17]; obj->pesym[i].type = le16(&symbuf[14]); numaux = obj->pesym[i].aux; if (numaux < 0) numaux = 0; } // create symbols for mapped sections for(i=0; i<obj->nsect; i++) { sect = &obj->sect[i]; if(sect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE) continue; if(map(obj, sect) < 0) goto bad; name = smprint("%s(%s)", pn, sect->name); s = lookup(name, version); free(name); switch(sect->sh.Characteristics&(IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_CNT_INITIALIZED_DATA| IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE)) { case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ: //.rdata s->type = SRODATA; break; case IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.bss s->type = SBSS; break; case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.data s->type = SDATA; break; case IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ: //.text s->type = STEXT; break; default: werrstr("unexpected flags for PE section %s", sect->name); goto bad; } s->p = sect->base; s->np = sect->size; s->size = sect->size; if(s->type == STEXT) { if(etextp) etextp->next = s; else textp = s; etextp = s; } sect->sym = s; if(strcmp(sect->name, ".rsrc") == 0) setpersrc(sect->sym); } // load relocations for(i=0; i<obj->nsect; i++) { rsect = &obj->sect[i]; if(rsect->sym == 0 || rsect->sh.NumberOfRelocations == 0) continue; if(rsect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE) continue; r = mal(rsect->sh.NumberOfRelocations*sizeof r[0]); Bseek(f, obj->base+rsect->sh.PointerToRelocations, 0); for(j=0; j<rsect->sh.NumberOfRelocations; j++) { rp = &r[j]; if(Bread(f, symbuf, 10) != 10) goto bad; uint32 rva, symindex; uint16 type; rva = le32(&symbuf[0]); symindex = le32(&symbuf[4]); type = le16(&symbuf[8]); if(readsym(obj, symindex, &sym) < 0) goto bad; if(sym->sym == nil) { werrstr("reloc of invalid sym %s idx=%d type=%d", sym->name, symindex, sym->type); goto bad; } rp->sym = sym->sym; rp->siz = 4; rp->off = rva; switch(type) { default: diag("%s: unknown relocation type %d;", pn, type); case IMAGE_REL_I386_REL32: case IMAGE_REL_AMD64_REL32: case IMAGE_REL_AMD64_ADDR32: // R_X86_64_PC32 case IMAGE_REL_AMD64_ADDR32NB: rp->type = D_PCREL; rp->add = le32(rsect->base+rp->off); break; case IMAGE_REL_I386_DIR32NB: case IMAGE_REL_I386_DIR32: rp->type = D_ADDR; // load addend from image rp->add = le32(rsect->base+rp->off); break; case IMAGE_REL_AMD64_ADDR64: // R_X86_64_64 rp->siz = 8; rp->type = D_ADDR; // load addend from image rp->add = le64(rsect->base+rp->off); break; } } qsort(r, rsect->sh.NumberOfRelocations, sizeof r[0], rbyoff); s = rsect->sym; s->r = r; s->nr = rsect->sh.NumberOfRelocations; } // enter sub-symbols into symbol table. for(i=0; i<obj->npesym; i++) { if(obj->pesym[i].name == 0) continue; if(obj->pesym[i].name[0] == '.') //skip section continue; if(obj->pesym[i].sectnum > 0) { sect = &obj->sect[obj->pesym[i].sectnum-1]; if(sect->sym == 0) continue; } if(readsym(obj, i, &sym) < 0) goto bad; s = sym->sym; if(sym->sectnum == 0) {// extern if(s->type == SDYNIMPORT) s->plt = -2; // flag for dynimport in PE object files. if (s->type == SXREF && sym->value > 0) {// global data s->type = SDATA; s->size = sym->value; } continue; } else if (sym->sectnum > 0) { sect = &obj->sect[sym->sectnum-1]; if(sect->sym == 0) diag("%s: %s sym == 0!", pn, s->name); } else { diag("%s: %s sectnum < 0!", pn, s->name); } if(sect == nil) return; s->sub = sect->sym->sub; sect->sym->sub = s; s->type = sect->sym->type | SSUB; s->value = sym->value; s->size = 4; s->outer = sect->sym; if(sect->sym->type == STEXT) { Prog *p; if(s->text != P) diag("%s: duplicate definition of %s", pn, s->name); // build a TEXT instruction with a unique pc // just to make the rest of the linker happy. p = prg(); p->as = ATEXT; p->from.type = D_EXTERN; p->from.sym = s; p->textflag = 7; p->to.type = D_CONST; p->link = nil; p->pc = pc++; s->text = p; etextp->next = s; etextp = s; } } return; bad: diag("%s: malformed pe file: %r", pn); }