diff options
author | Christophe Grenier <grenier@cgsecurity.org> | 2009-02-03 22:35:15 +0100 |
---|---|---|
committer | Christophe Grenier <grenier@cgsecurity.org> | 2009-02-03 22:35:15 +0100 |
commit | e8b390f73086d43b7a1e4b84c7f25fd57a7056a1 (patch) | |
tree | d872c767958fd55415a5b715f4aceb3dc6c2f8df /src/file_exe.c | |
parent | 0ed831f349773e62283d0e5e9c868886e9efcaf9 (diff) |
PhotoRec: fix Windows PE .exe file identification bug and recover i386-COFF executable
Diffstat (limited to 'src/file_exe.c')
-rw-r--r-- | src/file_exe.c | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/src/file_exe.c b/src/file_exe.c index 8035865..6bce6ed 100644 --- a/src/file_exe.c +++ b/src/file_exe.c @@ -46,7 +46,7 @@ const file_hint_t file_hint_exe= { .register_header_check=®ister_header_check_exe }; -static const unsigned char exe_header[] = {'M','Z'}; +static const unsigned char exe_header[2] = {'M','Z'}; static void register_header_check_exe(file_stat_t *file_stat) { @@ -55,23 +55,48 @@ 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) { - if(memcmp(buffer,exe_header,sizeof(exe_header))==0) + const struct dos_image_file_hdr *dos_hdr=(const struct dos_image_file_hdr*)buffer; + if(memcmp(buffer,exe_header,sizeof(exe_header))==0 && + le16(dos_hdr->bytes_in_last_block) <= 512 && + le16(dos_hdr->blocks_in_file) > 0 && + le16(dos_hdr->min_extra_paragraphs) <= le16(dos_hdr->max_extra_paragraphs) + ) { const struct pe_image_file_hdr *pe_hdr; - uint32_t e_lfanew=buffer[0x3c]+ (buffer[0x3c+1]<<8) + - (buffer[0x3c+2]<<16) + (buffer[0x3c+3]<<24); /* address of new exe header */ - if(e_lfanew==0 || e_lfanew>buffer_size-sizeof(struct pe_image_file_hdr)) - { -#ifdef DEBUG_EXE - log_debug("EXE rejected, not PE (e_lfanew)\n"); -#endif - return 0; - } - pe_hdr=(const struct pe_image_file_hdr *)(buffer+e_lfanew); - if(le32(pe_hdr->Magic) != IMAGE_NT_SIGNATURE) + 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) != IMAGE_NT_SIGNATURE) { + uint64_t coff_offset=0; + coff_offset=le16(dos_hdr->blocks_in_file)*512; + if(le16(dos_hdr->bytes_in_last_block)) + coff_offset-=512-le16(dos_hdr->bytes_in_last_block); + + if(coff_offset+1 < buffer_size && + buffer[coff_offset]==0x4c && buffer[coff_offset+1]==0x01) + { /* COFF_I386MAGIC */ + reset_file_recovery(file_recovery_new); + file_recovery_new->extension=file_hint_exe.extension; + return 1; + } #ifdef DEBUG_EXE - log_debug("EXE rejected, not PE (missing signature)\n"); + { + unsigned int i; + const struct exe_reloc *exe_reloc; + log_info("Maybe a DOS EXE\n"); + log_info("blocks %llu\n", (long long unsigned)coff_offset); + log_info("data start %llx\n", (long long unsigned)16*le16(dos_hdr->header_paragraphs)); + log_info("reloc %u\n", le16(dos_hdr->num_relocs)); + for(i=0, exe_reloc=(const struct exe_reloc *)(buffer+le16(dos_hdr->reloc_table_offset)); + i < le16(dos_hdr->num_relocs) && + le16(dos_hdr->reloc_table_offset)+ (i+1)*sizeof(struct exe_reloc) < buffer_size; + i++, exe_reloc++) + { + log_info("offset %x, segment %x\n", + le16(exe_reloc->offset), le16(exe_reloc->segment)); + } + } #endif return 0; } @@ -81,7 +106,7 @@ static int header_check_exe(const unsigned char *buffer, const unsigned int buff reset_file_recovery(file_recovery_new); file_recovery_new->extension="dll"; } - else if(le16(pe_hdr->Characteristics) & 0x01) + else if(le16(pe_hdr->Characteristics) & 0x02) { reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_exe.extension; @@ -89,7 +114,7 @@ static int header_check_exe(const unsigned char *buffer, const unsigned int buff else { #ifdef DEBUG_EXE - log_debug("EXE rejected, bad characteristics\n"); + log_warning("EXE rejected, bad characteristics %02x\n", le16(pe_hdr->Characteristics)); #endif return 0; } |