MEW support code added (enabled via configure option)

Merge not complete, please don't freeze yet.


git-svn: trunk@2609
remotes/push_mirror/metadata
aCaB 19 years ago
parent c7090d88b6
commit 4aa4a05cc7
  1. 5
      clamav-devel/ChangeLog
  2. 2
      clamav-devel/libclamav/Makefile.am
  3. 11
      clamav-devel/libclamav/Makefile.in
  4. 764
      clamav-devel/libclamav/mew.c
  5. 38
      clamav-devel/libclamav/mew.h
  6. 256
      clamav-devel/libclamav/packlibs.c
  7. 4
      clamav-devel/libclamav/packlibs.h
  8. 162
      clamav-devel/libclamav/pe.c

@ -1,3 +1,8 @@
Fri Jan 12 18:51:33 CET 2007 (acab)
-----------------------------------
* libclamav: add MEW support from Michal Spadlinski <gim913 * gmail.com>
Part of the Google Summer of Code program
Fri Jan 12 18:35:02 CET 2007 (tk)
---------------------------------
* libclamav/phishcheck.c: add img url link-type filtering (patch from Edwin)

@ -95,6 +95,8 @@ libclamav_la_SOURCES = \
packlibs.h \
fsg.c \
fsg.h \
mew.c \
mew.h \
line.c \
line.h \
untar.c \

@ -83,10 +83,10 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher-ncore.lo \
snprintf.lo table.lo text.lo ole2_extract.lo vba_extract.lo \
msexpand.lo pe.lo upx.lo htmlnorm.lo chmunpack.lo rebuildpe.lo \
petite.lo wwunpack.lo suecrypt.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 \
mew.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 mspack.lo cab.lo entconv.lo hashtab.lo dconf.lo
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
@ -307,6 +307,8 @@ libclamav_la_SOURCES = \
packlibs.h \
fsg.c \
fsg.h \
mew.c \
mew.h \
line.c \
line.h \
untar.c \
@ -466,6 +468,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbox.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mew.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msexpand.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mspack.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ole2_extract.Plo@am__quote@

