/* * Copyright (C) 2007-2008 Sourcefire, Inc. * * Authors: Alberto Wu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ #if HAVE_CONFIG_H #include "clamav-config.h" #endif #include "cltypes.h" #include "others.h" #include "execs.h" #include "wwunpack.h" #if HAVE_STRING_H #include #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<>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