PhotoRec: recover Camtasia Studio .camrec file

This commit is contained in:
Christophe Grenier 2014-02-02 15:21:05 +01:00
parent d4ad151788
commit 5b0b6e820b

View file

@ -89,6 +89,7 @@ static void file_check_doc(file_recovery_t *file_recovery)
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
@ -109,11 +110,11 @@ static void file_check_doc(file_recovery_t *file_recovery)
i>0 && le32(fat[i])==0xFFFFFFFF;
i--)
freesect_count++;
doc_file_size=512+(((le32(header->num_FAT_blocks)<<le16(header->uSectorShift))/4-freesect_count)<<le16(header->uSectorShift));
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=512+((%u<<%u)/4-%u)<<%u\n",
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",
@ -148,7 +149,7 @@ static void file_check_doc(file_recovery_t *file_recovery)
free(fat);
return ;
}
if(fseek(file_recovery->handle, 512+(block<<le16(header->uSectorShift)), SEEK_SET)<0)
if(fseek(file_recovery->handle, (1+block)<<le16(header->uSectorShift), SEEK_SET)<0)
{
#ifdef DEBUG_OLE
log_info("fseek failed\n");
@ -211,7 +212,7 @@ static const char *ole_get_file_extension(const unsigned char *buffer, const uns
else
{
const uint32_t *fati=(const uint32_t *)(header+1);
const unsigned int fat_offset=(le32(fati[0]) << le16(header->uSectorShift))+512;
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)
@ -228,7 +229,7 @@ static const char *ole_get_file_extension(const unsigned char *buffer, const uns
block<fat_entries && block!=0xFFFFFFFE && i<fat_entries;
block=le32(fat[block]), i++)
{
const unsigned int offset_root_dir=512+(block<<le16(header->uSectorShift));
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
@ -370,110 +371,115 @@ static const char *ole_get_file_extension(const unsigned char *buffer, const uns
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)
{
if(memcmp(buffer,doc_header,sizeof(doc_header))==0)
{
const struct OLE_HDR *header=(const struct OLE_HDR *)buffer;
if(le16(header->reserved)!=0 || le32(header->reserved1)!=0)
return 0;
if(le16(header->uMiniSectorShift)!=6)
return 0;
/* max and qbb file have uSectorShift=12 */
if(le16(header->uSectorShift)!=9 && le16(header->uSectorShift)!=12)
return 0;
if(le16(header->uSectorShift)==9 && le32(header->csectDir)!=0)
return 0;
/* max file have csectDir=1
* qbb file have csectDir=4 */
if(le16(header->uSectorShift)==12 && 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
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(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(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,"StarImpress",11)!=NULL)
file_recovery_new->extension="sdd";
}
if(td_memmem(buffer,buffer_size,"WordDocument",12)!=NULL)
else if(strcmp(file_recovery_new->extension,"wps")==0)
{
file_recovery_new->extension="doc";
/* Distinguish between MS Works .wps and MS Publisher .pub */
if(td_memmem(buffer,buffer_size,"Microsoft Publisher",19)!=NULL)
file_recovery_new->extension="pub";
}
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;
}
return 0;
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 uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header)
@ -491,7 +497,7 @@ static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header)
i<le32(header->num_extra_FAT_blocks) && block!=0xFFFFFFFF && block!=0xFFFFFFFE;
i++, block=le32(dif[109+i*(((1<<le16(header->uSectorShift))/4)-1)]))
{
if(fseek(IN, 512+(block<<le16(header->uSectorShift)), SEEK_SET) < 0)
if(fseek(IN, (1+block)<<le16(header->uSectorShift), SEEK_SET) < 0)
{
free(dif);
return NULL;
@ -512,7 +518,7 @@ static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header)
j<le32(header->num_FAT_blocks);
j++, data+=(1<<le16(header->uSectorShift)))
{
if(fseek(IN,512+(le32(dif[j])<<le16(header->uSectorShift)),SEEK_SET)<0)
if(fseek(IN, (1+le32(dif[j]))<<le16(header->uSectorShift), SEEK_SET)<0)
{
free(dif);
free(fat);
@ -547,7 +553,7 @@ static void *OLE_read_stream(FILE *IN,
free(dataPt);
return NULL;
}
if(fseek(IN, 512+(block<<uSectorShift), SEEK_SET)<0)
if(fseek(IN, (1+block)<<uSectorShift, SEEK_SET)<0)
{
free(dataPt);
return NULL;
@ -574,7 +580,7 @@ static uint32_t *OLE_load_MiniFAT(FILE *IN, const struct OLE_HDR *header, const
block=le32(header->MiniFat_block);
for(i=0; i < le32(header->csectMiniFat) && block < fat_entries; i++)
{
if(fseek(IN, ((uint64_t)block << le16(header->uSectorShift)) + 512, SEEK_SET) < 0)
if(fseek(IN, ((uint64_t)1+block) << le16(header->uSectorShift), SEEK_SET) < 0)
{
free(minifat);
return NULL;
@ -848,15 +854,6 @@ static void file_rename_doc(const char *old_filename)
fclose(file);
return ;
}
if(le16(header->uSectorShift)==12)
{
fclose(file);
if(le32(header->csectDir)==1)
file_rename(old_filename, NULL, 0, 0, "max", 1);
else
file_rename(old_filename, NULL, 0, 0, "qbb", 1);
return ;
}
if((fat=OLE_load_FAT(file, header))==NULL)
{
fclose(file);
@ -880,7 +877,7 @@ static void file_rename_doc(const char *old_filename)
block=le32(fat[block]), i++)
{
struct OLE_DIR *dir_entries;
if(fseek(file, 512+(block<<le16(header->uSectorShift)), SEEK_SET)<0)
if(fseek(file, (1+block)<<le16(header->uSectorShift), SEEK_SET)<0)
{
free(fat);
fclose(file);
@ -888,7 +885,7 @@ static void file_rename_doc(const char *old_filename)
return ;
}
dir_entries=(struct OLE_DIR *)MALLOC(1<<le16(header->uSectorShift));
if(fread(dir_entries, (1<<le16(header->uSectorShift)), 1, file)!=1)
if(fread(dir_entries, 1<<le16(header->uSectorShift), 1, file)!=1)
{
free(fat);
free(dir_entries);
@ -993,6 +990,10 @@ static void file_rename_doc(const char *old_filename)
#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";
@ -1002,6 +1003,8 @@ static void file_rename_doc(const char *old_filename)
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 */