Browse code

pe: detect skewed UPX1

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@664 77e5149b-7576-45b1-b177-96237e5ba77b

Tomasz Kojm authored on 2004/07/09 11:23:11
Showing 5 changed files
... ...
@@ -1,3 +1,8 @@
1
+Fri Jul  9 04:14:37 CEST 2004 (tk)
2
+----------------------------------
3
+  * libclamav: pe: detect skewed UPX1 (patch by aCaB)
4
+  * libclamav: use new rule set for HTML detection (thanks to Trog)
5
+
1 6
 Thu Jul  8 23:23:34 BST 2004 (njh)
2 7
 ----------------------------------
3 8
   * clamav-milter:	Validate arguments given to inet_ntop. This
... ...
@@ -112,27 +112,22 @@ static const struct cli_magic_s cli_magic[] = {
112 112
 
113 113
 static const struct cli_smagic_s cli_smagic[] = {
114 114
 
115
-    /* <html>*<body */
116 115
     /* "From: " * "Content-Type: " */
117 116
     {"46726f6d3a20*436f6e74656e742d547970653a20",    "Mail file", CL_MAILFILE},
118 117
 
119
-    /* matcher is case sensitive - we have to check all variants of <html> */
120
-    {"3c68746d6c3e",    "HTML data", CL_HTMLFILE},
121
-    {"3c48746d6c3e",    "HTML data", CL_HTMLFILE},
122
-    {"3c68546d6c3e",    "HTML data", CL_HTMLFILE},
123
-    {"3c68744d6c3e",    "HTML data", CL_HTMLFILE},
124
-    {"3c68746d4c3e",    "HTML data", CL_HTMLFILE},
125
-    {"3c48546d6c3e",    "HTML data", CL_HTMLFILE},
126
-    {"3c48744d6c3e",    "HTML data", CL_HTMLFILE},
127
-    {"3c48746d4c3e",    "HTML data", CL_HTMLFILE},
128
-    {"3c68544d6c3e",    "HTML data", CL_HTMLFILE},
129
-    {"3c68546d4c3e",    "HTML data", CL_HTMLFILE},
130
-    {"3c68744d4c3e",    "HTML data", CL_HTMLFILE},
131
-    {"3c48544d6c3e",    "HTML data", CL_HTMLFILE},
132
-    {"3c48744d4c3e",    "HTML data", CL_HTMLFILE},
133
-    {"3c68544d4c3e",    "HTML data", CL_HTMLFILE},
134
-    {"3c48546d4c3e",    "HTML data", CL_HTMLFILE},
135
-    {"3c48544d4c3e",    "HTML data", CL_HTMLFILE},
118
+    /* remember the matcher is case sensitive */
119
+    {"3c62723e",    "HTML data", CL_HTMLFILE},	/* <br> */
120
+    {"3c42723e",    "HTML data", CL_HTMLFILE},	/* <Br> */
121
+    {"3c42523e",    "HTML data", CL_HTMLFILE},	/* <BR> */
122
+    {"3c703e",	    "HTML data", CL_HTMLFILE},	/* <p> */
123
+    {"3c503e",	    "HTML data", CL_HTMLFILE},	/* <P> */
124
+    {"68726566",    "HTML data", CL_HTMLFILE},	/* href */
125
+    {"48726566",    "HTML data", CL_HTMLFILE},	/* Href */
126
+    {"48524546",    "HTML data", CL_HTMLFILE},	/* HREF */
127
+    {"3c666f6e74",  "HTML data", CL_HTMLFILE},	/* <font */
128
+    {"3c466f6e74",  "HTML data", CL_HTMLFILE},	/* <Font */
129
+    {"3c464f4e54",  "HTML data", CL_HTMLFILE},	/* <FONT */
130
+
136 131
 
137 132
     {NULL,  NULL,   CL_UNKNOWN_TYPE}
138 133
 };
... ...
@@ -47,6 +47,7 @@ pthread_mutex_t cl_gentemp_mutex = PTHREAD_MUTEX_INITIALIZER;
47 47
 #include "clamav.h"
48 48
 #include "others.h"
49 49
 #include "md5.h"
50
+#include "cltypes.h"
50 51
 
51 52
 #define CL_FLEVEL 2 /* don't touch it */
52 53
 
... ...
@@ -453,3 +454,19 @@ int cli_writen(int fd, void *buff, unsigned int count)
453 453
         return count;
454 454
 }
