Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
73bf360
Bytecode debugging improvements
val-ms Jul 13, 2022
590b642
Tests: add allmatch regression tests
val-ms Jul 13, 2022
99df935
Tests: All-match mode tests
val-ms Jul 28, 2022
5e04de6
Tests: allmatch with pattern match + embedded file type recognition
val-ms Jul 28, 2022
4d74703
Tests: Add NDB & LDB to allmatch test
val-ms Aug 15, 2022
8ab6dda
Tests: heuristic alerts with/out allmatch, precedence-mode
val-ms Aug 17, 2022
d67bf60
Tests: break out clamscan tests into separate files
val-ms Aug 23, 2022
00d10c8
Tests: Add FP tests for trusting by hash at diff layers
val-ms Aug 23, 2022
2fbd69e
Tests: add pe-allmatch test set
val-ms Aug 23, 2022
0d60c63
Tests: Fix failure if markdown module installed
val-ms Aug 25, 2022
0203c6b
Allmatch-mode overhaul, part 1: append_virus
val-ms Aug 4, 2022
4061468
Bytecode: Remove individual allmatch checks
val-ms Aug 9, 2022
58a7ef1
7zip: Remove individual allmatch checks
val-ms Aug 9, 2022
0491cca
Disk partition parsers: Remove all-match checks + code cleanup
val-ms Aug 9, 2022
d825e42
Install Shield: Remove all-match checks + code cleanup
val-ms Aug 9, 2022
3288131
AutoIT: Remove all-match checks + code cleanup
val-ms Aug 9, 2022
c84fec7
CPIO: Remove all-match checks + code cleanup
val-ms Aug 10, 2022
8f0e4d1
ISO9660: Remove all-match checks + code cleanup
val-ms Aug 10, 2022
c52f7e5
HWP3, ASN1, blob: Remove all-match checks
val-ms Aug 10, 2022
92222f4
Hashtable / hashmap / hashset code cleanup
val-ms Aug 12, 2022
33ebd49
Fix image parser match reporting issue
val-ms Aug 17, 2022
8c1c059
PDF: Remove all-match checks
val-ms Aug 17, 2022
7c2fd9b
XAR: Remove allmatch checks
val-ms Aug 17, 2022
3283136
Code cleanup: be explicit about what if-conditions are checking
val-ms Aug 17, 2022
51896a0
Fix issue reporting all Heuristic/PUA matches in allmatch mode
val-ms Aug 17, 2022
b461168
Code cleanup: More accurate variable types in bytecode modules
val-ms Aug 17, 2022
090c272
Bytecode: Fix compiler warning for unused iptr variable
val-ms Aug 17, 2022
4395f1f
CAB/CHM: Remove allmatch checks & clean up error handling
val-ms Aug 18, 2022
9179c40
Matcher: Remove allmatch checks and significantly tidy code
val-ms Aug 19, 2022
8c33191
Matcher: code cleanup, fix possible leaks
val-ms Aug 19, 2022
3056883
Fix issue detecting embedded zips attached to small files
val-ms Aug 19, 2022
3797005
Strong indicator precedence over PUA / Heuristic detections
val-ms Aug 19, 2022
b765e56
PCRE: Remove allmatch check + minor code cleanup
val-ms Aug 23, 2022
74a5ea8
MSXML: Remove allmatch checks + minor code cleanup
val-ms Aug 23, 2022
47ddd92
OLE2: Remove allmatch checks + minor code cleanup
val-ms Aug 23, 2022
fa95ceb
PDF: remove allmatch checks
val-ms Aug 23, 2022
0a299a4
PE: Remove allmatch checks + minor code cleanup
val-ms Aug 24, 2022
3fe98fe
Fix certificate load x509 -> PEM result check
val-ms Aug 27, 2022
b41d62c
Correct parameter type in cl_strerror() public API
val-ms Aug 27, 2022
17c4104
Fix error handling in Mach-O and ELF bytecode unpacker hooks
val-ms Aug 27, 2022
8804925
TAR: Remove allmatch checks
val-ms Aug 27, 2022
150fd6c
ZIP: Remove allmatch checks
val-ms Aug 27, 2022
677c1f4
Excel (XLM, VBA): Remove allmatch checks + some code cleanup
val-ms Aug 27, 2022
e2201ed
Phishcheck: remove allmatch check
val-ms Aug 27, 2022
47d574c
Scanners: Remove allmatch checks + significant code cleanup
val-ms Aug 27, 2022
d9dae44
PE, ELF, Mach-O: code cleanup
val-ms Aug 29, 2022
3961175
Fix bytecode hook out-file descriptor error handling
val-ms Sep 17, 2022
612a869
Change timeout message verbosity in PDF parser to debug
val-ms Sep 17, 2022
6399496
Do not report timeout as error
val-ms Sep 21, 2022
9ebed53
HFS+ parser: Fix bugs introduced in refactor
val-ms Sep 30, 2022
5b84b9c
Use correct enum types for cli_memcpy internal API
val-ms Sep 30, 2022
051bc96
Fmap: Fix copy-paste bug when checking if map hash exists
val-ms Sep 30, 2022
ff4826b
Improvements to adhere to scan time limit
val-ms Oct 4, 2022
c50a8c2
Refactor logical sig evaluation, fix minor bug
val-ms Oct 4, 2022
155ca1b
Improve strictness of max-scantime
val-ms Oct 17, 2022
efa8a01
Improve file type detection for some small files
val-ms Oct 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,6 @@ elseif(APPLE)
)
if(${MARKDOWN_MODULE_EXIT_CODE} EQUAL 0)
# The markdown module is installed, we can do the conversion.
set(PythonTest_COMMAND "${Python3_EXECUTABLE};-m;markdown;-v")

execute_process(
COMMAND echo "<html><body>"
OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/prefix.html)
Expand Down Expand Up @@ -894,6 +892,7 @@ else()
extract_valid_cxx_flags(WARNCXXFLAGS
-Wall
-Wformat-security
-Wno-comment # Disabled because LLVM's CFG.h has a warning about a multiline comment because of ascii-art of a graph with a `\` in it.
)
endif()

Expand Down
7 changes: 5 additions & 2 deletions clambc/bcrun.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "others.h"
#include "bytecode.h"
#include "bytecode_priv.h"
#include "clamav_rust.h"

// common
#include "optparser.h"
Expand Down Expand Up @@ -393,8 +394,9 @@ int main(int argc, char *argv[])
fprintf(stderr, "Out of memory\n");
exit(3);
}
ctx->ctx = &cctx;
cctx.engine = engine;
ctx->ctx = &cctx;
cctx.engine = engine;
cctx.evidence = evidence_new();

cctx.recursion_stack_size = cctx.engine->max_recursion_level;
cctx.recursion_stack = cli_calloc(sizeof(recursion_level_t), cctx.recursion_stack_size);
Expand Down Expand Up @@ -478,6 +480,7 @@ int main(int argc, char *argv[])
funmap(map);
cl_engine_free(engine);
free(cctx.recursion_stack);
evidence_free(cctx.evidence);
}
cli_bytecode_destroy(bc);
cli_bytecode_done(&bcs);
Expand Down
4 changes: 2 additions & 2 deletions common/cert_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ static cl_error_t _x509_to_pem(X509 *cert,
ret = CL_SUCCESS;

done:
return (0);
return ret;
}

