Browse code

fsg handler improved

git-svn: trunk@1694

aCaB authored on 2005/08/16 01:21:05
Showing 4 changed files
... ...
@@ -1,3 +1,7 @@
1
+Mon Aug 15 18:17:29 CEST 2005 (acab)
2
+------------------------------------
3
+  * libclamav: fsg handler improved
4
+
1 5
 Sat Aug 13 19:08:55 CEST 2005 (acab)
2 6
 -----------------------------------
3 7
   * libclamav/spin.c: improvements and fixups
... ...
@@ -186,7 +186,7 @@ static int unfsg(char *source, char *dest, int ssize, int dsize, char **endsrc,
186 186
 	}
187 187
 	lostbit = 0;
188 188
       }
189
-      if ((backsize >= dest + dsize - cdst) || (backbytes > cdst - dest))
189
+      if ((backsize > dest + dsize - cdst) || (backbytes > cdst - dest))
190 190
 	return -1;
191 191
       while(backsize--) {
192 192
 	*cdst=*(cdst-backbytes);
... ...
@@ -207,12 +207,28 @@ static int unfsg(char *source, char *dest, int ssize, int dsize, char **endsrc,
207 207
   return 0;
208 208
 }
209 209
 
210
-int unfsg_200(char *source, char *dest, int ssize, int dsize) {
211
-  char *fake;
212 210
 
213
-  return unfsg(source, dest, ssize, dsize, &fake, &fake);
211
+int unfsg_200(char *source, char *dest, int ssize, int dsize, uint32_t rva, uint32_t base, uint32_t ep, int file) {
212
+  char *fake, *tsrc;
213
+  struct SECTION section; // Yup, just one ;)
214
+
215
+  if ( unfsg(source, dest, ssize, dsize, &fake, &fake) ) return -1;
216
+  
217
+  section.raw=0;
218
+  section.rsz = dsize;
219
+  section.vsz = dsize;
220
+  section.rva = rva;
221
+  if ( (tsrc = rebuildpe(dest, &section, 1, base, ep, 0, 0)) ) {
222
+    write(file, tsrc, 0x148+0x80+0x28+dsize);
223
+    free(tsrc);
224
+  } else {
225
+    cli_dbgmsg("FSG: Rebuilding failed\n");
226
+    return 0;
227
+  }
228
+  return 1;
214 229
 }
215 230
 
231
+
216 232
 int unfsg_133(char *source, char *dest, int ssize, int dsize, struct SECTION *sections, int sectcount, uint32_t base, uint32_t ep, int file) {
217 233
   char *tsrc=source, *tdst=dest;
218 234
   int i, upd=1, offs=0, lastsz=dsize;
... ...
@@ -266,7 +282,6 @@ int unfsg_133(char *source, char *dest, int ssize, int dsize, struct SECTION *se
266 266
     write(file, tsrc, 0x148+0x80+0x28*(sectcount+1)+offs);
267 267
     free(tsrc);
268 268
   } else {
269
-    free(tsrc);
270 269
     cli_dbgmsg("FSG: Rebuilding failed\n");
271 270
     return 0;
272 271
   }
... ...
@@ -22,7 +22,7 @@
22 22
 #include "cltypes.h"
23 23
 #include "rebuildpe.h"
24 24
 
25
-int unfsg_200(char *, char *, int, int);
25
+int unfsg_200(char *, char *, int, int, uint32_t, uint32_t, uint32_t, int);
26 26
 int unfsg_133(char *, char *, int , int, struct SECTION *, int, uint32_t, uint32_t, int);
27 27
 
28 28
 #endif
... ...
@@ -666,8 +666,8 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
666 666
 		    break;
667 667
 		}
668 668
 
669
-		/* FIXME: unused atm, needed for pe rebuilding */
670
-		cli_dbgmsg("FSG: found old EP @%x\n", cli_readint32(newebx + 12 - EC32(section_hdr[i + 1].VirtualAddress) + src) - EC32(optional_hdr.ImageBase));
669
+		newedx=cli_readint32(newebx + 12 - EC32(section_hdr[i + 1].VirtualAddress) + src) - EC32(optional_hdr.ImageBase);
670
+		cli_dbgmsg("FSG: found old EP @%x\n",newedx);
671 671
 
672 672
 		if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
673 673
 		    free(section_hdr);
... ...
@@ -675,16 +675,60 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
675 675
 		    return CL_EMEM;
676 676
 		}
677 677
 
678
-		if(unfsg_200(newesi - EC32(section_hdr[i + 1].VirtualAddress) + src, dest, ssize + EC32(section_hdr[i + 1].VirtualAddress) - newesi, dsize) == -1) {
679
-		    cli_dbgmsg("FSG: Unpacking failed\n");
678
+		tempfile = cli_gentemp(NULL);
679
+		if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
680
+		    cli_dbgmsg("FSG: Can't create file %s\n", tempfile);
681
+		    free(tempfile);
682
+		    free(section_hdr);
680 683
 		    free(src);
681 684
 		    free(dest);
682
-		    break;
685
+		    return CL_EIO;
686
+		}
687
+		
688
+		switch (unfsg_200(newesi - EC32(section_hdr[i + 1].VirtualAddress) + src, dest, ssize + EC32(section_hdr[i + 1].VirtualAddress) - newesi, dsize, newedi, EC32(optional_hdr.ImageBase), newedx, ndesc)) {
689
+		    case 1: /* Everything OK */
690
+			cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile);
691
+			free(src);
692
+			free(dest);
693
+			fsync(ndesc);
694
+			lseek(ndesc, 0, SEEK_SET);
695
+
696
+			cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
697
+			if(cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
698
+			    free(section_hdr);
699
+			    close(ndesc);
700
+			    if(!cli_leavetemps_flag)
701
+				unlink(tempfile);
702
+			    free(tempfile);
703
+			    return CL_VIRUS;
704
+			}
705
+
706
+			close(ndesc);
707
+			if(!cli_leavetemps_flag)
708
+			    unlink(tempfile);
709
+			free(tempfile);
710
+			free(section_hdr);
711
+			return CL_CLEAN;
712
+
713
+		    case 0: /* We've got an unpacked buffer, no exe though */
714
+			cli_dbgmsg("FSG: FSG: Successfully decompressed\n");
715
+			close(ndesc);
716
+			unlink(tempfile);
717
+			free(tempfile);
718
+			found = 0;
719
+			upx_success = 1;
720
+			break; /* Go and scan the buffer! */
721
+
722
+		    default: /* Everything gone wrong */
723
+			cli_dbgmsg("FSG: Unpacking failed\n");
724
+			close(ndesc);
725
+			unlink(tempfile); // It's empty anyway
726
+			free(tempfile);
727
+			free(src);
728
+			free(dest);
729
+			break;
683 730
 		}
684 731
 
685
-		found = 0;
686
-		upx_success = 1;
687
-		cli_dbgmsg("FSG: Successfully decompressed\n");
688 732
 	    }
689 733
 	}
690 734