add support for NsPack

git-svn: trunk@2428
remotes/push_mirror/metadata
aCaB 19 years ago
parent b4ff5537e8
commit 81030038e5
  1. 4
      clamav-devel/ChangeLog
  2. 2
      clamav-devel/libclamav/Makefile.am
  3. 15
      clamav-devel/libclamav/Makefile.in
  4. 140
      clamav-devel/libclamav/pe.c
  5. 530
      clamav-devel/libclamav/unsp.c
  6. 50
      clamav-devel/libclamav/unsp.h

@ -1,3 +1,7 @@
Wed Oct 25 04:30:36 CEST 2006 (acab)
------------------------------------
* libclamav: add support for NsPack (--enable-experimental)
Mon Oct 23 17:48:39 CEST 2006 (tk)
----------------------------------
* libclamav: improve support for NodalCore SDK 3.3

@ -96,6 +96,8 @@ libclamav_la_SOURCES = \
wwunpack.h \
suecrypt.c \
suecrypt.h \
unsp.c \
unsp.h \
packlibs.c \
packlibs.h \
fsg.c \

@ -83,12 +83,12 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher.lo \
text.lo ole2_extract.lo vba_extract.lo msexpand.lo pe.lo \
cabd.lo lzxd.lo mszipd.lo qtmd.lo system.lo upx.lo htmlnorm.lo \
chmunpack.lo rebuildpe.lo petite.lo wwunpack.lo suecrypt.lo \
packlibs.lo fsg.lo line.lo untar.lo unzip.lo special.lo \
binhex.lo is_tar.lo tnef.lo unrar15.lo unrarvm.lo unrar.lo \
unrarfilter.lo unrarppm.lo unrar20.lo unrarcmd.lo pdf.lo \
spin.lo yc.lo elf.lo sis.lo uuencode.lo pst.lo phishcheck.lo \
phish_domaincheck_db.lo phish_whitelist.lo regex_list.lo \
sha256.lo
unsp.lo packlibs.lo fsg.lo line.lo untar.lo unzip.lo \
special.lo binhex.lo is_tar.lo tnef.lo unrar15.lo unrarvm.lo \
unrar.lo unrarfilter.lo unrarppm.lo unrar20.lo unrarcmd.lo \
pdf.lo spin.lo yc.lo elf.lo sis.lo uuencode.lo pst.lo \
phishcheck.lo phish_domaincheck_db.lo phish_whitelist.lo \
regex_list.lo sha256.lo
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
@ -297,6 +297,8 @@ libclamav_la_SOURCES = \
wwunpack.h \
suecrypt.c \
suecrypt.h \
unsp.c \
unsp.h \
packlibs.c \
packlibs.h \
fsg.c \
@ -480,6 +482,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrarfilter.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrarppm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrarvm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unsp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/untar.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unzip.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upx.Plo@am__quote@