/**
Expand Down Expand Up @@ -125,7 +125,7 @@ static cl_error_t _x509_to_pem_append(X509 *ca_cert,

current_len = *total_buf_len;

if (_x509_to_pem(ca_cert, &pem_data, &pem_data_len) != 0) {
if (CL_SUCCESS != _x509_to_pem(ca_cert, &pem_data, &pem_data_len)) {
mprintf(LOGG_ERROR, "Failed to convert x509 certificate to PEM\n");
goto done;
}
Expand Down
36 changes: 15 additions & 21 deletions libclamav/7z_iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
int namelen = UTFBUFSZ;
cl_error_t found = CL_CLEAN;
Int64 begin_of_archive = offset;
UInt32 viruses_found = 0;

/* Replacement for
FileInStream_CreateVTable(&archiveStream); */
Expand All @@ -111,7 +110,7 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
if (res == SZ_ERROR_ENCRYPTED && SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
cli_dbgmsg("cli_7unz: Encrypted header found in archive.\n");
found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
found = cli_append_potentially_unwanted(ctx, "Heuristics.Encrypted.7Zip");
} else if (res == SZ_OK) {
UInt32 i, blockIndex = 0xFFFFFFFF;
Byte *outBuffer = 0;
Expand All @@ -127,12 +126,14 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
size_t j;
int newnamelen, fd;

// abort if we would exceed max files or max scan time.
if ((found = cli_checklimits("7unz", ctx, 0, 0, 0)))
break;

if (f->IsDir)
continue;

// skip this file if we would exceed max file size or max scan size. (we already checked for the max files and max scan time)
if (cli_checklimits("7unz", ctx, f->Size, 0, 0))
continue;

Expand Down Expand Up @@ -164,21 +165,15 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
encrypted = 1;
if (SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n");
found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
if (found != CL_CLEAN) {
if (found == CL_VIRUS) {
if (SCAN_ALLMATCHES)
viruses_found++;
} else
break;
found = cli_append_potentially_unwanted(ctx, "Heuristics.Encrypted.7Zip");
if (found != CL_SUCCESS) {
break;
}
}
}
if (cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) {
if (CL_VIRUS == cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) {
found = CL_VIRUS;
viruses_found++;
if (!SCAN_ALLMATCHES)
break;
break;
}
if (res != SZ_OK)
cli_dbgmsg("cli_unz: extraction failed with %d\n", res);
Expand All @@ -189,18 +184,19 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
break;

cli_dbgmsg("cli_7unz: Saving to %s\n", tmp_name);
if (cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed)
if (cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed) {
found = CL_EWRITE;
else if (CL_VIRUS == (found = cli_magic_scan_desc(fd, tmp_name, ctx, name, LAYER_ATTRIBUTES_NONE)))
viruses_found++;
}

found = cli_magic_scan_desc(fd, tmp_name, ctx, name, LAYER_ATTRIBUTES_NONE);

close(fd);
if (!ctx->engine->keeptmp && cli_unlink(tmp_name))
found = CL_EUNLINK;

free(tmp_name);
if (found != CL_CLEAN)
if (!(SCAN_ALLMATCHES && found == CL_VIRUS))
break;
if (found != CL_SUCCESS)
break;
}
}
IAlloc_Free(&allocImp, outBuffer);
Expand All @@ -222,7 +218,5 @@ int cli_7unz(cli_ctx *ctx, size_t offset)
else
cli_dbgmsg("cli_7unz: error %d\n", res);

