mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 18:33:16 +00:00
scan meta-data in RAR files
git-svn: trunk@1400
This commit is contained in:
parent
e77215736b
commit
a62ae54fc1
6 changed files with 107 additions and 37 deletions
|
@ -1,3 +1,7 @@
|
|||
Fri Mar 18 02:24:05 CET 2005 (tk)
|
||||
---------------------------------
|
||||
* libclamav: scan meta-data in RAR files
|
||||
|
||||
Wed Mar 16 21:55:44 CET 2005 (tk)
|
||||
---------------------------------
|
||||
* libclamav/pe.c: fix section handling in petite block
|
||||
|
|
|
@ -121,10 +121,10 @@ struct cli_md5_node {
|
|||
struct cli_md5_node *next;
|
||||
};
|
||||
|
||||
struct cli_zip_node {
|
||||
int compr, csize, size, encrypted, crc32, fileno, maxdepth;
|
||||
struct cli_meta_node {
|
||||
int method, csize, size, encrypted, crc32, fileno, maxdepth;
|
||||
char *filename, *virname;
|
||||
struct cli_zip_node *next;
|
||||
struct cli_meta_node *next;
|
||||
};
|
||||
|
||||
struct cl_node {
|
||||
|
@ -143,7 +143,11 @@ struct cl_node {
|
|||
struct cli_md5_node **md5_hlist;
|
||||
|
||||
/* Zip metadata */
|
||||
struct cli_zip_node *zip_mlist;
|
||||
struct cli_meta_node *zip_mlist;
|
||||
|
||||
/* RAR metadata */
|
||||
struct cli_meta_node *rar_mlist;
|
||||
|
||||
};
|
||||
|
||||
struct cl_limits {
|
||||
|
|
|
@ -390,7 +390,7 @@ void cl_free(struct cl_node *root)
|
|||
{
|
||||
int i;
|
||||
struct cli_md5_node *md5pt, *md5h;
|
||||
struct cli_zip_node *zippt, *ziph;
|
||||
struct cli_meta_node *metapt, *metah;
|
||||
|
||||
if(!root) {
|
||||
cli_errmsg("cl_free: root == NULL\n");
|
||||
|
@ -432,14 +432,24 @@ void cl_free(struct cl_node *root)
|
|||
free(root->md5_hlist);
|
||||
}
|
||||
|
||||
zippt = root->zip_mlist;
|
||||
while(zippt) {
|
||||
ziph = zippt;
|
||||
zippt = zippt->next;
|
||||
free(ziph->virname);
|
||||
if(ziph->filename)
|
||||
free(ziph->filename);
|
||||
free(ziph);
|
||||
metapt = root->zip_mlist;
|
||||
while(metapt) {
|
||||
metah = metapt;
|
||||
metapt = metapt->next;
|
||||
free(metah->virname);
|
||||
if(metah->filename)
|
||||
free(metah->filename);
|
||||
free(metah);
|
||||
}
|
||||
|
||||
metapt = root->rar_mlist;
|
||||
while(metapt) {
|
||||
metah = metapt;
|
||||
metapt = metapt->next;
|
||||
free(metah->virname);
|
||||
if(metah->filename)
|
||||
free(metah->filename);
|
||||
free(metah);
|
||||
}
|
||||
|
||||
free(root);
|
||||
|
|
|
@ -705,11 +705,11 @@ static int cli_loadhdb(FILE *fd, struct cl_node **root, unsigned int *signo, uns
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cli_loadzmd(FILE *fd, struct cl_node **root, unsigned int *signo)
|
||||
static int cli_loadmd(FILE *fd, struct cl_node **root, unsigned int *signo, int type)
|
||||
{
|
||||
char buffer[FILEBUFF], *pt;
|
||||
int line = 0, comments = 0, ret = 0;
|
||||
struct cli_zip_node *new;
|
||||
struct cli_meta_node *new;
|
||||
|
||||
|
||||
if(!*root) {
|
||||
|
@ -728,7 +728,7 @@ static int cli_loadzmd(FILE *fd, struct cl_node **root, unsigned int *signo)
|
|||
|
||||
cli_chomp(buffer);
|
||||
|
||||
new = (struct cli_zip_node *) cli_calloc(1, sizeof(struct cli_zip_node));
|
||||
new = (struct cli_meta_node *) cli_calloc(1, sizeof(struct cli_meta_node));
|
||||
if(!new) {
|
||||
ret = CL_EMEM;
|
||||
break;
|
||||
|
@ -817,9 +817,9 @@ static int cli_loadzmd(FILE *fd, struct cl_node **root, unsigned int *signo)
|
|||
break;
|
||||
} else {
|
||||
if(!strcmp(pt, "*"))
|
||||
new->compr = -1;
|
||||
new->method = -1;
|
||||
else
|
||||
new->compr = atoi(pt);
|
||||
new->method = atoi(pt);
|
||||
free(pt);
|
||||
}
|
||||
|
||||
|
@ -851,8 +851,13 @@ static int cli_loadzmd(FILE *fd, struct cl_node **root, unsigned int *signo)
|
|||
free(pt);
|
||||
}
|
||||
|
||||
new->next = (*root)->zip_mlist;
|
||||
(*root)->zip_mlist = new;
|
||||
if(type == 1) {
|
||||
new->next = (*root)->zip_mlist;
|
||||
(*root)->zip_mlist = new;
|
||||
} else {
|
||||
new->next = (*root)->rar_mlist;
|
||||
(*root)->rar_mlist = new;
|
||||
}
|
||||
}
|
||||
|
||||
if(!line) {
|
||||
|
@ -907,7 +912,10 @@ int cl_loaddb(const char *filename, struct cl_node **root, unsigned int *signo)
|
|||
ret = cli_loadndb(fd, root, signo);
|
||||
|
||||
} else if(cli_strbcasestr(filename, ".zmd")) {
|
||||
ret = cli_loadzmd(fd, root, signo);
|
||||
ret = cli_loadmd(fd, root, signo, 1);
|
||||
|
||||
} else if(cli_strbcasestr(filename, ".rmd")) {
|
||||
ret = cli_loadmd(fd, root, signo, 2);
|
||||
|
||||
} else {
|
||||
cli_dbgmsg("cl_loaddb: unknown extension - assuming old database format\n");
|
||||
|
@ -958,9 +966,10 @@ int cl_loaddbdir(const char *dirname, struct cl_node **root, unsigned int *signo
|
|||
cli_strbcasestr(dent->d_name, ".db2") ||
|
||||
cli_strbcasestr(dent->d_name, ".db3") ||
|
||||
cli_strbcasestr(dent->d_name, ".hdb") ||
|
||||
cli_strbcasestr(dent->d_name, ".fp") ||
|
||||
cli_strbcasestr(dent->d_name, ".fp") ||
|
||||
cli_strbcasestr(dent->d_name, ".ndb") ||
|
||||
cli_strbcasestr(dent->d_name, ".zmd") ||
|
||||
cli_strbcasestr(dent->d_name, ".rmd") ||
|
||||
cli_strbcasestr(dent->d_name, ".cvd"))) {
|
||||
|
||||
dbfile = (char *) cli_calloc(strlen(dent->d_name) + strlen(dirname) + 2, sizeof(char));
|
||||
|
@ -1040,6 +1049,7 @@ int cl_statinidir(const char *dirname, struct cl_stat *dbstat)
|
|||
cli_strbcasestr(dent->d_name, ".fp") ||
|
||||
cli_strbcasestr(dent->d_name, ".ndb") ||
|
||||
cli_strbcasestr(dent->d_name, ".zmd") ||
|
||||
cli_strbcasestr(dent->d_name, ".rmd") ||
|
||||
cli_strbcasestr(dent->d_name, ".cvd"))) {
|
||||
|
||||
dbstat->no++;
|
||||
|
@ -1110,6 +1120,7 @@ int cl_statchkdir(const struct cl_stat *dbstat)
|
|||
cli_strbcasestr(dent->d_name, ".fp") ||
|
||||
cli_strbcasestr(dent->d_name, ".ndb") ||
|
||||
cli_strbcasestr(dent->d_name, ".zmd") ||
|
||||
cli_strbcasestr(dent->d_name, ".rmd") ||
|
||||
cli_strbcasestr(dent->d_name, ".cvd"))) {
|
||||
|
||||
fname = cli_calloc(strlen(dbstat->dir) + strlen(dent->d_name) + 2, sizeof(char));
|
||||
|
|
|
@ -120,23 +120,23 @@ static void cli_unlock_mutex(void *mtx)
|
|||
static int cli_scanrar(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, int *arec, int *mrec)
|
||||
{
|
||||
FILE *tmp = NULL;
|
||||
int files = 0, fd, ret = CL_CLEAN, afiles;
|
||||
int files = 0, fd, ret = CL_CLEAN, afiles, encrypted;
|
||||
ArchiveList_struct *rarlist = NULL;
|
||||
ArchiveList_struct *rarlist_head = NULL;
|
||||
char *rar_data_ptr;
|
||||
unsigned long rar_data_size;
|
||||
struct cli_meta_node *mdata;
|
||||
|
||||
|
||||
cli_dbgmsg("in scanrar()\n");
|
||||
|
||||
|
||||
#ifdef CL_THREAD_SAFE
|
||||
pthread_cleanup_push(cli_unlock_mutex, &cli_scanrar_mutex);
|
||||
pthread_mutex_lock(&cli_scanrar_mutex);
|
||||
cli_scanrar_inuse = 1;
|
||||
#endif
|
||||
|
||||
if(! (afiles = urarlib_list(desc, (ArchiveList_struct *) &rarlist))) {
|
||||
if(!(afiles = urarlib_list(desc, (ArchiveList_struct *) &rarlist))) {
|
||||
#ifdef CL_THREAD_SAFE
|
||||
pthread_mutex_unlock(&cli_scanrar_mutex);
|
||||
cli_scanrar_inuse = 0;
|
||||
|
@ -149,8 +149,52 @@ static int cli_scanrar(int desc, const char **virname, long int *scanned, const
|
|||
rarlist_head = rarlist;
|
||||
|
||||
while(rarlist) {
|
||||
|
||||
files++;
|
||||
encrypted = rarlist->item.Flags & 0x04;
|
||||
|
||||
cli_dbgmsg("RAR: %s, crc32: 0x%x, encrypted: %d, compressed: %u, normal: %u, method: %d, ratio: %d (max: %d)\n", rarlist->item.Name, rarlist->item.FileCRC, encrypted, rarlist->item.PackSize, rarlist->item.UnpSize, rarlist->item.Method, rarlist->item.PackSize ? (rarlist->item.UnpSize / rarlist->item.PackSize) : 0, limits ? limits->maxratio : -1);
|
||||
|
||||
/* Scan metadata */
|
||||
mdata = root->rar_mlist;
|
||||
if(mdata) do {
|
||||
if(mdata->encrypted != encrypted)
|
||||
continue;
|
||||
|
||||
if(mdata->crc32 && mdata->crc32 != rarlist->item.FileCRC)
|
||||
continue;
|
||||
|
||||
if(mdata->csize > 0 && mdata->csize != rarlist->item.PackSize)
|
||||
continue;
|
||||
|
||||
if(mdata->size >= 0 && mdata->size != rarlist->item.UnpSize)
|
||||
continue;
|
||||
|
||||
if(mdata->method >= 0 && mdata->method != rarlist->item.Method)
|
||||
continue;
|
||||
|
||||
if(mdata->fileno && mdata->fileno != files)
|
||||
continue;
|
||||
|
||||
if(mdata->maxdepth && *arec > mdata->maxdepth)
|
||||
continue;
|
||||
|
||||
/* TODO add support for regex */
|
||||
/*if(mdata->filename && !strstr(zdirent.d_name, mdata->filename))*/
|
||||
if(mdata->filename && strcmp(rarlist->item.Name, mdata->filename))
|
||||
continue;
|
||||
|
||||
break; /* matched */
|
||||
|
||||
} while((mdata = mdata->next));
|
||||
|
||||
if(mdata) {
|
||||
*virname = mdata->virname;
|
||||
ret = CL_VIRUS;
|
||||
break;
|
||||
}
|
||||
|
||||
if(DETECT_ENCRYPTED && (rarlist->item.Flags & 0x04)) {
|
||||
files++;
|
||||
cli_dbgmsg("RAR: Encrypted files found in archive.\n");
|
||||
lseek(desc, 0, SEEK_SET);
|
||||
ret = cli_scandesc(desc, virname, scanned, root, 0, 0);
|
||||
|
@ -166,7 +210,6 @@ static int cli_scanrar(int desc, const char **virname, long int *scanned, const
|
|||
if((rarlist->item.Flags & 0x03) != 0) {
|
||||
cli_dbgmsg("RAR: Skipping %s (splitted)\n", rarlist->item.Name);
|
||||
rarlist = rarlist->next;
|
||||
files++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -184,7 +227,6 @@ static int cli_scanrar(int desc, const char **virname, long int *scanned, const
|
|||
if(limits->maxfilesize && (rarlist->item.UnpSize > (unsigned int) limits->maxfilesize)) {
|
||||
cli_dbgmsg("RAR: %s: Size exceeded (%u, max: %lu)\n", rarlist->item.Name, (unsigned int) rarlist->item.UnpSize, limits->maxfilesize);
|
||||
rarlist = rarlist->next;
|
||||
files++;
|
||||
if(BLOCKMAX) {
|
||||
*virname = "RAR.ExceededFileSize";
|
||||
ret = CL_VIRUS;
|
||||
|
@ -206,7 +248,6 @@ static int cli_scanrar(int desc, const char **virname, long int *scanned, const
|
|||
|
||||
if(rarlist->item.FileAttr & RAR_FENTRY_ATTR_DIRECTORY) {
|
||||
rarlist = rarlist->next;
|
||||
files++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -273,7 +314,6 @@ static int cli_scanrar(int desc, const char **virname, long int *scanned, const
|
|||
fclose(tmp);
|
||||
tmp = NULL;
|
||||
rarlist = rarlist->next;
|
||||
files++;
|
||||
}
|
||||
|
||||
urarlib_freelist(rarlist_head);
|
||||
|
@ -298,7 +338,7 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
|
|||
char *buff;
|
||||
int fd, bytes, files = 0, ret = CL_CLEAN, encrypted;
|
||||
struct stat source;
|
||||
struct cli_zip_node *mdata;
|
||||
struct cli_meta_node *mdata;
|
||||
zzip_error_t err;
|
||||
|
||||
|
||||
|
@ -331,7 +371,7 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
|
|||
|
||||
encrypted = zdirent.d_flags;
|
||||
|
||||
cli_dbgmsg("Zip: %s, crc32: 0x%x, encrypted: %d, compressed: %u, normal: %u, ratio: %d (max: %d)\n", zdirent.d_name, zdirent.d_crc32, encrypted, zdirent.d_csize, zdirent.st_size, zdirent.d_csize ? (zdirent.st_size / zdirent.d_csize) : 0, limits ? limits->maxratio : -1);
|
||||
cli_dbgmsg("Zip: %s, crc32: 0x%x, encrypted: %d, compressed: %u, normal: %u, method: %d, ratio: %d (max: %d)\n", zdirent.d_name, zdirent.d_crc32, encrypted, zdirent.d_csize, zdirent.st_size, zdirent.d_compr, zdirent.d_csize ? (zdirent.st_size / zdirent.d_csize) : 0, limits ? limits->maxratio : -1);
|
||||
|
||||
if(!zdirent.st_size) {
|
||||
if(zdirent.d_crc32) {
|
||||
|
@ -358,7 +398,7 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
|
|||
if(mdata->size >= 0 && mdata->size != zdirent.st_size)
|
||||
continue;
|
||||
|
||||
if(mdata->compr >= 0 && mdata->compr != zdirent.d_compr)
|
||||
if(mdata->method >= 0 && mdata->method != zdirent.d_compr)
|
||||
continue;
|
||||
|
||||
if(mdata->fileno && mdata->fileno != files)
|
||||
|
|
|
@ -251,7 +251,7 @@ int build(struct optstruct *opt)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if(stat("main.db", &foo) == -1 && stat("daily.db", &foo) == -1 && stat("main.hdb", &foo) == -1 && stat("daily.hdb", &foo) == -1 && stat("main.ndb", &foo) == -1 && stat("daily.ndb", &foo) == -1 && stat("main.zmd", &foo) == -1 && stat("daily.zmd", &foo) == -1) {
|
||||
if(stat("main.db", &foo) == -1 && stat("daily.db", &foo) == -1 && stat("main.hdb", &foo) == -1 && stat("daily.hdb", &foo) == -1 && stat("main.ndb", &foo) == -1 && stat("daily.ndb", &foo) == -1 && stat("main.zmd", &foo) == -1 && stat("main.rmd", &foo) == -1 && stat("daily.zmd", &foo) == -1 && stat("daily.rmd", &foo) == -1) {
|
||||
mprintf("Virus database not found in current working directory.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ int build(struct optstruct *opt)
|
|||
mprintf("WARNING: There are no signatures in the database(s).\n");
|
||||
} else {
|
||||
mprintf("Signatures: %d\n", no);
|
||||
realno = countlines("main.db") + countlines("daily.db") + countlines("main.hdb") + countlines("daily.hdb") + countlines("main.ndb") + countlines("daily.ndb") + countlines("main.zmd") + countlines("daily.zmd");
|
||||
realno = countlines("main.db") + countlines("daily.db") + countlines("main.hdb") + countlines("daily.hdb") + countlines("main.ndb") + countlines("daily.ndb") + countlines("main.zmd") + countlines("daily.zmd") + countlines("main.rmd") + countlines("daily.rmd");
|
||||
if(realno != no) {
|
||||
mprintf("!Signatures in database: %d. Loaded: %d.\n", realno, no);
|
||||
mprintf("Please check the current directory and remove unnecessary databases\n");
|
||||
|
@ -288,7 +288,7 @@ int build(struct optstruct *opt)
|
|||
exit(1);
|
||||
case 0:
|
||||
{
|
||||
char *args[] = { "tar", "-cvf", NULL, "COPYING", "main.db", "daily.db", "Notes", "viruses.db3", "main.hdb", "daily.hdb", "main.ndb", "daily.ndb", "main.zmd", "daily.zmd", "main.fp", "daily.fp", NULL };
|
||||
char *args[] = { "tar", "-cvf", NULL, "COPYING", "main.db", "daily.db", "Notes", "viruses.db3", "main.hdb", "daily.hdb", "main.ndb", "daily.ndb", "main.zmd", "daily.zmd", "main.rmd", "daily.rmd", "main.fp", "daily.fp", NULL };
|
||||
args[2] = tarfile;
|
||||
execv("/bin/tar", args);
|
||||
mprintf("!Can't execute tar\n");
|
||||
|
@ -705,7 +705,7 @@ int listdb(const char *filename)
|
|||
free(start);
|
||||
}
|
||||
|
||||
} else if(cli_strbcasestr(filename, ".ndb") || cli_strbcasestr(filename, ".zmd")) {
|
||||
} else if(cli_strbcasestr(filename, ".ndb") || cli_strbcasestr(filename, ".zmd") || cli_strbcasestr(filename, ".rmd")) {
|
||||
|
||||
while(fgets(buffer, FILEBUFF, fd)) {
|
||||
line++;
|
||||
|
@ -755,6 +755,7 @@ int listdir(const char *dirname)
|
|||
cli_strbcasestr(dent->d_name, ".hdb") ||
|
||||
cli_strbcasestr(dent->d_name, ".ndb") ||
|
||||
cli_strbcasestr(dent->d_name, ".zmd") ||
|
||||
cli_strbcasestr(dent->d_name, ".rmd") ||
|
||||
cli_strbcasestr(dent->d_name, ".cvd"))) {
|
||||
|
||||
dbfile = (char *) mcalloc(strlen(dent->d_name) + strlen(dirname) + 2, sizeof(char));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue