From 4490fd97ee2f5f434593dfb123785fa2c1cdfbf1 Mon Sep 17 00:00:00 2001 From: aCaB Date: Tue, 20 Mar 2007 03:57:21 +0000 Subject: [PATCH] More generic approach for ghost detection/fixup on rebuild. Better handling of rebuilt headers size with lots of sects. Nested (2+) petite packed files still result in Broken.Executable but they're indeed broken - not too elegant, but... git-svn-id: file:///var/lib/svn/clamav-devel/branches/temp_branch_pe_cleanup@2954 77e5149b-7576-45b1-b177-96237e5ba77b --- libclamav/pe.c | 4 +--- libclamav/petite.c | 15 +-------------- libclamav/petite.h | 2 +- libclamav/rebuildpe.c | 26 +++++++++++++++++++------- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/libclamav/pe.c b/libclamav/pe.c index 914356222..d9fbe1d6e 100644 --- a/libclamav/pe.c +++ b/libclamav/pe.c @@ -2254,7 +2254,7 @@ skip_upack_and_go_to_next_unpacker: if (!petite_inflate2x_1to9(dest, min, max - min, exe_sections, nsections - (found == 1 ? 1 : 0), EC32(optional_hdr32.ImageBase), vep, ndesc, found, EC32(optional_hdr32.DataDirectory[2].VirtualAddress), - EC32(optional_hdr32.DataDirectory[2].Size), min)) { + EC32(optional_hdr32.DataDirectory[2].Size))) { cli_dbgmsg("Petite: Unpacked and rebuilt executable saved in %s\n", tempfile); cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); free(dest); @@ -2818,7 +2818,6 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo) for(i = 0; falign!=0x200 && insections; i++) { /* file alignment fallback mode - blah */ if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200)) { - cli_dbgmsg("Found misaligned section, using 0x200\n"); falign = 0x200; } } @@ -2834,7 +2833,6 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo) if (peinfo->section[i].rsz && !CLI_ISCONTAINED(0, (uint32_t) fsize, peinfo->section[i].raw, peinfo->section[i].rsz)) peinfo->section[i].rsz = (fsize - peinfo->section[i].raw)*(fsize>peinfo->section[i].raw); - } if(pe_plus) diff --git a/libclamav/petite.c b/libclamav/petite.c index 1a322e77d..ed58c201d 100644 --- a/libclamav/petite.c +++ b/libclamav/petite.c @@ -75,7 +75,7 @@ static int doubledl(char **scur, uint8_t *mydlptr, char *buffer, uint32_t buffer return (olddl>>7)&1; } -int petite_inflate2x_1to9(char *buf, uint32_t minrva, uint32_t bufsz, struct cli_exe_section *sections, unsigned int sectcount, uint32_t Imagebase, uint32_t pep, int desc, int version, uint32_t ResRva, uint32_t ResSize, uint32_t firstrva) +int petite_inflate2x_1to9(char *buf, uint32_t minrva, uint32_t bufsz, struct cli_exe_section *sections, unsigned int sectcount, uint32_t Imagebase, uint32_t pep, int desc, int version, uint32_t ResRva, uint32_t ResSize) { char *adjbuf = buf - minrva; char *packed = NULL; @@ -149,19 +149,6 @@ int petite_inflate2x_1to9(char *buf, uint32_t minrva, uint32_t bufsz, struct cli usects[t].vsz = usects[t+1].rva - usects[t].rva; } - if (firstrva!=usects[0].rva) { - struct cli_exe_section *nusects; - cli_dbgmsg("Petite: making room for ghosts.\n"); - if ((nusects=cli_calloc(j+1, sizeof(struct cli_exe_section)))) { - memcpy(&nusects[1], usects, sizeof(struct cli_exe_section)*j); - nusects[0].rva=firstrva; - nusects[0].vsz=nusects[1].rva-firstrva; - free(usects); - usects = nusects; - j++; - } - } - /* * Our encryption is pathetic and out software is lame but * we need to claim it's unbreakable. diff --git a/libclamav/petite.h b/libclamav/petite.h index 5aaaa68d9..612de0ca5 100644 --- a/libclamav/petite.h +++ b/libclamav/petite.h @@ -23,6 +23,6 @@ #include "cltypes.h" #include "pe.h" -int petite_inflate2x_1to9(char *buf, uint32_t minrva, uint32_t bufsz, struct cli_exe_section *sections, unsigned int sectcount, uint32_t Imagebase, uint32_t pep, int desc, int version, uint32_t ResRva, uint32_t ResSize, uint32_t baserva); +int petite_inflate2x_1to9(char *buf, uint32_t minrva, uint32_t bufsz, struct cli_exe_section *sections, unsigned int sectcount, uint32_t Imagebase, uint32_t pep, int desc, int version, uint32_t ResRva, uint32_t ResSize); #endif diff --git a/libclamav/rebuildpe.c b/libclamav/rebuildpe.c index b03d8f8ef..351ab4780 100644 --- a/libclamav/rebuildpe.c +++ b/libclamav/rebuildpe.c @@ -119,45 +119,57 @@ struct IMAGE_PE_HEADER { int cli_rebuildpe(char *buffer, struct cli_exe_section *sections, int sects, uint32_t base, uint32_t ep, uint32_t ResRva, uint32_t ResSize, int file) { - int i; - uint32_t datasize=0, rawbase; + uint32_t datasize=0, rawbase=PESALIGN(0x148+0x80+0x28*sects, 0x200); char *pefile=NULL, *curpe; struct IMAGE_PE_HEADER *fakepe; + int i, gotghost=(sections[0].rva > PESALIGN(rawbase, 0x1000)); - if(sects > 96) + if (gotghost) rawbase=PESALIGN(0x148+0x80+0x28*(sects+1), 0x200); + + if(sects+gotghost > 96) return 0; for (i=0; i < sects; i++) datasize+=PESALIGN(sections[i].rsz, 0x200); - rawbase = PESALIGN(0x148+0x80+0x28*sects, 0x200); - if(datasize > CLI_MAX_ALLOCATION) return 0; if((pefile = (char *) cli_calloc(rawbase+datasize, 1))) { memcpy(pefile, HEADERS, 0x148); - datasize = 0x1000; + datasize = PESALIGN(rawbase, 0x1000); fakepe = (struct IMAGE_PE_HEADER *)(pefile+0xd0); - fakepe->NumberOfSections = EC16(sects); + fakepe->NumberOfSections = EC16(sects+gotghost); fakepe->AddressOfEntryPoint = EC32(ep); fakepe->ImageBase = EC32(base); + fakepe->SizeOfHeaders = EC32(rawbase); memset(pefile+0x148, 0, 0x80); cli_writeint32(pefile+0x148+0x10, ResRva); cli_writeint32(pefile+0x148+0x14, ResSize); curpe = pefile+0x148+0x80; + if (gotghost) { + snprintf(curpe, 8, "empty"); + cli_writeint32(curpe+8, sections[0].rva-datasize); /* vsize */ + cli_writeint32(curpe+12, datasize); /* rva */ + cli_writeint32(curpe+0x24, 0xffffffff); + curpe+=40; + datasize+=PESALIGN(sections[0].rva-datasize, 0x1000); + } + for (i=0; i < sects; i++) { snprintf(curpe, 8, ".clam%.2d", i+1); cli_writeint32(curpe+8, sections[i].vsz); cli_writeint32(curpe+12, sections[i].rva); cli_writeint32(curpe+16, sections[i].rsz); cli_writeint32(curpe+20, rawbase); + /* already zeroed cli_writeint32(curpe+24, 0); cli_writeint32(curpe+28, 0); cli_writeint32(curpe+32, 0); + */ cli_writeint32(curpe+0x24, 0xffffffff); memcpy(pefile+rawbase, buffer+sections[i].raw, sections[i].rsz); rawbase+=PESALIGN(sections[i].rsz, 0x200);