@ -0,0 +1,764 @@
/*
* Copyright (C) 2006 Michal 'GiM' Spadlinski http://gim.org.pl/
*
* 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.
*/
/*
* lzma.c
*
* o2:28:18 CEST 2oo6-25-o6 - initial 0xA4/0x536
* oo:29:4o CEST 2oo6-26-o6 - 0x1cd/0x536 [+0x129]
* o2:13:19 CEST 2oo6-o1-o7, 2oo6-3o-o6 - 0x536/0x536
*
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#ifdef CL_EXPERIMENTAL
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include "cltypes.h"
#include "pe.h"
#include "rebuildpe.h"
#include "others.h"
#include "mew.h"
#include "packlibs.h"
#define EC32(x) le32_to_host(x) /* Convert little endian to host */
#define CE32(x) be32_to_host(x) /* Convert big endian to host */
/* modifies all parameters */
/* northfox does this shitty way,
* this should be done with just a bswap
*/
char *lzma_bswap_4861dc(struct lzmastate *p, char *old_edx)
{
/* dumb_dump_start
*
old_edx was 'uint32_t *' before and in mew_lzma there was
&new_edx where new_edx = var1C
uint32_t loc_esi, loc_edi;
uint8_t *loc_eax;
p->p2 = loc_esi = 0;
p->p0 = loc_eax = (uint8_t *)*old_edx;
*old_edx = 5;
do {
loc_esi = p->p2 << 8;
loc_edi = *(uint8_t *)((loc_eax)++);
loc_esi |= loc_edi;
(*old_edx)--;
p->p2 = loc_esi;
} while (*old_edx);
p->p0 = loc_eax;
p->p1 = 0xffffffff;
* dumb_dump_end
*/
/* XXX, mine replacement */
p->p2 = EC32(CE32(((uint32_t)cli_readint32(old_edx + 1))));
p->p1 = 0xffffffff;
p->p0 = old_edx + 5;
return p->p0;
}
int lzma_486248 (struct lzmastate *p, char **old_ecx, char *src, uint32_t size)
{
uint32_t loc_esi, loc_edi, loc_eax, loc_ecx, ret;
if (!CLI_ISCONTAINED(src, size, *old_ecx, 4) || !CLI_ISCONTAINED(src, size, p->p0, 1))
return -1;
loc_esi = p->p1;
loc_eax = loc_esi >> 0xb;
loc_ecx = cli_readint32(*old_ecx);
ret = loc_ecx&0xffff;
(loc_eax) *= ret;
loc_edi = p->p2;
if (loc_edi < loc_eax)
{
/* 48625f */
p->p1 = loc_eax;
loc_esi = ret;
loc_edi = ((int32_t)(0x800 - ret) >> 5) + ((loc_eax&0xffff0000) | ret);
/* signed<-sar, &|<-mov ax, [ecx] */
loc_ecx = (loc_ecx&0xffff0000)|(loc_edi&0xffff);
cli_writeint32(*old_ecx, loc_ecx);
ret = 0;
} else {
/* 48629e */
loc_esi -= loc_eax;
loc_edi -= loc_eax;
p->p1 = loc_esi;
p->p2 = loc_edi;
loc_eax = (loc_eax & 0xffff0000) | ret;
loc_esi = (loc_esi & 0xffff0000) | (ret >> 5);
loc_eax -= loc_esi;
loc_ecx = (loc_ecx&0xffff0000)|(loc_eax&0xffff);
cli_writeint32(*old_ecx, loc_ecx);
ret = 1;
}
loc_eax = p->p1;
if (loc_eax < 0x1000000)
{
*old_ecx = p->p0;
loc_edi = (*(uint8_t *)(p->p0));
loc_esi = ((p->p2) << 8) | loc_edi;
(*old_ecx)++;
loc_eax <<= 8;
p->p2 = loc_esi;
p->p1 = loc_eax;
p->p0 = *old_ecx;
}
return ret;
}
uint32_t lzma_48635C(uint8_t znaczek, char **old_ecx, struct lzmastate *p, uint32_t *retval, char *src, uint32_t size)
{
uint32_t loc_esi = (znaczek&0xff) >> 7, /* msb */
loc_ebx, ret;
char *loc_edi;
znaczek <<= 1;
ret = loc_esi << 9;
loc_edi = *old_ecx;
*old_ecx = loc_edi + ret + 0x202;
if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
return -1;
loc_ebx = ret | 2;
while (loc_esi == ret)
{
if (loc_ebx >= 0x100)
{
ret = (ret&0xffffff00) | (loc_ebx&0xff);
*retval = ret;
return 0;
}
loc_esi = (znaczek&0xff) >> 7;
znaczek <<= 1;
ret = ((loc_esi + 1) << 8) + loc_ebx;
*old_ecx = loc_edi + ret*2;
if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
return -1;
loc_ebx += loc_ebx;
loc_ebx |= ret;
}
loc_esi = 0x100;
while (loc_ebx < loc_esi)
{
loc_ebx += loc_ebx;
*old_ecx = loc_edi + loc_ebx;
if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
return -1;
loc_ebx |= ret;
}
ret = (ret&0xffffff00) | (loc_ebx&0xff);
*retval = ret;
return 0;
}
uint32_t lzma_4862e0 (struct lzmastate *p, char **old_ecx, uint32_t *old_edx, uint32_t *retval, char *src, uint32_t size)
{
uint32_t loc_ebx, loc_esi, stack_ecx, ret;
char *loc_edi;
loc_ebx = *old_edx;
ret = 1;
loc_edi = *old_ecx;
if (loc_ebx && !(loc_ebx&0x80000000))
{
/* loc_4862f1 */
stack_ecx = loc_ebx;
do {
loc_esi = ret+ret;
*old_ecx = loc_edi + loc_esi;
if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
return -1;
ret += loc_esi;
stack_ecx--;
} while (stack_ecx);
}
/* loc_48630b */
/* unneeded
*old_ecx = (uint8_t *)loc_ebx;
*/
*old_edx = 1 << (loc_ebx&0xff);
ret -= *old_edx;
*retval = ret;
return 0;
}
/* old_edx - write only */
uint32_t lzma_4863da (uint32_t var0, struct lzmastate *p, char **old_ecx, uint32_t *old_edx, uint32_t *retval, char *src, uint32_t size)
{
uint32_t ret;
char *loc_esi = *old_ecx;
if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
return -1;
if (ret)
{
/* loc_4863ff */
*old_ecx = loc_esi+2;
if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
return -1;
if (ret)
{
/* loc_486429 */
*old_edx = 8;
*old_ecx = loc_esi + 0x204;
if (lzma_4862e0 (p, old_ecx, old_edx, &ret, src, size) == -1)
return -1;
ret += 0x10;
} else {
/* loc_48640e */
ret = var0 << 4;
*old_edx = 3;
*old_ecx = loc_esi + 0x104 + ret;
if (lzma_4862e0 (p, old_ecx, old_edx, &ret, src, size) == -1)
return -1;
ret += 0x8;
}
} else {
/* loc_4863e9 */
ret = var0 << 4;
*old_edx = 3;
*old_ecx = loc_esi + 0x4 + ret;
if (lzma_4862e0 (p, old_ecx, old_edx, &ret, src, size) == -1)
return -1;
}
*retval = ret;
return 0;
}
uint32_t lzma_486204 (struct lzmastate *p, uint32_t old_edx, uint32_t *retval, char *src, uint32_t size)
{
uint32_t loc_esi, loc_edi, loc_ebx, loc_eax;
char *loc_edx;
loc_esi = p->p1;
loc_edi = p->p2;
loc_eax = 0;
if (old_edx && !(old_edx&0x80000000))
{
/* loc_4866212 */
loc_ebx = old_edx;
do {
loc_esi >>= 1;
loc_eax <<= 1;
if (loc_edi >= loc_esi)
{
loc_edi -= loc_esi;
loc_eax |= 1;
}
/* loc_486222 */
if (loc_esi < 0x1000000)
{
if (!CLI_ISCONTAINED(src, size, p->p0, 1))
return -1;
loc_edx = p->p0;
loc_edi <<= 8;
loc_esi <<= 8;
loc_edi |= (*loc_edx)&0xff; /* movzx ebp, byte ptr [edx] */
p->p0 = ++loc_edx;
}
loc_ebx--;
} while (loc_ebx);
}
p->p2 = loc_edi;
p->p1 = loc_esi;
*retval = loc_eax;
return 0;
}
uint32_t lzma_48631a (struct lzmastate *p, char **old_ecx, uint32_t *old_edx, uint32_t *retval, char *src, uint32_t size)
{
uint32_t copy1, copy2;
uint32_t loc_esi, loc_edi, ret;
char *loc_ebx;
copy1 = *old_edx;
loc_edi = 0;
loc_ebx = *old_ecx;
*old_edx = 1;
copy2 = (uint32_t)loc_edi;
if (copy1 <= (uint32_t)loc_edi)
{
*retval = copy2;
return 0;
}
do {
loc_esi = *old_edx + *old_edx;
*old_ecx = loc_esi + loc_ebx;
if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
return -1;
/* unneeded *old_ecx = loc_edi; */
*old_edx = loc_esi + ret;
/* ret <<= (uint32_t)(*old_ecx)&0xff; */
ret <<= (loc_edi&0xff);
copy2 |= ret;
loc_edi++;
} while (loc_edi < copy1);
*retval = copy2;
return 0;
}
int mew_lzma(struct pe_image_section_hdr *section_hdr, char *orgsource, char *buf, uint32_t size_sum, uint32_t vma, uint32_t special)
{
uint32_t var08, var0C, var10, var14, var18, var20, var24, var28, var34;
struct lzmastate var40;
uint32_t new_eax, new_edx, temp, loc_edi, loc_esi;
int i, mainloop;
char var1, var30;
char *source = buf, *dest, *new_ebx, *new_ecx, *var0C_ecxcopy, *var2C;
char *pushed_esi = NULL, *pushed_ebx = NULL;
uint32_t pushed_edx=0;
if (special)
{
pushed_edx = cli_readint32(source);
source += 4;
}
temp = cli_readint32(source) - vma;
source += 4;
if (!special) pushed_ebx = source;
new_ebx = orgsource + temp;
do {
mainloop = 1;
do {
/* loc_486450 */
if (!special)
{
source = pushed_ebx;
if (cli_readint32(source) == 0)
{
return 0;
}
}
var28 = cli_readint32 (source);
source += 4;
temp = cli_readint32 (source) - vma;
var18 = (uint32_t)orgsource + temp;
if (special) pushed_esi = orgsource + temp;
source += 4;
temp = cli_readint32 (source);
source += 5; /* yes, five */
var2C = source;
source += temp;
if (special) pushed_ebx = source;
else pushed_ebx = source;
var1 = 0;
dest = new_ebx;
if(!CLI_ISCONTAINED(orgsource, size_sum, dest, 0x6E6C))
return -1;
for (i=0; i<0x1b9b; i++)
{
cli_writeint32(dest, 0x4000400);
dest += 4;
}
loc_esi = 0;
var08 = var20 = 0;
loc_edi = 1;
var14 = var10 = var24 = 1;
lzma_bswap_4861dc(&var40, var2C);
new_edx = 0;
} while (var28 <= loc_esi); /* source = 0 */
cli_dbgmsg("MEWlzma: entering do while loop\n");
do {
/* loc_4864a5 */
new_eax = var08 & 3;
new_ecx = (((loc_esi << 4) + new_eax)*2) + new_ebx;
var0C = new_eax;
if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
return -1;
if (new_eax)
{
/* loc_486549 */
new_ecx = new_ebx + loc_esi*2 + 0x180;
var20 = 1;
/* eax=1 */
if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
return -1;
if (new_eax != 1)
{
/* loc_486627 */
var24 = var10;
var10 = var14;
/* xor eax,eax; cmp esi, 7; setnl al; dec eax; add eax, 0Ah */
/* new_eax = (((loc_esi >= 7)-1)&0xFFFFFFFD) + 0xA; */
new_eax = loc_esi>=7 ? 10:7;
new_ecx = new_ebx + 0x664;
var14 = loc_edi;
loc_esi = new_eax;
if (lzma_4863da (var0C, &var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == -1)
return -1;
var0C = new_eax;
if (var0C >= 4)
new_eax = 3;
/* loc_486662 */
new_edx = 6;
new_eax <<= 7;
new_ecx = new_eax + new_ebx + 0x360;
if (lzma_4862e0 (&var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == -1)
return -1;
if (new_eax < 4)
{
/* loc_4866ca */
loc_edi = new_eax;
} else {
/* loc_48667d */
uint32_t loc_ecx;
loc_ecx = ((int32_t)new_eax >> 1)-1; /* sar */
loc_edi = ((new_eax&1)|2) << (loc_ecx&0xff);
if (new_eax >= 0xe)
{
/* loc_4866ab */
new_edx = loc_ecx - 4;
if (lzma_486204 (&var40, new_edx, &new_eax, orgsource, size_sum) == -1)
return -1;
loc_edi += new_eax << 4;
new_edx = 4;
new_ecx = new_ebx + 0x644;
} else {
/* loc_486691 */
new_edx = loc_ecx;
loc_ecx = loc_edi - new_eax;
new_ecx = new_ebx + loc_ecx*2 + 0x55e;
}
/* loc_4866a2 */
if (lzma_48631a (&var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == -1)
return -1;
loc_edi += new_eax;
}
loc_edi++;
} else {
/* loc_486568 */
new_ecx = new_ebx + loc_esi*2 + 0x198;
if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
return -1;
if (new_eax)
{
/* loc_4865bd */
new_ecx = new_ebx + loc_esi*2 + 0x1B0;
if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
return -1;
if (new_eax)
{
/* loc_4865d2 */
new_ecx = new_ebx + loc_esi*2 + 0x1C8;
if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
return -1;
if (new_eax) {
/* loc_4865ea */
new_eax = var24;
var24 = var10;
} else {
/* loc_4865e5 */
new_eax = var10;
}
/* loc_4865f3 */
var10 = var14;
} else {
/* loc_4865cd */
new_eax = var14;
}
/* loc_4865f9 */
var14 = loc_edi;
loc_edi = new_eax;
} else {
/* loc_48657e */
new_eax = ((loc_esi + 0xf) << 4) + var0C;
new_ecx = new_ebx + new_eax*2;
if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
return -1;
if (!new_eax) {
uint32_t loc_ecx;
/* loc_486593 */
loc_ecx = var08;
loc_ecx -= loc_edi;
/* loc_esi = ((((loc_esi >= 7)-1)&0xFFFFFFFE) + 0xB); */
loc_esi = loc_esi>=7 ? 11:9;
new_eax = var18;
if (!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_eax + loc_ecx), 1))
return -1;
var1 = *(uint8_t *)(new_eax + loc_ecx);
loc_ecx = (loc_ecx&0xffffff00) | var1;
/* loc_4865af */
new_edx = var08++;
if (!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_eax + new_edx), 1))
return -1;
*(uint8_t *)(new_eax + new_edx) = loc_ecx & 0xff;
new_ecx = (char*)loc_ecx;
/* loc_4866fe */
new_eax = var08;
continue; /* !!! */
}
}
/* loc_4865fe */
new_ecx = new_ebx + 0xa68;
if (lzma_4863da (var0C, &var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == -1)
return -1;
var0C = new_eax;
/* new_eax = (((loc_esi >= 7)-1)&0xFFFFFFFD) + 0xB; */
new_eax = loc_esi>=7 ? 11:8;
loc_esi = new_eax;
}
/* loc_4866cd */
if (!loc_edi)
{
break;
} else {
var0C += 2;
new_ecx = (char*)var18;
new_edx = new_eax = var08;
new_eax -= loc_edi;
if ( ((var0C < var28 - new_edx) &&
(!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_ecx + new_eax), var0C) ||
!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_ecx + new_edx), var0C))) ||
(!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_ecx + new_eax), var28 - new_edx) ||
!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_ecx + new_edx), var28 - new_edx)) )
return -1;
do {
var1 = *(uint8_t *)(new_ecx + new_eax);
*(uint8_t *)(new_ecx + new_edx) = var1;
new_edx++;
new_eax++;
var0C--;
if (var0C <= 0)
break;
} while (new_edx < var28);
var08 = new_edx;
}
} else {
/* loc_4864C8 */
new_eax = (((var1 & 0xff) >> 4)*3) << 9;
new_ecx = new_eax + new_ebx + 0xe6c;
var0C_ecxcopy = new_ecx;
if (loc_esi >= 4)
{
/* loc_4864e8 */
if (loc_esi >= 10)
loc_esi -= 6;
else
loc_esi -= 3;
} else {
/* loc_4864e4 */
loc_esi = 0;
}
if (var20 == 0) {
/* loc_48651D */
new_eax = 1;
do {
/* loc_486525 */
/*new_ecx = var0C_ecxcopy;*/
new_eax += new_eax;
new_ecx += new_eax;
var34 = new_eax;
if ((new_eax = lzma_486248(&var40, &new_ecx, orgsource, size_sum)) == -1)
return -1;
new_eax |= var34;
/* loc_486522 */
/* keeping it here instead of at the top
* seems to work faster
*/
if (new_eax < 0x100)
{
new_ecx = var0C_ecxcopy;
}
} while (new_eax < 0x100);
/* loc_48653e */
var1 = (uint8_t)(new_eax & 0xff);
} else {
int t;
/* loc_4864FB */
new_edx = var18;
new_eax = var08 - loc_edi;
if (!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_eax + new_edx), 1))
return -1;
t = *(uint8_t *)(new_eax+new_edx);
new_eax = (new_eax&0xffffff00) | t;
/*new_edx = (uint32_t)&var40;*/
var30 = t;
if (lzma_48635C (t, &new_ecx, &var40, &new_eax, orgsource, size_sum) == -1)
return -1;
var20 = 0;
var1 = new_eax&0xff;
}
/* loc_486541 */
new_eax = var18;
/* unneeded: new_ecx = (new_ecx&0xffffff00) | var1; */
/* loc_4865af */
new_edx = var08++;
if (!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_eax + new_edx), 1))
return -1;
*(uint8_t *)(new_eax + new_edx) = var1;
}
/* loc_4866fe */
new_eax = var08;
} while (new_eax < var28);
if (special) {
uint32_t loc_ecx;
/* let's fix calls */
loc_ecx = 0;
cli_dbgmsg("MEWlen: %08x ? %08x\n", new_edx, pushed_edx);
if (!CLI_ISCONTAINED(orgsource, size_sum, pushed_esi, pushed_edx))
return -1;
do {
/* 0xe8, 0xe9 call opcodes */
if (pushed_esi[loc_ecx] == '\xe8' || pushed_esi[loc_ecx] == '\xe9')
{
char *adr = (char *)(pushed_esi + loc_ecx + 1);
loc_ecx++;
cli_writeint32(adr, EC32(CE32((uint32_t)cli_readint32(adr)))-loc_ecx);
loc_ecx += 4;
} else
loc_ecx++;
} while (loc_ecx != pushed_edx);
return 0; /*pushed_edx;*/
}
} while (mainloop);
return 0xbadc0de;
}
/* UPack lzma */
/* compare with 486248 */
uint32_t lzma_upack_esi_00(struct lzmastate *p, char *old_ecx, char *bb, uint32_t bl)
{
uint32_t loc_eax, ret, loc_edi;
loc_eax = p->p1 >> 0xb;
if (!CLI_ISCONTAINED(bb, bl, old_ecx, 4) || !CLI_ISCONTAINED(bb, bl, p->p0, 4))
{
if (!CLI_ISCONTAINED(bb, bl, old_ecx, 4))
cli_dbgmsg("contain error! %08x %08x ecx: %08x [%08x]\n", bb, bl, old_ecx,bb+bl);
else
cli_dbgmsg("contain error! %08x %08x p0: %08x [%08x]\n", bb, bl, p->p0,bb+bl);
return -1;
}
ret = cli_readint32(old_ecx);
loc_eax *= ret;
loc_edi = cli_readint32((char *)p->p0);
loc_edi = EC32(CE32(loc_edi)); /* bswap */
loc_edi -= p->p2;
if (loc_edi < loc_eax)
{
p->p1 = loc_eax;
loc_eax = (0x800 - ret) >> 5;
cli_writeint32(old_ecx, cli_readint32(old_ecx) + loc_eax);
ret = 0;
} else {
p->p2 += loc_eax;
p->p1 -= loc_eax;
loc_eax = ret >> 5;
cli_writeint32(old_ecx, cli_readint32(old_ecx) - loc_eax);
ret = 1;
}
if(((p->p1)&0xff000000) == 0)
{
p->p2 <<= 8;
p->p1 <<= 8;
p->p0++;
}
return ret;
}
/* compare with lzma_4862e0 */
/* lzma_upack_esi_4c 0x1 as eax!
*/
uint32_t lzma_upack_esi_50(struct lzmastate *p, uint32_t old_eax, uint32_t old_ecx, char **old_edx, char *old_ebp, uint32_t *retval, char *bs, uint32_t bl)
{
uint32_t loc_eax = old_eax, original = old_eax, ret;
do {
*old_edx = old_ebp + (loc_eax<<2);
if ((ret = lzma_upack_esi_00(p, *old_edx, bs, bl)) == -1)
return -1;
loc_eax += loc_eax;
loc_eax += ret;
} while (loc_eax < old_ecx);
/* cli_dbgmsg("loc_eax: %08x - ecx: %08x = %08x || original: %08x\n", loc_eax, old_ecx, loc_eax - old_ecx, original); */
*retval = loc_eax - old_ecx;
return 0;
}
uint32_t lzma_upack_esi_54(struct lzmastate *p, uint32_t old_eax, uint32_t *old_ecx, char **old_edx, uint32_t *retval, char *bs, uint32_t bl)
{
uint32_t ret, loc_eax = old_eax;
*old_ecx = ((*old_ecx)&0xffffff00)|8;
ret = lzma_upack_esi_00 (p, *old_edx, bs, bl);
*old_edx = ((*old_edx) + 4);
loc_eax = (loc_eax&0xffffff00)|1;
if (ret)
{
ret = lzma_upack_esi_00 (p, *old_edx, bs, bl);
loc_eax |= 8; /* mov al, 9 */
if (ret)
{
*old_ecx <<= 5;
loc_eax = 0x11; /* mov al, 11 */
}
}
ret = loc_eax;
if (lzma_upack_esi_50(p, 1, *old_ecx, old_edx, *old_edx + (loc_eax << 2), &loc_eax, bs, bl) == -1)
return -1;
*retval = ret + loc_eax;
return 0;
}
#endif

