From 0ae3da416103e2d47bb944bcaaa33e2bf736d96c Mon Sep 17 00:00:00 2001 From: Christophe Grenier Date: Mon, 5 Aug 2019 16:25:06 +0200 Subject: [PATCH] PhotoRec: avoid potential integer overflow while parsing exe files --- src/file_exe.c | 181 +++++++++++++++++++++++++------------------------ 1 file changed, 91 insertions(+), 90 deletions(-) diff --git a/src/file_exe.c b/src/file_exe.c index 1348db53..12f1400d 100644 --- a/src/file_exe.c +++ b/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; - iNumberOfSections) && - (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; + iNumberOfSections) && + (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); +}