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