git-svn: trunk@756
aCaB authored on 2004/08/17 04:14:14... | ... |
@@ -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 */ |