PE, ELF, Mach-O: code cleanup

The header parsing / executable metadata collecting functions for the
PE, ELF, and Mach-O file types were using `int` for the return type.
Mostly they were returning 0 for success and -1, -2, -3, or -4 for
failure. But in some cases they were returning cl_error_t enum values
for failure. Regardless, the function using them was treating 0 as
success and non-zero as failure, which it stored as -1 ... every time.

This commit switches them all to use cl_error_t.  I am continuing to
storeo the final result as 0 / -1 in the `peinfo` struct, but outside of
that everything has been made consistent.

While I was working on that, I got a tad side tracked.  I noticed that
the target type isn't an enum, or even a set of #defines. So I made an
enum and then changed the code that uses target types to use the enum.

I also removed the `target` parameter from a number of functions that
don't actually use it at all. Some recursion was masking the fact that
it was an unused parameter which is why there was no warning about it.
pull/727/head
Micah Snyder 3 years ago committed by Micah Snyder
parent 0bd2ae26bc
commit f7b139a776
  1. 24
      libclamav/elf.c
  2. 2
      libclamav/elf.h
  3. 59
      libclamav/macho.c
  4. 4
      libclamav/macho.h
  5. 23
      libclamav/matcher.c
  6. 50
      libclamav/matcher.h
  7. 87
      libclamav/pe.c
  8. 11
      libclamav/pe.h
  9. 56
      libclamav/readdb.c
  10. 9
      libclamav/readdb.h
  11. 2
      libclamav/regex_list.c
  12. 3
      libclamav/regex_suffix.c
  13. 6
      sigtool/sigtool.c
  14. 2
      sigtool/vba.c
  15. 24
      unit_tests/check_matchers.c

@ -99,7 +99,7 @@ static uint64_t cli_rawaddr64(uint64_t vaddr, struct elf_program_hdr64 *ph, uint
}
/* Return converted endian-fixed header, or error code */
static int cli_elf_fileheader(cli_ctx *ctx, fmap_t *map, union elf_file_hdr *file_hdr,
static cl_error_t cli_elf_fileheader(cli_ctx *ctx, fmap_t *map, union elf_file_hdr *file_hdr,
uint8_t *do_convert, uint8_t *is64)
{
uint8_t format64, conv;
@ -306,7 +306,7 @@ static int cli_elf_ph32(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
}
/* Read 64-bit program headers */
static int cli_elf_ph64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
static cl_error_t cli_elf_ph64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
struct elf_file_hdr64 *file_hdr, uint8_t conv)
{
struct elf_program_hdr64 *program_hdr = NULL;
@ -791,11 +791,11 @@ cl_error_t cli_scanelf(cli_ctx *ctx)
/* ELF header parsing only
* Returns 0 on success, -1 on error
*/
int cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo)
cl_error_t cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo)
{
union elf_file_hdr file_hdr;
uint8_t conv = 0, is64 = 0;
int ret;
cl_error_t ret = CL_SUCCESS;
cli_dbgmsg("in cli_elfheader\n");
@ -806,8 +806,8 @@ int cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo)
}
ret = cli_elf_fileheader(NULL, ctx->fmap, &file_hdr, &conv, &is64);
if (ret != CL_CLEAN) {
return -1;
if (ret != CL_SUCCESS) {
goto done;
}
/* Program headers and Entry */
@ -816,8 +816,8 @@ int cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo)
} else {
ret = cli_elf_ph32(NULL, ctx->fmap, elfinfo, &(file_hdr.hdr32.hdr), conv);
}
if (ret != CL_CLEAN) {
return -1;
if (ret != CL_SUCCESS) {
goto done;
}
/* Section Headers */
@ -826,11 +826,13 @@ int cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo)
} else {
ret = cli_elf_sh32(NULL, ctx->fmap, elfinfo, &(file_hdr.hdr32.hdr), conv);
}
if (ret != CL_CLEAN) {
return -1;
if (ret != CL_SUCCESS) {
goto done;
}
return 0;
done:
return ret;
}
/*

@ -145,7 +145,7 @@ struct elf_section_hdr64 {
cl_error_t cli_scanelf(cli_ctx *ctx);
int cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo);
cl_error_t cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo);
cl_error_t cli_unpackelf(cli_ctx *ctx);

@ -169,8 +169,6 @@ struct macho_fat_arch {
};
#define RETURN_BROKEN \
if (matcher) \
return -1; \
if (SCAN_HEURISTIC_BROKEN) { \
if (CL_VIRUS == cli_append_potentially_unwanted(ctx, "Heuristics.Broken.Executable")) \
return CL_VIRUS; \
@ -197,7 +195,7 @@ static uint32_t cli_rawaddr(uint32_t vaddr, struct cli_exe_section *sects, uint1
return vaddr - sects[i].rva + sects[i].raw;
}
int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
cl_error_t cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
{
struct macho_hdr hdr;
struct macho_load_cmd load_cmd;
@ -205,7 +203,8 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
struct macho_segment_cmd64 segment_cmd64;
struct macho_section section;
struct macho_section64 section64;
unsigned int i, j, sect = 0, conv, m64, nsects, matcher = 0;
unsigned int i, j, sect = 0, conv, m64, nsects;
bool get_fileinfo = false;
unsigned int arch = 0, ep = 0, err;
struct cli_exe_section *sections = NULL;
char name[16];
@ -213,7 +212,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
ssize_t at;
if (fileinfo) {
matcher = 1;
get_fileinfo = true;
// TODO This code assumes fileinfo->offset == 0, which might not always
// be the case. For now just print this debug message and continue on
@ -224,7 +223,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
if (fmap_readn(map, &hdr, 0, sizeof(hdr)) != sizeof(hdr)) {
cli_dbgmsg("cli_scanmacho: Can't read header\n");
return matcher ? -1 : CL_EFORMAT;
return CL_EFORMAT;
}
at = sizeof(hdr);
@ -242,44 +241,44 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
m64 = 1;
} else {
cli_dbgmsg("cli_scanmacho: Incorrect magic\n");
return matcher ? -1 : CL_EFORMAT;
return CL_EFORMAT;
}
switch (EC32(hdr.cpu_type, conv)) {
case 7:
if (!matcher)
if (!get_fileinfo)
cli_dbgmsg("MACHO: CPU Type: Intel 32-bit\n");
arch = 1;
break;
case 7 | 0x1000000:
if (!matcher)
if (!get_fileinfo)
cli_dbgmsg("MACHO: CPU Type: Intel 64-bit\n");
break;
case 12:
if (!matcher)
if (!get_fileinfo)
cli_dbgmsg("MACHO: CPU Type: ARM\n");
break;
case 14:
if (!matcher)
if (!get_fileinfo)
cli_dbgmsg("MACHO: CPU Type: SPARC\n");
break;
case 18:
if (!matcher)
if (!get_fileinfo)
cli_dbgmsg("MACHO: CPU Type: POWERPC 32-bit\n");
arch = 2;
break;
case 18 | 0x1000000:
if (!matcher)
if (!get_fileinfo)
cli_dbgmsg("MACHO: CPU Type: POWERPC 64-bit\n");
arch = 3;
break;
default:
if (!matcher)
if (!get_fileinfo)
cli_dbgmsg("MACHO: CPU Type: ** UNKNOWN ** (%u)\n", EC32(hdr.cpu_type, conv));
break;
}
if (!matcher) switch (EC32(hdr.filetype, conv)) {
if (!get_fileinfo) switch (EC32(hdr.filetype, conv)) {
case 0x1: /* MH_OBJECT */
cli_dbgmsg("MACHO: Filetype: Relocatable object file\n");
break;
@ -311,7 +310,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
cli_dbgmsg("MACHO: Filetype: ** UNKNOWN ** (0x%x)\n", EC32(hdr.filetype, conv));
}
if (!matcher) {
if (!get_fileinfo) {
cli_dbgmsg("MACHO: Number of load commands: %u\n", EC32(hdr.ncmds, conv));
cli_dbgmsg("MACHO: Size of load commands: %u\n", EC32(hdr.sizeofcmds, conv));
}
@ -362,7 +361,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
strncpy(name, segment_cmd.segname, sizeof(name));
name[sizeof(name) - 1] = '\0';
}
if (!matcher) {
if (!get_fileinfo) {
cli_dbgmsg("MACHO: Segment name: %s\n", name);
cli_dbgmsg("MACHO: Number of sections: %u\n", nsects);
}
@ -372,14 +371,14 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
RETURN_BROKEN;
}
if (!nsects) {
if (!matcher)
if (!get_fileinfo)
cli_dbgmsg("MACHO: ------------------\n");
continue;
}
sections = (struct cli_exe_section *)cli_realloc2(sections, (sect + nsects) * sizeof(struct cli_exe_section));
if (!sections) {
cli_errmsg("cli_scanmacho: Can't allocate memory for 'sections'\n");
return matcher ? -1 : CL_EMEM;
return CL_EMEM;
}
for (j = 0; j < nsects; j++) {
@ -417,7 +416,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
strncpy(name, section.sectname, sizeof(name));
name[sizeof(name) - 1] = '\0';
}
if (!matcher) {
if (!get_fileinfo) {
cli_dbgmsg("MACHO: --- Section %u ---\n", sect);
cli_dbgmsg("MACHO: Name: %s\n", name);
cli_dbgmsg("MACHO: Virtual address: 0x%x\n", (unsigned int)sections[sect].rva);
@ -428,7 +427,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
}
sect++;
}
if (!matcher)
if (!get_fileinfo)
cli_dbgmsg("MACHO: ------------------\n");
} else if (arch && (load_cmd.cmd == 0x4 || load_cmd.cmd == 0x5)) { /* LC_(UNIX)THREAD */
@ -477,7 +476,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
default:
cli_errmsg("cli_scanmacho: Invalid arch setting!\n");
free(sections);
return matcher ? -1 : CL_EARG;
return CL_EARG;
}
} else {
if (EC32(load_cmd.cmdsize, conv) > sizeof(load_cmd))
@ -486,32 +485,32 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
}
if (ep) {
if (!matcher)
if (!get_fileinfo)
cli_dbgmsg("Entry Point: 0x%x\n", ep);
if (sections) {
ep = cli_rawaddr(ep, sections, sect, &err);
if (err) {
cli_dbgmsg("cli_scanmacho: Can't calculate EP offset\n");
free(sections);
return matcher ? -1 : CL_EFORMAT;
return CL_EFORMAT;
}
if (!matcher)
if (!get_fileinfo)
cli_dbgmsg("Entry Point file offset: %u\n", ep);
}
}
if (matcher) {
if (get_fileinfo) {
fileinfo->ep = ep;
fileinfo->nsections = sect;
fileinfo->sections = sections;
return 0;
} else {
free(sections);
return CL_SUCCESS;
}
return CL_SUCCESS;
}
int cli_machoheader(cli_ctx *ctx, struct cli_exe_info *fileinfo)
cl_error_t cli_machoheader(cli_ctx *ctx, struct cli_exe_info *fileinfo)
{
return cli_scanmacho(ctx, fileinfo);
}
@ -520,7 +519,7 @@ cl_error_t cli_scanmacho_unibin(cli_ctx *ctx)
{
struct macho_fat_header fat_header;
struct macho_fat_arch fat_arch;
unsigned int conv, i, matcher = 0;
unsigned int conv, i;
cl_error_t ret = CL_SUCCESS;
fmap_t *map = ctx->fmap;
ssize_t at;

@ -26,8 +26,8 @@
#include "execs.h"
#include "fmap.h"
int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo);
int cli_machoheader(cli_ctx *ctx, struct cli_exe_info *fileinfo);
cl_error_t cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo);
cl_error_t cli_machoheader(cli_ctx *ctx, struct cli_exe_info *fileinfo);
cl_error_t cli_scanmacho_unibin(cli_ctx *ctx);
cl_error_t cli_unpackmacho(cli_ctx *ctx);

