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... | ... |
@@ -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; |