PhotoRec: avoid potential integer overflow while parsing exe files
This commit is contained in:
parent
94fa96ce3f
commit
0ae3da4161
1 changed files with 91 additions and 90 deletions
181
src/file_exe.c
181
src/file_exe.c
|
@ -37,7 +37,6 @@
|
|||
#include "log.h"
|
||||
|
||||
static void register_header_check_exe(file_stat_t *file_stat);
|
||||
static int header_check_exe(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);
|
||||
static void file_rename_pe_exe(file_recovery_t *file_recovery);
|
||||
|
||||
const file_hint_t file_hint_exe= {
|
||||
|
@ -51,122 +50,119 @@ const file_hint_t file_hint_exe= {
|
|||
|
||||
static const unsigned char exe_header[2] = {'M','Z'};
|
||||
|
||||
static void register_header_check_exe(file_stat_t *file_stat)
|
||||
{
|
||||
register_header_check(0, exe_header,sizeof(exe_header), &header_check_exe, file_stat);
|
||||
}
|
||||
|
||||
static int header_check_exe(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 dos_image_file_hdr *dos_hdr=(const struct dos_image_file_hdr*)buffer;
|
||||
const struct pe_image_file_hdr *pe_hdr;
|
||||
if(memcmp(buffer,exe_header,sizeof(exe_header))!=0)
|
||||
return 0;
|
||||
pe_hdr=(const struct pe_image_file_hdr *)(buffer+le32(dos_hdr->e_lfanew));
|
||||
if(le32(dos_hdr->e_lfanew)>0 &&
|
||||
le32(dos_hdr->e_lfanew) <= buffer_size-sizeof(struct pe_image_file_hdr) &&
|
||||
(le32(pe_hdr->Magic) & 0xffff) == IMAGE_WIN16_SIGNATURE)
|
||||
le32(dos_hdr->e_lfanew) <= buffer_size-sizeof(struct pe_image_file_hdr))
|
||||
{
|
||||
/* NE Win16 */
|
||||
reset_file_recovery(file_recovery_new);
|
||||
file_recovery_new->extension=file_hint_exe.extension;
|
||||
return 1;
|
||||
}
|
||||
if(le32(dos_hdr->e_lfanew)>0 &&
|
||||
le32(dos_hdr->e_lfanew) <= buffer_size-sizeof(struct pe_image_file_hdr) &&
|
||||
(le32(pe_hdr->Magic) & 0xffff) == IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
/* Windows PE */
|
||||
if(le16(pe_hdr->Characteristics) & 0x2000)
|
||||
{
|
||||
/* Dynamic Link Library */
|
||||
reset_file_recovery(file_recovery_new);
|
||||
file_recovery_new->extension="dll";
|
||||
}
|
||||
else if(le16(pe_hdr->Characteristics) & 0x02)
|
||||
const struct pe_image_file_hdr *pe_hdr=(const struct pe_image_file_hdr *)(buffer+le32(dos_hdr->e_lfanew));
|
||||
if((le32(pe_hdr->Magic) & 0xffff) == IMAGE_WIN16_SIGNATURE)
|
||||
{
|
||||
/* NE Win16 */
|
||||
reset_file_recovery(file_recovery_new);
|
||||
file_recovery_new->extension=file_hint_exe.extension;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
if((le32(pe_hdr->Magic) & 0xffff) == IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
#ifdef DEBUG_EXE
|
||||
log_warning("EXE rejected, bad characteristics %02x\n", le16(pe_hdr->Characteristics));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
file_recovery_new->time=le32(pe_hdr->TimeDateStamp);
|
||||
#ifdef DEBUG_EXE
|
||||
{
|
||||
const struct pe_image_optional_hdr32 *pe_image_optional32=(const struct pe_image_optional_hdr32 *)
|
||||
(((const unsigned char*)pe_hdr + sizeof(struct pe_image_file_hdr)));
|
||||
if(le16(pe_image_optional32->Magic)==IMAGE_NT_OPTIONAL_HDR_MAGIC)
|
||||
/* Windows PE */
|
||||
if(le16(pe_hdr->Characteristics) & 0x2000)
|
||||
{
|
||||
log_debug("SizeOfCode %lx\n", (long unsigned)le32(pe_image_optional32->SizeOfCode));
|
||||
log_debug("SizeOfImage %lx\n", (long unsigned)le32(pe_image_optional32->SizeOfImage));
|
||||
/* Dynamic Link Library */
|
||||
reset_file_recovery(file_recovery_new);
|
||||
file_recovery_new->extension="dll";
|
||||
}
|
||||
else if(le16(pe_image_optional32->Magic)==IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||
else if(le16(pe_hdr->Characteristics) & 0x02)
|
||||
{
|
||||
const struct pe_image_optional_hdr64 *pe_image_optional64=(const struct pe_image_optional_hdr64 *)
|
||||
reset_file_recovery(file_recovery_new);
|
||||
file_recovery_new->extension=file_hint_exe.extension;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_EXE
|
||||
log_warning("EXE rejected, bad characteristics %02x\n", le16(pe_hdr->Characteristics));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
file_recovery_new->time=le32(pe_hdr->TimeDateStamp);
|
||||
#ifdef DEBUG_EXE
|
||||
{
|
||||
const struct pe_image_optional_hdr32 *pe_image_optional32=(const struct pe_image_optional_hdr32 *)
|
||||
(((const unsigned char*)pe_hdr + sizeof(struct pe_image_file_hdr)));
|
||||
}
|
||||
log_debug("PE image opt 0x%lx-0x%lx\n", (long unsigned)sizeof(struct pe_image_file_hdr),
|
||||
(long unsigned)(sizeof(struct pe_image_file_hdr) + le16(pe_hdr->SizeOfOptionalHeader) - 1));
|
||||
}
|
||||
#endif
|
||||
{
|
||||
unsigned int i;
|
||||
uint64_t sum=0;
|
||||
const struct pe_image_section_hdr *pe_image_section=(const struct pe_image_section_hdr*)
|
||||
((const unsigned char*)pe_hdr + sizeof(struct pe_image_file_hdr) + le16(pe_hdr->SizeOfOptionalHeader));
|
||||
for(i=0;
|
||||
i<le16(pe_hdr->NumberOfSections) &&
|
||||
(const unsigned char*)(pe_image_section+1) <= buffer+buffer_size;
|
||||
i++,pe_image_section++)
|
||||
{
|
||||
if(le32(pe_image_section->SizeOfRawData)>0)
|
||||
if(le16(pe_image_optional32->Magic)==IMAGE_NT_OPTIONAL_HDR_MAGIC)
|
||||
{
|
||||
#ifdef DEBUG_EXE
|
||||
log_debug("%s 0x%lx-0x%lx\n", pe_image_section->Name,
|
||||
(unsigned long)le32(pe_image_section->PointerToRawData),
|
||||
(unsigned long)le32(pe_image_section->PointerToRawData)+le32(pe_image_section->SizeOfRawData)-1);
|
||||
log_debug("SizeOfCode %lx\n", (long unsigned)le32(pe_image_optional32->SizeOfCode));
|
||||
log_debug("SizeOfImage %lx\n", (long unsigned)le32(pe_image_optional32->SizeOfImage));
|
||||
}
|
||||
else if(le16(pe_image_optional32->Magic)==IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
const struct pe_image_optional_hdr64 *pe_image_optional64=(const struct pe_image_optional_hdr64 *)
|
||||
(((const unsigned char*)pe_hdr + sizeof(struct pe_image_file_hdr)));
|
||||
}
|
||||
log_debug("PE image opt 0x%lx-0x%lx\n", (long unsigned)sizeof(struct pe_image_file_hdr),
|
||||
(long unsigned)(sizeof(struct pe_image_file_hdr) + le16(pe_hdr->SizeOfOptionalHeader) - 1));
|
||||
}
|
||||
#endif
|
||||
if(le32(pe_image_section->SizeOfRawData)%32==0)
|
||||
{
|
||||
unsigned int i;
|
||||
uint64_t sum=0;
|
||||
const struct pe_image_section_hdr *pe_image_section=(const struct pe_image_section_hdr*)
|
||||
((const unsigned char*)pe_hdr + sizeof(struct pe_image_file_hdr) + le16(pe_hdr->SizeOfOptionalHeader));
|
||||
for(i=0;
|
||||
i<le16(pe_hdr->NumberOfSections) &&
|
||||
(const unsigned char*)(pe_image_section+1) <= buffer+buffer_size;
|
||||
i++,pe_image_section++)
|
||||
{
|
||||
if(le32(pe_image_section->SizeOfRawData)>0)
|
||||
{
|
||||
if(sum < le32(pe_image_section->PointerToRawData) + le32(pe_image_section->SizeOfRawData))
|
||||
sum=le32(pe_image_section->PointerToRawData) + le32(pe_image_section->SizeOfRawData);
|
||||
const uint64_t tmp=(uint64_t)le32(pe_image_section->PointerToRawData) + le32(pe_image_section->SizeOfRawData);
|
||||
#ifdef DEBUG_EXE
|
||||
log_debug("%s 0x%lx-0x%lx\n", pe_image_section->Name,
|
||||
(unsigned long)le32(pe_image_section->PointerToRawData),
|
||||
(unsigned long)(tmp-1));
|
||||
#endif
|
||||
if(le32(pe_image_section->SizeOfRawData)%32==0)
|
||||
{
|
||||
if(sum < tmp)
|
||||
sum=tmp;
|
||||
}
|
||||
}
|
||||
if(le16(pe_image_section->NumberOfRelocations)>0)
|
||||
{
|
||||
const uint64_t tmp=(uint64_t)le32(pe_image_section->PointerToRelocations)+ 1*le16(pe_image_section->NumberOfRelocations);
|
||||
#ifdef DEBUG_EXE
|
||||
log_debug("relocations 0x%lx-0x%lx\n",
|
||||
(unsigned long)le32(pe_image_section->PointerToRelocations),
|
||||
(unsigned long)(tmp-1));
|
||||
#endif
|
||||
if(sum < tmp)
|
||||
sum = tmp;
|
||||
}
|
||||
}
|
||||
if(le16(pe_image_section->NumberOfRelocations)>0)
|
||||
if(le32(pe_hdr->NumberOfSymbols)>0)
|
||||
{
|
||||
const uint64_t tmp=(uint64_t)le32(pe_hdr->PointerToSymbolTable)+ IMAGE_SIZEOF_SYMBOL*(uint64_t)le32(pe_hdr->NumberOfSymbols);
|
||||
#ifdef DEBUG_EXE
|
||||
log_debug("relocations 0x%lx-0x%lx\n",
|
||||
(unsigned long)le32(pe_image_section->PointerToRelocations),
|
||||
(unsigned long)le32(pe_image_section->PointerToRelocations)+1*le16(pe_image_section->NumberOfRelocations)-1);
|
||||
log_debug("Symboles 0x%lx-0x%lx\n", (long unsigned)le32(pe_hdr->PointerToSymbolTable),
|
||||
(long unsigned)(tmp-1));
|
||||
#endif
|
||||
if(sum < le32(pe_image_section->PointerToRelocations)+ 1*le16(pe_image_section->NumberOfRelocations))
|
||||
sum = le32(pe_image_section->PointerToRelocations)+ 1*le16(pe_image_section->NumberOfRelocations);
|
||||
if(le32(pe_hdr->NumberOfSymbols)<0x10000)
|
||||
{
|
||||
if(sum < tmp)
|
||||
sum = tmp;
|
||||
}
|
||||
}
|
||||
/* It's not perfect, EXE overlay are not recovered */
|
||||
file_recovery_new->calculated_file_size=sum;
|
||||
}
|
||||
if(le32(pe_hdr->NumberOfSymbols)>0)
|
||||
{
|
||||
#ifdef DEBUG_EXE
|
||||
log_debug("Symboles 0x%lx-0x%lx\n", (long unsigned)le32(pe_hdr->PointerToSymbolTable),
|
||||
(long unsigned)(le32(pe_hdr->PointerToSymbolTable)+ IMAGE_SIZEOF_SYMBOL*le32(pe_hdr->NumberOfSymbols))-1);
|
||||
#endif
|
||||
if(le32(pe_hdr->NumberOfSymbols)<0x10000)
|
||||
{
|
||||
if(sum < le32(pe_hdr->PointerToSymbolTable)+ IMAGE_SIZEOF_SYMBOL*le32(pe_hdr->NumberOfSymbols))
|
||||
sum = le32(pe_hdr->PointerToSymbolTable)+ IMAGE_SIZEOF_SYMBOL*le32(pe_hdr->NumberOfSymbols);
|
||||
}
|
||||
}
|
||||
/* It's not perfect, EXE overlay are not recovered */
|
||||
file_recovery_new->calculated_file_size=sum;
|
||||
file_recovery_new->data_check=&data_check_size;
|
||||
file_recovery_new->file_check=&file_check_size;
|
||||
file_recovery_new->file_rename=&file_rename_pe_exe;
|
||||
return 1;
|
||||
}
|
||||
file_recovery_new->data_check=&data_check_size;
|
||||
file_recovery_new->file_check=&file_check_size;
|
||||
file_recovery_new->file_rename=&file_rename_pe_exe;
|
||||
return 1;
|
||||
}
|
||||
if(le16(dos_hdr->bytes_in_last_block) <= 512 &&
|
||||
le16(dos_hdr->blocks_in_file) > 0 &&
|
||||
|
@ -520,3 +516,8 @@ static void file_rename_pe_exe(file_recovery_t *file_recovery)
|
|||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
static void register_header_check_exe(file_stat_t *file_stat)
|
||||
{
|
||||
register_header_check(0, exe_header,sizeof(exe_header), &header_check_exe, file_stat);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue