コード例 #1
0
ファイル: libclamav_unzip.c プロジェクト: 5432935/crossbridge
inline static void __fixup_rootseek(off_t offset_of_trailer, struct zip_disk_trailer *trailer)
{
    if((off_t) EC32(trailer->z_rootseek) >
	offset_of_trailer - (off_t) EC32(trailer->z_rootsize) &&
	offset_of_trailer > (off_t) EC32(trailer->z_rootsize))
	    trailer->z_rootseek = (uint32_t) (offset_of_trailer -  EC32(trailer->z_rootsize)); 
}
コード例 #2
0
ファイル: macho.c プロジェクト: badania/clamav-devel
int cli_scanmacho_unibin(cli_ctx *ctx)
{
	struct macho_fat_header fat_header;
	struct macho_fat_arch fat_arch;
	unsigned int conv, i, matcher = 0;
	int ret = CL_CLEAN;
	fmap_t *map = *ctx->fmap;
	ssize_t at;

    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;
    } else if(fat_header.magic == 0xbebafeca) {
	conv = 1;
    } else {
	cli_dbgmsg("cli_scanmacho_unibin: Incorrect magic\n");
	return CL_EFORMAT;
    }

    fat_header.nfats = EC32(fat_header.nfats, conv);
    if((fat_header.nfats & 0xffff) >= 39) /* Java Bytecode */
	return CL_CLEAN;

    if(fat_header.nfats > 32) {
	cli_dbgmsg("cli_scanmacho_unibin: Invalid number of architectures\n");
	return CL_EFORMAT;
    }
    cli_dbgmsg("UNIBIN: Number of architectures: %u\n", (unsigned int) fat_header.nfats);
    for(i = 0; i < fat_header.nfats; i++) {
	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;
	}
	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_map_scan(map, fat_arch.offset, fat_arch.size, ctx);
	if(ret == CL_VIRUS)
	    break;
    }

    return ret; /* result from the last binary */
}
コード例 #3
0
ファイル: elf.c プロジェクト: CyberIntelMafia/clamav-devel
static uint32_t cli_rawaddr32(uint32_t vaddr, struct elf_program_hdr32 *ph, uint16_t phnum, uint8_t conv, uint8_t *err)
{
	uint16_t i, found = 0;

    for(i = 0; i < phnum; i++) {
	if(EC32(ph[i].p_vaddr, conv) <= vaddr && EC32(ph[i].p_vaddr, conv) + EC32(ph[i].p_memsz, conv) > vaddr) {
	    found = 1;
	    break;
	}
    }

    if(!found) {
	*err = 1;
	return 0;
    }

    *err = 0;
    return vaddr - EC32(ph[i].p_vaddr, conv) + EC32(ph[i].p_offset, conv);
}
コード例 #4
0
int cli_msexpand(cli_ctx *ctx, int ofd)
{
	const struct msexp_hdr *hdr;
	uint8_t i, mask, bits;
	unsigned char buff[B_SIZE], wbuff[RW_SIZE];
	const unsigned char *rbuff;
	unsigned int j = B_SIZE - 16, k, l, r = 0, w = 0, rbytes = 0, wbytes = 0;
	fmap_t *map = *ctx->fmap;
	off_t cur_off = sizeof(*hdr);
	unsigned int fsize;
	int ret;

    if(!(hdr = fmap_need_off_once(map, 0, sizeof(*hdr))))
	return CL_EREAD;

    if(EC32(hdr->magic1) != MAGIC1 || EC32(hdr->magic2) != MAGIC2 || EC16(hdr->magic3) != MAGIC3) {
	cli_dbgmsg("MSEXPAND: Not supported file format\n");
	return CL_EFORMAT;
    }

    fsize = EC32(hdr->fsize);
    cli_dbgmsg("MSEXPAND: File size from header: %u\n", fsize);

    if(cli_checklimits("MSEXPAND", ctx, fsize, 0, 0)!=CL_CLEAN)
        return CL_SUCCESS;

    memset(buff, 0, B_SIZE);
    while(1) {

	if(!rbytes || (r == rbytes)) {
	    READBYTES;
	}

	bits = rbuff[r]; r++;

	mask = 1;
	for(i = 0; i < 8; i++) {
	    if(bits & mask) {
		if(r == rbytes) {
		    READBYTES;
		}

		if(w == RW_SIZE) {
		    WRITEBYTES;
		}

		wbuff[w] = buff[j] = rbuff[r];
		r++; w++;
		j++; j %= B_SIZE;
	    } else {
		if(r == rbytes) {
		    READBYTES;
		}
		k = rbuff[r]; r++;

		if(r == rbytes) {
		    READBYTES;
		}
		l = rbuff[r]; r++;

		k += (l & 0xf0) << 4;
		l = (l & 0x0f) + 3;
		while(l--) {
		    if(w == RW_SIZE) {
			WRITEBYTES;
		    }
		    wbuff[w] = buff[j] = buff[k];
		    w++;
		    k++; k %= B_SIZE;
		    j++; j %= B_SIZE;
		}
	    }
	    mask *= 2;
	}
    }

    if(w) {
	WRITEBYTES;
    }

    return CL_SUCCESS;
}
コード例 #5
0
ファイル: elf.c プロジェクト: CyberIntelMafia/clamav-devel
/* 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,
    uint8_t *do_convert, uint8_t *is64)
{
	uint8_t format64, conv;

    /* Load enough for smaller header first */
    if(fmap_readn(map, file_hdr, 0, sizeof(struct elf_file_hdr32)) != sizeof(struct elf_file_hdr32)) {
	/* Not an ELF file? */
	cli_dbgmsg("ELF: Can't read file header\n");
	return CL_BREAK;
    }

    if(memcmp(file_hdr->hdr64.e_ident, "\x7f\x45\x4c\x46", 4)) {
	cli_dbgmsg("ELF: Not an ELF file\n");
	return CL_BREAK;
    }

    switch(file_hdr->hdr64.e_ident[4]) {
	case 1:
	    cli_dbgmsg("ELF: ELF class 1 (32-bit)\n");
	    format64 = 0;
	    break;
        case 2:
	    cli_dbgmsg("ELF: ELF class 2 (64-bit)\n");
	    format64 = 1;
	    break;
        default:
	    cli_dbgmsg("ELF: Unknown ELF class (%u)\n", file_hdr->hdr64.e_ident[4]);
	    return CL_EFORMAT;
    }

    /* Need to know to endian convert */
    if(file_hdr->hdr64.e_ident[5] == 1) {
#if WORDS_BIGENDIAN == 0
	if(ctx)
            cli_dbgmsg("ELF: File is little-endian - conversion not required\n");
	conv = 0;
#else
	if(ctx)
            cli_dbgmsg("ELF: File is little-endian - data conversion enabled\n");
	conv = 1;
#endif
    } else {
#if WORDS_BIGENDIAN == 0
	if(ctx)
            cli_dbgmsg("ELF: File is big-endian - data conversion enabled\n");
	conv = 1;
#else
	if(ctx)
            cli_dbgmsg("ELF: File is big-endian - conversion not required\n");
	conv = 0;
#endif
    }

    *do_convert = conv;
    *is64 = format64;

    /* Solve bit-size and conversion pronto */
    file_hdr->hdr64.e_type = EC16(file_hdr->hdr64.e_type, conv);
    file_hdr->hdr64.e_machine = EC16(file_hdr->hdr64.e_machine, conv);
    file_hdr->hdr64.e_version = EC32(file_hdr->hdr64.e_version, conv);

    if(format64) {
	/* Read rest of 64-bit header */
	if(fmap_readn(map, file_hdr->hdr32.pad, sizeof(struct elf_file_hdr32), ELF_HDR_SIZEDIFF)
                != ELF_HDR_SIZEDIFF) {
	    /* Not an ELF file? */
	    cli_dbgmsg("ELF: Can't read file header\n");
	    return CL_BREAK;
	}
	/* Now endian convert, if needed */
	if(conv) {
	    file_hdr->hdr64.e_entry = EC64(file_hdr->hdr64.e_entry, conv);
            file_hdr->hdr64.e_phoff = EC64(file_hdr->hdr64.e_phoff, conv);
            file_hdr->hdr64.e_shoff = EC64(file_hdr->hdr64.e_shoff, conv);
	    file_hdr->hdr64.e_flags = EC32(file_hdr->hdr64.e_flags, conv);
	    file_hdr->hdr64.e_ehsize = EC16(file_hdr->hdr64.e_ehsize, conv);
	    file_hdr->hdr64.e_phentsize = EC16(file_hdr->hdr64.e_phentsize, conv);
	    file_hdr->hdr64.e_phnum = EC16(file_hdr->hdr64.e_phnum, conv);
	    file_hdr->hdr64.e_shentsize = EC16(file_hdr->hdr64.e_shentsize, conv);
	    file_hdr->hdr64.e_shnum = EC16(file_hdr->hdr64.e_shnum, conv);
	    file_hdr->hdr64.e_shstrndx = EC16(file_hdr->hdr64.e_shstrndx, conv);
	}
    }
    else {
	/* Convert 32-bit structure, if needed */
	if(conv) {
	    file_hdr->hdr32.hdr.e_entry = EC32(file_hdr->hdr32.hdr.e_entry, conv);
            file_hdr->hdr32.hdr.e_phoff = EC32(file_hdr->hdr32.hdr.e_phoff, conv);
            file_hdr->hdr32.hdr.e_shoff = EC32(file_hdr->hdr32.hdr.e_shoff, conv);
	    file_hdr->hdr32.hdr.e_flags = EC32(file_hdr->hdr32.hdr.e_flags, conv);
	    file_hdr->hdr32.hdr.e_ehsize = EC16(file_hdr->hdr32.hdr.e_ehsize, conv);
	    file_hdr->hdr32.hdr.e_phentsize = EC16(file_hdr->hdr32.hdr.e_phentsize, conv);
	    file_hdr->hdr32.hdr.e_phnum = EC16(file_hdr->hdr32.hdr.e_phnum, conv);
	    file_hdr->hdr32.hdr.e_shentsize = EC16(file_hdr->hdr32.hdr.e_shentsize, conv);
	    file_hdr->hdr32.hdr.e_shnum = EC16(file_hdr->hdr32.hdr.e_shnum, conv);
	    file_hdr->hdr32.hdr.e_shstrndx = EC16(file_hdr->hdr32.hdr.e_shstrndx, conv);
        }
        /* Wipe pad for safety */
        memset(file_hdr->hdr32.pad, 0, ELF_HDR_SIZEDIFF);
    }

    return CL_CLEAN;
}
コード例 #6
0
ファイル: elf.c プロジェクト: CyberIntelMafia/clamav-devel
/* 64-bit version of section header parsing */
static int cli_elf_sh64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo,
    struct elf_file_hdr64 *file_hdr, uint8_t conv)
{
	struct elf_section_hdr64 *section_hdr = NULL;
	uint16_t shnum, shentsize;
	uint32_t i;
	uint64_t shoff;

    shnum = file_hdr->e_shnum;
    cli_dbgmsg("ELF: Number of sections: %d\n", shnum);
    if(ctx && (shnum > 2048)) {
	cli_dbgmsg("ELF: Number of sections > 2048, skipping\n");
	return CL_BREAK;
    }
    else if(elfinfo && (shnum > 256)) {
	cli_dbgmsg("ELF: Suspicious number of sections\n");
	return CL_BREAK;
    }
    if(elfinfo) {
        elfinfo->nsections = shnum;
    }

    shentsize = file_hdr->e_shentsize;
    /* Sanity check */
    if(shentsize != sizeof(struct elf_section_hdr64)) {
	cli_dbgmsg("ELF: shentsize != sizeof(struct elf_section_hdr64)\n");
        if(ctx && DETECT_BROKEN) {
	    cli_append_virus(ctx, "Heuristics.Broken.Executable");
	    return CL_VIRUS;
        }
	return CL_EFORMAT;
    }

    if(elfinfo && !shnum) {
        return CL_CLEAN;
    }

    shoff = file_hdr->e_shoff;
    if(ctx)
        cli_dbgmsg("ELF: Section header table offset: " STDu64 "\n", shoff);

    if(elfinfo) {
        elfinfo->section = (struct cli_exe_section *)cli_calloc(shnum, sizeof(struct cli_exe_section));
        if(!elfinfo->section) {
            cli_dbgmsg("ELF: Can't allocate memory for section headers\n");
            return CL_EMEM;
        }
    }

    if(shnum) {
	section_hdr = (struct elf_section_hdr64 *) cli_calloc(shnum, shentsize);
	if(!section_hdr) {
	    cli_errmsg("ELF: Can't allocate memory for section headers\n");
	    if(elfinfo) {
                free(elfinfo->section);
                elfinfo->section = NULL;
	    }
	    return CL_EMEM;
	}
	if(ctx) {
            cli_dbgmsg("------------------------------------\n");
	}
    }

    /* Loop over section headers */
    for(i = 0; i < shnum; i++) {
        uint32_t sh_type, sh_flags;

	if(fmap_readn(map, &section_hdr[i], shoff, sizeof(struct elf_section_hdr64)) != sizeof(struct elf_section_hdr64)) {
            cli_dbgmsg("ELF: Can't read section header\n");
            if(ctx) {
                cli_dbgmsg("ELF: Possibly broken ELF file\n");
            }
            free(section_hdr);
            if(elfinfo) {
                free(elfinfo->section);
                elfinfo->section = NULL;
	    }
            if(ctx && DETECT_BROKEN) {
                cli_append_virus(ctx, "Heuristics.Broken.Executable");
		return CL_VIRUS;
            }
            return CL_BREAK;
        }

	shoff += sizeof(struct elf_section_hdr64);

        if(elfinfo) {
            elfinfo->section[i].rva = EC64(section_hdr[i].sh_addr, conv);
            elfinfo->section[i].raw = EC64(section_hdr[i].sh_offset, conv);
            elfinfo->section[i].rsz = EC64(section_hdr[i].sh_size, conv);
        }
        if(ctx) {
	    cli_dbgmsg("ELF: Section %u\n", i);
	    cli_dbgmsg("ELF: Section offset: " STDu64 "\n", EC64(section_hdr[i].sh_offset, conv));
	    cli_dbgmsg("ELF: Section size: " STDu64 "\n", EC64(section_hdr[i].sh_size, conv));

            sh_type = EC32(section_hdr[i].sh_type, conv);
            sh_flags = (uint32_t)(EC64(section_hdr[i].sh_flags, conv) & ELF_SHF_MASK);
            cli_elf_sectionlog(sh_type, sh_flags);

	    cli_dbgmsg("------------------------------------\n");
        }
    }

