예제 #1
0
static char *checkpe(char *dst, uint32_t dsize, char *pehdr, uint32_t *valign, unsigned int *sectcnt)
{
  char *sections;
  if (!CLI_ISCONTAINED(dst, dsize,  pehdr, 0xf8)) return NULL;

  if (cli_readint32(pehdr) != 0x4550 ) return NULL;
  
  if (!(*valign=cli_readint32(pehdr+0x38))) return NULL;
  
  sections = pehdr+0xf8;
  if (!(*sectcnt = (unsigned char)pehdr[6] + (unsigned char)pehdr[7]*256)) return NULL;
  
  if (!CLI_ISCONTAINED(dst, dsize, sections, *sectcnt*0x28)) return NULL;

  return sections;
}
예제 #2
0
END_TEST

/* test reading with different alignments, _i is parameter from tcase_add_loop_test */
START_TEST (test_cli_readint32)
{
    size_t j;
    int32_t value = le_expected[_i&3];
    /* read 4 bytes apart, start is not always aligned*/
    for(j=_i;j < DATA_REP*sizeof(le_data)-4;j += 4) {
        fail_unless(cli_readint32(&data[j]) == value, "(1) data read must be little endian");
    }
    value = le_expected[0];
    /* read 4 bytes apart, always aligned*/
    for(j=0;j < DATA_REP*sizeof(le_data)-4;j += 4) {
        fail_unless(cli_readint32(&data[j]) == value, "(2) data read must be little endian");
    }
}
예제 #3
0
END_TEST

