scanners to fmap - hackish

peheader to fmap
lacks review + elf + macho
0.96
aCaB 16 years ago
parent a5241d274c
commit 048d76777f
  1. 12
      libclamav/filetypes.c
  2. 3
      libclamav/filetypes.h
  3. 16
      libclamav/matcher-ac.c
  4. 3
      libclamav/matcher-ac.h
  5. 6
      libclamav/matcher-bm.c
  6. 3
      libclamav/matcher-bm.h
  7. 225
      libclamav/matcher.c
  8. 4
      libclamav/matcher.h
  9. 42
      libclamav/pe.c
  10. 3
      libclamav/pe.h
  11. 5
      libclamav/scanners.c

@ -143,10 +143,10 @@ cli_file_t cli_filetype(const unsigned char *buf, size_t buflen, const struct cl
int is_tar(unsigned char *buf, unsigned int nbytes);
cli_file_t cli_filetype2(int desc, const struct cl_engine *engine)
cli_file_t cli_filetype2(struct F_MAP *map, const struct cl_engine *engine)
{
unsigned char buff[MAGIC_BUFFER_SIZE + 1], *decoded;
int bread, sret;
unsigned char *buff, *decoded;
int bread = MIN(map->len, MAGIC_BUFFER_SIZE), sret;
cli_file_t ret = CL_TYPE_BINARY_DATA;
struct cli_matcher *root;
struct cli_ac_data mdata;
@ -157,11 +157,9 @@ cli_file_t cli_filetype2(int desc, const struct cl_engine *engine)
return CL_TYPE_ERROR;
}
memset(buff, 0, sizeof(buff));
bread = cli_readn(desc, buff, MAGIC_BUFFER_SIZE);
if(bread == -1)
buff = fmap_need_off_once(map, 0, bread);
if(!buff)
return CL_TYPE_ERROR;
buff[bread] = 0;
ret = cli_filetype(buff, bread, engine);

@ -25,6 +25,7 @@
#include "clamav.h"
#include "cltypes.h"
#include "fmap.h"
#define MAGIC_BUFFER_SIZE 1024
#define CL_TYPENO 500
@ -105,7 +106,7 @@ struct cli_matched_type {
cli_file_t cli_ftcode(const char *name);
void cli_ftfree(const struct cl_engine *engine);
cli_file_t cli_filetype(const unsigned char *buf, size_t buflen, const struct cl_engine *engine);
cli_file_t cli_filetype2(int desc, const struct cl_engine *engine);
cli_file_t cli_filetype2(struct F_MAP *map, const struct cl_engine *engine);
int cli_addtypesigs(struct cl_engine *engine);
#endif

@ -830,7 +830,7 @@ int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs,
return CL_SUCCESS;
}
int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, int fd)
int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, struct F_MAP *map)
{
int ret;
unsigned int i;
@ -838,20 +838,16 @@ int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, int
struct cli_target_info info;
struct stat sb;
if(fd != -1) {
if(map) {
memset(&info, 0, sizeof(info));
if(fstat(fd, &sb) == -1) {
cli_errmsg("cli_ac_caloff: fstat(%d) failed\n", fd);
return CL_ESTAT;
}
info.fsize = sb.st_size;
info.fsize = map->len;
}
for(i = 0; i < root->ac_reloff_num; i++) {
patt = root->ac_reloff[i];
if(fd == -1) {
if(!map) {
data->offset[patt->offset_min] = CLI_OFF_NONE;
} else if((ret = cli_caloff(NULL, &info, fd, root->type, patt->offdata, &data->offset[patt->offset_min], &data->offset[patt->offset_max]))) {
} else if((ret = cli_caloff(NULL, &info, map, root->type, patt->offdata, &data->offset[patt->offset_min], &data->offset[patt->offset_max]))) {
cli_errmsg("cli_ac_caloff: Can't calculate relative offset in signature for %s\n", patt->virname);
if(info.exeinfo.section)
free(info.exeinfo.section);
@ -860,7 +856,7 @@ int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, int
data->offset[patt->offset_min] = CLI_OFF_NONE;
}
}
if(fd != -1 && info.exeinfo.section)
if(map && info.exeinfo.section)
free(info.exeinfo.section);
return CL_SUCCESS;

@ -25,6 +25,7 @@
#include "filetypes.h"
#include "cltypes.h"
#include "fmap.h"
#define AC_CH_MAXDIST 32
@ -86,7 +87,7 @@ void cli_ac_freedata(struct cli_ac_data *data);
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);
int cli_ac_buildtrie(struct cli_matcher *root);
int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth);
int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, int fd);
int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, struct F_MAP *map);
void cli_ac_free(struct cli_matcher *root);
int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, uint32_t sigid, uint16_t parts, uint16_t partno, uint16_t rtype, uint16_t type, uint32_t mindist, uint32_t maxdist, const char *offset, const uint32_t *lsigid, unsigned int options);

@ -51,7 +51,7 @@ int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const
return CL_EMALFDB;
}
if((ret = cli_caloff(offset, NULL, -1, root->type, pattern->offdata, &pattern->offset_min, &pattern->offset_max))) {
if((ret = cli_caloff(offset, NULL, NULL, root->type, pattern->offdata, &pattern->offset_min, &pattern->offset_max))) {
cli_errmsg("cli_bm_addpatt: Can't calculate offset for signature %s\n", pattern->virname);
return ret;
}
@ -156,7 +156,7 @@ void cli_bm_free(struct cli_matcher *root)
}
}
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, int fd)
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, struct F_MAP *map)
{
uint32_t i, j, off, off_min, off_max;
uint8_t found, pchain, shift;
@ -229,7 +229,7 @@ int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
if(found && p->length + p->prefix_length == j) {
if(p->offset_min != CLI_OFF_ANY) {
if(p->offdata[0] != CLI_OFF_ABSOLUTE) {
ret = cli_caloff(NULL, &info, fd, root->type, p->offdata, &off_min, &off_max);
ret = cli_caloff(NULL, &info, map, root->type, p->offdata, &off_min, &off_max);
if(ret != CL_SUCCESS) {
cli_errmsg("cli_bm_scanbuff: Can't calculate relative offset in signature for %s\n", p->virname);
if(info.exeinfo.section)

@ -24,6 +24,7 @@
#include "matcher.h"
#include "filetypes.h"
#include "cltypes.h"
#include "fmap.h"
struct cli_bm_patt {
unsigned char *pattern, *prefix;
@ -37,7 +38,7 @@ struct cli_bm_patt {
int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const char *offset);
int cli_bm_init(struct cli_matcher *root);
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, int fd);
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, struct F_MAP *map);
void cli_bm_free(struct cli_matcher *root);
#endif

@ -45,6 +45,7 @@
#include "cltypes.h"
#include "default.h"
#include "macho.h"
#include "fmap.h"
int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata)
{
@ -76,7 +77,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
return ret;
if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, -1)) != CL_VIRUS)
if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, NULL)) != CL_VIRUS)
ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
if(!acdata)
@ -89,7 +90,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
return ret;
if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, -1)) != CL_VIRUS)
if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, NULL)) != CL_VIRUS)
ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
if(!acdata)
@ -104,9 +105,9 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
* offdata[2]: max shift
* offdata[3]: section number
*/
int cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max)
int cli_caloff(const char *offstr, struct cli_target_info *info, struct F_MAP *map, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max)
{
int (*einfo)(int, struct cli_exe_info *) = NULL;
int (*einfo)(struct F_MAP *, struct cli_exe_info *) = NULL;
char offcpy[65];
unsigned int n, val;
char *pt;
@ -206,14 +207,8 @@ int cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigne
}
if((offdata[0] == CLI_OFF_EOF_MINUS)) {
if(!info->fsize) {
if(fstat(fd, &sb) == -1) {
cli_errmsg("cli_caloff: fstat(%d) failed\n", fd);
return CL_ESTAT;
}
info->fsize = sb.st_size;
}
if(!info->fsize)
info->fsize = map->len;
} else if(!info->status) {
if(target == 1)
einfo = cli_peheader;
@ -227,20 +222,12 @@ int cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigne
return CL_EMALFDB;
}
if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
cli_errmsg("cli_caloff: lseek(%d) failed\n", fd);
return CL_ESEEK;
}
lseek(fd, 0, SEEK_SET);
if(einfo(fd, &info->exeinfo)) {
if(einfo(map, &info->exeinfo)) {
/* einfo *may* fail */
lseek(fd, pos, SEEK_SET);
info->status = -1;
*offset_min = *offset_max = 0;
return CL_SUCCESS;
}
lseek(fd, pos, SEEK_SET);
info->status = 1;
}
@ -303,7 +290,7 @@ int cli_checkfp(int fd, cli_ctx *ctx)
return 0;
}
if(cli_bm_scanbuff(digest, 16, &virname, ctx->engine->md5_fp, 0, -1) == CL_VIRUS) {
if(cli_bm_scanbuff(digest, 16, &virname, ctx->engine->md5_fp, 0, NULL) == CL_VIRUS) {
cli_dbgmsg("cli_checkfp(): Found false positive detection (fp sig: %s)\n", virname);
free(digest);
lseek(fd, pos, SEEK_SET);
@ -318,185 +305,15 @@ int cli_checkfp(int fd, cli_ctx *ctx)
int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode)
{
unsigned char *buffer, *buff, *endbl, *upt;
int ret = CL_CLEAN, type = CL_CLEAN, bytes;
unsigned int i, evalcnt;
uint32_t buffersize, length, maxpatlen, shift = 0, offset = 0;
uint64_t evalids;
struct cli_ac_data gdata, tdata;
cli_md5_ctx md5ctx;
unsigned char digest[16];
struct cli_matcher *groot = NULL, *troot = NULL;
if(!ctx->engine) {
cli_errmsg("cli_scandesc: engine == NULL\n");
return CL_ENULLARG;
}
if(!ftonly)
groot = ctx->engine->root[0]; /* generic signatures */
if(ftype) {
for(i = 1; i < CLI_MTARGETS; i++) {
if(cli_mtargets[i].target == ftype) {
troot = ctx->engine->root[i];
break;
}
}
}
if(ftonly) {
if(!troot)
return CL_CLEAN;
maxpatlen = troot->maxpatlen;
} else {
if(troot)
maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen);
else
maxpatlen = groot->maxpatlen;
}
/* prepare the buffer */
buffersize = maxpatlen + SCANBUFF;
if(!(buffer = (unsigned char *) cli_calloc(buffersize, sizeof(unsigned char)))) {
cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%u)\n", buffersize);
return CL_EMEM;
}
if(!ftonly)
if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, desc)))
return ret;
if(troot) {
if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, desc))) {
if(!ftonly)
cli_ac_freedata(&gdata);
return ret;
}
}
if(!ftonly && ctx->engine->md5_hdb)
cli_md5_init(&md5ctx);
buff = buffer;
buff += maxpatlen; /* pointer to read data block */
endbl = buff + SCANBUFF - maxpatlen; /* pointer to the last block
* length of maxpatlen
*/
upt = buff;
while((bytes = cli_readn(desc, buff + shift, SCANBUFF - shift)) > 0) {
if(ctx->scanned)
*ctx->scanned += bytes / CL_COUNT_PRECISION;
length = shift + bytes;
if(upt == buffer)
length += maxpatlen;
if(troot) {
if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, troot, offset, desc)) != CL_VIRUS)
ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, ftoffset, acmode, NULL);
if(ret == CL_VIRUS) {
free(buffer);
if(!ftonly)
cli_ac_freedata(&gdata);
cli_ac_freedata(&tdata);
if(cli_checkfp(desc, ctx))
return CL_CLEAN;
else
return CL_VIRUS;
}
}
if(!ftonly) {
if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, groot, offset, desc)) != CL_VIRUS)
ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, ftoffset, acmode, NULL);
if(ret == CL_VIRUS) {
free(buffer);
cli_ac_freedata(&gdata);
if(troot)
cli_ac_freedata(&tdata);
if(cli_checkfp(desc, ctx))
return CL_CLEAN;
else
return CL_VIRUS;
} else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
if(ret > type)
type = ret;
}
if(ctx->engine->md5_hdb)
cli_md5_update(&md5ctx, buff + shift, bytes);
}
if(bytes + shift == SCANBUFF) {
memmove(buffer, endbl, maxpatlen);
offset += SCANBUFF;
if(upt == buff) {
upt = buffer;
offset -= maxpatlen;
}
shift = 0;
} else {
shift += bytes;
}
}
free(buffer);
if(troot) {
for(i = 0; i < troot->ac_lsigs; i++) {
evalcnt = 0;
evalids = 0;
if(cli_ac_chklsig(troot->ac_lsigtable[i]->logic, troot->ac_lsigtable[i]->logic + strlen(troot->ac_lsigtable[i]->logic), tdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) {
if(ctx->virname)
*ctx->virname = troot->ac_lsigtable[i]->virname;
ret = CL_VIRUS;
break;
}
}
cli_ac_freedata(&tdata);
}
if(groot) {
if(ret != CL_VIRUS) for(i = 0; i < groot->ac_lsigs; i++) {
evalcnt = 0;
evalids = 0;
if(cli_ac_chklsig(groot->ac_lsigtable[i]->logic, groot->ac_lsigtable[i]->logic + strlen(groot->ac_lsigtable[i]->logic), gdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) {
if(ctx->virname)
*ctx->virname = groot->ac_lsigtable[i]->virname;
ret = CL_VIRUS;
break;
}
}
cli_ac_freedata(&gdata);
}
if(ret == CL_VIRUS) {
lseek(desc, 0, SEEK_SET);
if(cli_checkfp(desc, ctx))
return CL_CLEAN;
else
return CL_VIRUS;
}
int ret = CL_EMEM;
struct F_MAP *map = *ctx->fmap;
if(!ftonly && ctx->engine->md5_hdb) {
cli_md5_final(digest, &md5ctx);
if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, -1) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, -1) != CL_VIRUS))
return CL_VIRUS;
if(!(*ctx->fmap = fmap(desc, 0, 0))) {
ret = cli_fmap_scandesc(ctx, ftype, ftonly, ftoffset, acmode);
fmunmap(map);
}
return (acmode & AC_SCAN_FT) ? type : CL_CLEAN;
*ctx->fmap = map;
return ret;
}
@ -543,11 +360,11 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
}
if(!ftonly)
if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, map->fd)))
if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, map)))
return ret;
if(troot) {
if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, map->fd))) {
if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, map))) {
if(!ftonly)
cli_ac_freedata(&gdata);
return ret;
@ -566,7 +383,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
*ctx->scanned += bytes / CL_COUNT_PRECISION;
if(troot) {
if(troot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, troot, offset, map->fd)) != CL_VIRUS)
if(troot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, troot, offset, map)) != CL_VIRUS)
ret = cli_ac_scanbuff(buff, bytes, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, ftoffset, acmode, NULL);
if(ret == CL_VIRUS) {
@ -582,7 +399,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
}
if(!ftonly) {
if(groot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, groot, offset, map->fd)) != CL_VIRUS)
if(groot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, groot, offset, map)) != CL_VIRUS)
ret = cli_ac_scanbuff(buff, bytes, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, ftoffset, acmode, NULL);
if(ret == CL_VIRUS) {
@ -645,7 +462,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
if(!ftonly && ctx->engine->md5_hdb) {
cli_md5_final(digest, &md5ctx);
if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, -1) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, -1) != CL_VIRUS))
if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, NULL) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, NULL) != CL_VIRUS))
return CL_VIRUS;
}