@ -0,0 +1,38 @@
/*
* Copyright (C) 2006 Michal 'GiM' Spadlinski http://gim.org.pl/
*
* 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.
*/
#ifndef __MEW_H
#define __MEW_H
struct lzmastate {
char *p0;
uint32_t p1, p2;
};
int mew_lzma(struct pe_image_section_hdr *, char *, char *, uint32_t, uint32_t, uint32_t);
uint32_t lzma_upack_esi_00(struct lzmastate *, char *, char *, uint32_t);
uint32_t lzma_upack_esi_50(struct lzmastate *, uint32_t, uint32_t, char **, char *, uint32_t *, char *, uint32_t);
uint32_t lzma_upack_esi_54(struct lzmastate *, uint32_t, uint32_t *, char **, uint32_t *, char *, uint32_t);
#endif

@ -23,6 +23,9 @@
#endif
#include "others.h"
#include "execs.h"
#include "pe.h"
#include "rebuildpe.h"
static int doubledl(char **scur, uint8_t *mydlptr, char *buffer, uint32_t buffersize)
{
@ -166,3 +169,256 @@ int cli_unfsg(char *source, char *dest, int ssize, int dsize, char **endsrc, cha
if (enddst) *enddst = cdst;
return 0;
}
#ifdef CL_EXPERIMENTAL
static int unmew(char *source, char *dest, int ssize, int dsize, char **endsrc, char **enddst) {
uint8_t mydl=0x80;
uint32_t myeax_backbytes, myecx_backsize, oldback = 0;
char *csrc = source, *cdst = dest;
int oob, lostbit = 1;
*cdst++=*csrc++;
while ( 1 ) {
if ((oob=doubledl(&csrc, &mydl, source, ssize))) {
if (oob == -1)
return -1;
/* 164 */
myecx_backsize = 0;
if ((oob=doubledl(&csrc, &mydl, source, ssize))) {
if (oob == -1)
return -1;
/* 16a */
myeax_backbytes = 0;
if ((oob=doubledl(&csrc, &mydl, source, ssize))) {
if (oob == -1)
return -1;
/* 170 */
lostbit = 1;
myecx_backsize++;
myeax_backbytes = 0x10;
while ( myeax_backbytes < 0x100 ) {
if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
return -1;
myeax_backbytes = myeax_backbytes*2+oob;
}
myeax_backbytes &= 0xff;
if ( ! myeax_backbytes ) {
if (cdst >= dest+dsize)
return -1;
*cdst++=0x00;
/*cli_dbgmsg("X%02x ", *(cdst-1)&0xff);*/
continue;
}
} else {
/* 18f */
if (csrc >= source+ssize)
return -1;
myeax_backbytes = *(unsigned char*)csrc;
myecx_backsize = myecx_backsize * 2 + (myeax_backbytes & 1);
myeax_backbytes = (myeax_backbytes & 0xff)>>1;
csrc++;
if (! myeax_backbytes)
{
/* cli_dbgmsg("\nBREAK \n"); */
break;
}
myecx_backsize+=2;
oldback = myeax_backbytes;
lostbit = 0;
}
} else {
/* 180 */
myecx_backsize = 1;
do {
if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
return -1;
myecx_backsize = myecx_backsize*2+oob;
if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
return -1;
} while (oob);
myecx_backsize = myecx_backsize - 1 - lostbit;
if (! myecx_backsize) {
/* 18a */
myecx_backsize = 1;
do {
if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
return -1;
myecx_backsize = myecx_backsize*2+oob;
if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
return -1;
} while (oob);
myeax_backbytes = oldback;
} else {
/* 198 */
if (csrc >= source+ssize)
return -1;
myeax_backbytes = *(unsigned char*)csrc;
myeax_backbytes += (myecx_backsize-1)<<8;
myecx_backsize = 1;
csrc++;
do {
if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
return -1;
myecx_backsize = myecx_backsize*2+oob;
if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
return -1;
} while (oob);
if (myeax_backbytes >= 0x7d00)
myecx_backsize++;
if (myeax_backbytes >= 0x500)
myecx_backsize++;
if (myeax_backbytes <= 0x7f)
myecx_backsize += 2;
oldback = myeax_backbytes;
}
lostbit = 0;
}
if (!CLI_ISCONTAINED(dest, dsize, cdst, myecx_backsize) || !CLI_ISCONTAINED(dest, dsize, cdst-myeax_backbytes, myecx_backsize))
{
cli_dbgmsg("MEW: rete: %d %d %d %d %d || %d %d %d %d %d\n", dest, dsize, cdst, myecx_backsize,
CLI_ISCONTAINED(dest, dsize, cdst, myecx_backsize),
dest, dsize, cdst-myeax_backbytes, myecx_backsize,
CLI_ISCONTAINED(dest, dsize, cdst-myeax_backbytes, myecx_backsize) );
return -1;
}
while(myecx_backsize--) {
*cdst=*(cdst-myeax_backbytes);
cdst++;
}
} else {
/* 15d */
if (cdst < dest || cdst >= dest+dsize || csrc < source || csrc >= source+ssize)
{
cli_dbgmsg("MEW: retf %08x %08x+%08x=%08x, %08x %08x+%08x=%08x\n",
cdst, dest, dsize, dest+dsize, csrc, source, ssize, source+ssize);
return -1;
}
*cdst++=*csrc++;
/* cli_dbgmsg("Z%02x ", *(cdst-1)&0xff); */
lostbit=1;
}
}
*endsrc = csrc;
*enddst = cdst;
return 0;
}
int unmew11(struct pe_image_section_hdr *section_hdr, int sectnum, char *src, int off, int ssize, int dsize, uint32_t base, uint32_t vadd, int uselzma, char **endsrc, char **enddst, int filedesc)
{
uint32_t entry_point, newedi, loc_ds=dsize, loc_ss=ssize;
char *source = src + dsize + off; /*EC32(section_hdr[sectnum].VirtualSize) + off;*/
char *lesi = source + 12, *ledi;
char *f1, *f2;
int i;
struct cli_exe_section *section = NULL;
uint32_t vma = base + vadd, size_sum = ssize + dsize;
entry_point = cli_readint32(source + 4); /* 2vGiM: ate these safe enough?
* yup, if (EC32(section_hdr[i + 1].SizeOfRawData) < ...
* ~line #879 in pe.c
*/
newedi = cli_readint32(source + 8);
ledi = src + (newedi - vma);
i = 0;
ssize -= 12;
while (1)
{
cli_dbgmsg("MEW unpacking section %d (%08x->%08x)\n", i, lesi, ledi);
if (!CLI_ISCONTAINED(src, size_sum, lesi, 4) || !CLI_ISCONTAINED(src, size_sum, ledi, 4))
{
cli_dbgmsg("Possibly programmer error or hand-crafted PE file, report to clamav team\n");
return -1;
}
if (unmew(lesi, ledi, loc_ss, loc_ds, &f1, &f2))
{
free(section);
return -1;
}
/* we don't need last section in sections since this is information for fixing imptbl */
if (!CLI_ISCONTAINED(src, size_sum, f1, 4))
{
free(section);
return -1;
}
/* XXX */
loc_ss -= (f1+4-lesi);
loc_ds -= (f2-ledi);
ledi = src + (cli_readint32(f1) - vma);
lesi = f1+4;
if (!uselzma)
{
uint32_t val = f2 - src;
/* round-up to 4k boundary, I'm not sure of this XXX */
val >>= 12;
val <<= 12;
val += 0x1000;
/* eeevil XXX */
section = cli_realloc(section, (i+2)*sizeof(struct cli_exe_section));
section[0].raw = 0; section[0].rva = vadd;
section[i+1].raw = val;
section[i+1].rva = val + vadd;
section[i].rsz = section[i].vsz = i?val - section[i].raw:val;
}
i++;
if (!cli_readint32(f1))
break;
}
/* LZMA stuff */
if (uselzma) {
/* put everything in one section */
i = 1;
if (!CLI_ISCONTAINED(src, size_sum, src+uselzma+8, 1))
{
cli_dbgmsg("MEW: couldn't access lzma 'special' tag\n");
free(section);
return -1;
}
/* 0x50 -> push eax */
cli_dbgmsg("MEW: lzma %swas used, unpacking\n", (*(src + uselzma+8) == '\x50')?"special ":"");
if (!CLI_ISCONTAINED(src, size_sum, f1+4, 20 + 4 + 5))
{
cli_dbgmsg("MEW: lzma initialization data not available!\n");
free(section);
return -1;
}
if(mew_lzma(&(section_hdr[sectnum]), src, f1+4, size_sum, vma, *(src + uselzma+8) == '\x50'))
{
free(section);
return -1;
}
loc_ds >>= 12; loc_ds <<= 12; loc_ds += 0x1000;
/* I have EP but no section's information, so I weren't sure what to do with that */ /* 2vGiM: sounds fair */
section = cli_calloc(1, sizeof(struct cli_exe_section));
section[0].raw = 0; section[0].rva = vadd;
section[0].rsz = section[0].vsz = dsize;
}
if ((f1 = cli_rebuildpe(src, section, i, base, entry_point - base, 0, 0, filedesc)))
{
if (cli_writen(filedesc, f1, 0x148+0x80+0x28*i+dsize) == -1) {
free(f1);
return -1;
}
} else {
cli_dbgmsg("MEW: Rebuilding failed\n");
return -1;
}
return 1;
}
#endif

@ -20,6 +20,10 @@
#ifndef __PACKLIBS_H
#define __PACKLIBS_H
#include "cltypes.h"
#include "rebuildpe.h"
int cli_unfsg(char *, char *, int, int, char **, char **);
int unmew11(struct pe_image_section_hdr *, int, char *, int, int, int, uint32_t, uint32_t, int, char **, char **, int);
#endif

@ -49,6 +49,9 @@
#include "str.h"
#include "execs.h"
#include "md5.h"
#ifdef CL_EXPERIMENTAL
#include "mew.h"
#endif
#ifndef O_BINARY
#define O_BINARY 0
@ -1071,7 +1074,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
}
/* UPX & FSG support */
/* UPX, FSG, MEW support */
/* try to find the first section with physical size == 0 */
found = 0;
@ -1079,12 +1082,167 @@ int cli_scanpe(int desc, cli_ctx *ctx)
for(i = 0; i < (unsigned int) nsections - 1; i++) {
if(!section_hdr[i].SizeOfRawData && section_hdr[i].VirtualSize && section_hdr[i + 1].SizeOfRawData && section_hdr[i + 1].VirtualSize) {
found = 1;
cli_dbgmsg("UPX/FSG: empty section found - assuming compression\n");
cli_dbgmsg("UPX/FSG/MEW: empty section found - assuming compression\n");
break;
}
}
}
/* MEW support */
#ifdef CL_EXPERIMENTAL
if (found) {
uint32_t fileoffset;
/* Check EP for MEW */
if(lseek(desc, ep, SEEK_SET) == -1) {
cli_dbgmsg("MEW: lseek() failed\n");
free(section_hdr);
return CL_EIO;
}
if((bytes = read(desc, buff, 25)) != 25 && bytes < 16) {
cli_dbgmsg("MEW: Can't read at least 16 bytes at 0x%x (%d) %d\n", ep, ep, bytes);
cli_dbgmsg("MEW: Broken or not compressed file\n");
free(section_hdr);
return CL_CLEAN;
}
fileoffset = (vep + cli_readint32(buff + 1) + 5);
do {
if (found && (buff[0] == '\xe9') && (fileoffset == 0x154 || fileoffset == 0x158))
{
uint32_t offdiff, uselzma;
cli_dbgmsg ("MEW characteristics found: %08X + %08X + 5 = %08X\n",
cli_readint32(buff + 1), vep, cli_readint32(buff + 1) + vep + 5);
if(lseek(desc, fileoffset, SEEK_SET) == -1) {
cli_dbgmsg("MEW: lseek() failed\n");
free(section_hdr);
return CL_EIO;
}
if((bytes = read(desc, buff, 0xb0)) != 0xb0) {
cli_dbgmsg("MEW: Can't read 0xb0 bytes at 0x%x (%d) %d\n", fileoffset, fileoffset, bytes);
break;
}
if (fileoffset == 0x154)
cli_dbgmsg("MEW: Win9x compatibility was set!\n");
else
cli_dbgmsg("MEW: Win9x compatibility was NOT set!\n");
/* is it always 0x1C and 0x21C or not */
if((offdiff = cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase)) <= EC32(section_hdr[i + 1].VirtualAddress) || offdiff >= EC32(section_hdr[i + 1].VirtualAddress) + EC32(section_hdr[i + 1].SizeOfRawData) - 4)
{
cli_dbgmsg("MEW: ESI is not in proper section\n");
break;
}
offdiff -= EC32(section_hdr[i + 1].VirtualAddress);
if(lseek(desc, EC32(section_hdr[i + 1].PointerToRawData), SEEK_SET) == -1) {
cli_dbgmsg("MEW: lseek() failed\n"); /* ACAB: lseek won't fail here but checking doesn't hurt even */
free(section_hdr);
return CL_EIO;
}
ssize = EC32(section_hdr[i + 1].VirtualSize);
dsize = EC32(section_hdr[i].VirtualSize);
cli_dbgmsg("MEW: ssize %08x dsize %08x offdiff: %08x\n", ssize, dsize, offdiff);
if(ctx->limits && ctx->limits->maxfilesize && (ssize + dsize > ctx->limits->maxfilesize || EC32(section_hdr[i + 1].SizeOfRawData) > ctx->limits->maxfilesize)) {
cli_dbgmsg("MEW: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , ctx->limits->maxfilesize);
free(section_hdr);
if(BLOCKMAX) {
*ctx->virname = "PE.MEW.ExceededFileSize";
return CL_VIRUS;
} else {
return CL_CLEAN;
}
}
/* allocate needed buffer */
if (!(src = cli_calloc (ssize + dsize, sizeof(char)))) {
free(section_hdr);
return CL_EMEM;
}
if (EC32(section_hdr[i + 1].SizeOfRawData) < offdiff + 12 || EC32(section_hdr[i + 1].SizeOfRawData) > ssize)
{
cli_dbgmsg("MEW: Size mismatch: %08x\n", EC32(section_hdr[i + 1].SizeOfRawData));
free(src);
break;
}
if((bytes = read(desc, src + dsize, EC32(section_hdr[i + 1].SizeOfRawData))) != EC32(section_hdr[i + 1].SizeOfRawData)) {
cli_dbgmsg("MEW: Can't read %d bytes [readed: %d]\n", EC32(section_hdr[i + 1].SizeOfRawData), bytes);
free(section_hdr);
free(src);
return CL_EIO;
}
cli_dbgmsg("MEW: %d (%08x) bytes read\n", bytes, bytes);
/* count offset to lzma proc, if lzma used, 0xe8 -> call */
if (buff[0x7b] == '\xe8')
{
if (!CLI_ISCONTAINED(EC32(section_hdr[1].VirtualAddress), EC32(section_hdr[1].VirtualSize), cli_readint32(buff + 0x7c) + fileoffset + 0x80, 4))
{
cli_dbgmsg("MEW: lzma proc out of bounds!\n");
free(src);
break; /* to next unpacker in chain */
}
uselzma = cli_readint32(buff + 0x7c) - (EC32(section_hdr[0].VirtualAddress) - fileoffset - 0x80);
} else
uselzma = 0;
if(!(tempfile = cli_gentemp(NULL))) {
free(section_hdr);
free(src);
return CL_EMEM;
}
if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
cli_dbgmsg("MEW: Can't create file %s\n", tempfile);
free(tempfile);
free(section_hdr);
free(src);
return CL_EIO;
}
dest = src;
switch(unmew11(section_hdr, i, src, offdiff, ssize, dsize, EC32(optional_hdr32.ImageBase), EC32(section_hdr[0].VirtualAddress), uselzma, NULL, NULL, ndesc)) {
case 1: /* Everything OK */
cli_dbgmsg("MEW: Unpacked and rebuilt executable saved in %s\n", tempfile);
free(src);
fsync(ndesc);
lseek(ndesc, 0, SEEK_SET);
cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
free(section_hdr);
close(ndesc);
if(!cli_leavetemps_flag)
unlink(tempfile);
free(tempfile);
return CL_VIRUS;
}
close(ndesc);
if(!cli_leavetemps_flag)
unlink(tempfile);
free(tempfile);
free(section_hdr);
return CL_CLEAN;
default: /* Everything gone wrong */
cli_dbgmsg("MEW: Unpacking failed\n");
close(ndesc);
unlink(tempfile); /* It's empty anyway */
free(tempfile);
free(src);
break;
}
}
} while (0);
}
#endif
if(found) {
/* Check EP for UPX vs. FSG */

Loading…
Cancel
Save