/* test writing with different alignments, _i is parameter from tcase_add_loop_test */
START_TEST (test_cli_writeint32)
{
    size_t j;
    /* write 4 bytes apart, start is not always aligned*/
    for(j=_i;j < DATA_REP*sizeof(le_data) - 4;j += 4) {
        cli_writeint32(&data2[j], 0x12345678);
    }
    for(j=_i;j < DATA_REP*sizeof(le_data) - 4;j += 4) {
        fail_unless(cli_readint32(&data2[j]) == 0x12345678, "write/read mismatch");
    }
    /* write 4 bytes apart, always aligned*/
    for(j=0;j < DATA_REP*sizeof(le_data) - 4;j += 4) {
        cli_writeint32(&data2[j], 0x12345678);
    }
    for(j=0;j < DATA_REP*sizeof(le_data) - 4;j += 4) {
        fail_unless(cli_readint32(&data2[j]) == 0x12345678, "write/read mismatch");
    }
}
/* test file extract API */
int entrypoint(void)
{
  unsigned char buf[4];
  /* fixme:compiler assumes LE here = {1, 2, 3, 4}; */
  uint32_t x, i;
  uint64_t y;
  *(uint32_t*)buf = le32_to_host(0x04030201);
  for (i=0;i<3;i++) {
    extract_new(i);
    if (write(buf, sizeof(buf)) != sizeof(buf))
      return 0xbad1;
    /* switch input to extracted file */
    if (input_switch(1) != 0)
      return 0xbad2;
    if (seek(0, SEEK_END) != 4)
      return 0xbad3;
    if (seek(0, SEEK_SET) != 0)
      return 0xbad4;
    x = 0x5a5a5a5a;
    if (read(&x, sizeof(x)) != sizeof(x))
      return 0xbad5;
    if (cli_readint32(&x) != 0x04030201)
      return 0xbad6;
    /* switch back to normal file */
    if (input_switch(0) != 0)
      return 0xbad7;
    if (seek(0, SEEK_SET) != 0)
      return 0xbad8;
    if (read(&x, sizeof(x)) != sizeof(x))
      return 0xbad9;
    x = le32_to_host(x);
    if (x != 0x44434241)
      return 0xbad10;
    /* write to extracted file again */
    if (write(buf, sizeof(buf)) != sizeof(buf))
      return 0xbad11;
    /* switch input to extracted file */
    if (input_switch(1) != 0)
      return 0xbad12;
    if (seek(0, SEEK_END) != 8)
      return 0xbad13;
    if (seek(0, SEEK_SET) != 0)
      return 0xbad14;
    if (read(&y, sizeof(y)) != sizeof(y))
      return 0xbad15;
    y = le64_to_host(y);
    if (y != 0x0403020104030201UL)
      return 0xbad16;
    if (input_switch(0) != 0)
      return 0xbad17;
  }
  return 0xf00d;
}
예제 #5
0
파일: lzma_iface.c 프로젝트: OPSF/uClinux
int cli_LzmaInit(CLI_LZMA **Lp, uint64_t size_override) {
  CLI_LZMA *L = *Lp;

  if(!L) {
	  *Lp = L = cli_calloc(sizeof(*L), 1);
	  if(!L) {
		  return CL_EMEM;
	  }
  }

  L->initted = 0;
  if(size_override) L->usize=size_override;

  if (!L->next_in || L->avail_in < LZMA_PROPERTIES_SIZE + 8) return LZMA_RESULT_OK;
  if (LzmaDecodeProperties(&L->state.Properties, L->next_in, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
    return LZMA_RESULT_DATA_ERROR;

  L->next_in += LZMA_PROPERTIES_SIZE;
  L->avail_in -= LZMA_PROPERTIES_SIZE;

  if (!L->usize) {
    L->usize=(uint64_t)cli_readint32(L->next_in) + ((uint64_t)cli_readint32(L->next_in+4)<<32);
    L->next_in += 8;
    L->avail_in -= 8;
  }
    
  if (!(L->state.Probs = (CProb *)cli_malloc(LzmaGetNumProbs(&L->state.Properties) * sizeof(CProb))))
    return LZMA_RESULT_DATA_ERROR;

  if (!(L->state.Dictionary = (unsigned char *)cli_malloc(L->state.Properties.DictionarySize))) {
    free(L->state.Probs);
    return LZMA_RESULT_DATA_ERROR;
  }

  L->initted = 1;

  LzmaDecoderInit(&L->state);
  return LZMA_RESULT_OK;
}
예제 #6
0
static int doubleebx(const char *src, uint32_t *myebx, uint32_t *scur, uint32_t ssize)
{
  uint32_t oldebx = *myebx;

  *myebx*=2;
  if ( !(oldebx & 0x7fffffff)) {
    if (! CLI_ISCONTAINED(src, ssize, src+*scur, 4))
      return -1;
    oldebx = cli_readint32(src+*scur);
    *myebx = oldebx*2+1;
    *scur+=4;
  }
  return (oldebx>>31);
}
예제 #7
0
파일: unzip.c 프로젝트: nayden/clamav-devel
int cli_unzip(cli_ctx *ctx) {
    unsigned int fc=0, fu=0;
    int ret=CL_CLEAN;
    uint32_t fsize, lhoff = 0, coff = 0;
    fmap_t *map = *ctx->fmap;
    char *tmpd;
    const char *ptr;
    int virus_found = 0;
#if HAVE_JSON
    int toval = 0;
#endif

    cli_dbgmsg("in cli_unzip\n");
    fsize = (uint32_t)map->len;
    if(sizeof(off_t)!=sizeof(uint32_t) && (size_t)fsize!=map->len) {
        cli_dbgmsg("cli_unzip: file too big\n");
        return CL_CLEAN;
    }
    if (fsize < SIZEOF_CH) {
        cli_dbgmsg("cli_unzip: file too short\n");
        return CL_CLEAN;
    }
    if (!(tmpd = cli_gentemp(ctx->engine->tmpdir))) {
        return CL_ETMPDIR;
    }
    if (mkdir(tmpd, 0700)) {
        cli_dbgmsg("cli_unzip: Can't create temporary directory %s\n", tmpd);
        free(tmpd);
        return CL_ETMPDIR;
    }

    for(coff=fsize-22 ; coff>0 ; coff--) { /* sizeof(EOC)==22 */
        if(!(ptr = fmap_need_off_once(map, coff, 20)))
            continue;
        if(cli_readint32(ptr)==0x06054b50) {
            uint32_t chptr = cli_readint32(&ptr[16]);
            if(!CLI_ISCONTAINED(0, fsize, chptr, SIZEOF_CH)) continue;
            coff=chptr;
            break;
        }
    }

    if(coff) {
        cli_dbgmsg("cli_unzip: central @%x\n", coff);
        while(ret==CL_CLEAN && (coff=chdr(map, coff, fsize, &fu, fc+1, &ret, ctx, tmpd, NULL))) {
            fc++;
            if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
                cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
                ret=CL_EMAXFILES;
            }
#if HAVE_JSON
            if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) {
                return CL_ETIMEOUT;
            }
#endif

        }
    } else cli_dbgmsg("cli_unzip: central not found, using localhdrs\n");
    if(fu<=(fc/4)) { /* FIXME: make up a sane ratio or remove the whole logic */
        fc = 0;
        while (ret==CL_CLEAN && lhoff<fsize && (coff=lhdr(map, lhoff, fsize-lhoff, &fu, fc+1, NULL, &ret, ctx, tmpd, 1, zip_scan_cb))) {
            fc++;
            lhoff+=coff;
            if (SCAN_ALL && ret == CL_VIRUS) {
                ret = CL_CLEAN;
                virus_found = 1;
            }
            if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
                cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
                ret=CL_EMAXFILES;
            }
#if HAVE_JSON
            if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) {
                return CL_ETIMEOUT;
            }
#endif

        }
    }

    if (!ctx->engine->keeptmp) cli_rmdirs(tmpd);
    free(tmpd);

    if (ret == CL_CLEAN && virus_found)
        ret = CL_VIRUS;

    return ret;
}
예제 #8
0
파일: yc.c 프로젝트: Schnaffon/clamav-devel
int yc_decrypt(cli_ctx *ctx, char *fbuf, unsigned int filesize, struct cli_exe_section *sections, unsigned int sectcount, uint32_t peoffset, int desc, uint32_t ecx,int16_t offset) {
  uint32_t ycsect = sections[sectcount].raw+offset;
  unsigned int i;
  struct pe_image_file_hdr *pe = (struct pe_image_file_hdr*) (fbuf + peoffset);
  char *sname = (char *)pe + EC16(pe->SizeOfOptionalHeader) + 0x18;
  uint32_t max_emu;
  unsigned int ofilesize = filesize;
  /* 

  First layer (decryptor of the section decryptor) in last section 

  Start offset for analyze: Start of yC Section + 0x93
  End offset for analyze: Start of yC Section + 0xC3
  Length to decrypt - ECX = 0xB97

  */
  cli_dbgmsg("yC: offset: %x, length: %x\n", offset, ecx);
  cli_dbgmsg("yC: decrypting decryptor on sect %d\n", sectcount);
  switch (yc_poly_emulator(ctx, fbuf, filesize, fbuf + ycsect + 0x93, fbuf + ycsect + 0xc6, ecx, ecx)) {
  case 2:
      return CL_VIRUS;
  case 1:
      return CL_EUNPACK;
  }
  filesize-=sections[sectcount].ursz;

  /* 

  Second layer (decryptor of the sections) in last section 

  Start offset for analyze: Start of yC Section + 0x457
  End offset for analyze: Start of yC Section + 0x487
  Length to decrypt - ECX = Raw Size of Section

  */


  /* Loop through all sections and decrypt them... */
  for(i=0;i<sectcount;i++) {
    uint32_t name = (uint32_t) cli_readint32(sname+i*0x28);
    if (!sections[i].raw ||
	!sections[i].rsz ||
	name == 0x63727372 || /* rsrc */
	name == 0x7273722E || /* .rsr */
	name == 0x6F6C6572 || /* relo */
	name == 0x6C65722E || /* .rel */
	name == 0x6164652E || /* .eda */
	name == 0x6164722E || /* .rda */
	name == 0x6164692E || /* .ida */
	name == 0x736C742E || /* .tls */
	(name&0xffff) == 0x4379  /* yC */
	) continue;
    cli_dbgmsg("yC: decrypting sect%d\n",i);
    max_emu = filesize - sections[i].raw;
    if (max_emu > filesize) {
      cli_dbgmsg("yC: bad emulation length limit %u\n", max_emu);
      return 1;
    }
    switch (yc_poly_emulator(ctx, fbuf, ofilesize, fbuf + ycsect + (offset == -0x18 ? 0x3ea : 0x457), 
			 fbuf + sections[i].raw, 
			 sections[i].ursz, 
			 max_emu)) {
    case 2:
        return CL_VIRUS;
    case 1:
        return CL_EUNPACK;
    }
  }

  /* Remove yC section */
  pe->NumberOfSections=EC16(sectcount);

  /* Remove IMPORT_DIRECTORY information */
  memset((char *)pe + sizeof(struct pe_image_file_hdr) + 0x68, 0, 8);

  /* OEP resolving */
  /* OEP = DWORD PTR [ Start of yC section+ A0F] */
  cli_writeint32((char *)pe + sizeof(struct pe_image_file_hdr) + 16, cli_readint32(fbuf + ycsect + 0xa0f));

  /* Fix SizeOfImage */
  cli_writeint32((char *)pe + sizeof(struct pe_image_file_hdr) + 0x38, cli_readint32((char *)pe + sizeof(struct pe_image_file_hdr) + 0x38) - sections[sectcount].vsz);

  if (cli_writen(desc, fbuf, filesize)==-1) {
    cli_dbgmsg("yC: Cannot write unpacked file\n");
    return CL_EUNPACK;
  }
  return CL_SUCCESS;
}
예제 #9
0
static uint8_t nsis_detcomp(const char *b) {
  if (*b=='1') return COMP_BZIP2;
  if ((cli_readint32(b)&~0x80000000)==0x5d) return COMP_LZMA;
  return COMP_ZLIB;
}
예제 #10
0
static int nsis_headers(struct nsis_st *n, cli_ctx *ctx) {
  char buf[28];
  struct stat st;
  uint32_t pos;
  int i;
  uint8_t comps[] = {0, 0, 0, 0}, trunc = 0;
  
  if (fstat(n->ifd, &st)==-1 ||
      lseek(n->ifd, n->off, SEEK_SET)==-1 ||
      cli_readn(n->ifd, buf, 28) != 28)
    return CL_EIO;

  n->hsz = (uint32_t)cli_readint32(buf+0x14);
  n->asz = (uint32_t)cli_readint32(buf+0x18);

  cli_dbgmsg("NSIS: Header info - Flags=%x, Header size=%x, Archive size=%x\n", cli_readint32(buf), n->hsz, n->asz);

  if (st.st_size - n->off < (off_t) n->asz) {
    cli_dbgmsg("NSIS: Possibly truncated file\n");
    n->asz = st.st_size - n->off;
    trunc++;
  } else if (st.st_size - n->off != (off_t) n->asz) {
    cli_dbgmsg("NSIS: Overlays found\n");
  }

  n->asz -= 0x1c;

  /* Guess if solid */
  for (i=0, pos=0;pos < n->asz-4;i++) {
    int32_t nextsz;
    if (cli_readn(n->ifd, buf+4, 4)!=4) return CL_EIO;
    nextsz=cli_readint32(buf+4);
    if (!i) n->comp = nsis_detcomp(buf+4);
    if (nextsz&0x80000000) {
      nextsz&=~0x80000000;
      if (cli_readn(n->ifd, buf+4, 4)!=4) return CL_EIO;
      comps[nsis_detcomp(buf+4)]++;
      nextsz-=4;
      pos+=4;
    }
    if ((pos+=4+nextsz) > n->asz) {
      n->solid = 1;
      break;
    }

    if (lseek(n->ifd, nextsz, SEEK_CUR)==-1) return CL_EIO;
  }
  
  if (trunc && i>=2) n->solid=0;

  cli_dbgmsg("NSIS: solid compression%s detected\n", (n->solid)?"":" not");

  /* Guess the compression method */
  if (!n->solid) {
    cli_dbgmsg("NSIS: bzip2 %u - lzma %u - zlib %u\n", comps[1], comps[2], comps[3]);
    n->comp = (comps[1]<comps[2]) ? (comps[2]<comps[3] ? COMP_ZLIB : COMP_LZMA) : (comps[1]<comps[3] ? COMP_ZLIB : COMP_BZIP2);
  }

  if (lseek(n->ifd, n->off+0x1c, SEEK_SET)==-1) return CL_EIO;

  return nsis_unpack_next(n, ctx);
}
예제 #11
0
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;
		    }
		}
	    }
	}
    }