@ -33,7 +33,7 @@
#include "matcher-ac.h"
#include "matcher-bm.h"
#include "hashtab.h"
#include "fmap.h"
#include "mpool.h"
#define CLI_MATCH_WILDCARD 0xff00
@ -142,7 +142,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode);
int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode);
int cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max);
int cli_caloff(const char *offstr, struct cli_target_info *info, struct F_MAP *map, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max);
int cli_checkfp(int fd, cli_ctx *ctx);

@ -38,7 +38,6 @@
#include "cltypes.h"
#include "clamav.h"
#include "others.h"
#include "fmap.h"
#include "pe.h"
#include "petite.h"
#include "fsg.h"
@ -985,7 +984,6 @@ int cli_scanpe(cli_ctx *ctx)
CLI_UNPTEMP("DISASM",(exe_sections,0));
disasmbuf((unsigned char*)epbuff, epsize, ndesc);
lseek(ndesc, 0, SEEK_SET);
ret = cli_scandesc(ndesc, ctx, CL_TYPE_PE_DISASM, 1, NULL, AC_SCAN_VIR);
close(ndesc);
CLI_TMPUNLK();
@ -2153,7 +2151,7 @@ int cli_scanpe(cli_ctx *ctx)
return CL_CLEAN;
}
int cli_peheader(int desc, struct cli_exe_info *peinfo)
int cli_peheader(struct F_MAP *map, struct cli_exe_info *peinfo)
{
uint16_t e_magic; /* DOS signature ("MZ") */
uint32_t e_lfanew; /* address of new exe header */
@ -2171,19 +2169,14 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
unsigned int err, pe_plus = 0;
uint32_t valign, falign, hdr_size;
size_t fsize;
ssize_t at;
cli_dbgmsg("in cli_peheader\n");
if(fstat(desc, &sb) == -1) {
cli_dbgmsg("fstat failed\n");
return -1;
}
fsize = sb.st_size - peinfo->offset;
if(cli_readn(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
fsize = map->len - peinfo->offset;
if(fmap_readn(map, &e_magic, peinfo->offset, sizeof(e_magic)) != sizeof(e_magic)) {
cli_dbgmsg("Can't read DOS signature\n");
return -1;
return CL_CLEAN;
}
if(EC16(e_magic) != IMAGE_DOS_SIGNATURE && EC16(e_magic) != IMAGE_DOS_SIGNATURE_OLD) {
@ -2191,10 +2184,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
return -1;
}
lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */
if(cli_readn(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) {
cli_dbgmsg("Can't read new header address\n");
if(fmap_readn(map, &e_lfanew, peinfo->offset + 58 + sizeof(e_magic), sizeof(e_lfanew)) != sizeof(e_lfanew)) {
/* truncated header? */
return -1;
}
@ -2205,13 +2195,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
return -1;
}
if(lseek(desc, peinfo->offset + e_lfanew, SEEK_SET) < 0) {
/* probably not a PE file */
cli_dbgmsg("Can't lseek to e_lfanew\n");
return -1;
}
if(cli_readn(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
if(fmap_readn(map, &file_hdr, peinfo->offset + e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
/* bad information in e_lfanew - probably not a PE file */
cli_dbgmsg("Can't read file header\n");
return -1;
@ -2229,26 +2213,29 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
return -1;
}
if(cli_readn(desc, &optional_hdr32, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
at = peinfo->offset + e_lfanew + sizeof(struct pe_image_file_hdr);
if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
cli_dbgmsg("Can't read optional file header\n");
return -1;
}
at += sizeof(struct pe_image_optional_hdr32);
if(EC16(optional_hdr64.Magic)==PE32P_SIGNATURE) { /* PE+ */
if(EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr64)) {
cli_dbgmsg("Incorrect SizeOfOptionalHeader for PE32+\n");
return -1;
}
if(cli_readn(desc, &optional_hdr32 + 1, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
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)) {
cli_dbgmsg("Can't read optional file header\n");
return -1;
}
at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
hdr_size = EC32(optional_hdr64.SizeOfHeaders);
pe_plus=1;
} else { /* PE */
if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) {
/* Seek to the end of the long header */
lseek(desc, (EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32)), SEEK_CUR);
at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32);
}
hdr_size = EC32(optional_hdr32.SizeOfHeaders);
}
@ -2274,7 +2261,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
return -1;
}
if(cli_readn(desc, section_hdr, peinfo->nsections * sizeof(struct pe_image_section_hdr)) != peinfo->nsections * sizeof(struct pe_image_section_hdr)) {
if(fmap_readn(map, section_hdr, at, peinfo->nsections * sizeof(struct pe_image_section_hdr)) != peinfo->nsections * sizeof(struct pe_image_section_hdr)) {
cli_dbgmsg("Can't read section header\n");
cli_dbgmsg("Possibly broken PE file\n");
free(section_hdr);
@ -2282,6 +2269,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
peinfo->section = NULL;
return -1;
}
at += sizeof(struct pe_image_section_hdr)*peinfo->nsections;
for(i = 0; falign!=0x200 && i<peinfo->nsections; i++) {
/* file alignment fallback mode - blah */

@ -25,6 +25,7 @@
#include "execs.h"
#include "others.h"
#include "cltypes.h"
#include "fmap.h"
struct pe_image_file_hdr {
uint32_t Magic;
@ -130,6 +131,6 @@ struct pe_image_section_hdr {
int cli_scanpe(cli_ctx *ctx);
int cli_peheader(int desc, struct cli_exe_info *peinfo);
int cli_peheader(struct F_MAP *map, struct cli_exe_info *peinfo);
#endif

@ -1791,7 +1791,7 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_
memset(&peinfo, 0, sizeof(struct cli_exe_info));
peinfo.offset = fpt->offset;
lseek(map->fd, fpt->offset, SEEK_SET);
if(cli_peheader(map->fd, &peinfo) == 0) {
if(cli_peheader(map, &peinfo) == 0) {
cli_dbgmsg("*** Detected embedded PE file at %u ***\n", (unsigned int) fpt->offset);
if(peinfo.section)
free(peinfo.section);
@ -1904,8 +1904,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
return ret;
}
lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
type = cli_filetype2(desc, ctx->engine); /* FIXMEFMAP: port to fmap */
type = cli_filetype2(*ctx->fmap, ctx->engine); /* FIXMEFMAP: port to fmap */
if(type == CL_TYPE_ERROR) {
cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
fmunmap(*ctx->fmap);

Loading…
Cancel
Save