if (SCAN_ALLMATCHES && viruses_found)
return CL_VIRUS;
return found;
}
2 changes: 1 addition & 1 deletion libclamav/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ set(LIBCLAMAV_SOURCES
matcher-ac.c matcher-ac.h
matcher-bm.c matcher-bm.h
matcher-byte-comp.c matcher-byte-comp.h
matcher-hash.c matcher-hash.h
matcher-hash.c matcher-hash.h matcher-hash-types.h
matcher-pcre.c matcher-pcre.h
matcher.c matcher.h
regex_pcre.c regex_pcre.h
Expand Down
101 changes: 53 additions & 48 deletions libclamav/apm.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,30 @@
#define apm_parsemsg(...) ;
#endif

static int apm_partition_intersection(cli_ctx *ctx, struct apm_partition_info *aptable, size_t sectorsize, int old_school);
static cl_error_t apm_partition_intersection(cli_ctx *ctx, struct apm_partition_info *aptable, size_t sectorsize, bool old_school);

int cli_scanapm(cli_ctx *ctx)
cl_error_t cli_scanapm(cli_ctx *ctx)
{
cl_error_t status = CL_SUCCESS;
struct apm_driver_desc_map ddm;
struct apm_partition_info aptable, apentry;
int ret = CL_CLEAN, detection = CL_CLEAN, old_school = 0;
bool old_school = false;
size_t sectorsize, maplen, partsize;
size_t pos = 0, partoff = 0;
unsigned i;
uint32_t max_prtns = 0;

if (!ctx || !ctx->fmap) {
cli_errmsg("cli_scanapm: Invalid context\n");
return CL_ENULLARG;
status = CL_ENULLARG;
goto done;
}

/* read driver description map at sector 0 */
if (fmap_readn(ctx->fmap, &ddm, pos, sizeof(ddm)) != sizeof(ddm)) {
cli_dbgmsg("cli_scanapm: Invalid Apple driver description map\n");
return CL_EFORMAT;
status = CL_EFORMAT;
goto done;
}

/* convert driver description map big-endian to host */
Expand All @@ -76,7 +79,8 @@ int cli_scanapm(cli_ctx *ctx)
/* check DDM signature */
if (ddm.signature != DDM_SIGNATURE) {
cli_dbgmsg("cli_scanapm: Apple driver description map signature mismatch\n");
return CL_EFORMAT;
status = CL_EFORMAT;
goto done;
}

/* sector size is determined by the ddm */
Expand All @@ -87,20 +91,22 @@ int cli_scanapm(cli_ctx *ctx)
if ((ddm.blockSize * ddm.blockCount) != maplen) {
cli_dbgmsg("cli_scanapm: File described %u size does not match %lu actual size\n",
(ddm.blockSize * ddm.blockCount), (unsigned long)maplen);
return CL_EFORMAT;
status = CL_EFORMAT;
goto done;
}

/* check for old-school partition map */
if (sectorsize == 2048) {
if (fmap_readn(ctx->fmap, &aptable, APM_FALLBACK_SECTOR_SIZE, sizeof(aptable)) != sizeof(aptable)) {
cli_dbgmsg("cli_scanapm: Invalid Apple partition entry\n");
return CL_EFORMAT;
status = CL_EFORMAT;
goto done;
}

aptable.signature = be16_to_host(aptable.signature);
if (aptable.signature == APM_SIGNATURE) {
sectorsize = APM_FALLBACK_SECTOR_SIZE;
old_school = 1;
old_school = true;
}
}

Expand All @@ -109,7 +115,8 @@ int cli_scanapm(cli_ctx *ctx)

if (fmap_readn(ctx->fmap, &aptable, pos, sizeof(aptable)) != sizeof(aptable)) {
cli_dbgmsg("cli_scanapm: Invalid Apple partition table\n");
return CL_EFORMAT;
status = CL_EFORMAT;
goto done;
}

/* convert partition table big endian to host */
Expand All @@ -121,25 +128,24 @@ int cli_scanapm(cli_ctx *ctx)
/* check the partition entry signature */
if (aptable.signature != APM_SIGNATURE) {
cli_dbgmsg("cli_scanapm: Apple partition table signature mismatch\n");
return CL_EFORMAT;
status = CL_EFORMAT;
goto done;
}

/* check if partition table partition */
if (strncmp((char *)aptable.type, "Apple_Partition_Map", 32) &&
strncmp((char *)aptable.type, "Apple_partition_map", 32) &&
strncmp((char *)aptable.type, "Apple_patition_map", 32)) {
cli_dbgmsg("cli_scanapm: Initial Apple Partition Map partition is not detected\n");
return CL_EFORMAT;
status = CL_EFORMAT;
goto done;
}

/* check that the partition table fits in the space specified - HEURISTICS */
if (SCAN_HEURISTIC_PARTITION_INTXN && (ctx->dconf->other & OTHER_CONF_PRTNINTXN)) {
ret = apm_partition_intersection(ctx, &aptable, sectorsize, old_school);
if (ret != CL_CLEAN) {
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
status = apm_partition_intersection(ctx, &aptable, sectorsize, old_school);
if (status != CL_SUCCESS) {
goto done;
}
}

Expand Down Expand Up @@ -167,7 +173,8 @@ int cli_scanapm(cli_ctx *ctx)
pos = i * sectorsize;
if (fmap_readn(ctx->fmap, &apentry, pos, sizeof(apentry)) != sizeof(apentry)) {
cli_dbgmsg("cli_scanapm: Invalid Apple partition entry\n");
return CL_EFORMAT;
status = CL_EFORMAT;
goto done;
}

/* convert partition entry big endian to host */
Expand All @@ -180,7 +187,8 @@ int cli_scanapm(cli_ctx *ctx)
/* check the partition entry signature */
if (aptable.signature != APM_SIGNATURE) {
cli_dbgmsg("cli_scanapm: Apple partition entry signature mismatch\n");
return CL_EFORMAT;
status = CL_EFORMAT;
goto done;
}

/* check if a out-of-order partition map */
Expand Down Expand Up @@ -223,32 +231,30 @@ int cli_scanapm(cli_ctx *ctx)
apentry.pBlockStart, apentry.pBlockCount, partoff, partsize);

/* send the partition to cli_magic_scan_nested_fmap_type */
ret = cli_magic_scan_nested_fmap_type(ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY,
(const char *)apentry.name, LAYER_ATTRIBUTES_NONE);
if (ret != CL_CLEAN) {
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
status = cli_magic_scan_nested_fmap_type(ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY, (const char *)apentry.name, LAYER_ATTRIBUTES_NONE);
if (status != CL_SUCCESS) {
goto done;
}
}

if (i >= ctx->engine->maxpartitions) {
cli_dbgmsg("cli_scanapm: max partitions reached\n");
}

return detection;
done:

return status;
}

static int apm_partition_intersection(cli_ctx *ctx, struct apm_partition_info *aptable, size_t sectorsize, int old_school)
static cl_error_t apm_partition_intersection(cli_ctx *ctx, struct apm_partition_info *aptable, size_t sectorsize, bool old_school)
{
cl_error_t status = CL_SUCCESS;
cl_error_t ret;
partition_intersection_list_t prtncheck;
struct apm_partition_info apentry;
unsigned i, pitxn;
int ret = CL_CLEAN, tmp = CL_CLEAN;
size_t pos;
uint32_t max_prtns = 0;
int virus_found = 0;

partition_intersection_list_init(&prtncheck);

Expand All @@ -265,7 +271,8 @@ static int apm_partition_intersection(cli_ctx *ctx, struct apm_partition_info *a
if (fmap_readn(ctx->fmap, &apentry, pos, sizeof(apentry)) != sizeof(apentry)) {
cli_dbgmsg("cli_scanapm: Invalid Apple partition entry\n");
partition_intersection_list_free(&prtncheck);
return CL_EFORMAT;
status = CL_EFORMAT;
goto done;
}

/* convert necessary info big endian to host */
Expand All @@ -284,33 +291,31 @@ static int apm_partition_intersection(cli_ctx *ctx, struct apm_partition_info *a
}
}

tmp = partition_intersection_list_check(&prtncheck, &pitxn, apentry.pBlockStart, apentry.pBlockCount);
if (tmp != CL_CLEAN) {
if (tmp == CL_VIRUS) {
ret = partition_intersection_list_check(&prtncheck, &pitxn, apentry.pBlockStart, apentry.pBlockCount);
if (ret != CL_CLEAN) {
if (ret == CL_VIRUS) {
apm_parsemsg("Name: %s\n", (char *)aptable.name);
apm_parsemsg("Type: %s\n", (char *)aptable.type);

cli_dbgmsg("cli_scanapm: detected intersection with partitions "
"[%u, %u]\n",
pitxn, i);
ret = cli_append_virus(ctx, PRTN_INTXN_DETECTION);
if (ret == CL_VIRUS)
virus_found = 1;
if (SCAN_ALLMATCHES || ret == CL_CLEAN)
tmp = 0;
else
goto leave;
status = cli_append_potentially_unwanted(ctx, "Heuristics.APMPartitionIntersection");
if (status != CL_SUCCESS) {
goto done;
}
} else {
ret = tmp;
goto leave;
status = ret;
goto done;
}
}

/* increment the offsets to next partition entry */
pos += sectorsize;
}

leave:
done:
partition_intersection_list_free(&prtncheck);
if (virus_found)
return CL_VIRUS;
return ret;

return status;
}
Loading