macho to fmap

0.96
aCaB 16 years ago
parent ceb05b6b3c
commit f4363389c5
  1. 62
      libclamav/macho.c
  2. 4
      libclamav/macho.h
  3. 4
      libclamav/scanners.c

@ -176,7 +176,7 @@ struct macho_fat_arch
if(DETECT_BROKEN) { \
if(ctx->virname) \
*ctx->virname = "Broken.Executable"; \
return cli_checkfp(fd, ctx) ? CL_CLEAN : CL_VIRUS; \
return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS; \
} \
return CL_EFORMAT
@ -201,7 +201,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(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
{
struct macho_hdr hdr;
struct macho_load_cmd load_cmd;
@ -213,14 +213,17 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
unsigned int arch = 0, ep = 0, err;
struct cli_exe_section *sections = NULL;
char name[16];
struct F_MAP *map = *ctx->fmap;
ssize_t at;
if(fileinfo)
matcher = 1;
if(read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
if(fmap_readn(map, &hdr, 0, sizeof(hdr)) != sizeof(hdr)) {
cli_dbgmsg("cli_scanmacho: Can't read header\n");
return matcher ? -1 : CL_EFORMAT;
}
at = sizeof(hdr);
if(hdr.magic == 0xfeedface) {
conv = 0;
@ -311,7 +314,7 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
}
if(m64)
lseek(fd, 4, SEEK_CUR);
at += 4;
hdr.ncmds = EC32(hdr.ncmds, conv);
if(!hdr.ncmds || hdr.ncmds > 1024) {
@ -320,11 +323,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
}
for(i = 0; i < hdr.ncmds; i++) {
if(read(fd, &load_cmd, sizeof(load_cmd)) != sizeof(load_cmd)) {
if(fmap_readn(map, &load_cmd, at, sizeof(load_cmd)) != sizeof(load_cmd)) {
cli_dbgmsg("cli_scanmacho: Can't read load command\n");
free(sections);
RETURN_BROKEN;
}
at += sizeof(load_cmd);
/*
if((m64 && EC32(load_cmd.cmdsize, conv) % 8) || (!m64 && EC32(load_cmd.cmdsize, conv) % 4)) {
cli_dbgmsg("cli_scanmacho: Invalid command size (%u)\n", EC32(load_cmd.cmdsize, conv));
@ -335,19 +339,21 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
load_cmd.cmd = EC32(load_cmd.cmd, conv);
if((m64 && load_cmd.cmd == 0x19) || (!m64 && load_cmd.cmd == 0x01)) { /* LC_SEGMENT */
if(m64) {
if(read(fd, &segment_cmd64, sizeof(segment_cmd64)) != sizeof(segment_cmd64)) {
if(fmap_readn(map, &segment_cmd64, at, sizeof(segment_cmd64)) != sizeof(segment_cmd64)) {
cli_dbgmsg("cli_scanmacho: Can't read segment command\n");
free(sections);
RETURN_BROKEN;
}
at += sizeof(segment_cmd64);
nsects = EC32(segment_cmd64.nsects, conv);
strncpy(name, segment_cmd64.segname, 16);
} else {
if(read(fd, &segment_cmd, sizeof(segment_cmd)) != sizeof(segment_cmd)) {
if(fmap_readn(map, &segment_cmd, at, sizeof(segment_cmd)) != sizeof(segment_cmd)) {
cli_dbgmsg("cli_scanmacho: Can't read segment command\n");
free(sections);
RETURN_BROKEN;
}
at += sizeof(segment_cmd);
nsects = EC32(segment_cmd.nsects, conv);
strncpy(name, segment_cmd.segname, 16);
}
@ -374,11 +380,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
for(j = 0; j < nsects; j++) {
if(m64) {
if(read(fd, &section64, sizeof(section64)) != sizeof(section64)) {
if(fmap_readn(map, &section64, at, sizeof(section64)) != sizeof(section64)) {
cli_dbgmsg("cli_scanmacho: Can't read section\n");
free(sections);
RETURN_BROKEN;
}
at += sizeof(section64);
sections[sect].rva = EC64(section64.addr, conv);
sections[sect].vsz = EC64(section64.size, conv);
sections[sect].raw = EC32(section64.offset, conv);
@ -386,11 +393,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
sections[sect].rsz = sections[sect].vsz + (section64.align - (sections[sect].vsz % section64.align)) % section64.align; /* most likely we can assume it's the same as .vsz */
strncpy(name, section64.sectname, 16);
} else {
if(read(fd, &section, sizeof(section)) != sizeof(section)) {
if(fmap_readn(map, &section, at, sizeof(section)) != sizeof(section)) {
cli_dbgmsg("cli_scanmacho: Can't read section\n");
free(sections);
RETURN_BROKEN;
}
at += sizeof(section);
sections[sect].rva = EC32(section.addr, conv);
sections[sect].vsz = EC32(section.size, conv);
sections[sect].raw = EC32(section.offset, conv);
@ -414,17 +422,18 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
cli_dbgmsg("MACHO: ------------------\n");
} else if(arch && (load_cmd.cmd == 0x4 || load_cmd.cmd == 0x5)) { /* LC_(UNIX)THREAD */
lseek(fd, 8, SEEK_CUR);
at += 8;
switch(arch) {
case 1: /* x86 */
{
struct macho_thread_state_x86 thread_state_x86;
if(read(fd, &thread_state_x86, sizeof(thread_state_x86)) != sizeof(thread_state_x86)) {
if(fmap_readn(map, &thread_state_x86, at, sizeof(thread_state_x86)) != sizeof(thread_state_x86)) {
cli_dbgmsg("cli_scanmacho: Can't read thread_state_x86\n");
free(sections);
RETURN_BROKEN;
}
at += sizeof(thread_state_x86);
break;
}
@ -432,11 +441,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
{
struct macho_thread_state_ppc thread_state_ppc;
if(read(fd, &thread_state_ppc, sizeof(thread_state_ppc)) != sizeof(thread_state_ppc)) {
if(fmap_readn(map, &thread_state_ppc, at, sizeof(thread_state_ppc)) != sizeof(thread_state_ppc)) {
cli_dbgmsg("cli_scanmacho: Can't read thread_state_ppc\n");
free(sections);
RETURN_BROKEN;
}
at += sizeof(thread_state_ppc);
ep = EC32(thread_state_ppc.srr0, conv);
break;
}
@ -445,11 +455,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
{
struct macho_thread_state_ppc64 thread_state_ppc64;
if(read(fd, &thread_state_ppc64, sizeof(thread_state_ppc64)) != sizeof(thread_state_ppc64)) {
if(fmap_readn(map, &thread_state_ppc64, at, sizeof(thread_state_ppc64)) != sizeof(thread_state_ppc64)) {
cli_dbgmsg("cli_scanmacho: Can't read thread_state_ppc64\n");
free(sections);
RETURN_BROKEN;
}
at += sizeof(thread_state_ppc64);
ep = EC64(thread_state_ppc64.srr0, conv);
break;
}
@ -460,7 +471,7 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
}
} else {
if(EC32(load_cmd.cmdsize, conv) > sizeof(load_cmd))
lseek(fd, EC32(load_cmd.cmdsize, conv) - sizeof(load_cmd), SEEK_CUR);
at += EC32(load_cmd.cmdsize, conv) - sizeof(load_cmd);
}
}
@ -492,10 +503,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
int cli_machoheader(struct F_MAP *map, struct cli_exe_info *fileinfo)
{
return cli_scanmacho(map->fd, NULL, fileinfo);
cli_ctx ctx;
ctx.fmap = &map;
return cli_scanmacho(&ctx, fileinfo);
}
int cli_scanmacho_unibin(int fd, cli_ctx *ctx)
int cli_scanmacho_unibin(cli_ctx *ctx)
{
struct macho_fat_header fat_header;
struct macho_fat_arch fat_arch;
@ -503,16 +516,14 @@ int cli_scanmacho_unibin(int fd, cli_ctx *ctx)
int ret = CL_CLEAN;
struct stat sb;
off_t pos;
struct F_MAP *map = *ctx->fmap;
ssize_t at;
if(fstat(fd, &sb) == -1) {
cli_dbgmsg("cli_scanmacho_unibin: fstat failed for fd %d\n", fd);
return CL_ESTAT;
}
if(read(fd, &fat_header, sizeof(fat_header)) != sizeof(fat_header)) {
if(fmap_readn(map, &fat_header, 0, sizeof(fat_header)) != sizeof(fat_header)) {
cli_dbgmsg("cli_scanmacho_unibin: Can't read fat_header\n");
return CL_EFORMAT;
}
at = sizeof(fat_header);
if(fat_header.magic == 0xcafebabe) {
conv = 0;
@ -533,18 +544,17 @@ int cli_scanmacho_unibin(int fd, cli_ctx *ctx)
}
cli_dbgmsg("UNIBIN: Number of architectures: %u\n", (unsigned int) fat_header.nfats);
for(i = 0; i < fat_header.nfats; i++) {
if(read(fd, &fat_arch, sizeof(fat_arch)) != sizeof(fat_arch)) {
if(fmap_readn(map, &fat_arch, at, sizeof(fat_arch)) != sizeof(fat_arch)) {
cli_dbgmsg("cli_scanmacho_unibin: Can't read fat_arch\n");
RETURN_BROKEN;
}
pos = lseek(fd, 0, SEEK_CUR);
at += sizeof(fat_arch);
fat_arch.offset = EC32(fat_arch.offset, conv);
fat_arch.size = EC32(fat_arch.size, conv);
cli_dbgmsg("UNIBIN: Binary %u of %u\n", i + 1, fat_header.nfats);
cli_dbgmsg("UNIBIN: File offset: %u\n", fat_arch.offset);
cli_dbgmsg("UNIBIN: File size: %u\n", fat_arch.size);
ret = cli_dumpscan(fd, fat_arch.offset, fat_arch.size, ctx);
lseek(fd, pos, SEEK_SET);
ret = cli_dumpscan(map->fd, fat_arch.offset, fat_arch.size, ctx);
if(ret == CL_VIRUS)
break;
}

@ -25,8 +25,8 @@
#include "execs.h"
#include "fmap.h"
int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo);
int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo);
int cli_machoheader(struct F_MAP *map, struct cli_exe_info *fileinfo);
int cli_scanmacho_unibin(int fd, cli_ctx *ctx);
int cli_scanmacho_unibin(cli_ctx *ctx);
#endif

@ -2075,12 +2075,12 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
case CL_TYPE_MACHO:
if(ctx->dconf->macho)
ret = cli_scanmacho(desc, ctx, NULL);
ret = cli_scanmacho(ctx, NULL);
break;
case CL_TYPE_MACHO_UNIBIN:
if(ctx->dconf->macho)
ret = cli_scanmacho_unibin(desc, ctx);
ret = cli_scanmacho_unibin(ctx);
break;
case CL_TYPE_SIS:

Loading…
Cancel
Save