git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@715 77e5149b-7576-45b1-b177-96237e5ba77b
Tomasz Kojm authored on 2004/08/03 02:09:06... | ... |
@@ -22,12 +22,19 @@ OLE2 and VBA decoders, new thread manager in clamd. |
22 | 22 |
|
23 | 23 |
Thomas Lamy <tlamy*clamav.net> |
24 | 24 |
gpg key : http://www.clamav.net/gpg/tlamy.gpg |
25 |
+GPG fingerprint = C489 3262 31CE 85B3 98BF 7E4C 53C6 9727 0F48 F821 |
|
25 | 26 |
Random hacker. |
26 | 27 |
|
28 |
+aCaB <acab*clamav.net> |
|
29 |
+gpg key : http://www.clamav.net/gpg/acab.gpg |
|
30 |
+GPG fingerprint = 977D EAED 219F F275 6DAF F83A BA15 97C6 9D6D E6DGPG |
|
31 |
+Executable unpackers. |
|
32 |
+ |
|
27 | 33 |
Submission management interface (for database developers only): Diego d'Ambra |
28 | 34 |
<diego*clamav.net>, Thomas Madsen <tm*softcom.dk> |
29 | 35 |
|
30 |
-Database developers: |
|
36 |
+Database maintainers: |
|
37 |
+--------------------- |
|
31 | 38 |
|
32 | 39 |
aCaB <acab*clamav.net> |
33 | 40 |
|
... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Mon Aug 2 19:03:33 CEST 2004 (tk) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav: pe: integrate Petite unpacker from aCaB (not yet activated) |
|
4 |
+ |
|
1 | 5 |
Mon Aug 2 12:28:31 CEST 2004 (tk) |
2 | 6 |
---------------------------------- |
3 | 7 |
* clamd: scanstream: protect access to static memory referenced by |
... | ... |
@@ -45,6 +45,7 @@ libclamav_la_SOURCES = \ |
45 | 45 |
str.h \ |
46 | 46 |
defaults.h \ |
47 | 47 |
scanners.c \ |
48 |
+ scanners.h \ |
|
48 | 49 |
filetypes.c \ |
49 | 50 |
filetypes.h \ |
50 | 51 |
unrarlib.c \ |
... | ... |
@@ -104,6 +105,10 @@ libclamav_la_SOURCES = \ |
104 | 104 |
htmlnorm.c \ |
105 | 105 |
htmlnorm.h \ |
106 | 106 |
chmunpack.c \ |
107 |
- chmunpack.h |
|
107 |
+ chmunpack.h \ |
|
108 |
+ rebuildpe.c \ |
|
109 |
+ rebuildpe.h \ |
|
110 |
+ petite.c \ |
|
111 |
+ petite.h |
|
108 | 112 |
|
109 | 113 |
lib_LTLIBRARIES = libclamav.la |
... | ... |
@@ -79,7 +79,7 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher.lo \ |
79 | 79 |
blob.lo mbox.lo message.lo snprintf.lo strrcpy.lo table.lo \ |
80 | 80 |
text.lo ole2_extract.lo vba_extract.lo msexpand.lo pe.lo \ |
81 | 81 |
cabd.lo lzxd.lo mszipd.lo qtmd.lo system.lo upx.lo htmlnorm.lo \ |
82 |
- chmunpack.lo |
|
82 |
+ chmunpack.lo rebuildpe.lo petite.lo |
|
83 | 83 |
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS) |
84 | 84 |
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) |
85 | 85 |
depcomp = $(SHELL) $(top_srcdir)/depcomp |
... | ... |
@@ -95,7 +95,8 @@ am__depfiles_maybe = depfiles |
95 | 95 |
@AMDEP_TRUE@ ./$(DEPDIR)/mszipd.Plo \ |
96 | 96 |
@AMDEP_TRUE@ ./$(DEPDIR)/ole2_extract.Plo \ |
97 | 97 |
@AMDEP_TRUE@ ./$(DEPDIR)/others.Plo ./$(DEPDIR)/pe.Plo \ |
98 |
-@AMDEP_TRUE@ ./$(DEPDIR)/qtmd.Plo ./$(DEPDIR)/readdb.Plo \ |
|
98 |
+@AMDEP_TRUE@ ./$(DEPDIR)/petite.Plo ./$(DEPDIR)/qtmd.Plo \ |
|
99 |
+@AMDEP_TRUE@ ./$(DEPDIR)/readdb.Plo ./$(DEPDIR)/rebuildpe.Plo \ |
|
99 | 100 |
@AMDEP_TRUE@ ./$(DEPDIR)/scanners.Plo ./$(DEPDIR)/snprintf.Plo \ |
100 | 101 |
@AMDEP_TRUE@ ./$(DEPDIR)/str.Plo ./$(DEPDIR)/strc.Plo \ |
101 | 102 |
@AMDEP_TRUE@ ./$(DEPDIR)/strrcpy.Plo ./$(DEPDIR)/system.Plo \ |
... | ... |
@@ -253,6 +254,7 @@ libclamav_la_SOURCES = \ |
253 | 253 |
str.h \ |
254 | 254 |
defaults.h \ |
255 | 255 |
scanners.c \ |
256 |
+ scanners.h \ |
|
256 | 257 |
filetypes.c \ |
257 | 258 |
filetypes.h \ |
258 | 259 |
unrarlib.c \ |
... | ... |
@@ -312,7 +314,11 @@ libclamav_la_SOURCES = \ |
312 | 312 |
htmlnorm.c \ |
313 | 313 |
htmlnorm.h \ |
314 | 314 |
chmunpack.c \ |
315 |
- chmunpack.h |
|
315 |
+ chmunpack.h \ |
|
316 |
+ rebuildpe.c \ |
|
317 |
+ rebuildpe.h \ |
|
318 |
+ petite.c \ |
|
319 |
+ petite.h |
|
316 | 320 |
|
317 | 321 |
lib_LTLIBRARIES = libclamav.la |
318 | 322 |
all: all-am |
... | ... |
@@ -403,8 +409,10 @@ distclean-compile: |
403 | 403 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ole2_extract.Plo@am__quote@ |
404 | 404 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/others.Plo@am__quote@ |
405 | 405 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe.Plo@am__quote@ |
406 |
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/petite.Plo@am__quote@ |
|
406 | 407 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qtmd.Plo@am__quote@ |
407 | 408 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdb.Plo@am__quote@ |
409 |
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rebuildpe.Plo@am__quote@ |
|
408 | 410 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scanners.Plo@am__quote@ |
409 | 411 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snprintf.Plo@am__quote@ |
410 | 412 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str.Plo@am__quote@ |
... | ... |
@@ -1,9 +1,6 @@ |
1 | 1 |
/* |
2 | 2 |
* Copyright (C) 2004 Tomasz Kojm <tkojm@clamav.net> |
3 | 3 |
* |
4 |
- * Implementation (header structures) based on the PE format description |
|
5 |
- * by B. Luevelsmeyer |
|
6 |
- * |
|
7 | 4 |
* This program is free software; you can redistribute it and/or modify |
8 | 5 |
* it under the terms of the GNU General Public License as published by |
9 | 6 |
* the Free Software Foundation; either version 2 of the License, or |
... | ... |
@@ -35,7 +32,10 @@ |
35 | 35 |
#include "cltypes.h" |
36 | 36 |
#include "clamav.h" |
37 | 37 |
#include "others.h" |
38 |
+#include "pe.h" |
|
38 | 39 |
#include "upx.h" |
40 |
+#include "petite.h" |
|
41 |
+#include "scanners.h" |
|
39 | 42 |
|
40 | 43 |
#define IMAGE_DOS_SIGNATURE 0x5a4d /* MZ */ |
41 | 44 |
#define IMAGE_DOS_SIGNATURE_OLD 0x4d5a /* ZM */ |
... | ... |
@@ -63,75 +63,6 @@ static inline uint32_t EC32(uint32_t v) |
63 | 63 |
|
64 | 64 |
extern short cli_leavetemps_flag; |
65 | 65 |
|
66 |
-struct pe_image_file_hdr { |
|
67 |
- uint32_t Magic; |
|
68 |
- uint16_t Machine; |
|
69 |
- uint16_t NumberOfSections; |
|
70 |
- uint32_t TimeDateStamp; /* unreliable */ |
|
71 |
- uint32_t PointerToSymbolTable; /* debug */ |
|
72 |
- uint32_t NumberOfSymbols; /* debug */ |
|
73 |
- uint16_t SizeOfOptionalHeader; /* == 224 */ |
|
74 |
- uint16_t Characteristics; |
|
75 |
-}; |
|
76 |
- |
|
77 |
-struct pe_image_data_dir { |
|
78 |
- uint32_t VirtualAddress; |
|
79 |
- uint32_t Size; |
|
80 |
-}; |
|
81 |
- |
|
82 |
-struct pe_image_optional_hdr { |
|
83 |
- uint16_t Magic; |
|
84 |
- uint8_t MajorLinkerVersion; /* unreliable */ |
|
85 |
- uint8_t MinorLinkerVersion; /* unreliable */ |
|
86 |
- uint32_t SizeOfCode; /* unreliable */ |
|
87 |
- uint32_t SizeOfInitializedData; /* unreliable */ |
|
88 |
- uint32_t SizeOfUninitializedData; /* unreliable */ |
|
89 |
- uint32_t AddressOfEntryPoint; |
|
90 |
- uint32_t BaseOfCode; |
|
91 |
- uint32_t BaseOfData; |
|
92 |
- uint32_t ImageBase; /* multiple of 64 KB */ |
|
93 |
- uint32_t SectionAlignment; /* usually 32 or 4096 */ |
|
94 |
- uint32_t FileAlignment; /* usually 32 or 512 */ |
|
95 |
- uint16_t MajorOperatingSystemVersion; /* not used */ |
|
96 |
- uint16_t MinorOperatingSystemVersion; /* not used */ |
|
97 |
- uint16_t MajorImageVersion; /* unreliable */ |
|
98 |
- uint16_t MinorImageVersion; /* unreliable */ |
|
99 |
- uint16_t MajorSubsystemVersion; |
|
100 |
- uint16_t MinorSubsystemVersion; |
|
101 |
- uint32_t Win32VersionValue; /* ? */ |
|
102 |
- uint32_t SizeOfImage; |
|
103 |
- uint32_t SizeOfHeaders; |
|
104 |
- uint32_t CheckSum; /* NT drivers only */ |
|
105 |
- uint16_t Subsystem; |
|
106 |
- uint16_t DllCharacteristics; |
|
107 |
- uint32_t SizeOfStackReserve; |
|
108 |
- uint32_t SizeOfStackCommit; |
|
109 |
- uint32_t SizeOfHeapReserve; |
|
110 |
- uint32_t SizeOfHeapCommit; |
|
111 |
- uint32_t LoaderFlags; /* ? */ |
|
112 |
- uint32_t NumberOfRvaAndSizes; /* unreliable */ |
|
113 |
- struct pe_image_data_dir DataDirectory[16]; |
|
114 |
-}; |
|
115 |
- |
|
116 |
-struct pe_image_section_hdr { |
|
117 |
- uint8_t Name[8]; /* may not end with NULL */ |
|
118 |
- /* |
|
119 |
- union { |
|
120 |
- uint32_t PhysicalAddress; |
|
121 |
- uint32_t VirtualSize; |
|
122 |
- } AddrSize; |
|
123 |
- */ |
|
124 |
- uint32_t VirtualSize; |
|
125 |
- uint32_t VirtualAddress; |
|
126 |
- uint32_t SizeOfRawData; /* multiple of FileAlignment */ |
|
127 |
- uint32_t PointerToRawData; /* offset to the section's data */ |
|
128 |
- uint32_t PointerToRelocations; /* object files only */ |
|
129 |
- uint32_t PointerToLinenumbers; /* object files only */ |
|
130 |
- uint16_t NumberOfRelocations; /* object files only */ |
|
131 |
- uint16_t NumberOfLinenumbers; /* object files only */ |
|
132 |
- uint32_t Characteristics; |
|
133 |
-}; |
|
134 |
- |
|
135 | 66 |
static uint32_t cli_rawaddr(uint32_t rva, struct pe_image_section_hdr *shp, uint16_t nos) |
136 | 67 |
{ |
137 | 68 |
int i, found = 0; |
... | ... |
@@ -234,9 +165,11 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
234 | 234 |
struct pe_image_optional_hdr optional_hdr; |
235 | 235 |
struct pe_image_section_hdr *section_hdr; |
236 | 236 |
struct stat sb; |
237 |
- char sname[9], buff[126], *tempfile; |
|
238 |
- int i, found, upx_success = 0, broken = 0; |
|
237 |
+ char sname[9], buff[256], *tempfile; |
|
238 |
+ int i, found, upx_success = 0, broken = 0, min = 0, max = 0; |
|
239 | 239 |
int (*upxfn)(char *, int , char *, int) = NULL; |
240 |
+ char *src, *dest; |
|
241 |
+ int ssize, dsize, ndesc; |
|
240 | 242 |
|
241 | 243 |
|
242 | 244 |
if(read(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) { |
... | ... |
@@ -362,6 +295,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
362 | 362 |
} |
363 | 363 |
|
364 | 364 |
cli_dbgmsg("NumberOfRvaAndSizes: %d\n", EC32(optional_hdr.NumberOfRvaAndSizes)); |
365 |
+ cli_dbgmsg("------------------------------------\n"); |
|
365 | 366 |
|
366 | 367 |
section_hdr = (struct pe_image_section_hdr *) cli_calloc(nsections, sizeof(struct pe_image_section_hdr)); |
367 | 368 |
|
... | ... |
@@ -381,7 +315,6 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
381 | 381 |
|
382 | 382 |
strncpy(sname, section_hdr[i].Name, 8); |
383 | 383 |
sname[8] = 0; |
384 |
- cli_dbgmsg("------------------------------------\n"); |
|
385 | 384 |
cli_dbgmsg("Section %d\n", i); |
386 | 385 |
cli_dbgmsg("Section name: %s\n", sname); |
387 | 386 |
cli_dbgmsg("VirtualSize: %d\n", EC32(section_hdr[i].VirtualSize)); |
... | ... |
@@ -404,16 +337,18 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
404 | 404 |
|
405 | 405 |
if(EC32(section_hdr[i].Characteristics) & 0x20000000) |
406 | 406 |
cli_dbgmsg("Section's memory is executable\n"); |
407 |
+ cli_dbgmsg("------------------------------------\n"); |
|
407 | 408 |
|
408 |
-/* |
|
409 |
- if(!strcmp(sname, "_winzip_")) { |
|
410 |
- int ptrd = section_hdr.PointerToRawData & ~(optional_hdr.FileAlignment - 1); |
|
409 |
+ if(!i) { |
|
410 |
+ min = EC32(section_hdr[i].VirtualAddress); |
|
411 |
+ max = EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData); |
|
412 |
+ } else { |
|
413 |
+ if(EC32(section_hdr[i].VirtualAddress) < min) |
|
414 |
+ min = EC32(section_hdr[i].VirtualAddress); |
|
411 | 415 |
|
412 |
- cli_dbgmsg("WinZip section\n"); |
|
413 |
- ddump(desc, ptrd, section_hdr.SizeOfRawData, cli_gentemp(NULL)); |
|
416 |
+ if(EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData) > max) |
|
417 |
+ max = EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData); |
|
414 | 418 |
} |
415 |
-*/ |
|
416 |
- |
|
417 | 419 |
} |
418 | 420 |
|
419 | 421 |
if(fstat(desc, &sb) == -1) { |
... | ... |
@@ -423,7 +358,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
423 | 423 |
} |
424 | 424 |
|
425 | 425 |
if((ep = cli_rawaddr(EC32(optional_hdr.AddressOfEntryPoint), section_hdr, nsections)) == -1) { |
426 |
- cli_dbgmsg("Possibly broken PE file - Entry Point @%d out of file.\n", ep); |
|
426 |
+ cli_dbgmsg("Possibly broken PE file\n"); |
|
427 | 427 |
broken = 1; |
428 | 428 |
} |
429 | 429 |
|
... | ... |
@@ -454,9 +389,6 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
454 | 454 |
} |
455 | 455 |
|
456 | 456 |
if(found) { |
457 |
- int ssize, dsize; |
|
458 |
- char *src, *dest; |
|
459 |
- |
|
460 | 457 |
strncpy(sname, section_hdr[i].Name, 8); |
461 | 458 |
sname[8] = 0; |
462 | 459 |
cli_dbgmsg("UPX: Section %d name: %s\n", i, sname); |
... | ... |
@@ -483,7 +415,6 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
483 | 483 |
return CL_CLEAN; |
484 | 484 |
} |
485 | 485 |
|
486 |
- |
|
487 | 486 |
/* FIXME: use file operations in case of big files */ |
488 | 487 |
if((src = (char *) cli_malloc(ssize)) == NULL) { |
489 | 488 |
free(section_hdr); |
... | ... |
@@ -590,6 +521,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
590 | 590 |
tempfile = cli_gentemp(NULL); |
591 | 591 |
if((ndesc = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU)) < 0) { |
592 | 592 |
cli_dbgmsg("UPX: Can't create file %s\n", tempfile); |
593 |
+ free(tempfile); |
|
593 | 594 |
free(section_hdr); |
594 | 595 |
free(src); |
595 | 596 |
free(dest); |
... | ... |
@@ -598,6 +530,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
598 | 598 |
|
599 | 599 |
if(write(ndesc, dest, dsize) != dsize) { |
600 | 600 |
cli_dbgmsg("Can't write %d bytes\n", dsize); |
601 |
+ free(tempfile); |
|
601 | 602 |
free(section_hdr); |
602 | 603 |
free(src); |
603 | 604 |
free(dest); |
... | ... |
@@ -621,6 +554,100 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
621 | 621 |
free(dest); |
622 | 622 |
} |
623 | 623 |
|
624 |
+ /* Petite */ |
|
625 |
+ |
|
626 |
+ /* |
|
627 |
+ found = 2; |
|
628 |
+ |
|
629 |
+ lseek(desc, ep, SEEK_SET); |
|
630 |
+ if(read(desc, buff, 200) != 200) |
|
631 |
+ return CL_EIO; |
|
632 |
+ |
|
633 |
+ if(buff[0] != '\xb8' || cli_readint32(buff + 1) != EC32(section_hdr[nsections - 1].VirtualAddress) + EC32(optional_hdr.ImageBase)) { |
|
634 |
+ if(buff[0] != '\xb8' || cli_readint32(buff + 1) != EC32(section_hdr[nsections - 2].VirtualAddress) + EC32(optional_hdr.ImageBase)) |
|
635 |
+ found = 0; |
|
636 |
+ else |
|
637 |
+ found = 1; |
|
638 |
+ } |
|
639 |
+ |
|
640 |
+ if(found) { |
|
641 |
+ cli_dbgmsg("Petite: v2.%d compression detected\n", found); |
|
642 |
+ |
|
643 |
+ if(cli_readint32(buff + 0x80) == 0x163c988d) { |
|
644 |
+ cli_dbgmsg("Petite: level zero compression is not supported yet\n"); |
|
645 |
+ } else { |
|
646 |
+ dsize = max - min; |
|
647 |
+ |
|
648 |
+ if(limits && limits->maxfilesize && dsize > limits->maxfilesize) { |
|
649 |
+ cli_dbgmsg("Petite: Size exceeded (dsize: %d, max: %lu)\n", dsize, limits->maxfilesize); |
|
650 |
+ free(section_hdr); |
|
651 |
+ return CL_CLEAN; |
|
652 |
+ } |
|
653 |
+ |
|
654 |
+ if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
655 |
+ cli_dbgmsg("Petite: Can't allocate %d bytes\n", dsize); |
|
656 |
+ free(section_hdr); |
|
657 |
+ return CL_EMEM; |
|
658 |
+ } |
|
659 |
+ |
|
660 |
+ for(i = 0 ; i < nsections; i++) { |
|
661 |
+ lseek(desc, cli_rawaddr(EC32(section_hdr[i].VirtualAddress), section_hdr, nsections), SEEK_SET); |
|
662 |
+ read(desc, dest + EC32(section_hdr[i].VirtualAddress) - min, EC32(section_hdr[i].SizeOfRawData)); |
|
663 |
+ } |
|
664 |
+ |
|
665 |
+ tempfile = cli_gentemp(NULL); |
|
666 |
+ if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) { |
|
667 |
+ cli_dbgmsg("Petite: Can't create file %s\n", tempfile); |
|
668 |
+ free(tempfile); |
|
669 |
+ free(section_hdr); |
|
670 |
+ free(dest); |
|
671 |
+ return CL_EIO; |
|
672 |
+ } |
|
673 |
+ |
|
674 |
+ switch(petite_inflate2x_1to9(dest, min, max - min, section_hdr, |
|
675 |
+ nsections, EC32(optional_hdr.ImageBase), ep, ndesc, |
|
676 |
+ found, EC32(optional_hdr.DataDirectory[2].VirtualAddress), |
|
677 |
+ EC32(optional_hdr.DataDirectory[2].Size))) { |
|
678 |
+ case 1: |
|
679 |
+ cli_dbgmsg("Petite: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
680 |
+ break; |
|
681 |
+ |
|
682 |
+ case 0: |
|
683 |
+ cli_dbgmsg("Petite: Unpacked data saved in %s\n", tempfile); |
|
684 |
+ break; |
|
685 |
+ |
|
686 |
+ default: |
|
687 |
+ cli_dbgmsg("Petite: Unpacking failed\n"); |
|
688 |
+ } |
|
689 |
+ |
|
690 |
+ free(dest); |
|
691 |
+ fsync(ndesc); |
|
692 |
+ lseek(ndesc, 0, SEEK_SET); |
|
693 |
+ |
|
694 |
+ if(cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) { |
|
695 |
+ free(section_hdr); |
|
696 |
+ close(ndesc); |
|
697 |
+ if(!cli_leavetemps_flag) { |
|
698 |
+ unlink(tempfile); |
|
699 |
+ free(tempfile); |
|
700 |
+ } else { |
|
701 |
+ free(tempfile); |
|
702 |
+ } |
|
703 |
+ return CL_VIRUS; |
|
704 |
+ } |
|
705 |
+ |
|
706 |
+ close(ndesc); |
|
707 |
+ |
|
708 |
+ if(!cli_leavetemps_flag) { |
|
709 |
+ unlink(tempfile); |
|
710 |
+ free(tempfile); |
|
711 |
+ } else { |
|
712 |
+ free(tempfile); |
|
713 |
+ } |
|
714 |
+ } |
|
715 |
+ } |
|
716 |
+ */ |
|
717 |
+ |
|
624 | 718 |
/* to be continued ... */ |
625 | 719 |
|
626 | 720 |
free(section_hdr); |
... | ... |
@@ -1,6 +1,9 @@ |
1 | 1 |
/* |
2 | 2 |
* Copyright (C) 2004 Tomasz Kojm <tkojm@clamav.net> |
3 | 3 |
* |
4 |
+ * Implementation (header structures) based on the PE format description |
|
5 |
+ * by B. Luevelsmeyer |
|
6 |
+ * |
|
4 | 7 |
* This program is free software; you can redistribute it and/or modify |
5 | 8 |
* it under the terms of the GNU General Public License as published by |
6 | 9 |
* the Free Software Foundation; either version 2 of the License, or |
... | ... |
@@ -21,6 +24,75 @@ |
21 | 21 |
|
22 | 22 |
#include "clamav.h" |
23 | 23 |
|
24 |
+struct pe_image_file_hdr { |
|
25 |
+ uint32_t Magic; |
|
26 |
+ uint16_t Machine; |
|
27 |
+ uint16_t NumberOfSections; |
|
28 |
+ uint32_t TimeDateStamp; /* unreliable */ |
|
29 |
+ uint32_t PointerToSymbolTable; /* debug */ |
|
30 |
+ uint32_t NumberOfSymbols; /* debug */ |
|
31 |
+ uint16_t SizeOfOptionalHeader; /* == 224 */ |
|
32 |
+ uint16_t Characteristics; |
|
33 |
+}; |
|
34 |
+ |
|
35 |
+struct pe_image_data_dir { |
|
36 |
+ uint32_t VirtualAddress; |
|
37 |
+ uint32_t Size; |
|
38 |
+}; |
|
39 |
+ |
|
40 |
+struct pe_image_optional_hdr { |
|
41 |
+ uint16_t Magic; |
|
42 |
+ uint8_t MajorLinkerVersion; /* unreliable */ |
|
43 |
+ uint8_t MinorLinkerVersion; /* unreliable */ |
|
44 |
+ uint32_t SizeOfCode; /* unreliable */ |
|
45 |
+ uint32_t SizeOfInitializedData; /* unreliable */ |
|
46 |
+ uint32_t SizeOfUninitializedData; /* unreliable */ |
|
47 |
+ uint32_t AddressOfEntryPoint; |
|
48 |
+ uint32_t BaseOfCode; |
|
49 |
+ uint32_t BaseOfData; |
|
50 |
+ uint32_t ImageBase; /* multiple of 64 KB */ |
|
51 |
+ uint32_t SectionAlignment; /* usually 32 or 4096 */ |
|
52 |
+ uint32_t FileAlignment; /* usually 32 or 512 */ |
|
53 |
+ uint16_t MajorOperatingSystemVersion; /* not used */ |
|
54 |
+ uint16_t MinorOperatingSystemVersion; /* not used */ |
|
55 |
+ uint16_t MajorImageVersion; /* unreliable */ |
|
56 |
+ uint16_t MinorImageVersion; /* unreliable */ |
|
57 |
+ uint16_t MajorSubsystemVersion; |
|
58 |
+ uint16_t MinorSubsystemVersion; |
|
59 |
+ uint32_t Win32VersionValue; /* ? */ |
|
60 |
+ uint32_t SizeOfImage; |
|
61 |
+ uint32_t SizeOfHeaders; |
|
62 |
+ uint32_t CheckSum; /* NT drivers only */ |
|
63 |
+ uint16_t Subsystem; |
|
64 |
+ uint16_t DllCharacteristics; |
|
65 |
+ uint32_t SizeOfStackReserve; |
|
66 |
+ uint32_t SizeOfStackCommit; |
|
67 |
+ uint32_t SizeOfHeapReserve; |
|
68 |
+ uint32_t SizeOfHeapCommit; |
|
69 |
+ uint32_t LoaderFlags; /* ? */ |
|
70 |
+ uint32_t NumberOfRvaAndSizes; /* unreliable */ |
|
71 |
+ struct pe_image_data_dir DataDirectory[16]; |
|
72 |
+}; |
|
73 |
+ |
|
74 |
+struct pe_image_section_hdr { |
|
75 |
+ uint8_t Name[8]; /* may not end with NULL */ |
|
76 |
+ /* |
|
77 |
+ union { |
|
78 |
+ uint32_t PhysicalAddress; |
|
79 |
+ uint32_t VirtualSize; |
|
80 |
+ } AddrSize; |
|
81 |
+ */ |
|
82 |
+ uint32_t VirtualSize; |
|
83 |
+ uint32_t VirtualAddress; |
|
84 |
+ uint32_t SizeOfRawData; /* multiple of FileAlignment */ |
|
85 |
+ uint32_t PointerToRawData; /* offset to the section's data */ |
|
86 |
+ uint32_t PointerToRelocations; /* object files only */ |
|
87 |
+ uint32_t PointerToLinenumbers; /* object files only */ |
|
88 |
+ uint16_t NumberOfRelocations; /* object files only */ |
|
89 |
+ uint16_t NumberOfLinenumbers; /* object files only */ |
|
90 |
+ uint32_t Characteristics; |
|
91 |
+}; |
|
92 |
+ |
|
24 | 93 |
int cli_scanpe(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *arec, int *mrec); |
25 | 94 |
|
26 | 95 |
#endif |
27 | 96 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,455 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2004 aCaB <acab@clamav.net> |
|
2 |
+ * |
|
3 |
+ * This program is free software; you can redistribute it and/or modify |
|
4 |
+ * it under the terms of the GNU General Public License as published by |
|
5 |
+ * the Free Software Foundation; either version 2 of the License, or |
|
6 |
+ * (at your option) any later version. |
|
7 |
+ * |
|
8 |
+ * This program is distributed in the hope that it will be useful, |
|
9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 |
+ * GNU General Public License for more details. |
|
12 |
+ * |
|
13 |
+ * You should have received a copy of the GNU General Public License |
|
14 |
+ * along with this program; if not, write to the Free Software |
|
15 |
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+/* |
|
19 |
+** petitep.c |
|
20 |
+** |
|
21 |
+** 09/07/2k4 - Dumped and reversed |
|
22 |
+** 10/07/2k4 - Very 1st approach |
|
23 |
+** 10/07/2k4 - PE stuff and main loop |
|
24 |
+** 11/07/2k4 - Porting finished, tracking my bugs... |
|
25 |
+** 12/07/2k4 - ARRRRRGHHH :D |
|
26 |
+** 14/07/2k4 - Code cleaned |
|
27 |
+** 15/07/2k4 - Securing && ClamAV porting |
|
28 |
+** 21/07/2k4 - Unmangled imports now supported |
|
29 |
+** 22/07/2k4 - Unstripped .relocs now supported |
|
30 |
+** |
|
31 |
+*/ |
|
32 |
+ |
|
33 |
+/* |
|
34 |
+** Unpacks a buffer containing a petite 2.2 compressed |
|
35 |
+** file. Doesn't perform Import Table unmangling. Doesn't |
|
36 |
+** fixup call/jumps. Tries to "guess" the original sections |
|
37 |
+** structure and entrypoint. |
|
38 |
+** |
|
39 |
+** Lotta phanx to Micky for patiently bearing my screams :P |
|
40 |
+** Greets to Ian Luck: the SEH MOVSB thingy almost got me :O |
|
41 |
+** TODO: Cope with level 0 and older petite versions. |
|
42 |
+*/ |
|
43 |
+ |
|
44 |
+ |
|
45 |
+#if HAVE_CONFIG_H |
|
46 |
+#include "clamav-config.h" |
|
47 |
+#endif |
|
48 |
+ |
|
49 |
+#include <stdio.h> |
|
50 |
+#include <stdlib.h> |
|
51 |
+#include <sys/types.h> |
|
52 |
+#include <sys/stat.h> |
|
53 |
+#include <unistd.h> |
|
54 |
+#include <string.h> |
|
55 |
+ |
|
56 |
+#include "cltypes.h" |
|
57 |
+#include "pe.h" |
|
58 |
+#include "rebuildpe.h" |
|
59 |
+#include "others.h" |
|
60 |
+ |
|
61 |
+#if WORDS_BIGENDIAN == 0 |
|
62 |
+#define EC16(v) (v) |
|
63 |
+#define EC32(v) (v) |
|
64 |
+#else |
|
65 |
+static inline uint16_t EC16(uint16_t v) |
|
66 |
+{ |
|
67 |
+ return ((v >> 8) + (v << 8)); |
|
68 |
+} |
|
69 |
+ |
|
70 |
+static inline uint32_t EC32(uint32_t v) |
|
71 |
+{ |
|
72 |
+ return ((v >> 24) | ((v & 0x00FF0000) >> 8) | ((v & 0x0000FF00) << 8) | (v << 24)); |
|
73 |
+} |
|
74 |
+#endif |
|
75 |
+ |
|
76 |
+static int doubledl(char **scur, uint8_t *mydlptr, char *buffer, int buffersize) |
|
77 |
+{ |
|
78 |
+ unsigned char mydl = *mydlptr; |
|
79 |
+ unsigned char olddl = mydl; |
|
80 |
+ |
|
81 |
+ mydl*=2; |
|
82 |
+ if ( !(olddl & 0x7f)) { |
|
83 |
+ if ( *scur < buffer || *scur >= buffer+buffersize-1 ) |
|
84 |
+ return -1; |
|
85 |
+ olddl = **scur; |
|
86 |
+ mydl = olddl*2+1; |
|
87 |
+ *scur=*scur + 1; |
|
88 |
+ } |
|
89 |
+ *mydlptr = mydl; |
|
90 |
+ return (olddl>>7)&1; |
|
91 |
+} |
|
92 |
+ |
|
93 |
+int petite_inflate2x_1to9(char *buf, uint32_t minrva, int bufsz, struct pe_image_section_hdr *sections, int sectcount, uint32_t Imagebase, uint32_t pep, int desc, int version, uint32_t ResRva, uint32_t ResSize) |
|
94 |
+{ |
|
95 |
+ char *adjbuf = buf - minrva; |
|
96 |
+ char *packed = NULL; |
|
97 |
+ uint32_t thisrva=0, bottom = 0, enc_ep=0, irva=0, workdone=0, grown=0x355, skew=0x35; |
|
98 |
+ int j = 0, oob, mangled = 0, check4resources=0; |
|
99 |
+ struct SECTION *usects = NULL; |
|
100 |
+ |
|
101 |
+ /* |
|
102 |
+ -] The real thing [- |
|
103 |
+ */ |
|
104 |
+ |
|
105 |
+ /* NOTE: (435063->4350a5) Petite kernel32!imports and error strings */ |
|
106 |
+ |
|
107 |
+ /* Here we adjust the start of packed blob, the size of petite code, |
|
108 |
+ * the difference in size if relocs were stripped |
|
109 |
+ * See below... |
|
110 |
+ */ |
|
111 |
+ |
|
112 |
+ if ( version == 2 ) |
|
113 |
+ packed = adjbuf + EC32(sections[sectcount-1].VirtualAddress) + 0x1b8; |
|
114 |
+ if ( version == 1 ) { |
|
115 |
+ packed = adjbuf + EC32(sections[sectcount-1].VirtualAddress) + 0x178; |
|
116 |
+ grown=0x323; /* My name is Harry potter */ |
|
117 |
+ skew=0x34; |
|
118 |
+ } |
|
119 |
+ |
|
120 |
+ while (1) { |
|
121 |
+ char *ssrc, *ddst; |
|
122 |
+ uint32_t size, srva; |
|
123 |
+ int backbytes, oldback, backsize, addsize; |
|
124 |
+ |
|
125 |
+ if ( packed < buf || packed >= buf+bufsz-4) |
|
126 |
+ return -1; |
|
127 |
+ srva = cli_readint32(packed); |
|
128 |
+ |
|
129 |
+ if (! srva) { |
|
130 |
+ /* WERE DONE !!! :D */ |
|
131 |
+ int t, upd = 1; |
|
132 |
+ |
|
133 |
+ if ( j <= 0 ) /* Some non petite compressed files will get here */ |
|
134 |
+ return -1; |
|
135 |
+ |
|
136 |
+ /* Select * from sections order by rva asc; */ |
|
137 |
+ while ( upd ) { |
|
138 |
+ upd = 0; |
|
139 |
+ for (t = 0; t < j-1 ; t++) { |
|
140 |
+ uint32_t trva, trsz, tvsz; |
|
141 |
+ |
|
142 |
+ if ( usects[t].rva < usects[t+1].rva ) |
|
143 |
+ continue; |
|
144 |
+ trva = usects[t].rva; |
|
145 |
+ trsz = usects[t].rsz; |
|
146 |
+ tvsz = usects[t].vsz; |
|
147 |
+ usects[t].rva = usects[t+1].rva; |
|
148 |
+ usects[t].rsz = usects[t+1].rsz; |
|
149 |
+ usects[t].vsz = usects[t+1].vsz; |
|
150 |
+ usects[t+1].rva = trva; |
|
151 |
+ usects[t+1].rsz = trsz; |
|
152 |
+ usects[t+1].vsz = tvsz; |
|
153 |
+ upd = 1; |
|
154 |
+ } |
|
155 |
+ } |
|
156 |
+ |
|
157 |
+ /* Computes virtualsize... we try to guess, actually :O */ |
|
158 |
+ for (t = 0; t < j-1 ; t++) { |
|
159 |
+ if ( usects[t].vsz != usects[t+1].rva - usects[t].rva ) |
|
160 |
+ usects[t].vsz = usects[t+1].rva - usects[t].rva; |
|
161 |
+ } |
|
162 |
+ |
|
163 |
+ /* |
|
164 |
+ * Our encryption is pathetic and out software is lame but |
|
165 |
+ * we need to claim it's unbreakable. |
|
166 |
+ * So why dont we just mangle the imports and encrypt the EP?! |
|
167 |
+ */ |
|
168 |
+ |
|
169 |
+ /* Decrypts old entrypoint if we got enough clues */ |
|
170 |
+ if (enc_ep) { |
|
171 |
+ uint32_t virtaddr = pep + 5 + Imagebase, tmpep; |
|
172 |
+ int rndm = 0, dummy = 1; |
|
173 |
+ uint32_t *thunk = (uint32_t*)(adjbuf+irva); |
|
174 |
+ uint32_t *imports; |
|
175 |
+ |
|
176 |
+ if ( version == 2 ) { /* 2.2 onley */ |
|
177 |
+ |
|
178 |
+ while ( (char *)thunk >=buf && (char *)thunk<buf+bufsz-4 && dummy ) { |
|
179 |
+ uint32_t api; |
|
180 |
+ |
|
181 |
+ if (! *thunk ) { |
|
182 |
+ workdone = 1; |
|
183 |
+ break; |
|
184 |
+ } |
|
185 |
+ |
|
186 |
+ imports = (uint32_t *) (adjbuf + *thunk++); |
|
187 |
+ dummy = 0; |
|
188 |
+ |
|
189 |
+ while ( (char *)imports >=buf && (char *)imports<buf+bufsz-4 ) { |
|
190 |
+ dummy = 0; |
|
191 |
+ if ( ! (api = *imports++) ) { |
|
192 |
+ dummy = 1; |
|
193 |
+ break; |
|
194 |
+ } |
|
195 |
+ if ( (api != (api | 0x80000000)) && mangled && --rndm < 0) { |
|
196 |
+ api = virtaddr; |
|
197 |
+ virtaddr +=5; /* EB + 1 double */ |
|
198 |
+ rndm = virtaddr & 7; |
|
199 |
+ } else { |
|
200 |
+ api = 0xbff01337; /* KERNEL32!leet */ |
|
201 |
+ } |
|
202 |
+ if (EC32(sections[sectcount-1].VirtualAddress)+Imagebase < api ) |
|
203 |
+ enc_ep--; |
|
204 |
+ if ( api < virtaddr ) |
|
205 |
+ enc_ep--; |
|
206 |
+ tmpep = (enc_ep & 0xfffffff8)>>3 & 0x1fffffff; |
|
207 |
+ enc_ep = (enc_ep & 7)<<29 | tmpep; |
|
208 |
+ } |
|
209 |
+ } |
|
210 |
+ } else |
|
211 |
+ workdone = 1; |
|
212 |
+ enc_ep = pep+5+enc_ep; |
|
213 |
+ if ( workdone == 1 ) |
|
214 |
+ cli_dbgmsg("Petite: Old EP: %x\n", enc_ep); |
|
215 |
+ else |
|
216 |
+ cli_dbgmsg("Petite: In troubles while attempting to decrypt old EP\n"); |
|
217 |
+ } |
|
218 |
+ |
|
219 |
+ /* Let's compact data */ |
|
220 |
+ for (t = 1; t < j ; t++) { |
|
221 |
+ usects[t].raw = usects[t-1].raw + usects[t-1].rsz; |
|
222 |
+ if (usects[t].rsz != 0) |
|
223 |
+ memmove(buf + usects[t].raw, adjbuf + usects[t].rva, usects[t].rsz); |
|
224 |
+ } |
|
225 |
+ |
|
226 |
+ /* Showtime!!! */ |
|
227 |
+ cli_dbgmsg("Petite: Sections dump:\n"); |
|
228 |
+ for (t = 0; t < j ; t++) |
|
229 |
+ cli_dbgmsg("Petite: .SECT%d RVA:%x VSize:%x ROffset: %x, RSize:% x\n", t, usects[t].rva, usects[t].vsz, usects[t].raw, usects[t].rsz); |
|
230 |
+ if ( (ssrc = rebuildpe(buf, usects, j, Imagebase, enc_ep, ResRva, ResSize)) ) { |
|
231 |
+ write(desc, ssrc, 0x148+0x80+0x28*j+usects[j-1].raw+usects[j-1].rsz); |
|
232 |
+ free(ssrc); |
|
233 |
+ } else |
|
234 |
+ cli_dbgmsg("Petite: Rebuilding failed\n"); |
|
235 |
+ |
|
236 |
+ return workdone; |
|
237 |
+ } |
|
238 |
+ |
|
239 |
+ |
|
240 |
+ size = srva & 0x7fffffff; |
|
241 |
+ if ( srva != size ) { /* Test and clear bit 31 */ |
|
242 |
+ check4resources=0; |
|
243 |
+ /* |
|
244 |
+ Enumerates each petite data section |
|
245 |
+ I should get here once ot twice: |
|
246 |
+ - 1 time for the resource section (if present) |
|
247 |
+ - 1 time for the all_the_rest section |
|
248 |
+ */ |
|
249 |
+ |
|
250 |
+ if ( packed < buf || packed >= buf+bufsz-12) |
|
251 |
+ return -1; |
|
252 |
+ /* Save the end of current packed section for later use */ |
|
253 |
+ bottom = cli_readint32(packed+8) + 4; |
|
254 |
+ ssrc = adjbuf + cli_readint32(packed+4) - (size-1)*4; |
|
255 |
+ ddst = adjbuf + cli_readint32(packed+8) - (size-1)*4; |
|
256 |
+ |
|
257 |
+ if ( ssrc < buf || ssrc + size*4 >= buf + bufsz || ddst < buf || ddst + size*4 >= buf + bufsz ) |
|
258 |
+ return -1; |
|
259 |
+ |
|
260 |
+ /* Copy packed data to the end of the current packed section */ |
|
261 |
+ memmove(ddst, ssrc, size*4); |
|
262 |
+ packed += 0x0c; |
|
263 |
+ } else { |
|
264 |
+ uint32_t check1, check2; |
|
265 |
+ uint8_t mydl = 0; |
|
266 |
+ uint8_t goback; |
|
267 |
+ |
|
268 |
+ /* Unpak each original section in turn */ |
|
269 |
+ |
|
270 |
+ if ( packed < buf || packed >= buf+bufsz-16) |
|
271 |
+ return -1; |
|
272 |
+ |
|
273 |
+ size = cli_readint32(packed+4); /* How many bytes to unpack */ |
|
274 |
+ packed += 0x10; |
|
275 |
+ thisrva=cli_readint32(packed-8); /* RVA of the original section */ |
|
276 |
+ |
|
277 |
+ /* Alloc 1 more struct */ |
|
278 |
+ if ( ! (usects = (struct SECTION *) realloc(usects, sizeof(struct SECTION) * (j+1))) ) |
|
279 |
+ return -1; |
|
280 |
+ |
|
281 |
+ /* Save section spex for later rebuilding */ |
|
282 |
+ usects[j].rva = thisrva; |
|
283 |
+ usects[j].rsz = size; |
|
284 |
+ if ( (int)(bottom - thisrva) >0 ) |
|
285 |
+ usects[j].vsz = bottom - thisrva; |
|
286 |
+ else |
|
287 |
+ usects[j].vsz = size; |
|
288 |
+ usects[j].raw = 0; /* Cheaper than memset */ |
|
289 |
+ |
|
290 |
+ if (!size) { /* That's a ghost section! reloc any1? :P */ |
|
291 |
+ j++; |
|
292 |
+ continue; |
|
293 |
+ } |
|
294 |
+ |
|
295 |
+ ssrc = adjbuf + srva; |
|
296 |
+ ddst = adjbuf + thisrva; |
|
297 |
+ |
|
298 |
+ /* Last petite section (unpacked 1st) could contain unpacked data |
|
299 |
+ * (eg the icon): let's fix the rva |
|
300 |
+ */ |
|
301 |
+ |
|
302 |
+ if (!check4resources) { |
|
303 |
+ int q; |
|
304 |
+ for ( q = 0 ; q < sectcount ; q++ ) { |
|
305 |
+ if ( thisrva <= EC32(sections[q].VirtualAddress) || thisrva >= EC32(sections[q].VirtualAddress) + EC32(sections[q].VirtualSize)) |
|
306 |
+ continue; |
|
307 |
+ usects[j].rva = EC32(sections[q].VirtualAddress); |
|
308 |
+ usects[j].rsz = thisrva - EC32(sections[q].VirtualAddress) + size; |
|
309 |
+ break; |
|
310 |
+ } |
|
311 |
+ } |
|
312 |
+ |
|
313 |
+ /* Increase count of unpacked sections */ |
|
314 |
+ j++; |
|
315 |
+ |
|
316 |
+ |
|
317 |
+ /* Setup some crap for later checks */ |
|
318 |
+ if ( size < 0x10000 ) { |
|
319 |
+ check1 = 0x0FFFFC060; |
|
320 |
+ check2 = 0x0FFFFFC60; |
|
321 |
+ goback = 5; |
|
322 |
+ } else if ( size < 0x40000 ) { |
|
323 |
+ check1 = 0x0FFFF8180; |
|
324 |
+ check2 = 0x0FFFFF980; |
|
325 |
+ goback = 7; |
|
326 |
+ } else { |
|
327 |
+ check1 = 0x0FFFF8300; |
|
328 |
+ check2 = 0x0FFFFFB00; |
|
329 |
+ goback = 8; |
|
330 |
+ } |
|
331 |
+ |
|
332 |
+ /* |
|
333 |
+ * NOTE: on last loop we get esi=edi=ImageBase (which is not writeable) |
|
334 |
+ * The movsb on the next line causes the iat_rebuild_and_decrypt_oldEP() |
|
335 |
+ * func to get called instead... ehehe very smart ;) |
|
336 |
+ */ |
|
337 |
+ |
|
338 |
+ if ( ddst < buf || ddst >= buf+bufsz-1 || ssrc < buf || ssrc >= buf+bufsz-1 ) |
|
339 |
+ return -1; |
|
340 |
+ |
|
341 |
+ size--; |
|
342 |
+ *ddst++=*ssrc++; /* eheh u C gurus gotta luv these monsters :P */ |
|
343 |
+ backbytes=0; |
|
344 |
+ oldback = 0; |
|
345 |
+ |
|
346 |
+ /* No surprises here... NRV any1??? ;) */ |
|
347 |
+ while (size > 0) { |
|
348 |
+ oob = doubledl(&ssrc, &mydl, buf, bufsz); |
|
349 |
+ if ( oob == -1 ) |
|
350 |
+ return -1; |
|
351 |
+ if (!oob) { |
|
352 |
+ if ( ddst < buf || ddst >= buf+bufsz-1 || ssrc < buf || ssrc >= buf+bufsz-1 ) |
|
353 |
+ return -1; |
|
354 |
+ *ddst++ = (char)((*ssrc++)^(size & 0xff)); |
|
355 |
+ size--; |
|
356 |
+ } else { |
|
357 |
+ addsize = 0; |
|
358 |
+ backbytes++; |
|
359 |
+ while (1) { |
|
360 |
+ if ( (oob = doubledl(&ssrc, &mydl, buf, bufsz)) == -1 ) |
|
361 |
+ return -1; |
|
362 |
+ backbytes = backbytes*2 + oob; |
|
363 |
+ if ( (oob = doubledl(&ssrc, &mydl, buf, bufsz)) == -1 ) |
|
364 |
+ return -1; |
|
365 |
+ if (!oob) |
|
366 |
+ break; |
|
367 |
+ } |
|
368 |
+ backbytes -= 3; |
|
369 |
+ if ( backbytes >= 0 ) { |
|
370 |
+ backsize = goback; |
|
371 |
+ do { |
|
372 |
+ if ( (oob = doubledl(&ssrc, &mydl, buf, bufsz)) == -1 ) |
|
373 |
+ return -1; |
|
374 |
+ backbytes = backbytes*2 + oob; |
|
375 |
+ backsize--; |
|
376 |
+ } while (backsize); |
|
377 |
+ backbytes^=0xffffffff; |
|
378 |
+ addsize += 1 + ( backbytes < check2 ) + ( backbytes < check1 ); |
|
379 |
+ oldback = backbytes; |
|
380 |
+ } else { |
|
381 |
+ backsize = backbytes+1; |
|
382 |
+ backbytes = oldback; |
|
383 |
+ } |
|
384 |
+ |
|
385 |
+ if ( (oob = doubledl(&ssrc, &mydl, buf, bufsz)) == -1 ) |
|
386 |
+ return -1; |
|
387 |
+ backsize = backsize*2 + oob; |
|
388 |
+ if ( (oob = doubledl(&ssrc, &mydl, buf, bufsz)) == -1 ) |
|
389 |
+ return -1; |
|
390 |
+ backsize = backsize*2 + oob; |
|
391 |
+ if (!backsize) { |
|
392 |
+ backsize++; |
|
393 |
+ while (1) { |
|
394 |
+ if ( (oob = doubledl(&ssrc, &mydl, buf, bufsz)) == -1 ) |
|
395 |
+ return -1; |
|
396 |
+ backsize = backsize*2 + oob; |
|
397 |
+ if ( (oob = doubledl(&ssrc, &mydl, buf, bufsz)) == -1 ) |
|
398 |
+ return -1; |
|
399 |
+ if (!oob) |
|
400 |
+ break; |
|
401 |
+ } |
|
402 |
+ backsize+=2; |
|
403 |
+ } |
|
404 |
+ backsize+=addsize; |
|
405 |
+ size-=backsize; |
|
406 |
+ if ( ddst<buf || ddst+backsize>=buf+bufsz || ddst+backbytes<buf || ddst+backbytes+backsize>=buf+bufsz ) |
|
407 |
+ return -1; |
|
408 |
+ while(backsize--) { |
|
409 |
+ *ddst=*(ddst+backbytes); |
|
410 |
+ ddst++; |
|
411 |
+ } |
|
412 |
+ backbytes=0; |
|
413 |
+ backsize=0; |
|
414 |
+ } /* else */ |
|
415 |
+ } /* while(ebx) */ |
|
416 |
+ |
|
417 |
+ /* Any lame petite code here? If so let's strip it |
|
418 |
+ * We've done version adjustments already, see above |
|
419 |
+ */ |
|
420 |
+ |
|
421 |
+ if ( j && |
|
422 |
+ ( /* LONG MAGIC = 33C05E64 8B188B1B 8D63D65D */ |
|
423 |
+ ( (usects[j-1].rsz > grown ) && |
|
424 |
+ cli_readint32(ddst-grown+5+0x4f) == 0x645ec033 && |
|
425 |
+ cli_readint32(ddst-grown+5+0x4f+4) == 0x1b8b188b ) |
|
426 |
+ || |
|
427 |
+ /* This crap is ugly! Gotta make it all pretty one day or another */ |
|
428 |
+ ( (usects[j-1].rsz > grown+skew ) && |
|
429 |
+ cli_readint32(ddst-grown+5+0x4f-skew) == 0x645ec033 && |
|
430 |
+ cli_readint32(ddst-grown+5+0x4f+4-skew) == 0x1b8b188b ) |
|
431 |
+ ) |
|
432 |
+ ) |
|
433 |
+ { |
|
434 |
+ uint32_t test1, test2; |
|
435 |
+ /* If the original exe had a .reloc were skewed */ |
|
436 |
+ int reloc = skew*(cli_readint32(ddst-grown+5+0x4f-skew) == 0x645ec033); |
|
437 |
+ |
|
438 |
+ /* REMINDER: DON'T BPX IN HERE U DUMBASS!!!!!!!!!!!!!!!!!!!!!!!! */ |
|
439 |
+ test1 = cli_readint32(ddst-grown+0x0f-8-reloc)^0x9d6661aa; |
|
440 |
+ test2 = cli_readint32(ddst-grown+0x0f-4-reloc)^0xe908c483; |
|
441 |
+ cli_dbgmsg("Petite: Found petite code in sect%d(%x). Let's strip it.\n", j-1, usects[j-1].rva); |
|
442 |
+ if (test1 == test2) { |
|
443 |
+ irva = cli_readint32(ddst-grown+0x121-reloc); |
|
444 |
+ enc_ep = cli_readint32(ddst-grown+0x0f-reloc)^test1; |
|
445 |
+ mangled = (cli_readint32(ddst-grown+0x1c0-reloc) != 0x90909090); /* FIXME: Magic's too short??? */ |
|
446 |
+ cli_dbgmsg("Petite: Encrypted EP: %x | Array of imports: %x\n",enc_ep, irva); |
|
447 |
+ } |
|
448 |
+ usects[j-1].rsz -= grown+reloc; |
|
449 |
+ |
|
450 |
+ } |
|
451 |
+ check4resources++; |
|
452 |
+ } /* outer else */ |
|
453 |
+ } /* while true */ |
|
454 |
+} |
0 | 455 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,27 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2004 aCaB <acab@clamav.net> |
|
2 |
+ * |
|
3 |
+ * This program is free software; you can redistribute it and/or modify |
|
4 |
+ * it under the terms of the GNU General Public License as published by |
|
5 |
+ * the Free Software Foundation; either version 2 of the License, or |
|
6 |
+ * (at your option) any later version. |
|
7 |
+ * |
|
8 |
+ * This program is distributed in the hope that it will be useful, |
|
9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 |
+ * GNU General Public License for more details. |
|
12 |
+ * |
|
13 |
+ * You should have received a copy of the GNU General Public License |
|
14 |
+ * along with this program; if not, write to the Free Software |
|
15 |
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+#ifndef __PETITE_H |
|
19 |
+#define __PETITE_H |
|
20 |
+ |
|
21 |
+#include "cltypes.h" |
|
22 |
+#include "pe.h" |
|
23 |
+ |
|
24 |
+int petite_inflate2x_1to9(char *buf, uint32_t minrva, int bufsz, struct pe_image_section_hdr *sections, int sectcount, uint32_t Imagebase, uint32_t pep, int desc, int version, uint32_t ResRva, uint32_t ResSize); |
|
25 |
+ |
|
26 |
+#endif |
0 | 27 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,153 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2004 aCaB <acab@clamav.net> |
|
2 |
+ * |
|
3 |
+ * This program is free software; you can redistribute it and/or modify |
|
4 |
+ * it under the terms of the GNU General Public License as published by |
|
5 |
+ * the Free Software Foundation; either version 2 of the License, or |
|
6 |
+ * (at your option) any later version. |
|
7 |
+ * |
|
8 |
+ * This program is distributed in the hope that it will be useful, |
|
9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 |
+ * GNU General Public License for more details. |
|
12 |
+ * |
|
13 |
+ * You should have received a copy of the GNU General Public License |
|
14 |
+ * along with this program; if not, write to the Free Software |
|
15 |
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+/* |
|
19 |
+** rebuildpe.c |
|
20 |
+** |
|
21 |
+** 28/07/2k4 - Moved out of petitep.c |
|
22 |
+** |
|
23 |
+*/ |
|
24 |
+ |
|
25 |
+/* |
|
26 |
+** Rebuilds a fully parsable / *not runnable* PE file including |
|
27 |
+** a fake MZ header, a piece of informational 16bit code, |
|
28 |
+** lookalike PE & Optional headers, an array of structures and |
|
29 |
+** of course the real content. |
|
30 |
+** Sections characteristics will have all the bits set. |
|
31 |
+** Raw alignment is a waste and therefore is not performed. |
|
32 |
+*/ |
|
33 |
+ |
|
34 |
+#include <stdio.h> |
|
35 |
+#include <string.h> |
|
36 |
+#include <stdlib.h> |
|
37 |
+ |
|
38 |
+#include "cltypes.h" |
|
39 |
+#include "rebuildpe.h" |
|
40 |
+#include "others.h" |
|
41 |
+ |
|
42 |
+#define cli_writeint32(offset,value) *(uint32_t *)(offset) = (value) |
|
43 |
+ |
|
44 |
+struct IMAGE_PE_HEADER { |
|
45 |
+ uint32_t Signature; |
|
46 |
+ /* FILE HEADER */ |
|
47 |
+ uint16_t Machine; |
|
48 |
+ uint16_t NumberOfSections; |
|
49 |
+ uint32_t TimeDateStamp; |
|
50 |
+ uint32_t PointerToSymbolTable; |
|
51 |
+ uint32_t NumberOfSymbols; |
|
52 |
+ uint16_t SizeOfOptionalHeader; |
|
53 |
+ uint16_t Characteristics; |
|
54 |
+ /* OPTIONAL HEADER */ |
|
55 |
+ uint16_t Magic; |
|
56 |
+ uint8_t MajorLinkerVersion; |
|
57 |
+ uint8_t MinorLinkerVersion; |
|
58 |
+ uint32_t SizeOfCode; |
|
59 |
+ uint32_t SizeOfInitializedData; |
|
60 |
+ uint32_t SizeOfUninitializedData; |
|
61 |
+ uint32_t AddressOfEntryPoint; |
|
62 |
+ uint32_t BaseOfCode; |
|
63 |
+ uint32_t BaseOfData; |
|
64 |
+ /* NT additional fields. */ |
|
65 |
+ uint32_t ImageBase; |
|
66 |
+ uint32_t SectionAlignment; |
|
67 |
+ uint32_t FileAlignment; |
|
68 |
+ uint16_t MajorOperatingSystemVersion; |
|
69 |
+ uint16_t MinorOperatingSystemVersion; |
|
70 |
+ uint16_t MajorImageVersion; |
|
71 |
+ uint16_t MinorImageVersion; |
|
72 |
+ uint16_t MajorSubsystemVersion; |
|
73 |
+ uint16_t MinorSubsystemVersion; |
|
74 |
+ uint32_t Win32VersionValue; |
|
75 |
+ uint32_t SizeOfImage; |
|
76 |
+ uint32_t SizeOfHeaders; |
|
77 |
+ uint32_t CheckSum; |
|
78 |
+ uint16_t Subsystem; |
|
79 |
+ uint16_t DllCharacteristics; |
|
80 |
+ uint32_t SizeOfStackReserve; |
|
81 |
+ uint32_t SizeOfStackCommit; |
|
82 |
+ uint32_t SizeOfHeapReserve; |
|
83 |
+ uint32_t SizeOfHeapCommit; |
|
84 |
+ uint32_t LoaderFlags; |
|
85 |
+ uint32_t NumberOfRvaAndSizes; |
|
86 |
+ /* IMAGE_DATA_DIRECTORY follows.... */ |
|
87 |
+}; |
|
88 |
+ |
|
89 |
+#define HEADERS "\ |
|
90 |
+\x4D\x5A\x90\x00\x02\x00\x00\x00\x04\x00\x0F\x00\xFF\xFF\x00\x00\ |
|
91 |
+\xB0\x00\x00\x00\x00\x00\x00\x00\x40\x00\x1A\x00\x00\x00\x00\x00\ |
|
92 |
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ |
|
93 |
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xD0\x00\x00\x00\ |
|
94 |
+\x0E\x1F\xB4\x09\xBA\x0D\x00\xCD\x21\xB4\x4C\xCD\x21\x54\x68\x69\ |
|
95 |
+\x73\x20\x66\x69\x6C\x65\x20\x77\x61\x73\x20\x63\x72\x65\x61\x74\ |
|
96 |
+\x65\x64\x20\x62\x79\x20\x43\x6C\x61\x6D\x41\x56\x20\x66\x6F\x72\ |
|
97 |
+\x20\x69\x6E\x74\x65\x72\x6E\x61\x6C\x20\x75\x73\x65\x20\x61\x6E\ |
|
98 |
+\x64\x20\x73\x68\x6F\x75\x6C\x64\x20\x6E\x6F\x74\x20\x62\x65\x20\ |
|
99 |
+\x72\x75\x6E\x2E\x0D\x0A\x43\x6C\x61\x6D\x41\x56\x20\x2D\x20\x41\ |
|
100 |
+\x20\x47\x50\x4C\x20\x76\x69\x72\x75\x73\x20\x73\x63\x61\x6E\x6E\ |
|
101 |
+\x65\x72\x20\x2D\x20\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\ |
|
102 |
+\x63\x6C\x61\x6D\x61\x76\x2E\x6E\x65\x74\x0D\x0A\x24\x00\x00\x00\ |
|
103 |
+\x50\x45\x00\x00\x4C\x01\xFF\xFF\x43\x4C\x41\x4D\x00\x00\x00\x00\ |
|
104 |
+\x00\x00\x00\x00\xE0\x00\x83\x8F\x0B\x01\x00\x00\x00\x10\x00\x00\ |
|
105 |
+\x00\x10\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x10\x00\x00\ |
|
106 |
+\x00\x10\x00\x00\xFF\xFF\xFF\xFF\x00\x10\x00\x00\x00\x02\x00\x00\ |
|
107 |
+\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x0A\x00\x00\x00\x00\x00\ |
|
108 |
+\x00\x10\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\ |
|
109 |
+\x00\x00\x10\x00\x00\x10\x00\x00\x00\x00\x10\x00\x00\x10\x00\x00\ |
|
110 |
+\x00\x00\x00\x00\x10\x00\x00\x00\ |
|
111 |
+" |
|
112 |
+ |
|
113 |
+char *rebuildpe(char *buffer, struct SECTION *sections, int sects, uint32_t base, uint32_t ep, uint32_t ResRva, uint32_t ResSize) |
|
114 |
+{ |
|
115 |
+ int i; |
|
116 |
+ uint32_t datasize=0, rawbase; |
|
117 |
+ char *pefile=NULL, *curpe; |
|
118 |
+ struct IMAGE_PE_HEADER *fakepe; |
|
119 |
+ |
|
120 |
+ for (i=0; i < sects; i++) |
|
121 |
+ datasize+=sections[i].rsz; |
|
122 |
+ |
|
123 |
+ rawbase = 0x148+0x80+0x28*sects; |
|
124 |
+ if((pefile = (char *) cli_malloc(rawbase+datasize))) { |
|
125 |
+ memcpy(pefile, HEADERS, 0x148); |
|
126 |
+ |
|
127 |
+ fakepe = (struct IMAGE_PE_HEADER *)(pefile+0xd0); |
|
128 |
+ fakepe->NumberOfSections=sects; |
|
129 |
+ fakepe->AddressOfEntryPoint=ep; |
|
130 |
+ fakepe->ImageBase=base; |
|
131 |
+ memset(pefile+0x148, 0, 0x80); |
|
132 |
+ *(uint32_t*)(pefile+0x148+0x10) = ResRva; |
|
133 |
+ *(uint32_t*)(pefile+0x148+0x14) = ResSize; |
|
134 |
+ curpe = pefile+0x148+0x80; |
|
135 |
+ |
|
136 |
+ for (i=0; i < sects; i++) { |
|
137 |
+ snprintf(curpe, 8, ".clam%.2d", i+1); |
|
138 |
+ cli_writeint32(curpe+8, sections[i].vsz); |
|
139 |
+ cli_writeint32(curpe+12, sections[i].rva); |
|
140 |
+ cli_writeint32(curpe+16, sections[i].rsz); |
|
141 |
+ cli_writeint32(curpe+20, sections[i].raw + rawbase); |
|
142 |
+ cli_writeint32(curpe+24, 0); |
|
143 |
+ cli_writeint32(curpe+28, 0); |
|
144 |
+ cli_writeint32(curpe+32, 0); |
|
145 |
+ cli_writeint32(curpe+24, 0xffffffff); |
|
146 |
+ curpe+=40; |
|
147 |
+ } |
|
148 |
+ memcpy(curpe, buffer, datasize); |
|
149 |
+ } |
|
150 |
+ |
|
151 |
+ return pefile; |
|
152 |
+} |
0 | 153 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,33 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2004 aCaB <acab@clamav.net> |
|
2 |
+ * |
|
3 |
+ * This program is free software; you can redistribute it and/or modify |
|
4 |
+ * it under the terms of the GNU General Public License as published by |
|
5 |
+ * the Free Software Foundation; either version 2 of the License, or |
|
6 |
+ * (at your option) any later version. |
|
7 |
+ * |
|
8 |
+ * This program is distributed in the hope that it will be useful, |
|
9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 |
+ * GNU General Public License for more details. |
|
12 |
+ * |
|
13 |
+ * You should have received a copy of the GNU General Public License |
|
14 |
+ * along with this program; if not, write to the Free Software |
|
15 |
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+#ifndef __REBUILDPE_H |
|
19 |
+#define __REBUILDPE_H |
|
20 |
+ |
|
21 |
+#include "cltypes.h" |
|
22 |
+ |
|
23 |
+struct SECTION { |
|
24 |
+ uint32_t rva; |
|
25 |
+ uint32_t vsz; |
|
26 |
+ uint32_t raw; |
|
27 |
+ uint32_t rsz; |
|
28 |
+}; |
|
29 |
+ |
|
30 |
+char *rebuildpe(char *buffer, struct SECTION *sections, int sects, uint32_t base, uint32_t ep, uint32_t ResRva, uint32_t ResSize); |
|
31 |
+ |
|
32 |
+#endif |
... | ... |
@@ -51,6 +51,7 @@ extern int cli_mbox(const char *dir, int desc); /* FIXME */ |
51 | 51 |
|
52 | 52 |
#include "clamav.h" |
53 | 53 |
#include "others.h" |
54 |
+#include "scanners.h" |
|
54 | 55 |
#include "matcher-ac.h" |
55 | 56 |
#include "matcher-bm.h" |
56 | 57 |
#include "matcher.h" |
... | ... |
@@ -83,7 +84,6 @@ extern int cli_mbox(const char *dir, int desc); /* FIXME */ |
83 | 83 |
#define MAX_MAIL_RECURSION 15 |
84 | 84 |
|
85 | 85 |
|
86 |
-static int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *arec, int *mrec); |
|
87 | 86 |
static int cli_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *arec, int *mrec); |
88 | 87 |
|
89 | 88 |
|
... | ... |
@@ -977,7 +977,7 @@ static int cli_scanmail(int desc, const char **virname, long int *scanned, const |
977 | 977 |
return ret; |
978 | 978 |
} |
979 | 979 |
|
980 |
-static int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *arec, int *mrec) |
|
980 |
+int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *arec, int *mrec) |
|
981 | 981 |
{ |
982 | 982 |
char magic[MAGIC_BUFFER_SIZE+1]; |
983 | 983 |
int ret = CL_CLEAN, nret; |
984 | 984 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,26 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2002 - 2004 Tomasz Kojm <tkojm@clamav.net> |
|
2 |
+ * |
|
3 |
+ * This program is free software; you can redistribute it and/or modify |
|
4 |
+ * it under the terms of the GNU General Public License as published by |
|
5 |
+ * the Free Software Foundation; either version 2 of the License, or |
|
6 |
+ * (at your option) any later version. |
|
7 |
+ * |
|
8 |
+ * This program is distributed in the hope that it will be useful, |
|
9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 |
+ * GNU General Public License for more details. |
|
12 |
+ * |
|
13 |
+ * You should have received a copy of the GNU General Public License |
|
14 |
+ * along with this program; if not, write to the Free Software |
|
15 |
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+#ifndef __SCANNERS_H |
|
19 |
+#define __SCANNERS_H |
|
20 |
+ |
|
21 |
+#include "clamav.h" |
|
22 |
+ |
|
23 |
+int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *arec, int *mrec); |
|
24 |
+ |
|
25 |
+#endif |