455 455
 
456
+int32_t cli_readint32(const char *buff)
457
+{
458
+	int32_t ret, shift, i = 0;
459
+
460
+#if WORDS_BIGENDIAN == 0
461
+    ret = *(int32_t *) buff;
462
+#else
463
+    ret = 0;
464
+    for(shift = 0; shift < 32; shift += 8) {
465
+      ret |= (buff[i] & 0xff ) << shift;
466
+      i++;
467
+    }
468
+#endif
469
+
470
+    return ret;
471
+}
... ...
@@ -21,6 +21,7 @@
21 21
 
22 22
 #include <stdio.h>
23 23
 #include <stdlib.h>
24
+#include "cltypes.h"
24 25
 
25 26
 void cli_warnmsg(const char *str, ...);
26 27
 void cli_errmsg(const char *str, ...);
... ...
@@ -32,5 +33,6 @@ int cli_rmdirs(const char *dirname);
32 32
 char *cli_md5stream(FILE *fd);
33 33
 int cli_readn(int fd, void *buff, unsigned int count);
34 34
 int cli_writen(int fd, void *buff, unsigned int count);
35
+int32_t cli_readint32(const char *buff);
35 36
 
36 37
 #endif
... ...
@@ -234,7 +234,7 @@ 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[24], *tempfile;
237
+	char sname[9], buff[126], *tempfile;
238 238
 	int i, found, upx_success = 0, broken = 0;
239 239
 	int (*upxfn)(char *, int , char *, int) = NULL;
240 240
 
... ...
@@ -470,6 +470,12 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
470 470
 	    return CL_CLEAN;
471 471
 	}
472 472
 
