Browse code

add support for signature based self-protection mode

git-svn: trunk@1831

Tomasz Kojm authored on 2006/01/25 21:11:31
Showing 9 changed files
... ...
@@ -1,3 +1,7 @@
1
+Wed Jan 25 13:09:19 CET 2006 (tk)
2
+---------------------------------
3
+  * libclamav: add support for signature based self-protection mode
4
+
1 5
 Tue Jan 24 16:52:21 CET 2006 (tk)
2 6
 ---------------------------------
3 7
   * libclamav/unrar: fix compilation error on old linux systems
... ...
@@ -150,6 +150,7 @@ struct cli_matcher {
150 150
 struct cl_engine {
151 151
     unsigned int refcount; /* reference counter */
152 152
     unsigned short hwaccel;
153
+    unsigned short sdb;
153 154
 
154 155
     /* Roots table */
155 156
     struct cli_matcher **root;
... ...
@@ -260,7 +260,7 @@ inline static int cli_findpos(const char *buffer, unsigned int depth, unsigned i
260 260
     return 1;
261 261
 }
262 262
 
263
-int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, int *partcnt, short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, struct cli_matched_type **ftoffset)
263
+int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, int *partcnt, unsigned short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, struct cli_matched_type **ftoffset)
264 264
 {
265 265
 	struct cli_ac_node *current;
266 266
 	struct cli_ac_patt *pt;
... ...
@@ -26,7 +26,7 @@
26 26
 #define AC_DEFAULT_DEPTH 2
27 27
 
28 28
 int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern);
29
-int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, int *partcnt, short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, struct cli_matched_type **ftoffset);
29
+int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, int *partcnt, unsigned short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, struct cli_matched_type **ftoffset);
30 30
 int cli_ac_buildtrie(struct cli_matcher *root);
31 31
 void cli_ac_free(struct cli_matcher *root);
32 32
 void cli_ac_setdepth(unsigned int depth);
... ...
@@ -274,7 +274,7 @@ int cli_validatesig(unsigned short target, unsigned short ftype, const char *off
274 274
     return 1;
275 275
 }
276 276
 
277
-int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, short otfrec, unsigned short ftype, struct cli_matched_type **ftoffset)
277
+int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned short otfrec, unsigned short ftype, struct cli_matched_type **ftoffset)
278 278
 {
279 279
  	char *buffer, *buff, *endbl, *pt;
280 280
 	int bytes, buffsize, length, ret, *gpartcnt, *tpartcnt;
... ...
@@ -24,7 +24,7 @@
24 24
 
25 25
 #define CL_TARGET_TABLE_SIZE 7
26 26
 
27
-int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, short otfrec, unsigned short ftype, struct cli_matched_type **ftoffset);
27
+int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned short otfrec, unsigned short ftype, struct cli_matched_type **ftoffset);
28 28
 
29 29
 int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_engine *engine, unsigned short ftype);
30 30
 
... ...
@@ -72,7 +72,7 @@ static pthread_mutex_t cli_gentempname_mutex = PTHREAD_MUTEX_INITIALIZER;
72 72
 #define	O_BINARY	0
73 73
 #endif
74 74
 
75
-#define CL_FLEVEL 6 /* don't touch it */
75
+#define CL_FLEVEL 7 /* don't touch it */
76 76
 
77 77
 #define MAX_ALLOCATION 134217728
78 78
 
... ...
@@ -557,7 +557,7 @@ static int cli_loaddb(FILE *fd, struct cl_engine **engine, unsigned int *signo,
557 557
     return 0;
558 558
 }
559 559
 
560
-static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo, unsigned int options)
560
+static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo, unsigned short sdb, unsigned int options)
561 561
 {
562 562
 	char buffer[FILEBUFF], *sig, *virname, *offset, *pt;
563 563
 	struct cli_matcher *root;
... ...
@@ -594,7 +594,7 @@ static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo,
594 594
 	    break;
595 595
 	}
596 596
 