    free(section_hdr);
    return CL_CLEAN;
}
コード例 #7
0
ファイル: elf.c プロジェクト: CyberIntelMafia/clamav-devel
/* Read 64-bit program headers */
static int 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;
	uint16_t phnum, phentsize;
	uint64_t entry, fentry = 0, phoff;
	uint32_t i;
	uint8_t err;

    /* Program headers and Entry */
    phnum = file_hdr->e_phnum;
    cli_dbgmsg("ELF: Number of program headers: %d\n", phnum);
    if(phnum > 128) {
        cli_dbgmsg("ELF: Suspicious number of program headers\n");
        if(ctx && DETECT_BROKEN) {
            cli_append_virus(ctx, "Heuristics.Broken.Executable");
            return CL_VIRUS;
        }
        return CL_EFORMAT;
    }
    entry = file_hdr->e_entry;

    if(phnum && entry) {
        phentsize = file_hdr->e_phentsize;
        /* Sanity check */
        if (phentsize != sizeof(struct elf_program_hdr64)) {
            cli_dbgmsg("ELF: phentsize != sizeof(struct elf_program_hdr64)\n");
            if(ctx && DETECT_BROKEN) {
                cli_append_virus(ctx, "Heuristics.Broken.Executable");
                return CL_VIRUS;
            }
            return CL_EFORMAT;
        }

        phoff = file_hdr->e_phoff;
        if(ctx) {
            cli_dbgmsg("ELF: Program header table offset: " STDu64 "\n", phoff);
        }

        if(phnum) {
            program_hdr = (struct elf_program_hdr64 *) cli_calloc(phnum, sizeof(struct elf_program_hdr64));
            if(!program_hdr) {
                cli_errmsg("ELF: Can't allocate memory for program headers\n");
                return CL_EMEM;
            }
            if(ctx) {
                cli_dbgmsg("------------------------------------\n");
            }
        }

        for(i = 0; i < phnum; i++) {
            err = 0;
            if(fmap_readn(map, &program_hdr[i], phoff, sizeof(struct elf_program_hdr64)) != sizeof(struct elf_program_hdr64))
                err = 1;
            phoff += sizeof(struct elf_program_hdr64);

            if(err) {
                cli_dbgmsg("ELF: Can't read segment #%d\n", i);
                if(ctx) {
                    cli_dbgmsg("ELF: Possibly broken ELF file\n");
                }
                free(program_hdr);
                if(ctx && DETECT_BROKEN) {
                    cli_append_virus(ctx, "Heuristics.Broken.Executable");
                    return CL_VIRUS;
                }
                return CL_BREAK;
            }

            if(ctx) {
                cli_dbgmsg("ELF: Segment #%d\n", i);
                cli_dbgmsg("ELF: Segment type: 0x%x\n", EC32(program_hdr[i].p_type, conv));
                cli_dbgmsg("ELF: Segment offset: 0x" STDx64 "\n", EC64(program_hdr[i].p_offset, conv));
                cli_dbgmsg("ELF: Segment virtual address: 0x" STDx64 "\n", EC64(program_hdr[i].p_vaddr, conv));
                cli_dbgmsg("ELF: Segment real size: 0x" STDx64 "\n", EC64(program_hdr[i].p_filesz, conv));
                cli_dbgmsg("ELF: Segment virtual size: 0x" STDx64 "\n", EC64(program_hdr[i].p_memsz, conv));
                cli_dbgmsg("------------------------------------\n");
            }
        }

        fentry = cli_rawaddr64(entry, program_hdr, phnum, conv, &err);
        free(program_hdr);
        if(err) {
            cli_dbgmsg("ELF: Can't calculate file offset of entry point\n");
            if(ctx && DETECT_BROKEN) {
                cli_append_virus(ctx, "Heuristics.Broken.Executable");
                return CL_VIRUS;
            }
            return CL_EFORMAT;
        }
        if(ctx) {
            cli_dbgmsg("ELF: Entry point address: 0x%.16" PRIx64 "\n", entry);
            cli_dbgmsg("ELF: Entry point offset: 0x%.16" PRIx64 " (" STDi64 ")\n", fentry, fentry);
        }
    }

    if(elfinfo) {
        elfinfo->ep = fentry;
    }

    return CL_CLEAN;
}
コード例 #8
0
ファイル: rebuildpe.c プロジェクト: antchan2/clamav-devel
int cli_rebuildpe(char *buffer, struct cli_exe_section *sections, int sects, uint32_t base, uint32_t ep, uint32_t ResRva, uint32_t ResSize, int file)
{
  uint32_t datasize=0, rawbase=PESALIGN(0x148+0x80+0x28*sects, 0x200);
  char *pefile=NULL, *curpe;
  struct IMAGE_PE_HEADER *fakepe;
  int i, gotghost=(sections[0].rva > PESALIGN(rawbase, 0x1000));

  if (gotghost) rawbase=PESALIGN(0x148+0x80+0x28*(sects+1), 0x200);

  if(sects+gotghost > 96)
    return 0;

  for (i=0; i < sects; i++)
    datasize+=PESALIGN(sections[i].rsz, 0x200);

  if(datasize > CLI_MAX_ALLOCATION)
    return 0;

  if((pefile = (char *) cli_calloc(rawbase+datasize, 1))) {
    memcpy(pefile, HEADERS, 0x148);

    datasize = PESALIGN(rawbase, 0x1000);

    fakepe = (struct IMAGE_PE_HEADER *)(pefile+0xd0);
    fakepe->NumberOfSections = EC16(sects+gotghost);
    fakepe->AddressOfEntryPoint = EC32(ep);
    fakepe->ImageBase = EC32(base);
    fakepe->SizeOfHeaders = EC32(rawbase);
    memset(pefile+0x148, 0, 0x80);
    cli_writeint32(pefile+0x148+0x10, ResRva);
    cli_writeint32(pefile+0x148+0x14, ResSize);
    curpe = pefile+0x148+0x80;

    if (gotghost) {
      snprintf(curpe, 8, "empty");
      cli_writeint32(curpe+8, sections[0].rva-datasize); /* vsize */
      cli_writeint32(curpe+12, datasize); /* rva */
      cli_writeint32(curpe+0x24, 0xffffffff);
      curpe+=40;
      datasize+=PESALIGN(sections[0].rva-datasize, 0x1000);
    }

    for (i=0; i < sects; i++) {
      snprintf(curpe, 8, ".clam%.2d", i+1);
      cli_writeint32(curpe+8, sections[i].vsz);
      cli_writeint32(curpe+12, sections[i].rva);
      cli_writeint32(curpe+16, sections[i].rsz);
      cli_writeint32(curpe+20, rawbase);
      /* already zeroed
      cli_writeint32(curpe+24, 0);
      cli_writeint32(curpe+28, 0);
      cli_writeint32(curpe+32, 0);
      */
      cli_writeint32(curpe+0x24, 0xffffffff);
      memcpy(pefile+rawbase, buffer+sections[i].raw, sections[i].rsz);
      rawbase+=PESALIGN(sections[i].rsz, 0x200);
      curpe+=40;
      datasize+=PESALIGN(sections[i].vsz, 0x1000);
    }
    fakepe->SizeOfImage = EC32(datasize);
  } else {
    return 0;
  }

  i = (cli_writen(file, pefile, rawbase)!=-1);
  free(pefile);
  return i;
}
コード例 #9
0
static int nsis_unpack_next(struct nsis_st *n, cli_ctx *ctx) {
  unsigned char *ibuf;
  uint32_t size, loops;
  int ret;
  unsigned char obuf[BUFSIZ];

  if (n->eof) {
    cli_dbgmsg("NSIS: extraction complete\n");
    return CL_BREAK;
  }
  if (ctx->limits && ctx->limits->maxfiles && n->fno >= ctx->limits->maxfiles) {
    cli_dbgmsg("NSIS: Files limit reached (max: %u)\n", ctx->limits->maxfiles);
    return CL_EMAXFILES;
  }

  if (n->fno)
    snprintf(n->ofn, 1023, "%s/content.%.3u", n->dir, n->fno);
  else
    snprintf(n->ofn, 1023, "%s/headers", n->dir);

  n->fno++;

  if ((n->ofd=open(n->ofn, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600))==-1) {
    cli_errmsg("NSIS: unable to create output file %s - aborting.", n->ofn);
    return CL_EIO;
  }

  if (!n->solid) {
    if (cli_readn(n->ifd, &size, 4)!=4) {
      cli_dbgmsg("NSIS: reached EOF - extraction complete\n");
      close(n->ofd);
      return CL_BREAK;
    }
    if (n->asz==4) {
      cli_dbgmsg("NSIS: reached CRC - extraction complete\n");
      close(n->ofd);
      return CL_BREAK;
    }
    loops = EC32(size);
    if (!(size = (loops&~0x80000000))) {
      cli_dbgmsg("NSIS: empty file found\n");
      return CL_SUCCESS;
    }
    if (n->asz <4 || size > n->asz-4) {
      cli_dbgmsg("NSIS: next file is outside the archive\n");
      close(n->ofd);
      return CL_BREAK;
    }

    n->asz -= size+4;

    if (ctx->limits && ctx->limits->maxfilesize && size > ctx->limits->maxfilesize) {
      cli_dbgmsg("NSIS: Skipping file due to size limit (%u, max: %lu)\n", size, ctx->limits->maxfilesize);
      close(n->ofd);
      if (lseek(n->ifd, size, SEEK_CUR)==-1) return CL_EIO;
      return CL_EMAXSIZE;
    }
    if (!(ibuf= (unsigned char *) cli_malloc(size))) {
      	cli_dbgmsg("NSIS: out of memory"__AT__"\n");
      close(n->ofd);
      return CL_EMEM;
    }
    if (cli_readn(n->ifd, ibuf, size) != (ssize_t) size) {
      cli_dbgmsg("NSIS: cannot read %u bytes"__AT__"\n", size);
      free(ibuf);
      close(n->ofd);
      return CL_EIO;
    }
    if (loops==size) {
      if (cli_writen(n->ofd, ibuf, size) != (ssize_t) size) {
	cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
	free(ibuf);
	close(n->ofd);
	return CL_EIO;
      }
    } else {
      if ((ret=nsis_init(n))!=CL_SUCCESS) {
	cli_dbgmsg("NSIS: decompressor init failed"__AT__"\n");
	free(ibuf);
	close(n->ofd);
	return ret;
      }
      
      n->nsis.avail_in = size;
      n->nsis.next_in = ibuf;
      n->nsis.next_out = obuf;
      n->nsis.avail_out = BUFSIZ;
      loops=0;

      while ((ret=nsis_decomp(n))==CL_SUCCESS) {
	if ((size = n->nsis.next_out - obuf)) {
	  if (cli_writen(n->ofd, obuf, size) != (ssize_t) size) {
	    cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
	    free(ibuf);
	    close(n->ofd);
	    return CL_EIO;
	  }
	  n->nsis.next_out = obuf;
	  n->nsis.avail_out = BUFSIZ;
	  loops=0;
	  if (ctx->limits && ctx->limits->maxfilesize && size > ctx->limits->maxfilesize) {
	    cli_dbgmsg("NSIS: Skipping file due to size limit (%u, max: %lu)\n", size, ctx->limits->maxfilesize);
	    free(ibuf);
	    close(n->ofd);
	    nsis_shutdown(n);
	    return CL_EMAXSIZE;
	  }
	} else if (++loops > 10) {
	  cli_dbgmsg("NSIS: xs looping, breaking out"__AT__"\n");
	  ret = CL_BREAK;
	  break;
	}
      }

      if (ret != CL_BREAK) {
	cli_dbgmsg("NSIS: bad stream"__AT__"\n");
	free(ibuf);
	close(n->ofd);
	return CL_EFORMAT;
      }

      if (cli_writen(n->ofd, obuf, n->nsis.next_out - obuf) != n->nsis.next_out - obuf) {
	cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
	free(ibuf);
	close(n->ofd);
	return CL_EIO;
      }
      nsis_shutdown(n);
    }

    free(ibuf);
    return CL_SUCCESS;

  } else {
    if (!n->freeme) {
      if ((ret=nsis_init(n))!=CL_SUCCESS) {
	cli_dbgmsg("NSIS: decompressor init failed\n");
	close(n->ofd);
	return ret;
      }
      if (!(n->freeme= (unsigned char *) cli_malloc(n->asz))) {
	cli_dbgmsg("NSIS: out of memory\n");
	close(n->ofd);
	return CL_EMEM;
      }
      if (cli_readn(n->ifd, n->freeme, n->asz) != (ssize_t) n->asz) {
	cli_dbgmsg("NSIS: cannot read %u bytes"__AT__"\n", n->asz);
	close(n->ofd);
	return CL_EIO;
      }
      n->nsis.next_in = n->freeme;
      n->nsis.avail_in = n->asz;
    }

    if (n->nsis.avail_in<=4) {
      cli_dbgmsg("NSIS: extraction complete\n");
      close(n->ofd);
      return CL_BREAK;
    }
    n->nsis.next_out = obuf;
    n->nsis.avail_out = 4;
    loops = 0;

    while ((ret=nsis_decomp(n))==CL_SUCCESS) {
      if (n->nsis.next_out - obuf == 4) break;
      if (++loops > 20) {
	cli_dbgmsg("NSIS: xs looping, breaking out"__AT__"\n");
	ret = CL_BREAK;
	break;
      }
    }

    if (ret != CL_SUCCESS) {
      cli_dbgmsg("NSIS: bad stream"__AT__"\n");
      close(n->ofd);
      return CL_EFORMAT;
    }

    size=cli_readint32(obuf);
    if (ctx->limits && ctx->limits->maxfilesize && size > ctx->limits->maxfilesize) {
      cli_dbgmsg("NSIS: Breaking out due to filesize limit (%u, max: %lu) in solid archive\n", size, ctx->limits->maxfilesize);
      close(n->ofd);
      return CL_EFORMAT;
    }

    n->nsis.next_out = obuf;
    n->nsis.avail_out = MIN(BUFSIZ,size);
    loops = 0;

    while (size && (ret=nsis_decomp(n))==CL_SUCCESS) {
      unsigned int wsz;
      if ((wsz = n->nsis.next_out - obuf)) {
	if (cli_writen(n->ofd, obuf, wsz) != (ssize_t) wsz) {
	  close(n->ofd);
	  return CL_EIO;
	}
	size-=wsz;
	n->nsis.next_out = obuf;
	n->nsis.avail_out = MIN(size,BUFSIZ);
      } else if ( ++loops > 20 ) {
	cli_dbgmsg("NSIS: xs looping, breaking out"__AT__"\n");
	ret = CL_BREAK;
	break;
      }
    }

    if (ret == CL_BREAK) {
      if (cli_writen(n->ofd, obuf, n->nsis.next_out - obuf) != n->nsis.next_out - obuf) {
	close(n->ofd);
	return CL_EIO;
      }
      n->eof=1;
    } else if (ret != CL_SUCCESS) {
      cli_dbgmsg("NSIS: bad stream"__AT__"\n");
      close(n->ofd);
      return CL_EFORMAT;
    }
    
    return CL_SUCCESS;
  }

}
コード例 #10
0
ファイル: cab.c プロジェクト: OPSF/uClinux
int cab_open(int fd, off_t offset, struct cab_archive *cab)
{
	unsigned int i, folders = 0;
	struct cab_file *file, *lfile = NULL;
	struct cab_folder *folder, *lfolder = NULL;
	struct cab_hdr hdr;
	struct cab_hdr_opt hdr_opt;
	struct cab_folder_hdr folder_hdr;
	struct cab_file_hdr file_hdr;
	struct stat sb;
	uint16_t fidx;
	char *pt;
	int ret;
	off_t resfold = 0, rsize;


    if(lseek(fd, offset, SEEK_SET) == -1) {
	cli_errmsg("cab_open: Can't lseek to %u (offset)\n", (unsigned int) offset);
	return CL_ESEEK;
    }

    if(cli_readn(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
	cli_dbgmsg("cab_open: Can't read cabinet header\n");
	return CL_EFORMAT; /* most likely a corrupted file */
    }

    if(EC32(hdr.signature) != 0x4643534d) {
	cli_dbgmsg("cab_open: Incorrect CAB signature\n");
	return CL_EFORMAT;
    } else {
	cli_dbgmsg("CAB: -------------- Cabinet file ----------------\n");
    }

    if(fstat(fd, &sb) == -1) {
	cli_errmsg("cab_open: Can't fstat descriptor %d\n", fd);
	return CL_ESTAT;
    }
    rsize = sb.st_size;

    memset(cab, 0, sizeof(struct cab_archive));

    cab->length = EC32(hdr.cbCabinet);
    cli_dbgmsg("CAB: Cabinet length: %u\n", cab->length);
    if((off_t) cab->length > rsize) {
	cli_dbgmsg("CAB: Truncating file size from %lu to %lu\n", (unsigned long int) cab->length, (unsigned long int) rsize);
	cab->length = (uint32_t) rsize;
    }

    cab->nfolders = EC16(hdr.cFolders);
    if(!cab->nfolders) {
	cli_dbgmsg("cab_open: No folders in cabinet (fake cab?)\n");
	return CL_EFORMAT;
    } else {
	cli_dbgmsg("CAB: Folders: %u\n", cab->nfolders);
	if(cab->nfolders > CAB_FOLDER_LIMIT) {
	    cab->nfolders = CAB_FOLDER_LIMIT;
	    cli_dbgmsg("CAB: *** Number of folders limited to %u ***\n", cab->nfolders);
	}
    }

    cab->nfiles = EC16(hdr.cFiles);
    if(!cab->nfiles) {
	cli_dbgmsg("cab_open: No files in cabinet (fake cab?)\n");
	return CL_EFORMAT;
    } else {
	cli_dbgmsg("CAB: Files: %u\n", cab->nfiles);
	if(cab->nfiles > CAB_FILE_LIMIT) {
	    cab->nfiles = CAB_FILE_LIMIT;
	    cli_dbgmsg("CAB: *** Number of files limited to %u ***\n", cab->nfiles);
	}
    }

    cli_dbgmsg("CAB: File format version: %u.%u\n", hdr.versionMajor, hdr.versionMinor);

    cab->flags = EC16(hdr.flags);
    if(cab->flags & 0x0004) {
	if(cli_readn(fd, &hdr_opt, sizeof(hdr_opt)) != sizeof(hdr_opt)) {
	    cli_dbgmsg("cab_open: Can't read file header (fake cab?)\n");
	    return CL_EFORMAT; /* most likely a corrupted file */
	}

	cab->reshdr = EC16(hdr_opt.cbCFHeader);
	resfold = hdr_opt.cbCFFolder;
	cab->resdata = hdr_opt.cbCFData;

	if(cab->reshdr) {
	    if(lseek(fd, cab->reshdr, SEEK_CUR) == -1) {
		cli_dbgmsg("cab_open: Can't lseek to %u (fake cab?)\n", cab->reshdr);
		return CL_EFORMAT; /* most likely a corrupted file */
	    }
	}
    }

    if(cab->flags & 0x0001) { /* preceeding cabinet */
	/* name */
	pt = cab_readstr(fd, &ret);
	if(ret)
	    return ret;
	if(cab_chkname(pt, 0))
	    cli_dbgmsg("CAB: Invalid name of preceeding cabinet\n");
	else
	    cli_dbgmsg("CAB: Preceeding cabinet name: %s\n", pt);
	free(pt);
	/* info */
	pt = cab_readstr(fd, &ret);
	if(ret)
	    return ret;
	if(cab_chkname(pt, 0))
	    cli_dbgmsg("CAB: Invalid info for preceeding cabinet\n");
	else
	    cli_dbgmsg("CAB: Preceeding cabinet info: %s\n", pt);
	free(pt);
    }

    if(cab->flags & 0x0002) { /* next cabinet */
	/* name */
	pt = cab_readstr(fd, &ret);
	if(ret)
	    return ret;
	if(cab_chkname(pt, 0))
	    cli_dbgmsg("CAB: Invalid name of next cabinet\n");
	else
	    cli_dbgmsg("CAB: Next cabinet name: %s\n", pt);
	free(pt);
	/* info */
	pt = cab_readstr(fd, &ret);
	if(ret)
	    return ret;
	if(cab_chkname(pt, 0))
	    cli_dbgmsg("CAB: Invalid info for next cabinet\n");
	else
	    cli_dbgmsg("CAB: Next cabinet info: %s\n", pt);
	free(pt);
    }

    /* folders */
    for(i = 0; i < cab->nfolders; i++) {
	if(cli_readn(fd, &folder_hdr, sizeof(folder_hdr)) != sizeof(folder_hdr)) {
	    cli_dbgmsg("cab_open: Can't read header for folder %u\n", i);
	    break;
	}

	if(resfold) {
	    if(lseek(fd, resfold, SEEK_CUR) == -1) {
		cli_dbgmsg("cab_open: Can't lseek to %u (resfold)\n", (unsigned int) resfold);
		break;
	    }
	}

	if(EC32(folder_hdr.coffCabStart) + offset > rsize) {
	    cli_dbgmsg("CAB: Folder out of file\n");
	    continue;
	}

	if((EC16(folder_hdr.typeCompress) & 0x000f) > 3) {
	    cli_dbgmsg("CAB: Unknown compression method\n");
	    continue;
	}

	folder = (struct cab_folder *) cli_calloc(1, sizeof(struct cab_folder));
	if(!folder) {
	    cli_errmsg("cab_open: Can't allocate memory for folder\n");
	    cab_free(cab);
	    return CL_EMEM;
	}

	folder->cab = (struct cab_archive *) cab;
	folder->offset = (off_t) EC32(folder_hdr.coffCabStart) + offset;
	folder->nblocks = EC16(folder_hdr.cCFData);
	folder->cmethod = EC16(folder_hdr.typeCompress);

	cli_dbgmsg("CAB: Folder record %u\n", i);
	cli_dbgmsg("CAB: Folder offset: %u\n", (unsigned int) folder->offset);
	cli_dbgmsg("CAB: Folder compression method: %d\n", folder->cmethod);

	if(!lfolder)
	    cab->folders = folder;
	else
	    lfolder->next = folder;

	lfolder = folder;
	folders++;
    }
    cli_dbgmsg("CAB: Recorded folders: %u\n", folders);

    /* files */
    if(cab->nfolders != folders && lseek(fd, EC16(hdr.coffFiles), SEEK_SET) == -1) {
	cli_dbgmsg("cab_open: Can't lseek to hdr.coffFiles\n");
	cab_free(cab);
	return CL_EFORMAT;
    }
    for(i = 0; i < cab->nfiles; i++) {
	if(cli_readn(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
	    cli_dbgmsg("cab_open: Can't read file %u header\n", i);
	    break;
	}

	file = (struct cab_file *) cli_calloc(1, sizeof(struct cab_file));
	if(!file) {
	    cli_errmsg("cab_open: Can't allocate memory for file\n");
	    cab_free(cab);
	    return CL_EMEM;
	}

	file->cab = cab;
	file->fd = fd;
	file->offset = EC32(file_hdr.uoffFolderStart);
	file->length = EC32(file_hdr.cbFile);
	file->attribs = EC32(file_hdr.attribs);
	fidx = EC32(file_hdr.iFolder);
	file->error = CL_SUCCESS;

	file->name = cab_readstr(fd, &ret);
	if(ret) {
	    free(file);
	    continue;
	}
	cab_chkname(file->name, 1);

	cli_dbgmsg("CAB: File record %u\n", i);
	cli_dbgmsg("CAB: File name: %s\n", file->name);
	cli_dbgmsg("CAB: File offset: %u\n", (unsigned int) file->offset);
	cli_dbgmsg("CAB: File folder index: %u\n", fidx);
	cli_dbgmsg("CAB: File attribs: 0x%x\n", file->attribs);
	if(file->attribs & 0x01)
	    cli_dbgmsg("CAB:   * file is read-only\n");
	if(file->attribs & 0x02)
	    cli_dbgmsg("CAB:   * file is hidden\n");
	if(file->attribs & 0x04)
	    cli_dbgmsg("CAB:   * file is a system file\n");
	if(file->attribs & 0x20)
	    cli_dbgmsg("CAB:   * file modified since last backup\n");
	if(file->attribs & 0x40)
	    cli_dbgmsg("CAB:   * file to be run after extraction\n");
	if(file->attribs & 0x80)
	    cli_dbgmsg("CAB:   * file name contains UTF\n");

	/* folder index */
	if(fidx < 0xfffd) {
	    if(fidx > cab->nfolders) {
		cli_dbgmsg("cab_open: File %s is not associated with any folder\n", file->name);
		free(file->name);
		free(file);
		continue;
	    }

	    file->folder = cab->folders;
	    while(file->folder && fidx--)
		file->folder = file->folder->next;

	    if(!file->folder) {
		cli_dbgmsg("cab_open: Folder not found for file %s\n", file->name);
		free(file->name);
		free(file);
		continue;
	    }

	} else {
	    cli_dbgmsg("CAB: File is split *skipping*\n");
	    free(file->name);
	    free(file);
	    continue;
	}

	if(!lfile)
	    cab->files = file;
	else
	    lfile->next = file;

	lfile = file;

    }

    return CL_SUCCESS;
}
コード例 #11
0
ファイル: swf.c プロジェクト: capturePointer/clamav-devel
int cli_scanswf(cli_ctx *ctx)
{
    struct swf_file_hdr file_hdr;
    fmap_t *map = *ctx->fmap;
    unsigned int bitpos, bitbuf, getbits_n, nbits, getword_1, getword_2, getdword_1, getdword_2;
    const char *pt;
    unsigned char get_c;
    size_t offset = 0;
    unsigned int val, foo, tag_hdr, tag_type, tag_len;
    unsigned long int bits;

    cli_dbgmsg("in cli_scanswf()\n");

    if(fmap_readn(map, &file_hdr, offset, sizeof(file_hdr)) != sizeof(file_hdr)) {
        cli_dbgmsg("SWF: Can't read file header\n");
        return CL_CLEAN;
    }
    offset += sizeof(file_hdr);

    if(!strncmp(file_hdr.signature, "CWS", 3)) {
        cli_dbgmsg("SWF: zlib compressed file\n");
        return scancws(ctx, &file_hdr);
    } else if(!strncmp(file_hdr.signature, "ZWS", 3)) {
        cli_dbgmsg("SWF: LZMA compressed file\n");
        return scanzws(ctx, &file_hdr);
    } else if(!strncmp(file_hdr.signature, "FWS", 3)) {
        cli_dbgmsg("SWF: Uncompressed file\n");
    } else {
        cli_dbgmsg("SWF: Not a SWF file\n");
        return CL_CLEAN;
    }

    cli_dbgmsg("SWF: Version: %u\n", file_hdr.version);
    cli_dbgmsg("SWF: File size: %u\n", EC32(file_hdr.filesize));

    INITBITS;

    GETBITS(nbits, 5);
    cli_dbgmsg("SWF: FrameSize RECT size bits: %u\n", nbits);
    {
        uint32_t xMin = 0, xMax = 0, yMin = 0, yMax = 0;
        GETBITS(xMin, nbits); /* Should be zero */
        GETBITS(xMax, nbits);
        GETBITS(yMin, nbits); /* Should be zero */
        GETBITS(yMax, nbits);
        cli_dbgmsg("SWF: FrameSize xMin %u xMax %u yMin %u yMax %u\n", xMin, xMax, yMin, yMax);
    }

    GETWORD(foo);
    GETWORD(val);
    cli_dbgmsg("SWF: Frames total: %d\n", val);

    /* Skip Flash tag walk unless debug mode */
    if(!cli_debug_flag) {
        return CL_CLEAN;
    }

    while(offset < map->len) {
        GETWORD(tag_hdr);
        tag_type = tag_hdr >> 6;
        if(tag_type == 0)
            break;
        tag_len = tag_hdr & 0x3f;
        if(tag_len == 0x3f)
            GETDWORD(tag_len);

        pt = tagname(tag_type);
        cli_dbgmsg("SWF: %s\n", pt ? pt : "UNKNOWN TAG");
        cli_dbgmsg("SWF: Tag length: %u\n", tag_len);
        if (tag_len > map->len) {
            cli_dbgmsg("SWF: Invalid tag length.\n");
            return CL_EFORMAT;
        }
        if ((offset + tag_len) < offset) {
            cli_warnmsg("SWF: Tag length too large.\n");
            break;
        }
        if(!pt) {
            offset += tag_len;
            continue;
        }

        switch(tag_type) {
            case TAG_SCRIPTLIMITS: {
                unsigned int recursion, timeout;
                GETWORD(recursion);
                GETWORD(timeout);
                cli_dbgmsg("SWF: scriptLimits recursion %u timeout %u\n", recursion, timeout);
                break;
            }

            case TAG_FILEATTRIBUTES:
                GETDWORD(val);
                cli_dbgmsg("SWF: File attributes:\n");
                if(val & SWF_ATTR_USENETWORK)
                    cli_dbgmsg("    * Use network\n");
                if(val & SWF_ATTR_RELATIVEURLS)
                    cli_dbgmsg("    * Relative URLs\n");
                if(val & SWF_ATTR_SUPPRESSCROSSDOMAINCACHE)
                    cli_dbgmsg("    * Suppress cross domain cache\n");
                if(val & SWF_ATTR_ACTIONSCRIPT3)
                    cli_dbgmsg("    * ActionScript 3.0\n");
                if(val & SWF_ATTR_HASMETADATA)
                    cli_dbgmsg("    * Has metadata\n");
                if(val & SWF_ATTR_USEDIRECTBLIT)
                    cli_dbgmsg("    * Use hardware acceleration\n");
                if(val & SWF_ATTR_USEGPU)
                    cli_dbgmsg("    * Use GPU\n");
                break;

            default:
                offset += tag_len;
                continue;
        }
    }

    return CL_CLEAN;
}
コード例 #12
0
ファイル: libclamav_upack.c プロジェクト: 5432935/crossbridge
int unupack(int upack, char *dest, uint32_t dsize, char *buff, uint32_t vma, uint32_t ep, uint32_t base, uint32_t va, int file)
{
	int j, searchval;
	char *loc_esi, *loc_edi, *loc_ebx, *end_edi, *save_edi, *rpeb, *alvalue;
	char *paddr, *pushed_esi, *save2;
	uint32_t save1, save3, loc_ecx, count, shlsize, original_ep, ret, loc_ebx_u;
	struct cli_exe_section section;
	int upack_version = UPACK_399;

	/* buff [168 bytes] doesn't have to be checked, since it was checked in pe.c */
	if (upack)
	{
		uint32_t aljump, shroff, lngjmpoff;

		/* dummy characteristics ;/ */
		if (buff[5] == '\xff' && buff[6] == '\x36')
			upack_version = UPACK_0297729;
		loc_esi = dest + (cli_readint32(buff + 1) -  vma);

		if (!CLI_ISCONTAINED(dest, dsize, loc_esi, 12))
			return -1;
		original_ep = cli_readint32(loc_esi);
		loc_esi += 4;
		/*cli_readint32(loc_esi);*/
		loc_esi += 4;

		original_ep -= vma;
		cli_dbgmsg("Upack: EP: %08x original:  %08X || %08x\n", ep, original_ep, cli_readint32(loc_esi-8));

		if (upack_version == UPACK_399)
		{
			/* jmp 1 */
			loc_edi = dest + (cli_readint32(loc_esi) -  vma);
			if (!CLI_ISCONTAINED(dest, dsize, dest+ep+0xa, 2) || dest[ep+0xa] != '\xeb')
				return -1;
			loc_esi = dest + *(dest + ep + 0xb) + ep + 0xc;

			/* use this as a temp var */
			/* jmp 2 + 0xa */
			alvalue = loc_esi+0x1a;
			if (!CLI_ISCONTAINED(dest, dsize, alvalue, 2) || *alvalue != '\xeb')
				return -1;
			alvalue++;
			alvalue += (*alvalue&0xff) + 1 + 0xa;
			lngjmpoff = 8;
		} else {
			if (!CLI_ISCONTAINED(dest, dsize, dest+ep+7, 5) || dest[ep+7] != '\xe9')
				return -1;
			loc_esi = dest + cli_readint32(dest + ep + 8) + ep + 0xc;
			alvalue = loc_esi + 0x25;
			lngjmpoff = 10;
		}

		if (!CLI_ISCONTAINED(dest, dsize, alvalue, 2) || *alvalue != '\xb5')
			return -1;
		alvalue++;
		count = *alvalue&0xff;

		if (!CLI_ISCONTAINED(dest, dsize, alvalue, lngjmpoff+5) || *(alvalue+lngjmpoff) != '\xe9')
			return -1;
		/* use this as a temp to make a long jmp to head of unpacking proc */
		shlsize = cli_readint32(alvalue + lngjmpoff+1);
		/* upack_399 + upack_0151477 */
		if (upack_version == UPACK_399)
			shlsize = shlsize + (loc_esi - dest) + *(loc_esi+0x1b) + 0x1c + 0x018; /* read checked above */
		else
			/* there is no additional jump in upack_0297729 */
			shlsize = shlsize + (loc_esi - dest) + 0x035;
		/* do the jump, 43 - point to jecxz */
		alvalue = dest+shlsize+43;

		/* 0.39 */
		aljump = 8;
		shroff = 24;
		if (!CLI_ISCONTAINED(dest, dsize, alvalue-1, 2) || *(alvalue-1) != '\xe3')
		{
			/* in upack_0297729 and upack_0151477 jecxz is at offset: 46 */
			alvalue = dest+shlsize+46;
			if (!CLI_ISCONTAINED(dest, dsize, alvalue-1, 2) || *(alvalue-1) != '\xe3')
				return -1;
			else {
				if (upack_version != UPACK_0297729)
					upack_version = UPACK_0151477;
				aljump = 7;
				shroff = 26;
			}
			
		}
		/* do jecxz */
		alvalue += (*alvalue&0xff) + 1;
		/* is there a long jump ? */
		if (!CLI_ISCONTAINED(dest, dsize, alvalue, aljump+5) || *(alvalue+aljump) != '\xe9')
			return -1;
		/* do jmp, 1+4 - size of jmp instruction, aljump - instruction offset, 27 offset to cmp al,xx*/
		ret = cli_readint32(alvalue+aljump+1);
		alvalue += ret + aljump+1+4 + 27;
		if (upack_version == UPACK_0297729)
			alvalue += 2;
		/* shr ebp */
		if (!CLI_ISCONTAINED(dest, dsize, dest+shlsize+shroff, 3) || *(dest+shlsize+shroff) != '\xc1' || *(dest+shlsize+shroff+1) != '\xed')
			return -1;
		shlsize = (*(dest + shlsize + shroff+2))&0xff;
		count *= 0x100;
		if (shlsize < 2 || shlsize > 8)
		{
			cli_dbgmsg ("Upack: context bits out of bounds\n");
			return -1;
		}
		cli_dbgmsg("Upack: Context Bits parameter used with lzma: %02x, %02x\n", shlsize, count);
		/* check if loc_esi + .. == 0xbe -> mov esi */
		/* upack_0297729 has mov esi, .. + mov edi, .., in upack_0151477 and upack_399 EDI has been already set before */
		if (upack_version == UPACK_0297729)
		{
			if (!CLI_ISCONTAINED(dest, dsize, loc_esi+6, 10) || *(loc_esi+6) != '\xbe' || *(loc_esi+11) != '\xbf')
				return -1;
			if ((uint32_t)cli_readint32(loc_esi + 7) < base || (uint32_t)cli_readint32(loc_esi+7) > vma)
				return -1;
			loc_edi = dest + (cli_readint32(loc_esi + 12) - vma);
			loc_esi = dest + (cli_readint32(loc_esi + 7) - base);
		} else {
			if (!CLI_ISCONTAINED(dest, dsize, loc_esi+7, 5) || *(loc_esi+7) != '\xbe')
				return -1;
			loc_esi = dest + (cli_readint32(loc_esi + 8) - vma);
		}

		if (upack_version == UPACK_0297729)
		{
			/* 0x16*4=0x58, 6longs*4 = 24, 0x64-last loc_esi read location */
			if (!CLI_ISCONTAINED(dest, dsize, loc_edi, (0x58 + 24 + 4*count)) || !CLI_ISCONTAINED(dest, dsize, loc_esi, (0x58 + 0x64 + 4)))
				return -1;

			/* XXX I don't know if this [0x16] is constant number, not enough samples provided */
			for (j=0; j<0x16; j++, loc_esi+=4, loc_edi+=4)
				cli_writeint32(loc_edi, cli_readint32(loc_esi)); 
		} else {
			/* 0x27*4=0x9c, 6longs*4 = 24, 0x34-last loc_esi read location */
			if (!CLI_ISCONTAINED(dest, dsize, loc_edi, (0x9c + 24 + 4*count)) || !CLI_ISCONTAINED(dest, dsize, loc_esi, (0x9c + 0x34 + 4)))
				return -1;
			for (j=0; j<0x27; j++, loc_esi+=4, loc_edi+=4)
				cli_writeint32(loc_edi, cli_readint32(loc_esi)); 
		}
		save3 = cli_readint32(loc_esi + 4);
		paddr = dest + ((uint32_t)cli_readint32(loc_edi - 4)) - vma;
		loc_ebx = loc_edi;
		cli_writeint32(loc_edi, 0xffffffff);
		loc_edi+=4;
		cli_writeint32(loc_edi, 0);
		loc_edi+=4;
		for (j=0; j<4; j++, loc_edi+=4)
		    cli_writeint32(loc_edi, (1));

		for (j=0; (unsigned int)j<count; j++, loc_edi+=4)
		    cli_writeint32(loc_edi, 0x400);
		
		loc_edi = dest + cli_readint32(loc_esi + 0xc) - vma;
		if (upack_version == UPACK_0297729)
			loc_edi = dest+vma-base; /* XXX not enough samples provided to be sure of it! */

		pushed_esi = loc_edi;
		end_edi = dest + cli_readint32(loc_esi + 0x34) - vma;
		if (upack_version == UPACK_0297729)
		{
			end_edi = dest + cli_readint32(loc_esi + 0x64) - vma;
			save3 = cli_readint32(loc_esi + 0x40);
		}
		/* begin end */
		cli_dbgmsg("Upack: data initialized, before upack lzma call!\n");
		if ((ret = (uint32_t)unupack399(dest, dsize, 0, loc_ebx, 0, loc_edi, end_edi, shlsize, paddr)) == 0xffffffff)
			return -1;
	/* alternative begin */
	} else {
		int ep_jmp_offs, rep_stosd_count_offs, context_bits_offs;
		loc_esi = dest + vma + ep;
		/* yet another dummy characteristics ;/ */
		if (buff[0] == '\xbe' && buff[5] == '\xad' && buff[6] == '\x8b' && buff[7] == '\xf8')
			upack_version = UPACK_11_12;

		if (upack_version == UPACK_11_12)
		{
			ep_jmp_offs = 0x1a4;
			rep_stosd_count_offs = 0x1b;
			context_bits_offs = 0x41;
			alvalue = loc_esi + 0x184;
		} else {
			ep_jmp_offs = 0x217;
			rep_stosd_count_offs = 0x3a;
			context_bits_offs = 0x5f;
			alvalue = loc_esi + 0x1c1;
		}

		if (!CLI_ISCONTAINED(dest, dsize, loc_esi, ep_jmp_offs+4))
			return -1;
		save1 = cli_readint32(loc_esi + ep_jmp_offs);
		original_ep = (loc_esi - dest) + ep_jmp_offs + 4;
		original_ep += (int32_t)save1;
		cli_dbgmsg("Upack: EP: %08x original %08x\n", ep, original_ep);

		/* this are really ugly hacks,
		 * rep_stosd_count_offs & context_bits_offs are < ep_jmp_offs,
		 * so checked in CLI_ISCONTAINED above */
		count = (*(loc_esi + rep_stosd_count_offs))&0xff;
		shlsize = (*(loc_esi + context_bits_offs))&0xff;
		shlsize = 8 - shlsize;
		if (shlsize < 2 || shlsize > 8)
		{
			cli_dbgmsg ("Upack: context bits out of bounds\n");
			return -1;
		}
		count *= 0x100;
		cli_dbgmsg("Upack: Context Bits parameter used with lzma: %02x, %02x\n", shlsize, count);
		if (upack_version == UPACK_399)
		{
			loc_esi += 4;
			loc_ecx = cli_readint32(loc_esi+2);
			cli_writeint32(loc_esi+2,0);
			if (!loc_ecx)
			{
				cli_dbgmsg("Upack: something's wrong, report back\n");
				return -1;/* XXX XXX XXX XXX */
			}
			loc_esi -= (loc_ecx - 2);
			if (!CLI_ISCONTAINED(dest, dsize, loc_esi, 12))
				return -1;

			cli_dbgmsg("Upack: %08x %08x %08x %08x\n", loc_esi, dest, cli_readint32(loc_esi), base);
			loc_ebx_u = loc_esi - (dest + cli_readint32(loc_esi) - base);
			cli_dbgmsg("Upack: EBX: %08x\n", loc_ebx_u);
			loc_esi += 4;
			save2 = loc_edi = dest + cli_readint32(loc_esi) - base;
			cli_dbgmsg("Upack: DEST: %08x, %08x\n", cli_readint32(loc_esi), cli_readint32(loc_esi) - base);
			loc_esi += 4;
			/* 2vGiM: j is signed. Is that really what you want? Will it cause problems with the following checks?
			 * yes! this is wrong! how did you notice that?!
			 */
			j = cli_readint32(loc_esi);
			if (j<0)
			{
				cli_dbgmsg("Upack: probably hand-crafted data, report back\n");
				return -1;
			}
			loc_esi += 4;
			cli_dbgmsg("Upack: ecx counter: %08x\n", j);

			if (!CLI_ISCONTAINED(dest, dsize, loc_esi, (j*4)) || !CLI_ISCONTAINED(dest, dsize, loc_edi, ((j+count)*4)))
				return -1;
			for (;j--; loc_edi+=4, loc_esi+=4)
				cli_writeint32(loc_edi, cli_readint32(loc_esi));
			if (!CLI_ISCONTAINED(dest, dsize, save2, 8))
				return -1;
			loc_ecx = cli_readint32(save2);
			save2 += 4;
			loc_esi = save2;
			/* I could probably do simple loc_esi+= (0xe<<2),
			 *  but I'm not sure if there is always 0xe and is always ebx =0
			 */
			do {
				loc_esi += loc_ebx_u;
				loc_esi += 4;
			} while (--loc_ecx);
			if (!CLI_ISCONTAINED(dest, dsize, loc_esi, 4))
				return -1;
			save1 = cli_readint32(loc_esi); /* loc_eax = 0x400 */
			loc_esi += 4;

			for (j=0; j<count; j++, loc_edi+=4) /* checked above */
				cli_writeint32(loc_edi, (save1));

			if (!CLI_ISCONTAINED(dest, dsize, (loc_esi+0x10), 4))
				return -1;
			cli_writeint32(loc_esi+0x10, (uint32_t)cli_readint32(loc_esi+0x10)+loc_ebx_u);
			loc_ebx = loc_esi+0x14;
			loc_esi = save2;
			/* loc_ebx_u gets saved */
			/* checked above, (...save2, 8) */
			save_edi = loc_edi = dest + ((uint32_t)cli_readint32(loc_esi) - base);
			loc_esi +=4;
			cli_dbgmsg("Upack: before_fixing\n");
			/* fix values */
			if (!CLI_ISCONTAINED(dest, dsize, loc_ebx-4, (12 + 4*4)) || !CLI_ISCONTAINED(dest, dsize, loc_esi+0x24, 4) || !CLI_ISCONTAINED(dest, dsize, loc_esi+0x40, 4))
				return -1;
			for (j=2; j<6; j++)
			      cli_writeint32(loc_ebx+(j<<2), cli_readint32(loc_ebx+(j<<2)));
			paddr = dest + cli_readint32(loc_ebx - 4) - base;
			save1 = loc_ecx;
			pushed_esi = loc_edi;
			end_edi = dest + cli_readint32(loc_esi+0x24) - base;
			vma = cli_readint32(loc_ebx); cli_writeint32(loc_ebx, cli_readint32(loc_ebx + 4)); cli_writeint32((loc_ebx + 4), vma);
		/* Upack 1.1/1.2 is something between 0.39 2-section and 0.39 3-section */
		} else if (upack_version == UPACK_11_12) {
			cli_dbgmsg("Upack v 1.1/1.2\n");
			loc_esi = dest + 0x148; /* always constant? */
			loc_edi = dest + cli_readint32(loc_esi) - base; /* read checked above */
			loc_esi += 4;
			save_edi = loc_edi;
			/* movsd */
			paddr = dest + ((uint32_t)cli_readint32(loc_esi)) - base;
			loc_esi += 4;
			loc_edi += 4;
			loc_ebx = loc_edi;
		
			if (!CLI_ISCONTAINED(dest, dsize, loc_edi, ((6+count)*4)))
				return -1;
			cli_writeint32(loc_edi, 0xffffffff);
			loc_edi += 4;
			cli_writeint32(loc_edi, 0);
			loc_edi += 4;
			for (j=0; j<4; j++, loc_edi+=4)
				cli_writeint32(loc_edi, (1));

			for (j=0; j<count; j++, loc_edi+=4)
				cli_writeint32(loc_edi, 0x400);
			
			loc_edi = dest + cli_readint32(loc_esi) - base; /* read checked above */
			pushed_esi = loc_edi;
			loc_esi += 4;
			loc_ecx = 0;

			loc_esi += 4;

			end_edi = dest + cli_readint32(loc_esi-0x28) - base; /* read checked above */
			loc_esi = save_edi;
		}
		cli_dbgmsg("Upack: data initialized, before upack lzma call!\n");
		if ((ret = (uint32_t)unupack399(dest, dsize, loc_ecx, loc_ebx, loc_ecx, loc_edi, end_edi, shlsize, paddr)) == 0xffffffff)
			return -1;
		if (upack_version == UPACK_399)
			save3 = cli_readint32(loc_esi + 0x40);
		else if (upack_version == UPACK_11_12)
			save3 = cli_readint32(dest + vma + ep + 0x174);
	}

	/* let's fix calls */
	loc_ecx = 0;
	if (!CLI_ISCONTAINED(dest, dsize, alvalue, 1)) {
		cli_dbgmsg("Upack: alvalue out of bounds\n");
		return -1;
	}

	searchval = *alvalue&0xff;
	cli_dbgmsg("Upack: loops: %08x search value: %02x\n", save3, searchval);
	while(save3) {
		if (!CLI_ISCONTAINED(dest, dsize, pushed_esi + loc_ecx, 1))
		{
			cli_dbgmsg("Upack: callfixerr %08x %08x = %08x, %08x\n", dest, dsize, dest+dsize, pushed_esi+loc_ecx);
			return -1;
		}
		if (pushed_esi[loc_ecx] == '\xe8' || pushed_esi[loc_ecx] == '\xe9')
		{
			char *adr = (pushed_esi + loc_ecx + 1);
			loc_ecx++;
			if (!CLI_ISCONTAINED(dest, dsize, adr, 4))
			{
				cli_dbgmsg("Upack: callfixerr\n");
				return -1;
			}
			if ((cli_readint32(adr)&0xff) != searchval)
				continue;
			cli_writeint32(adr, EC32(CE32((uint32_t)(cli_readint32(adr)&0xffffff00)))-loc_ecx-4);
			loc_ecx += 4;
			save3--;
		} else 
			loc_ecx++;
	}

	section.raw = 0;
	section.rva = va;
	section.rsz = end_edi-loc_edi;
	section.vsz = end_edi-loc_edi;

	if (!cli_rebuildpe(dest + (upack?0:va), &section, 1, base, original_ep, 0, 0, file)) {
		cli_dbgmsg("Upack: Rebuilding failed\n");
		return 0;
	}
	return 1;
}
コード例 #13
0
ファイル: libclamav_upack.c プロジェクト: 5432935/crossbridge
int unupack399(char *bs, uint32_t bl, uint32_t init_eax, char *init_ebx, uint32_t init_ecx, char *init_edi, char *end_edi, uint32_t shlsize, char *paddr)
{
	struct lzmastate p;
	uint32_t loc_eax, ret, loc_al, loc_ecx = init_ecx, loc_ebp, eax_copy = init_eax, temp, i, jakas_kopia;
	uint32_t state[6], temp_ebp;
	char *loc_edx, *loc_ebx = init_ebx, *loc_edi = init_edi, *loc_ebp8, *edi_copy;
	p.p0 = paddr;
	p.p1 = cli_readint32(init_ebx);
	p.p2 = cli_readint32(init_ebx + 4);

	cli_dbgmsg("\n\tp0: %08x\n\tp1: %08x\n\tp2: %08x\n", p.p0, p.p1, p.p2);
	for (i = 0; i<6; i++)
		state[i] = cli_readint32(loc_ebx + (i<<2)),
		cli_dbgmsg("state[%d] = %08x\n", i, state[i]);
	do {
		loc_eax = eax_copy;
		loc_edx = loc_ebx + (loc_eax<<2) + 0x58;

		if ((ret = lzma_upack_esi_00(&p, loc_edx, bs, bl)))
		{
			/* loc_483927 */
			loc_al = loc_eax&0xff;
			loc_al = ((loc_al + 0xf9) > 0xff)?(3+8):8;
			loc_eax = (loc_eax&0xffffff00)|(loc_al&0xff);
			loc_ebp = state[2];
			loc_ecx = (loc_ecx&0xffffff00)|0x30;
			loc_edx += loc_ecx;
			/* *(uint32_t *)(loc_ebx + 14) = loc_ebp; ???? */
			if (!(ret = lzma_upack_esi_00(&p, loc_edx, bs, bl))) {
				/* loc_48397c */
				loc_eax--;
				/*
				temp_ebp = loc_ebp; loc_ebp = cli_readint32(loc_ebx+0x0c); cli_writeint32(loc_ebx+0x0c, temp_ebp);
				temp_ebp = loc_ebp; loc_ebp = cli_readint32(loc_ebx+0x10); cli_writeint32(loc_ebx+0x10, temp_ebp);
				*/
				temp_ebp = loc_ebp;
				loc_ebp = state[4];
				state[4] = state[3];
				state[3] = temp_ebp;
				eax_copy = loc_eax;
				loc_edx = loc_ebx + 0xbc0;
				state[5] = loc_ebp;
				if (lzma_upack_esi_54(&p, loc_eax, &loc_ecx, &loc_edx, &temp, bs, bl) == 0xffffffff)
					return -1;
				loc_ecx = 3;
				jakas_kopia = temp;
				loc_eax = temp-1;
				if (loc_eax >= loc_ecx)
					loc_eax = loc_ecx;
				loc_ecx = 0x40;
				loc_eax <<= 6; /* ecx=0x40, mul cl */
				loc_ebp8 = loc_ebx + ((loc_eax<<2) + 0x378);
				if (lzma_upack_esi_50(&p, 1, loc_ecx, &loc_edx, loc_ebp8, &loc_eax, bs, bl) == 0xffffffff)
					return -1;
				loc_ebp = loc_eax;
				if ((loc_eax&0xff) >= 4)
				{
					/* loc_4839af */
					loc_ebp = 2 + (loc_eax&1);
					loc_eax >>= 1;
					loc_eax--;
					temp_ebp = loc_eax; loc_eax = loc_ecx; loc_ecx = temp_ebp;
					loc_ebp <<= (loc_ecx&0xff);
					loc_edx = loc_ebx + (loc_ebp<<2) + 0x178;
					if ((loc_ecx&0xff) > 5)
					{
						/* loc_4839c6 */
						loc_ecx = (loc_ecx&0xffffff00)|(((loc_ecx&0xff)-4)&0xff);
						loc_eax = 0;
						do {
							uint32_t temp_edx;
							/* compare with lzma_upack_esi_00 */
							/* do not put in one statment because of difference in signedness */
							if (!CLI_ISCONTAINED(bs, bl, p.p0, 4))
								return -1;
							temp_edx = cli_readint32((char *)p.p0);
							temp_edx = EC32(CE32(temp_edx));
							p.p1 >>= 1;
							temp_edx -= p.p2;
							loc_eax <<= 1;
							if (temp_edx >= p.p1)
							{
								temp_edx = p.p1;
								loc_eax++;
								p.p2 += temp_edx;
							}
							if(((p.p1)&0xff000000) == 0)
							{
								p.p2 <<= 8;
								p.p1 <<= 8;
								p.p0++;
							}
						} while (--loc_ecx);
						/* loc_4839e8 */
						loc_ecx = (loc_ecx&0xffffff00)|4;
						loc_eax <<= 4;
						loc_ebp += loc_eax;
						loc_edx = loc_ebx + 0x18;
					}
					/* loc4839f1 */
					loc_eax = 1;
					loc_eax <<= (loc_ecx&0xff);
					loc_ebp8 = loc_edx;
					temp_ebp = loc_ecx; loc_ecx = loc_eax; loc_eax = temp_ebp;
					if (lzma_upack_esi_50(&p, 1, loc_ecx, &loc_edx, loc_ebp8, &loc_eax, bs, bl) == 0xffffffff)
						return -1;
					/* cdq, loc_edx = (loc_eax&0x80000000)?0xffffffff:0; */
					loc_ecx = temp_ebp;
					temp_ebp = CLI_SRS((int32_t)loc_eax, 31); /* thx, desp */
					/* loc_483a00 */
					do {
						temp_ebp += temp_ebp;
						temp_ebp += (loc_eax&1);
						loc_eax >>= 1;
					} while (--loc_ecx);
					loc_ebp += temp_ebp;
					/* loc_483a06 */
				}
コード例 #14
0
ファイル: macho.c プロジェクト: badania/clamav-devel
int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
{
	struct macho_hdr hdr;
	struct macho_load_cmd load_cmd;
	struct macho_segment_cmd segment_cmd;
	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 arch = 0, ep = 0, err;
	struct cli_exe_section *sections = NULL;
	char name[16];
	fmap_t *map = *ctx->fmap;
	ssize_t at;

    if(fileinfo)
	matcher = 1;

    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;
	m64 = 0;
    } else if(hdr.magic == 0xcefaedfe) {
	conv = 1;
	m64 = 0;
    } else if(hdr.magic == 0xfeedfacf) {
	conv = 0;
	m64 = 1;
    } else if(hdr.magic == 0xcffaedfe) {
	conv = 1;
	m64 = 1;
    } else {
	cli_dbgmsg("cli_scanmacho: Incorrect magic\n");
	return matcher ? -1 : CL_EFORMAT;
    }

    switch(EC32(hdr.cpu_type, conv)) {
	case 7:
	    if(!matcher)
		cli_dbgmsg("MACHO: CPU Type: Intel 32-bit\n");
	    arch = 1;
	    break;
	case 7 | 0x1000000:
	    if(!matcher)
		cli_dbgmsg("MACHO: CPU Type: Intel 64-bit\n");
	    break;
	case 12:
	    if(!matcher)
		cli_dbgmsg("MACHO: CPU Type: ARM\n");
	    break;
	case 14:
	    if(!matcher)
		cli_dbgmsg("MACHO: CPU Type: SPARC\n");
	    break;
	case 18:
	    if(!matcher)
		cli_dbgmsg("MACHO: CPU Type: POWERPC 32-bit\n");
	    arch = 2;
	    break;
	case 18 | 0x1000000:
	    if(!matcher)
		cli_dbgmsg("MACHO: CPU Type: POWERPC 64-bit\n");
	    arch = 3;
	    break;
	default:
	    if(!matcher)
		cli_dbgmsg("MACHO: CPU Type: ** UNKNOWN ** (%u)\n", EC32(hdr.cpu_type, conv));
	    break;
    }

    if(!matcher) switch(EC32(hdr.filetype, conv)) {
	case 0x1: /* MH_OBJECT */
	    cli_dbgmsg("MACHO: Filetype: Relocatable object file\n");
	    break;
	case 0x2: /* MH_EXECUTE */
	    cli_dbgmsg("MACHO: Filetype: Executable\n");
	    break;
	case 0x3: /* MH_FVMLIB */
	    cli_dbgmsg("MACHO: Filetype: Fixed VM shared library file\n");
	    break;
	case 0x4: /* MH_CORE */
	    cli_dbgmsg("MACHO: Filetype: Core file\n");
	    break;
	case 0x5: /* MH_PRELOAD */
	    cli_dbgmsg("MACHO: Filetype: Preloaded executable file\n");
	    break;
	case 0x6: /* MH_DYLIB */
	    cli_dbgmsg("MACHO: Filetype: Dynamically bound shared library\n");
	    break;
	case 0x7: /* MH_DYLINKER */
	    cli_dbgmsg("MACHO: Filetype: Dynamic link editor\n");
	    break;
	case 0x8: /* MH_BUNDLE */
	    cli_dbgmsg("MACHO: Filetype: Dynamically bound bundle file\n");
	    break;
	case 0x9: /* MH_DYLIB_STUB */
	    cli_dbgmsg("MACHO: Filetype: Shared library stub for static\n");
	    break;
	default:
	    cli_dbgmsg("MACHO: Filetype: ** UNKNOWN ** (0x%x)\n", EC32(hdr.filetype, conv));
    }

    if(!matcher) {
	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));
    }

    if(m64)
	at += 4;

    hdr.ncmds = EC32(hdr.ncmds, conv);
    if(!hdr.ncmds || hdr.ncmds > 1024) {
	cli_dbgmsg("cli_scanmacho: Invalid number of load commands (%u)\n", hdr.ncmds);
	RETURN_BROKEN;
    }

    for(i = 0; i < hdr.ncmds; i++) {
	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));
	    free(sections);
	    RETURN_BROKEN;
	}
	*/
	load_cmd.cmd = EC32(load_cmd.cmd, conv);
	if((m64 && load_cmd.cmd == 0x19) || (!m64 && load_cmd.cmd == 0x01)) { /* LC_SEGMENT */
	    if(m64) {
		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, sizeof(name));
        name[sizeof(name)-1] = '\0';
	    } else {
		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, sizeof(name));
	    }
	    if(!matcher) {
		name[sizeof(name)-1] = '\0';
		cli_dbgmsg("MACHO: Segment name: %s\n", name);
		cli_dbgmsg("MACHO: Number of sections: %u\n", nsects);
	    }
	    if(nsects > 255) {
		cli_dbgmsg("cli_scanmacho: Invalid number of sections\n");
		free(sections);
		RETURN_BROKEN;
	    }
	    if(!nsects) {
		if(!matcher)
		    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;
	    }

	    for(j = 0; j < nsects; j++) {
		if(m64) {
		    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);
		    section64.align = 1 << EC32(section64.align, conv);
		    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, sizeof(name));
		} else {
		    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);
		    section.align = 1 << EC32(section.align, conv);
		    sections[sect].rsz = sections[sect].vsz + (section.align - (sections[sect].vsz % section.align)) % section.align;
		    strncpy(name, section.sectname, sizeof(name));
		}
		if(!matcher) {
		    name[sizeof(name)-1] = '\0';
		    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);
		    cli_dbgmsg("MACHO: Virtual size: %u\n", (unsigned int) sections[sect].vsz);
		    cli_dbgmsg("MACHO: Raw size: %u\n", (unsigned int) sections[sect].rsz);
		    if(sections[sect].raw)
			cli_dbgmsg("MACHO: File offset: %u\n", (unsigned int) sections[sect].raw);
		}
		sect++;
	    }
	    if(!matcher)
		cli_dbgmsg("MACHO: ------------------\n");

	} else if(arch && (load_cmd.cmd == 0x4 || load_cmd.cmd == 0x5)) { /* LC_(UNIX)THREAD */
	    at += 8;
	    switch(arch) {
		case 1: /* x86 */
		{
			struct macho_thread_state_x86 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;
		}

		case 2: /* PPC */
		{
			struct macho_thread_state_ppc 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;
		}

		case 3: /* PPC64 */
		{
			struct macho_thread_state_ppc64 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;
		}
		default:
		    cli_errmsg("cli_scanmacho: Invalid arch setting!\n");
		    free(sections);
		    return matcher ? -1 : CL_EARG;
	    }
	} else {
	    if(EC32(load_cmd.cmdsize, conv) > sizeof(load_cmd))
		at += EC32(load_cmd.cmdsize, conv) - sizeof(load_cmd);
	}
    }

    if(ep) {
	if(!matcher)
	    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;
	    }
	    if(!matcher)
		cli_dbgmsg("Entry Point file offset: %u\n", ep);
	}
    }

    if(matcher) {
	fileinfo->ep = ep;
	fileinfo->nsections = sect;
	fileinfo->section = sections;
	return 0;
    } else {
	free(sections);
	return CL_SUCCESS;
    }
}
コード例 #15
0
ファイル: nulsft.c プロジェクト: rossguide/clamav-devel
static int nsis_unpack_next(struct nsis_st *n, cli_ctx *ctx) {
  const unsigned char *ibuf;
  uint32_t size, loops;
  int ret, gotsome=0, opened=0;
  unsigned char obuf[BUFSIZ];

  if (n->eof) {
    cli_dbgmsg("NSIS: extraction complete\n");
    return CL_BREAK;
  }
  
  if ((ret=cli_checklimits("NSIS", ctx, 0, 0, 0))!=CL_CLEAN)
    return ret;

  if (n->fno)
    snprintf(n->ofn, 1023, "%s"PATHSEP"content.%.3u", n->dir, n->fno);
  else
    snprintf(n->ofn, 1023, "%s"PATHSEP"headers", n->dir);

  n->fno++;
  n->opened = 0;

  if (!n->solid) {
    if (fmap_readn(n->map, &size, n->curpos, 4)!=4) {
      cli_dbgmsg("NSIS: reached EOF - extraction complete\n");
      return CL_BREAK;
    }
    n->curpos += 4;
    if (n->asz==4) {
      cli_dbgmsg("NSIS: reached CRC - extraction complete\n");
      return CL_BREAK;
    }
    loops = EC32(size);
    if (!(size = (loops&~0x80000000))) {
      cli_dbgmsg("NSIS: empty file found\n");
      return CL_SUCCESS;
    }
    if (n->asz <4 || size > n->asz-4) {
      cli_dbgmsg("NSIS: next file is outside the archive\n");
      return CL_BREAK;
    }

    n->asz -= size+4;

    if ((ret=cli_checklimits("NSIS", ctx, size, 0, 0))!=CL_CLEAN) {
      n->curpos += size;
      return ret;
    }
    if (!(ibuf = fmap_need_off_once(n->map, n->curpos, size))) {
      cli_dbgmsg("NSIS: cannot read %u bytes"__AT__"\n", size);
      return CL_EREAD;
    }
  if ((n->ofd=open(n->ofn, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600))==-1) {
    cli_errmsg("NSIS: unable to create output file %s - aborting.", n->ofn);
    return CL_ECREAT;
  }
  n->opened = 1;
    n->curpos += size;
    if (loops==size) {

      if (cli_writen(n->ofd, ibuf, size) != (ssize_t) size) {
	cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
	close(n->ofd);
	return CL_EWRITE;
      }
    } else {
      if ((ret=nsis_init(n))!=CL_SUCCESS) {
	cli_dbgmsg("NSIS: decompressor init failed"__AT__"\n");
	close(n->ofd);
	return ret;
      }
      
      n->nsis.avail_in = size;
      n->nsis.next_in = (void*)ibuf;
      n->nsis.next_out = obuf;
      n->nsis.avail_out = BUFSIZ;
      loops=0;

      while ((ret=nsis_decomp(n))==CL_SUCCESS) {
	if ((size = n->nsis.next_out - obuf)) {
	  gotsome=1;
	  if (cli_writen(n->ofd, obuf, size) != (ssize_t) size) {
	    cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
	    close(n->ofd);
	    nsis_shutdown(n);
	    return CL_EWRITE;
	  }
	  n->nsis.next_out = obuf;
	  n->nsis.avail_out = BUFSIZ;
	  loops=0;
	  if ((ret=cli_checklimits("NSIS", ctx, size, 0, 0))!=CL_CLEAN) {
	    close(n->ofd);
	    nsis_shutdown(n);
	    return ret;
	  }
	} else if (++loops > 20) {
	  cli_dbgmsg("NSIS: xs looping, breaking out"__AT__"\n");
	  ret = CL_EFORMAT;
	  break;
	}
      }

      nsis_shutdown(n);

      if (n->nsis.next_out - obuf) {
	gotsome=1;
	if (cli_writen(n->ofd, obuf, n->nsis.next_out - obuf) != n->nsis.next_out - obuf) {
	  cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
	  close(n->ofd);
	  return CL_EWRITE;
	}
      }

      if (ret != CL_SUCCESS && ret != CL_BREAK) {
	cli_dbgmsg("NSIS: bad stream"__AT__"\n");
	if (gotsome) {
	  ret = CL_SUCCESS;
	} else {
	  ret = CL_EMAXSIZE;
	  close(n->ofd);
	}
	return ret;
      }

    }

    return CL_SUCCESS;

  } else {
    if (!n->freeme) {
      if ((ret=nsis_init(n))!=CL_SUCCESS) {
	cli_dbgmsg("NSIS: decompressor init failed\n");
	return ret;
      }
      if(!(n->freeme = fmap_need_off_once(n->map, n->curpos, n->asz))) {
	cli_dbgmsg("NSIS: cannot read %u bytes"__AT__"\n", n->asz);
	return CL_EREAD;
      }
      n->nsis.next_in = (void*)n->freeme;
      n->nsis.avail_in = n->asz;
    }

    if (n->nsis.avail_in<=4) {
      cli_dbgmsg("NSIS: extraction complete\n");
      return CL_BREAK;
    }
    n->nsis.next_out = obuf;
    n->nsis.avail_out = 4;
    loops = 0;

    while ((ret=nsis_decomp(n))==CL_SUCCESS) {
      if (n->nsis.next_out - obuf == 4) break;
      if (++loops > 20) {
	cli_dbgmsg("NSIS: xs looping, breaking out"__AT__"\n");
	ret = CL_BREAK;
	break;
      }
    }

    if (ret != CL_SUCCESS) {
      cli_dbgmsg("NSIS: bad stream"__AT__"\n");
      return CL_EFORMAT;
    }

    size=cli_readint32(obuf);
    if ((ret=cli_checklimits("NSIS", ctx, size, 0, 0))!=CL_CLEAN) {
      return ret;
    }

    if (size == 0) {
        cli_dbgmsg("NSIS: Empty file found.\n");
        return CL_SUCCESS;
    }

    n->nsis.next_out = obuf;
    n->nsis.avail_out = MIN(BUFSIZ,size);
    loops = 0;

      if ((n->ofd=open(n->ofn, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600))==-1) {
        cli_errmsg("NSIS: unable to create output file %s - aborting.", n->ofn);
        return CL_ECREAT;
      }
      n->opened = 1;

    while (size && (ret=nsis_decomp(n))==CL_SUCCESS) {
      unsigned int wsz;
      if ((wsz = n->nsis.next_out - obuf)) {
	gotsome=1;
	if (cli_writen(n->ofd, obuf, wsz) != (ssize_t) wsz) {
	  cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
	  close(n->ofd);
	  return CL_EWRITE;
	}
	size-=wsz;
	loops=0;
	n->nsis.next_out = obuf;
	n->nsis.avail_out = MIN(size,BUFSIZ);
      } else if ( ++loops > 20 ) {
	cli_dbgmsg("NSIS: xs looping, breaking out"__AT__"\n");
	ret = CL_EFORMAT;
	break;
      }
    }

    if (n->nsis.next_out - obuf) {
      gotsome=1;
      if (cli_writen(n->ofd, obuf, n->nsis.next_out - obuf) != n->nsis.next_out - obuf) {
	cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
	close(n->ofd);
	return CL_EWRITE;
      }
    }

    if (ret == CL_EFORMAT) {
      cli_dbgmsg("NSIS: bad stream"__AT__"\n");
      if (!gotsome) {
	close(n->ofd);
	return CL_EMAXSIZE;
      } 
    }

    if (ret == CL_EFORMAT || ret == CL_BREAK) {
      n->eof=1;
    } else if (ret != CL_SUCCESS) {
      cli_dbgmsg("NSIS: bad stream"__AT__"\n");
      close(n->ofd);
      return CL_EFORMAT;
    }
    return CL_SUCCESS;
  }

}
コード例 #16
0
ファイル: libclamav_unzip.c プロジェクト: 5432935/crossbridge
static int __zip_find_disk_trailer(int fd, off_t filesize, struct zip_disk_trailer *trailer, off_t *start)
{
	char *buf, *end, *tail;
	off_t offset = 0, bufsize;
	struct zip_root_dirent dirent;
	uint32_t u_rootseek, shift = 0;
	int i;


    if(!trailer) {
	cli_errmsg("Unzip: __zip_find_disk_trailer: trailer == NULL\n");
	return CL_ENULLARG;
    }

    if(filesize < __sizeof(struct zip_disk_trailer)) {
	cli_errmsg("Unzip: __zip_find_disk_trailer: File too short\n");
	return CL_EFORMAT;
    }

    if(!(buf = cli_malloc(ZIPBUFSIZ)))
	return CL_EMEM;

    offset = filesize;
    while(1) {

	if(offset <= 0) {
	     cli_dbgmsg("Unzip: __zip_find_disk_trailer: Central directory not found\n");
	     free(buf);
	     return CL_EFORMAT;
	}

	if(offset >= ZIPBUFSIZ) {
	    if(offset == filesize)
		offset -= ZIPBUFSIZ;
	    else
		offset -= ZIPBUFSIZ - sizeof(struct zip_disk_trailer);

	    bufsize = ZIPBUFSIZ;
	} else {
	    if(filesize < ZIPBUFSIZ)
		bufsize = offset;
	    else
		bufsize = ZIPBUFSIZ;

	    offset = 0;
	}

        if(lseek(fd, offset, SEEK_SET) < 0) {
	    cli_errmsg("Unzip: __zip_find_disk_trailer: Can't lseek descriptor %d\n", fd);
	    free(buf);
	    return CL_EIO;
	}

        if(cli_readn(fd, buf, (size_t) bufsize) < (ssize_t) bufsize) {
	    cli_errmsg("Unzip: __zip_find_disk_trailer: Can't read %u bytes\n", (unsigned int) bufsize);
	    free(buf);
	    return CL_EIO;
	}

	end = buf + bufsize;
	for(tail = end - 1; tail >= buf; tail--) {
	    if((*tail == 'P') && (end - tail >= __sizeof(struct zip_disk_trailer) - 2) && cli_readint32(tail) == ZIP_DISK_TRAILER_MAGIC) {
		if(end - tail >= __sizeof(struct zip_disk_trailer)) {
		    memcpy(trailer, tail, sizeof(struct zip_disk_trailer)); 
		} else {
		    memcpy(trailer, tail, sizeof(struct zip_disk_trailer) - 2);
		    trailer->z_comment = 0; 
		}
		__fixup_rootseek(offset + tail - buf, trailer);

		u_rootseek = EC32(trailer->z_rootseek);
		if(u_rootseek > (uint32_t) filesize) {
		    cli_dbgmsg("Unzip: __zip_find_disk_trailer: u_rootseek > filesize, continue search\n");
		    continue;
		}

		for(i = 0; i < 2; i++) {
		    if(u_rootseek + shift + sizeof(dirent) < (uint32_t) filesize) {
			if(lseek(fd, u_rootseek + shift, SEEK_SET) < 0) {
			    cli_errmsg("Unzip: __zip_find_disk_trailer: Can't lseek descriptor %d\n", fd);
			    free(buf);
			    return CL_EIO;
			}

			if(cli_readn(fd, &dirent, sizeof(dirent)) < __sizeof(dirent)) {
			    cli_errmsg("Unzip: __zip_find_disk_trailer: Can't read %u bytes\n", (unsigned int) bufsize);
			    free(buf);
			    return CL_EIO;
			}

			if(EC32(dirent.z_magic) == ZIP_ROOT_DIRENT_MAGIC) {
			    cli_dbgmsg("Unzip: __zip_find_disk_trailer: found file header at %u, shift %u\n", u_rootseek + shift, shift);
			    free(buf);
			    *start = shift;
			    return CL_SUCCESS;
			}

			shift = *start;
		    }
		}
	    }
	}
    }