Browse code

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

aCaB authored on 2007/03/20 12:57:21
Showing 4 changed files
... ...
@@ -2254,7 +2254,7 @@ skip_upack_and_go_to_next_unpacker:
2254 2254
 	    if (!petite_inflate2x_1to9(dest, min, max - min, exe_sections,
2255 2255
 		    nsections - (found == 1 ? 1 : 0), EC32(optional_hdr32.ImageBase),
2256 2256
 		    vep, ndesc, found, EC32(optional_hdr32.DataDirectory[2].VirtualAddress),
2257
-		    EC32(optional_hdr32.DataDirectory[2].Size), min)) {
2257
+		    EC32(optional_hdr32.DataDirectory[2].Size))) {
2258 2258
 	        cli_dbgmsg("Petite: Unpacked and rebuilt executable saved in %s\n", tempfile);
2259 2259
 		cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
2260 2260
 		free(dest);
... ...
@@ -2818,7 +2818,6 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
2818 2818
     for(i = 0; falign!=0x200 && i<peinfo->nsections; i++) {
2819 2819
 	/* file alignment fallback mode - blah */
2820 2820
 	if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200)) {
2821
-	    cli_dbgmsg("Found misaligned section, using 0x200\n");
2822 2821
 	    falign = 0x200;
2823 2822
 	}
2824 2823
     }
... ...
@@ -2834,7 +2833,6 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
2834 2834
 
2835 2835
 	if (peinfo->section[i].rsz && !CLI_ISCONTAINED(0, (uint32_t) fsize, peinfo->section[i].raw, peinfo->section[i].rsz))
2836 2836
 	    peinfo->section[i].rsz = (fsize - peinfo->section[i].raw)*(fsize>peinfo->section[i].raw);
2837
-
2838 2837
     }
2839 2838
 
2840 2839
     if(pe_plus)
... ...
@@ -75,7 +75,7 @@ static int doubledl(char **scur, uint8_t *mydlptr, char *buffer, uint32_t buffer
75 75
   return (olddl>>7)&1;
76 76
 }
77 77
 
78
-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)
78
+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)
79 79
 {
80 80
   char *adjbuf = buf - minrva;
81 81
   char *packed = NULL;
... ...
@@ -149,19 +149,6 @@ int petite_inflate2x_1to9(char *buf, uint32_t minrva, uint32_t bufsz, struct cli
149 149
 	  usects[t].vsz = usects[t+1].rva - usects[t].rva;
150 150
       }
151 151
       
152
-      if (firstrva!=usects[0].rva) {
153
-	struct cli_exe_section *nusects;
154
-	cli_dbgmsg("Petite: making room for ghosts.\n");
155
-	if ((nusects=cli_calloc(j+1, sizeof(struct cli_exe_section)))) {
156
-	  memcpy(&nusects[1], usects, sizeof(struct cli_exe_section)*j);
157
-	  nusects[0].rva=firstrva;
158
-	  nusects[0].vsz=nusects[1].rva-firstrva;
159
-	  free(usects);
160
-	  usects = nusects;
161
-	  j++;
162
-	}
163
-      }
164
-     
165 152
       /*
166 153
        * Our encryption is pathetic and out software is lame but
167 154
        * we need to claim it's unbreakable.
... ...
@@ -23,6 +23,6 @@
23 23
 #include "cltypes.h"
24 24
 #include "pe.h"
25 25
 
26
-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);
26
+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);
27 27
 
28 28
 #endif
... ...
@@ -119,45 +119,57 @@ struct IMAGE_PE_HEADER {
119 119
 
120 120
 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)
121 121
 {
122
-  int i;
123
-  uint32_t datasize=0, rawbase;
122
+  uint32_t datasize=0, rawbase=PESALIGN(0x148+0x80+0x28*sects, 0x200);
124 123
   char *pefile=NULL, *curpe;
125 124
   struct IMAGE_PE_HEADER *fakepe;
125
+  int i, gotghost=(sections[0].rva > PESALIGN(rawbase, 0x1000));
126 126
 
127
-  if(sects > 96)
127
+  if (gotghost) rawbase=PESALIGN(0x148+0x80+0x28*(sects+1), 0x200);
128
+
129
+  if(sects+gotghost > 96)
128 130
     return 0;
129 131
 
130 132
   for (i=0; i < sects; i++)
131 133
     datasize+=PESALIGN(sections[i].rsz, 0x200);
132 134
 
133
-  rawbase = PESALIGN(0x148+0x80+0x28*sects, 0x200);
134
-
135 135
   if(datasize > CLI_MAX_ALLOCATION)
136 136
     return 0;
137 137
 
138 138
   if((pefile = (char *) cli_calloc(rawbase+datasize, 1))) {
139 139
     memcpy(pefile, HEADERS, 0x148);
140 140
 
141
-    datasize = 0x1000;
141
+    datasize = PESALIGN(rawbase, 0x1000);
142 142
 
143 143
     fakepe = (struct IMAGE_PE_HEADER *)(pefile+0xd0);
144
-    fakepe->NumberOfSections = EC16(sects);
144
+    fakepe->NumberOfSections = EC16(sects+gotghost);
145 145
     fakepe->AddressOfEntryPoint = EC32(ep);
146 146
     fakepe->ImageBase = EC32(base);
147
+    fakepe->SizeOfHeaders = EC32(rawbase);
147 148
     memset(pefile+0x148, 0, 0x80);
148 149
     cli_writeint32(pefile+0x148+0x10, ResRva);
149 150
     cli_writeint32(pefile+0x148+0x14, ResSize);
150 151
     curpe = pefile+0x148+0x80;
151 152
 
153
+    if (gotghost) {
154
+      snprintf(curpe, 8, "empty");
155
+      cli_writeint32(curpe+8, sections[0].rva-datasize); /* vsize */
156
+      cli_writeint32(curpe+12, datasize); /* rva */
157
+      cli_writeint32(curpe+0x24, 0xffffffff);
158
+      curpe+=40;
159
+      datasize+=PESALIGN(sections[0].rva-datasize, 0x1000);
160
+    }
161
+
152 162
     for (i=0; i < sects; i++) {
153 163
       snprintf(curpe, 8, ".clam%.2d", i+1);
154 164
       cli_writeint32(curpe+8, sections[i].vsz);
155 165
       cli_writeint32(curpe+12, sections[i].rva);
156 166
       cli_writeint32(curpe+16, sections[i].rsz);
157 167
       cli_writeint32(curpe+20, rawbase);
168
+      /* already zeroed
158 169
       cli_writeint32(curpe+24, 0);
159 170
       cli_writeint32(curpe+28, 0);
160 171
       cli_writeint32(curpe+32, 0);
172
+      */
161 173
       cli_writeint32(curpe+0x24, 0xffffffff);
162 174
       memcpy(pefile+rawbase, buffer+sections[i].raw, sections[i].rsz);
163 175
       rawbase+=PESALIGN(sections[i].rsz, 0x200);