Browse code

Added support for FSG 1.31

git-svn: trunk@756

aCaB authored on 2004/08/17 04:14:14
Showing 1 changed files
... ...
@@ -405,7 +405,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
405 405
 	}
406 406
 
407 407
         if(read(desc, buff, 168) != 168) {
408
-	    cli_dbgmsg("UPX/FSG: Can't read 126 bytes at 0x%x (%d)\n", ep, ep);
408
+	    cli_dbgmsg("UPX/FSG: Can't read 168 bytes at 0x%x (%d)\n", ep, ep);
409 409
             free(section_hdr);
410 410
 	    return CL_EIO;
411 411
 	}
... ...
@@ -521,7 +521,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
521 521
 	    dsize = EC32(section_hdr[i].VirtualSize);
522 522
 
523 523
 	    while(found) {
524
-		    int gp, t, sectcnt = 0;
524
+	            int gp, t, sectcnt = 0;
525 525
 		    char *support;
526 526
 		    uint32_t newesi, newedi, newebx, oldep;
527 527
 		    struct SECTION *sections;
... ...
@@ -544,6 +544,9 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
544 544
 		    break;
545 545
 		}
546 546
 
547
+		lseek(desc, gp, SEEK_SET);
548
+		gp = EC32(section_hdr[i + 1].PointerToRawData) - gp;
549
+
547 550
 		if(limits && limits->maxfilesize && gp > limits->maxfilesize) {
548 551
 		    cli_dbgmsg("FSG: Buffer size exceeded (size: %d, max: %lu)\n", gp, limits->maxfilesize);
549 552
 		    free(section_hdr);
... ...
@@ -555,9 +558,6 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
555 555
 		    return CL_EMEM;
556 556
 		}
557 557
 
558
-		lseek(desc, gp, SEEK_SET);
559
-		gp = EC32(section_hdr[i + 1].PointerToRawData) - gp;
560
-
561 558
 		if(read(desc, support, gp) != gp) {
562 559
 		    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
563 560
 		    free(section_hdr);
... ...
@@ -704,6 +704,198 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
704 704
 	    }
705 705
 	}
706 706
 
