Exemple #1
0
int unfsg_133(const char *source, char *dest, int ssize, int dsize, struct cli_exe_section *sections, int sectcount, uint32_t base, uint32_t ep, int file) {
  const char *tsrc=source;
  char *tdst=dest;
  int i, upd=1, offs=0, lastsz=dsize;

  for (i = 0 ; i <= sectcount ; i++) {
    char *startd=tdst;
    if ( cli_unfsg(tsrc, tdst, ssize - (tsrc - source), dsize - (tdst - dest), &tsrc, &tdst) == -1 )
      return -1;

    /* RVA has been filled already in pe.c */
    sections[i].raw=offs;
    sections[i].rsz=tdst-startd;
    /*    cli_dbgmsg("Unpacked section %d @%x size %x Vsize =%x \n", i, offs, tdst-startd, dsize - (startd - dest)); */
    offs+=tdst-startd;
  }

  /* Sort out the sections */
  while ( upd ) {
    upd = 0;
    for (i = 0; i < sectcount  ; i++) {
      uint32_t trva,trsz,traw;
      
      if ( sections[i].rva <= sections[i+1].rva )
	continue;
      trva = sections[i].rva;
      traw = sections[i].raw;
      trsz = sections[i].rsz;
      sections[i].rva = sections[i+1].rva;
      sections[i].rsz = sections[i+1].rsz;
      sections[i].raw = sections[i+1].raw;
      sections[i+1].rva = trva;
      sections[i+1].raw = traw;
      sections[i+1].rsz = trsz;
      upd = 1;
    }
  }

  /* Cure Vsizes and debugspam */
  for (i = 0; i <= sectcount ; i++) {
    if ( i != sectcount ) {
      sections[i].vsz = sections[i+1].rva - sections[i].rva;
      lastsz-= sections[i+1].rva - sections[i].rva;
    }
    else 
      sections[i].vsz = lastsz;

    cli_dbgmsg("FSG: .SECT%d RVA:%x VSize:%x ROffset: %x, RSize:%x\n", i, sections[i].rva, sections[i].vsz, sections[i].raw, sections[i].rsz);
  }

  if (!cli_rebuildpe(dest, sections, sectcount+1, base, ep, 0, 0, file)) {
    cli_dbgmsg("FSG: Rebuilding failed\n");
    return 0;
  }
  return 1;
}
Exemple #2
0
int unfsg_200(const char *source, char *dest, int ssize, int dsize, uint32_t rva, uint32_t base, uint32_t ep, int file) {
  struct cli_exe_section section; /* Yup, just one ;) */
  
  if ( cli_unfsg(source, dest, ssize, dsize, NULL, NULL) ) return -1;
  
  section.raw=0;
  section.rsz = dsize;
  section.vsz = dsize;
  section.rva = rva;

  if (!cli_rebuildpe(dest, &section, 1, base, ep, 0, 0, file)) {
    cli_dbgmsg("FSG: Rebuilding failed\n");
    return 0;
  }
  return 1;
}
Exemple #3
0
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;
    }
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;
}