... | ... |
@@ -107,6 +107,7 @@ int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_rea |
107 | 107 |
{ |
108 | 108 |
struct scan_cb_data *scandata = data->data; |
109 | 109 |
const char *virname; |
110 |
+ const char **virpp = &virname; |
|
110 | 111 |
int ret; |
111 | 112 |
int type = scandata->type; |
112 | 113 |
struct cb_context context; |
... | ... |
@@ -227,11 +228,18 @@ int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_rea |
227 | 227 |
thrmgr_setactivetask(filename, NULL); |
228 | 228 |
context.filename = filename; |
229 | 229 |
context.virsize = 0; |
230 |
- ret = cl_scanfile_callback(filename, &virname, &scandata->scanned, scandata->engine, scandata->options, &context); |
|
230 |
+ ret = cl_scanfile_callback(filename, virpp, &scandata->scanned, scandata->engine, scandata->options, &context); |
|
231 | 231 |
thrmgr_setactivetask(NULL, NULL); |
232 | 232 |
|
233 |
+ if (scandata->options & CL_SCAN_ALLMATCHES) { |
|
234 |
+ virpp = (const char **)*virpp; /* temp hack for scanall mode until api augmentation */ |
|
235 |
+ virname = virpp[0]; |
|
236 |
+ } |
|
237 |
+ |
|
233 | 238 |
if (thrmgr_group_need_terminate(scandata->conn->group)) { |
234 | 239 |
free(filename); |
240 |
+ if (ret == CL_VIRUS && scandata->options & CL_SCAN_ALLMATCHES) |
|
241 |
+ free((void *)virpp); |
|
235 | 242 |
logg("*Client disconnected while scanjob was active\n"); |
236 | 243 |
return ret == CL_ETIMEOUT ? ret : CL_BREAK; |
237 | 244 |
} |
... | ... |
@@ -240,8 +248,19 @@ int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_rea |
240 | 240 |
scandata->infected++; |
241 | 241 |
if (conn_reply_virus(scandata->conn, filename, virname) == -1) { |
242 | 242 |
free(filename); |
243 |
+ if (scandata->options & CL_SCAN_ALLMATCHES) |
|
244 |
+ free((void *)virpp); |
|
243 | 245 |
return CL_ETIMEOUT; |
244 | 246 |
} |
247 |
+ if (scandata->options & CL_SCAN_ALLMATCHES && virpp[1] != NULL) { |
|
248 |
+ int i = 1; |
|
249 |
+ while (NULL != virpp[i]) |
|
250 |
+ if (conn_reply_virus(scandata->conn, filename, virpp[i++]) == -1) { |
|
251 |
+ free(filename); |
|
252 |
+ free((void *)virpp); |
|
253 |
+ return CL_ETIMEOUT; |
|
254 |
+ } |
|
255 |
+ } |
|
245 | 256 |
if(context.virsize) |
246 | 257 |
detstats_add(virname, filename, context.virsize, context.virhash); |
247 | 258 |
if(context.virsize && optget(scandata->opts, "ExtendedDetectionInfo")->enabled) |
... | ... |
@@ -249,6 +268,11 @@ int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_rea |
249 | 249 |
else |
250 | 250 |
logg("~%s: %s FOUND\n", filename, virname); |
251 | 251 |
virusaction(filename, virname, scandata->opts); |
252 |
+ if (scandata->options & CL_SCAN_ALLMATCHES && virpp[1] != NULL) { |
|
253 |
+ int i = 1; |
|
254 |
+ while (NULL != virpp[i]) |
|
255 |
+ logg("~%s: %s FOUND\n", filename, virpp[i++]); |
|
256 |
+ } |
|
252 | 257 |
} else if (ret != CL_CLEAN) { |
253 | 258 |
scandata->errors++; |
254 | 259 |
if (conn_reply(scandata->conn, filename, cl_strerror(ret), "ERROR") == -1) { |
... | ... |
@@ -261,6 +285,8 @@ int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_rea |
261 | 261 |
} |
262 | 262 |
|
263 | 263 |
free(filename); |
264 |
+ if (ret == CL_VIRUS && scandata->options & CL_SCAN_ALLMATCHES) |
|
265 |
+ free((void *)virpp); |
|
264 | 266 |
if(ret == CL_EMEM) /* stop scanning */ |
265 | 267 |
return ret; |
266 | 268 |
|
... | ... |
@@ -94,7 +94,8 @@ static struct { |
94 | 94 |
{CMD16, sizeof(CMD16)-1, COMMAND_IDSESSION, 0, 0, 1}, |
95 | 95 |
{CMD17, sizeof(CMD17)-1, COMMAND_INSTREAM, 0, 0, 1}, |
96 | 96 |
{CMD19, sizeof(CMD19)-1, COMMAND_DETSTATSCLEAR, 0, 1, 1}, |
97 |
- {CMD20, sizeof(CMD20)-1, COMMAND_DETSTATS, 0, 1, 1} |
|
97 |
+ {CMD20, sizeof(CMD20)-1, COMMAND_DETSTATS, 0, 1, 1}, |
|
98 |
+ {CMD21, sizeof(CMD21)-1, COMMAND_ALLMATCHSCAN, 1, 0, 1} |
|
98 | 99 |
}; |
99 | 100 |
|
100 | 101 |
enum commands parse_command(const char *cmd, const char **argument, int oldstyle) |
... | ... |
@@ -314,129 +315,135 @@ int command(client_conn_t *conn, int *virus) |
314 | 314 |
} |
315 | 315 |
return ret; |
316 | 316 |
#else |
317 |
- conn_reply_error(conn, "FILDES support not compiled in."); |
|
318 |
- close(conn->scanfd); |
|
319 |
- return 0; |
|
320 |
-#endif |
|
321 |
- case COMMAND_STATS: |
|
322 |
- thrmgr_setactivetask(NULL, "STATS"); |
|
323 |
- if (conn->group) |
|
324 |
- mdprintf(desc, "%u: ", conn->id); |
|
325 |
- thrmgr_printstats(desc, conn->term); |
|
326 |
- return 0; |
|
327 |
- case COMMAND_STREAM: |
|
328 |
- thrmgr_setactivetask(NULL, "STREAM"); |
|
329 |
- ret = scanstream(desc, NULL, engine, options, opts, conn->term); |
|
330 |
- if (ret == CL_VIRUS) |
|
331 |
- *virus = 1; |
|
332 |
- if (ret == CL_EMEM) { |
|
333 |
- if(optget(opts, "ExitOnOOM")->enabled) |
|
334 |
- return -1; |
|
335 |
- else |
|
336 |
- return 1; |
|
337 |
- } |
|
338 |
- return 0; |
|
339 |
- case COMMAND_INSTREAMSCAN: |
|
340 |
- thrmgr_setactivetask(NULL, "INSTREAM"); |
|
341 |
- ret = scanfd(conn, NULL, engine, options, opts, desc, 1); |
|
342 |
- if (ret == CL_VIRUS) { |
|
343 |
- *virus = 1; |
|
344 |
- ret = 0; |
|
345 |
- } else if (ret == CL_EMEM) { |
|
346 |
- if(optget(opts, "ExitOnOOM")->enabled) |
|
347 |
- ret = -1; |
|
348 |
- else |
|
349 |
- ret = 1; |
|
350 |
- } else if (ret == CL_ETIMEOUT) { |
|
351 |
- thrmgr_group_terminate(conn->group); |
|
352 |
- ret = 1; |
|
353 |
- } else |
|
354 |
- ret = 0; |
|
355 |
- if (ftruncate(conn->scanfd, 0) == -1) { |
|
356 |
- /* not serious, we're going to close it and unlink it anyway */ |
|
357 |
- logg("*ftruncate failed: %d\n", errno); |
|
358 |
- } |
|
359 |
- close(conn->scanfd); |
|
360 |
- conn->scanfd = -1; |
|
361 |
- cli_unlink(conn->filename); |
|
362 |
- return ret; |
|
363 |
- default: |
|
364 |
- logg("!Invalid command distpached: %d\n", conn->cmdtype); |
|
365 |
- return 1; |
|
366 |
- } |
|
367 |
- |
|
368 |
- scandata.type = type; |
|
369 |
- maxdirrec = optget(opts, "MaxDirectoryRecursion")->numarg; |
|
370 |
- if (optget(opts, "FollowDirectorySymlinks")->enabled) |
|
371 |
- flags |= CLI_FTW_FOLLOW_DIR_SYMLINK; |
|
372 |
- if (optget(opts, "FollowFileSymlinks")->enabled) |
|
373 |
- flags |= CLI_FTW_FOLLOW_FILE_SYMLINK; |
|
374 |
- |
|
375 |
- if(!optget(opts, "CrossFilesystems")->enabled) |
|
376 |
- if(STAT(conn->filename, &sb) == 0) |
|
377 |
- scandata.dev = sb.st_dev; |
|
378 |
- |
|
379 |
- ret = cli_ftw(conn->filename, flags, maxdirrec ? maxdirrec : INT_MAX, scan_callback, &data, scan_pathchk); |
|
380 |
- if (ret == CL_EMEM) { |
|
381 |
- if(optget(opts, "ExitOnOOM")->enabled) |
|
382 |
- return -1; |
|
383 |
- else |
|
384 |
- return 1; |
|
385 |
- } |
|
386 |
- if (scandata.group && type == TYPE_MULTISCAN) { |
|
387 |
- thrmgr_group_waitforall(group, &ok, &error, &total); |
|
388 |
- pthread_mutex_lock(&conn->thrpool->pool_mutex); |
|
389 |
- conn->thrpool->thr_multiscan--; |
|
390 |
- pthread_mutex_unlock(&conn->thrpool->pool_mutex); |
|
391 |
- } else { |
|
392 |
- error = scandata.errors; |
|
393 |
- total = scandata.total; |
|
394 |
- ok = total - error - scandata.infected; |
|
395 |
- } |
|
396 |
- |
|
397 |
- if (ok + error == total && (error != total)) { |
|
398 |
- if (conn_reply_single(conn, conn->filename, "OK") == -1) |
|
399 |
- ret = CL_ETIMEOUT; |
|
400 |
- } |
|
401 |
- *virus = total - (ok + error); |
|
402 |
- |
|
403 |
- if (ret == CL_ETIMEOUT) |
|
404 |
- thrmgr_group_terminate(conn->group); |
|
405 |
- return error; |
|
406 |
-} |
|
407 |
- |
|
408 |
-static int dispatch_command(client_conn_t *conn, enum commands cmd, const char *argument) |
|
409 |
-{ |
|
410 |
- int ret = 0; |
|
411 |
- int bulk; |
|
412 |
- client_conn_t *dup_conn = (client_conn_t *) malloc(sizeof(struct client_conn_tag)); |
|
413 |
- |
|
414 |
- if(!dup_conn) { |
|
415 |
- logg("!Can't allocate memory for client_conn\n"); |
|
416 |
- return -1; |
|
417 |
- } |
|
418 |
- memcpy(dup_conn, conn, sizeof(*conn)); |
|
419 |
- dup_conn->cmdtype = cmd; |
|
420 |
- if(cl_engine_addref(dup_conn->engine)) { |
|
421 |
- logg("!cl_engine_addref() failed\n"); |
|
422 |
- free(dup_conn); |
|
423 |
- return -1; |
|
424 |
- } |
|
425 |
- dup_conn->scanfd = -1; |
|
426 |
- bulk = 1; |
|
427 |
- switch (cmd) { |
|
428 |
- case COMMAND_FILDES: |
|
429 |
- if (conn->scanfd == -1) { |
|
430 |
- conn_reply_error(dup_conn, "No file descriptor received."); |
|
431 |
- ret = 1; |
|
432 |
- } |
|
433 |
- dup_conn->scanfd = conn->scanfd; |
|
434 |
- /* consume FD */ |
|
435 |
- conn->scanfd = -1; |
|
436 |
- break; |
|
437 |
- case COMMAND_SCAN: |
|
438 |
- case COMMAND_CONTSCAN: |
|
439 |
- case COMMAND_MULTISCAN: |
|
317 |
+ conn_reply_error(conn, "FILDES support not compiled in."); |
|
318 |
+ close(conn->scanfd); |
|
319 |
+ return 0; |
|
320 |
+ #endif |
|
321 |
+ case COMMAND_STATS: |
|
322 |
+ thrmgr_setactivetask(NULL, "STATS"); |
|
323 |
+ if (conn->group) |
|
324 |
+ mdprintf(desc, "%u: ", conn->id); |
|
325 |
+ thrmgr_printstats(desc, conn->term); |
|
326 |
+ return 0; |
|
327 |
+ case COMMAND_STREAM: |
|
328 |
+ thrmgr_setactivetask(NULL, "STREAM"); |
|
329 |
+ ret = scanstream(desc, NULL, engine, options, opts, conn->term); |
|
330 |
+ if (ret == CL_VIRUS) |
|
331 |
+ *virus = 1; |
|
332 |
+ if (ret == CL_EMEM) { |
|
333 |
+ if(optget(opts, "ExitOnOOM")->enabled) |
|
334 |
+ return -1; |
|
335 |
+ else |
|
336 |
+ return 1; |
|
337 |
+ } |
|
338 |
+ return 0; |
|
339 |
+ case COMMAND_INSTREAMSCAN: |
|
340 |
+ thrmgr_setactivetask(NULL, "INSTREAM"); |
|
341 |
+ ret = scanfd(conn, NULL, engine, options, opts, desc, 1); |
|
342 |
+ if (ret == CL_VIRUS) { |
|
343 |
+ *virus = 1; |
|
344 |
+ ret = 0; |
|
345 |
+ } else if (ret == CL_EMEM) { |
|
346 |
+ if(optget(opts, "ExitOnOOM")->enabled) |
|
347 |
+ ret = -1; |
|
348 |
+ else |
|
349 |
+ ret = 1; |
|
350 |
+ } else if (ret == CL_ETIMEOUT) { |
|
351 |
+ thrmgr_group_terminate(conn->group); |
|
352 |
+ ret = 1; |
|
353 |
+ } else |
|
354 |
+ ret = 0; |
|
355 |
+ if (ftruncate(conn->scanfd, 0) == -1) { |
|
356 |
+ /* not serious, we're going to close it and unlink it anyway */ |
|
357 |
+ logg("*ftruncate failed: %d\n", errno); |
|
358 |
+ } |
|
359 |
+ close(conn->scanfd); |
|
360 |
+ conn->scanfd = -1; |
|
361 |
+ cli_unlink(conn->filename); |
|
362 |
+ return ret; |
|
363 |
+ case COMMAND_ALLMATCHSCAN: |
|
364 |
+ thrmgr_setactivetask(NULL, "ALLMATCHSCAN"); |
|
365 |
+ scandata.options |= CL_SCAN_ALLMATCHES; |
|
366 |
+ type = TYPE_SCAN; |
|
367 |
+ break; |
|
368 |
+ default: |
|
369 |
+ logg("!Invalid command distpached: %d\n", conn->cmdtype); |
|
370 |
+ return 1; |
|
371 |
+ } |
|
372 |
+ |
|
373 |
+ scandata.type = type; |
|
374 |
+ maxdirrec = optget(opts, "MaxDirectoryRecursion")->numarg; |
|
375 |
+ if (optget(opts, "FollowDirectorySymlinks")->enabled) |
|
376 |
+ flags |= CLI_FTW_FOLLOW_DIR_SYMLINK; |
|
377 |
+ if (optget(opts, "FollowFileSymlinks")->enabled) |
|
378 |
+ flags |= CLI_FTW_FOLLOW_FILE_SYMLINK; |
|
379 |
+ |
|
380 |
+ if(!optget(opts, "CrossFilesystems")->enabled) |
|
381 |
+ if(STAT(conn->filename, &sb) == 0) |
|
382 |
+ scandata.dev = sb.st_dev; |
|
383 |
+ |
|
384 |
+ ret = cli_ftw(conn->filename, flags, maxdirrec ? maxdirrec : INT_MAX, scan_callback, &data, scan_pathchk); |
|
385 |
+ if (ret == CL_EMEM) { |
|
386 |
+ if(optget(opts, "ExitOnOOM")->enabled) |
|
387 |
+ return -1; |
|
388 |
+ else |
|
389 |
+ return 1; |
|
390 |
+ } |
|
391 |
+ if (scandata.group && type == TYPE_MULTISCAN) { |
|
392 |
+ thrmgr_group_waitforall(group, &ok, &error, &total); |
|
393 |
+ pthread_mutex_lock(&conn->thrpool->pool_mutex); |
|
394 |
+ conn->thrpool->thr_multiscan--; |
|
395 |
+ pthread_mutex_unlock(&conn->thrpool->pool_mutex); |
|
396 |
+ } else { |
|
397 |
+ error = scandata.errors; |
|
398 |
+ total = scandata.total; |
|
399 |
+ ok = total - error - scandata.infected; |
|
400 |
+ } |
|
401 |
+ |
|
402 |
+ if (ok + error == total && (error != total)) { |
|
403 |
+ if (conn_reply_single(conn, conn->filename, "OK") == -1) |
|
404 |
+ ret = CL_ETIMEOUT; |
|
405 |
+ } |
|
406 |
+ *virus = total - (ok + error); |
|
407 |
+ |
|
408 |
+ if (ret == CL_ETIMEOUT) |
|
409 |
+ thrmgr_group_terminate(conn->group); |
|
410 |
+ return error; |
|
411 |
+ } |
|
412 |
+ |
|
413 |
+ static int dispatch_command(client_conn_t *conn, enum commands cmd, const char *argument) |
|
414 |
+ { |
|
415 |
+ int ret = 0; |
|
416 |
+ int bulk; |
|
417 |
+ client_conn_t *dup_conn = (client_conn_t *) malloc(sizeof(struct client_conn_tag)); |
|
418 |
+ |
|
419 |
+ if(!dup_conn) { |
|
420 |
+ logg("!Can't allocate memory for client_conn\n"); |
|
421 |
+ return -1; |
|
422 |
+ } |
|
423 |
+ memcpy(dup_conn, conn, sizeof(*conn)); |
|
424 |
+ dup_conn->cmdtype = cmd; |
|
425 |
+ if(cl_engine_addref(dup_conn->engine)) { |
|
426 |
+ logg("!cl_engine_addref() failed\n"); |
|
427 |
+ free(dup_conn); |
|
428 |
+ return -1; |
|
429 |
+ } |
|
430 |
+ dup_conn->scanfd = -1; |
|
431 |
+ bulk = 1; |
|
432 |
+ switch (cmd) { |
|
433 |
+ case COMMAND_FILDES: |
|
434 |
+ if (conn->scanfd == -1) { |
|
435 |
+ conn_reply_error(dup_conn, "No file descriptor received."); |
|
436 |
+ ret = 1; |
|
437 |
+ } |
|
438 |
+ dup_conn->scanfd = conn->scanfd; |
|
439 |
+ /* consume FD */ |
|
440 |
+ conn->scanfd = -1; |
|
441 |
+ break; |
|
442 |
+ case COMMAND_SCAN: |
|
443 |
+ case COMMAND_CONTSCAN: |
|
444 |
+ case COMMAND_MULTISCAN: |
|
445 |
+ case COMMAND_ALLMATCHSCAN: |
|
440 | 446 |
dup_conn->filename = cli_strdup_to_utf8(argument); |
441 | 447 |
if (!dup_conn->filename) { |
442 | 448 |
logg("!Failed to allocate memory for filename\n"); |
... | ... |
@@ -608,6 +615,7 @@ int execute_or_dispatch_command(client_conn_t *conn, enum commands cmd, const ch |
608 | 608 |
case COMMAND_FILDES: |
609 | 609 |
case COMMAND_SCAN: |
610 | 610 |
case COMMAND_INSTREAMSCAN: |
611 |
+ case COMMAND_ALLMATCHSCAN: |
|
611 | 612 |
return dispatch_command(conn, cmd, argument); |
612 | 613 |
case COMMAND_IDSESSION: |
613 | 614 |
conn->group = thrmgr_group_new(); |
... | ... |
@@ -43,6 +43,8 @@ |
43 | 43 |
#define CMD19 "DETSTATSCLEAR" |
44 | 44 |
#define CMD20 "DETSTATS" |
45 | 45 |
|
46 |
+#define CMD21 "ALLMATCHSCAN" |
|
47 |
+ |
|
46 | 48 |
#include "libclamav/clamav.h" |
47 | 49 |
#include "shared/optparser.h" |
48 | 50 |
#include "server.h" |
... | ... |
@@ -70,7 +72,8 @@ enum commands { |
70 | 70 |
COMMAND_DETSTATS, |
71 | 71 |
/* internal commands */ |
72 | 72 |
COMMAND_MULTISCANFILE, |
73 |
- COMMAND_INSTREAMSCAN |
|
73 |
+ COMMAND_INSTREAMSCAN, |
|
74 |
+ COMMAND_ALLMATCHSCAN |
|
74 | 75 |
}; |
75 | 76 |
|
76 | 77 |
typedef struct client_conn_tag { |
... | ... |
@@ -236,7 +236,9 @@ int client(const struct optstruct *opts, int *infected, int *err) |
236 | 236 |
if(remote || scandash) { |
237 | 237 |
scantype = STREAM; |
238 | 238 |
session = optget(opts, "multiscan")->enabled; |
239 |
- } else if(optget(opts, "multiscan")->enabled) scantype = MULTI; |
|
239 |
+ } |
|
240 |
+ else if(optget(opts, "multiscan")->enabled) scantype = MULTI; |
|
241 |
+ else if(optget(opts, "allmatch")->enabled) scantype = ALLMATCH; |
|
240 | 242 |
else scantype = CONT; |
241 | 243 |
|
242 | 244 |
maxrec = optget(clamdopts, "MaxDirectoryRecursion")->numarg; |
... | ... |
@@ -58,7 +58,7 @@ extern unsigned long int maxstream; |
58 | 58 |
int printinfected; |
59 | 59 |
extern struct optstruct *clamdopts; |
60 | 60 |
|
61 |
-static const char *scancmd[] = { "CONTSCAN", "MULTISCAN" }; |
|
61 |
+static const char *scancmd[] = { "CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", "ALLMATCHSCAN" }; |
|
62 | 62 |
|
63 | 63 |
/* Connects to clamd |
64 | 64 |
* Returns a FD or -1 on error */ |
... | ... |
@@ -203,6 +203,7 @@ int dsresult(int sockd, int scantype, const char *filename, int *printok, int *e |
203 | 203 |
switch(scantype) { |
204 | 204 |
case MULTI: |
205 | 205 |
case CONT: |
206 |
+ case ALLMATCH: |
|
206 | 207 |
if (!filename) { |
207 | 208 |
logg("Filename cannot be NULL for MULTISCAN or CONTSCAN.\n"); |
208 | 209 |
return -1; |
... | ... |
@@ -254,7 +255,13 @@ int dsresult(int sockd, int scantype, const char *filename, int *printok, int *e |
254 | 254 |
colon = strrchr(bol, ':'); |
255 | 255 |
} |
256 | 256 |
if(!colon) { |
257 |
- logg("Failed to parse reply\n"); |
|
257 |
+ char * unkco = "UNKNOWN COMMAND"; |
|
258 |
+ if (!strncmp(bol, unkco, sizeof(unkco) - 1)) |
|
259 |
+ logg("clamd replied \"UNKNOWN COMMAND\". Command was %s\n", |
|
260 |
+ (scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" : |
|
261 |
+ scancmd[scantype]); |
|
262 |
+ else |
|
263 |
+ logg("Failed to parse reply: \"%s\"\n", bol); |
|
258 | 264 |
return -1; |
259 | 265 |
} else if(!memcmp(eol - 7, " FOUND", 6)) { |
260 | 266 |
*(eol - 7) = 0; |
... | ... |
@@ -217,6 +217,7 @@ static void scanfile(const char *filename, struct cl_engine *engine, const struc |
217 | 217 |
unsigned i; |
218 | 218 |
const struct optstruct *opt; |
219 | 219 |
const char *virname; |
220 |
+ const char **virpp = &virname; |
|
220 | 221 |
STATBUF sb; |
221 | 222 |
struct metachain chain; |
222 | 223 |
|
... | ... |
@@ -291,7 +292,7 @@ static void scanfile(const char *filename, struct cl_engine *engine, const struc |
291 | 291 |
} |
292 | 292 |
|
293 | 293 |
|
294 |
- if((ret = cl_scandesc_callback(fd, &virname, &info.blocks, engine, options, &chain)) == CL_VIRUS) { |
|
294 |
+ if((ret = cl_scandesc_callback(fd, virpp, &info.blocks, engine, options, &chain)) == CL_VIRUS) { |
|
295 | 295 |
if(optget(opts, "archive-verbose")->enabled) { |
296 | 296 |
if (chain.n > 1) { |
297 | 297 |
char str[128]; |
... | ... |
@@ -300,7 +301,16 @@ static void scanfile(const char *filename, struct cl_engine *engine, const struc |
300 | 300 |
} else if (chain.lastvir) |
301 | 301 |
logg("~%s!(%d): %s FOUND\n", filename, chain.lastvir-1, virname); |
302 | 302 |
} |
303 |
- logg("~%s: %s FOUND\n", filename, virname); |
|
303 |
+ if (options & CL_SCAN_ALLMATCHES) { |
|
304 |
+ int i = 0; |
|
305 |
+ virpp = (const char **)*virpp; /* horrible */ |
|
306 |
+ virname = virpp[0]; |
|
307 |
+ while (virpp[i]) |
|
308 |
+ logg("~%s: %s FOUND\n", filename, virpp[i++]); |
|
309 |
+ free((void *)virpp); |
|
310 |
+ } |
|
311 |
+ else |
|
312 |
+ logg("~%s: %s FOUND\n", filename, virname); |
|
304 | 313 |
info.files++; |
305 | 314 |
info.ifiles++; |
306 | 315 |
|
... | ... |
@@ -432,6 +442,8 @@ static int scanstdin(const struct cl_engine *engine, const struct optstruct *opt |
432 | 432 |
int ret; |
433 | 433 |
unsigned int fsize = 0; |
434 | 434 |
const char *virname, *tmpdir; |
435 |
+ const char **virpp = &virname; |
|
436 |
+ |
|
435 | 437 |
char *file, buff[FILEBUFF]; |
436 | 438 |
size_t bread; |
437 | 439 |
FILE *fs; |
... | ... |
@@ -474,7 +486,17 @@ static int scanstdin(const struct cl_engine *engine, const struct optstruct *opt |
474 | 474 |
info.rblocks += fsize / CL_COUNT_PRECISION; |
475 | 475 |
|
476 | 476 |
if((ret = cl_scanfile(file, &virname, &info.blocks, engine, options)) == CL_VIRUS) { |
477 |
- logg("stdin: %s FOUND\n", virname); |
|
477 |
+ if (options & CL_SCAN_ALLMATCHES) { |
|
478 |
+ int i = 0; |
|
479 |
+ virpp = (const char **)*virpp; /* temp hack for scanall mode until api augmentation */ |
|
480 |
+ virname = virpp[0]; |
|
481 |
+ while (virpp[i]) |
|
482 |
+ logg("stdin: %s FOUND\n", virpp[i++]); |
|
483 |
+ free((void *)virpp); |
|
484 |
+ } |
|
485 |
+ else |
|
486 |
+ logg("stdin: %s FOUND\n", virname); |
|
487 |
+ |
|
478 | 488 |
info.ifiles++; |
479 | 489 |
|
480 | 490 |
if(bell) |
... | ... |
@@ -710,6 +732,9 @@ int scanmanager(const struct optstruct *opts) |
710 | 710 |
} |
711 | 711 |
|
712 | 712 |
/* set scan options */ |
713 |
+ if(optget(opts, "allmatch")->enabled) |
|
714 |
+ options |= CL_SCAN_ALLMATCHES; |
|
715 |
+ |
|
713 | 716 |
if(optget(opts,"phishing-ssl")->enabled) |
714 | 717 |
options |= CL_SCAN_PHISHING_BLOCKSSL; |
715 | 718 |
|
... | ... |
@@ -81,6 +81,7 @@ int cli_7unz (cli_ctx *ctx, size_t offset) { |
81 | 81 |
UInt16 utf16buf[UTFBUFSZ], *utf16name = utf16buf; |
82 | 82 |
int namelen = UTFBUFSZ, found = CL_CLEAN; |
83 | 83 |
Int64 begin_of_archive = offset; |
84 |
+ UInt32 viruses_found = 0; |
|
84 | 85 |
|
85 | 86 |
/* Replacement for |
86 | 87 |
FileInStream_CreateVTable(&archiveStream); */ |
... | ... |
@@ -150,14 +151,19 @@ int cli_7unz (cli_ctx *ctx, size_t offset) { |
150 | 150 |
encrypted = 1; |
151 | 151 |
if(DETECT_ENCRYPTED) { |
152 | 152 |
cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n"); |
153 |
- *ctx->virname = "Heuristics.Encrypted.7Zip"; |
|
154 |
- found = CL_VIRUS; |
|
155 |
- break; |
|
153 |
+ cli_append_virus(ctx, "Heuristics.Encrypted.7Zip"); |
|
154 |
+ viruses_found++; |
|
155 |
+ if(!SCAN_ALL) { |
|
156 |
+ found = CL_VIRUS; |
|
157 |
+ break; |
|
158 |
+ } |
|
156 | 159 |
} |
157 | 160 |
} |
158 | 161 |
if(cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) { |
159 | 162 |
found = CL_VIRUS; |
160 |
- break; |
|
163 |
+ viruses_found++; |
|
164 |
+ if (!SCAN_ALL) |
|
165 |
+ break; |
|
161 | 166 |
} |
162 | 167 |
if (res != SZ_OK) |
163 | 168 |
cli_dbgmsg("cli_unz: extraction failed with %d\n", res); |
... | ... |
@@ -169,14 +175,16 @@ int cli_7unz (cli_ctx *ctx, size_t offset) { |
169 | 169 |
if(cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed) |
170 | 170 |
found = CL_EWRITE; |
171 | 171 |
else |
172 |
- found = cli_magic_scandesc(fd, ctx); |
|
172 |
+ if ((found = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) |
|
173 |
+ viruses_found++; |
|
173 | 174 |
close(fd); |
174 | 175 |
if(!ctx->engine->keeptmp && cli_unlink(name)) |
175 | 176 |
found = CL_EUNLINK; |
176 | 177 |
|
177 | 178 |
free(name); |
178 | 179 |
if(found != CL_CLEAN) |
179 |
- break; |
|
180 |
+ if (!(SCAN_ALL && found == CL_VIRUS)) |
|
181 |
+ break; |
|
180 | 182 |
} |
181 | 183 |
} |
182 | 184 |
IAlloc_Free(&allocImp, outBuffer); |
... | ... |
@@ -196,5 +204,7 @@ int cli_7unz (cli_ctx *ctx, size_t offset) { |
196 | 196 |
else |
197 | 197 |
cli_dbgmsg("cli_7unz: error %d\n", res); |
198 | 198 |
|
199 |
+ if (SCAN_ALL && viruses_found) |
|
200 |
+ return CL_VIRUS; |
|
199 | 201 |
return found; |
200 | 202 |
} |
... | ... |
@@ -2594,7 +2594,7 @@ int cli_bytecode_context_setfile(struct cli_bc_ctx *ctx, fmap_t *map) |
2594 | 2594 |
|
2595 | 2595 |
int cli_bytecode_runlsig(cli_ctx *cctx, struct cli_target_info *tinfo, |
2596 | 2596 |
const struct cli_all_bc *bcs, unsigned bc_idx, |
2597 |
- const char **virname, const uint32_t* lsigcnt, |
|
2597 |
+ const uint32_t* lsigcnt, |
|
2598 | 2598 |
const uint32_t *lsigsuboff, fmap_t *map) |
2599 | 2599 |
{ |
2600 | 2600 |
int ret; |
... | ... |
@@ -2641,9 +2641,8 @@ int cli_bytecode_runlsig(cli_ctx *cctx, struct cli_target_info *tinfo, |
2641 | 2641 |
if (ctx.virname) { |
2642 | 2642 |
int rc; |
2643 | 2643 |
cli_dbgmsg("Bytecode found virus: %s\n", ctx.virname); |
2644 |
- if (virname) |
|
2645 |
- *virname = ctx.virname; |
|
2646 |
- if (!strncmp(*virname, "BC.Heuristics", 13)) |
|
2644 |
+ cli_append_virus(cctx, ctx.virname); |
|
2645 |
+ if (!strncmp(ctx.virname, "BC.Heuristics", 13)) |
|
2647 | 2646 |
rc = cli_found_possibly_unwanted(cctx); |
2648 | 2647 |
else |
2649 | 2648 |
rc = CL_VIRUS; |
... | ... |
@@ -2657,7 +2656,7 @@ int cli_bytecode_runlsig(cli_ctx *cctx, struct cli_target_info *tinfo, |
2657 | 2657 |
} |
2658 | 2658 |
|
2659 | 2659 |
int cli_bytecode_runhook(cli_ctx *cctx, const struct cl_engine *engine, struct cli_bc_ctx *ctx, |
2660 |
- unsigned id, fmap_t *map, const char **virname) |
|
2660 |
+ unsigned id, fmap_t *map) |
|
2661 | 2661 |
{ |
2662 | 2662 |
const unsigned *hooks = engine->hooks[id - _BC_START_HOOKS]; |
2663 | 2663 |
unsigned i, hooks_cnt = engine->hooks_cnt[id - _BC_START_HOOKS]; |
... | ... |
@@ -2690,10 +2689,13 @@ int cli_bytecode_runhook(cli_ctx *cctx, const struct cl_engine *engine, struct c |
2690 | 2690 |
} |
2691 | 2691 |
if (ctx->virname) { |
2692 | 2692 |
cli_dbgmsg("Bytecode found virus: %s\n", ctx->virname); |
2693 |
- if (virname) |
|
2694 |
- *virname = ctx->virname; |
|
2695 |
- cli_bytecode_context_clear(ctx); |
|
2696 |
- return CL_VIRUS; |
|
2693 |
+ cli_append_virus(cctx, ctx->virname); |
|
2694 |
+ if (!(cctx->options & CL_SCAN_ALLMATCHES)) { |
|
2695 |
+ cli_bytecode_context_clear(ctx); |
|
2696 |
+ return CL_VIRUS; |
|
2697 |
+ } |
|
2698 |
+ cli_bytecode_context_reset(ctx); |
|
2699 |
+ continue; |
|
2697 | 2700 |
} |
2698 | 2701 |
ret = cli_bytecode_context_getresult_int(ctx); |
2699 | 2702 |
/* TODO: use prefix here */ |
... | ... |
@@ -2726,10 +2728,15 @@ int cli_bytecode_runhook(cli_ctx *cctx, const struct cl_engine *engine, struct c |
2726 | 2726 |
} |
2727 | 2727 |
free(tempfile); |
2728 | 2728 |
if (ret != CL_CLEAN) { |
2729 |
- if (ret == CL_VIRUS) |
|
2729 |
+ if (ret == CL_VIRUS) { |
|
2730 | 2730 |
cli_dbgmsg("Scanning unpacked file by bytecode %u found a virus\n", bc->id); |
2731 |
- cli_bytecode_context_clear(ctx); |
|
2732 |
- return ret; |
|
2731 |
+ if (cctx->options & CL_SCAN_ALLMATCHES) { |
|
2732 |
+ cli_bytecode_context_reset(ctx); |
|
2733 |
+ continue; |
|
2734 |
+ } |
|
2735 |
+ cli_bytecode_context_clear(ctx); |
|
2736 |
+ return ret; |
|
2737 |
+ } |
|
2733 | 2738 |
} |
2734 | 2739 |
cli_bytecode_context_reset(ctx); |
2735 | 2740 |
continue; |
... | ... |
@@ -118,8 +118,8 @@ void cli_bytecode_describe(const struct cli_bc *bc); |
118 | 118 |
struct cli_exe_info; |
119 | 119 |
struct cli_ctx_tag; |
120 | 120 |
struct cli_target_info; |
121 |
-int cli_bytecode_runlsig(struct cli_ctx_tag *ctx, struct cli_target_info *info, const struct cli_all_bc *bcs, unsigned bc_idx, const char **virname, const uint32_t* lsigcnt, const uint32_t *lsigsuboff, fmap_t *map); |
|
122 |
-int cli_bytecode_runhook(struct cli_ctx_tag *cctx, const struct cl_engine *engine, struct cli_bc_ctx *ctx, unsigned id, fmap_t *map, const char **virname); |
|
121 |
+int cli_bytecode_runlsig(struct cli_ctx_tag *ctx, struct cli_target_info *info, const struct cli_all_bc *bcs, unsigned bc_idx, const uint32_t* lsigcnt, const uint32_t *lsigsuboff, fmap_t *map); |
|
122 |
+int cli_bytecode_runhook(struct cli_ctx_tag *cctx, const struct cl_engine *engine, struct cli_bc_ctx *ctx, unsigned id, fmap_t *map); |
|
123 | 123 |
|
124 | 124 |
#ifdef __cplusplus |
125 | 125 |
extern "C" { |
... | ... |
@@ -511,8 +511,7 @@ int32_t cli_bcapi_extract_new(struct cli_bc_ctx *ctx, int32_t id) |
511 | 511 |
cctx->recursion--; |
512 | 512 |
cctx->container_type = current; |
513 | 513 |
if (res == CL_VIRUS) { |
514 |
- if (cctx->virname) |
|
515 |
- ctx->virname = *cctx->virname; |
|
514 |
+ ctx->virname = cli_get_last_virus(cctx); |
|
516 | 515 |
ctx->found = 1; |
517 | 516 |
} |
518 | 517 |
} |
... | ... |
@@ -142,6 +142,7 @@ typedef enum { |
142 | 142 |
#define CL_SCAN_PARTIAL_MESSAGE 0x40000 |
143 | 143 |
#define CL_SCAN_HEURISTIC_PRECEDENCE 0x80000 |
144 | 144 |
#define CL_SCAN_BLOCKMACROS 0x100000 |
145 |
+#define CL_SCAN_ALLMATCHES 0x200000 |
|
145 | 146 |
|
146 | 147 |
#define CL_SCAN_PERFORMANCE_INFO 0x40000000 /* collect performance timings */ |
147 | 148 |
#define CL_SCAN_INTERNAL_COLLECT_SHA 0x80000000 /* Enables hash output in sha-collect builds - for internal use only */ |
... | ... |
@@ -73,7 +73,7 @@ int cli_scanelf(cli_ctx *ctx) |
73 | 73 |
uint8_t conv = 0, err; |
74 | 74 |
unsigned int format; |
75 | 75 |
fmap_t *map = *ctx->fmap; |
76 |
- |
|
76 |
+ uint32_t viruses_found = 0; |
|
77 | 77 |
|
78 | 78 |
cli_dbgmsg("in cli_scanelf\n"); |
79 | 79 |
|
... | ... |
@@ -214,8 +214,7 @@ int cli_scanelf(cli_ctx *ctx) |
214 | 214 |
if(phnum > 128) { |
215 | 215 |
cli_dbgmsg("ELF: Suspicious number of program headers\n"); |
216 | 216 |
if(DETECT_BROKEN) { |
217 |
- if(ctx->virname) |
|
218 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
217 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
219 | 218 |
return CL_VIRUS; |
220 | 219 |
} |
221 | 220 |
return CL_EFORMAT; |
... | ... |
@@ -227,8 +226,7 @@ int cli_scanelf(cli_ctx *ctx) |
227 | 227 |
if(phentsize != sizeof(struct elf_program_hdr32)) { |
228 | 228 |
cli_dbgmsg("ELF: phentsize != sizeof(struct elf_program_hdr32)\n"); |
229 | 229 |
if(DETECT_BROKEN) { |
230 |
- if(ctx->virname) |
|
231 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
230 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
232 | 231 |
return CL_VIRUS; |
233 | 232 |
} |
234 | 233 |
return CL_EFORMAT; |
... | ... |
@@ -275,8 +273,7 @@ int cli_scanelf(cli_ctx *ctx) |
275 | 275 |
cli_dbgmsg("ELF: Possibly broken ELF file\n"); |
276 | 276 |
free(program_hdr); |
277 | 277 |
if(DETECT_BROKEN) { |
278 |
- if(ctx->virname) |
|
279 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
278 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
280 | 279 |
return CL_VIRUS; |
281 | 280 |
} |
282 | 281 |
return CL_CLEAN; |
... | ... |
@@ -296,8 +293,7 @@ int cli_scanelf(cli_ctx *ctx) |
296 | 296 |
if(err) { |
297 | 297 |
cli_dbgmsg("ELF: Can't calculate file offset of entry point\n"); |
298 | 298 |
if(DETECT_BROKEN) { |
299 |
- if(ctx->virname) |
|
300 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
299 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
301 | 300 |
return CL_VIRUS; |
302 | 301 |
} |
303 | 302 |
return CL_EFORMAT; |
... | ... |
@@ -319,8 +315,7 @@ int cli_scanelf(cli_ctx *ctx) |
319 | 319 |
if(shentsize != sizeof(struct elf_section_hdr32)) { |
320 | 320 |
cli_dbgmsg("ELF: shentsize != sizeof(struct elf_section_hdr32)\n"); |
321 | 321 |
if(DETECT_BROKEN) { |
322 |
- if(ctx->virname) |
|
323 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
322 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
324 | 323 |
return CL_VIRUS; |
325 | 324 |
} |
326 | 325 |
return CL_EFORMAT; |
... | ... |
@@ -369,8 +364,7 @@ int cli_scanelf(cli_ctx *ctx) |
369 | 369 |
cli_dbgmsg("ELF: Possibly broken ELF file\n"); |
370 | 370 |
free(section_hdr); |
371 | 371 |
if(DETECT_BROKEN) { |
372 |
- if(ctx->virname) |
|
373 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
372 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
374 | 373 |
return CL_VIRUS; |
375 | 374 |
} |
376 | 375 |
return CL_CLEAN; |
... | ... |
@@ -175,8 +175,7 @@ struct macho_fat_arch |
175 | 175 |
if(matcher) \ |
176 | 176 |
return -1; \ |
177 | 177 |
if(DETECT_BROKEN) { \ |
178 |
- if(ctx->virname) \ |
|
179 |
- *ctx->virname = "Heuristics.Broken.Executable"; \ |
|
178 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); \ |
|
180 | 179 |
return CL_VIRUS; \ |
181 | 180 |
} \ |
182 | 181 |
return CL_EFORMAT |
... | ... |
@@ -1157,7 +1157,7 @@ void cli_ac_chkmacro(struct cli_matcher *root, struct cli_ac_data *data, unsigne |
1157 | 1157 |
} |
1158 | 1158 |
|
1159 | 1159 |
|
1160 |
-int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx) |
|
1160 |
+int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int mode, cli_ctx *ctx) |
|
1161 | 1161 |
{ |
1162 | 1162 |
struct cli_ac_node *current; |
1163 | 1163 |
struct cli_ac_patt *patt, *pt; |
... | ... |
@@ -1359,11 +1359,18 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
1359 | 1359 |
pt = pt->next_same; |
1360 | 1360 |
continue; |
1361 | 1361 |
} else { |
1362 |
- if(virname) |
|
1363 |
- *virname = pt->virname; |
|
1362 |
+ if(virname) { |
|
1363 |
+ if (ctx && SCAN_ALL && virname == ctx->virname) |
|
1364 |
+ cli_append_virus(ctx, (const char *)pt->virname); |
|
1365 |
+ else |
|
1366 |
+ *virname = pt->virname; |
|
1367 |
+ } |
|
1364 | 1368 |
if(customdata) |
1365 | 1369 |
*customdata = pt->customdata; |
1366 |
- return CL_VIRUS; |
|
1370 |
+ if (!ctx || !SCAN_ALL) |
|
1371 |
+ return CL_VIRUS; |
|
1372 |
+ pt = pt->next_same; |
|
1373 |
+ continue; |
|
1367 | 1374 |
} |
1368 | 1375 |
} |
1369 | 1376 |
} |
... | ... |
@@ -1403,11 +1410,18 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
1403 | 1403 |
pt = pt->next_same; |
1404 | 1404 |
continue; |
1405 | 1405 |
} else { |
1406 |
- if(virname) |
|
1407 |
- *virname = pt->virname; |
|
1406 |
+ if(virname) { |
|
1407 |
+ if (ctx && SCAN_ALL && virname == ctx->virname) |
|
1408 |
+ cli_append_virus(ctx, pt->virname); |
|
1409 |
+ else |
|
1410 |
+ *virname = pt->virname; |
|
1411 |
+ } |
|
1408 | 1412 |
if(customdata) |
1409 | 1413 |
*customdata = pt->customdata; |
1410 |
- return CL_VIRUS; |
|
1414 |
+ if (!ctx || !SCAN_ALL) |
|
1415 |
+ return CL_VIRUS; |
|
1416 |
+ pt = pt->next_same; |
|
1417 |
+ continue; |
|
1411 | 1418 |
} |
1412 | 1419 |
} |
1413 | 1420 |
} |
... | ... |
@@ -93,7 +93,7 @@ int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs, |
93 | 93 |
void cli_ac_chkmacro(struct cli_matcher *root, struct cli_ac_data *data, unsigned lsigid1); |
94 | 94 |
int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigned int *cnt, uint64_t *ids, unsigned int parse_only); |
95 | 95 |
void cli_ac_freedata(struct cli_ac_data *data); |
96 |
-int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx); |
|
96 |
+int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int mode, cli_ctx *ctx); |
|
97 | 97 |
int cli_ac_buildtrie(struct cli_matcher *root); |
98 | 98 |
int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth, uint8_t dconf_prefiltering); |
99 | 99 |
int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, const struct cli_target_info *info); |
... | ... |
@@ -244,7 +244,7 @@ void cli_bm_free(struct cli_matcher *root) |
244 | 244 |
} |
245 | 245 |
} |
246 | 246 |
|
247 |
-int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, const struct cli_target_info *info, struct cli_bm_off *offdata) |
|
247 |
+int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, const struct cli_target_info *info, struct cli_bm_off *offdata, uint32_t *viroffset) |
|
248 | 248 |
{ |
249 | 249 |
uint32_t i, j, off, off_min, off_max; |
250 | 250 |
uint8_t found, pchain, shift; |
... | ... |
@@ -374,8 +374,11 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
374 | 374 |
continue; |
375 | 375 |
} |
376 | 376 |
} |
377 |
- if(virname) |
|
377 |
+ if(virname) { |
|
378 | 378 |
*virname = p->virname; |
379 |
+ if(viroffset) |
|
380 |
+ *viroffset = offset + i + j - BM_MIN_LENGTH + BM_BLOCK_SIZE; |
|
381 |
+ } |
|
379 | 382 |
if(patt) |
380 | 383 |
*patt = p; |
381 | 384 |
return CL_VIRUS; |
... | ... |
@@ -47,7 +47,7 @@ int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const |
47 | 47 |
int cli_bm_init(struct cli_matcher *root); |
48 | 48 |
int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, const struct cli_target_info *info); |
49 | 49 |
void cli_bm_freeoff(struct cli_bm_off *data); |
50 |
-int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, const struct cli_target_info *info, struct cli_bm_off *offdata); |
|
50 |
+int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, const struct cli_target_info *info, struct cli_bm_off *offdata, uint32_t *viroffset); |
|
51 | 51 |
void cli_bm_free(struct cli_matcher *root); |
52 | 52 |
|
53 | 53 |
#endif |
... | ... |
@@ -91,13 +91,16 @@ static inline int matcher_run(const struct cli_matcher *root, |
91 | 91 |
unsigned int acmode, |
92 | 92 |
struct cli_ac_result **acres, |
93 | 93 |
fmap_t *map, |
94 |
- struct cli_bm_off *offdata) |
|
94 |
+ struct cli_bm_off *offdata, |
|
95 |
+ uint32_t *viroffset, |
|
96 |
+ cli_ctx *ctx) |
|
95 | 97 |
{ |
96 | 98 |
int ret; |
97 | 99 |
int32_t pos = 0; |
98 | 100 |
struct filter_match_info info; |
99 | 101 |
uint32_t orig_length, orig_offset; |
100 | 102 |
const unsigned char* orig_buffer; |
103 |
+ unsigned int viruses_found = 0; |
|
101 | 104 |
|
102 | 105 |
if (root->filter) { |
103 | 106 |
if(filter_search_ext(root->filter, buffer, length, &info) == -1) { |
... | ... |
@@ -128,15 +131,30 @@ static inline int matcher_run(const struct cli_matcher *root, |
128 | 128 |
/* Don't use prefiltering for BM offset mode, since BM keeps tracks |
129 | 129 |
* of offsets itself, and doesn't work if we skip chunks of input |
130 | 130 |
* data */ |
131 |
- ret = cli_bm_scanbuff(orig_buffer, orig_length, virname, NULL, root, orig_offset, tinfo, offdata); |
|
131 |
+ ret = cli_bm_scanbuff(orig_buffer, orig_length, virname, NULL, root, orig_offset, tinfo, offdata, viroffset); |
|
132 | 132 |
} else { |
133 |
- ret = cli_bm_scanbuff(buffer, length, virname, NULL, root, offset, tinfo, offdata); |
|
133 |
+ ret = cli_bm_scanbuff(buffer, length, virname, NULL, root, offset, tinfo, offdata, viroffset); |
|
134 |
+ } |
|
135 |
+ if (ret == CL_VIRUS) { |
|
136 |
+ if (ctx) { |
|
137 |
+ cli_append_virus(ctx, *virname); |
|
138 |
+#if 1 |
|
139 |
+ if (SCAN_ALL) |
|
140 |
+ viruses_found++; |
|
141 |
+ else |
|
142 |
+#endif |
|
143 |
+ return ret; |
|
144 |
+ } |
|
134 | 145 |
} |
135 |
- if (ret == CL_VIRUS) |
|
136 |
- return ret; |
|
137 | 146 |
} |
138 | 147 |
PERF_LOG_TRIES(acmode, 0, length); |
139 | 148 |
ret = cli_ac_scanbuff(buffer, length, virname, NULL, acres, root, mdata, offset, ftype, ftoffset, acmode, NULL); |
149 |
+#if 1 |
|
150 |
+ if (ctx && ret == CL_VIRUS) |
|
151 |
+ cli_append_virus(ctx, *virname); |
|
152 |
+ if (ctx && SCAN_ALL && viruses_found) |
|
153 |
+ return CL_VIRUS; |
|
154 |
+#endif |
|
140 | 155 |
return ret; |
141 | 156 |
} |
142 | 157 |
|
... | ... |
@@ -146,7 +164,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, |
146 | 146 |
unsigned int i; |
147 | 147 |
struct cli_ac_data mdata; |
148 | 148 |
struct cli_matcher *groot, *troot = NULL; |
149 |
- const char **virname=ctx->virname; |
|
149 |
+ const char *virname = NULL; |
|
150 | 150 |
const struct cl_engine *engine=ctx->engine; |
151 | 151 |
|
152 | 152 |
if(!engine) { |
... | ... |
@@ -170,8 +188,10 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, |
170 | 170 |
if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) |
171 | 171 |
return ret; |
172 | 172 |
|
173 |
- ret = matcher_run(troot, buffer, length, virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL); |
|
173 |
+ ret = matcher_run(troot, buffer, length, &virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx); |
|
174 | 174 |
|
175 |
+ // if (virname) |
|
176 |
+ // cli_append_virus(ctx, virname); |
|
175 | 177 |
if(!acdata) |
176 | 178 |
cli_ac_freedata(&mdata); |
177 | 179 |
|
... | ... |
@@ -179,11 +199,15 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, |
179 | 179 |
return ret; |
180 | 180 |
} |
181 | 181 |
|
182 |
+ virname = NULL; |
|
183 |
+ |
|
182 | 184 |
if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) |
183 | 185 |
return ret; |
184 | 186 |
|
185 |
- ret = matcher_run(groot, buffer, length, virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL); |
|
187 |
+ ret = matcher_run(groot, buffer, length, &virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx); |
|
186 | 188 |
|
189 |
+ // if (virname) |
|
190 |
+ // cli_append_virus(ctx, virname); |
|
187 | 191 |
if(!acdata) |
188 | 192 |
cli_ac_freedata(&mdata); |
189 | 193 |
|
... | ... |
@@ -412,11 +436,12 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx) |
412 | 412 |
for(i = 0; i < 16; i++) |
413 | 413 |
sprintf(md5 + i * 2, "%02x", digest[i]); |
414 | 414 |
md5[32] = 0; |
415 |
- cli_dbgmsg("FP SIGNATURE: %s:%u:%s\n", md5, (unsigned int) size, *ctx->virname ? *ctx->virname : "Name"); |
|
415 |
+ cli_dbgmsg("FP SIGNATURE: %s:%u:%s\n", md5, (unsigned int) size, |
|
416 |
+ cli_get_last_virus(ctx) ? cli_get_last_virus(ctx) : "Name"); |
|
416 | 417 |
} |
417 | 418 |
|
418 |
- if(ctx->virname) |
|
419 |
- do_dsig_check = strncmp("W32S.", *ctx->virname, 5); |
|
419 |
+ if(cli_get_last_virus(ctx)) |
|
420 |
+ do_dsig_check = strncmp("W32S.", cli_get_last_virus(ctx), 5); |
|
420 | 421 |
|
421 | 422 |
map = *ctx->fmap; |
422 | 423 |
have_sha1 = cli_hm_have_size(ctx->engine->hm_fp, CLI_HASH_SHA1, size) || (cli_hm_have_size(ctx->engine->hm_fp, CLI_HASH_SHA1, 1) && do_dsig_check); |
... | ... |
@@ -487,7 +512,7 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx) |
487 | 487 |
} |
488 | 488 |
} |
489 | 489 |
if (ctx->engine->cb_hash) |
490 |
- ctx->engine->cb_hash(fmap_fd(*ctx->fmap), size, md5, ctx->virname ? *ctx->virname : NULL, ctx->cb_ctx); |
|
490 |
+ ctx->engine->cb_hash(fmap_fd(*ctx->fmap), size, md5, cli_get_last_virus(ctx), ctx->cb_ctx); |
|
491 | 491 |
|
492 | 492 |
return CL_VIRUS; |
493 | 493 |
} |
... | ... |
@@ -572,6 +597,7 @@ int cli_lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *ac |
572 | 572 |
unsigned int i, evalcnt; |
573 | 573 |
uint64_t evalids; |
574 | 574 |
fmap_t *map = *ctx->fmap; |
575 |
+ unsigned int viruses_found = 0; |
|
575 | 576 |
|
576 | 577 |
for(i = 0; i < root->ac_lsigs; i++) { |
577 | 578 |
evalcnt = 0; |
... | ... |
@@ -598,6 +624,10 @@ int cli_lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *ac |
598 | 598 |
memcpy(ctx->handlertype_hash, hash, 16); |
599 | 599 |
if(cli_magic_scandesc_type(ctx, root->ac_lsigtable[i]->tdb.handlertype[0]) == CL_VIRUS) { |
600 | 600 |
ctx->recursion--; |
601 |
+ if (SCAN_ALL) { |
|
602 |
+ viruses_found++; |
|
603 |
+ continue; |
|
604 |
+ } |
|
601 | 605 |
return CL_VIRUS; |
602 | 606 |
} |
603 | 607 |
ctx->recursion--; |
... | ... |
@@ -610,25 +640,41 @@ int cli_lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *ac |
610 | 610 |
continue; |
611 | 611 |
if(matchicon(ctx, &target_info->exeinfo, root->ac_lsigtable[i]->tdb.icongrp1, root->ac_lsigtable[i]->tdb.icongrp2) == CL_VIRUS) { |
612 | 612 |
if(!root->ac_lsigtable[i]->bc_idx) { |
613 |
- if(ctx->virname) |
|
614 |
- *ctx->virname = root->ac_lsigtable[i]->virname; |
|
613 |
+ cli_append_virus(ctx, root->ac_lsigtable[i]->virname); |
|
614 |
+ if (SCAN_ALL) { |
|
615 |
+ viruses_found++; |
|
616 |
+ continue; |
|
617 |
+ } |
|
615 | 618 |
return CL_VIRUS; |
616 |
- } else if(cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, root->ac_lsigtable[i]->bc_idx, ctx->virname, acdata->lsigcnt[i], acdata->lsigsuboff_first[i], map) == CL_VIRUS) { |
|
619 |
+ } else if(cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, root->ac_lsigtable[i]->bc_idx, acdata->lsigcnt[i], acdata->lsigsuboff_first[i], map) == CL_VIRUS) { |
|
620 |
+ if (SCAN_ALL) { |
|
621 |
+ viruses_found++; |
|
622 |
+ continue; |
|
623 |
+ } |
|
617 | 624 |
return CL_VIRUS; |
618 | 625 |
} |
619 | 626 |
} |
620 | 627 |
continue; |
621 | 628 |
} |
622 | 629 |
if(!root->ac_lsigtable[i]->bc_idx) { |
623 |
- if(ctx->virname) |
|
624 |
- *ctx->virname = root->ac_lsigtable[i]->virname; |
|
625 |
- return CL_VIRUS; |
|
630 |
+ cli_append_virus(ctx, root->ac_lsigtable[i]->virname); |
|
631 |
+ if (SCAN_ALL) { |
|
632 |
+ viruses_found++; |
|
633 |
+ continue; |
|
634 |
+ } |
|
635 |
+ return CL_VIRUS; |
|
626 | 636 |
} |
627 |
- if(cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, root->ac_lsigtable[i]->bc_idx, ctx->virname, acdata->lsigcnt[i], acdata->lsigsuboff_first[i], map) == CL_VIRUS) { |
|
628 |
- return CL_VIRUS; |
|
637 |
+ if(cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, root->ac_lsigtable[i]->bc_idx, acdata->lsigcnt[i], acdata->lsigsuboff_first[i], map) == CL_VIRUS) { |
|
638 |
+ if (SCAN_ALL) { |
|
639 |
+ viruses_found++; |
|
640 |
+ continue; |
|
641 |
+ } |
|
642 |
+ return CL_VIRUS; |
|
629 | 643 |
} |
630 | 644 |
} |
631 | 645 |
} |
646 |
+ if (SCAN_ALL && viruses_found) |
|
647 |
+ return CL_VIRUS; |
|
632 | 648 |
return CL_CLEAN; |
633 | 649 |
} |
634 | 650 |
|
... | ... |
@@ -648,6 +694,9 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli |
648 | 648 |
struct cli_target_info info; |
649 | 649 |
fmap_t *map = *ctx->fmap; |
650 | 650 |
struct cli_matcher *hdb, *fp; |
651 |
+ const char *virname = NULL; |
|
652 |
+ uint32_t viroffset = 0; |
|
653 |
+ uint32_t viruses_found = 0; |
|
651 | 654 |
|
652 | 655 |
if(!ctx->engine) { |
653 | 656 |
cli_errmsg("cli_scandesc: engine == NULL\n"); |
... | ... |
@@ -749,9 +798,15 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli |
749 | 749 |
*ctx->scanned += bytes / CL_COUNT_PRECISION; |
750 | 750 |
|
751 | 751 |
if(troot) { |
752 |
- ret = matcher_run(troot, buff, bytes, ctx->virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL); |
|
752 |
+ virname = NULL; |
|
753 |
+ viroffset = 0; |
|
754 |
+ ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &viroffset, ctx); |
|
753 | 755 |
|
754 |
- if(ret == CL_VIRUS || ret == CL_EMEM) { |
|
756 |
+ if (virname) { |
|
757 |
+ // cli_append_virus(ctx, virname); |
|
758 |
+ viruses_found++; |
|
759 |
+ } |
|
760 |
+ if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) { |
|
755 | 761 |
if(!ftonly) |
756 | 762 |
cli_ac_freedata(&gdata); |
757 | 763 |
cli_ac_freedata(&tdata); |
... | ... |
@@ -765,9 +820,15 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli |
765 | 765 |
} |
766 | 766 |
|
767 | 767 |
if(!ftonly) { |
768 |
- ret = matcher_run(groot, buff, bytes, ctx->virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL); |
|
768 |
+ virname = NULL; |
|
769 |
+ viroffset = 0; |
|
770 |
+ ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &viroffset, ctx); |
|
769 | 771 |
|
770 |
- if(ret == CL_VIRUS || ret == CL_EMEM) { |
|
772 |
+ if (virname) { |
|
773 |
+ // cli_append_virus(ctx, virname); |
|
774 |
+ viruses_found++; |
|
775 |
+ } |
|
776 |
+ if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) { |
|
771 | 777 |
cli_ac_freedata(&gdata); |
772 | 778 |
if(troot) { |
773 | 779 |
cli_ac_freedata(&tdata); |
... | ... |
@@ -783,7 +844,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli |
783 | 783 |
type = ret; |
784 | 784 |
} |
785 | 785 |
|
786 |
- if(hdb) { |
|
786 |
+ if(hdb && !SCAN_ALL) { |
|
787 | 787 |
const void *data = buff + maxpatlen * (offset!=0); |
788 | 788 |
uint32_t data_len = bytes - maxpatlen * (offset!=0); |
789 | 789 |
|
... | ... |
@@ -796,12 +857,17 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli |
796 | 796 |
} |
797 | 797 |
} |
798 | 798 |
|
799 |
+ if(SCAN_ALL && viroffset) { |
|
800 |
+ offset = viroffset; |
|
801 |
+ continue; |
|
802 |
+ } |
|
799 | 803 |
if(bytes < SCANBUFF) break; |
800 | 804 |
offset += bytes - maxpatlen; |
801 | 805 |
} |
802 | 806 |
|
803 | 807 |
if(!ftonly && hdb) { |
804 | 808 |
enum CLI_HASH_TYPE hashtype; |
809 |
+ unsigned int hvirs = 0, hfps = 0; |
|
805 | 810 |
|
806 | 811 |
if(compute_hash[CLI_HASH_MD5]) |
807 | 812 |
cli_md5_final(digest[CLI_HASH_MD5], &md5ctx); |
... | ... |
@@ -812,31 +878,39 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli |
812 | 812 |
if(compute_hash[CLI_HASH_SHA256]) |
813 | 813 |
sha256_final(&sha256ctx, digest[CLI_HASH_SHA256]); |
814 | 814 |
|
815 |
+ virname = NULL; |
|
815 | 816 |
for(hashtype = CLI_HASH_MD5; hashtype < CLI_HASH_AVAIL_TYPES; hashtype++) { |
816 |
- if(compute_hash[hashtype] && (ret = cli_hm_scan(digest[hashtype], map->len, ctx->virname, hdb, hashtype)) == CL_VIRUS) |
|
817 |
- break; |
|
818 |
- } |
|
817 |
+ if(compute_hash[hashtype] && (ret = cli_hm_scan(digest[hashtype], map->len, &virname, hdb, hashtype)) == CL_VIRUS) { |
|
819 | 818 |
|
820 |
- if(ret == CL_VIRUS && fp) { |
|
821 |
- for(hashtype = CLI_HASH_MD5; hashtype < CLI_HASH_AVAIL_TYPES; hashtype++) { |
|
822 |
- if(compute_hash[hashtype] && cli_hm_scan(digest[hashtype], map->len, ctx->virname, fp, hashtype) == CL_VIRUS) { |
|
823 |
- ret = CL_CLEAN; |
|
824 |
- break; |
|
819 |
+ if(fp && cli_hm_scan(digest[hashtype], map->len, NULL, fp, hashtype) == CL_VIRUS) { |
|
820 |
+ hfps++; |
|
821 |
+ continue; |
|
825 | 822 |
} |
823 |
+ hvirs++; |
|
824 |
+ cli_append_virus(ctx, virname); |
|
825 |
+ virname = NULL; |
|
826 |
+ if(!SCAN_ALL) |
|
827 |
+ break; |
|
826 | 828 |
} |
827 | 829 |
} |
830 |
+ if(hvirs > hfps) |
|
831 |
+ ret = CL_VIRUS; |
|
832 |
+ else |
|
833 |
+ ret = CL_CLEAN; |
|
828 | 834 |
} |
829 | 835 |
|
830 | 836 |
if(troot) { |
831 |
- if(ret != CL_VIRUS) |
|
837 |
+ if(ret != CL_VIRUS || SCAN_ALL) |
|
832 | 838 |
ret = cli_lsig_eval(ctx, troot, &tdata, &info, refhash); |
839 |
+ if (ret == CL_VIRUS) |
|
840 |
+ viruses_found++; |
|
833 | 841 |
cli_ac_freedata(&tdata); |
834 | 842 |
if(bm_offmode) |
835 | 843 |
cli_bm_freeoff(&toff); |
836 | 844 |
} |
837 | 845 |
|
838 | 846 |
if(groot) { |
839 |
- if(ret != CL_VIRUS) |
|
847 |
+ if(ret != CL_VIRUS || SCAN_ALL) |
|
840 | 848 |
ret = cli_lsig_eval(ctx, groot, &gdata, &info, refhash); |
841 | 849 |
cli_ac_freedata(&gdata); |
842 | 850 |
} |
... | ... |
@@ -845,6 +919,8 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli |
845 | 845 |
free(info.exeinfo.section); |
846 | 846 |
cli_hashset_destroy(&info.exeinfo.vinfo); |
847 | 847 |
|
848 |
+ if (SCAN_ALL && viruses_found) |
|
849 |
+ return CL_VIRUS; |
|
848 | 850 |
if(ret == CL_VIRUS) |
849 | 851 |
return CL_VIRUS; |
850 | 852 |
|
... | ... |
@@ -854,6 +930,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli |
854 | 854 |
int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer, int encrypted, unsigned int filepos, int res1, void *res2) |
855 | 855 |
{ |
856 | 856 |
const struct cli_cdb *cdb; |
857 |
+ unsigned int viruses_found = 0; |
|
857 | 858 |
|
858 | 859 |
cli_dbgmsg("CDBNAME:%s:%lu:%s:%lu:%lu:%d:%u:%u:%p\n", |
859 | 860 |
cli_ftname(ctx->container_type), fsizec, fname, fsizec, fsizer, encrypted, filepos, res1, res2); |
... | ... |
@@ -861,8 +938,11 @@ int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer, |
861 | 861 |
if (ctx->engine && ctx->engine->cb_meta) |
862 | 862 |
if (ctx->engine->cb_meta(cli_ftname(ctx->container_type), fsizec, fname, fsizer, encrypted, filepos, ctx->cb_ctx) == CL_VIRUS) { |
863 | 863 |
cli_dbgmsg("inner file blacklisted by callback: %s\n", fname); |
864 |
- *ctx->virname = "Detected.By.Callback"; |
|
865 |
- return CL_VIRUS; |
|
864 |
+ |
|
865 |
+ cli_append_virus(ctx, "Detected.By.Callback"); |
|
866 |
+ viruses_found++; |
|
867 |
+ if(!SCAN_ALL) |
|
868 |
+ return CL_VIRUS; |
|
866 | 869 |
} |
867 | 870 |
|
868 | 871 |
if(!ctx->engine || !(cdb = ctx->engine->cdb)) |
... | ... |
@@ -895,10 +975,14 @@ int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer, |
895 | 895 |
if(cdb->name.re_magic && (!fname || cli_regexec(&cdb->name, fname, 0, NULL, 0) == REG_NOMATCH)) |
896 | 896 |
continue; |
897 | 897 |
|
898 |
- *ctx->virname = cdb->virname; |
|
899 |
- return CL_VIRUS; |
|
898 |
+ cli_append_virus(ctx, cdb->virname); |
|
899 |
+ viruses_found++; |
|
900 |
+ if(!SCAN_ALL) |
|
901 |
+ return CL_VIRUS; |
|
900 | 902 |
|
901 | 903 |
} while((cdb = cdb->next)); |
902 | 904 |
|
905 |
+ if (SCAN_ALL && viruses_found) |
|
906 |
+ return CL_VIRUS; |
|
903 | 907 |
return CL_CLEAN; |
904 | 908 |
} |
... | ... |
@@ -544,11 +544,18 @@ cli_parse_mbox(const char *dir, cli_ctx *ctx) |
544 | 544 |
*/ |
545 | 545 |
messageDestroy(body); |
546 | 546 |
} |
547 |
- |
|
547 |
+ |
|
548 |
+#if 0 |
|
548 | 549 |
if((retcode == CL_CLEAN) && ctx->found_possibly_unwanted && (*ctx->virname == NULL)) { |
549 |
- *ctx->virname = "Heuristics.Phishing.Email"; |
|
550 |
- ctx->found_possibly_unwanted = 0; |
|
551 |
- retcode = CL_VIRUS; |
|
550 |
+ *ctx->virname = "Heuristics.Phishing.Email"; |
|
551 |
+#else |
|
552 |
+ /* TBD: Breaks unit_test/check1_clamscan.sh and check2_clamd.sh w/SCAN_ALL */ |
|
553 |
+ if((retcode == CL_CLEAN) && ctx->found_possibly_unwanted && |
|
554 |
+ (*ctx->virname == NULL || SCAN_ALL)) { |
|
555 |
+ cli_append_virus(ctx, "Heuristics.Phishing.Email"); |
|
556 |
+#endif |
|
557 |
+ ctx->found_possibly_unwanted = 0; |
|
558 |
+ retcode = CL_VIRUS; |
|
552 | 559 |
} |
553 | 560 |
|
554 | 561 |
cli_dbgmsg("cli_mbox returning %d\n", retcode); |
... | ... |
@@ -770,6 +770,44 @@ int cli_unlink(const char *pathname) |
770 | 770 |
return 0; |
771 | 771 |
} |
772 | 772 |
|
773 |
+void cli_append_virus(cli_ctx * ctx, const char * virname) |
|
774 |
+{ |
|
775 |
+ if (!ctx->virname) |
|
776 |
+ return; |
|
777 |
+ if (SCAN_ALL) { |
|
778 |
+ if (ctx->size_viruses == 0) { |
|
779 |
+ ctx->size_viruses = 2; |
|
780 |
+ if (!(ctx->virname = malloc(ctx->size_viruses * sizeof(char *)))) { |
|
781 |
+ cli_errmsg("cli_append_virus: fails on malloc() - virus %s virname not appended.\n", virname); |
|
782 |
+ return; |
|
783 |
+ } |
|
784 |
+ } else if (ctx->num_viruses+1 == ctx->size_viruses) { |
|
785 |
+ ctx->size_viruses *= 2; |
|
786 |
+ if ((ctx->virname = realloc((void *)ctx->virname, ctx->size_viruses * sizeof (char *))) == NULL) { |
|
787 |
+ cli_errmsg("cli_append_virus: fails on realloc() - virus %s virname not appended.\n", virname); |
|
788 |
+ return; |
|
789 |
+ } |
|
790 |
+ } |
|
791 |
+ ctx->virname[ctx->num_viruses++] = virname; |
|
792 |
+ ctx->virname[ctx->num_viruses] = NULL; |
|
793 |
+ } |
|
794 |
+ else |
|
795 |
+ *ctx->virname = virname; |
|
796 |
+} |
|
797 |
+ |
|
798 |
+const char * cli_get_last_virus(const cli_ctx * ctx) |
|
799 |
+{ |
|
800 |
+ if (!ctx->virname) |
|
801 |
+ return NULL; |
|
802 |
+ |
|
803 |
+ if (SCAN_ALL && ctx->num_viruses) { |
|
804 |
+ return ctx->virname[ctx->num_viruses-1]; |
|
805 |
+ } |
|
806 |
+ else |
|
807 |
+ return *ctx->virname; |
|
808 |
+} |
|
809 |
+ |
|
810 |
+ |
|
773 | 811 |
#ifdef C_WINDOWS |
774 | 812 |
/* |
775 | 813 |
* Windows doesn't allow you to delete a directory while it is still open |
... | ... |
@@ -55,7 +55,7 @@ |
55 | 55 |
* in re-enabling affected modules. |
56 | 56 |
*/ |
57 | 57 |
|
58 |
-#define CL_FLEVEL 72 |
|
58 |
+#define CL_FLEVEL 73 |
|
59 | 59 |
#define CL_FLEVEL_DCONF CL_FLEVEL |
60 | 60 |
#define CL_FLEVEL_SIGTOOL CL_FLEVEL |
61 | 61 |
|
... | ... |
@@ -111,6 +111,8 @@ typedef struct bitset_tag |
111 | 111 |
/* internal clamav context */ |
112 | 112 |
typedef struct cli_ctx_tag { |
113 | 113 |
const char **virname; |
114 |
+ unsigned int num_viruses; /* manages virname when CL_SCAN_ALLMATCHES == 1 */ |
|
115 |
+ unsigned int size_viruses; /* manages virname when CL_SCAN_ALLMATCHES == 1 */ |
|
114 | 116 |
unsigned long int *scanned; |
115 | 117 |
const struct cli_matcher *root; |
116 | 118 |
const struct cl_engine *engine; |
... | ... |
@@ -324,6 +326,7 @@ extern int have_rar; |
324 | 324 |
#define DETECT_BROKEN (ctx->options & CL_SCAN_BLOCKBROKEN) |
325 | 325 |
#define BLOCK_MACROS (ctx->options & CL_SCAN_BLOCKMACROS) |
326 | 326 |
#define SCAN_STRUCTURED (ctx->options & CL_SCAN_STRUCTURED) |
327 |
+#define SCAN_ALL (ctx->options & CL_SCAN_ALLMATCHES) |
|
327 | 328 |
|
328 | 329 |
/* based on macros from A. Melnikoff */ |
329 | 330 |
#define cbswap16(v) (((v & 0xff) << 8) | (((v) >> 8) & 0xff)) |
... | ... |
@@ -422,6 +425,9 @@ static inline void cli_writeint32(char *offset, uint32_t value) |
422 | 422 |
} |
423 | 423 |
#endif |
424 | 424 |
|
425 |
+void cli_append_virus(cli_ctx *ctx, const char *virname); |
|
426 |
+const char *cli_get_last_virus(const cli_ctx *ctx); |
|
427 |
+ |
|
425 | 428 |
/* used by: spin, yc (C) aCaB */ |
426 | 429 |
#define __SHIFTBITS(a) (sizeof(a)<<3) |
427 | 430 |
#define __SHIFTMASK(a) (__SHIFTBITS(a)-1) |
... | ... |
@@ -584,7 +584,7 @@ static int run_pdf_hooks(struct pdf_struct *pdf, enum pdf_phase phase, int fd, |
584 | 584 |
cli_bytecode_context_setpdf(bc_ctx, phase, pdf->nobjs, pdf->objs, |
585 | 585 |
&pdf->flags, pdf->size, pdf->startoff); |
586 | 586 |
cli_bytecode_context_setctx(bc_ctx, ctx); |
587 |
- ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_PDF, map, ctx->virname); |
|
587 |
+ ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_PDF, map); |
|
588 | 588 |
cli_bytecode_context_destroy(bc_ctx); |
589 | 589 |
if (fd != -1) { |
590 | 590 |
funmap(map); |
... | ... |
@@ -2074,7 +2074,7 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset) |
2074 | 2074 |
/* It is encrypted, and a password/key needs to be supplied to decrypt. |
2075 | 2075 |
* This doesn't trigger for PDFs that are encrypted but don't need |
2076 | 2076 |
* a password to decrypt */ |
2077 |
- *ctx->virname = "Heuristics.Encrypted.PDF"; |
|
2077 |
+ cli_append_virus(ctx, "Heuristics.Encrypted.PDF"); |
|
2078 | 2078 |
rc = CL_VIRUS; |
2079 | 2079 |
} |
2080 | 2080 |
|
... | ... |
@@ -2096,7 +2096,7 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset) |
2096 | 2096 |
if (!rc && (ctx->options & CL_SCAN_ALGORITHMIC)) { |
2097 | 2097 |
if (pdf.flags & (1 << ESCAPED_COMMON_PDFNAME)) { |
2098 | 2098 |
/* for example /Fl#61te#44#65#63#6f#64#65 instead of /FlateDecode */ |
2099 |
- *ctx->virname = "Heuristics.PDF.ObfuscatedNameObject"; |
|
2099 |
+ cli_append_virus(ctx, "Heuristics.PDF.ObfuscatedNameObject"); |
|
2100 | 2100 |
rc = cli_found_possibly_unwanted(ctx); |
2101 | 2101 |
} |
2102 | 2102 |
} |
... | ... |
@@ -537,6 +537,8 @@ int cli_scanpe(cli_ctx *ctx) |
537 | 537 |
#ifdef HAVE__INTERNAL__SHA_COLLECT |
538 | 538 |
int sha_collect = ctx->sha_collect; |
539 | 539 |
#endif |
540 |
+ const char * virname = NULL; |
|
541 |
+ uint32_t viruses_found = 0; |
|
540 | 542 |
|
541 | 543 |
if(!ctx) { |
542 | 544 |
cli_errmsg("cli_scanpe: ctx == NULL\n"); |
... | ... |
@@ -557,8 +559,7 @@ int cli_scanpe(cli_ctx *ctx) |
557 | 557 |
cli_dbgmsg("Can't read new header address\n"); |
558 | 558 |
/* truncated header? */ |
559 | 559 |
if(DETECT_BROKEN_PE) { |
560 |
- if(ctx->virname) |
|
561 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
560 |
+ cli_append_virus(ctx,"Heuristics.Broken.Executable"); |
|
562 | 561 |
return CL_VIRUS; |
563 | 562 |
} |
564 | 563 |
return CL_CLEAN; |
... | ... |
@@ -687,8 +688,7 @@ int cli_scanpe(cli_ctx *ctx) |
687 | 687 |
nsections = EC16(file_hdr.NumberOfSections); |
688 | 688 |
if(nsections < 1 || nsections > 96) { |
689 | 689 |
if(DETECT_BROKEN_PE) { |
690 |
- if(ctx->virname) |
|
691 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
690 |
+ cli_append_virus(ctx,"Heuristics.Broken.Executable"); |
|
692 | 691 |
return CL_VIRUS; |
693 | 692 |
} |
694 | 693 |
if(!ctx->corrupted_input) { |
... | ... |
@@ -709,8 +709,7 @@ int cli_scanpe(cli_ctx *ctx) |
709 | 709 |
if (EC16(file_hdr.SizeOfOptionalHeader) < sizeof(struct pe_image_optional_hdr32)) { |
710 | 710 |
cli_dbgmsg("SizeOfOptionalHeader too small\n"); |
711 | 711 |
if(DETECT_BROKEN_PE) { |
712 |
- if(ctx->virname) |
|
713 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
712 |
+ cli_append_virus(ctx,"Heuristics.Broken.Executable"); |
|
714 | 713 |
return CL_VIRUS; |
715 | 714 |
} |
716 | 715 |
return CL_CLEAN; |
... | ... |
@@ -720,8 +719,7 @@ int cli_scanpe(cli_ctx *ctx) |
720 | 720 |
if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) { |
721 | 721 |
cli_dbgmsg("Can't read optional file header\n"); |
722 | 722 |
if(DETECT_BROKEN_PE) { |
723 |
- if(ctx->virname) |
|
724 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
723 |
+ cli_append_virus(ctx,"Heuristics.Broken.Executable"); |
|
725 | 724 |
return CL_VIRUS; |
726 | 725 |
} |
727 | 726 |
return CL_CLEAN; |
... | ... |
@@ -734,8 +732,7 @@ int cli_scanpe(cli_ctx *ctx) |
734 | 734 |
/* FIXME: need to play around a bit more with xp64 */ |
735 | 735 |
cli_dbgmsg("Incorrect SizeOfOptionalHeader for PE32+\n"); |
736 | 736 |
if(DETECT_BROKEN_PE) { |
737 |
- if(ctx->virname) |
|
738 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
737 |
+ cli_append_virus(ctx,"Heuristics.Broken.Executable"); |
|
739 | 738 |
return CL_VIRUS; |
740 | 739 |
} |
741 | 740 |
return CL_CLEAN; |
... | ... |
@@ -777,8 +774,7 @@ int cli_scanpe(cli_ctx *ctx) |
777 | 777 |
if(fmap_readn(map, &optional_hdr32 + 1, at, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) { |
778 | 778 |
cli_dbgmsg("Can't read optional file header\n"); |
779 | 779 |
if(DETECT_BROKEN_PE) { |
780 |
- if(ctx->virname) |
|
781 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
780 |
+ cli_append_virus(ctx,"Heuristics.Broken.Executable"); |
|
782 | 781 |
return CL_VIRUS; |
783 | 782 |
} |
784 | 783 |
return CL_CLEAN; |
... | ... |
@@ -858,15 +854,13 @@ int cli_scanpe(cli_ctx *ctx) |
858 | 858 |
|
859 | 859 |
if (DETECT_BROKEN_PE && !native && (!(pe_plus?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment)) || (pe_plus?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment))%0x1000)) { |
860 | 860 |
cli_dbgmsg("Bad virtual alignemnt\n"); |
861 |
- if(ctx->virname) |
|
862 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
861 |
+ cli_append_virus(ctx,"Heuristics.Broken.Executable"); |
|
863 | 862 |
return CL_VIRUS; |
864 | 863 |
} |
865 | 864 |
|
866 | 865 |
if (DETECT_BROKEN_PE && !native && (!(pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment)) || (pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment))%0x200)) { |
867 | 866 |
cli_dbgmsg("Bad file alignemnt\n"); |
868 |
- if(ctx->virname) |
|
869 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
867 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
870 | 868 |
return CL_VIRUS; |
871 | 869 |
} |
872 | 870 |
|
... | ... |
@@ -896,8 +890,7 @@ int cli_scanpe(cli_ctx *ctx) |
896 | 896 |
free(section_hdr); |
897 | 897 |
free(exe_sections); |
898 | 898 |
if(DETECT_BROKEN_PE) { |
899 |
- if(ctx->virname) |
|
900 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
899 |
+ cli_append_virus(ctx,"Heuristics.Broken.Executable"); |
|
901 | 900 |
return CL_VIRUS; |
902 | 901 |
} |
903 | 902 |
return CL_CLEAN; |
... | ... |
@@ -964,8 +957,7 @@ int cli_scanpe(cli_ctx *ctx) |
964 | 964 |
|
965 | 965 |
if (DETECT_BROKEN_PE && (!valign || (exe_sections[i].urva % valign))) { /* Bad virtual alignment */ |
966 | 966 |
cli_dbgmsg("VirtualAddress is misaligned\n"); |
967 |
- if(ctx->virname) |
|
968 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
967 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
969 | 968 |
free(section_hdr); |
970 | 969 |
free(exe_sections); |
971 | 970 |
return CL_VIRUS; |
... | ... |
@@ -977,8 +969,7 @@ int cli_scanpe(cli_ctx *ctx) |
977 | 977 |
free(section_hdr); |
978 | 978 |
free(exe_sections); |
979 | 979 |
if(DETECT_BROKEN_PE) { |
980 |
- if(ctx->virname) |
|
981 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
980 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
982 | 981 |
return CL_VIRUS; |
983 | 982 |
} |
984 | 983 |
return CL_CLEAN; /* no ninjas to see here! move along! */ |
... | ... |
@@ -992,15 +983,19 @@ int cli_scanpe(cli_ctx *ctx) |
992 | 992 |
unsigned char md5_dig[16]; |
993 | 993 |
if(cli_hm_have_size(md5_sect, CLI_HASH_MD5, exe_sections[i].rsz) && |
994 | 994 |
cli_md5sect(map, &exe_sections[i], md5_dig) && |
995 |
- cli_hm_scan(md5_dig, exe_sections[i].rsz, ctx->virname, md5_sect, CLI_HASH_MD5) == CL_VIRUS) { |
|
995 |
+ cli_hm_scan(md5_dig, exe_sections[i].rsz, &virname, md5_sect, CLI_HASH_MD5) == CL_VIRUS) { |
|
996 | 996 |
if(cli_hm_scan(md5_dig, fsize, NULL, ctx->engine->hm_fp, CLI_HASH_MD5) != CL_VIRUS) { |
997 |
- free(section_hdr); |
|
998 |
- free(exe_sections); |
|
999 |
- return CL_VIRUS; |
|
997 |
+ if (!SCAN_ALL) { |
|
998 |
+ free(section_hdr); |
|
999 |
+ free(exe_sections); |
|
1000 |
+ return CL_VIRUS; |
|
1001 |
+ } |
|
1000 | 1002 |
} |
1003 |
+ cli_append_virus(ctx, virname); |
|
1004 |
+ viruses_found++; |
|
1001 | 1005 |
} |
1002 | 1006 |
} |
1003 |
- |
|
1007 |
+ |
|
1004 | 1008 |
} |
1005 | 1009 |
|
1006 | 1010 |
if (exe_sections[i].urva>>31 || exe_sections[i].uvsz>>31 || (exe_sections[i].rsz && exe_sections[i].uraw>>31) || exe_sections[i].ursz>>31) { |
... | ... |
@@ -1008,8 +1003,7 @@ int cli_scanpe(cli_ctx *ctx) |
1008 | 1008 |
free(section_hdr); |
1009 | 1009 |
free(exe_sections); |
1010 | 1010 |
if(DETECT_BROKEN_PE) { |
1011 |
- if(ctx->virname) |
|
1012 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
1011 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
1013 | 1012 |
return CL_VIRUS; |
1014 | 1013 |
} |
1015 | 1014 |
return CL_CLEAN; |
... | ... |
@@ -1018,8 +1012,7 @@ int cli_scanpe(cli_ctx *ctx) |
1018 | 1018 |
if(!i) { |
1019 | 1019 |
if (DETECT_BROKEN_PE && exe_sections[i].urva!=hdr_size) { /* Bad first section RVA */ |
1020 | 1020 |
cli_dbgmsg("First section is in the wrong place\n"); |
1021 |
- if(ctx->virname) |
|
1022 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
1021 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
1023 | 1022 |
free(section_hdr); |
1024 | 1023 |
free(exe_sections); |
1025 | 1024 |
return CL_VIRUS; |
... | ... |
@@ -1029,8 +1022,7 @@ int cli_scanpe(cli_ctx *ctx) |
1029 | 1029 |
} else { |
1030 | 1030 |
if (DETECT_BROKEN_PE && exe_sections[i].urva - exe_sections[i-1].urva != exe_sections[i-1].vsz) { /* No holes, no overlapping, no virtual disorder */ |
1031 | 1031 |
cli_dbgmsg("Virtually misplaced section (wrong order, overlapping, non contiguous)\n"); |
1032 |
- if(ctx->virname) |
|
1033 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
1032 |
+ cli_append_virus(ctx, "Heuristics.Broken.Executable"); |
|
1034 | 1033 |
free(section_hdr); |
1035 | 1034 |
free(exe_sections); |
1036 | 1035 |
return CL_VIRUS; |
... | ... |
@@ -1051,8 +1043,7 @@ int cli_scanpe(cli_ctx *ctx) |
1051 | 1051 |
cli_dbgmsg("EntryPoint out of file\n"); |
1052 | 1052 |
free(exe_sections); |
1053 | 1053 |
if(DETECT_BROKEN_PE) { |
1054 |
- if(ctx->virname) |
|
1055 |
- *ctx->virname = "Heuristics.Broken.Executable"; |
|
1054 |
+ cli_append_virus(ctx,"Heuristics.Broken.Executable"); |
|
1056 | 1055 |
return CL_VIRUS; |
1057 | 1056 |
} |
1058 | 1057 |
return CL_CLEAN; |
... | ... |
@@ -1112,7 +1103,7 @@ int cli_scanpe(cli_ctx *ctx) |
1112 | 1112 |
} |
1113 | 1113 |
cli_bytecode_context_setpe(bc_ctx, &pedata, exe_sections); |
1114 | 1114 |
cli_bytecode_context_setctx(bc_ctx, ctx); |
1115 |
- ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_PE_ALL, map, ctx->virname); |
|
1115 |
+ ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_PE_ALL, map); |
|
1116 | 1116 |
switch (ret) { |
1117 | 1117 |
case CL_ENULLARG: |
1118 | 1118 |
cli_warnmsg("cli_scanpe: NULL argument supplied\n"); |
... | ... |
@@ -1132,9 +1123,12 @@ int cli_scanpe(cli_ctx *ctx) |
1132 | 1132 |
if(pt) { |
1133 | 1133 |
pt += 15; |
1134 | 1134 |
if((((uint32_t)cli_readint32(pt) ^ (uint32_t)cli_readint32(pt + 4)) == 0x505a4f) && (((uint32_t)cli_readint32(pt + 8) ^ (uint32_t)cli_readint32(pt + 12)) == 0xffffb) && (((uint32_t)cli_readint32(pt + 16) ^ (uint32_t)cli_readint32(pt + 20)) == 0xb8)) { |
1135 |
- *ctx->virname = "Heuristics.W32.Parite.B"; |
|
1136 |
- free(exe_sections); |
|
1137 |
- return CL_VIRUS; |
|
1135 |
+ cli_append_virus(ctx,"Heuristics.W32.Parite.B"); |
|
1136 |
+ if (!SCAN_ALL) { |
|
1137 |
+ free(exe_sections); |
|
1138 |
+ return CL_VIRUS; |
|
1139 |
+ } |
|
1140 |
+ viruses_found++; |
|
1138 | 1141 |
} |
1139 | 1142 |
} |
1140 | 1143 |
} |
... | ... |
@@ -1215,9 +1209,11 @@ int cli_scanpe(cli_ctx *ctx) |
1215 | 1215 |
break; |
1216 | 1216 |
case KZSLOOP: |
1217 | 1217 |
if (op==kzdsize+0x48 && *kzcode==0x75 && kzlen-(int8_t)kzcode[1]-3<=kzinitlen && kzlen-(int8_t)kzcode[1]>=kzxorlen) { |
1218 |
- *ctx->virname = "Heuristics.W32.Kriz"; |
|
1218 |
+ cli_append_virus(ctx,"Heuristics.W32.Kriz"); |
|
1219 | 1219 |
free(exe_sections); |
1220 |
- return CL_VIRUS; |
|
1220 |
+ if (!SCAN_ALL) |
|
1221 |
+ return CL_VIRUS; |
|
1222 |
+ viruses_found++; |
|
1221 | 1223 |
} |
1222 | 1224 |
cli_dbgmsg("kriz: loop out of bounds, corrupted sample?\n"); |
1223 | 1225 |
kzstate++; |
... | ... |
@@ -1242,9 +1238,11 @@ int cli_scanpe(cli_ctx *ctx) |
1242 | 1242 |
|
1243 | 1243 |
if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) { |
1244 | 1244 |
if(cli_memstr(tbuff, 4091, "\xe8\x2c\x61\x00\x00", 5)) { |
1245 |
- *ctx->virname = dam ? "Heuristics.W32.Magistr.A.dam" : "Heuristics.W32.Magistr.A"; |
|
1245 |
+ cli_append_virus(ctx, dam ? "Heuristics.W32.Magistr.A.dam" : "Heuristics.W32.Magistr.A"); |
|
1246 | 1246 |
free(exe_sections); |
1247 |
- return CL_VIRUS; |
|
1247 |
+ if (!SCAN_ALL) |
|
1248 |
+ return CL_VIRUS; |
|
1249 |
+ viruses_found++; |
|
1248 | 1250 |
} |
1249 | 1251 |
} |
1250 | 1252 |
|
... | ... |
@@ -1254,9 +1252,11 @@ int cli_scanpe(cli_ctx *ctx) |
1254 | 1254 |
|
1255 | 1255 |
if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) { |
1256 | 1256 |
if(cli_memstr(tbuff, 4091, "\xe8\x04\x72\x00\x00", 5)) { |
1257 |
- *ctx->virname = dam ? "Heuristics.W32.Magistr.B.dam" : "Heuristics.W32.Magistr.B"; |
|
1257 |
+ cli_append_virus(ctx,dam ? "Heuristics.W32.Magistr.B.dam" : "Heuristics.W32.Magistr.B"); |
|
1258 | 1258 |
free(exe_sections); |
1259 |
- return CL_VIRUS; |
|
1259 |
+ if (!SCAN_ALL) |
|
1260 |
+ return CL_VIRUS; |
|
1261 |
+ viruses_found++; |
|
1260 | 1262 |
} |
1261 | 1263 |
} |
1262 | 1264 |
} |
... | ... |
@@ -1302,10 +1302,12 @@ int cli_scanpe(cli_ctx *ctx) |
1302 | 1302 |
for(i=0;i<xsjs;i++) { |
1303 | 1303 |
if(!(code = fmap_need_off_once(map, jumps[i], 9))) continue; |
1304 | 1304 |
if((jump=cli_readint32(code))==0x60ec8b55 || (code[4]==0x0ec && ((jump==0x83ec8b55 && code[6]==0x60) || (jump==0x81ec8b55 && !code[7] && !code[8])))) { |
1305 |
- *ctx->virname = "Heuristics.W32.Polipos.A"; |
|
1305 |
+ cli_append_virus(ctx,"Heuristics.W32.Polipos.A"); |
|
1306 | 1306 |
free(jumps); |
1307 | 1307 |
free(exe_sections); |
1308 |
- return CL_VIRUS; |
|
1308 |
+ if (!SCAN_ALL) |
|
1309 |
+ return CL_VIRUS; |
|
1310 |
+ viruses_found++; |
|
1309 | 1311 |
} |
1310 | 1312 |
} |
1311 | 1313 |
free(jumps); |
... | ... |
@@ -1324,13 +1326,16 @@ int cli_scanpe(cli_ctx *ctx) |
1324 | 1324 |
else { |
1325 | 1325 |
cli_parseres_special(EC32(dirs[2].VirtualAddress), EC32(dirs[2].VirtualAddress), map, exe_sections, nsections, fsize, hdr_size, 0, 0, &m, stats); |
1326 | 1326 |
if ((ret = cli_detect_swizz(stats)) == CL_VIRUS) { |
1327 |
- *ctx->virname = "Heuristics.Trojan.Swizzor.Gen"; |
|
1327 |
+ cli_append_virus(ctx,"Heuristics.Trojan.Swizzor.Gen"); |
|
1328 | 1328 |
} |
1329 | 1329 |
free(stats); |
1330 | 1330 |
} |
1331 | 1331 |
if (ret != CL_CLEAN) { |
1332 |
+ if (!(ret == CL_VIRUS && SCAN_ALL)) { |
|
1332 | 1333 |
free(exe_sections); |
1333 | 1334 |
return ret; |
1335 |
+ } |
|
1336 |
+ viruses_found++; |
|
1334 | 1337 |
} |
1335 | 1338 |
} |
1336 | 1339 |
} |
... | ... |
@@ -2281,7 +2286,7 @@ int cli_scanpe(cli_ctx *ctx) |
2281 | 2281 |
} |
2282 | 2282 |
cli_bytecode_context_setpe(bc_ctx, &pedata, exe_sections); |
2283 | 2283 |
cli_bytecode_context_setctx(bc_ctx, ctx); |
2284 |
- ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_PE_UNPACKER, map, ctx->virname); |
|
2284 |
+ ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_PE_UNPACKER, map); |
|
2285 | 2285 |
switch (ret) { |
2286 | 2286 |
case CL_VIRUS: |
2287 | 2287 |
free(exe_sections); |
... | ... |
@@ -2299,6 +2304,8 @@ int cli_scanpe(cli_ctx *ctx) |
2299 | 2299 |
} |
2300 | 2300 |
|
2301 | 2301 |
free(exe_sections); |
2302 |
+ if (SCAN_ALL && viruses_found) |
|
2303 |
+ return CL_VIRUS; |
|
2302 | 2304 |
return CL_CLEAN; |
2303 | 2305 |
} |
2304 | 2306 |
|
... | ... |
@@ -1513,8 +1513,7 @@ static int parseicon(icon_groupset *set, uint32_t rva, cli_ctx *ctx, struct cli_ |
1513 | 1513 |
if(confidence >= positivematch) { |
1514 | 1514 |
cli_dbgmsg("confidence: %u\n", confidence); |
1515 | 1515 |
|
1516 |
- if(ctx->virname) |
|
1517 |
- *ctx->virname = matcher->icons[enginesize][x].name; |
|
1516 |
+ cli_append_virus(ctx,matcher->icons[enginesize][x].name); |
|
1518 | 1517 |
return CL_VIRUS; |
1519 | 1518 |
} |
1520 | 1519 |
} |
... | ... |
@@ -735,7 +735,7 @@ int phishingScan(cli_ctx* ctx,tag_arguments_t* hrefs) |
735 | 735 |
if(!pchk || pchk->is_disabled) |
736 | 736 |
return CL_CLEAN; |
737 | 737 |
|
738 |
- if(!ctx->found_possibly_unwanted) |
|
738 |
+ if(!ctx->found_possibly_unwanted && !SCAN_ALL) |
|
739 | 739 |
*ctx->virname=NULL; |
740 | 740 |
#if 0 |
741 | 741 |
FILE *f = fopen("/home/edwin/quarantine/urls","r"); |
... | ... |
@@ -810,29 +810,29 @@ int phishingScan(cli_ctx* ctx,tag_arguments_t* hrefs) |
810 | 810 |
case CL_PHISH_CLEAN: |
811 | 811 |
continue; |
812 | 812 |
case CL_PHISH_NUMERIC_IP: |
813 |
- *ctx->virname="Heuristics.Phishing.Email.Cloaked.NumericIP"; |
|
813 |
+ cli_append_virus(ctx, "Heuristics.Phishing.Email.Cloaked.NumericIP"); |
|
814 | 814 |
break; |
815 | 815 |
case CL_PHISH_CLOAKED_NULL: |
816 |
- *ctx->virname="Heuristics.Phishing.Email.Cloaked.Null";/*fakesite%01%00@fake.example.com*/ |
|
816 |
+ cli_append_virus(ctx, "Heuristics.Phishing.Email.Cloaked.Null");/*fakesite%01%00@fake.example.com*/ |
|
817 | 817 |
break; |
818 | 818 |
case CL_PHISH_SSL_SPOOF: |
819 |
- *ctx->virname="Heuristics.Phishing.Email.SSL-Spoof"; |
|
819 |
+ cli_append_virus(ctx, "Heuristics.Phishing.Email.SSL-Spoof"); |
|
820 | 820 |
break; |
821 | 821 |
case CL_PHISH_CLOAKED_UIU: |
822 |
- *ctx->virname="Heuristics.Phishing.Email.Cloaked.Username";/*http://banksite@fake.example.com*/ |
|
822 |
+ cli_append_virus(ctx, "Heuristics.Phishing.Email.Cloaked.Username");/*http://banksite@fake.example.com*/ |
|
823 | 823 |
break; |
824 | 824 |
case CL_PHISH_HASH0: |
825 |
- *ctx->virname="Heuristics.Safebrowsing.Suspected-malware_safebrowsing.clamav.net"; |
|
825 |
+ cli_append_virus(ctx, "Heuristics.Safebrowsing.Suspected-malware_safebrowsing.clamav.net"); |
|
826 | 826 |
break; |
827 | 827 |
case CL_PHISH_HASH1: |
828 |
- *ctx->virname="Heuristics.Phishing.URL.Blacklisted"; |
|
828 |
+ cli_append_virus(ctx, "Heuristics.Phishing.URL.Blacklisted"); |
|
829 | 829 |
break; |
830 | 830 |
case CL_PHISH_HASH2: |
831 |
- *ctx->virname="Heuristics.Safebrowsing.Suspected-phishing_safebrowsing.clamav.net"; |
|
831 |
+ cli_append_virus(ctx, "Heuristics.Safebrowsing.Suspected-phishing_safebrowsing.clamav.net"); |
|
832 | 832 |
break; |
833 | 833 |
case CL_PHISH_NOMATCH: |
834 | 834 |
default: |
835 |
- *ctx->virname="Heuristics.Phishing.Email.SpoofedDomain"; |
|
835 |
+ cli_append_virus(ctx, "Heuristics.Phishing.Email.SpoofedDomain"); |
|
836 | 836 |
break; |
837 | 837 |
} |
838 | 838 |
return cli_found_possibly_unwanted(ctx); |
... | ... |
@@ -1207,14 +1207,14 @@ static int hash_match(const struct regex_matcher *rlist, const char *host, size_ |
1207 | 1207 |
cli_dbgmsg("Looking up hash %s for %s(%u)%s(%u)\n", h, host, (unsigned)hlen, path, (unsigned)plen); |
1208 | 1208 |
#if 0 |
1209 | 1209 |
if (prefix_matched) { |
1210 |
- if (cli_bm_scanbuff(sha256_dig, 4, &virname, NULL, &rlist->hostkey_prefix,0,NULL,NULL) == CL_VIRUS) { |
|
1210 |
+ if (cli_bm_scanbuff(sha256_dig, 4, &virname, NULL, &rlist->hostkey_prefix,0,NULL,NULL,NULL) == CL_VIRUS) { |
|
1211 | 1211 |
cli_dbgmsg("prefix matched\n"); |
1212 | 1212 |
*prefix_matched = 1; |
1213 | 1213 |
} else |
1214 | 1214 |
return CL_SUCCESS; |
1215 | 1215 |
} |
1216 | 1216 |
#endif |
1217 |
- if (cli_bm_scanbuff(sha256_dig, 32, &virname, NULL, &rlist->sha256_hashes,0,NULL,NULL) == CL_VIRUS) { |
|
1217 |
+ if (cli_bm_scanbuff(sha256_dig, 32, &virname, NULL, &rlist->sha256_hashes,0,NULL,NULL,NULL) == CL_VIRUS) { |
|
1218 | 1218 |
cli_dbgmsg("This hash matched: %s\n", h); |
1219 | 1219 |
switch(*virname) { |
1220 | 1220 |
case 'W': |
... | ... |
@@ -489,7 +489,7 @@ static int cli_chkign(const struct cli_matcher *ignored, const char *signame, co |
489 | 489 |
if(!ignored || !signame || !entry) |
490 | 490 |
return 0; |
491 | 491 |
|
492 |
- if(cli_bm_scanbuff((const unsigned char *) signame, strlen(signame), &md5_expected, NULL, ignored, 0, NULL, NULL) == CL_VIRUS) { |
|
492 |
+ if(cli_bm_scanbuff((const unsigned char *) signame, strlen(signame), &md5_expected, NULL, ignored, 0, NULL, NULL,NULL) == CL_VIRUS) { |
|
493 | 493 |
if(md5_expected) { |
494 | 494 |
cli_md5_init(&md5ctx); |
495 | 495 |
cli_md5_update(&md5ctx, entry, strlen(entry)); |
... | ... |
@@ -357,7 +357,7 @@ static int add_hash(struct regex_matcher *matcher, char* pattern, const char fl, |
357 | 357 |
|
358 | 358 |
if (fl != 'W' && pat->length == 32 && |
359 | 359 |
cli_hashset_contains(&matcher->sha256_pfx_set, cli_readint32(pat->pattern)) && |
360 |
- cli_bm_scanbuff(pat->pattern, 32, &vname, NULL, &matcher->sha256_hashes,0,NULL,NULL) == CL_VIRUS) { |
|
360 |
+ cli_bm_scanbuff(pat->pattern, 32, &vname, NULL, &matcher->sha256_hashes,0,NULL,NULL,NULL) == CL_VIRUS) { |
|
361 | 361 |
if (*vname == 'W') { |
362 | 362 |
/* hash is whitelisted in local.gdb */ |
363 | 363 |
cli_dbgmsg("Skipping hash %s\n", pattern); |
... | ... |
@@ -118,7 +118,7 @@ static int cli_scandir(const char *dirname, cli_ctx *ctx) |
118 | 118 |
#endif |
119 | 119 |
STATBUF statbuf; |
120 | 120 |
char *fname; |
121 |
- |
|
121 |
+ unsigned int viruses_found = 0; |
|
122 | 122 |
|
123 | 123 |
if((dd = opendir(dirname)) != NULL) { |
124 | 124 |
#ifdef HAVE_READDIR_R_3 |
... | ... |
@@ -145,29 +145,43 @@ static int cli_scandir(const char *dirname, cli_ctx *ctx) |
145 | 145 |
if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) { |
146 | 146 |
if(cli_scandir(fname, ctx) == CL_VIRUS) { |
147 | 147 |
free(fname); |
148 |
- closedir(dd); |
|
149 |
- return CL_VIRUS; |
|
150 |
- } |
|
148 |
+ |
|
149 |
+ if (SCAN_ALL) { |
|
150 |
+ viruses_found++; |
|
151 |
+ continue; |
|
152 |
+ } |
|
153 |
+ |
|
154 |
+ closedir(dd); |
|
155 |
+ return CL_VIRUS; |
|
156 |
+ } |
|
151 | 157 |
} else { |
152 | 158 |
if(S_ISREG(statbuf.st_mode)) { |
153 | 159 |
if(cli_scanfile(fname, ctx) == CL_VIRUS) { |
154 | 160 |
free(fname); |
155 |
- closedir(dd); |
|
156 |
- return CL_VIRUS; |
|
157 |
- } |
|
161 |
+ |
|
162 |
+ if (SCAN_ALL) { |
|
163 |
+ viruses_found++; |
|
164 |
+ continue; |
|
165 |
+ } |
|
166 |
+ |
|
167 |
+ closedir(dd); |
|
168 |
+ return CL_VIRUS; |
|
169 |
+ } |
|
158 | 170 |
} |
159 | 171 |
} |
160 | 172 |
} |
161 | 173 |
free(fname); |
162 | 174 |
} |
163 | 175 |
} |
164 |
- } |
|
176 |
+ } |
|
165 | 177 |
} else { |
166 | 178 |
cli_dbgmsg("cli_scandir: Can't open directory %s.\n", dirname); |
167 | 179 |
return CL_EOPEN; |
168 | 180 |
} |
169 | 181 |
|
170 | 182 |
closedir(dd); |
183 |
+ if (SCAN_ALL && viruses_found) |
|
184 |
+ return CL_VIRUS; |
|
171 | 185 |
return CL_CLEAN; |
172 | 186 |
} |
173 | 187 |
|
... | ... |
@@ -194,7 +208,7 @@ static int cli_unrar_scanmetadata(int desc, unrar_metadata_t *metadata, cli_ctx |
194 | 194 |
cli_dbgmsg("RAR: Encrypted files found in archive.\n"); |
195 | 195 |
ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, NULL); |
196 | 196 |
if(ret != CL_VIRUS) { |
197 |
- *ctx->virname = "Heuristics.Encrypted.RAR"; |
|
197 |
+ cli_append_virus(ctx, "Heuristics.Encrypted.RAR"); |
|
198 | 198 |
return CL_VIRUS; |
199 | 199 |
} |
200 | 200 |
} |
... | ... |
@@ -208,7 +222,7 @@ static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c |
208 | 208 |
unrar_metadata_t *metadata, *metadata_tmp; |
209 | 209 |
char *dir; |
210 | 210 |
unrar_state_t rar_state; |
211 |
- |
|
211 |
+ unsigned int viruses_found = 0; |
|
212 | 212 |
|
213 | 213 |
cli_dbgmsg("in scanrar()\n"); |
214 | 214 |
|
... | ... |
@@ -236,7 +250,7 @@ static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c |
236 | 236 |
lseek(desc, 0, SEEK_SET); |
237 | 237 |
ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, NULL); |
238 | 238 |
if(ret != CL_VIRUS) |
239 |
- *ctx->virname = "Heuristics.Encrypted.RAR"; |
|
239 |
+ cli_append_virus(ctx, "Heuristics.Encrypted.RAR"); |
|
240 | 240 |
return CL_VIRUS; |
241 | 241 |
} |
242 | 242 |
return CL_CLEAN; |
... | ... |
@@ -286,12 +300,19 @@ static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c |
286 | 286 |
if(!ctx->engine->keeptmp) |
287 | 287 |
if (cli_unlink(rar_state.filename)) ret = CL_EUNLINK; |
288 | 288 |
if(rc == CL_VIRUS ) { |
289 |
- cli_dbgmsg("RAR: infected with %s\n",*ctx->virname); |
|
289 |
+ cli_dbgmsg("RAR: infected with %s\n", cli_get_last_virus(ctx)); |
|
290 | 290 |
ret = CL_VIRUS; |
291 |
- break; |
|
291 |
+ viruses_found++; |
|
292 | 292 |
} |
293 | 293 |
} |
294 | 294 |
|
295 |
+ if(ret == CL_VIRUS) { |
|
296 |
+ if(SCAN_ALL) |
|
297 |
+ ret = CL_SUCCESS; |
|
298 |
+ else |
|
299 |
+ break; |
|
300 |
+ } |
|
301 |
+ |
|
295 | 302 |
if(ret == CL_SUCCESS) |
296 | 303 |
ret = cli_unrar_scanmetadata(desc,rar_state.metadata_tail, ctx, rar_state.file_count, sfx_check); |
297 | 304 |
|
... | ... |
@@ -321,6 +342,8 @@ static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c |
321 | 321 |
} |
322 | 322 |
cli_dbgmsg("RAR: Exit code: %d\n", ret); |
323 | 323 |
|
324 |
+ if (SCAN_ALL && viruses_found) |
|
325 |
+ return CL_VIRUS; |
|
324 | 326 |
return ret; |
325 | 327 |
} |
326 | 328 |
|
... | ... |
@@ -373,7 +396,7 @@ static int cli_scanarj(cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check) |
373 | 373 |
rc = cli_magic_scandesc(metadata.ofd, ctx); |
374 | 374 |
close(metadata.ofd); |
375 | 375 |
if (rc == CL_VIRUS) { |
376 |
- cli_dbgmsg("ARJ: infected with %s\n",*ctx->virname); |
|
376 |
+ cli_dbgmsg("ARJ: infected with %s\n", cli_get_last_virus(ctx)); |
|
377 | 377 |
ret = CL_VIRUS; |
378 | 378 |
if (metadata.filename) { |
379 | 379 |
free(metadata.filename); |
... | ... |
@@ -446,7 +469,7 @@ static int cli_scangzip_with_zib_from_the_80s(cli_ctx *ctx, unsigned char *buff) |
446 | 446 |
gzclose(gz); |
447 | 447 |
|
448 | 448 |
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) { |
449 |
- cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname); |
|
449 |
+ cli_dbgmsg("GZip: Infected with %s\n", cli_get_last_virus(ctx)); |
|
450 | 450 |
close(fd); |
451 | 451 |
if(!ctx->engine->keeptmp) { |
452 | 452 |
if (cli_unlink(tmpname)) { |
... | ... |
@@ -538,7 +561,7 @@ static int cli_scangzip(cli_ctx *ctx) |
538 | 538 |
inflateEnd(&z); |
539 | 539 |
|
540 | 540 |
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) { |
541 |
- cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname); |
|
541 |
+ cli_dbgmsg("GZip: Infected with %s\n", cli_get_last_virus(ctx)); |
|
542 | 542 |
close(fd); |
543 | 543 |
if(!ctx->engine->keeptmp) { |
544 | 544 |
if (cli_unlink(tmpname)) { |
... | ... |
@@ -648,7 +671,7 @@ static int cli_scanbzip(cli_ctx *ctx) |
648 | 648 |
} |
649 | 649 |
|
650 | 650 |
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS ) { |
651 |
- cli_dbgmsg("Bzip: Infected with %s\n", *ctx->virname); |
|
651 |
+ cli_dbgmsg("Bzip: Infected with %s\n", cli_get_last_virus(ctx)); |
|
652 | 652 |
} |
653 | 653 |
close(fd); |
654 | 654 |
if(!ctx->engine->keeptmp) |
... | ... |
@@ -700,7 +723,7 @@ static int cli_scanmscab(cli_ctx *ctx, off_t sfx_offset) |
700 | 700 |
struct cab_archive cab; |
701 | 701 |
struct cab_file *file; |
702 | 702 |
unsigned int corrupted_input; |
703 |
- |
|
703 |
+ unsigned int viruses_found = 0; |
|
704 | 704 |
|
705 | 705 |
cli_dbgmsg("in cli_scanmscab()\n"); |
706 | 706 |
|
... | ... |
@@ -711,8 +734,11 @@ static int cli_scanmscab(cli_ctx *ctx, off_t sfx_offset) |
711 | 711 |
files++; |
712 | 712 |
|
713 | 713 |
if(cli_matchmeta(ctx, file->name, 0, file->length, 0, files, 0, NULL) == CL_VIRUS) { |
714 |
- ret = CL_VIRUS; |
|
715 |
- break; |
|
714 |
+ if (!SCAN_ALL) { |
|
715 |
+ ret = CL_VIRUS; |
|
716 |
+ break; |
|
717 |
+ } |
|
718 |
+ viruses_found++; |
|
716 | 719 |
} |
717 | 720 |
|
718 | 721 |
if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) { |
... | ... |
@@ -751,11 +777,17 @@ static int cli_scanmscab(cli_ctx *ctx, off_t sfx_offset) |
751 | 751 |
} |
752 | 752 |
} |
753 | 753 |
free(tempname); |
754 |
- if(ret == CL_VIRUS) |
|
755 |
- break; |
|
754 |
+ if(ret == CL_VIRUS) { |
|
755 |
+ if (SCAN_ALL) |
|
756 |
+ viruses_found++; |
|
757 |
+ else |
|
758 |
+ break; |
|
759 |
+ } |
|
756 | 760 |
} |
757 | 761 |
|
758 | 762 |
cab_free(&cab); |
763 |
+ if (viruses_found) |
|
764 |
+ return CL_VIRUS; |
|
759 | 765 |
return ret; |
760 | 766 |
} |
761 | 767 |
|
... | ... |
@@ -766,6 +798,7 @@ static int vba_scandata(const unsigned char *data, unsigned int len, cli_ctx *ct |
766 | 766 |
struct cli_ac_data gmdata, tmdata; |
767 | 767 |
struct cli_ac_data *mdata[2]; |
768 | 768 |
int ret; |
769 |
+ unsigned int viruses_found = 0; |
|
769 | 770 |
|
770 | 771 |
if((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) |
771 | 772 |
return ret; |
... | ... |
@@ -779,14 +812,20 @@ static int vba_scandata(const unsigned char *data, unsigned int len, cli_ctx *ct |
779 | 779 |
|
780 | 780 |
ret = cli_scanbuff(data, len, 0, ctx, CL_TYPE_MSOLE2, mdata); |
781 | 781 |
|
782 |
- if(ret != CL_VIRUS) { |
|
782 |
+ if(ret != CL_VIRUS || SCAN_ALL) { |
|
783 |
+ if (SCAN_ALL) |
|
784 |
+ viruses_found++; |
|
783 | 785 |
ret = cli_lsig_eval(ctx, troot, &tmdata, NULL, NULL); |
784 |
- if(ret != CL_VIRUS) |
|
786 |
+ if(ret != CL_VIRUS || SCAN_ALL) |
|
787 |
+ if (SCAN_ALL) |
|
788 |
+ viruses_found++; |
|
785 | 789 |
ret = cli_lsig_eval(ctx, groot, &gmdata, NULL, NULL); |
786 | 790 |
} |
787 | 791 |
cli_ac_freedata(&tmdata); |
788 | 792 |
cli_ac_freedata(&gmdata); |
789 | 793 |
|
794 |
+ if (viruses_found) |
|
795 |
+ return CL_VIRUS; |
|
790 | 796 |
return ret; |
791 | 797 |
} |
792 | 798 |
|
... | ... |
@@ -807,6 +846,7 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U) |
807 | 807 |
unsigned char *data; |
808 | 808 |
char *hash; |
809 | 809 |
uint32_t hashcnt; |
810 |
+ unsigned int viruses_found = 0; |
|
810 | 811 |
|
811 | 812 |
|
812 | 813 |
cli_dbgmsg("VBADir: %s\n", dirname); |
... | ... |
@@ -831,9 +871,13 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U) |
831 | 831 |
if(ctx->scanned) |
832 | 832 |
*ctx->scanned += data_len / CL_COUNT_PRECISION; |
833 | 833 |
if(vba_scandata(data, data_len, ctx) == CL_VIRUS) { |
834 |
- free(data); |
|
835 |
- ret = CL_VIRUS; |
|
836 |
- break; |
|
834 |
+ if (SCAN_ALL) |
|
835 |
+ viruses_found++; |
|
836 |
+ else { |
|
837 |
+ free(data); |
|
838 |
+ ret = CL_VIRUS; |
|
839 |
+ break; |
|
840 |
+ } |
|
837 | 841 |
} |
838 | 842 |
free(data); |
839 | 843 |
} |
... | ... |
@@ -845,10 +889,12 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U) |
845 | 845 |
free(vba_project->dir); |
846 | 846 |
free(vba_project->offset); |
847 | 847 |
free(vba_project); |
848 |
- if (ret == CL_VIRUS) break; |
|
848 |
+ if (ret == CL_VIRUS && !SCAN_ALL) |
|
849 |
+ break; |
|
849 | 850 |
} |
850 | 851 |
|
851 |
- if(ret == CL_CLEAN && (hashcnt = uniq_get(U, "powerpoint document", 19, &hash))) { |
|
852 |
+ if((ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) && |
|
853 |
+ (hashcnt = uniq_get(U, "powerpoint document", 19, &hash))) { |
|
852 | 854 |
while(hashcnt--) { |
853 | 855 |
snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", dirname, hash, hashcnt); |
854 | 856 |
vbaname[sizeof(vbaname)-1] = '\0'; |
... | ... |
@@ -857,6 +903,7 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U) |
857 | 857 |
if ((fullname = cli_ppt_vba_read(fd, ctx))) { |
858 | 858 |
if(cli_scandir(fullname, ctx) == CL_VIRUS) { |
859 | 859 |
ret = CL_VIRUS; |
860 |
+ viruses_found++; |
|
860 | 861 |
} |
861 | 862 |
if(!ctx->engine->keeptmp) |
862 | 863 |
cli_rmdirs(fullname); |
... | ... |
@@ -866,7 +913,8 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U) |
866 | 866 |
} |
867 | 867 |
} |
868 | 868 |
|
869 |
- if (ret == CL_CLEAN && (hashcnt = uniq_get(U, "worddocument", 12, &hash))) { |
|
869 |
+ if ((ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) && |
|
870 |
+ (hashcnt = uniq_get(U, "worddocument", 12, &hash))) { |
|
870 | 871 |
while(hashcnt--) { |
871 | 872 |
snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt); |
872 | 873 |
vbaname[sizeof(vbaname)-1] = '\0'; |
... | ... |
@@ -888,9 +936,13 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U) |
888 | 888 |
if(ctx->scanned) |
889 | 889 |
*ctx->scanned += vba_project->length[i] / CL_COUNT_PRECISION; |
890 | 890 |
if(vba_scandata(data, vba_project->length[i], ctx) == CL_VIRUS) { |
891 |
+ if (SCAN_ALL) |
|
892 |
+ viruses_found++; |
|
893 |
+ else { |
|
891 | 894 |
free(data); |
892 | 895 |
ret = CL_VIRUS; |
893 | 896 |
break; |
897 |
+ } |
|
894 | 898 |
} |
895 | 899 |
free(data); |
896 | 900 |
} |
... | ... |
@@ -904,11 +956,16 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U) |
904 | 904 |
free(vba_project->key); |
905 | 905 |
free(vba_project->length); |
906 | 906 |
free(vba_project); |
907 |
- if(ret == CL_VIRUS) break; |
|
907 |
+ if(ret == CL_VIRUS) { |
|
908 |
+ if (SCAN_ALL) |
|
909 |
+ viruses_found++; |
|
910 |
+ else |
|
911 |
+ break; |
|
912 |
+ } |
|
908 | 913 |
} |
909 | 914 |
} |
910 | 915 |
|
911 |
- if(ret != CL_CLEAN) |
|
916 |
+ if(ret != CL_CLEAN && !(ret == CL_VIRUS && SCAN_ALL)) |
|
912 | 917 |
return ret; |
913 | 918 |
|
914 | 919 |
/* Check directory for embedded OLE objects */ |
... | ... |
@@ -921,7 +978,7 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U) |
921 | 921 |
if (fd >= 0) { |
922 | 922 |
ret = cli_scan_ole10(fd, ctx); |
923 | 923 |
close(fd); |
924 |
- if(ret != CL_CLEAN) |
|
924 |
+ if(ret != CL_CLEAN && !(ret == CL_VIRUS && SCAN_ALL)) |
|
925 | 925 |
return ret; |
926 | 926 |
} |
927 | 927 |
} |
... | ... |
@@ -954,10 +1011,14 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U) |
954 | 954 |
if(LSTAT(fullname, &statbuf) != -1) { |
955 | 955 |
if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) |
956 | 956 |
if (cli_vba_scandir(fullname, ctx, U) == CL_VIRUS) { |
957 |
- ret = CL_VIRUS; |
|
958 |
- free(fullname); |
|
959 |
- break; |
|
960 |
- } |
|
957 |
+ if (SCAN_ALL) |
|
958 |
+ viruses_found++; |
|
959 |
+ else { |
|
960 |
+ ret = CL_VIRUS; |
|
961 |
+ free(fullname); |
|
962 |
+ break; |
|
963 |
+ } |
|
964 |
+ } |
|
961 | 965 |
} |
962 | 966 |
free(fullname); |
963 | 967 |
} |
... | ... |
@@ -970,9 +1031,12 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U) |
970 | 970 |
|
971 | 971 |
closedir(dd); |
972 | 972 |
if(BLOCK_MACROS && hasmacros) { |
973 |
- *ctx->virname = "Heuristics.OLE2.ContainsMacros"; |
|
973 |
+ cli_append_virus(ctx, "Heuristics.OLE2.ContainsMacros"); |
|
974 | 974 |
ret = CL_VIRUS; |
975 |
+ viruses_found++; |
|
975 | 976 |
} |
977 |
+ if (SCAN_ALL && viruses_found) |
|
978 |
+ return CL_VIRUS; |
|
976 | 979 |
return ret; |
977 | 980 |
} |
978 | 981 |
|
... | ... |
@@ -981,6 +1045,7 @@ static int cli_scanhtml(cli_ctx *ctx) |
981 | 981 |
char *tempname, fullname[1024]; |
982 | 982 |
int ret=CL_CLEAN, fd; |
983 | 983 |
fmap_t *map = *ctx->fmap; |
984 |
+ unsigned int viruses_found = 0; |
|
984 | 985 |
|
985 | 986 |
cli_dbgmsg("in cli_scanhtml()\n"); |
986 | 987 |
|
... | ... |
@@ -1008,34 +1073,38 @@ static int cli_scanhtml(cli_ctx *ctx) |
1008 | 1008 |
snprintf(fullname, 1024, "%s"PATHSEP"nocomment.html", tempname); |
1009 | 1009 |
fd = open(fullname, O_RDONLY|O_BINARY); |
1010 | 1010 |
if (fd >= 0) { |
1011 |
- ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL); |
|
1012 |
- close(fd); |
|
1011 |
+ if ((ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS) |
|
1012 |
+ viruses_found++; |
|
1013 |
+ close(fd); |
|
1013 | 1014 |
} |
1014 | 1015 |
|
1015 |
- if(ret == CL_CLEAN && map->len < 2097152) { |
|
1016 |
+ if((ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) && map->len < 2097152) { |
|
1016 | 1017 |
/* limit to 2 MB, we're not interesting in scanning large files in notags form */ |
1017 | 1018 |
/* TODO: don't even create notags if file is over 2 MB */ |
1018 | 1019 |
snprintf(fullname, 1024, "%s"PATHSEP"notags.html", tempname); |
1019 | 1020 |
fd = open(fullname, O_RDONLY|O_BINARY); |
1020 | 1021 |
if(fd >= 0) { |
1021 |
- ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL); |
|
1022 |
- close(fd); |
|
1022 |
+ if ((ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS) |
|
1023 |
+ viruses_found++; |
|
1024 |
+ close(fd); |
|
1023 | 1025 |
} |
1024 | 1026 |
} |
1025 | 1027 |
|
1026 |
- if(ret == CL_CLEAN) { |
|
1028 |
+ if(ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) { |
|
1027 | 1029 |
snprintf(fullname, 1024, "%s"PATHSEP"javascript", tempname); |
1028 | 1030 |
fd = open(fullname, O_RDONLY|O_BINARY); |
1029 | 1031 |
if(fd >= 0) { |
1030 |
- ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL); |
|
1031 |
- if (ret == CL_CLEAN) { |
|
1032 |
- ret = cli_scandesc(fd, ctx, CL_TYPE_TEXT_ASCII, 0, NULL, AC_SCAN_VIR, NULL); |
|
1033 |
- } |
|
1034 |
- close(fd); |
|
1032 |
+ if ((ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS) |
|
1033 |
+ viruses_found++; |
|
1034 |
+ if (ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) { |
|
1035 |
+ if ((ret = cli_scandesc(fd, ctx, CL_TYPE_TEXT_ASCII, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS) |
|
1036 |
+ viruses_found++; |
|
1037 |
+ } |
|
1038 |
+ close(fd); |
|
1035 | 1039 |
} |
1036 | 1040 |
} |
1037 | 1041 |
|
1038 |
- if (ret == CL_CLEAN) { |
|
1042 |
+ if (ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) { |
|
1039 | 1043 |
snprintf(fullname, 1024, "%s"PATHSEP"rfc2397", tempname); |
1040 | 1044 |
ret = cli_scandir(fullname, ctx); |
1041 | 1045 |
} |
... | ... |
@@ -1044,6 +1113,8 @@ static int cli_scanhtml(cli_ctx *ctx) |
1044 | 1044 |
cli_rmdirs(tempname); |
1045 | 1045 |
|
1046 | 1046 |
free(tempname); |
1047 |
+ if (SCAN_ALL && viruses_found) |
|
1048 |
+ return CL_VIRUS; |
|
1047 | 1049 |
return ret; |
1048 | 1050 |
} |
1049 | 1051 |
|
... | ... |
@@ -1061,6 +1132,7 @@ static int cli_scanscript(cli_ctx *ctx) |
1061 | 1061 |
struct cli_ac_data *mdata[2]; |
1062 | 1062 |
fmap_t *map = *ctx->fmap; |
1063 | 1063 |
size_t at = 0; |
1064 |
+ unsigned int viruses_found = 0; |
|
1064 | 1065 |
|
1065 | 1066 |
if (!ctx || !ctx->engine->root) |
1066 | 1067 |
return CL_ENULLARG; |
... | ... |
@@ -1094,7 +1166,7 @@ static int cli_scanscript(cli_ctx *ctx) |
1094 | 1094 |
text_normalize_init(&state, normalized, SCANBUFF + maxpatlen); |
1095 | 1095 |
ret = CL_CLEAN; |
1096 | 1096 |
|
1097 |
- if ((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) |
|
1097 |
+ if ((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) |
|
1098 | 1098 |
return ret; |
1099 | 1099 |
|
1100 | 1100 |
if ((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) { |
... | ... |
@@ -1118,8 +1190,12 @@ static int cli_scanscript(cli_ctx *ctx) |
1118 | 1118 |
} |
1119 | 1119 |
/* when we flush the buffer also scan */ |
1120 | 1120 |
if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) { |
1121 |
- ret = CL_VIRUS; |
|
1122 |
- break; |
|
1121 |
+ if (SCAN_ALL) |
|
1122 |
+ viruses_found++; |
|
1123 |
+ else { |
|
1124 |
+ ret = CL_VIRUS; |
|
1125 |
+ break; |
|
1126 |
+ } |
|
1123 | 1127 |
} |
1124 | 1128 |
if(ctx->scanned) |
1125 | 1129 |
*ctx->scanned += state.out_pos / CL_COUNT_PRECISION; |
... | ... |
@@ -1140,14 +1216,18 @@ static int cli_scanscript(cli_ctx *ctx) |
1140 | 1140 |
close(ofd); |
1141 | 1141 |
} |
1142 | 1142 |
free(normalized); |
1143 |
- if(ret != CL_VIRUS) { |
|
1144 |
- ret = cli_lsig_eval(ctx, troot, &tmdata, NULL, NULL); |
|
1145 |
- if(ret != CL_VIRUS) |
|
1146 |
- ret = cli_lsig_eval(ctx, groot, &gmdata, NULL, NULL); |
|
1143 |
+ if(ret != CL_VIRUS || SCAN_ALL) { |
|
1144 |
+ if ((ret = cli_lsig_eval(ctx, troot, &tmdata, NULL, NULL)) == CL_VIRUS) |
|
1145 |
+ viruses_found++; |
|
1146 |
+ if(ret != CL_VIRUS || SCAN_ALL) |
|
1147 |
+ if ((ret = cli_lsig_eval(ctx, groot, &gmdata, NULL, NULL)) == CL_VIRUS) |
|
1148 |
+ viruses_found++; |
|
1147 | 1149 |
} |
1148 | 1150 |
cli_ac_freedata(&tmdata); |
1149 | 1151 |
cli_ac_freedata(&gmdata); |
1150 | 1152 |
|
1153 |
+ if (SCAN_ALL && viruses_found) |
|
1154 |
+ return CL_VIRUS; |
|
1151 | 1155 |
return ret; |
1152 | 1156 |
} |
1153 | 1157 |
|
... | ... |
@@ -1293,6 +1373,7 @@ static int cli_scanmschm(cli_ctx *ctx) |
1293 | 1293 |
int ret = CL_CLEAN, rc; |
1294 | 1294 |
chm_metadata_t metadata; |
1295 | 1295 |
char *dir; |
1296 |
+ unsigned int viruses_found = 0; |
|
1296 | 1297 |
|
1297 | 1298 |
cli_dbgmsg("in cli_scanmschm()\n"); |
1298 | 1299 |
|
... | ... |
@@ -1325,9 +1406,13 @@ static int cli_scanmschm(cli_ctx *ctx) |
1325 | 1325 |
rc = cli_magic_scandesc(metadata.ofd, ctx); |
1326 | 1326 |
close(metadata.ofd); |
1327 | 1327 |
if (rc == CL_VIRUS) { |
1328 |
- cli_dbgmsg("CHM: infected with %s\n",*ctx->virname); |
|
1329 |
- ret = CL_VIRUS; |
|
1330 |
- break; |
|
1328 |
+ cli_dbgmsg("CHM: infected with %s\n", cli_get_last_virus(ctx)); |
|
1329 |
+ if (SCAN_ALL) |
|
1330 |
+ viruses_found++; |
|
1331 |
+ else { |
|
1332 |
+ ret = CL_VIRUS; |
|
1333 |
+ break; |
|
1334 |
+ } |
|
1331 | 1335 |
} |
1332 | 1336 |
} |
1333 | 1337 |
|
... | ... |
@@ -1344,6 +1429,8 @@ static int cli_scanmschm(cli_ctx *ctx) |
1344 | 1344 |
if (ret == CL_BREAK) |
1345 | 1345 |
ret = CL_CLEAN; |
1346 | 1346 |
|
1347 |
+ if (SCAN_ALL && viruses_found) |
|
1348 |
+ return CL_VIRUS; |
|
1347 | 1349 |
return ret; |
1348 | 1350 |
} |
1349 | 1351 |
|
... | ... |
@@ -1379,7 +1466,7 @@ static int cli_scanriff(cli_ctx *ctx) |
1379 | 1379 |
|
1380 | 1380 |
if(cli_check_riff_exploit(ctx) == 2) { |
1381 | 1381 |
ret = CL_VIRUS; |
1382 |
- *ctx->virname = "Heuristics.Exploit.W32.MS05-002"; |
|
1382 |
+ cli_append_virus(ctx, "Heuristics.Exploit.W32.MS05-002"); |
|
1383 | 1383 |
} |
1384 | 1384 |
|
1385 | 1385 |
return ret; |
... | ... |
@@ -1391,7 +1478,7 @@ static int cli_scanjpeg(cli_ctx *ctx) |
1391 | 1391 |
|
1392 | 1392 |
if(cli_check_jpeg_exploit(ctx, 0) == 1) { |
1393 | 1393 |
ret = CL_VIRUS; |
1394 |
- *ctx->virname = "Heuristics.Exploit.W32.MS04-028"; |
|
1394 |
+ cli_append_virus(ctx, "Heuristics.Exploit.W32.MS04-028"); |
|
1395 | 1395 |
} |
1396 | 1396 |
|
1397 | 1397 |
return ret; |
... | ... |
@@ -1446,7 +1533,7 @@ static int cli_scancryptff(cli_ctx *ctx) |
1446 | 1446 |
cli_dbgmsg("CryptFF: Scanning decrypted data\n"); |
1447 | 1447 |
|
1448 | 1448 |
if((ret = cli_magic_scandesc(ndesc, ctx)) == CL_VIRUS) |
1449 |
- cli_dbgmsg("CryptFF: Infected with %s\n", *ctx->virname); |
|
1449 |
+ cli_dbgmsg("CryptFF: Infected with %s\n", cli_get_last_virus(ctx)); |
|
1450 | 1450 |
|
1451 | 1451 |
close(ndesc); |
1452 | 1452 |
|
... | ... |
@@ -1538,7 +1625,7 @@ static int cli_scanmail(cli_ctx *ctx) |
1538 | 1538 |
{ |
1539 | 1539 |
char *dir; |
1540 | 1540 |
int ret; |
1541 |
- |
|
1541 |
+ unsigned int viruses_found = 0; |
|
1542 | 1542 |
|
1543 | 1543 |
cli_dbgmsg("Starting cli_scanmail(), recursion = %u\n", ctx->recursion); |
1544 | 1544 |
|
... | ... |
@@ -1556,10 +1643,14 @@ static int cli_scanmail(cli_ctx *ctx) |
1556 | 1556 |
* Extract the attachments into the temporary directory |
1557 | 1557 |
*/ |
1558 | 1558 |
if((ret = cli_mbox(dir, ctx))) { |
1559 |
- if(!ctx->engine->keeptmp) |
|
1560 |
- cli_rmdirs(dir); |
|
1561 |
- free(dir); |
|
1562 |
- return ret; |
|
1559 |
+ if (ret == CL_VIRUS && SCAN_ALL) |
|
1560 |
+ viruses_found++; |
|
1561 |
+ else { |
|
1562 |
+ if(!ctx->engine->keeptmp) |
|
1563 |
+ cli_rmdirs(dir); |
|
1564 |
+ free(dir); |
|
1565 |
+ return ret; |
|
1566 |
+ } |
|
1563 | 1567 |
} |
1564 | 1568 |
|
1565 | 1569 |
ret = cli_scandir(dir, ctx); |
... | ... |
@@ -1568,6 +1659,8 @@ static int cli_scanmail(cli_ctx *ctx) |
1568 | 1568 |
cli_rmdirs(dir); |
1569 | 1569 |
|
1570 | 1570 |
free(dir); |
1571 |
+ if (SCAN_ALL && viruses_found) |
|
1572 |
+ return CL_VIRUS; |
|
1571 | 1573 |
return ret; |
1572 | 1574 |
} |
1573 | 1575 |
|
... | ... |
@@ -1582,7 +1675,7 @@ static int cli_scan_structured(cli_ctx *ctx) |
1582 | 1582 |
size_t pos = 0; |
1583 | 1583 |
int (*ccfunc)(const unsigned char *buffer, int length); |
1584 | 1584 |
int (*ssnfunc)(const unsigned char *buffer, int length); |
1585 |
- |
|
1585 |
+ unsigned int viruses_found; |
|
1586 | 1586 |
|
1587 | 1587 |
if(ctx == NULL) |
1588 | 1588 |
return CL_ENULLARG; |
... | ... |
@@ -1632,16 +1725,24 @@ static int cli_scan_structured(cli_ctx *ctx) |
1632 | 1632 |
|
1633 | 1633 |
if(cc_count != 0 && cc_count >= ctx->engine->min_cc_count) { |
1634 | 1634 |
cli_dbgmsg("cli_scan_structured: %u credit card numbers detected\n", cc_count); |
1635 |
- *ctx->virname = "Heuristics.Structured.CreditCardNumber"; |
|
1636 |
- return CL_VIRUS; |
|
1635 |
+ cli_append_virus(ctx,"Heuristics.Structured.CreditCardNumber"); |
|
1636 |
+ if (SCAN_ALL) |
|
1637 |
+ viruses_found++; |
|
1638 |
+ else |
|
1639 |
+ return CL_VIRUS; |
|
1637 | 1640 |
} |
1638 | 1641 |
|
1639 | 1642 |
if(ssn_count != 0 && ssn_count >= ctx->engine->min_ssn_count) { |
1640 | 1643 |
cli_dbgmsg("cli_scan_structured: %u social security numbers detected\n", ssn_count); |
1641 |
- *ctx->virname = "Heuristics.Structured.SSN"; |
|
1642 |
- return CL_VIRUS; |
|
1644 |
+ cli_append_virus(ctx,"Heuristics.Structured.SSN"); |
|
1645 |
+ if (SCAN_ALL) |
|
1646 |
+ viruses_found++; |
|
1647 |
+ else |
|
1648 |
+ return CL_VIRUS; |
|
1643 | 1649 |
} |
1644 | 1650 |
|
1651 |
+ if (SCAN_ALL && viruses_found) |
|
1652 |
+ return CL_VIRUS; |
|
1645 | 1653 |
return CL_CLEAN; |
1646 | 1654 |
} |
1647 | 1655 |
|
... | ... |
@@ -1707,7 +1808,7 @@ static int cli_scanembpe(cli_ctx *ctx, off_t offset) |
1707 | 1707 |
ret = cli_magic_scandesc(fd, ctx); |
1708 | 1708 |
ctx->corrupted_input = corrupted_input; |
1709 | 1709 |
if(ret == CL_VIRUS) { |
1710 |
- cli_dbgmsg("cli_scanembpe: Infected with %s\n", *ctx->virname); |
|
1710 |
+ cli_dbgmsg("cli_scanembpe: Infected with %s\n", cli_get_last_virus(ctx)); |
|
1711 | 1711 |
close(fd); |
1712 | 1712 |
if(!ctx->engine->keeptmp) { |
1713 | 1713 |
if (cli_unlink(tmpname)) { |
... | ... |
@@ -1903,7 +2004,7 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_ |
1903 | 1903 |
if(ret >= CL_TYPENO) { |
1904 | 1904 |
perf_nested_start(ctx, PERFT_RAWTYPENO, PERFT_SCAN); |
1905 | 1905 |
ctx->recursion++; |
1906 |
- if(nret != CL_VIRUS) { |
|
1906 |
+ if(nret != CL_VIRUS) { //TODO: don't need this test: nret == CL_CLEAN |
|
1907 | 1907 |
lastrar = 0xdeadbeef; |
1908 | 1908 |
fpt = ftoffset; |
1909 | 1909 |
while(fpt) { |
... | ... |
@@ -2068,7 +2169,7 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_ |
2068 | 2068 |
} |
2069 | 2069 |
|
2070 | 2070 |
if(ret == CL_VIRUS) |
2071 |
- cli_dbgmsg("%s found\n", *ctx->virname); |
|
2071 |
+ cli_dbgmsg("%s found\n", cli_get_last_virus(ctx)); |
|
2072 | 2072 |
|
2073 | 2073 |
return ret; |
2074 | 2074 |
} |
... | ... |
@@ -2090,26 +2191,25 @@ static void emax_reached(cli_ctx *ctx) { |
2090 | 2090 |
#define LINESTR2(x) LINESTR(x) |
2091 | 2091 |
#define __AT__ " at line "LINESTR2(__LINE__) |
2092 | 2092 |
|
2093 |
-#define early_ret_from_magicscan(retcode) \ |
|
2094 |
- do {\ |
|
2095 |
- cli_dbgmsg("cli_magic_scandesc: returning %d %s (no post, no cache)\n", retcode, __AT__);\ |
|
2096 |
- return retcode; \ |
|
2093 |
+#define early_ret_from_magicscan(retcode) \ |
|
2094 |
+ do { \ |
|
2095 |
+ cli_dbgmsg("cli_magic_scandesc: returning %d %s (no post, no cache)\n", retcode, __AT__); \ |
|
2096 |
+ return retcode; \ |
|
2097 | 2097 |
} while(0) |
2098 | 2098 |
|
2099 |
-#define ret_from_magicscan(retcode) \ |
|
2100 |
- do { \ |
|
2101 |
- cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__); \ |
|
2102 |
- if(ctx->engine->cb_post_scan) { \ |
|
2103 |
- perf_start(ctx, PERFT_POSTCB); \ |
|
2104 |
- switch(ctx->engine->cb_post_scan(fmap_fd(*ctx->fmap), retcode, retcode == CL_VIRUS && ctx->virname ? *ctx->virname : NULL, ctx->cb_ctx)) { \ |
|
2099 |
+#define ret_from_magicscan(retcode) \ |
|
2100 |
+ do { \ |
|
2101 |
+ cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__); \ |
|
2102 |
+ if(ctx->engine->cb_post_scan) { \ |
|
2103 |
+ perf_start(ctx, PERFT_POSTCB); \ |
|
2104 |
+ switch(ctx->engine->cb_post_scan(fmap_fd(*ctx->fmap), retcode, ret == CL_VIRUS ? cli_get_last_virus(ctx) : NULL, ctx->cb_ctx)) { \ |
|
2105 | 2105 |
case CL_BREAK: \ |
2106 | 2106 |
cli_dbgmsg("cli_magic_scandesc: file whitelisted by post_scan callback\n"); \ |
2107 | 2107 |
perf_stop(ctx, PERFT_POSTCB); \ |
2108 | 2108 |
return CL_CLEAN; \ |
2109 | 2109 |
case CL_VIRUS: \ |
2110 | 2110 |
cli_dbgmsg("cli_magic_scandesc: file blacklisted by post_scan callback\n"); \ |
2111 |
- if(ctx->virname) \ |
|
2112 |
- *ctx->virname = "Detected.By.Callback"; \ |
|
2111 |
+ cli_append_virus(ctx, "Detected.By.Callback"); \ |
|
2113 | 2112 |
perf_stop(ctx, PERFT_POSTCB); \ |
2114 | 2113 |
if (retcode != CL_VIRUS) \ |
2115 | 2114 |
return cli_checkfp(hash, hashed_size, ctx); \ |
... | ... |
@@ -2140,8 +2240,7 @@ static void emax_reached(cli_ctx *ctx) { |
2140 | 2140 |
ret_from_magicscan(CL_CLEAN); \ |
2141 | 2141 |
case CL_VIRUS: \ |
2142 | 2142 |
cli_dbgmsg("cli_magic_scandesc: file blacklisted by "#scanfn" callback\n"); \ |
2143 |
- if(ctx->virname) \ |
|
2144 |
- *ctx->virname = "Detected.By.Callback"; \ |
|
2143 |
+ cli_append_virus(ctx, "Detected.By.Callback"); \ |
|
2145 | 2144 |
perf_stop(ctx, PERFT_PRECB); \ |
2146 | 2145 |
ret_from_magicscan(cli_checkfp(hash, hashed_size, ctx)); \ |
2147 | 2146 |
case CL_CLEAN: \ |
... | ... |
@@ -2165,6 +2264,7 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
2165 | 2165 |
bitset_t *old_hook_lsig_matches; |
2166 | 2166 |
const char *filetype; |
2167 | 2167 |
int cache_clean = 0, res; |
2168 |
+ unsigned int viruses_found = 0; |
|
2168 | 2169 |
|
2169 | 2170 |
cli_dbgmsg("in magic_scandesc\n"); |
2170 | 2171 |
if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) { |
... | ... |
@@ -2212,7 +2312,7 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
2212 | 2212 |
old_hook_lsig_matches = ctx->hook_lsig_matches; |
2213 | 2213 |
ctx->hook_lsig_matches = NULL; |
2214 | 2214 |
|
2215 |
- if(!ctx->options || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */ |
|
2215 |
+ if(!(ctx->options&~CL_SCAN_ALLMATCHES) || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */ |
|
2216 | 2216 |
if(ctx->recursion == ctx->engine->maxreclevel) |
2217 | 2217 |
cli_dbgmsg("cli_magic_scandesc: Hit recursion limit, only scanning raw file\n"); |
2218 | 2218 |
else |
... | ... |
@@ -2221,7 +2321,7 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
2221 | 2221 |
CALL_PRESCAN_CB(cb_pre_scan); |
2222 | 2222 |
/* ret_from_magicscan can be used below here*/ |
2223 | 2223 |
if((ret = cli_fmap_scandesc(ctx, 0, 0, NULL, AC_SCAN_VIR, NULL, hash)) == CL_VIRUS) |
2224 |
- cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, fmap_fd(*ctx->fmap)); |
|
2224 |
+ cli_dbgmsg("%s found in descriptor %d\n", cli_get_last_virus(ctx), fmap_fd(*ctx->fmap)); |
|
2225 | 2225 |
else if(ret == CL_CLEAN) { |
2226 | 2226 |
if(ctx->recursion != ctx->engine->maxreclevel) |
2227 | 2227 |
cache_clean = 1; /* Only cache if limits are not reached */ |
... | ... |
@@ -2564,6 +2664,8 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
2564 | 2564 |
/* CL_VIRUS = malware found, check FP and report */ |
2565 | 2565 |
case CL_VIRUS: |
2566 | 2566 |
ret = cli_checkfp(hash, hashed_size, ctx); |
2567 |
+ if (SCAN_ALL) |
|
2568 |
+ break; |
|
2567 | 2569 |
cli_bitset_free(ctx->hook_lsig_matches); |
2568 | 2570 |
ctx->hook_lsig_matches = old_hook_lsig_matches; |
2569 | 2571 |
ret_from_magicscan(ret); |
... | ... |
@@ -2596,7 +2698,7 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
2596 | 2596 |
case CL_TYPE_TEXT_UTF16LE: |
2597 | 2597 |
case CL_TYPE_TEXT_UTF8: |
2598 | 2598 |
perf_nested_start(ctx, PERFT_SCRIPT, PERFT_SCAN); |
2599 |
- if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML) |
|
2599 |
+ if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML && ret != CL_VIRUS) |
|
2600 | 2600 |
ret = cli_scanscript(ctx); |
2601 | 2601 |
if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX) && ret != CL_VIRUS && (ctx->container_type == CL_TYPE_MAIL || dettype == CL_TYPE_MAIL)) { |
2602 | 2602 |
ret = cli_fmap_scandesc(ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR, NULL, NULL); |
... | ... |
@@ -2758,6 +2860,9 @@ static int scan_common(int desc, cl_fmap_t *map, const char **virname, unsigned |
2758 | 2758 |
ctx.virname = virname; |
2759 | 2759 |
ctx.scanned = scanned; |
2760 | 2760 |
ctx.options = scanoptions; |
2761 |
+#if 0 /* for development testing only */ |
|
2762 |
+ ctx.options |= CL_SCAN_ALLMATCHES; |
|
2763 |
+#endif |
|
2761 | 2764 |
ctx.found_possibly_unwanted = 0; |
2762 | 2765 |
ctx.container_type = CL_TYPE_ANY; |
2763 | 2766 |
ctx.container_size = 0; |
... | ... |
@@ -2777,6 +2882,7 @@ static int scan_common(int desc, cl_fmap_t *map, const char **virname, unsigned |
2777 | 2777 |
char link[32]; |
2778 | 2778 |
ssize_t linksz; |
2779 | 2779 |
|
2780 |
+ |
|
2780 | 2781 |
snprintf(link, sizeof(link), "/proc/self/fd/%u", desc); |
2781 | 2782 |
link[sizeof(link)-1]='\0'; |
2782 | 2783 |
if((linksz=readlink(link, ctx.entry_filename, sizeof(ctx.entry_filename)-1))==-1) { |
... | ... |
@@ -2790,6 +2896,12 @@ static int scan_common(int desc, cl_fmap_t *map, const char **virname, unsigned |
2790 | 2790 |
cli_logg_setup(&ctx); |
2791 | 2791 |
rc = map ? cli_map_scandesc(map, 0, map->len, &ctx) : cli_magic_scandesc(desc, &ctx); |
2792 | 2792 |
|
2793 |
+ if (ctx.options & CL_SCAN_ALLMATCHES) { |
|
2794 |
+ *virname = (char *)ctx.virname; /* temp hack for scanall mode until api augmentation */ |
|
2795 |
+ if (rc == CL_CLEAN && ctx.num_viruses) |
|
2796 |
+ rc = CL_VIRUS; |
|
2797 |
+ } |
|
2798 |
+ |
|
2793 | 2799 |
cli_bitset_free(ctx.hook_lsig_matches); |
2794 | 2800 |
free(ctx.fmap); |
2795 | 2801 |
if(rc == CL_CLEAN && ctx.found_possibly_unwanted) |
... | ... |
@@ -2811,24 +2923,24 @@ int cl_scanmap_callback(cl_fmap_t *map, const char **virname, unsigned long int |
2811 | 2811 |
|
2812 | 2812 |
int cli_found_possibly_unwanted(cli_ctx* ctx) |
2813 | 2813 |
{ |
2814 |
- if(ctx->virname) { |
|
2815 |
- cli_dbgmsg("found Possibly Unwanted: %s\n",*ctx->virname); |
|
2816 |
- if(ctx->options & CL_SCAN_HEURISTIC_PRECEDENCE) { |
|
2817 |
- /* we found a heuristic match, don't scan further, |
|
2818 |
- * but consider it a virus. */ |
|
2819 |
- cli_dbgmsg("cli_found_possibly_unwanted: CL_VIRUS\n"); |
|
2820 |
- return CL_VIRUS; |
|
2821 |
- } |
|
2822 |
- /* heuristic scan isn't taking precedence, keep scanning. |
|
2823 |
- * If this is part of an archive, and |
|
2824 |
- * we find a real malware we report that instead of the |
|
2825 |
- * heuristic match */ |
|
2826 |
- ctx->found_possibly_unwanted = 1; |
|
2827 |
- } else { |
|
2828 |
- cli_warnmsg("cli_found_possibly_unwanted called, but virname is not set\n"); |
|
2814 |
+ if(cli_get_last_virus(ctx)) { |
|
2815 |
+ cli_dbgmsg("found Possibly Unwanted: %s\n", cli_get_last_virus(ctx)); |
|
2816 |
+ if(ctx->options & CL_SCAN_HEURISTIC_PRECEDENCE) { |
|
2817 |
+ /* we found a heuristic match, don't scan further, |
|
2818 |
+ * but consider it a virus. */ |
|
2819 |
+ cli_dbgmsg("cli_found_possibly_unwanted: CL_VIRUS\n"); |
|
2820 |
+ return CL_VIRUS; |
|
2829 | 2821 |
} |
2830 |
- emax_reached(ctx); |
|
2831 |
- return CL_CLEAN; |
|
2822 |
+ /* heuristic scan isn't taking precedence, keep scanning. |
|
2823 |
+ * If this is part of an archive, and |
|
2824 |
+ * we find a real malware we report that instead of the |
|
2825 |
+ * heuristic match */ |
|
2826 |
+ ctx->found_possibly_unwanted = 1; |
|
2827 |
+ } else { |
|
2828 |
+ cli_warnmsg("cli_found_possibly_unwanted called, but virname is not set\n"); |
|
2829 |
+ } |
|
2830 |
+ emax_reached(ctx); |
|
2831 |
+ return CL_CLEAN; |
|
2832 | 2832 |
} |
2833 | 2833 |
|
2834 | 2834 |
static int cli_scanfile(const char *filename, cli_ctx *ctx) |
... | ... |
@@ -253,24 +253,24 @@ static int dumpscan(fmap_t *map, unsigned int offset, unsigned int size, const c |
253 | 253 |
} else if(!memcmp(buff, "\xff\xd9\xff\xd8", 4)) { |
254 | 254 |
cli_dbgmsg("SWF: JPEG image data (erroneous header)\n"); |
255 | 255 |
if(version >= 8 && SCAN_ALGO) { |
256 |
- *ctx->virname = "Heuristics.SWF.SuspectImage.A"; |
|
256 |
+ cli_append_virus(ctx, "Heuristics.SWF.SuspectImage.A"); |
|
257 | 257 |
ret = CL_VIRUS; |
258 | 258 |
} |
259 | 259 |
} else if(!memcmp(buff, "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8)) { |
260 | 260 |
cli_dbgmsg("SWF: PNG image data\n"); |
261 | 261 |
if(version < 8 && SCAN_ALGO) { |
262 |
- *ctx->virname = "Heuristics.SWF.SuspectImage.B"; |
|
262 |
+ cli_append_virus(ctx, "Heuristics.SWF.SuspectImage.B"); |
|
263 | 263 |
ret = CL_VIRUS; |
264 | 264 |
} |
265 | 265 |
} else if(!memcmp(buff, "\x47\x49\x46\x38\x39\x61", 6)) { |
266 | 266 |
cli_dbgmsg("SWF: GIF89a image data\n"); |
267 | 267 |
if(version < 8 && SCAN_ALGO) { |
268 |
- *ctx->virname = "Heuristics.SWF.SuspectImage.C"; |
|
268 |
+ cli_append_virus(ctx, "Heuristics.SWF.SuspectImage.C"); |
|
269 | 269 |
ret = CL_VIRUS; |
270 | 270 |
} |
271 | 271 |
} else if(SCAN_ALGO) { |
272 | 272 |
cli_warnmsg("SWF: Unknown image data\n"); |
273 |
- *ctx->virname = "Heuristics.SWF.SuspectImage.D"; |
|
273 |
+ cli_append_virus(ctx, "Heuristics.SWF.SuspectImage.D"); |
|
274 | 274 |
ret = CL_VIRUS; |
275 | 275 |
} |
276 | 276 |
if(ret == CL_VIRUS) { |
... | ... |
@@ -279,7 +279,7 @@ static int dumpscan(fmap_t *map, unsigned int offset, unsigned int size, const c |
279 | 279 |
} |
280 | 280 |
ret = cli_map_scandesc(map, offset, size, ctx); |
281 | 281 |
if(ctx->img_validate && ret == CL_EPARSE && SCAN_ALGO) { |
282 |
- *ctx->virname = "Heuristics.SWF.SuspectImage.E"; |
|
282 |
+ cli_append_virus(ctx, "Heuristics.SWF.SuspectImage.E"); |
|
283 | 283 |
return CL_VIRUS; |
284 | 284 |
} |
285 | 285 |
return ret; |
... | ... |
@@ -130,6 +130,7 @@ cli_untar(const char *dir, unsigned int posix, cli_ctx *ctx) |
130 | 130 |
size_t pos = 0; |
131 | 131 |
size_t currsize = 0; |
132 | 132 |
char zero[BLOCKSIZE]; |
133 |
+ unsigned int num_viruses = 0; |
|
133 | 134 |
|
134 | 135 |
cli_dbgmsg("In untar(%s)\n", dir); |
135 | 136 |
memset(zero, 0, sizeof(zero)); |
... | ... |
@@ -168,8 +169,12 @@ cli_untar(const char *dir, unsigned int posix, cli_ctx *ctx) |
168 | 168 |
close(fout); |
169 | 169 |
if (!ctx->engine->keeptmp) |
170 | 170 |
if (cli_unlink(fullname)) return CL_EUNLINK; |
171 |
- if (ret==CL_VIRUS) |
|
171 |
+ if (ret==CL_VIRUS) { |
|
172 |
+ if (!SCAN_ALL) |
|
172 | 173 |
return CL_VIRUS; |
174 |
+ else |
|
175 |
+ num_viruses++; |
|
176 |
+ } |
|
173 | 177 |
fout = -1; |
174 | 178 |
} |
175 | 179 |
|
... | ... |
@@ -285,8 +290,12 @@ cli_untar(const char *dir, unsigned int posix, cli_ctx *ctx) |
285 | 285 |
|
286 | 286 |
strncpy(name, block, 100); |
287 | 287 |
name[100] = '\0'; |
288 |
- if(cli_matchmeta(ctx, name, size, size, 0, files, 0, NULL) == CL_VIRUS) |
|
289 |
- return CL_VIRUS; |
|
288 |
+ if(cli_matchmeta(ctx, name, size, size, 0, files, 0, NULL) == CL_VIRUS) { |
|
289 |
+ if (!SCAN_ALL) |
|
290 |
+ return CL_VIRUS; |
|
291 |
+ else |
|
292 |
+ num_viruses++; |
|
293 |
+ } |
|
290 | 294 |
|
291 | 295 |
snprintf(fullname, sizeof(fullname)-1, "%s"PATHSEP"tar%02u", dir, files); |
292 | 296 |
fullname[sizeof(fullname)-1] = '\0'; |
... | ... |
@@ -349,5 +358,7 @@ cli_untar(const char *dir, unsigned int posix, cli_ctx *ctx) |
349 | 349 |
if (ret==CL_VIRUS) |
350 | 350 |
return CL_VIRUS; |
351 | 351 |
} |
352 |
+ if (num_viruses) |
|
353 |
+ return CL_VIRUS; |
|
352 | 354 |
return CL_CLEAN; |
353 | 355 |
} |
... | ... |
@@ -350,7 +350,7 @@ static unsigned int lhdr(fmap_t *map, uint32_t loff,uint32_t zsize, unsigned int |
350 | 350 |
|
351 | 351 |
if(detect_encrypted && (LH_flags & F_ENCR) && DETECT_ENCRYPTED) { |
352 | 352 |
cli_dbgmsg("cli_unzip: Encrypted files found in archive.\n"); |
353 |
- *ctx->virname = "Heuristics.Encrypted.Zip"; |
|
353 |
+ cli_append_virus(ctx, "Heuristics.Encrypted.Zip"); |
|
354 | 354 |
*ret = CL_VIRUS; |
355 | 355 |
fmap_unneed_off(map, loff, SIZEOF_LH); |
356 | 356 |
return 0; |
... | ... |
@@ -81,6 +81,7 @@ const struct clam_option __clam_options[] = { |
81 | 81 |
{ NULL, "multiscan", 'm', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN, "", "" }, |
82 | 82 |
{ NULL, "fdpass", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN, "", "" }, |
83 | 83 |
{ NULL, "stream", 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDSCAN, "", "" }, |
84 |
+ { NULL, "allmatch", 'z', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN | OPT_CLAMDSCAN, "", "" }, |
|
84 | 85 |
{ NULL, "database", 'd', TYPE_STRING, NULL, -1, DATADIR, FLAG_REQUIRED | FLAG_MULTIPLE, OPT_CLAMSCAN, "", "" }, /* merge it with DatabaseDirectory (and fix conflict with --datadir */ |
85 | 86 |
{ NULL, "recursive", 'r', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMSCAN, "", "" }, |
86 | 87 |
{ NULL, "follow-dir-symlinks", 0, TYPE_NUMBER, MATCH_NUMBER, 1, NULL, 0, OPT_CLAMSCAN, "", "" }, |
... | ... |
@@ -59,8 +59,11 @@ static void runtest(const char *file, uint64_t expected, int fail, int nojit, |
59 | 59 |
struct cl_engine *engine; |
60 | 60 |
int fdin = -1; |
61 | 61 |
char filestr[512]; |
62 |
+ char * virname = NULL; |
|
62 | 63 |
|
63 | 64 |
memset(&cctx, 0, sizeof(cctx)); |
65 |
+ cctx.options |= CL_SCAN_ALLMATCHES; |
|
66 |
+ cctx.virname = &virname; |
|
64 | 67 |
cctx.engine = engine = cl_engine_new(); |
65 | 68 |
fail_unless(!!cctx.engine, "cannot create engine"); |
66 | 69 |
rc = cl_engine_compile(engine); |
... | ... |
@@ -170,7 +170,29 @@ START_TEST (test_cl_scandesc) |
170 | 170 |
} |
171 | 171 |
END_TEST |
172 | 172 |
|
173 |
-/* int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options) */ |
|
173 |
+START_TEST (test_cl_scandesc_allscan) |
|
174 |
+{ |
|
175 |
+ const char *virname = NULL; |
|
176 |
+ const char ** virpp = &virname; |
|
177 |
+ char file[256]; |
|
178 |
+ unsigned long size; |
|
179 |
+ unsigned long int scanned = 0; |
|
180 |
+ int ret; |
|
181 |
+ |
|
182 |
+ int fd = get_test_file(_i, file, sizeof(file), &size); |
|
183 |
+ cli_dbgmsg("scanning (scandesc) %s\n", file); |
|
184 |
+ ret = cl_scandesc(fd, virpp, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT); |
|
185 |
+ virpp = (const char **)*virpp; /* allscan api hack */ |
|
186 |
+ cli_dbgmsg("scan end (scandesc) %s\n", file); |
|
187 |
+ |
|
188 |
+ fail_unless_fmt(ret == CL_VIRUS, "cl_scandesc_allscan failed for %s: %s", file, cl_strerror(ret)); |
|
189 |
+ fail_unless_fmt(*virpp && !strcmp(*virpp, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", *virpp); |
|
190 |
+ free((void *)virpp); |
|
191 |
+ close(fd); |
|
192 |
+} |
|
193 |
+END_TEST |
|
194 |
+ |
|
195 |
+//* int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options) */ |
|
174 | 196 |
START_TEST (test_cl_scanfile) |
175 | 197 |
{ |
176 | 198 |
const char *virname = NULL; |
... | ... |
@@ -191,6 +213,29 @@ START_TEST (test_cl_scanfile) |
191 | 191 |
} |
192 | 192 |
END_TEST |
193 | 193 |
|
194 |
+START_TEST (test_cl_scanfile_allscan) |
|
195 |
+{ |
|
196 |
+ const char *virname = NULL; |
|
197 |
+ const char **virpp = &virname; |
|
198 |
+ char file[256]; |
|
199 |
+ unsigned long size; |
|
200 |
+ unsigned long int scanned = 0; |
|
201 |
+ int ret; |
|
202 |
+ |
|
203 |
+ int fd = get_test_file(_i, file, sizeof(file), &size); |
|
204 |
+ close(fd); |
|
205 |
+ |
|
206 |
+ cli_dbgmsg("scanning (scanfile_allscan) %s\n", file); |
|
207 |
+ ret = cl_scanfile(file, virpp, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT); |
|
208 |
+ virpp = (const char **)*virpp; /* allscan api hack */ |
|
209 |
+ cli_dbgmsg("scan end (scanfile_allscan) %s\n", file); |
|
210 |
+ |
|
211 |
+ fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile_allscan failed for %s: %s", file, cl_strerror(ret)); |
|
212 |
+ fail_unless_fmt(*virpp && !strcmp(*virpp, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", *virpp); |
|
213 |
+ free((void *)virpp); |
|
214 |
+} |
|
215 |
+END_TEST |
|
216 |
+ |
|
194 | 217 |
START_TEST (test_cl_scanfile_callback) |
195 | 218 |
{ |
196 | 219 |
const char *virname = NULL; |
... | ... |
@@ -207,11 +252,35 @@ START_TEST (test_cl_scanfile_callback) |
207 | 207 |
ret = cl_scanfile_callback(file, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL); |
208 | 208 |
cli_dbgmsg("scan end (scanfile_cb) %s\n", file); |
209 | 209 |
|
210 |
- fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile failed for %s: %s", file, cl_strerror(ret)); |
|
210 |
+ fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile_cb failed for %s: %s", file, cl_strerror(ret)); |
|
211 | 211 |
fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname); |
212 | 212 |
} |
213 | 213 |
END_TEST |
214 | 214 |
|
215 |
+START_TEST (test_cl_scanfile_callback_allscan) |
|
216 |
+{ |
|
217 |
+ const char *virname = NULL; |
|
218 |
+ const char **virpp = &virname; |
|
219 |
+ char file[256]; |
|
220 |
+ unsigned long size; |
|
221 |
+ unsigned long int scanned = 0; |
|
222 |
+ int ret; |
|
223 |
+ |
|
224 |
+ int fd = get_test_file(_i, file, sizeof(file), &size); |
|
225 |
+ close(fd); |
|
226 |
+ |
|
227 |
+ cli_dbgmsg("scanning (scanfile_cb_allscan) %s\n", file); |
|
228 |
+ /* TODO: test callbacks */ |
|
229 |
+ ret = cl_scanfile_callback(file, virpp, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL); |
|
230 |
+ virpp = (const char **)*virpp; /* allscan api hack */ |
|
231 |
+ cli_dbgmsg("scan end (scanfile_cb_allscan) %s\n", file); |
|
232 |
+ |
|
233 |
+ fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile_cb_allscan failed for %s: %s", file, cl_strerror(ret)); |
|
234 |
+ fail_unless_fmt(*virpp && !strcmp(*virpp, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", *virpp); |
|
235 |
+ free((void *)virpp); |
|
236 |
+} |
|
237 |
+END_TEST |
|
238 |
+ |
|
215 | 239 |
START_TEST (test_cl_scandesc_callback) |
216 | 240 |
{ |
217 | 241 |
const char *virname = NULL; |
... | ... |
@@ -232,6 +301,31 @@ START_TEST (test_cl_scandesc_callback) |
232 | 232 |
close(fd); |
233 | 233 |
} |
234 | 234 |
END_TEST |
235 |
+ |
|
236 |
+START_TEST (test_cl_scandesc_callback_allscan) |
|
237 |
+{ |
|
238 |
+ const char *virname = NULL; |
|
239 |
+ const char **virpp = &virname; |
|
240 |
+ char file[256]; |
|
241 |
+ unsigned long size; |
|
242 |
+ unsigned long int scanned = 0; |
|
243 |
+ int ret; |
|
244 |
+ |
|
245 |
+ int fd = get_test_file(_i, file, sizeof(file), &size); |
|
246 |
+ |
|
247 |
+ cli_dbgmsg("scanning (scandesc_cb_allscan) %s\n", file); |
|
248 |
+ /* TODO: test callbacks */ |
|
249 |
+ ret = cl_scandesc_callback(fd, virpp, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL); |
|
250 |
+ virpp = (const char **)*virpp; /* allscan api hack */ |
|
251 |
+ cli_dbgmsg("scan end (scandesc_cb_allscan) %s\n", file); |
|
252 |
+ |
|
253 |
+ fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile_allscan failed for %s: %s", file, cl_strerror(ret)); |
|
254 |
+ fail_unless_fmt(*virpp && !strcmp(*virpp, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", *virpp); |
|
255 |
+ free((void *)virpp); |
|
256 |
+ close(fd); |
|
257 |
+} |
|
258 |
+END_TEST |
|
259 |
+ |
|
235 | 260 |
#endif |
236 | 261 |
|
237 | 262 |
/* int cl_load(const char *path, struct cl_engine **engine, unsigned int *signo, unsigned int options) */ |
... | ... |
@@ -367,6 +461,33 @@ START_TEST (test_cl_scanmap_callback_handle) |
367 | 367 |
} |
368 | 368 |
END_TEST |
369 | 369 |
|
370 |
+START_TEST (test_cl_scanmap_callback_handle_allscan) |
|
371 |
+{ |
|
372 |
+ const char *virname = NULL; |
|
373 |
+ const char ** virpp = &virname; |
|
374 |
+ unsigned long int scanned = 0; |
|
375 |
+ cl_fmap_t *map; |
|
376 |
+ int ret; |
|
377 |
+ char file[256]; |
|
378 |
+ unsigned long size; |
|
379 |
+ |
|
380 |
+ int fd = get_test_file(_i, file, sizeof(file), &size); |
|
381 |
+ /* intentionally use different way than scanners.c for testing */ |
|
382 |
+ map = cl_fmap_open_handle(&fd, 0, size, pread_cb, 1); |
|
383 |
+ fail_unless(!!map, "cl_fmap_open_handle"); |
|
384 |
+ |
|
385 |
+ cli_dbgmsg("scanning (handle) allscan %s\n", file); |
|
386 |
+ ret = cl_scanmap_callback(map, virpp, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL); |
|
387 |
+ virpp = (const char **)*virpp; /* allscan api hack */ |
|
388 |
+ cli_dbgmsg("scan end (handle) allscan %s\n", file); |
|
389 |
+ |
|
390 |
+ fail_unless_fmt(ret == CL_VIRUS, "cl_scanmap_callback_allscan failed for %s: %s", file, cl_strerror(ret)); |
|
391 |
+ fail_unless_fmt(*virpp && !strcmp(*virpp, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", *virpp); |
|
392 |
+ free((void *)virpp); |
|
393 |
+ close(fd); |
|
394 |
+} |
|
395 |
+END_TEST |
|
396 |
+ |
|
370 | 397 |
START_TEST (test_cl_scanmap_callback_mem) |
371 | 398 |
{ |
372 | 399 |
const char *virname = NULL; |
... | ... |
@@ -397,6 +518,39 @@ START_TEST (test_cl_scanmap_callback_mem) |
397 | 397 |
munmap(mem, size); |
398 | 398 |
} |
399 | 399 |
END_TEST |
400 |
+ |
|
401 |
+START_TEST (test_cl_scanmap_callback_mem_allscan) |
|
402 |
+{ |
|
403 |
+ const char *virname = NULL; |
|
404 |
+ const char **virpp = &virname; |
|
405 |
+ unsigned long int scanned = 0; |
|
406 |
+ cl_fmap_t *map; |
|
407 |
+ int ret; |
|
408 |
+ void *mem; |
|
409 |
+ unsigned long size; |
|
410 |
+ char file[256]; |
|
411 |
+ |
|
412 |
+ int fd = get_test_file(_i, file, sizeof(file), &size); |
|
413 |
+ |
|
414 |
+ mem = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); |
|
415 |
+ fail_unless(mem != MAP_FAILED, "mmap"); |
|
416 |
+ |
|
417 |
+ /* intentionally use different way than scanners.c for testing */ |
|
418 |
+ map = cl_fmap_open_memory(mem, size); |
|
419 |
+ fail_unless(!!map, "cl_fmap_open_mem"); |
|
420 |
+ |
|
421 |
+ cli_dbgmsg("scanning (mem) allscan %s\n", file); |
|
422 |
+ ret = cl_scanmap_callback(map, virpp, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL); |
|
423 |
+ virpp = (const char **)*virpp; /* allscan api hack */ |
|
424 |
+ cli_dbgmsg("scan end (mem) allscan %s\n", file); |
|
425 |
+ fail_unless_fmt(ret == CL_VIRUS, "cl_scanmap_callback failed for %s: %s", file, cl_strerror(ret)); |
|
426 |
+ fail_unless_fmt(*virpp && !strcmp(*virpp, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s for %s", *virpp, file); |
|
427 |
+ close(fd); |
|
428 |
+ cl_fmap_close(map); |
|
429 |
+ free((void *)virpp); |
|
430 |
+ munmap(mem, size); |
|
431 |
+} |
|
432 |
+END_TEST |
|
400 | 433 |
#endif |
401 | 434 |
|
402 | 435 |
static Suite *test_cl_suite(void) |
... | ... |
@@ -427,11 +581,17 @@ static Suite *test_cl_suite(void) |
427 | 427 |
tcase_add_checked_fixture (tc_cl_scan, engine_setup, engine_teardown); |
428 | 428 |
#ifdef CHECK_HAVE_LOOPS |
429 | 429 |
tcase_add_loop_test(tc_cl_scan, test_cl_scandesc, 0, expected_testfiles); |
430 |
+ tcase_add_loop_test(tc_cl_scan, test_cl_scandesc_allscan, 0, expected_testfiles); |
|
430 | 431 |
tcase_add_loop_test(tc_cl_scan, test_cl_scanfile, 0, expected_testfiles); |
432 |
+ tcase_add_loop_test(tc_cl_scan, test_cl_scanfile_allscan, 0, expected_testfiles); |
|
431 | 433 |
tcase_add_loop_test(tc_cl_scan, test_cl_scandesc_callback, 0, expected_testfiles); |
434 |
+ tcase_add_loop_test(tc_cl_scan, test_cl_scandesc_callback_allscan, 0, expected_testfiles); |
|
432 | 435 |
tcase_add_loop_test(tc_cl_scan, test_cl_scanfile_callback, 0, expected_testfiles); |
436 |
+ tcase_add_loop_test(tc_cl_scan, test_cl_scanfile_callback_allscan, 0, expected_testfiles); |
|
433 | 437 |
tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_handle, 0, expected_testfiles); |
438 |
+ tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_handle_allscan, 0, expected_testfiles); |
|
434 | 439 |
tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_mem, 0, expected_testfiles); |
440 |
+ tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_mem_allscan, 0, expected_testfiles); |
|
435 | 441 |
#endif |
436 | 442 |
return s; |
437 | 443 |
} |
... | ... |
@@ -145,7 +145,83 @@ START_TEST (test_bm_scanbuff) { |
145 | 145 |
ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, "*", 0, NULL, 0); |
146 | 146 |
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); |
147 | 147 |
|
148 |
- ret = cli_bm_scanbuff((const unsigned char*)"blah\xde\xad\xbe\xef", 12, &virname, NULL, root, 0, NULL, NULL); |
|
148 |
+ ret = cli_bm_scanbuff((const unsigned char*)"blah\xde\xad\xbe\xef", 12, &virname, NULL, root, 0, NULL, NULL, NULL); |
|
149 |
+ fail_unless(ret == CL_VIRUS, "cli_bm_scanbuff() failed"); |
|
150 |
+ fail_unless(!strncmp(virname, "Sig2", 4), "Incorrect signature matched in cli_bm_scanbuff()\n"); |
|
151 |
+} |
|
152 |
+END_TEST |
|
153 |
+ |
|
154 |
+START_TEST (test_ac_scanbuff_allscan) { |
|
155 |
+ struct cli_ac_data mdata; |
|
156 |
+ struct cli_matcher *root; |
|
157 |
+ unsigned int i; |
|
158 |
+ int ret; |
|
159 |
+ |
|
160 |
+ root = ctx.engine->root[0]; |
|
161 |
+ fail_unless(root != NULL, "root == NULL"); |
|
162 |
+ root->ac_only = 1; |
|
163 |
+ |
|
164 |
+#ifdef USE_MPOOL |
|
165 |
+ root->mempool = mpool_create(); |
|
166 |
+#endif |
|
167 |
+ ret = cli_ac_init(root, CLI_DEFAULT_AC_MINDEPTH, CLI_DEFAULT_AC_MAXDEPTH, 1); |
|
168 |
+ fail_unless(ret == CL_SUCCESS, "cli_ac_init() failed"); |
|
169 |
+ |
|
170 |
+ |
|
171 |
+ for(i = 0; ac_testdata[i].data; i++) { |
|
172 |
+ ret = cli_parse_add(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, "*", 0, NULL, 0); |
|
173 |
+ fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); |
|
174 |
+ } |
|
175 |
+ |
|
176 |
+ ret = cli_ac_buildtrie(root); |
|
177 |
+ fail_unless(ret == CL_SUCCESS, "cli_ac_buildtrie() failed"); |
|
178 |
+ |
|
179 |
+ ret = cli_ac_initdata(&mdata, root->ac_partsigs, 0, 0, CLI_DEFAULT_AC_TRACKLEN); |
|
180 |
+ fail_unless(ret == CL_SUCCESS, "cli_ac_initdata() failed"); |
|
181 |
+ |
|
182 |
+ ctx.options |= CL_SCAN_ALLMATCHES; |
|
183 |
+ for(i = 0; ac_testdata[i].data; i++) { |
|
184 |
+ ret = cli_ac_scanbuff((const unsigned char*)ac_testdata[i].data, strlen(ac_testdata[i].data), &virname, NULL, NULL, root, &mdata, 0, 0, NULL, AC_SCAN_VIR, NULL); |
|
185 |
+ fail_unless_fmt(ret == CL_VIRUS, "cli_ac_scanbuff() failed for %s", ac_testdata[i].virname); |
|
186 |
+ fail_unless_fmt(!strncmp(virname, ac_testdata[i].virname, strlen(ac_testdata[i].virname)), "Dataset %u matched with %s", i, virname); |
|
187 |
+ |
|
188 |
+ ret = cli_scanbuff((const unsigned char*)ac_testdata[i].data, strlen(ac_testdata[i].data), 0, &ctx, 0, NULL); |
|
189 |
+ fail_unless_fmt(ret == CL_VIRUS, "cli_scanbuff() failed for %s", ac_testdata[i].virname); |
|
190 |
+ fail_unless_fmt(!strncmp(virname, ac_testdata[i].virname, strlen(ac_testdata[i].virname)), "Dataset %u matched with %s", i, virname); |
|
191 |
+ if (ctx.num_viruses) { |
|
192 |
+ free((void *)ctx.virname); |
|
193 |
+ ctx.num_viruses = 0; |
|
194 |
+ ctx.size_viruses = 0; |
|
195 |
+ } |
|
196 |
+ } |
|
197 |
+ |
|
198 |
+ cli_ac_freedata(&mdata); |
|
199 |
+} |
|
200 |
+END_TEST |
|
201 |
+ |
|
202 |
+START_TEST (test_bm_scanbuff_allscan) { |
|
203 |
+ struct cli_matcher *root; |
|
204 |
+ const char *virname = NULL; |
|
205 |
+ int ret; |
|
206 |
+ |
|
207 |
+ |
|
208 |
+ root = ctx.engine->root[0]; |
|
209 |
+ fail_unless(root != NULL, "root == NULL"); |
|
210 |
+ |
|
211 |
+#ifdef USE_MPOOL |
|
212 |
+ root->mempool = mpool_create(); |
|
213 |
+#endif |
|
214 |
+ ret = cli_bm_init(root); |
|
215 |
+ fail_unless(ret == CL_SUCCESS, "cli_bm_init() failed"); |
|
216 |
+ |
|
217 |
+ ret = cli_parse_add(root, "Sig1", "deadbabe", 0, 0, "*", 0, NULL, 0); |
|
218 |
+ fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); |
|
219 |
+ ret = cli_parse_add(root, "Sig2", "deadbeef", 0, 0, "*", 0, NULL, 0); |
|
220 |
+ fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); |
|
221 |
+ ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, "*", 0, NULL, 0); |
|
222 |
+ fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed"); |
|
223 |
+ |
|
224 |
+ ret = cli_bm_scanbuff((const unsigned char*)"blah\xde\xad\xbe\xef", 12, &virname, NULL, root, 0, NULL, NULL, NULL); |
|
149 | 225 |
fail_unless(ret == CL_VIRUS, "cli_bm_scanbuff() failed"); |
150 | 226 |
fail_unless(!strncmp(virname, "Sig2", 4), "Incorrect signature matched in cli_bm_scanbuff()\n"); |
151 | 227 |
} |
... | ... |
@@ -160,6 +236,8 @@ Suite *test_matchers_suite(void) |
160 | 160 |
tcase_add_checked_fixture (tc_matchers, setup, teardown); |
161 | 161 |
tcase_add_test(tc_matchers, test_ac_scanbuff); |
162 | 162 |
tcase_add_test(tc_matchers, test_bm_scanbuff); |
163 |
+ tcase_add_test(tc_matchers, test_ac_scanbuff_allscan); |
|
164 |
+ tcase_add_test(tc_matchers, test_bm_scanbuff_allscan); |
|
163 | 165 |
return s; |
164 | 166 |
} |
165 | 167 |
|
... | ... |
@@ -425,12 +425,85 @@ static void do_phishing_test(const struct rtest *rtest) |
425 | 425 |
} |
426 | 426 |
} |
427 | 427 |
|
428 |
+static void do_phishing_test_allscan(const struct rtest *rtest) |
|
429 |
+{ |
|
430 |
+ char *realurl; |
|
431 |
+ cli_ctx ctx; |
|
432 |
+ const char *virname = NULL; |
|
433 |
+ tag_arguments_t hrefs; |
|
434 |
+ int rc; |
|
435 |
+ |
|
436 |
+ memset(&ctx, 0, sizeof(ctx)); |
|
437 |
+ |
|
438 |
+ realurl = cli_strdup(rtest->realurl); |
|
439 |
+ fail_unless(!!realurl, "cli_strdup"); |
|
440 |
+ |
|
441 |
+ hrefs.count = 1; |
|
442 |
+ hrefs.value = cli_malloc(sizeof(*hrefs.value)); |
|
443 |
+ fail_unless(!!hrefs.value, "cli_malloc"); |
|
444 |
+ hrefs.value[0] = (unsigned char*)realurl; |
|
445 |
+ hrefs.contents = cli_malloc(sizeof(*hrefs.contents)); |
|
446 |
+ fail_unless(!!hrefs.contents, "cli_malloc"); |
|
447 |
+ hrefs.tag = cli_malloc(sizeof(*hrefs.tag)); |
|
448 |
+ fail_unless(!!hrefs.tag, "cli_malloc"); |
|
449 |
+ hrefs.tag[0] = (unsigned char*)cli_strdup("href"); |
|
450 |
+ hrefs.contents[0] = (unsigned char*)cli_strdup(rtest->displayurl); |
|
451 |
+ |
|
452 |
+ ctx.engine = engine; |
|
453 |
+ ctx.virname = &virname; |
|
454 |
+ ctx.options |= CL_SCAN_ALLMATCHES; |
|
455 |
+ |
|
456 |
+ rc = phishingScan(&ctx, &hrefs); |
|
457 |
+ |
|
458 |
+ html_tag_arg_free(&hrefs); |
|
459 |
+ fail_unless(rc == CL_CLEAN,"phishingScan"); |
|
460 |
+ switch(rtest->result) { |
|
461 |
+ case 0: |
|
462 |
+ fail_unless_fmt(ctx.found_possibly_unwanted, |
|
463 |
+ "this should be phishing, realURL: %s, displayURL: %s", |
|
464 |
+ rtest->realurl, rtest->displayurl); |
|
465 |
+ break; |
|
466 |
+ case 1: |
|
467 |
+ fail_unless_fmt(!ctx.found_possibly_unwanted, |
|
468 |
+ "this should be whitelisted, realURL: %s, displayURL: %s", |
|
469 |
+ rtest->realurl, rtest->displayurl); |
|
470 |
+ break; |
|
471 |
+ case 2: |
|
472 |
+ fail_unless_fmt(!ctx.found_possibly_unwanted, |
|
473 |
+ "this should be clean, realURL: %s, displayURL: %s", |
|
474 |
+ rtest->realurl, rtest->displayurl); |
|
475 |
+ break; |
|
476 |
+ case 3: |
|
477 |
+ if(!loaded_2) |
|
478 |
+ fail_unless_fmt(!ctx.found_possibly_unwanted, |
|
479 |
+ "this should be clean, realURL: %s, displayURL: %s", |
|
480 |
+ rtest->realurl, rtest->displayurl); |
|
481 |
+ else { |
|
482 |
+ fail_unless_fmt(ctx.found_possibly_unwanted, |
|
483 |
+ "this should be blacklisted, realURL: %s, displayURL: %s", |
|
484 |
+ rtest->realurl, rtest->displayurl); |
|
485 |
+ if (*ctx.virname) |
|
486 |
+ fail_unless_fmt(!strstr((const char*)*ctx.virname,"Blacklisted"), |
|
487 |
+ "should be blacklisted, but is: %s\n", ctx.virname); |
|
488 |
+ } |
|
489 |
+ break; |
|
490 |
+ } |
|
491 |
+ if (ctx.num_viruses) |
|
492 |
+ free((void *)ctx.virname); |
|
493 |
+} |
|
494 |
+ |
|
428 | 495 |
#ifdef CHECK_HAVE_LOOPS |
429 | 496 |
START_TEST (phishingScan_test) |
430 | 497 |
{ |
431 | 498 |
do_phishing_test(&rtests[_i]); |
432 | 499 |
} |
433 | 500 |
END_TEST |
501 |
+ |
|
502 |
+START_TEST (phishingScan_test_allscan) |
|
503 |
+{ |
|
504 |
+ do_phishing_test_allscan(&rtests[_i]); |
|
505 |
+} |
|
506 |
+END_TEST |
|
434 | 507 |
#endif |
435 | 508 |
|
436 | 509 |
#ifdef CHECK_HAVE_LOOPS |
... | ... |
@@ -515,6 +588,27 @@ START_TEST(phishing_fake_test) |
515 | 515 |
} |
516 | 516 |
END_TEST |
517 | 517 |
|
518 |
+START_TEST(phishing_fake_test_allscan) |
|
519 |
+{ |
|
520 |
+ char buf[4096]; |
|
521 |
+ FILE *f = fdopen(open_testfile("input/daily.pdb"),"r"); |
|
522 |
+ fail_unless(!!f,"fopen daily.pdb"); |
|
523 |
+ while(fgets(buf, sizeof(buf), f)) { |
|
524 |
+ struct rtest rtest; |
|
525 |
+ const char *pdb = strchr(buf,':'); |
|
526 |
+ fail_unless(!!pdb, "missing : in pdb"); |
|
527 |
+ rtest.realurl = pdb; |
|
528 |
+ rtest.displayurl = pdb; |
|
529 |
+ rtest.result = 2; |
|
530 |
+ do_phishing_test_allscan(&rtest); |
|
531 |
+ rtest.realurl = "http://fake.example.com"; |
|
532 |
+ rtest.result = 0; |
|
533 |
+ do_phishing_test_allscan(&rtest); |
|
534 |
+ } |
|
535 |
+ fclose(f); |
|
536 |
+} |
|
537 |
+END_TEST |
|
538 |
+ |
|
518 | 539 |
Suite *test_regex_suite(void) |
519 | 540 |
{ |
520 | 541 |
Suite *s = suite_create("regex"); |
... | ... |
@@ -539,16 +633,20 @@ Suite *test_regex_suite(void) |
539 | 539 |
tcase_add_unchecked_fixture(tc_phish, psetup, pteardown); |
540 | 540 |
#ifdef CHECK_HAVE_LOOPS |
541 | 541 |
tcase_add_loop_test(tc_phish, phishingScan_test, 0, sizeof(rtests)/sizeof(rtests[0])); |
542 |
+ tcase_add_loop_test(tc_phish, phishingScan_test_allscan, 0, sizeof(rtests)/sizeof(rtests[0])); |
|
542 | 543 |
#endif |
543 | 544 |
tcase_add_test(tc_phish, phishing_fake_test); |
545 |
+ tcase_add_test(tc_phish, phishing_fake_test_allscan); |
|
544 | 546 |
|
545 | 547 |
tc_phish2 = tcase_create("phishingScan with 2 dbs"); |
546 | 548 |
suite_add_tcase(s, tc_phish2); |
547 | 549 |
tcase_add_unchecked_fixture(tc_phish2, psetup2, pteardown); |
548 | 550 |
#ifdef CHECK_HAVE_LOOPS |
549 | 551 |
tcase_add_loop_test(tc_phish2, phishingScan_test, 0, sizeof(rtests)/sizeof(rtests[0])); |
552 |
+ tcase_add_loop_test(tc_phish2, phishingScan_test_allscan, 0, sizeof(rtests)/sizeof(rtests[0])); |
|
550 | 553 |
#endif |
551 | 554 |
tcase_add_test(tc_phish2, phishing_fake_test); |
555 |
+ tcase_add_test(tc_phish2, phishing_fake_test_allscan); |
|
552 | 556 |
#ifdef CHECK_HAVE_LOOPS |
553 | 557 |
tcase_add_loop_test(tc_phish, test_url_canon, 0, sizeof(uc)/sizeof(uc[0])); |
554 | 558 |
#endif |