Browse code

sigtool: add --test-sigs (basic functionality) (bb#1246)

Tomasz Kojm authored on 2009/12/10 07:32:34
Showing 7 changed files
... ...
@@ -1,3 +1,7 @@
1
+Wed Dec  9 23:31:54 CET 2009 (tk)
2
+---------------------------------
3
+ * sigtool: add --test-sigs (basic functionality) (bb#1246)
4
+
1 5
 Fri Dec  4 15:55:51 CET 2009 (tk)
2 6
 ---------------------------------
3 7
  * freshclam/manager.c: improve handling of problematic mirrors (bb#1758)
... ...
@@ -74,6 +74,12 @@ List all signature names from the local database directory (default) or from FIL
74 74
 .TP 
75 75
 \fB\-fREGEX, \-\-find\-sigs=REGEX\fR
76 76
 Find and display signatures from the local database directory which match the given REGEX. The whole signature body (name, hex string, etc.) is checked.
77
+.TP 
78
+\fB\-fREGEX, \-\-decode\-sigs=REGEX\fR
79
+Decode signatures read from the standard input (eg. piped from \-\-find\-sigs)
80
+.TP 
81
+\fB\-fREGEX, \-\-test\-sigs=DATABASE TARGET_FILE\fR
82
+Test all signatures from DATABASE against TARGET_FILE.
77 83
 .SH "EXAMPLES"
78 84
 .LP 
79 85
 .TP 
... ...
@@ -123,6 +123,7 @@ CLAMAV_PRIVATE {
123 123
     cli_bm_init;
124 124
     cli_bm_scanbuff;
125 125
     cli_bm_free;
126
+    cli_initroots;
126 127
     html_screnc_decode;
127 128
     mpool_create;
128 129
     mpool_destroy;
... ...
@@ -273,7 +273,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
273 273
     return CL_SUCCESS;
274 274
 }
275 275
 
276
-static int cli_initroots(struct cl_engine *engine, unsigned int options)
276
+int cli_initroots(struct cl_engine *engine, unsigned int options)
277 277
 {
278 278
 	int i, ret;
279 279
 	struct cli_matcher *root;
... ...
@@ -61,4 +61,6 @@ int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo
61 61
 
62 62
 char *cli_dbgets(char *buff, unsigned int size, FILE *fs, struct cli_dbio *dbio);
63 63
 
64
+int cli_initroots(struct cl_engine *engine, unsigned int options);
65
+
64 66
 #endif
... ...
@@ -108,6 +108,7 @@ const struct clam_option __clam_options[] = {
108 108
     { NULL, "list-sigs", 'l', TYPE_STRING, NULL, -1, DATADIR, 0, OPT_SIGTOOL, "", "" },
109 109
     { NULL, "find-sigs", 'f', TYPE_STRING, NULL, -1, DATADIR, FLAG_REQUIRED, OPT_SIGTOOL, "", "" },
110 110
     { NULL, "decode-sigs", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" },
111
+    { NULL, "test-sigs", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
111 112
     { NULL, "vba", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
112 113
     { NULL, "vba-hex", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
113 114
     { NULL, "diff", 'd', TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
... ...
@@ -65,6 +65,7 @@
65 65
 #include "libclamav/htmlnorm.h"
66 66
 #include "libclamav/default.h"
67 67
 #include "libclamav/fmap.h"
68
+#include "libclamav/readdb.h"
68 69
 
69 70
 #define MAX_DEL_LOOKAHEAD   200
70 71
 
... ...
@@ -1627,6 +1628,41 @@ static int verifydiff(const char *diff, const char *cvd, const char *incdir)
1627 1627
     return ret;
1628 1628
 }
1629 1629
 
1630
+static int matchsig(const char *sig, int fd)
1631
+{
1632
+	struct cl_engine *engine;
1633
+	int ret;
1634
+
1635
+    if(!(engine = cl_engine_new())) {
1636
+	mprintf("!matchsig: Can't create new engine\n");
1637
+	return 0;
1638
+    }
1639
+
1640
+    if(cli_initroots(engine, 0) != CL_SUCCESS) {
1641
+	mprintf("!matchsig: cli_initroots() failed\n");
1642
+	cl_engine_free(engine);
1643
+	return 0;
1644
+    }
1645
+
1646
+    if(cli_parse_add(engine->root[0], "test", sig, 0, 0, "*", 0, NULL, 0) != CL_SUCCESS) {
1647
+	mprintf("!matchsig: Can't parse signature\n");
1648
+	cl_engine_free(engine);
1649
+	return 0;
1650
+    }
1651
+
1652
+    if(cl_engine_compile(engine) != CL_SUCCESS) {
1653
+	mprintf("!matchsig: Can't compile engine\n");
1654
+	cl_engine_free(engine);
1655
+	return 0;
1656
+    }
1657
+
1658
+    lseek(fd, 0, SEEK_SET);
1659
+    ret = cl_scandesc(fd, NULL, NULL, engine, CL_SCAN_STDOPT);
1660
+    cl_engine_free(engine);
1661
+
1662
+    return (ret == CL_VIRUS) ? 1 : 0;
1663
+}
1664
+
1630 1665
 static char *decodehexstr(const char *hex, unsigned int *dlen)
1631 1666
 {
1632 1667
 	uint16_t *str16;
... ...
@@ -1982,7 +2018,7 @@ static int decodehex(const char *hexsig)
1982 1982
     return 0;
1983 1983
 }
1984 1984
 
1985
-static int decodesig(char *sig)
1985
+static int decodesig(char *sig, int fd)
1986 1986
 {
1987 1987
 	char *pt;
1988 1988
 	const char *tokens[68];
... ...
@@ -2019,8 +2055,12 @@ static int decodesig(char *sig)
2019 2019
 	    } else {
2020 2020
 		mprintf(" +-> OFFSET: ANY\n");
2021 2021
 	    }
2022
-	    mprintf(" +-> DECODED SUBSIGNATURE:\n");
2023
-	    decodehex(tokens[3 + i]);
2022
+	    if(fd == -1) {
2023
+		mprintf(" +-> DECODED SUBSIGNATURE:\n");
2024
+		decodehex(tokens[3 + i]);
2025
+	    } else {
2026
+		mprintf(" +-> MATCH: %s\n", matchsig(tokens[3 + i], fd) ? "YES" : "** NO **");
2027
+	    }
2024 2028
 	}
2025 2029
     } else if(strchr(sig, ':')) { /* ndb */
2026 2030
 	tokens_count = cli_strtokenize(sig, ':', 6 + 1, tokens);
... ...
@@ -2076,13 +2116,21 @@ static int decodesig(char *sig)
2076 2076
 		return -1;
2077 2077
 	}
2078 2078
 	mprintf("OFFSET: %s\n", tokens[2]);
2079
-	mprintf("DECODED SIGNATURE:\n");
2080
-	decodehex(tokens[3]);
2079
+	if(fd == -1) {
2080
+	    mprintf("DECODED SIGNATURE:\n");
2081
+	    decodehex(tokens[3]);
2082
+	} else {
2083
+	    mprintf("MATCH: %s\n", matchsig(tokens[3], fd) ? "YES" : "** NO **");
2084
+	}
2081 2085
     } else if((pt = strchr(sig, '='))) {
2082 2086
 	*pt++ = 0;
2083 2087
 	mprintf("VIRUS NAME: %s\n", sig);
2084
-	mprintf("DECODED SIGNATURE:\n");
2085
-	decodehex(pt);
2088
+	if(fd == -1) {
2089
+	    mprintf("DECODED SIGNATURE:\n");
2090
+	    decodehex(pt);
2091
+	} else {
2092
+	    mprintf("MATCH: %s\n", matchsig(pt, fd) ? "YES" : "** NO **");
2093
+	}
2086 2094
     } else {
2087 2095
 	mprintf("decodesig: Not supported signature format\n");
2088 2096
 	return -1;
... ...
@@ -2100,12 +2148,57 @@ static int decodesigs(void)
2100 2100
 	cli_chomp(buffer);
2101 2101
 	if(!strlen(buffer))
2102 2102
 	    break;
2103
-	if(decodesig(buffer) == -1)
2103
+	if(decodesig(buffer, -1) == -1)
2104 2104
 	    return -1;
2105 2105
     }
2106 2106
     return 0;
2107 2107
 }
2108 2108
 
2109
+static int testsigs(const struct optstruct *opts)
2110
+{
2111
+	char buffer[32769];
2112
+	FILE *sigs;
2113
+	int ret = 0, fd;
2114
+
2115
+
2116
+    if(!opts->filename) {
2117
+	mprintf("!--test-sigs requires two arguments\n");
2118
+	return -1;
2119
+    }
2120
+
2121
+    if(cl_init(CL_INIT_DEFAULT) != CL_SUCCESS) {
2122
+	mprintf("!testsigs: Can't initialize libclamav: %s\n", cl_strerror(ret));
2123
+	return -1;
2124
+    }
2125
+
2126
+    sigs = fopen(optget(opts, "test-sigs")->strarg, "rb");
2127
+    if(!sigs) {
2128
+	mprintf("!testsigs: Can't open file %s\n", optget(opts, "test-sigs")->strarg);
2129
+	return -1;
2130
+    }
2131
+
2132
+    fd = open(opts->filename[0], O_RDONLY|O_BINARY);
2133
+    if(fd == -1) {
2134
+	mprintf("!testsigs: Can't open file %s\n", optget(opts, "test-sigs")->strarg);
2135
+	fclose(sigs);
2136
+	return -1;
2137
+    }
2138
+
2139
+    while(fgets(buffer, sizeof(buffer), sigs)) {
2140
+	cli_chomp(buffer);
2141
+	if(!strlen(buffer))
2142
+	    break;
2143
+	if(decodesig(buffer, fd) == -1) {
2144
+	    ret = -1;
2145
+	    break;
2146
+	}
2147
+    }
2148
+
2149
+    close(fd);
2150
+    fclose(sigs);
2151
+    return ret;
2152
+}
2153
+
2109 2154
 static int diffdirs(const char *old, const char *new, const char *patch)
2110 2155
 {
2111 2156
 	FILE *diff;
... ...
@@ -2312,6 +2405,7 @@ static void help(void)
2312 2312
     mprintf("    --list-sigs[=FILE]     -l[FILE]        List signature names\n");
2313 2313
     mprintf("    --find-sigs=REGEX      -fREGEX         Find signatures matching REGEX\n");
2314 2314
     mprintf("    --decode-sigs                          Decode signatures from stdin\n");
2315
+    mprintf("    --test-sigs=DATABASE TARGET_FILE       Test signatures from DATABASE against TARGET_FILE\n");
2315 2316
     mprintf("    --vba=FILE                             Extract VBA/Word6 macro code\n");
2316 2317
     mprintf("    --vba-hex=FILE                         Extract Word6 macro code with hex values\n");
2317 2318
     mprintf("    --diff=OLD NEW         -d OLD NEW      Create diff for OLD and NEW CVDs\n");
... ...
@@ -2379,6 +2473,8 @@ int main(int argc, char **argv)
2379 2379
 	ret = listsigs(opts, 1);
2380 2380
     else if(optget(opts, "decode-sigs")->active)
2381 2381
 	ret = decodesigs();
2382
+    else if(optget(opts, "test-sigs")->enabled)
2383
+	ret = testsigs(opts);
2382 2384
     else if(optget(opts, "vba")->enabled || optget(opts, "vba-hex")->enabled)
2383 2385
 	ret = vbadump(opts);
2384 2386
     else if(optget(opts, "diff")->enabled)