707
+	/* FIXME: easy 2 hack */
708
+ 	if(found && buff[0] == '\xbb' && cli_readint32(buff + 1) - EC32(optional_hdr.ImageBase) < min && buff[5] == '\xbf' && buff[10] == '\xbe') {
709
+
710
+	    /* FSG support - v. 1.31 */
711
+
712
+	    ssize = EC32(section_hdr[i + 1].SizeOfRawData);
713
+	    dsize = EC32(section_hdr[i].VirtualSize);
714
+
715
+	    while(found) {
716
+		    int gp = cli_readint32(buff+1) - EC32(optional_hdr.ImageBase), t, sectcnt = 0;
717
+		    char *support;
718
+		    uint32_t newesi = cli_readint32(buff+11) - EC32(optional_hdr.ImageBase);
719
+		    uint32_t newedi = cli_readint32(buff+6) - EC32(optional_hdr.ImageBase);
720
+		    uint32_t oldep = EC32(optional_hdr.AddressOfEntryPoint);
721
+		    struct SECTION *sections;
722
+
723
+	        if (oldep <= EC32(section_hdr[i + 1].VirtualAddress) || oldep > EC32(section_hdr[i + 1].VirtualAddress)+EC32(section_hdr[i + 1].SizeOfRawData) - 0xe0) {
724
+		  cli_dbgmsg("FSG: EP not in section %d\n", i+1);
725
+		  break;
726
+		}
727
+		oldep -= EC32(section_hdr[i + 1].VirtualAddress);
728
+
729
+		if(newesi < EC32(section_hdr[i + 1].VirtualAddress || newesi >= EC32(section_hdr[i + 1].VirtualAddress) + EC32(section_hdr[i + 1].SizeOfRawData))) {
730
+		    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
731
+		    break;
732
+		}
733
+
734
+		if(newedi != EC32(section_hdr[i].VirtualAddress)) {
735
+		    cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, EC32(section_hdr[i].VirtualAddress));
736
+		    break;
737
+		}
738
+
739
+		if(limits && limits->maxfilesize && (ssize > limits->maxfilesize || dsize > limits->maxfilesize)) {
740
+		    cli_dbgmsg("FSG: Sizes exceeded (ssize: %d, dsize: %d, max: %lu)\n", ssize, dsize, limits->maxfilesize);
741
+		    free(section_hdr);
742
+		    return CL_CLEAN;
743
+		}
744
+
745
+		if(ssize <= 0x19 || dsize <= ssize) {
746
+		    cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
747
+		    free(section_hdr);
748
+		    return CL_CLEAN;
749
+		}
750
+
751
+		if( gp >= EC32(section_hdr[i + 1].PointerToRawData) || gp < 0) {
752
+		    cli_dbgmsg("FSG: Support data out of padding area (newedi: %d, vaddr: %d)\n", newedi, EC32(section_hdr[i].VirtualAddress));
753
+		    break;
754
+		}
755
+
756
+		lseek(desc, gp, SEEK_SET);
757
+		gp = EC32(section_hdr[i + 1].PointerToRawData) - gp;
758
+
759
+		if(limits && limits->maxfilesize && gp > limits->maxfilesize) {
760
+		    cli_dbgmsg("FSG: Buffer size exceeded (size: %d, max: %lu)\n", gp, limits->maxfilesize);
761
+		    free(section_hdr);
762
+		    return CL_CLEAN;
763
+		}
764
+
765
+		if((support = (char *) cli_malloc(gp)) == NULL) {
766
+		    free(section_hdr);
767
+		    return CL_EMEM;
768
+		}
769
+
770
+		if(read(desc, support, gp) != gp) {
771
+		    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
772
+		    free(section_hdr);
773
+		    free(support);
774
+		    return CL_EIO;
775
+		}
776
+
777
+		/* Counting original sections */
778
+		for(t = 0; t < gp - 2; t += 2) {
779
+		  uint32_t rva = support[t]+256*support[t+1];
780
+		  
781
+		  if (rva == 2 || rva == 1)
782
+		    break;
783
+
784
+		  rva = ((rva-2)<<12) - EC32(optional_hdr.ImageBase);
785
+		  sectcnt++;
786
+
787
+		  if(rva < EC32(section_hdr[i].VirtualAddress) || rva >= EC32(section_hdr[i].VirtualAddress)+EC32(section_hdr[i].VirtualSize)) {
788
+		    cli_dbgmsg("FSG: Original section %d is out of bounds\n", sectcnt);
789
+		    break;
790
+		  }
791
+		}
792
+
793
+		if( t >= gp-10 || cli_readint32(support + t + 6) != 2 ) {
794
+		    free(support);
795
+		    break;
796
+		}
797
+
798
+		if((sections = (struct SECTION *) cli_malloc((sectcnt + 1) * sizeof(struct SECTION))) == NULL) {
799
+		    free(section_hdr);
800
+		    free(support);
801
+		    return CL_EMEM;
802
+		}
803
+
804
+		sections[0].rva = newedi;
805
+		for(t = 0; t <= sectcnt - 1; t++) {
806
+		  sections[t+1].rva = (((support[t*2]+256*support[t*2+1])-2)<<12)-EC32(optional_hdr.ImageBase);
807
+		}
808
+
809
+		free(support);
810
+
811
+		if((src = (char *) cli_malloc(ssize)) == NULL) {
812
+		    free(section_hdr);
813
+		    free(sections);
814
+		    return CL_EMEM;
815
+		}
816
+
817
+		lseek(desc, EC32(section_hdr[i + 1].PointerToRawData), SEEK_SET);
818
+		if(read(desc, src, ssize) != ssize) {
819
+		    cli_dbgmsg("Can't read raw data of section %d\n", i);
820
+		    free(section_hdr);
821
+		    free(sections);
822
+		    free(src);
823
+		    return CL_EIO;
824
+		}
825
+
826
+		if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
827
+		    free(section_hdr);
828
+		    free(src);
829
+		    free(sections);
830
+		    return CL_EMEM;
831
+		}
832
+
833
+		/* Better not increasing buff size any further, let's go the hard way */
834
+		oldep = EC32(optional_hdr.AddressOfEntryPoint) + 0xda + 6 + cli_readint32(src+0xdc+oldep);
835
+		cli_dbgmsg("FSG: found old EP @%x\n", oldep);
836
+
837
+		tempfile = cli_gentemp(NULL);
838
+		if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
839
+		    cli_dbgmsg("FSG: Can't create file %s\n", tempfile);
840
+		    free(tempfile);
841
+		    free(section_hdr);
842
+		    free(src);
843
+		    free(dest);
844
+		    free(sections);
845
+		    return CL_EIO;
846
+		}
847
+
848
+		switch(unfsg_133(src + newesi - EC32(section_hdr[i + 1].VirtualAddress), dest, ssize + EC32(section_hdr[i + 1].VirtualAddress) - newesi, dsize, sections, sectcnt, EC32(optional_hdr.ImageBase), oldep, ndesc)) {
849
+		    case 1: /* Everything OK */
850
+			cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile);
851
+			free(src);
852
+			free(dest);
853
+			free(sections);
854
+			fsync(ndesc);
855
+			lseek(ndesc, 0, SEEK_SET);
856
+
857
+			if(cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
858
+			    free(section_hdr);
859
+			    close(ndesc);
860
+			    if(!cli_leavetemps_flag)
861
+				unlink(tempfile);
862
+			    free(tempfile);
863
+			    return CL_VIRUS;
864
+			}
865
+
866
+			close(ndesc);
867
+			if(!cli_leavetemps_flag)
868
+			    unlink(tempfile);
869
+			free(tempfile);
870
+			free(section_hdr);
871
+			return CL_CLEAN;
872
+
873
+		    case 0: /* We've got an unpacked buffer, no exe though */
874
+			cli_dbgmsg("FSG: FSG: Successfully decompressed\n");
875
+			close(ndesc);
876
+			unlink(tempfile);
877
+			free(tempfile);
878
+			free(sections);
879
+			found = 0;
880
+			upx_success = 1;
881
+			break; /* Go and scan the buffer! */
882
+
883
+		    default: /* Everything gone wrong */
884
+			cli_dbgmsg("FSG: Unpacking failed\n");
885
+			close(ndesc);
886
+			unlink(tempfile); // It's empty anyway
887
+			free(tempfile);
888
+			free(src);
889
+			free(dest);
890
+			free(sections);
891
+			break;
892
+		}
893
+
894
+		break; /* were done with 1.31 */
895
+	    }
896
+	}
897
+
898
+
707 899
 	if(found) {
708 900
 
709 901
 	    /* UPX support */