@ -346,7 +346,7 @@ cl_error_t cli_scan_buff(const unsigned char *buffer, uint32_t length, uint32_t
* offdata[2]: max shift
* offdata[3]: section number
*/
cl_error_t cli_caloff(const char *offstr, const struct cli_target_info *info, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max)
cl_error_t cli_caloff(const char *offstr, const struct cli_target_info *info, cli_target_t target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max)
{
char offcpy[65] = {0};
unsigned int n = 0, val = 0;
@ -453,7 +453,7 @@ cl_error_t cli_caloff(const char *offstr, const struct cli_target_info *info, un
if (offdata[0] != CLI_OFF_ANY && offdata[0] != CLI_OFF_ABSOLUTE &&
offdata[0] != CLI_OFF_EOF_MINUS && offdata[0] != CLI_OFF_MACRO) {
if (target != 1 && target != 6 && target != 9) {
if (target != TARGET_PE && target != TARGET_ELF && target != TARGET_MACHO) {
cli_errmsg("cli_caloff: Invalid offset type for target %u\n", target);
return CL_EMALFDB;
}
@ -533,22 +533,27 @@ void cli_targetinfo_init(struct cli_target_info *info)
cli_exe_info_init(&(info->exeinfo), 0);
}
void cli_targetinfo(struct cli_target_info *info, unsigned int target, cli_ctx *ctx)
void cli_targetinfo(struct cli_target_info *info, cli_target_t target, cli_ctx *ctx)
{
int (*einfo)(cli_ctx *, struct cli_exe_info *) = NULL;
cl_error_t (*einfo)(cli_ctx *, struct cli_exe_info *) = NULL;
info->fsize = ctx->fmap->len;
if (target == 1)
switch (target) {
case TARGET_PE:
einfo = cli_pe_targetinfo;
else if (target == 6)
break;
case TARGET_ELF:
einfo = cli_elfheader;
else if (target == 9)
break;
case TARGET_MACHO:
einfo = cli_machoheader;
else
break;
default:
return;
}
if (einfo(ctx, &info->exeinfo))
if (CL_SUCCESS != einfo(ctx, &info->exeinfo))
info->status = -1;
else
info->status = 1;

@ -203,11 +203,29 @@ struct cli_cdb {
struct cli_cdb *next;
};
typedef enum {
TARGET_GENERIC = 0,
TARGET_PE = 1,
TARGET_OLE2 = 2,
TARGET_HTML = 3,
TARGET_MAIL = 4,
TARGET_GRAPHICS = 5,
TARGET_ELF = 6,
TARGET_ASCII = 7,
TARGET_NOT_USED = 8,
TARGET_MACHO = 9,
TARGET_PDF = 10,
TARGET_FLASH = 11,
TARGET_JAVA = 12,
TARGET_INTERNAL = 13,
TARGET_OTHER = 14,
} cli_target_t;
#define CLI_MAX_TARGETS 10 /* maximum filetypes for a specific target */
struct cli_mtarget {
cli_file_t target[CLI_MAX_TARGETS];
const char *name;
uint8_t idx; /* idx of matcher */
cli_target_t idx; /* idx of matcher */
uint8_t ac_only;
uint8_t enable_prefiltering;
uint8_t target_count; /* must be synced with non-zero values in the target array */
@ -216,21 +234,21 @@ struct cli_mtarget {
#define CLI_MTARGETS 15
static const struct cli_mtarget cli_mtargets[CLI_MTARGETS] = {
/* All types for target, name, idx, ac_only, pre-filtering?, # of types */
{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "GENERIC", 0, 0, 1, 1},
{{CL_TYPE_MSEXE, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "PE", 1, 0, 1, 1},
{{CL_TYPE_MSOLE2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OLE2", 2, 1, 0, 1},
{{CL_TYPE_HTML, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "HTML", 3, 1, 0, 1},
{{CL_TYPE_MAIL, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "MAIL", 4, 1, 1, 1},
{{CL_TYPE_GRAPHICS, CL_TYPE_GIF, CL_TYPE_PNG, CL_TYPE_JPEG, CL_TYPE_TIFF, 0, 0, 0, 0, 0}, "GRAPHICS", 5, 1, 0, 5},
{{CL_TYPE_ELF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "ELF", 6, 1, 0, 1},
{{CL_TYPE_TEXT_ASCII, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "ASCII", 7, 1, 1, 1},
{{CL_TYPE_ERROR, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "NOT USED", 8, 1, 0, 1},
{{CL_TYPE_MACHO, CL_TYPE_MACHO_UNIBIN, 0, 0, 0, 0, 0, 0, 0, 0}, "MACH-O", 9, 1, 0, 2},
{{CL_TYPE_PDF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "PDF", 10, 1, 0, 1},
{{CL_TYPE_SWF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "FLASH", 11, 1, 0, 1},
{{CL_TYPE_JAVA, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "JAVA", 12, 1, 0, 1},
{{CL_TYPE_INTERNAL, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "INTERNAL", 13, 1, 0, 1},
{{CL_TYPE_OTHER, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OTHER", 14, 1, 0, 1}};
{{CL_TYPE_ANY, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "GENERIC", TARGET_GENERIC, 0, 1, 1},
{{CL_TYPE_MSEXE, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "PE", TARGET_PE, 0, 1, 1},
{{CL_TYPE_MSOLE2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OLE2", TARGET_OLE2, 1, 0, 1},
{{CL_TYPE_HTML, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "HTML", TARGET_HTML, 1, 0, 1},
{{CL_TYPE_MAIL, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "MAIL", TARGET_MAIL, 1, 1, 1},
{{CL_TYPE_GRAPHICS, CL_TYPE_GIF, CL_TYPE_PNG, CL_TYPE_JPEG, CL_TYPE_TIFF, 0, 0, 0, 0, 0}, "GRAPHICS", TARGET_GRAPHICS, 1, 0, 5},
{{CL_TYPE_ELF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "ELF", TARGET_ELF, 1, 0, 1},
{{CL_TYPE_TEXT_ASCII, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "ASCII", TARGET_ASCII, 1, 1, 1},
{{CL_TYPE_ERROR, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "NOT USED", TARGET_NOT_USED, 1, 0, 1},
{{CL_TYPE_MACHO, CL_TYPE_MACHO_UNIBIN, 0, 0, 0, 0, 0, 0, 0, 0}, "MACH-O", TARGET_MACHO, 1, 0, 2},
{{CL_TYPE_PDF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "PDF", TARGET_PDF, 1, 0, 1},
{{CL_TYPE_SWF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "FLASH", TARGET_FLASH, 1, 0, 1},
{{CL_TYPE_JAVA, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "JAVA", TARGET_JAVA, 1, 0, 1},
{{CL_TYPE_INTERNAL, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "INTERNAL", TARGET_INTERNAL, 1, 0, 1},
{{CL_TYPE_OTHER, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OTHER", TARGET_OTHER, 1, 0, 1}};
// clang-format off

@ -2775,7 +2775,7 @@ int cli_scanpe(cli_ctx *ctx)
char *dest = NULL;
int ndesc;
cl_error_t ret = CL_SUCCESS;
cli_peheader_error_t peheader_ret;
cl_error_t peheader_ret;
int upack = 0;
size_t fsize;
struct cli_bc_ctx *bc_ctx;
@ -2829,34 +2829,39 @@ int cli_scanpe(cli_ctx *ctx)
// successfully on Windows, we need to relax our PE parsing standards so
// that we make sure the executable gets scanned appropriately
#define PE_HDR_PARSE_FAIL_CONSEQUENCE "won't attempt .mdb / .imp / PE-specific BC rule matching or exe unpacking\n"
if (CLI_PEHEADER_RET_BROKEN_PE == peheader_ret) {
switch (peheader_ret) {
case CL_EFORMAT:
ret = CL_SUCCESS;
if (DETECT_BROKEN_PE) {
ret = cli_append_potentially_unwanted(ctx, "Heuristics.Broken.Executable");
}
cli_dbgmsg("cli_scanpe: PE header appears broken - " PE_HDR_PARSE_FAIL_CONSEQUENCE);
cli_dbgmsg("cli_scanpe: PE header appears broken - won't attempt .mdb / .imp / PE-specific BC rule matching or exe unpacking\n");
cli_exe_info_destroy(peinfo);
return ret;
} else if (CLI_PEHEADER_RET_JSON_TIMEOUT == peheader_ret) {
cli_dbgmsg("cli_scanpe: JSON creation timed out - " PE_HDR_PARSE_FAIL_CONSEQUENCE);
case CL_ERROR:
ret = CL_SUCCESS;
cli_dbgmsg("cli_scanpe: An error occurred when parsing the PE header - won't attempt .mdb / .imp / PE-specific BC rule matching or exe unpacking\n");
cli_exe_info_destroy(peinfo);
return CL_ETIMEOUT;
return ret;
} else if (CLI_PEHEADER_RET_GENERIC_ERROR == peheader_ret) {
cli_dbgmsg("cli_scanpe: An error occurred when parsing the PE header - " PE_HDR_PARSE_FAIL_CONSEQUENCE);
case CL_ETIMEOUT:
ret = CL_ETIMEOUT;
cli_dbgmsg("cli_scanpe: JSON creation timed out - won't attempt .mdb / .imp / PE-specific BC rule matching or exe unpacking\n");
cli_exe_info_destroy(peinfo);
return CL_SUCCESS;
return ret;
default:
break;
}
if (!peinfo->is_pe32plus) { /* PE */
if (DCONF & PE_CONF_UPACK)
if (DCONF & PE_CONF_UPACK) {
upack = (EC16(peinfo->file_hdr.SizeOfOptionalHeader) == 0x148);
}
for (i = 0; i < peinfo->nsections; i++) {
}
for (i = 0; i < peinfo->nsections; i++) {
if (peinfo->sections[i].rsz) { /* Don't bother with virtual only sections */
// TODO Regarding the commented out check below:
// This used to check that the section name was NULL, but now that
@ -4428,7 +4433,7 @@ int cli_scanpe(cli_ctx *ctx)
return CL_SUCCESS;
}
cli_peheader_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo)
cl_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo)
{
return cli_peheader(ctx->fmap, peinfo, CLI_PEHEADER_OPT_EXTRACT_VINFO, NULL);
}
@ -4461,10 +4466,9 @@ cli_peheader_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo
* rsz is just set to 0 for it.
* @param ctx The overarching cli_ctx. This is required with certain opts, but
* optional otherwise.
* @return If the PE header is parsed successfully, CLI_PEHEADER_RET_SUCCESS
* is returned. If it seems like the PE is broken,
* CLI_PEHEADER_RET_BROKEN_PE is returned. Otherwise, one of the
* other error codes is returned.
* @return If the PE header is parsed successfully, CL_SUCCESS is returned.
* If it seems like the PE is broken, CL_EFORMAT is returned.
* Otherwise, one of the other error codes is returned.
* The caller MUST destroy peinfo, regardless of what this function
* returns.
*
@ -4491,8 +4495,10 @@ cli_peheader_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo
*
* TODO Same as above but with JSON creation
*/
cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint32_t opts, cli_ctx *ctx)
cl_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint32_t opts, cli_ctx *ctx)
{
cl_error_t ret = CL_ERROR;
uint16_t e_magic; /* DOS signature ("MZ") */
const char *archtype = NULL, *subsystem = NULL;
time_t timestamp;
@ -4514,7 +4520,6 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
int native = 0;
size_t read;
cli_peheader_error_t ret = CLI_PEHEADER_RET_GENERIC_ERROR;
#if HAVE_JSON
int toval = 0;
struct json_object *pe_json = NULL;
@ -4548,7 +4553,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
if (fmap_readn(map, &(peinfo->e_lfanew), peinfo->offset + 58 + sizeof(e_magic), sizeof(peinfo->e_lfanew)) != sizeof(peinfo->e_lfanew)) {
/* truncated header? */
cli_dbgmsg("cli_peheader: Unable to read e_lfanew - truncated header?\n");
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
@ -4743,7 +4748,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
cli_dbgmsg("cli_peheader: Invalid NumberOfSections (0)\n");
}
}
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
@ -4776,14 +4781,14 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
pe_add_heuristic_property(ctx, "BadOptionalHeaderSize");
}
#endif
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
at = peinfo->offset + peinfo->e_lfanew + sizeof(struct pe_image_file_hdr);
if (fmap_readn(map, &(peinfo->pe_opt.opt32), at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
cli_dbgmsg("cli_peheader: Can't read optional file header\n");
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
stored_opt_hdr_size = sizeof(struct pe_image_optional_hdr32);
@ -4802,13 +4807,13 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
pe_add_heuristic_property(ctx, "BadOptionalHeaderSizePE32Plus");
}
#endif
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
if (fmap_readn(map, (void *)(((size_t) & (peinfo->pe_opt.opt64)) + sizeof(struct pe_image_optional_hdr32)), at, OPT_HDR_SIZE_DIFF) != OPT_HDR_SIZE_DIFF) {
cli_dbgmsg("cli_peheader: Can't read additional optional file header bytes\n");
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
@ -4991,7 +4996,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
if (!native && (!salign || (salign % 0x1000))) {
cli_dbgmsg("cli_peheader: Bad section alignment\n");
if (opts & CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS) {
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
}
@ -4999,7 +5004,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
if (!native && (!falign || (falign % 0x200))) {
cli_dbgmsg("cli_peheader: Bad file alignment\n");
if (opts & CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS) {
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
}
@ -5029,7 +5034,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
if (opt_hdr_size < (stored_opt_hdr_size + data_dirs_size)) {
cli_dbgmsg("cli_peheader: SizeOfOptionalHeader too small (doesn't include data dir size)\n");
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
@ -5080,7 +5085,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
read = fmap_readn(map, section_hdrs, at, peinfo->nsections * sizeof(struct pe_image_section_hdr));
if ((read == (size_t)-1) || (read != peinfo->nsections * sizeof(struct pe_image_section_hdr))) {
cli_dbgmsg("cli_peheader: Can't read section header - possibly broken PE file\n");
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
at += sizeof(struct pe_image_section_hdr) * peinfo->nsections;
@ -5126,7 +5131,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
if (opts & CLI_PEHEADER_OPT_REMOVE_MISSING_SECTIONS) {
if (peinfo->nsections == 1) {
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
@ -5169,7 +5174,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
add_section_info(ctx, &peinfo->sections[i]);
if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) {
ret = CLI_PEHEADER_RET_JSON_TIMEOUT;
ret = CL_ETIMEOUT;
goto done;
}
}
@ -5213,7 +5218,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
if (!salign || (section->urva % salign)) { /* Bad section alignment */
cli_dbgmsg("cli_peheader: Broken PE - section's VirtualAddress is misaligned\n");
if (opts & CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS) {
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
}
@ -5222,7 +5227,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
// section? Why the exception for uraw?
if (section->urva >> 31 || section->uvsz >> 31 || (section->rsz && section->uraw >> 31) || peinfo->sections[i].ursz >> 31) {
cli_dbgmsg("cli_peheader: Found PE values with sign bit set\n");
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
@ -5230,7 +5235,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
if (section->urva != peinfo->hdr_size) { /* Bad first section RVA */
cli_dbgmsg("cli_peheader: First section doesn't start immediately after the header\n");
if (opts & CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS) {
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
}
@ -5241,7 +5246,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
if (section->urva - peinfo->sections[i - 1].urva != peinfo->sections[i - 1].vsz) { /* No holes, no overlapping, no virtual disorder */
cli_dbgmsg("cli_peheader: Virtually misplaced section (wrong order, overlapping, non contiguous)\n");
if (opts & CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS) {
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
}
@ -5268,7 +5273,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
// TODO Should this offset include peinfo->offset?
if (!(peinfo->ep = cli_rawaddr(peinfo->vep, peinfo->sections, peinfo->nsections, &err, fsize, peinfo->hdr_size)) && err) {
cli_dbgmsg("cli_peheader: Broken PE file - Can't map EntryPoint to a file offset\n");
ret = CLI_PEHEADER_RET_BROKEN_PE;
ret = CL_EFORMAT;
goto done;
}
@ -5277,7 +5282,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
cli_jsonint(pe_json, "EntryPointOffset", peinfo->ep);
if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) {
ret = CLI_PEHEADER_RET_JSON_TIMEOUT;
ret = CL_ETIMEOUT;
goto done;
}
}
@ -5480,7 +5485,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint
// Do final preperations for peinfo to be passed back
peinfo->is_dll = is_dll;
ret = CLI_PEHEADER_RET_SUCCESS;
ret = CL_SUCCESS;
done:
/* In the fail case, peinfo will get destroyed by the caller */
@ -5546,7 +5551,7 @@ cl_error_t cli_check_auth_header(cli_ctx *ctx, struct cli_exe_info *peinfo)
peinfo = &_peinfo;
cli_exe_info_init(peinfo, 0);
if (cli_peheader(ctx->fmap, peinfo, CLI_PEHEADER_OPT_NONE, NULL) != CLI_PEHEADER_RET_SUCCESS) {
if (CL_SUCCESS != cli_peheader(ctx->fmap, peinfo, CLI_PEHEADER_OPT_NONE, NULL)) {
cli_exe_info_destroy(peinfo);
return CL_EFORMAT;
}
@ -5800,7 +5805,7 @@ cl_error_t cli_genhash_pe(cli_ctx *ctx, unsigned int class, int type, stats_sect
// if so, use that to avoid having to re-parse the header
cli_exe_info_init(peinfo, 0);
if (cli_peheader(ctx->fmap, peinfo, CLI_PEHEADER_OPT_NONE, NULL) != CLI_PEHEADER_RET_SUCCESS) {
if (cli_peheader(ctx->fmap, peinfo, CLI_PEHEADER_OPT_NONE, NULL) != CL_SUCCESS) {
cli_exe_info_destroy(peinfo);
return CL_EFORMAT;
}

@ -87,15 +87,8 @@ enum {
#define CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS 0x8
#define CLI_PEHEADER_OPT_REMOVE_MISSING_SECTIONS 0x10
typedef enum cli_peheader_error {
CLI_PEHEADER_RET_SUCCESS = 0,
CLI_PEHEADER_RET_GENERIC_ERROR = -1,
CLI_PEHEADER_RET_BROKEN_PE = -2,
CLI_PEHEADER_RET_JSON_TIMEOUT = -3
} cli_peheader_error_t;
cli_peheader_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo);
cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint32_t opts, cli_ctx *ctx);
cl_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo);
cl_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint32_t opts, cli_ctx *ctx);
cl_error_t cli_check_auth_header(cli_ctx *ctx, struct cli_exe_info *peinfo);
cl_error_t cli_genhash_pe(cli_ctx *ctx, unsigned int class, int type, stats_section_t *hashes);

@ -127,7 +127,7 @@ char *cli_virname(const char *virname, unsigned int official)
cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, const char *hexsig,
uint8_t sigopts, uint16_t rtype, uint16_t type,
const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options)
const char *offset, const uint32_t *lsigid, unsigned int options)
{
char *hexcpy, *start, *end, *mid;
unsigned int i;
@ -191,7 +191,7 @@ cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, co
return CL_EMALFDB;
}
ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, target, lsigid, options);
ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, lsigid, options);
free(hexcpy);
return ret;
}
@ -203,7 +203,7 @@ cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, co
if (start != end && mid && (*(++mid) == '#' || !strncmp(mid, ">>", 2) || !strncmp(mid, "<<", 2) || !strncmp(mid, "0#", 2))) {
/* TODO byte compare currently does not have support for sigopts, pass through */
ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, target, lsigid, options);
ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, lsigid, options);
free(hexcpy);
return ret;
}
@ -300,7 +300,7 @@ cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, co
}
/* NOCASE sigopt is handled in cli_ac_addsig */
ret = cli_add_content_match_pattern(root, virname, hexovr, sigopts, rtype, type, offset, target, lsigid, options);
ret = cli_add_content_match_pattern(root, virname, hexovr, sigopts, rtype, type, offset, lsigid, options);
free(hexovr);
if (ret != CL_SUCCESS || !(sigopts & ACPATT_OPTION_ASCII)) {
free(hexcpy);
@ -312,7 +312,7 @@ cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, co
}
/* ASCII sigopt; NOCASE sigopt is handled in cli_ac_addsig */
ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, target, lsigid, options);
ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, lsigid, options);
free(hexcpy);
return ret;
}
@ -426,7 +426,7 @@ done:
}
cl_error_t readdb_parse_ldb_subsignature(struct cli_matcher *root, const char *virname, char *hexsig,
const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options,
const char *offset, const uint32_t *lsigid, unsigned int options,
int current_subsig_index, int num_subsigs, struct cli_lsig_tdb *tdb)
{
cl_error_t status = CL_EPARSE;
@ -615,9 +615,9 @@ cl_error_t readdb_parse_ldb_subsignature(struct cli_matcher *root, const char *v
sig = (subtokens_count % 2) ? subtokens[0] : subtokens[1];
if (subsig_opts) {
ret = cli_sigopts_handler(root, virname, sig, subsig_opts, 0, 0, offset, target, lsigid, options);
ret = cli_sigopts_handler(root, virname, sig, subsig_opts, 0, 0, offset, lsigid, options);
} else {
ret = cli_add_content_match_pattern(root, virname, sig, 0, 0, 0, offset, target, lsigid, options);
ret = cli_add_content_match_pattern(root, virname, sig, 0, 0, 0, offset, lsigid, options);
}
if (CL_SUCCESS != ret) {
@ -647,13 +647,12 @@ done:
* @param hexsig The string containing the regex
* @param subsig_opts Content match pattern options. See ACPATT_* macros in matcher-ac.h.
* @param offset The string offset where the pattern starts
* @param target The clamav target type.
* @param lsigid An array of 2 uint32_t numbers: lsig_id and subsig_id. May be NULL for testing.
* @param options Database options. See CL_DB_* macros in clamav.h.
* @return cl_error_t
*/
static cl_error_t readdb_parse_yara_string(struct cli_matcher *root, const char *virname, char *hexsig, uint8_t subsig_opts,
const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options)
const char *offset, const uint32_t *lsigid, unsigned int options)
{
cl_error_t status = CL_EPARSE;
cl_error_t ret;
@ -669,9 +668,9 @@ static cl_error_t readdb_parse_yara_string(struct cli_matcher *root, const char
* Looks like an AC/BM content match subsignature.
*/
if (subsig_opts) {
ret = cli_sigopts_handler(root, virname, hexsig, subsig_opts, 0, 0, offset, target, lsigid, options);
ret = cli_sigopts_handler(root, virname, hexsig, subsig_opts, 0, 0, offset, lsigid, options);
} else {
ret = cli_add_content_match_pattern(root, virname, hexsig, 0, 0, 0, offset, target, lsigid, options);
ret = cli_add_content_match_pattern(root, virname, hexsig, 0, 0, 0, offset, lsigid, options);
}
}
@ -700,14 +699,13 @@ done:
* @param rtype
* @param type
* @param offset The string offset where the pattern starts
* @param target The clamav target type.
* @param lsigid An array of 2 uint32_t numbers: lsig_id and subsig_id. May be NULL for testing.
* @param options Database options. See CL_DB_* macros in clamav.h.
* @return cl_error_t
*/
cl_error_t cli_add_content_match_pattern(struct cli_matcher *root, const char *virname, const char *hexsig,
uint8_t sigopts, uint16_t rtype, uint16_t type,
const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options)
const char *offset, const uint32_t *lsigid, unsigned int options)
{
struct cli_bm_patt *bm_new;
char *pt, *hexcpy, *n, l, r;
@ -747,7 +745,7 @@ cl_error_t cli_add_content_match_pattern(struct cli_matcher *root, const char *v
}
strcat(hexcpy, ++wild);
ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, target, lsigid, options);
ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, lsigid, options);
free(hexcpy);
return ret;
@ -1275,7 +1273,7 @@ static cl_error_t cli_loaddb(FILE *fs, struct cl_engine *engine, unsigned int *s
if (*pt == '=') continue;
if (CL_SUCCESS != (ret = cli_add_content_match_pattern(root, start, pt, 0, 0, 0, "*", 0, NULL, options))) {
if (CL_SUCCESS != (ret = cli_add_content_match_pattern(root, start, pt, 0, 0, 0, "*", NULL, options))) {
cli_dbgmsg("cli_loaddb: cli_add_content_match_pattern failed on line %d\n", line);
ret = CL_EMALFDB;
break;
@ -1584,7 +1582,7 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
const char *sig, *virname, *offset, *pt;
struct cli_matcher *root;
int line = 0, sigs = 0, ret = 0, tokens_count;
unsigned short target;
cli_target_t target;
unsigned int phish = options & CL_DB_PHISHING;
UNUSEDPARAM(dbname);
@ -1661,19 +1659,19 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
ret = CL_EMALFDB;
break;
}
target = (unsigned short)atoi(pt);
target = (cli_target_t)atoi(pt);
if (target >= CLI_MTARGETS) {
cli_dbgmsg("Not supported target type in signature for %s\n", virname);
if (target >= CLI_MTARGETS || target < 0) {
cli_dbgmsg("Not supported target type (%d) in signature for %s\n", (int)target, virname);
continue;
}
root = engine->root[target];
root = engine->root[(size_t)target];
offset = tokens[2];
sig = tokens[3];
if (CL_SUCCESS != (ret = cli_add_content_match_pattern(root, virname, sig, 0, 0, 0, offset, target, NULL, options))) {
if (CL_SUCCESS != (ret = cli_add_content_match_pattern(root, virname, sig, 0, 0, 0, offset, NULL, options))) {
ret = CL_EMALFDB;
break;
}
@ -2018,13 +2016,13 @@ static inline int init_tdb(struct cli_lsig_tdb *tdb, struct cl_engine *engine, c
return CL_BREAK;
}
if ((tdb->icongrp1 || tdb->icongrp2) && tdb->target[0] != 1) {
if ((tdb->icongrp1 || tdb->icongrp2) && tdb->target[0] != TARGET_PE) {
FREE_TDB_P(tdb);
cli_errmsg("init_tdb: IconGroup is only supported in PE (target 1) signatures\n");
return CL_EMALFDB;
}
if ((tdb->ep || tdb->nos) && tdb->target[0] != 1 && tdb->target[0] != 6 && tdb->target[0] != 9) {
if ((tdb->ep || tdb->nos) && tdb->target[0] != TARGET_PE && tdb->target[0] != TARGET_ELF && tdb->target[0] != TARGET_MACHO) {
FREE_TDB_P(tdb);
cli_errmsg("init_tdb: EntryPoint/NumberOfSections is only supported in PE/ELF/Mach-O signatures\n");
return CL_EMALFDB;
@ -2047,7 +2045,6 @@ static cl_error_t load_oneldb(char *buffer, int chkpua, struct cl_engine *engine
struct cli_ac_lsig *lsig = NULL;
char *tokens[LDB_TOKENS + 1];
int i, subsigs, tokens_count;
unsigned short target = 0;
struct cli_matcher *root;
struct cli_lsig_tdb tdb;
uint32_t lsigid[2];
@ -2186,7 +2183,7 @@ static cl_error_t load_oneldb(char *buffer, int chkpua, struct cl_engine *engine
lsigid[1] = i;
// handle each LDB subsig
ret = readdb_parse_ldb_subsignature(root, virname, tokens[3 + i], "*", target, lsigid, options, i, subsigs, &tdb);
ret = readdb_parse_ldb_subsignature(root, virname, tokens[3 + i], "*", lsigid, options, i, subsigs, &tdb);
if (CL_SUCCESS != ret) {
cli_errmsg("cli_loadldb: failed to parse subsignature %d in %s\n", i, virname);
status = ret;
@ -2496,7 +2493,7 @@ static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options,
magictype = atoi(tokens[0]);
if (magictype == 1) { /* A-C */
if (CL_SUCCESS != (ret = cli_add_content_match_pattern(engine->root[0], tokens[3], tokens[2], 0, rtype, type, tokens[1], 0, NULL, options)))
if (CL_SUCCESS != (ret = cli_add_content_match_pattern(engine->root[0], tokens[3], tokens[2], 0, rtype, type, tokens[1], NULL, options)))
break;
} else if ((magictype == 0) || (magictype == 4)) { /* memcmp() */
@ -3802,7 +3799,7 @@ static int yara_hexstr_verify(YR_STRING *string, const char *hexstr, uint32_t *l
}
/* Long Check: Attempt to load hexstr */
if (CL_SUCCESS != (ret = cli_sigopts_handler(engine->test_root, "test-hex", hexstr, 0, 0, 0, "*", 0, lsigid, options))) {
if (CL_SUCCESS != (ret = cli_sigopts_handler(engine->test_root, "test-hex", hexstr, 0, 0, 0, "*", lsigid, options))) {
if (ret == CL_EMALFDB) {
cli_warnmsg("load_oneyara[verify]: recovered from database loading error\n");
/* TODO: if necessary, reset testing matcher if error occurs */
@ -3831,7 +3828,6 @@ static int load_oneyara(YR_RULE *rule, int chkpua, struct cl_engine *engine, uns
uint32_t lsigid[2];
struct cli_matcher *root;
struct cli_ac_lsig **newtable, *lsig, *tsig = NULL;
unsigned short target = 0;
char *logic = NULL, *target_str = NULL;
char *newident = NULL;
/* size_t lsize; */ // only used in commented out code
@ -4312,7 +4308,7 @@ static int load_oneyara(YR_RULE *rule, int chkpua, struct cl_engine *engine, uns
(ytable.table[i]->sigopts & ACPATT_OPTION_ASCII) ? "a" : "");
ret = readdb_parse_yara_string(root, newident, ytable.table[i]->hexstr, ytable.table[i]->sigopts,
ytable.table[i]->offset, target, lsigid, options);
ytable.table[i]->offset, lsigid, options);
if (CL_SUCCESS != ret) {
root->ac_lsigs--;
FREE_TDB(tdb);

@ -140,14 +140,13 @@ char *cli_virname(const char *virname, unsigned int official);
* @param rtype
* @param type
* @param offset
* @param target
* @param lsigid
* @param options
* @return cl_error_t
*/
cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, const char *hexsig,
uint8_t sigopts, uint16_t rtype, uint16_t type,
const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options);
const char *offset, const uint32_t *lsigid, unsigned int options);
/**
* @brief Parse body-based patterns that DO NOT have subsignature modifiers.
@ -162,14 +161,13 @@ cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, co
* @param rtype
* @param type
* @param offset
* @param target
* @param lsigid
* @param options
* @return cl_error_t
*/
cl_error_t cli_add_content_match_pattern(struct cli_matcher *root, const char *virname, const char *hexsig,
uint8_t sigopts, uint16_t rtype, uint16_t type,
const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options);
const char *offset, const uint32_t *lsigid, unsigned int options);
/**
* @brief Parse a subsignature from a logical signature.
@ -188,7 +186,6 @@ cl_error_t cli_add_content_match_pattern(struct cli_matcher *root, const char *v
* @param virname
* @param hexsig
* @param offset
* @param target
* @param lsigid An array of 2 uint32_t numbers: lsig_id and subsig_id. May be NULL for testing.
* @param options
* @param current_subsig_index
@ -197,7 +194,7 @@ cl_error_t cli_add_content_match_pattern(struct cli_matcher *root, const char *v
* @return cl_error_t
*/
cl_error_t readdb_parse_ldb_subsignature(struct cli_matcher *root, const char *virname, char *hexsig,
const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options,
const char *offset, const uint32_t *lsigid, unsigned int options,
int current_subsig_index, int num_subsigs, struct cli_lsig_tdb *tdb);
cl_error_t cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio);

@ -757,7 +757,6 @@ static cl_error_t add_pattern_suffix(void *cbdata, const char *suffix, size_t su
struct regex_matcher *matcher = cbdata;
struct regex_list *regex = NULL;
const struct cli_element *el = NULL;
void *tmp_matcher = NULL; /* save original address if OOM occurs */
cl_error_t ret = CL_SUCCESS;
if (NULL == matcher) {
@ -804,7 +803,6 @@ static cl_error_t add_pattern_suffix(void *cbdata, const char *suffix, size_t su
/* new suffix */
size_t n = matcher->suffix_cnt;
el = cli_hashtab_insert(&matcher->suffix_hash, suffix, suffix_len, (cli_element_data)n);
tmp_matcher = matcher->suffix_regexes; /* save the current value before cli_realloc() */
CLI_REALLOC(matcher->suffix_regexes,
(n + 1) * sizeof(*matcher->suffix_regexes),
cli_errmsg("add_pattern_suffix: Unable to reallocate memory for matcher->suffix_regexes\n");

@ -329,6 +329,7 @@ static struct node *parse_regex(const uint8_t *p, size_t *last)
/* next char is escaped, advance pointer
* and let fall-through handle it */
++*last;
/* fall-through */
default:
right = make_leaf(p[*last]);
v = make_node(concat, v, right);
@ -479,7 +480,7 @@ cl_error_t cli_regex2suffix(const char *pattern, regex_t *preg, suffix_callback
cli_errmsg("cli_regex2suffix: unable to strdup regex.pattern");
rc = REG_ESPACE);
n = parse_regex(pattern, &last);
n = parse_regex((const uint8_t *)pattern, &last);
if (!n) {
rc = REG_ESPACE;
goto done;

@ -195,7 +195,7 @@ static int hashpe(const char *filename, unsigned int class, int type)
goto done;
}
if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", 0, NULL, 0) != CL_SUCCESS) {
if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", NULL, 0) != CL_SUCCESS) {
mprintf(LOGG_ERROR, "hashpe: Can't parse signature\n");
goto done;
}
@ -2096,7 +2096,7 @@ static void matchsig(char *sig, const char *offset, int fd)
goto done;
}
if (readdb_parse_ldb_subsignature(engine->root[0], "test", sig, "*", 0, NULL, 0, 0, 1, &tdb) != CL_SUCCESS) {
if (readdb_parse_ldb_subsignature(engine->root[0], "test", sig, "*", NULL, 0, 0, 1, &tdb) != CL_SUCCESS) {
mprintf(LOGG_ERROR, "matchsig: Can't parse signature\n");
goto done;
}
@ -3313,7 +3313,7 @@ static int dumpcerts(const struct optstruct *opts)
goto done;
}
if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", 0, NULL, 0) != CL_SUCCESS) {
if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", NULL, 0) != CL_SUCCESS) {
mprintf(LOGG_ERROR, "dumpcerts: Can't parse signature\n");
goto done;
}

@ -77,7 +77,7 @@ cli_ctx *convenience_ctx(int fd)
goto done;
}
if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", 0, NULL, 0) != CL_SUCCESS) {
if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", NULL, 0) != CL_SUCCESS) {
printf("convenience_ctx: Can't parse signature\n");
goto done;
}

@ -220,7 +220,7 @@ START_TEST(test_ac_scanbuff)
ck_assert_msg(ret == CL_SUCCESS, "cli_ac_init() failed");
for (i = 0; ac_testdata[i].data; i++) {
ret = cli_add_content_match_pattern(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, 0, "*", 0, NULL, 0);
ret = cli_add_content_match_pattern(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, 0, "*", NULL, 0);
ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed");
}
@ -263,7 +263,7 @@ START_TEST(test_ac_scanbuff_allscan)
ck_assert_msg(ret == CL_SUCCESS, "cli_ac_init() failed");
for (i = 0; ac_testdata[i].data; i++) {
ret = cli_add_content_match_pattern(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, 0, "*", 0, NULL, 0);
ret = cli_add_content_match_pattern(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, 0, "*", NULL, 0);
ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed");
}
@ -315,7 +315,7 @@ START_TEST(test_ac_scanbuff_ex)
ck_assert_msg(ret == CL_SUCCESS, "[ac_ex] cli_ac_init() failed");
for (i = 0; ac_sigopts_testdata[i].data; i++) {
ret = cli_sigopts_handler(root, ac_sigopts_testdata[i].virname, ac_sigopts_testdata[i].hexsig, ac_sigopts_testdata[i].sigopts, 0, 0, ac_sigopts_testdata[i].offset, 0, NULL, 0);
ret = cli_sigopts_handler(root, ac_sigopts_testdata[i].virname, ac_sigopts_testdata[i].hexsig, ac_sigopts_testdata[i].sigopts, 0, 0, ac_sigopts_testdata[i].offset, NULL, 0);
ck_assert_msg(ret == CL_SUCCESS, "[ac_ex] cli_sigopts_handler() failed");
}
@ -358,7 +358,7 @@ START_TEST(test_ac_scanbuff_allscan_ex)
ck_assert_msg(ret == CL_SUCCESS, "[ac_ex] cli_ac_init() failed");
for (i = 0; ac_sigopts_testdata[i].data; i++) {
ret = cli_sigopts_handler(root, ac_sigopts_testdata[i].virname, ac_sigopts_testdata[i].hexsig, ac_sigopts_testdata[i].sigopts, 0, 0, ac_sigopts_testdata[i].offset, 0, NULL, 0);
ret = cli_sigopts_handler(root, ac_sigopts_testdata[i].virname, ac_sigopts_testdata[i].hexsig, ac_sigopts_testdata[i].sigopts, 0, 0, ac_sigopts_testdata[i].offset, NULL, 0);
ck_assert_msg(ret == CL_SUCCESS, "[ac_ex] cli_sigopts_handler() failed");
}
@ -413,11 +413,11 @@ START_TEST(test_bm_scanbuff)
ret = cli_bm_init(root);
ck_assert_msg(ret == CL_SUCCESS, "cli_bm_init() failed");
ret = cli_add_content_match_pattern(root, "Sig1", "deadbabe", 0, 0, 0, "*", 0, NULL, 0);
ret = cli_add_content_match_pattern(root, "Sig1", "deadbabe", 0, 0, 0, "*", NULL, 0);
ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed");
ret = cli_add_content_match_pattern(root, "Sig2", "deadbeef", 0, 0, 0, "*", 0, NULL, 0);
ret = cli_add_content_match_pattern(root, "Sig2", "deadbeef", 0, 0, 0, "*", NULL, 0);
ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed");
ret = cli_add_content_match_pattern(root, "Sig3", "babedead", 0, 0, 0, "*", 0, NULL, 0);
ret = cli_add_content_match_pattern(root, "Sig3", "babedead", 0, 0, 0, "*", NULL, 0);
ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed");
ctx.options->general &= ~CL_SCAN_GENERAL_ALLMATCHES; /* make sure all-match is disabled */
@ -442,11 +442,11 @@ START_TEST(test_bm_scanbuff_allscan)
ret = cli_bm_init(root);
ck_assert_msg(ret == CL_SUCCESS, "cli_bm_init() failed");
ret = cli_add_content_match_pattern(root, "Sig1", "deadbabe", 0, 0, 0, "*", 0, NULL, 0);
ret = cli_add_content_match_pattern(root, "Sig1", "deadbabe", 0, 0, 0, "*", NULL, 0);
ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed");
ret = cli_add_content_match_pattern(root, "Sig2", "deadbeef", 0, 0, 0, "*", 0, NULL, 0);
ret = cli_add_content_match_pattern(root, "Sig2", "deadbeef", 0, 0, 0, "*", NULL, 0);
ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed");
ret = cli_add_content_match_pattern(root, "Sig3", "babedead", 0, 0, 0, "*", 0, NULL, 0);
ret = cli_add_content_match_pattern(root, "Sig3", "babedead", 0, 0, 0, "*", NULL, 0);
ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed");
ctx.options->general |= CL_SCAN_GENERAL_ALLMATCHES; /* enable all-match */
@ -484,7 +484,7 @@ START_TEST(test_pcre_scanbuff)
strncat(hexsig, PCRE_BYPASS, hexlen);
strncat(hexsig, pcre_testdata[i].hexsig, hexlen);
ret = readdb_parse_ldb_subsignature(root, pcre_testdata[i].virname, hexsig, pcre_testdata[i].offset, 0, NULL, 0, 0, 0, NULL);
ret = readdb_parse_ldb_subsignature(root, pcre_testdata[i].virname, hexsig, pcre_testdata[i].offset, NULL, 0, 0, 0, NULL);
ck_assert_msg(ret == CL_SUCCESS, "[pcre] readdb_parse_ldb_subsignature failed");
free(hexsig);
}
@ -538,7 +538,7 @@ START_TEST(test_pcre_scanbuff_allscan)
strncat(hexsig, PCRE_BYPASS, hexlen);
strncat(hexsig, pcre_testdata[i].hexsig, hexlen);
ret = readdb_parse_ldb_subsignature(root, pcre_testdata[i].virname, hexsig, pcre_testdata[i].offset, 0, NULL, 0, 0, 1, NULL);
ret = readdb_parse_ldb_subsignature(root, pcre_testdata[i].virname, hexsig, pcre_testdata[i].offset, NULL, 0, 0, 1, NULL);
ck_assert_msg(ret == CL_SUCCESS, "[pcre] readdb_parse_ldb_subsignature failed");
free(hexsig);
}

Loading…
Cancel
Save