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

This commit is contained in:
Tomasz Kojm 2009-12-09 23:32:34 +01:00
parent 33ab5c3c85
commit a96eead450
7 changed files with 119 additions and 9 deletions

View file

@ -1,3 +1,7 @@
Wed Dec 9 23:31:54 CET 2009 (tk)
---------------------------------
* sigtool: add --test-sigs (basic functionality) (bb#1246)
Fri Dec 4 15:55:51 CET 2009 (tk)
---------------------------------
* freshclam/manager.c: improve handling of problematic mirrors (bb#1758)

View file

@ -74,6 +74,12 @@ List all signature names from the local database directory (default) or from FIL
.TP
\fB\-fREGEX, \-\-find\-sigs=REGEX\fR
Find and display signatures from the local database directory which match the given REGEX. The whole signature body (name, hex string, etc.) is checked.
.TP
\fB\-fREGEX, \-\-decode\-sigs=REGEX\fR
Decode signatures read from the standard input (eg. piped from \-\-find\-sigs)
.TP
\fB\-fREGEX, \-\-test\-sigs=DATABASE TARGET_FILE\fR
Test all signatures from DATABASE against TARGET_FILE.
.SH "EXAMPLES"
.LP
.TP

View file

@ -123,6 +123,7 @@ CLAMAV_PRIVATE {
cli_bm_init;
cli_bm_scanbuff;
cli_bm_free;
cli_initroots;
html_screnc_decode;
mpool_create;
mpool_destroy;

View file

@ -273,7 +273,7 @@ int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hex
return CL_SUCCESS;
}
static int cli_initroots(struct cl_engine *engine, unsigned int options)
int cli_initroots(struct cl_engine *engine, unsigned int options)
{
int i, ret;
struct cli_matcher *root;

View file

@ -61,4 +61,6 @@ int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo
char *cli_dbgets(char *buff, unsigned int size, FILE *fs, struct cli_dbio *dbio);
int cli_initroots(struct cl_engine *engine, unsigned int options);
#endif

View file

@ -108,6 +108,7 @@ const struct clam_option __clam_options[] = {
{ NULL, "list-sigs", 'l', TYPE_STRING, NULL, -1, DATADIR, 0, OPT_SIGTOOL, "", "" },
{ NULL, "find-sigs", 'f', TYPE_STRING, NULL, -1, DATADIR, FLAG_REQUIRED, OPT_SIGTOOL, "", "" },
{ NULL, "decode-sigs", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_SIGTOOL, "", "" },
{ NULL, "test-sigs", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
{ NULL, "vba", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
{ NULL, "vba-hex", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
{ NULL, "diff", 'd', TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },

View file

@ -65,6 +65,7 @@
#include "libclamav/htmlnorm.h"
#include "libclamav/default.h"
#include "libclamav/fmap.h"
#include "libclamav/readdb.h"
#define MAX_DEL_LOOKAHEAD 200
@ -1627,6 +1628,41 @@ static int verifydiff(const char *diff, const char *cvd, const char *incdir)
return ret;
}
static int matchsig(const char *sig, int fd)
{
struct cl_engine *engine;
int ret;
if(!(engine = cl_engine_new())) {
mprintf("!matchsig: Can't create new engine\n");
return 0;
}
if(cli_initroots(engine, 0) != CL_SUCCESS) {
mprintf("!matchsig: cli_initroots() failed\n");
cl_engine_free(engine);
return 0;
}
if(cli_parse_add(engine->root[0], "test", sig, 0, 0, "*", 0, NULL, 0) != CL_SUCCESS) {
mprintf("!matchsig: Can't parse signature\n");
cl_engine_free(engine);
return 0;
}
if(cl_engine_compile(engine) != CL_SUCCESS) {
mprintf("!matchsig: Can't compile engine\n");
cl_engine_free(engine);
return 0;
}
lseek(fd, 0, SEEK_SET);
ret = cl_scandesc(fd, NULL, NULL, engine, CL_SCAN_STDOPT);
cl_engine_free(engine);
return (ret == CL_VIRUS) ? 1 : 0;
}
static char *decodehexstr(const char *hex, unsigned int *dlen)
{
uint16_t *str16;
@ -1982,7 +2018,7 @@ static int decodehex(const char *hexsig)
return 0;
}
static int decodesig(char *sig)
static int decodesig(char *sig, int fd)
{
char *pt;
const char *tokens[68];
@ -2019,8 +2055,12 @@ static int decodesig(char *sig)
} else {
mprintf(" +-> OFFSET: ANY\n");
}
mprintf(" +-> DECODED SUBSIGNATURE:\n");
decodehex(tokens[3 + i]);
if(fd == -1) {
mprintf(" +-> DECODED SUBSIGNATURE:\n");
decodehex(tokens[3 + i]);
} else {
mprintf(" +-> MATCH: %s\n", matchsig(tokens[3 + i], fd) ? "YES" : "** NO **");
}
}
} else if(strchr(sig, ':')) { /* ndb */
tokens_count = cli_strtokenize(sig, ':', 6 + 1, tokens);
@ -2076,13 +2116,21 @@ static int decodesig(char *sig)
return -1;
}
mprintf("OFFSET: %s\n", tokens[2]);
mprintf("DECODED SIGNATURE:\n");
decodehex(tokens[3]);
if(fd == -1) {
mprintf("DECODED SIGNATURE:\n");
decodehex(tokens[3]);
} else {
mprintf("MATCH: %s\n", matchsig(tokens[3], fd) ? "YES" : "** NO **");
}
} else if((pt = strchr(sig, '='))) {
*pt++ = 0;
mprintf("VIRUS NAME: %s\n", sig);
mprintf("DECODED SIGNATURE:\n");
decodehex(pt);
if(fd == -1) {
mprintf("DECODED SIGNATURE:\n");
decodehex(pt);
} else {
mprintf("MATCH: %s\n", matchsig(pt, fd) ? "YES" : "** NO **");
}
} else {
mprintf("decodesig: Not supported signature format\n");
return -1;
@ -2100,12 +2148,57 @@ static int decodesigs(void)
cli_chomp(buffer);
if(!strlen(buffer))
break;
if(decodesig(buffer) == -1)
if(decodesig(buffer, -1) == -1)
return -1;
}
return 0;
}
static int testsigs(const struct optstruct *opts)
{
char buffer[32769];
FILE *sigs;
int ret = 0, fd;
if(!opts->filename) {
mprintf("!--test-sigs requires two arguments\n");
return -1;
}
if(cl_init(CL_INIT_DEFAULT) != CL_SUCCESS) {
mprintf("!testsigs: Can't initialize libclamav: %s\n", cl_strerror(ret));
return -1;
}
sigs = fopen(optget(opts, "test-sigs")->strarg, "rb");
if(!sigs) {
mprintf("!testsigs: Can't open file %s\n", optget(opts, "test-sigs")->strarg);
return -1;
}
fd = open(opts->filename[0], O_RDONLY|O_BINARY);
if(fd == -1) {
mprintf("!testsigs: Can't open file %s\n", optget(opts, "test-sigs")->strarg);
fclose(sigs);
return -1;
}
while(fgets(buffer, sizeof(buffer), sigs)) {
cli_chomp(buffer);
if(!strlen(buffer))
break;
if(decodesig(buffer, fd) == -1) {
ret = -1;
break;
}
}
close(fd);
fclose(sigs);
return ret;
}
static int diffdirs(const char *old, const char *new, const char *patch)
{
FILE *diff;
@ -2312,6 +2405,7 @@ static void help(void)
mprintf(" --list-sigs[=FILE] -l[FILE] List signature names\n");
mprintf(" --find-sigs=REGEX -fREGEX Find signatures matching REGEX\n");
mprintf(" --decode-sigs Decode signatures from stdin\n");
mprintf(" --test-sigs=DATABASE TARGET_FILE Test signatures from DATABASE against TARGET_FILE\n");
mprintf(" --vba=FILE Extract VBA/Word6 macro code\n");
mprintf(" --vba-hex=FILE Extract Word6 macro code with hex values\n");
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)
ret = listsigs(opts, 1);
else if(optget(opts, "decode-sigs")->active)
ret = decodesigs();
else if(optget(opts, "test-sigs")->enabled)
ret = testsigs(opts);
else if(optget(opts, "vba")->enabled || optget(opts, "vba-hex")->enabled)
ret = vbadump(opts);
else if(optget(opts, "diff")->enabled)