git-svn-id: file:///var/lib/svn/clamav-devel/branches/temp_branch_pe_cleanup@2950 77e5149b-7576-45b1-b177-96237e5ba77b
aCaB authored on 2007/03/19 09:35:27... | ... |
@@ -788,14 +788,6 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
788 | 788 |
|
789 | 789 |
cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", ep, ep); |
790 | 790 |
|
791 |
- |
|
792 |
- |
|
793 |
- /* ----------------------- |
|
794 |
- BREAK HERE IF WE GOT |
|
795 |
- CALLED AS cli_peheader |
|
796 |
- ----------------------- */ |
|
797 |
- |
|
798 |
- |
|
799 | 791 |
if(pe_plus) { /* Do not continue for PE32+ files */ |
800 | 792 |
free(exe_sections); |
801 | 793 |
return CL_CLEAN; |
... | ... |
@@ -2709,7 +2701,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo) |
2709 | 2709 |
struct stat sb; |
2710 | 2710 |
int i; |
2711 | 2711 |
unsigned int err, pe_plus = 0; |
2712 |
- uint32_t valign, falign; |
|
2712 |
+ uint32_t valign, falign, hdr_size; |
|
2713 | 2713 |
size_t fsize; |
2714 | 2714 |
|
2715 | 2715 |
cli_dbgmsg("in cli_peheader\n"); |
... | ... |
@@ -2762,7 +2754,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo) |
2762 | 2762 |
return -1; |
2763 | 2763 |
} |
2764 | 2764 |
|
2765 |
- peinfo->nsections = EC16(file_hdr.NumberOfSections); |
|
2765 |
+ if ( (peinfo->nsections = EC16(file_hdr.NumberOfSections)) < 1 || peinfo->nsections > 96 ) return -1; |
|
2766 | 2766 |
|
2767 | 2767 |
if (EC16(file_hdr.SizeOfOptionalHeader) < sizeof(struct pe_image_optional_hdr32)) { |
2768 | 2768 |
cli_dbgmsg("SizeOfOptionalHeader too small\n"); |
... | ... |
@@ -2774,33 +2766,30 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo) |
2774 | 2774 |
return -1; |
2775 | 2775 |
} |
2776 | 2776 |
|
2777 |
- if(EC32(optional_hdr64.Magic)==PE32P_SIGNATURE) { |
|
2777 |
+ if(EC32(optional_hdr64.Magic)==PE32P_SIGNATURE) { /* PE+ */ |
|
2778 | 2778 |
if(EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr64)) { |
2779 | 2779 |
cli_dbgmsg("Incorrect SizeOfOptionalHeader for PE32+\n"); |
2780 | 2780 |
return -1; |
2781 | 2781 |
} |
2782 |
- pe_plus = 1; |
|
2783 |
- } |
|
2784 |
- |
|
2785 |
- if(!pe_plus) { /* PE */ |
|
2786 |
- cli_dbgmsg("File format: PE\n"); |
|
2787 |
- if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) { |
|
2788 |
- /* Seek to the end of the long header */ |
|
2789 |
- lseek(desc, (EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32)), SEEK_CUR); |
|
2790 |
- } |
|
2791 |
- |
|
2792 |
- } else { /* PE+ */ |
|
2793 | 2782 |
if(cli_readn(desc, &optional_hdr32 + 1, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) { |
2794 | 2783 |
cli_dbgmsg("Can't read optional file header\n"); |
2795 | 2784 |
return -1; |
2796 | 2785 |
} |
2797 |
- |
|
2798 |
- cli_dbgmsg("File format: PE32+\n"); |
|
2786 |
+ hdr_size = EC32(optional_hdr64.SizeOfHeaders); |
|
2787 |
+ pe_plus=1; |
|
2788 |
+ } else { /* PE */ |
|
2789 |
+ if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) { |
|
2790 |
+ /* Seek to the end of the long header */ |
|
2791 |
+ lseek(desc, (EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32)), SEEK_CUR); |
|
2792 |
+ } |
|
2793 |
+ hdr_size = EC32(optional_hdr32.SizeOfHeaders); |
|
2799 | 2794 |
} |
2800 | 2795 |
|
2801 | 2796 |
valign = (pe_plus)?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment); |
2802 | 2797 |
falign = (pe_plus)?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment); |
2803 | 2798 |
|
2799 |
+ hdr_size = PESALIGN(hdr_size, ((pe_plus ? EC16(optional_hdr64.Subsystem) : EC16(optional_hdr32.Subsystem))==1) ? falign : 0x200); |
|
2800 |
+ |
|
2804 | 2801 |
peinfo->section = (struct cli_exe_section *) cli_calloc(peinfo->nsections, sizeof(struct cli_exe_section)); |
2805 | 2802 |
|
2806 | 2803 |
if(!peinfo->section) { |
... | ... |
@@ -2817,23 +2806,35 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo) |
2817 | 2817 |
return -1; |
2818 | 2818 |
} |
2819 | 2819 |
|
2820 |
- for(i = 0; i < peinfo->nsections; i++) { |
|
2820 |
+ if(cli_readn(desc, section_hdr, peinfo->nsections * sizeof(struct pe_image_section_hdr)) != peinfo->nsections * sizeof(struct pe_image_section_hdr)) { |
|
2821 |
+ cli_dbgmsg("Can't read section header\n"); |
|
2822 |
+ cli_dbgmsg("Possibly broken PE file\n"); |
|
2823 |
+ free(section_hdr); |
|
2824 |
+ free(peinfo->section); |
|
2825 |
+ peinfo->section = NULL; |
|
2826 |
+ return -1; |
|
2827 |
+ } |
|
2821 | 2828 |
|
2822 |
- if(cli_readn(desc, §ion_hdr[i], sizeof(struct pe_image_section_hdr)) != sizeof(struct pe_image_section_hdr)) { |
|
2823 |
- cli_dbgmsg("Can't read section header\n"); |
|
2824 |
- cli_dbgmsg("Possibly broken PE file\n"); |
|
2825 |
- free(section_hdr); |
|
2826 |
- free(peinfo->section); |
|
2827 |
- peinfo->section = NULL; |
|
2828 |
- return -1; |
|
2829 |
+ for(i = 0; falign!=0x200 && i<peinfo->nsections; i++) { |
|
2830 |
+ /* file alignment fallback mode - blah */ |
|
2831 |
+ if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200)) { |
|
2832 |
+ cli_dbgmsg("Found misaligned section, using 0x200\n"); |
|
2833 |
+ falign = 0x200; |
|
2829 | 2834 |
} |
2835 |
+ } |
|
2830 | 2836 |
|
2831 |
- peinfo->section[i].rva = PEALIGN(EC32(section_hdr[i].VirtualAddress), valign); |
|
2837 |
+ for(i = 0; i < peinfo->nsections; i++) { |
|
2838 |
+ peinfo->section[i].rva = PEALIGN(EC32(section_hdr[i].VirtualAddress), valign); |
|
2832 | 2839 |
peinfo->section[i].vsz = PESALIGN(EC32(section_hdr[i].VirtualSize), valign); |
2833 | 2840 |
peinfo->section[i].raw = PEALIGN(EC32(section_hdr[i].PointerToRawData), falign); |
2834 | 2841 |
peinfo->section[i].rsz = PESALIGN(EC32(section_hdr[i].SizeOfRawData), falign); |
2842 |
+ |
|
2843 |
+ if (!peinfo->section[i].vsz && peinfo->section[i].rsz) |
|
2844 |
+ peinfo->section[i].vsz=PESALIGN(EC32(section_hdr[i].SizeOfRawData), valign); |
|
2845 |
+ |
|
2835 | 2846 |
if (peinfo->section[i].rsz && !CLI_ISCONTAINED(0, (uint32_t) fsize, peinfo->section[i].raw, peinfo->section[i].rsz)) |
2836 | 2847 |
peinfo->section[i].rsz = (fsize - peinfo->section[i].raw)*(fsize>peinfo->section[i].raw); |
2848 |
+ |
|
2837 | 2849 |
} |
2838 | 2850 |
|
2839 | 2851 |
if(pe_plus) |
... | ... |
@@ -2841,7 +2842,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo) |
2841 | 2841 |
else |
2842 | 2842 |
peinfo->ep = EC32(optional_hdr32.AddressOfEntryPoint); |
2843 | 2843 |
|
2844 |
- if(!(peinfo->ep = cli_rawaddr(peinfo->ep, peinfo->section, peinfo->nsections, &err, fsize, 0x1000)) && err) { /* HARDCODED for now - to be wiped anyway */ |
|
2844 |
+ if(!(peinfo->ep = cli_rawaddr(peinfo->ep, peinfo->section, peinfo->nsections, &err, fsize, hdr_size)) && err) { |
|
2845 | 2845 |
cli_dbgmsg("Broken PE file\n"); |
2846 | 2846 |
free(section_hdr); |
2847 | 2847 |
free(peinfo->section); |