Browse code

libclamav: pe: integrate Petite unpacker from aCaB (not yet activated)

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
Showing 12 changed files
... ...
@@ -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