git-svn: trunk@1941
Tomasz Kojm authored on 2006/05/02 03:32:13... | ... |
@@ -1,3 +1,8 @@ |
1 |
+Mon May 1 20:30:10 CEST 2006 (tk) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav/pe.c: add W32.Polipos.A detection |
|
4 |
+ Thanks to aCaB for virus analysis and detection improvements |
|
5 |
+ |
|
1 | 6 |
Mon May 1 19:54:57 CEST 2006 (tk) |
2 | 7 |
---------------------------------- |
3 | 8 |
* freshclam/manager.c: fix possible buffer overflow |
... | ... |
@@ -1,5 +1,5 @@ |
1 | 1 |
/* |
2 |
- * Copyright (C) 2004 - 2005 Tomasz Kojm <tkojm@clamav.net> |
|
2 |
+ * Copyright (C) 2004 - 2006 Tomasz Kojm <tkojm@clamav.net> |
|
3 | 3 |
* |
4 | 4 |
* With additions from aCaB <acab@clamav.net> |
5 | 5 |
* |
... | ... |
@@ -61,6 +61,11 @@ |
61 | 61 |
|
62 | 62 |
extern short cli_leavetemps_flag; |
63 | 63 |
|
64 |
+struct offset_list { |
|
65 |
+ uint32_t offset; |
|
66 |
+ struct offset_list *next; |
|
67 |
+}; |
|
68 |
+ |
|
64 | 69 |
static uint32_t cli_rawaddr(uint32_t rva, struct pe_image_section_hdr *shp, uint16_t nos, unsigned int *err) |
65 | 70 |
{ |
66 | 71 |
int i, found = 0; |
... | ... |
@@ -74,7 +79,6 @@ static uint32_t cli_rawaddr(uint32_t rva, struct pe_image_section_hdr *shp, uint |
74 | 74 |
} |
75 | 75 |
|
76 | 76 |
if(!found) { |
77 |
- cli_dbgmsg("Can't calculate raw address from RVA 0x%x\n", rva); |
|
78 | 77 |
*err = 1; |
79 | 78 |
return 0; |
80 | 79 |
} |
... | ... |
@@ -143,7 +147,7 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
143 | 143 |
uint16_t nsections; |
144 | 144 |
uint32_t e_lfanew; /* address of new exe header */ |
145 | 145 |
uint32_t ep; /* entry point (raw) */ |
146 |
- uint32_t tmp; |
|
146 |
+ uint8_t polipos = 0; |
|
147 | 147 |
time_t timestamp; |
148 | 148 |
struct pe_image_file_hdr file_hdr; |
149 | 149 |
struct pe_image_optional_hdr32 optional_hdr32; |
... | ... |
@@ -151,11 +155,13 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
151 | 151 |
struct pe_image_section_hdr *section_hdr; |
152 | 152 |
struct stat sb; |
153 | 153 |
char sname[9], buff[4096], *tempfile; |
154 |
+ unsigned char *ubuff; |
|
155 |
+ ssize_t bytes; |
|
154 | 156 |
unsigned int i, found, upx_success = 0, min = 0, max = 0, err, broken = 0; |
155 | 157 |
unsigned int ssize = 0, dsize = 0, dll = 0, pe_plus = 0; |
156 | 158 |
int (*upxfn)(char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t) = NULL; |
157 | 159 |
char *src = NULL, *dest = NULL; |
158 |
- int ndesc, ret; |
|
160 |
+ int ndesc, ret = CL_CLEAN; |
|
159 | 161 |
size_t fsize; |
160 | 162 |
|
161 | 163 |
|
... | ... |
@@ -536,6 +542,14 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
536 | 536 |
max = EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData); |
537 | 537 |
} |
538 | 538 |
|
539 |
+ if(SCAN_ALGO && !strlen(sname)) { |
|
540 |
+ if(EC32(section_hdr[i].VirtualSize) > 40000 && EC32(section_hdr[i].VirtualSize) < 70000) { |
|
541 |
+ if(EC32(section_hdr[i].Characteristics) == 0xe0000060) { |
|
542 |
+ polipos = i; |
|
543 |
+ } |
|
544 |
+ } |
|
545 |
+ } |
|
546 |
+ |
|
539 | 547 |
} |
540 | 548 |
|
541 | 549 |
if(pe_plus) |
... | ... |
@@ -609,6 +623,98 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
609 | 609 |
} |
610 | 610 |
} |
611 | 611 |
|
612 |
+ /* W32.Polipos.A */ |
|
613 |
+ if(polipos && !dll && !pe_plus && nsections > 2 && nsections < 13 && e_lfanew <= 0x800 && (EC16(optional_hdr32.Subsystem) == 2 || EC16(optional_hdr32.Subsystem) == 3) && EC16(file_hdr.Machine) == 0x14c && optional_hdr32.SizeOfStackReserve >= 0x80000) { |
|
614 |
+ uint32_t remaining = EC32(section_hdr[0].SizeOfRawData); |
|
615 |
+ uint32_t chunk = sizeof(buff); |
|
616 |
+ uint32_t val, shift, raddr, curroff, total = 0; |
|
617 |
+ const char *jpt; |
|
618 |
+ struct offset_list *offlist = NULL, *offnode; |
|
619 |
+ |
|
620 |
+ |
|
621 |
+ cli_dbgmsg("Detected W32.Polipos.A characteristics\n"); |
|
622 |
+ |
|
623 |
+ if(remaining < chunk) |
|
624 |
+ chunk = remaining; |
|
625 |
+ |
|
626 |
+ lseek(desc, EC32(section_hdr[0].PointerToRawData), SEEK_SET); |
|
627 |
+ while((bytes = cli_readn(desc, buff, chunk)) > 0) { |
|
628 |
+ shift = 0; |
|
629 |
+ while(bytes - 5 > shift) { |
|
630 |
+ jpt = buff + shift; |
|
631 |
+ if(*jpt!='\xe9' && *jpt!='\xe8') { |
|
632 |
+ shift++; |
|
633 |
+ continue; |
|
634 |
+ } |
|
635 |
+ val = cli_readint32(jpt + 1); |
|
636 |
+ val += 5 + EC32(section_hdr[0].VirtualAddress) + total + shift; |
|
637 |
+ raddr = cli_rawaddr(val, section_hdr, nsections, &err); |
|
638 |
+ |
|
639 |
+ if(!err && (raddr >= EC32(section_hdr[polipos].PointerToRawData) && raddr < EC32(section_hdr[polipos].PointerToRawData) + EC32(section_hdr[polipos].SizeOfRawData)) && (!offlist || (raddr != offlist->offset))) { |
|
640 |
+ offnode = (struct offset_list *) cli_malloc(sizeof(struct offset_list)); |
|
641 |
+ if(!offnode) { |
|
642 |
+ free(section_hdr); |
|
643 |
+ while(offlist) { |
|
644 |
+ offnode = offlist; |
|
645 |
+ offlist = offlist->next; |
|
646 |
+ free(offnode); |
|
647 |
+ } |
|
648 |
+ return CL_EMEM; |
|
649 |
+ } |
|
650 |
+ offnode->offset = raddr; |
|
651 |
+ offnode->next = offlist; |
|
652 |
+ offlist = offnode; |
|
653 |
+ } |
|
654 |
+ |
|
655 |
+ shift++; |
|
656 |
+ } |
|
657 |
+ |
|
658 |
+ if(remaining < chunk) { |
|
659 |
+ chunk = remaining; |
|
660 |
+ } else { |
|
661 |
+ remaining -= bytes; |
|
662 |
+ if(remaining < chunk) { |
|
663 |
+ chunk = remaining; |
|
664 |
+ } |
|
665 |
+ } |
|
666 |
+ |
|
667 |
+ if(!remaining) |
|
668 |
+ break; |
|
669 |
+ |
|
670 |
+ total += bytes; |
|
671 |
+ } |
|
672 |
+ |
|
673 |
+ offnode = offlist; |
|
674 |
+ while(offnode) { |
|
675 |
+ cli_dbgmsg("Polipos: Checking offset 0x%x (%u)", offnode->offset, offnode->offset); |
|
676 |
+ lseek(desc, offnode->offset, SEEK_SET); |
|
677 |
+ if(cli_readn(desc, buff, 9) == 9) { |
|
678 |
+ ubuff = (unsigned char *) buff; |
|
679 |
+ if(ubuff[0] == 0x55 && ubuff[1] == 0x8b && ubuff[2] == 0xec && |
|
680 |
+ ((ubuff[3] == 0x83 && ubuff[4] == 0xec && ubuff[6] == 0x60) || ubuff[3] == 0x60 || |
|
681 |
+ (ubuff[3] == 0x81 && ubuff[4] == 0xec && ubuff[7] == 0x00 && ubuff[8] == 0x00))) { |
|
682 |
+ ret = CL_VIRUS; |
|
683 |
+ *ctx->virname = "W32.Polipos.A"; |
|
684 |
+ break; |
|
685 |
+ } |
|
686 |
+ } |
|
687 |
+ |
|
688 |
+ offnode = offnode->next; |
|
689 |
+ } |
|
690 |
+ |
|
691 |
+ while(offlist) { |
|
692 |
+ offnode = offlist; |
|
693 |
+ offlist = offlist->next; |
|
694 |
+ free(offnode); |
|
695 |
+ } |
|
696 |
+ |
|
697 |
+ if(ret == CL_VIRUS) { |
|
698 |
+ free(section_hdr); |
|
699 |
+ return CL_VIRUS; |
|
700 |
+ } |
|
701 |
+ } |
|
702 |
+ |
|
703 |
+ |
|
612 | 704 |
if(broken) { |
613 | 705 |
free(section_hdr); |
614 | 706 |
return CL_CLEAN; |