@ -45,6 +45,7 @@
#include "yc.h"
#include "wwunpack.h"
#include "suecrypt.h"
#include "unsp.h"
#include "scanners.h"
#include "rebuildpe.h"
#include "str.h"
@ -67,6 +68,9 @@
#define EC32(x) le32_to_host(x) /* Convert little endian to host */
#define EC16(x) le16_to_host(x)
/* lower and upper bondary alignment (size vs offset) */
#define PEALIGN(o,a) (((a))?(((o)/(a))*(a)):(o))
#define PESALIGN(o,a) (((a))?(((o)/(a)+((o)%(a)!=0))*(a)):(o))
extern short cli_leavetemps_flag;
@ -75,13 +79,13 @@ struct offset_list {
struct offset_list *next;
};
static uint32_t cli_rawaddr(uint32_t rva, struct pe_image_section_hdr *shp, uint16_t nos, unsigned int *err)
static uint32_t cli_rawaddr(uint32_t rva, struct pe_image_section_hdr *shp, uint16_t nos, unsigned int *err, uint32_t valign, uint32_t falign)
{
int i, found = 0;
for(i = 0; i < nos; i++) {
if(EC32(shp[i].VirtualAddress) <= rva && EC32(shp[i].VirtualAddress) + EC32(shp[i].SizeOfRawData) > rva) {
if(PEALIGN(EC32(shp[i].VirtualAddress), valign) <= rva && PEALIGN(EC32(shp[i].VirtualAddress), valign) + PESALIGN(EC32(shp[i].SizeOfRawData), falign) > rva) {
found = 1;
break;
}
@ -93,7 +97,7 @@ static uint32_t cli_rawaddr(uint32_t rva, struct pe_image_section_hdr *shp, uint
}
*err = 0;
return rva - EC32(shp[i].VirtualAddress) + EC32(shp[i].PointerToRawData);
return rva - PEALIGN(EC32(shp[i].VirtualAddress), valign) + PEALIGN(EC32(shp[i].PointerToRawData), falign);
}
static void xckriz(char **opcode, int *len, int checksize, int reg) {
@ -661,7 +665,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
else
ep = EC32(optional_hdr32.AddressOfEntryPoint);
if(ep >= min && !(ep = cli_rawaddr(ep, section_hdr, nsections, &err)) && err) {
if(ep >= min && !(ep = cli_rawaddr(ep, section_hdr, nsections, &err, 0, 0)) && err) {
cli_dbgmsg("Possibly broken PE file\n");
free(section_hdr);
if(DETECT_BROKEN) {
@ -813,7 +817,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
}
val = cli_readint32(jpt + 1);
val += 5 + EC32(section_hdr[0].VirtualAddress) + total + shift;
raddr = cli_rawaddr(val, section_hdr, nsections, &err);
raddr = cli_rawaddr(val, section_hdr, nsections, &err, 0, 0);
if(!err && (raddr >= EC32(section_hdr[polipos].PointerToRawData) && raddr < EC32(section_hdr[polipos].PointerToRawData) + EC32(section_hdr[polipos].SizeOfRawData)) && (!offlist || (raddr != offlist->offset))) {
offnode = (struct offset_list *) cli_malloc(sizeof(struct offset_list));
@ -1815,7 +1819,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
for(i = 0 ; i < nsections; i++) {
if(section_hdr[i].SizeOfRawData) {
uint32_t offset = cli_rawaddr(EC32(section_hdr[i].VirtualAddress), section_hdr, nsections, &err);
uint32_t offset = cli_rawaddr(EC32(section_hdr[i].VirtualAddress), section_hdr, nsections, &err, 0, 0);
if(err || lseek(desc, offset, SEEK_SET) == -1 || (unsigned int) cli_readn(desc, dest + EC32(section_hdr[i].VirtualAddress) - min, EC32(section_hdr[i].SizeOfRawData)) != EC32(section_hdr[i].SizeOfRawData)) {
free(section_hdr);
@ -1892,8 +1896,8 @@ int cli_scanpe(int desc, cli_ctx *ctx)
EC32(optional_hdr32.AddressOfEntryPoint) < EC32(section_hdr[nsections - 1].VirtualAddress) + EC32(section_hdr[nsections - 1].SizeOfRawData) - 0x3217 - 4 &&
memcmp(buff+4, "\xe8\x00\x00\x00\x00\x8b\x1c\x24\x83\xc3", 10) == 0) {
char *spinned;
char *spinned;
if(ctx->limits && ctx->limits->maxfilesize && fsize > ctx->limits->maxfilesize) {
cli_dbgmsg("PEspin: Size exceeded (fsize: %u, max: %lu)\n", fsize, ctx->limits->maxfilesize);
free(section_hdr);
@ -2059,7 +2063,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
char *dest, *wwp;
for(i = 0 ; i < (unsigned int)nsections-1; i++) {
uint32_t offset = cli_rawaddr(EC32(section_hdr[i].VirtualAddress), section_hdr, nsections, &err);
uint32_t offset = cli_rawaddr(EC32(section_hdr[i].VirtualAddress), section_hdr, nsections, &err, 0, 0);
if (!err && offset<headsize) headsize=offset;
}
@ -2093,7 +2097,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
for(i = 0 ; i < (unsigned int)nsections-1; i++) {
if(section_hdr[i].SizeOfRawData) {
uint32_t offset = cli_rawaddr(EC32(section_hdr[i].VirtualAddress), section_hdr, nsections, &err);
uint32_t offset = cli_rawaddr(EC32(section_hdr[i].VirtualAddress), section_hdr, nsections, &err, 0, 0);
if(err || lseek(desc, offset, SEEK_SET) == -1 || (unsigned int) cli_readn(desc, dest + headsize + EC32(section_hdr[i].VirtualAddress) - min, EC32(section_hdr[i].SizeOfRawData)) != EC32(section_hdr[i].SizeOfRawData)) {
free(dest);
@ -2175,6 +2179,120 @@ int cli_scanpe(int desc, cli_ctx *ctx)
}
}
#ifdef CL_EXPERIMENTAL
/* NsPack */
/* WATCH OUT: ep && buff destroyed!!! */
while (1) {
uint32_t eprva = EC32(optional_hdr32.AddressOfEntryPoint);
uint32_t start_of_stuff, ssize, dsize;
unsigned int nowinldr;
char *src, *dest;
FILE *asd;
ep = cli_rawaddr(eprva , section_hdr, nsections, &err, EC32(optional_hdr32.SectionAlignment), EC32(optional_hdr32.FileAlignment));
if (lseek(desc, ep, SEEK_SET)==-1) break;
if (cli_readn(desc, buff, 13)!=13) break;
if (*buff=='\xe9') { /* bitched headers */
eprva = cli_readint32(buff+1)+EC32(optional_hdr32.AddressOfEntryPoint)+5;
ep = cli_rawaddr(eprva, section_hdr, nsections, &err, EC32(optional_hdr32.SectionAlignment), EC32(optional_hdr32.FileAlignment));
if (lseek(desc, ep, SEEK_SET)==-1) break;
if (cli_readn(desc, buff, 24)!=24) break;
}
if (memcmp(buff, "\x9c\x60\xe8\x00\x00\x00\x00\x5d\xb8\x07\x00\x00\x00", 13)) break;
nowinldr = 0x54-cli_readint32(buff+17);
cli_dbgmsg("NsPack: Found *start_of_stuff @delta-%x\n", nowinldr);
if (lseek(desc, ep-nowinldr, SEEK_SET)==-1) break;
if (cli_readn(desc, buff, 4)!=4) break;
start_of_stuff=ep+cli_readint32(buff);
if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break;
if (cli_readn(desc, buff, 20)!=20) break;
src = buff;
if (!cli_readint32(buff)) {
start_of_stuff+=4; /* FIXME: more to do */
src+=4;
}
ssize = cli_readint32(src+5)|0xff;
dsize = cli_readint32(src+9);
if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) {
cli_dbgmsg("NsPack: Size exceeded\n");
free(section_hdr);
if(BLOCKMAX) {
*ctx->virname = "PE.NsPack.ExceededFileSize";
return CL_VIRUS;
} else {
return CL_CLEAN;
}
}
if ( !ssize || !dsize || dsize != (uint32_t)PESALIGN(EC32(section_hdr[0].VirtualSize), EC32(optional_hdr32.SectionAlignment))) break;
if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break;
if (!(dest=cli_malloc(dsize))) break;
/* memset(dest, 0xfc, dsize); */
if (!(src=cli_malloc(ssize))) {
free(dest);
break;
}
/* memset(src, 0x00, ssize); */
cli_readn(desc, src, ssize);
eprva+=0x27a;
ep = cli_rawaddr(eprva, section_hdr, nsections, &err, EC32(optional_hdr32.SectionAlignment), EC32(optional_hdr32.FileAlignment));
if (lseek(desc, ep, SEEK_SET)==-1) break;
if (cli_readn(desc, buff, 5)!=5) break;
eprva=eprva+5+cli_readint32(buff+1);
cli_dbgmsg("NsPack: OEP = %08x\n", eprva);
if(!(tempfile = cli_gentemp(NULL))) {
free(src);
free(dest);
free(section_hdr);
return CL_EMEM;
}
if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
cli_dbgmsg("NsPack: Can't create file %s\n", tempfile);
free(tempfile);
free(src);
free(dest);
free(section_hdr);
return CL_EIO;
}
if (!unspack(src, dest, ctx, EC32(section_hdr[0].VirtualAddress), EC32(optional_hdr32.ImageBase), eprva, ndesc)) {
free(src);
free(dest);
if (cli_leavetemps_flag)
cli_dbgmsg("NsPack: Unpacked and rebuilt executable saved in %s\n", tempfile);
else
cli_dbgmsg("NsPack: Unpacked and rebuilt executable\n");
fsync(ndesc);
lseek(ndesc, 0, SEEK_SET);
if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
free(section_hdr);
close(ndesc);
if(!cli_leavetemps_flag) unlink(tempfile);
free(tempfile);
return CL_VIRUS;
}
} else {
free(src);
free(dest);
cli_dbgmsg("NsPack: Unpacking failed\n");
}
close(ndesc);
if(!cli_leavetemps_flag) unlink(tempfile);
free(tempfile);
break;
}
#endif /* CL_EXPERIMENTAL - NsPack */
/* to be continued ... */
@ -2320,7 +2438,7 @@ int cli_peheader(int desc, struct cli_exe_info *peinfo)
else
peinfo->ep = EC32(optional_hdr32.AddressOfEntryPoint);
if(peinfo->ep >= min && !(peinfo->ep = cli_rawaddr(peinfo->ep, section_hdr, peinfo->nsections, &err)) && err) {
if(peinfo->ep >= min && !(peinfo->ep = cli_rawaddr(peinfo->ep, section_hdr, peinfo->nsections, &err, 0, 0)) && err) {
cli_dbgmsg("Possibly broken PE file\n");
free(section_hdr);
free(peinfo->section);

@ -0,0 +1,530 @@
/*
* Copyright (C) 2006 aCaB <acab@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
/*
** unsp.c
**
** 11/10/2k6 - Merge started.
**
*/
/*
** Plays around with NsPack compressed executables
**
** This piece of code is dedicated to Damian Put
** who I made a successful and wealthy man.
**
** Damian, you owe me a pint!
*/
/*
** TODO:
**
** - Investigate the "unused" code in NsPack
** - Fetch all the nspacked samples from the zoo and run extensive testing
** - Add bound checks
** - Test against the zoo again
** - Perform regression testing against the full zoo
** - check nested
** - look at the 64bit version (one of these days)
**
*/
/*
FIXME: clean this rubbish
init_and_check_dll_loadflags();
nsp1:004359FE add edi, [ebp-28Dh]
nsp1:00435A04 mov ebx, edi
nsp1:00435A06 cmp dword ptr [edi], 0
nsp1:00435A09 jnz short loc_435A15
nsp1:00435A0B add edi, 4
nsp1:00435A0E mov ecx, 0
nsp1:00435A13 jmp short loc_435A2B
nsp1:00435A15 ; ---------------------------------------------------------------------------
nsp1:00435A15
nsp1:00435A15 loc_435A15: ; CODE XREF: start+349EEj
nsp1:00435A15 mov ecx, 1
nsp1:00435A1A add edi, [ebx]
nsp1:00435A1C add ebx, 4
nsp1:00435A1F
nsp1:00435A1F loc_435A1F: ; CODE XREF: start+34A3Dj
nsp1:00435A1F cmp dword ptr [ebx], 0
nsp1:00435A22 jz short loc_435A5A
nsp1:00435A24 add [ebx], edx
nsp1:00435A26 mov esi, [ebx]
nsp1:00435A28 add edi, [ebx+4]
nsp1:00435A2B
nsp1:00435A2B loc_435A2B: ; CODE XREF: start+349F8j
nsp1:00435A2B push edi
nsp1:00435A2C push ecx
nsp1:00435A2D push edx
nsp1:00435A2E push ebx
nsp1:00435A2F push dword ptr [ebp-1D1h] ; VirtualFree
nsp1:00435A35 push dword ptr [ebp-1D5h] ; alloc
nsp1:00435A3B mov edx, esi
nsp1:00435A3D mov ecx, edi
nsp1:00435A3F mov eax, offset get_byte
nsp1:00435A44 int 3 ; Trap to Debugger
nsp1:00435A45 add eax, 5A9h
nsp1:00435A4A call eax ; real_unpack ; edx=401000
nsp1:00435A4A ; ecx=436282
nsp1:00435A4C pop ebx
nsp1:00435A4D pop edx
nsp1:00435A4E pop ecx
nsp1:00435A4F pop edi
nsp1:00435A50 cmp ecx, 0
nsp1:00435A53 jz short loc_435A5A
nsp1:00435A55 add ebx, 8
nsp1:00435A58 jmp short loc_435A1F
nsp1:00435A5A ; ---------------------------------------------------------------------------
nsp1:00435A5A
nsp1:00435A5A loc_435A5A: ; CODE XREF: start+34A07j
nsp1:00435A5A ; start+34A38j
nsp1:00435A5A push 8000h
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#ifdef CL_EXPERIMENTAL
#include <stdlib.h>
#include "cltypes.h"
#include "clamav.h"
#include "others.h"
#include "rebuildpe.h"
#include "unsp.h"
/* real_unpack(start_of_stuff, dest, malloc, free); */
uint32_t unspack(char *start_of_stuff, char *dest, cli_ctx *ctx, uint32_t rva, uint32_t base, uint32_t ep, int file) {
uint8_t c = *start_of_stuff;
uint32_t i,firstbyte,tre,allocsz,tablesz,dsize,ssize;
uint16_t *table;
char *dst = dest;
char *src = start_of_stuff+0xd;
struct SECTION section;
if (c>=0xe1) return 1;
if (c>=0x2d) {
firstbyte = i = c/0x2d;
do {c+=0xd3;} while (--i);
} else firstbyte = 0;
if (c>=9) {
allocsz = i = c/9;
do {c+=0xf7;} while (--i);
} else allocsz = 0;
tre = c;
i = allocsz;
c = (tre+i)&0xff;
tablesz = ((0x300<<c)+0x736)*sizeof(uint16_t);
if(ctx->limits && ctx->limits->maxfilesize && tablesz > ctx->limits->maxfilesize) {
return 1; /* Should be ~15KB, if it's so big it's prolly just not nspacked */
}
cli_dbgmsg("unsp: table size = %d\n", tablesz);
if (!(table = cli_malloc(tablesz))) return 1;
dsize = cli_readint32(start_of_stuff+9);
ssize = cli_readint32(start_of_stuff+5);
tre = very_real_unpack(table,tablesz,tre,allocsz,firstbyte,src,ssize,dst,dsize);
free(table);
if (tre) return 1;
section.raw=0;
section.rsz = dsize;
section.vsz = dsize;
section.rva = rva;
if ( (src = rebuildpe(dest, &section, 1, base, ep, 0, 0)) ) {
if (cli_writen(file, src, 0x148+0x80+0x28+dsize)!=-1) {
free(src);
return 0;
}
free(src);
}
return 1;
}
uint32_t very_real_unpack(uint16_t *table, uint32_t tablesz, uint32_t tre, uint32_t allocsz, uint32_t firstbyte, char *src, uint32_t ssize, char *dst, uint32_t dsize) {
struct UNSP read_struct;
uint32_t i = (0x300<<((allocsz+tre)&0xff)) + 0x736;
uint32_t previous_bit = 0;
uint32_t unpacked_so_far = 0;
uint32_t backbytes = 1;
uint32_t oldbackbytes = 1;
uint32_t old_oldbackbytes = 1;
uint32_t old_old_oldbackbytes = 1;
uint32_t damian = 0;
uint32_t put = (1<<(allocsz&0xff))-1;
uint32_t bielle = 0;
firstbyte = (1<<(firstbyte&0xff))-1;
if (tablesz < i*sizeof(uint16_t)) return 2;
/* init table */
while (i) table[--i]=0x400;
/* table noinit */
/* get_five - inlined */
read_struct.error = 0;
read_struct.oldval = 0;
read_struct.src_curr = src;
read_struct.bitmap = 0xffffffff;
read_struct.src_end = src + ssize;
read_struct.table = (char *)table;
read_struct.tablesz = tablesz;
for ( i = 0; i<5 ; i++) read_struct.oldval = (read_struct.oldval<<8) | get_byte(&read_struct);
if (read_struct.error) return 1;
/* if (!dsize) return 0; - checked in pe.c */
/* very_unpacking_loop */
while (1) {
uint32_t backsize = firstbyte&unpacked_so_far;
uint32_t tpos;
uint32_t temp = damian;
if (read_struct.error) return 1; /* checked once per mainloop, keeps the code readable and it's still safe */
if (!getbit_from_table(&table[(damian<<4) + backsize], &read_struct)) { /* no_mainbit */
uint32_t shft = 8 - (tre&0xff);
shft &= 0xff;
tpos = (bielle>>shft) + ((put&unpacked_so_far)<<(tre&0xff));
tpos *=3;
tpos<<=8;
if ((int32_t)damian>=4) { /* signed */
if ((int32_t)damian>=0xa) { /* signed */
damian -= 6;
} else {
damian -= 3;
}
} else {
damian=0;
}
/* 44847E */
if (previous_bit) {
if (!CLI_ISCONTAINED(dst, dsize, &dst[unpacked_so_far - backbytes], 1)) return 1;
ssize = (ssize&0xffffff00) | (uint8_t)dst[unpacked_so_far - backbytes]; /* FIXME! ssize is not static */
bielle = get_100_bits_from_tablesize(&table[tpos+0x736], &read_struct, ssize);
previous_bit=0;
} else {
bielle = get_100_bits_from_table(&table[tpos+0x736], &read_struct);
}
/* unpack_one_byte - duplicated */
if (!CLI_ISCONTAINED(dst, dsize, &dst[unpacked_so_far], 1)) return 1;
dst[unpacked_so_far] = bielle;
unpacked_so_far++;
if (unpacked_so_far>=dsize) return 0;
continue;
} else { /* got_mainbit */
bielle = previous_bit = 1;
if (getbit_from_table(&table[damian+0xc0], &read_struct)) {
if (!getbit_from_table(&table[damian+0xcc], &read_struct)) {
tpos = damian+0xf;
tpos <<=4;
tpos += backsize;
if (!getbit_from_table(&table[tpos], &read_struct)) {
if (!unpacked_so_far) return bielle; /* FIXME: WTF?! */
damian = 2*((int32_t)damian>=7)+9; /* signed */
if (!CLI_ISCONTAINED(dst, dsize, &dst[unpacked_so_far - backbytes], 1)) return 1;
bielle = (uint8_t)dst[unpacked_so_far - backbytes];
/* unpack_one_byte - real */
dst[unpacked_so_far] = bielle;
unpacked_so_far++;
if (unpacked_so_far>=dsize) return 0;
continue;
} else { /* gotbit_tre */
backsize = get_n_bits_from_tablesize(&table[0x534], &read_struct, backsize);
damian = ((int32_t)damian>=7); /* signed */
damian = ((damian-1) & 0xfffffffd)+0xb;
/* jmp checkloop_and_backcopy (uses edx) */
} /* gotbit_uno ends */
} else { /* gotbit_due */
if (!getbit_from_table(&table[damian+0xd8], &read_struct)) {
tpos = oldbackbytes;
} else {
if (!getbit_from_table(&table[damian+0xe4], &read_struct)) {
tpos = old_oldbackbytes;
} else {
/* set_old_old_oldback */
tpos = old_old_oldbackbytes;
old_old_oldbackbytes = old_oldbackbytes;
}
/* set_old_oldback */
old_oldbackbytes = oldbackbytes;
}
/* set_oldback */
oldbackbytes = backbytes;
backbytes = tpos;
backsize = get_n_bits_from_tablesize(&table[0x534], &read_struct, backsize);
damian = ((int32_t)damian>=7); /* signed */
damian = ((damian-1) & 0xfffffffd)+0xb;
/* jmp checkloop_and_backcopy (uses edx) */
} /* gotbit_due ends */
} else { /* gotbit_uno */
old_old_oldbackbytes = old_oldbackbytes;
old_oldbackbytes = oldbackbytes;
oldbackbytes = backbytes;
damian = ((int32_t)damian>=7); /* signed */
damian = ((damian-1) & 0xfffffffd)+0xa;
backsize = get_n_bits_from_tablesize(&table[0x332], &read_struct, backsize);
tpos = ((int32_t)backsize>=4)?3:backsize; /* signed */
tpos<<=6;
tpos = get_n_bits_from_table(&table[0x1b0+tpos], 6, &read_struct);
if (tpos>=4) { /* signed */
uint32_t s = tpos;
s>>=1;
s--;
temp = (tpos & bielle) | 2;
temp<<=(s&0xff);
if ((int32_t)tpos<0xe) {
temp += get_bb(&table[(temp-tpos)+0x2af], s, &read_struct);
} else {
s += 0xfffffffc;
tpos = get_bitmap(&read_struct, s);
tpos <<=4;
temp += tpos;
temp += get_bb(&table[0x322], 4, &read_struct);
}
} else {
/* gotbit_uno_out1 */
backbytes = temp = tpos;
}
/* gotbit_uno_out2 */
backbytes = temp+1;
/* jmp checkloop_and_backcopy (uses edx) */
} /* gotbit_uno ends */
/* checkloop_and_backcopy */
if (!backbytes) return 0; /* very_real_unpack_end */
if (backbytes > unpacked_so_far) return bielle; /* FIXME: WTF?! */
backsize +=2;
if (!CLI_ISCONTAINED(dst, dsize, &dst[unpacked_so_far], backsize) ||
!CLI_ISCONTAINED(dst, dsize, &dst[unpacked_so_far - backbytes], backsize)
) {
cli_dbgmsg("%x %x %x %x\n", dst, dsize, &dst[unpacked_so_far], backsize);
return 1;
}
do {
dst[unpacked_so_far] = dst[unpacked_so_far - backbytes];
unpacked_so_far++;
} while (--backsize && unpacked_so_far<dsize);
bielle = (uint8_t)dst[unpacked_so_far - 1];
if (unpacked_so_far>=dsize) return 0;
} /* got_mainbit ends */
} /* while true ends */
}
uint32_t get_byte(struct UNSP *read_struct) {
uint32_t ret;
if (read_struct->src_curr >= read_struct->src_end) {
read_struct->error = 1;
return 0xff;
}
ret = *(read_struct->src_curr);
read_struct->src_curr++;
return ret&0xff;
}
int getbit_from_table(uint16_t *intable, struct UNSP *read_struct) {
uint32_t nval;
if (!CLI_ISCONTAINED((char *)read_struct->table, read_struct->tablesz, (char *)intable, sizeof(uint16_t))) {
read_struct->error = 1;
return 0xff;
}
nval = *intable * (read_struct->bitmap>>0xb);
if (read_struct->oldval<nval) { /* unsigned */
uint32_t sval;
read_struct->bitmap = nval;
nval = *intable;
sval = 0x800 - nval;
sval = ((int32_t)sval)>>5; /* signed */
sval += nval;
*intable=sval;
if (read_struct->bitmap<0x1000000) { /* unsigned */
read_struct->oldval = (read_struct->oldval<<8) | get_byte(read_struct);
read_struct->bitmap<<=8;
}
return 0;
}
read_struct->bitmap -= nval;
read_struct->oldval -= nval;
nval = *intable;
nval -= (nval>>5); /* word, unsigned */
*intable=nval;
if (read_struct->bitmap<0x1000000) { /* unsigned */
read_struct->oldval = (read_struct->oldval<<8) | get_byte(read_struct);
read_struct->bitmap<<=8;
}
return 1;
}
uint32_t get_100_bits_from_tablesize(uint16_t *intable, struct UNSP *read_struct, uint32_t ssize) {
uint32_t count = 1;
while (count<0x100) {
uint32_t lpos, tpos;
lpos = ssize&0xff;
ssize=(ssize&0xffffff00)|((lpos<<1)&0xff);
lpos>>=7;
tpos = lpos+1;
tpos<<=8;
tpos+=count;
tpos = getbit_from_table(&intable[tpos], read_struct);
count=(count*2)|tpos;
if (lpos!=tpos) {
/* second loop */
while (count<0x100)
count = (count*2)|getbit_from_table(&intable[count], read_struct);
}
}
return count&0xff;
}
uint32_t get_100_bits_from_table(uint16_t *intable, struct UNSP *read_struct) {
uint32_t count = 1;
while (count<0x100)
count = (count*2)|getbit_from_table(&intable[count], read_struct);
return count&0xff;
}
uint32_t get_n_bits_from_table(uint16_t *intable, uint32_t bits, struct UNSP *read_struct) {
uint32_t count = 1;
uint32_t bitcounter;
/* if (bits) { always set! */
bitcounter = bits;
while (bitcounter--)
count = count*2 + getbit_from_table(&intable[count], read_struct);
/* } */
return count-(1<<(bits&0xff));
}
uint32_t get_n_bits_from_tablesize(uint16_t *intable, struct UNSP *read_struct, uint32_t backsize) {
if (!getbit_from_table(intable, read_struct))
return get_n_bits_from_table(&intable[(backsize<<3)+2], 3, read_struct);
if (!getbit_from_table(&intable[1], read_struct))
return 8+get_n_bits_from_table(&intable[(backsize<<3)+0x82], 3, read_struct);
return 0x10+get_n_bits_from_table(&intable[0x102], 8, read_struct);
}
uint32_t get_bb(uint16_t *intable, uint32_t back, struct UNSP *read_struct) {
uint32_t pos = 1;
uint32_t bb = 0;
uint32_t i;
if ((int32_t)back<=0) /* signed */
return 0;
for (i=0;i<back;i++) {
uint32_t bit = getbit_from_table(&intable[pos], read_struct);
pos=(pos*2) + bit;
bb|=(bit<<i);
}
return bb;
}
uint32_t get_bitmap(struct UNSP *read_struct, uint32_t bits) {
uint32_t retv = 0;
if ((int32_t)bits<=0) return 0; /* signed */
while (bits--) {
read_struct->bitmap>>=1; /* unsigned */
retv<<=1;
if (read_struct->oldval>=read_struct->bitmap) { /* unsigned */
read_struct->oldval-=read_struct->bitmap;
retv|=1;
}
if (read_struct->bitmap<0x1000000) {
read_struct->bitmap<<=8;
read_struct->oldval = (read_struct->oldval<<8) | get_byte(read_struct);
}
}
return retv;
}
#endif

@ -0,0 +1,50 @@
/*
* Copyright (C) 2006 aCaB <acab@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifdef CL_EXPERIMENTAL
#ifndef __UNSP_H
#define __UNSP_H
#include "cltypes.h"
#include "others.h"
struct UNSP {
char *src_curr;
char *src_end;
uint32_t bitmap;
uint32_t oldval;
int error;
/* the following are not in the original structure */
char *table;
uint32_t tablesz;
};
uint32_t unspack(char *, char *, cli_ctx *, uint32_t, uint32_t, uint32_t, int);
uint32_t very_real_unpack(uint16_t *, uint32_t, uint32_t, uint32_t, uint32_t, char *, uint32_t, char *, uint32_t);
uint32_t get_byte(struct UNSP *);
int getbit_from_table(uint16_t *, struct UNSP *);
uint32_t get_100_bits_from_tablesize(uint16_t *, struct UNSP *, uint32_t);
uint32_t get_100_bits_from_table(uint16_t *, struct UNSP *);
uint32_t get_n_bits_from_table(uint16_t *, uint32_t, struct UNSP *);
uint32_t get_n_bits_from_tablesize(uint16_t *, struct UNSP *, uint32_t);
uint32_t get_bb(uint16_t *, uint32_t, struct UNSP *);
uint32_t get_bitmap(struct UNSP *, uint32_t);
#endif
#endif
Loading…
Cancel
Save