473
+	if(ssize <= 0x19 || dsize <= ssize) { /* FIXME: What are reasonable values? */
474
+	    cli_dbgmsg("UPX: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
475
+	    return CL_CLEAN;
476
+	}
477
+
478
+
473 479
 	/* FIXME: use file operations in case of big files */
474 480
 	if((src = (char *) cli_malloc(ssize)) == NULL) {
475 481
 	    free(section_hdr);
... ...
@@ -493,39 +499,50 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
493 493
 
494 494
 	/* try to detect UPX code */
495 495
 
496
-	if(lseek(desc, ep + 0x69, SEEK_SET) == -1) {
496
+	if(lseek(desc, ep, SEEK_SET) == -1) {
497 497
 	    cli_dbgmsg("lseek() failed\n");
498 498
 	    free(section_hdr);
499 499
 	    return CL_EIO;
500 500
 	}
501 501
 
502
-	if(read(desc, buff, 21) != 21) {
503
-	    cli_dbgmsg("UPX: Can't read 21 bytes at 0x%x (%d)\n", ep + 0x69, ep + 0x78);
502
+	if(read(desc, buff, 126) != 126) { /* i.e. 0x69 + 13 + 8 */
503
+	    cli_dbgmsg("UPX: Can't read 126 bytes at 0x%x (%d)\n", ep, ep);
504 504
 	    return CL_EIO;
505 505
 	} else {
506
-	    if(cli_memstr(UPX_NRV2B, 24, buff, 13) || cli_memstr(UPX_NRV2B, 24, buff + 8, 13)) {
506
+	    if(cli_memstr(UPX_NRV2B, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2B, 24, buff + 0x69 + 8, 13)) {
507 507
 		cli_dbgmsg("UPX: Looks like a NRV2B decompression routine\n");
508 508
 		upxfn = upx_inflate2b;
509
-	    } else if(cli_memstr(UPX_NRV2D, 24, buff, 13) || cli_memstr(UPX_NRV2D, 24, buff + 8, 13)) {
509
+	    } else if(cli_memstr(UPX_NRV2D, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2D, 24, buff + 0x69 + 8, 13)) {
510 510
 		cli_dbgmsg("UPX: Looks like a NRV2D decompression routine\n");
511 511
 		upxfn = upx_inflate2d;
512
-	    } else if(cli_memstr(UPX_NRV2E, 24, buff, 13) || cli_memstr(UPX_NRV2E, 24, buff + 8, 13)) {
512
+	    } else if(cli_memstr(UPX_NRV2E, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2E, 24, buff + 0x69 + 8, 13)) {
513 513
 		cli_dbgmsg("UPX: Looks like a NRV2E decompression routine\n");
514 514
 		upxfn = upx_inflate2e;
515 515
 	    }
516 516
 	}
517 517
 
518 518
 	if(upxfn) {
519
-	    if(upxfn(src, ssize, dest, dsize)) {
520
-		cli_dbgmsg("UPX: Prefered decompressor failed\n");
519
+		int ret, skew = cli_readint32(buff + 2) - EC32(optional_hdr.ImageBase) - EC32(section_hdr[i+1].VirtualAddress);
520
+
521
+	    if(buff[1] != '\xbe' || skew <= 0 || skew > 0x2e ) { /* FIXME: legit skews?? */
522
+		skew = 0; 
523
+		if(!upxfn(src, ssize, dest, dsize))
524
+		    upx_success = 1;
525
+
521 526
 	    } else {
522
-		upx_success = 1;
523
-		cli_dbgmsg("UPX: Successfully decompressed\n");
527
+		cli_dbgmsg("UPX: UPX1 seems skewed by %d bytes\n", skew);
528
+		if(!upxfn(src + skew, ssize - skew, dest, dsize) || !upxfn(src, ssize, dest, dsize))
529
+		    upx_success = 1;
524 530
 	    }
531
+
532
+	    if(upx_success)
533
+		cli_dbgmsg("UPX: Successfully decompressed\n");
534
+	    else
535
+		cli_dbgmsg("UPX: Prefered decompressor failed\n");
525 536
 	}
526 537
 
527 538
 	if(!upx_success && upxfn != upx_inflate2b) {
528
-	    if(upx_inflate2b(src, ssize, dest, dsize)) {
539
+	    if(upx_inflate2b(src, ssize, dest, dsize) && upx_inflate2b(src + 0x15, ssize - 0x15, dest, dsize) ) {
529 540
 		cli_dbgmsg("UPX: NRV2B decompressor failed\n");
530 541
 	    } else {
531 542
 		upx_success = 1;
... ...
@@ -534,7 +551,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
534 534
 	}
535 535
 
536 536
 	if(!upx_success && upxfn != upx_inflate2d) {
537
-	    if(upx_inflate2d(src, ssize, dest, dsize)) {
537
+	    if(upx_inflate2d(src, ssize, dest, dsize) && upx_inflate2d(src+0x15, ssize-0x15, dest, dsize) ) {
538 538
 		cli_dbgmsg("UPX: NRV2D decompressor failed\n");
539 539
 	    } else {
540 540
 		upx_success = 1;
... ...
@@ -543,7 +560,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
543 543
 	}
544 544
 
545 545
 	if(!upx_success && upxfn != upx_inflate2e) {
546
-	    if(upx_inflate2e(src, ssize, dest, dsize)) {
546
+	    if(upx_inflate2e(src, ssize, dest, dsize) && upx_inflate2e(src + 0x15, ssize - 0x15, dest, dsize) ) {
547 547
 		cli_dbgmsg("UPX: NRV2E decompressor failed\n");
548 548
 	    } else {
549 549
 		upx_success = 1;