예제 #12
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;
  }

}
예제 #13
0
파일: petite.c 프로젝트: OPSF/uClinux
int petite_inflate2x_1to9(char *buf, uint32_t minrva, uint32_t bufsz, struct cli_exe_section *sections, unsigned int sectcount, uint32_t Imagebase, uint32_t pep, int desc, int version, uint32_t ResRva, uint32_t ResSize)
{
  char *adjbuf = buf - minrva;
  char *packed = NULL;
  uint32_t thisrva=0, bottom = 0, enc_ep=0, irva=0, workdone=0, grown=0x355, skew=0x35;
  int j = 0, oob, mangled = 0, check4resources=0;
  struct cli_exe_section *usects = NULL;
  void *tmpsct = NULL;

  /*
    -] The real thing [-
  */

  /* NOTE: (435063->4350a5) Petite kernel32!imports and error strings */

  /* Here we adjust the start of packed blob, the size of petite code,
   * the difference in size if relocs were stripped
   * See below...
   */

  if ( version == 2 )
    packed = adjbuf + sections[sectcount-1].rva + 0x1b8;
  if ( version == 1 ) {
    packed = adjbuf + sections[sectcount-1].rva + 0x178;
    grown=0x323;    /* My name is Harry potter */
    skew=0x34;
  }

  while (1) {
    char *ssrc, *ddst;
    uint32_t size, srva;
    int backbytes, oldback, backsize, addsize;
    
    if ( ! CLI_ISCONTAINED(buf, bufsz, packed, 4)) {
      if (usects)
	free(usects);
      return 1;
    }
    srva = cli_readint32(packed);

    if (! srva) {
      /* WERE DONE !!! :D */
      int t, upd = 1;

      if ( j <= 0 ) /* Some non petite compressed files will get here */
	return 1;
    
      /* Select * from sections order by rva asc; */
      while ( upd ) {
	upd = 0;
	for (t = 0; t < j-1 ; t++) {
	  uint32_t trva, trsz, tvsz;

	  if ( usects[t].rva <= usects[t+1].rva )
	    continue;
	  trva = usects[t].rva;
	  trsz = usects[t].rsz;
	  tvsz = usects[t].vsz;
	  usects[t].rva = usects[t+1].rva;
	  usects[t].rsz = usects[t+1].rsz;
	  usects[t].vsz = usects[t+1].vsz;
	  usects[t+1].rva = trva;
	  usects[t+1].rsz = trsz;
	  usects[t+1].vsz = tvsz;
	  upd = 1;
	}
      }

      /* Computes virtualsize... we try to guess, actually :O */
      for (t = 0; t < j-1 ; t++) {
	if ( usects[t].vsz != usects[t+1].rva - usects[t].rva )
	  usects[t].vsz = usects[t+1].rva - usects[t].rva;
      }
      
      /*
       * Our encryption is pathetic and out software is lame but
       * we need to claim it's unbreakable.
       * So why dont we just mangle the imports and encrypt the EP?!
       */

      /* Decrypts old entrypoint if we got enough clues */
      if (enc_ep) {
	uint32_t virtaddr = pep + 5 + Imagebase, tmpep;
	int rndm = 0, dummy = 1;
	char *thunk = adjbuf+irva;
	char *imports;

	if ( version == 2 ) { /* 2.2 onley */

	  while ( dummy && CLI_ISCONTAINED(buf, bufsz, thunk, 4) ) {
	    uint32_t api;

	    if (! cli_readint32(thunk)) {
	      workdone = 1;
	      break;
	    }

	    imports = adjbuf + cli_readint32(thunk);
	    thunk+=4;
	    dummy = 0;

	    while ( CLI_ISCONTAINED(buf, bufsz, imports, 4)) {
	      dummy = 0;

	      imports+=4;
	      if ( ! (api = cli_readint32(imports-4)) ) {
		dummy  = 1;
		break;
	      }
	      if ( (api != (api | 0x80000000)) && mangled && --rndm < 0) {
		api = virtaddr;
		virtaddr +=5; /* EB + 1 double */
		rndm = virtaddr & 7;
	      } else {
		api = 0xbff01337; /* KERNEL32!leet */
	      }
	      if (sections[sectcount-1].rva+Imagebase < api )
		enc_ep--;
	      if ( api < virtaddr )
		enc_ep--;
	      tmpep = (enc_ep & 0xfffffff8)>>3 & 0x1fffffff;
	      enc_ep = (enc_ep & 7)<<29 | tmpep;
	    }
	  }
	} else 
	  workdone = 1;
	enc_ep = pep+5+enc_ep;
	if ( workdone == 1 ) {
	  cli_dbgmsg("Petite: Old EP: %x\n", enc_ep);
	} else {
	  enc_ep = usects[0].rva;
	  cli_dbgmsg("Petite: In troubles while attempting to decrypt old EP, using bogus %x\n", enc_ep);
	}
      }

      /* Let's compact data */
      for (t = 0; t < j ; t++) {
	usects[t].raw = (t>0)?(usects[t-1].raw + usects[t-1].rsz):0;
	if (usects[t].rsz != 0) {
	  if(CLI_ISCONTAINED(buf, bufsz, buf + usects[t].raw, usects[t].rsz)) {
	    memmove(buf + usects[t].raw, adjbuf + usects[t].rva, usects[t].rsz);
	  } else {
	    cli_dbgmsg("Petite: Skipping section %d, Raw: %x, RSize:%x\n", t, usects[t].raw, usects[t].rsz);
	    usects[t].raw = t>0 ? usects[t-1].raw : 0;
	    usects[t].rsz = 0;
	  }
	}
      }

      /* Showtime!!! */
      cli_dbgmsg("Petite: Sections dump:\n");
      for (t = 0; t < j ; t++)
	cli_dbgmsg("Petite: .SECT%d RVA:%x VSize:%x ROffset: %x, RSize:%x\n", t, usects[t].rva, usects[t].vsz, usects[t].raw, usects[t].rsz);
      if (! cli_rebuildpe(buf, usects, j, Imagebase, enc_ep, ResRva, ResSize, desc)) {
	cli_dbgmsg("Petite: Rebuilding failed\n");
	free(usects);
	return 1;
      }
      free(usects);
      return 0;
    }
예제 #14
0
int wwunpack(uint8_t *exe, uint32_t exesz, uint8_t *wwsect, struct cli_exe_section *sects, uint16_t scount, uint32_t pe, int desc) {
  uint8_t *structs = wwsect + 0x2a1, *compd, *ccur, *unpd, *ucur, bc;
  uint32_t src, srcend, szd, bt, bits;
  int error=0, i;

  cli_dbgmsg("in wwunpack\n");
  while (1) {
    if (!CLI_ISCONTAINED(wwsect, sects[scount].rsz, structs, 17)) {
      cli_dbgmsg("WWPack: Array of structs out of section\n");
      break;
    }
    src = sects[scount].rva - cli_readint32(structs); /* src delta / dst delta - not used / dwords / end of src */
    structs+=8;
    szd = cli_readint32(structs) * 4;
    structs+=4;
    srcend = cli_readint32(structs);
    structs+=4;

    unpd = ucur = exe+src+srcend+4-szd;
    if (!szd || !CLI_ISCONTAINED(exe, exesz, unpd, szd)) {
      cli_dbgmsg("WWPack: Compressed data out of file\n");
      break;
    }
    cli_dbgmsg("WWP: src: %x, szd: %x, srcend: %x - %x\n", src, szd, srcend, srcend+4-szd);
    if (!(compd = cli_malloc(szd))) {
        cli_dbgmsg("WWPack: Unable to allocate memory for compd\n");
        break;
    }
    memcpy(compd, unpd, szd);
    memset(unpd, -1, szd); /*FIXME*/
    ccur=compd;
    
    RESEED;
    while(!error) {
      uint32_t backbytes, backsize;
      uint8_t saved;

      BIT;
      if (!bits) { /* BYTE copy */
	if(ccur-compd>=szd || !CLI_ISCONTAINED(exe, exesz, ucur, 1))
	  error=1;
	else
	  *ucur++=*ccur++;
	continue;
      }

      BITS(2);
      if(bits==3) { /* WORD backcopy */
	uint8_t shifted, subbed = 31;
	BITS(2);
	shifted = bits + 5;
	if(bits>=2) {
	  shifted++;
	  subbed += 0x80;
	}
	backbytes = (1<<shifted)-subbed; /* 1h, 21h, 61h, 161h */
	BITS(shifted); /* 5, 6, 8, 9 */
	if(error || bits == 0x1ff) break;
	backbytes+=bits;
	if(!CLI_ISCONTAINED(exe, exesz, ucur, 2) || !CLI_ISCONTAINED(exe, exesz, ucur-backbytes, 2)) {
	  error=1;
	} else {
	  ucur[0]=*(ucur-backbytes);
	  ucur[1]=*(ucur-backbytes+1);
	  ucur+=2;
	}
	continue;
      }

      /* BLOCK backcopy */
      saved = bits; /* cmp al, 1 / pushf */

      BITS(3);
      if (bits<6) {
	backbytes = bits;
	switch(bits) {
	case 4: /* 10,11 */
	  backbytes++;
	case 3: /* 8,9 */
	  BIT;
	  backbytes+=bits;
	case 0:	case 1:	case 2: /* 5,6,7 */
	  backbytes+=5;
	  break;
	case 5: /* 12 */
	  backbytes=12;
	  break;
	}
	BITS(backbytes);
	bits+=(1<<backbytes)-31;
      } else if(bits==6) {
	BITS(0x0e);
	bits+=0x1fe1;
      } else {
	BITS(0x0f);
	bits+=0x5fe1;
      }

      backbytes = bits;

      /* popf / jb */
      if (!saved) {
	BIT;
	if(!bits) {
	  BIT;
	  bits+=5;
	} else {
	  BITS(3);
	  if(bits) {
	    bits+=6;
	  } else {
	    BITS(4);
	    if(bits) {
	      bits+=13;
	    } else {
	      uint8_t cnt = 4;
	      uint16_t shifted = 0x0d;
	      
	      do {
		if(cnt==7) { cnt = 0x0e; shifted = 0; break; }
		shifted=((shifted+2)<<1)-1;
		BIT;
		cnt++;
	      } while(!bits);
	      BITS(cnt);
	      bits+=shifted;
	    }
	  }
	}
	backsize = bits;
      } else {
	backsize = saved+2;
      }

      if(!CLI_ISCONTAINED(exe, exesz, ucur, backsize) || !CLI_ISCONTAINED(exe, exesz, ucur-backbytes, backsize)) error=1;
      else while(backsize--) {
	*ucur=*(ucur-backbytes);
	ucur++;
      }
    }
    free(compd);
    if(error) {
      cli_dbgmsg("WWPack: decompression error\n");
      break;
    }
    if (error || !*structs++) break;
  }

  if(!error) {
    exe[pe+6]=(uint8_t)scount;
    exe[pe+7]=(uint8_t)(scount>>8);
    cli_writeint32(&exe[pe+0x28], cli_readint32(wwsect+0x295)+sects[scount].rva+0x299);
    cli_writeint32(&exe[pe+0x50], cli_readint32(&exe[pe+0x50])-sects[scount].vsz);

    structs = &exe[(0xffff&cli_readint32(&exe[pe+0x14]))+pe+0x18];
    for(i=0 ; i<scount ; i++) {
	  if (!CLI_ISCONTAINED(exe, exesz, structs, 0x28)) {
	    cli_dbgmsg("WWPack: structs pointer out of bounds\n");
	    return CL_EFORMAT;
	  }

      cli_writeint32(structs+8, sects[i].vsz);
      cli_writeint32(structs+12, sects[i].rva);
      cli_writeint32(structs+16, sects[i].vsz);
      cli_writeint32(structs+20, sects[i].rva);
      structs+=0x28;
    }
	if (!CLI_ISCONTAINED(exe, exesz, structs, 0x28)) {
	  cli_dbgmsg("WWPack: structs pointer out of bounds\n");
	  return CL_EFORMAT;
	}

    memset(structs, 0, 0x28);
    error = (uint32_t)cli_writen(desc, exe, exesz)!=exesz;
  }
예제 #15
0
int unspin(char *src, int ssize, struct cli_exe_section *sections, int sectcnt, uint32_t nep, int desc, cli_ctx *ctx) {
  char *curr, *emu, *ep, *spinned;
  char **sects;
  int blobsz=0, j;
  uint32_t key32, bitmap, bitman;
  uint32_t len;
  uint8_t key8;

  cli_dbgmsg("in unspin\n");

  if ((spinned = (char *) cli_malloc(sections[sectcnt].rsz)) == NULL )
    return 1;

  memcpy(spinned, src + sections[sectcnt].raw, sections[sectcnt].rsz); 
  ep = spinned + nep - sections[sectcnt].rva;

  curr = ep+0xdb;
  if ( *curr != '\xbb' ) {
    free(spinned);
    cli_dbgmsg("spin: Not spinned or bad version\n");
    return 1;
  }
  
  key8 = (uint8_t)*++curr;
  curr+=4;
  if ( *curr != '\xb9' ) {
    free(spinned);
    cli_dbgmsg("spin: Not spinned or bad version\n");
    return 1;
  }

  if ( (len = cli_readint32(curr+1)) != 0x11fe ) {
    free(spinned);
    cli_dbgmsg("spin: Not spinned or bad version\n");
    return 1;
  }

  cli_dbgmsg("spin: Key8 is %x, Len is %x\n", key8, len);

  if (!CLI_ISCONTAINED(spinned, sections[sectcnt].rsz, ep, len+0x1fe5-1) || !CLI_ISCONTAINED(spinned, sections[sectcnt].rsz, ep+0x3217, 4)) {
    free(spinned);
    cli_dbgmsg("spin: len or key out of bounds, giving up\n");
    return 1;
  }

  if ( ep[0x1e0]!='\xb8' )
    cli_dbgmsg("spin: prolly not spinned, expect failure\n");
  
  if ( (cli_readint32(ep+0x1e1) & 0x00200000) )
    cli_dbgmsg("spin: password protected, expect failure\n");

  curr = ep+0x1fe5+len-1;
  while ( len-- ) {
    *curr=(*curr)^(key8--);
    curr--;
  }

  curr = ep+0x26eb;
  key32 = cli_readint32(curr);
  if ( (len = cli_readint32(curr+5)) != 0x5a0) {
    free(spinned);
    cli_dbgmsg("spin: Not spinned or bad version\n");
    return 1;
  }

  curr = ep+0x2d5;
  cli_dbgmsg("spin: Key is %x, Len is %x\n", key32, len);

  while ( len-- ) {
    if ( key32 & 1 ) {
      key32 = key32>>1;
      key32 ^= 0x8c328834;
    } else {
예제 #16
0
static int pefromupx (const char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t ep, uint32_t upx0, uint32_t upx1, uint32_t *magic, uint32_t dend)
{
  char *imports, *sections=NULL, *pehdr=NULL, *newbuf;
  unsigned int sectcnt=0, upd=1;
  uint32_t realstuffsz=0, valign=0;
  uint32_t foffset=0xd0+0xf8;

  if((dst == NULL) || (src == NULL))
    return 0;

  while ((valign=magic[sectcnt++])) {
    if ( ep - upx1 + valign <= ssize-5  &&    /* Wondering how we got so far?! */
	 src[ep - upx1 + valign - 2] == '\x8d' && /* lea edi, ...                  */
	 src[ep - upx1 + valign - 1] == '\xbe' )  /* ... [esi + offset]          */
      break;
  }

  if (!valign && ep - upx1 + 0x80 < ssize-8) {
    const char *pt = &src[ep - upx1 + 0x80];
    cli_dbgmsg("UPX: bad magic - scanning for imports\n");
    
    while ((pt=cli_memstr(pt, ssize - (pt-src) - 8, "\x8d\xbe", 2))) {
      if (pt[6] == '\x8b' && pt[7] == '\x07') { /* lea edi, [esi+imports] / mov eax, [edi] */
	valign=pt-src+2-ep+upx1;
	break;
      }
      pt++;
    }
  }

  if (valign && CLI_ISCONTAINED(src, ssize, src + ep - upx1 + valign, 4)) {
    imports = dst + cli_readint32(src + ep - upx1 + valign);
    
    realstuffsz = imports-dst;
    
    if (realstuffsz >= *dsize ) {
      cli_dbgmsg("UPX: wrong realstuff size\n");
      /* fallback and eventually craft */
    } else {
      pehdr = imports;
      while (CLI_ISCONTAINED(dst, *dsize,  pehdr, 8) && cli_readint32(pehdr)) {
	pehdr+=8;
	while(CLI_ISCONTAINED(dst, *dsize,  pehdr, 2) && *pehdr) {
	  pehdr++;
	  while (CLI_ISCONTAINED(dst, *dsize,  pehdr, 2) && *pehdr)
	    pehdr++;
	  pehdr++;
	}
	pehdr++;
      }
      
      pehdr+=4;
      if (!(sections=checkpe(dst, *dsize, pehdr, &valign, &sectcnt))) pehdr=NULL;
    }
  }

  if (!pehdr && dend>0xf8+0x28) {
    cli_dbgmsg("UPX: no luck - scanning for PE\n");
    pehdr = &dst[dend-0xf8-0x28];
    while (pehdr>dst) {
      if ((sections=checkpe(dst, *dsize, pehdr, &valign, &sectcnt)))
	break;
      pehdr--;
    }
    if (!(realstuffsz = pehdr-dst)) pehdr=NULL;
  }

  if (!pehdr) {
    uint32_t rebsz = PESALIGN(dend, 0x1000);
    cli_dbgmsg("UPX: no luck - brutally crafing a reasonable PE\n");
    if (!(newbuf = (char *)cli_calloc(rebsz+0x200, sizeof(char)))) {
      cli_dbgmsg("UPX: malloc failed - giving up rebuild\n");
      return 0;
    }
    memcpy(newbuf, HEADERS, 0xd0);
    memcpy(newbuf+0xd0, FAKEPE, 0x120);
    memcpy(newbuf+0x200, dst, dend);
    memcpy(dst, newbuf, dend+0x200);
    free(newbuf);
    cli_writeint32(dst+0xd0+0x50, rebsz+0x1000);
    cli_writeint32(dst+0xd0+0x100, rebsz);
    cli_writeint32(dst+0xd0+0x108, rebsz);
    *dsize=rebsz+0x200;
    cli_dbgmsg("UPX: PE structure added to uncompressed data\n");
    return 1;
  }

  if (!sections)
    sectcnt = 0;
  foffset = PESALIGN(foffset+0x28*sectcnt, valign);
  
  for (upd = 0; upd <sectcnt ; upd++) {
    uint32_t vsize=PESALIGN((uint32_t)cli_readint32(sections+8), valign);
    uint32_t urva=PEALIGN((uint32_t)cli_readint32(sections+12), valign);
    
    /* Within bounds ? */
    if (!CLI_ISCONTAINED(upx0, realstuffsz, urva, vsize)) {
      cli_dbgmsg("UPX: Sect %d out of bounds - giving up rebuild\n", upd);
      return 0;
    }
    
    cli_writeint32(sections+8, vsize);
    cli_writeint32(sections+12, urva);
    cli_writeint32(sections+16, vsize);
    cli_writeint32(sections+20, foffset);
    if (foffset + vsize < foffset) {
        /* Integer overflow */
        return 0;
    }
    foffset+=vsize;
    
    sections+=0x28;
  }

  cli_writeint32(pehdr+8, 0x4d414c43);
  cli_writeint32(pehdr+0x3c, valign);

  if (!(newbuf = (char *) cli_calloc(foffset, sizeof(char)))) {
    cli_dbgmsg("UPX: malloc failed - giving up rebuild\n");
    return 0;
  }
  
  memcpy(newbuf, HEADERS, 0xd0);
  memcpy(newbuf+0xd0, pehdr,0xf8+0x28*sectcnt);
  sections = pehdr+0xf8;
  for (upd = 0; upd <sectcnt ; upd++) {
      uint32_t offset1, offset2, offset3;
      offset1 = (uint32_t)cli_readint32(sections+20);
      offset2 = (uint32_t)cli_readint32(sections+16);
      if (offset1 > foffset || offset2 > foffset || offset1 + offset2 > foffset) {
          free(newbuf);
          return 1;
      }

      offset3 = (uint32_t)cli_readint32(sections+12);
      if (offset3-upx0 > *dsize) {
          free(newbuf);
          return 1;
      }
    memcpy(newbuf+offset1, dst+offset3-upx0, offset2);
    sections+=0x28;
  }

  /* CBA restoring the imports they'll look different from the originals anyway... */
  /* ...and yeap i miss the icon too :P */

  if (foffset > *dsize + 8192) {
    cli_dbgmsg("UPX: wrong raw size - giving up rebuild\n");
    free(newbuf);
    return 0;
  }
  memcpy(dst, newbuf, foffset);
  *dsize = foffset;
  free(newbuf);

  cli_dbgmsg("UPX: PE structure rebuilt from compressed file\n");
  return 1;
}
예제 #17
0
파일: unzip.c 프로젝트: nayden/clamav-devel
static unsigned int lhdr(fmap_t *map, uint32_t loff,uint32_t zsize, unsigned int *fu, unsigned int fc, const uint8_t *ch, int *ret, cli_ctx *ctx, char *tmpd, int detect_encrypted, zip_cb zcb) {
    const uint8_t *lh, *zip;
    char name[256];
    uint32_t csize, usize;

    if(!(lh = fmap_need_off(map, loff, SIZEOF_LH))) {
        cli_dbgmsg("cli_unzip: lh - out of file\n");
        return 0;
    }
    if(LH_magic != 0x04034b50) {
        if (!ch) cli_dbgmsg("cli_unzip: lh - wrkcomplete\n");
        else cli_dbgmsg("cli_unzip: lh - bad magic\n");
        fmap_unneed_off(map, loff, SIZEOF_LH);
        return 0;
    }

    zip = lh + SIZEOF_LH;
    zsize-=SIZEOF_LH;

    if(zsize<=LH_flen) {
        cli_dbgmsg("cli_unzip: lh - fname out of file\n");
        fmap_unneed_off(map, loff, SIZEOF_LH);
        return 0;
    }
    if(ctx->engine->cdb || cli_debug_flag) {
        uint32_t nsize = (LH_flen>=sizeof(name))?sizeof(name)-1:LH_flen;
        const char *src;
        if(nsize && (src = fmap_need_ptr_once(map, zip, nsize))) {
            memcpy(name, zip, nsize);
            name[nsize]='\0';
        } else
            name[0] = '\0';
    }
    zip+=LH_flen;
    zsize-=LH_flen;

    cli_dbgmsg("cli_unzip: lh - ZMDNAME:%d:%s:%u:%u:%x:%u:%u:%u\n", ((LH_flags & F_ENCR)!=0), name, LH_usize, LH_csize, LH_crc32, LH_method, fc, ctx->recursion);
    /* ZMDfmt virname:encrypted(0-1):filename(exact|*):usize(exact|*):csize(exact|*):crc32(exact|*):method(exact|*):fileno(exact|*):maxdepth(exact|*) */

    if(cli_matchmeta(ctx, name, LH_csize, LH_usize, (LH_flags & F_ENCR)!=0, fc, LH_crc32, NULL) == CL_VIRUS) {
        *ret = CL_VIRUS;
        return 0;
    }

    if(LH_flags & F_MSKED) {
        cli_dbgmsg("cli_unzip: lh - header has got unusable masked data\n");
        /* FIXME: need to find/craft a sample */
        fmap_unneed_off(map, loff, SIZEOF_LH);
        return 0;
    }

    if(detect_encrypted && (LH_flags & F_ENCR) && DETECT_ENCRYPTED) {
        cli_dbgmsg("cli_unzip: Encrypted files found in archive.\n");
        cli_append_virus(ctx, "Heuristics.Encrypted.Zip");
        *ret = CL_VIRUS;
        fmap_unneed_off(map, loff, SIZEOF_LH);
        return 0;
    }

    if(LH_flags & F_USEDD) {
        cli_dbgmsg("cli_unzip: lh - has data desc\n");
        if(!ch) {
            fmap_unneed_off(map, loff, SIZEOF_LH);
            return 0;
        }
        else {
            usize = CH_usize;
            csize = CH_csize;
        }
    } else {
        usize = LH_usize;
        csize = LH_csize;
    }

    if(zsize<=LH_elen) {
        cli_dbgmsg("cli_unzip: lh - extra out of file\n");
        fmap_unneed_off(map, loff, SIZEOF_LH);
        return 0;
    }
    zip+=LH_elen;
    zsize-=LH_elen;

    if (!csize) { /* FIXME: what's used for method0 files? csize or usize? Nothing in the specs, needs testing */
        cli_dbgmsg("cli_unzip: lh - skipping empty file\n");
    } else {
        if(zsize<csize) {
            cli_dbgmsg("cli_unzip: lh - stream out of file\n");
            fmap_unneed_off(map, loff, SIZEOF_LH);
            return 0;
        }
        if(LH_flags & F_ENCR) {
            cli_dbgmsg("cli_unzip: lh - skipping encrypted file\n");
        } else {
            if(fmap_need_ptr_once(map, zip, csize))
                *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd, zcb);
        }
        zip+=csize;
        zsize-=csize;
    }

    fmap_unneed_off(map, loff, SIZEOF_LH); /* unneed now. block is guaranteed to exists till the next need */
    if(LH_flags & F_USEDD) {
        if(zsize<12) {
            cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
            return 0;
        }
        zsize-=12;
        if(fmap_need_ptr_once(map, zip, 4)) {
            if(cli_readint32(zip)==0x08074b50) {
                if(zsize<4) {
                    cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
                    return 0;
                }
                zip+=4;
            }
        }
        zip+=12;
    }
    return zip-lh;
}
예제 #18
0
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;
}
예제 #19
0
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 */
				}
예제 #20
0
static int nsis_headers(struct nsis_st *n, cli_ctx *ctx) {
  const char *buf;
  uint32_t pos;
  int i;
  uint8_t comps[] = {0, 0, 0, 0}, trunc = 0;
  
  if (!(buf = fmap_need_off_once(n->map, n->off, 0x1c)))
    return CL_EREAD;

  n->hsz = (uint32_t)cli_readint32(buf+0x14);
  n->asz = (uint32_t)cli_readint32(buf+0x18);
  n->fullsz = n->map->len;

  cli_dbgmsg("NSIS: Header info - Flags=%x, Header size=%x, Archive size=%x\n", cli_readint32(buf), n->hsz, n->asz);

  if (n->fullsz - n->off < (off_t) n->asz) {
    cli_dbgmsg("NSIS: Possibly truncated file\n");
    n->asz = n->fullsz - n->off;
    trunc++;
  } else if (n->fullsz - n->off != (off_t) n->asz) {
    cli_dbgmsg("NSIS: Overlays found\n");
  }

  n->asz -= 0x1c;
  buf += 0x1c;

  /* Guess if solid */
  for (i=0, pos=0;pos < n->asz-4;i++) {
    int32_t nextsz;
    if (!(buf = fmap_need_ptr_once(n->map, (void *)buf, 4))) return CL_EREAD;
    nextsz=cli_readint32(buf);
    if (!i) n->comp = nsis_detcomp(buf);
    buf += 4;
    if (nextsz&0x80000000) {
      nextsz&=~0x80000000;
      if (!(buf = fmap_need_ptr_once(n->map, (void *)buf, 4))) return CL_EREAD;
      comps[nsis_detcomp(buf)]++;
      nextsz-=4;
      pos+=4;
      buf+=4;
    }
    if ((pos+=4+nextsz) > n->asz) {
      n->solid = 1;
      break;
    }

    buf += nextsz;
  }
  
  if (trunc && i>=2) n->solid=0;

  cli_dbgmsg("NSIS: solid compression%s detected\n", (n->solid)?"":" not");

  /* Guess the compression method */
  if (!n->solid) {
    cli_dbgmsg("NSIS: bzip2 %u - lzma %u - zlib %u\n", comps[1], comps[2], comps[3]);
    n->comp = (comps[1]<comps[2]) ? (comps[2]<comps[3] ? COMP_ZLIB : COMP_LZMA) : (comps[1]<comps[3] ? COMP_ZLIB : COMP_BZIP2);
  }

  n->curpos = n->off+0x1c;
  return nsis_unpack_next(n, ctx);
}
예제 #21
0
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;
  }

}
예제 #22
0
파일: yc.c 프로젝트: OPSF/uClinux
int yc_decrypt(char *fbuf, unsigned int filesize, struct cli_exe_section *sections, unsigned int sectcount, uint32_t peoffset, int desc)
{
  uint32_t ycsect = sections[sectcount].raw;
  unsigned int i;
  struct pe_image_file_hdr *pe = (struct pe_image_file_hdr*) (fbuf + peoffset);
  char *sname = (char *)pe + EC16(pe->SizeOfOptionalHeader) + 0x18;

  /* 

  First layer (decryptor of the section decryptor) in last section 

  Start offset for analyze: Start of yC Section + 0x93
  End offset for analyze: Start of yC Section + 0xC3
  Lenght to decrypt - ECX = 0xB97

  */
  cli_dbgmsg("yC: decrypting decryptor on sect %d\n", sectcount); 
  if (yc_poly_emulator(fbuf + ycsect + 0x93, fbuf + ycsect + 0xc6 ,0xB97))
    return 1;
  filesize-=sections[sectcount].ursz;

  /* 

  Second layer (decryptor of the sections) in last section 

  Start offset for analyze: Start of yC Section + 0x457
  End offset for analyze: Start of yC Section + 0x487
  Lenght to decrypt - ECX = Raw Size of Section

  */


  /* Loop through all sections and decrypt them... */
  for(i=0;i<sectcount;i++)
    {
      uint32_t name = (uint32_t) cli_readint32(sname+i*0x28);
      if ( !sections[i].raw ||
	   !sections[i].rsz ||
	   name == 0x63727372 || /* rsrc */
	   name == 0x7273722E || /* .rsr */
	   name == 0x6F6C6572 || /* relo */
	   name == 0x6C65722E || /* .rel */
	   name == 0x6164652E || /* .eda */
	   name == 0x6164722E || /* .rda */
	   name == 0x6164692E || /* .ida */
	   name == 0x736C742E || /* .tls */
	   (name&0xffff) == 0x4379  /* yC */
	) continue;
      cli_dbgmsg("yC: decrypting sect%d\n",i); 
      if (yc_poly_emulator(fbuf + ycsect + 0x457, fbuf + sections[i].raw, sections[i].ursz))
	return 1;
    }

  /* Remove yC section */
  pe->NumberOfSections=EC16(sectcount);

  /* Remove IMPORT_DIRECTORY information */
  memset((char *)pe + sizeof(struct pe_image_file_hdr) + 0x68, 0, 8);

  /* OEP resolving */
  /* OEP = DWORD PTR [ Start of yC section+ A0F] */
  cli_writeint32((char *)pe + sizeof(struct pe_image_file_hdr) + 16, cli_readint32(fbuf + ycsect + 0xa0f));

  /* Fix SizeOfImage */
  cli_writeint32((char *)pe + sizeof(struct pe_image_file_hdr) + 0x38, cli_readint32((char *)pe + sizeof(struct pe_image_file_hdr) + 0x38) - sections[sectcount].vsz);

  if (cli_writen(desc, fbuf, filesize)==-1) {
    cli_dbgmsg("yC: Cannot write unpacked file\n");
    return 1;
  }
  return 0;
}
예제 #23
0
파일: unzip.c 프로젝트: nayden/clamav-devel
int unzip_search(cli_ctx *ctx, const char *name, size_t nlen, uint32_t *loff)
{
    unsigned int fc = 0;
    fmap_t *map;
    size_t fsize;
    uint32_t coff = 0;
    const char *ptr;
    zip_request_t request;
    int ret = CL_CLEAN;
#if HAVE_JSON
    uint32_t toval = 0;
#endif

    cli_dbgmsg("in unzip_search\n");
    if (!ctx) {
        return CL_ENULLARG;
    }

    map = *ctx->fmap;
    fsize = map->len;
    if(sizeof(off_t)!=sizeof(uint32_t) && fsize!=map->len) {
        cli_dbgmsg("unzip_search: file too big\n");
        return CL_CLEAN;
    }
    if (fsize < SIZEOF_CH) {
        cli_dbgmsg("unzip_search: file too short\n");
        return CL_CLEAN;
    }

    for(coff=fsize-22 ; coff>0 ; coff--) { /* sizeof(EOC)==22 */
        if(!(ptr = fmap_need_off_once(map, coff, 20)))
            continue;
        if(cli_readint32(ptr)==0x06054b50) {
            uint32_t chptr = cli_readint32(&ptr[16]);
            if(!CLI_ISCONTAINED(0, fsize, chptr, SIZEOF_CH)) continue;
            coff=chptr;
            break;
        }
    }

    request.name = name;
    request.namelen = nlen;
    request.found = 0;

    if(coff) {
        cli_dbgmsg("unzip_search: central @%x\n", coff);
        while(ret==CL_CLEAN && (coff=chdr(map, coff, fsize, NULL, fc+1, &ret, ctx, NULL, &request))) {
            if (request.found) {
                *loff = request.loff;
                return CL_VIRUS;
            }

            fc++;
            if (ctx->engine->maxfiles && fc >= ctx->engine->maxfiles) {
                cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
                ret=CL_EMAXFILES;
            }
#if HAVE_JSON
            if (cli_json_timeout_cycle_check(ctx, (int *)(&toval)) != CL_SUCCESS) {
                return CL_ETIMEOUT;
            }
#endif
        }
    } else {
        cli_dbgmsg("unzip_search: cannot locate central directory\n");
    }

    return ret;
}