597
-	if((pt = cli_strtok(buffer, 4, ":"))) {
597
+	if((pt = cli_strtok(buffer, 4, ":"))) { /* min version */
598 598
 	    if(!isdigit(*pt)) {
599 599
 		free(virname);
600 600
 		free(pt);
... ...
@@ -611,6 +611,24 @@ static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo,
611 611
 	    }
612 612
 
613 613
 	    free(pt);
614
+
615
+	    if((pt = cli_strtok(buffer, 5, ":"))) { /* max version */
616
+		if(!isdigit(*pt)) {
617
+		    free(virname);
618
+		    free(pt);
619
+		    ret = CL_EMALFDB;
620
+		    break;
621
+		}
622
+
623
+		if(atoi(pt) < cl_retflevel()) {
624
+		    sigs--;
625
+		    free(virname);
626
+		    free(pt);
627
+		    continue;
628
+		}
629
+
630
+		free(pt);
631
+	    }
614 632
 	}
615 633
 
616 634
 	if(!(pt = cli_strtok(buffer, 1, ":")) || !isdigit(*pt)) {
... ...
@@ -677,6 +695,11 @@ static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo,
677 677
     if(signo)
678 678
 	*signo += sigs;
679 679
 
680
+    if(sdb && sigs && !(*engine)->sdb) {
681
+	(*engine)->sdb = 1;
682
+	cli_dbgmsg("*** Self protection mechanism activated.\n");
683
+    }
684
+
680 685
     return 0;
681 686
 }
682 687
 
... ...
@@ -970,7 +993,10 @@ static int cli_load(const char *filename, struct cl_engine **engine, unsigned in
970 970
 	ret = cli_loadhdb(fd, engine, signo, 1, options);
971 971
 
972 972
     } else if(cli_strbcasestr(filename, ".ndb")) {
973
-	ret = cli_loadndb(fd, engine, signo, options);
973
+	ret = cli_loadndb(fd, engine, signo, 0, options);
974
+
975
+    } else if(cli_strbcasestr(filename, ".sdb")) {
976
+	ret = cli_loadndb(fd, engine, signo, 1, options);
974 977
 
975 978
     } else if(cli_strbcasestr(filename, ".zmd")) {
976 979
 	ret = cli_loadmd(fd, engine, signo, 1, options);
... ...
@@ -1033,6 +1059,7 @@ static int cli_loaddbdir(const char *dirname, struct cl_engine **engine, unsigne
1033 1033
 	     cli_strbcasestr(dent->d_name, ".hdb")  ||
1034 1034
 	     cli_strbcasestr(dent->d_name, ".fp")   ||
1035 1035
 	     cli_strbcasestr(dent->d_name, ".ndb")  ||
1036
+	     cli_strbcasestr(dent->d_name, ".sdb")  ||
1036 1037
 	     cli_strbcasestr(dent->d_name, ".zmd")  ||
1037 1038
 	     cli_strbcasestr(dent->d_name, ".rmd")  ||
1038 1039
 	     cli_strbcasestr(dent->d_name, ".cvd"))) {
... ...
@@ -1153,6 +1180,7 @@ int cl_statinidir(const char *dirname, struct cl_stat *dbstat)
1153 1153
 	    cli_strbcasestr(dent->d_name, ".hdb")  || 
1154 1154
 	    cli_strbcasestr(dent->d_name, ".fp")  || 
1155 1155
 	    cli_strbcasestr(dent->d_name, ".ndb")  || 
1156
+	    cli_strbcasestr(dent->d_name, ".sdb")  || 
1156 1157
 	    cli_strbcasestr(dent->d_name, ".zmd")  || 
1157 1158
 	    cli_strbcasestr(dent->d_name, ".rmd")  || 
1158 1159
 	    cli_strbcasestr(dent->d_name, ".cvd"))) {
... ...
@@ -1224,6 +1252,7 @@ int cl_statchkdir(const struct cl_stat *dbstat)
1224 1224
 	    cli_strbcasestr(dent->d_name, ".hdb")  || 
1225 1225
 	    cli_strbcasestr(dent->d_name, ".fp")  || 
1226 1226
 	    cli_strbcasestr(dent->d_name, ".ndb")  || 
1227
+	    cli_strbcasestr(dent->d_name, ".sdb")  || 
1227 1228
 	    cli_strbcasestr(dent->d_name, ".zmd")  || 
1228 1229
 	    cli_strbcasestr(dent->d_name, ".rmd")  || 
1229 1230
 	    cli_strbcasestr(dent->d_name, ".cvd"))) {
... ...
@@ -1438,8 +1438,7 @@ static int cli_scantnef(int desc, const char **virname, unsigned long int *scann
1438 1438
     return ret;
1439 1439
 }
1440 1440
 
1441
-static int
1442
-cli_scanuuencoded(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1441
+static int cli_scanuuencoded(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1443 1442
 {
1444 1443
 	int ret;
1445 1444
 	char *dir = cli_gentemp(NULL);
... ...
@@ -1497,6 +1496,90 @@ static int cli_scanmail(int desc, const char **virname, unsigned long int *scann
1497 1497
     return ret;
1498 1498
 }
1499 1499
 
1500
+static int cli_scanraw(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec, cli_file_t type)
1501
+{
1502
+	int ret = CL_CLEAN;
1503
+	unsigned short ftrec;
1504
+	struct cli_matched_type *ftoffset = NULL, *fpt;
1505
+
1506
+
1507
+    switch(type) {
1508
+	case CL_TYPE_UNKNOWN_TEXT:
1509
+	case CL_TYPE_MSEXE:
1510
+	    ftrec = 1;
1511
+	    break;
1512
+	default:
1513
+	    ftrec = 0;
1514
+    }
1515
+
1516
+    if(lseek(desc, 0, SEEK_SET) < 0) {
1517
+	cli_errmsg("cli_scanraw: lseek() failed\n");
1518
+	return CL_EIO;
1519
+    }
1520
+
1521
+    if((ret = cli_scandesc(desc, virname, scanned, engine, ftrec, type, &ftoffset)) == CL_VIRUS) {
1522
+	cli_dbgmsg("%s found in descriptor %d.\n", *virname, desc);
1523
+	return CL_VIRUS;
1524
+
1525
+    } else if(ret < 0) {
1526
+	return ret;
1527
+
1528
+    } else if(ret >= CL_TYPENO) {
1529
+	lseek(desc, 0, SEEK_SET);
1530
+
1531
+	ret == CL_TYPE_MAIL ? mrec++ : arec++;
1532
+	switch(ret) {
1533
+	    case CL_TYPE_HTML:
1534
+		if(SCAN_HTML && type == CL_TYPE_UNKNOWN_TEXT)
1535
+		    if(cli_scanhtml(desc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS)
1536
+			return CL_VIRUS;
1537
+		break;
1538
+
1539
+	    case CL_TYPE_MAIL:
1540
+		if(SCAN_MAIL && type == CL_TYPE_UNKNOWN_TEXT)
1541
+		    if(cli_scanmail(desc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS)
1542
+			return CL_VIRUS;
1543
+		break;
1544
+
1545
+	    case CL_TYPE_RARSFX:
1546
+	    case CL_TYPE_ZIPSFX:
1547
+		if(type == CL_TYPE_MSEXE) {
1548
+		    if(SCAN_ARCHIVE) {
1549
+			fpt = ftoffset;
1550
+			while(fpt) {
1551
+			    if(fpt->type == CL_TYPE_RARSFX) {
1552
+				cli_dbgmsg("RAR-SFX signature found at %d\n", fpt->offset);
1553
+				if((ret = cli_scanrar(desc, virname, scanned, engine, limits, options, arec, mrec, fpt->offset) == CL_VIRUS))
1554
+				    break;
1555
+			    } else if(fpt->type == CL_TYPE_ZIPSFX) {
1556
+				cli_dbgmsg("ZIP-SFX signature found at %d\n", fpt->offset);
1557
+				if((ret = cli_scanzip(desc, virname, scanned, engine, limits, options, arec, mrec, fpt->offset) == CL_VIRUS))
1558
+				    break;
1559
+			    }
1560
+			    fpt = fpt->next;
1561
+			}
1562
+		    }
1563
+
1564
+		    while(ftoffset) {
1565
+			fpt = ftoffset;
1566
+			ftoffset = ftoffset->next;
1567
+			free(fpt);
1568
+		    }
1569
+
1570
+		    if(ret == CL_VIRUS)
1571
+			return ret;
1572
+		}
1573
+		break;
1574
+
1575
+	    default:
1576
+		break;
1577
+	}
1578
+	ret == CL_TYPE_MAIL ? mrec-- : arec--;
1579
+    }
1580
+
1581
+    return ret;
1582
+}
1583
+
1500 1584
 int cli_magic_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1501 1585
 {
1502 1586
 	int ret = CL_CLEAN, nret;
... ...
@@ -1548,6 +1631,12 @@ int cli_magic_scandesc(int desc, const char **virname, unsigned long int *scanne
1548 1548
     type = cli_filetype2(desc);
1549 1549
     lseek(desc, 0, SEEK_SET);
1550 1550
 
1551
+    if(type != CL_TYPE_DATA && engine->sdb) {
1552
+	if((ret = cli_scanraw(desc, virname, scanned, engine, limits, options, arec, mrec, type) == CL_VIRUS))
1553
+	    return CL_VIRUS;
1554
+	lseek(desc, 0, SEEK_SET);
1555
+    }
1556
+
1551 1557
     type == CL_TYPE_MAIL ? mrec++ : arec++;
1552 1558
 
1553 1559
     switch(type) {
... ...
@@ -1671,81 +1760,9 @@ int cli_magic_scandesc(int desc, const char **virname, unsigned long int *scanne
1671 1671
 
1672 1672
     type == CL_TYPE_MAIL ? mrec-- : arec--;
1673 1673
 
1674
-    if(type != CL_TYPE_DATA && ret != CL_VIRUS) { /* scan the raw file */
1675
-	    int ftrec;
1676
-	    struct cli_matched_type *ftoffset = NULL, *fpt;
1677
-
1678
-	switch(type) {
1679
-	    case CL_TYPE_UNKNOWN_TEXT:
1680
-	    case CL_TYPE_MSEXE:
1681
-		ftrec = 1;
1682
-		break;
1683
-	    default:
1684
-		ftrec = 0;
1685
-	}
1686
-
1687
-	if(lseek(desc, 0, SEEK_SET) < 0)
1688
-	    cli_errmsg("lseek() failed, trying to continue anyway...\n");
1689
-
1690
-	if((nret = cli_scandesc(desc, virname, scanned, engine, ftrec, type, &ftoffset)) == CL_VIRUS) {
1691
-	    cli_dbgmsg("%s found in descriptor %d.\n", *virname, desc);
1674
+    if(type != CL_TYPE_DATA && ret != CL_VIRUS && !engine->sdb) {
1675
+	if((ret = cli_scanraw(desc, virname, scanned, engine, limits, options, arec, mrec, type) == CL_VIRUS))
1692 1676
 	    return CL_VIRUS;
1693
-
1694
-	} else if(nret < 0) {
1695
-	    return nret;
1696
-
1697
-	} else if(nret >= CL_TYPENO) {
1698
-	    lseek(desc, 0, SEEK_SET);
1699
-
1700
-	    nret == CL_TYPE_MAIL ? mrec++ : arec++;
1701
-	    switch(nret) {
1702
-		case CL_TYPE_HTML:
1703
-		    if(SCAN_HTML && type == CL_TYPE_UNKNOWN_TEXT)
1704
-			if(cli_scanhtml(desc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS)
1705
-			    return CL_VIRUS;
1706
-		    break;
1707
-
1708
-		case CL_TYPE_MAIL:
1709
-		    if(SCAN_MAIL && type == CL_TYPE_UNKNOWN_TEXT)
1710
-			if(cli_scanmail(desc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS)
1711
-			    return CL_VIRUS;
1712
-		    break;
1713
-
1714
-		case CL_TYPE_RARSFX:
1715
-		case CL_TYPE_ZIPSFX:
1716
-		    if(type == CL_TYPE_MSEXE) {
1717
-			if(SCAN_ARCHIVE) {
1718
-			    fpt = ftoffset;
1719
-			    while(fpt) {
1720
-				if(fpt->type == CL_TYPE_RARSFX) {
1721
-				    cli_dbgmsg("RAR-SFX signature found at %d\n", fpt->offset);
1722
-				    if((ret = cli_scanrar(desc, virname, scanned, engine, limits, options, arec, mrec, fpt->offset) == CL_VIRUS))
1723
-					break;
1724
-				} else if(fpt->type == CL_TYPE_ZIPSFX) {
1725
-				    cli_dbgmsg("ZIP-SFX signature found at %d\n", fpt->offset);
1726
-				    if((ret = cli_scanzip(desc, virname, scanned, engine, limits, options, arec, mrec, fpt->offset) == CL_VIRUS))
1727
-					break;
1728
-				}
1729
-				fpt = fpt->next;
1730
-			    }
1731
-			}
1732
-
1733
-			while(ftoffset) {
1734
-			    fpt = ftoffset;
1735
-			    ftoffset = ftoffset->next;
1736
-			    free(fpt);
1737
-			}
1738
-
1739
-			if(ret == CL_VIRUS)
1740
-			    return ret;
1741
-		    }
1742
-		    break;
1743
-
1744
-		default:
1745
-		    break;
1746
-	    }
1747
-	    nret == CL_TYPE_MAIL ? mrec-- : arec--;
1748
-	}
1749 1677
     }
1750 1678
 
1751 1679
     arec++;