50593e02 |
#if HAVE_STRING_H
#include <string.h>
#endif
#define RESEED \
if (CLI_ISCONTAINED(compd, szd, ccur, 4)) { \
bt = cli_readint32(ccur); \
ccur+=4; \
} else { \
cli_dbgmsg("WWPack: Out of bits\n"); \
error=1; \
} \
bc = 32;
#define BIT \
bits = bt>>31; \
bt<<=1; \
if(!--bc) { \
RESEED; \
}
#define BITS(N) \
bits = bt>>(32-(N)); \
if (bc>=(N)) { \
bc -= (N); \
bt<<=(N); \
if (!bc) { \
RESEED; \
} \
} else { \
if (CLI_ISCONTAINED(compd, szd, ccur, 4)) { \
bt = cli_readint32(ccur); \
ccur+=4; \
bc += 32 - (N); \
bits |= bt>>(bc); \
bt <<= (32-bc); \
} else { \
cli_dbgmsg("WWPack: Out of bits\n"); \
error=1; \
} \
}
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))) 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; |