added SUE decryptor (enable via CONFIG_EXPERIMENTAL)

git-svn: trunk@2190
This commit is contained in:
aCaB 2006-08-11 18:30:35 +00:00
parent a946fc1cee
commit 3fcb62ca7b
6 changed files with 266 additions and 5 deletions

View file

@ -1,3 +1,7 @@
Fri Aug 11 19:37:24 CEST 2006 (acab)
------------------------------------
* libclamav: add support for SUE decryption (disabled)
Fri Aug 11 18:09:00 CEST 2006 (tk)
----------------------------------
* libclamav/others.c: apply win32 support patch from NJH

View file

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

View file

@ -82,9 +82,9 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher.lo \
filetypes.lo blob.lo mbox.lo message.lo snprintf.lo table.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 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 \
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
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
@ -293,6 +293,8 @@ libclamav_la_SOURCES = \
petite.h \
wwunpack.c \
wwunpack.h \
suecrypt.c \
suecrypt.h \
packlibs.c \
packlibs.h \
fsg.c \
@ -448,6 +450,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/special.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spin.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/suecrypt.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/table.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text.Plo@am__quote@

View file

@ -29,7 +29,9 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <time.h>
#include "cltypes.h"
@ -42,6 +44,7 @@
#include "upx.h"
#include "yc.h"
#include "wwunpack.h"
#include "suecrypt.h"
#include "scanners.h"
#include "rebuildpe.h"
#include "str.h"
@ -812,6 +815,82 @@ int cli_scanpe(int desc, cli_ctx *ctx)
}
#ifdef CONFIG_EXPERIMENTAL
/* SUE */
if(nsections > 2 && EC32(optional_hdr32.AddressOfEntryPoint) == EC32(section_hdr[nsections - 1].VirtualAddress) && EC32(section_hdr[nsections - 1].SizeOfRawData) > 0x350 && EC32(section_hdr[nsections - 1].SizeOfRawData) < 0x292+0x350+1000) {
char *sue=buff+0x74;
uint32_t key;
if(lseek(desc, ep-4, SEEK_SET) == -1) {
cli_dbgmsg("SUE: lseek() failed - EP out of file\n");
free(section_hdr);
return CL_EIO;
}
if((unsigned int) cli_readn(desc, buff, EC32(section_hdr[nsections - 1].SizeOfRawData)+4) == EC32(section_hdr[nsections - 1].SizeOfRawData)+4) {
found=0;
while(CLI_ISCONTAINED(buff+4, EC32(section_hdr[nsections - 1].SizeOfRawData), sue, 4*3)) {
if((cli_readint32(sue)^cli_readint32(sue+4))==0x5c41090e && (cli_readint32(sue)^cli_readint32(sue+8))==0x021e0145) {
found=1;
key=(cli_readint32(sue)^0x6e72656b);
break;
}
sue++;
}
cli_dbgmsg("SUE: key(%x) found @%x\n", key, sue-buff);
if (found && CLI_ISCONTAINED(buff, EC32(section_hdr[nsections - 1].SizeOfRawData), sue-0x74, 0xbe) &&
(sue=sudecrypt(desc, fsize, section_hdr, nsections-1, sue, key, cli_readint32(buff), e_lfanew))) {
if(!(tempfile = cli_gentemp(NULL))) {
free(sue);
free(section_hdr);
return CL_EMEM;
}
if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
cli_dbgmsg("sue: Can't create file %s\n", tempfile);
free(tempfile);
free(sue);
free(section_hdr);
return CL_EIO;
}
if((unsigned int) write(ndesc, sue, ep) != ep) {
cli_dbgmsg("sue: Can't write %d bytes\n", ep);
close(ndesc);
free(tempfile);
free(sue);
free(section_hdr);
return CL_EIO;
}
free(sue);
if (cli_leavetemps_flag)
cli_dbgmsg("SUE: Decrypted executable saved in %s\n", tempfile);
else
cli_dbgmsg("SUE: Executable decrypted\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;
}
close(ndesc);
if(!cli_leavetemps_flag)
unlink(tempfile);
free(tempfile);
}
}
}
#endif
/* UPX & FSG support */
/* try to find the first section with physical size == 0 */
@ -1961,7 +2040,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
}
if((unsigned int) write(ndesc, dest, dsize) != dsize) {
cli_dbgmsg("UPX/FSG: Can't write %d bytes\n", dsize);
cli_dbgmsg("WWPack: Can't write %d bytes\n", dsize);
close(ndesc);
free(tempfile);
free(dest);
@ -1970,7 +2049,11 @@ int cli_scanpe(int desc, cli_ctx *ctx)
}
free(dest);
cli_dbgmsg("WWPack: Unpacked and rebuilt executable saved in %s\n", tempfile);
if (cli_leavetemps_flag)
cli_dbgmsg("WWPack: Unpacked and rebuilt executable saved in %s\n", tempfile);
else
cli_dbgmsg("WWPack: Unpacked and rebuilt executable\n");
fsync(ndesc);
lseek(ndesc, 0, SEEK_SET);

View file

@ -0,0 +1,139 @@
/*
* 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.
*/
/*
** suecrypt.c
**
** 05/08/2k6 - Quick RCE, started coding.
** 06/08/2k6 - There were large drops of black rain.
** 07/08/2k6 - Found more versions, back to reversing.
** 11/08/2k6 - Generic and special cases handler. Release.
**
*/
/*
** Unpacks and rebuilds suecrypt(*)
**
** Not sure at all what this stuff is, couldn't find any reference to it
** Seems to be popular in dialers, can't say more except...
** Christoph asked for it and that's enough :)
**
** (*) some versions or maybe only some samples
*/
/*
** TODO:
**
** needs performance tests
**
*/
#ifdef CONFIG_EXPERIMENTAL
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include "cltypes.h"
#include "others.h"
#include "pe.h"
#define EC32(x) le32_to_host(x) /* Convert little endian to host */
#define EC16(x) le16_to_host(x)
#define VAALIGN(s) (((s)/0x1000+((s)%0x1000!=0))*0x1000)
char *sudecrypt(int desc, size_t fsize, struct pe_image_section_hdr *section_hdr, uint16_t sects, char *buff, uint32_t bkey, uint32_t pkey, uint32_t e_lfanew) {
char *file, *hunk;
uint32_t va,sz,key;
int i, j;
cli_dbgmsg("in suecrypt\n");
if (!(file=cli_calloc(fsize, 1))) return 0;
lseek(desc, 0, SEEK_SET);
if((size_t) cli_readn(desc, file, fsize) != fsize) {
cli_dbgmsg("SUE: Can't read %d bytes\n", fsize);
free(file);
return 0;
}
va=(bkey>>16)|(bkey<<16);
key=((sz=cli_readint32(buff+0x3e))^va);
if (!key || key==0x208 || key==0x3bc) key=((sz=cli_readint32(buff+0x46))^va); /* FIXME: black magic */
if (key!=pkey) {
cli_dbgmsg("SUE: Key seems not (entirely) encrypted\n\tpossible key: 0%08x\n\tcrypted key: 0%08x\n\tplain key: 0%08x\n", pkey, key, sz);
va=0;
for (i=0; i<4; i++) {
va=(va<<8)|0xff;
if (((key&va)|(sz&(~va)))==pkey) {
key=pkey;
break;
}
}
if (i==4) cli_dbgmsg("SUE: let's roll the dice...\n");
}
cli_dbgmsg("SUE: Decrypting with 0%08x\n", key);
i=0;
while(1) {
if (!CLI_ISCONTAINED(buff-0x74, 0xbe, buff-0x58+i*8, 8)) {
free(file);
return 0;
}
va=(cli_readint32(buff-0x58+i*8)^bkey);
sz=(cli_readint32(buff-0x58+4+i*8)^bkey);
if (!va) break;
cli_dbgmsg("SUE: Hunk #%d RVA:%x size:%d\n", i, va, sz);
for (j=0; j<sects; j++) {
if(!CLI_ISCONTAINED(EC32(section_hdr[j].VirtualAddress), EC32(section_hdr[j].SizeOfRawData), va, sz)) continue;
hunk=file+EC32(section_hdr[j].VirtualAddress)-va+EC32(section_hdr[j].PointerToRawData);
while(sz>=4) {
cli_writeint32(hunk, cli_readint32(hunk)^key);
hunk+=4;
sz-=4;
}
break;
}
if (j==sects) {
cli_dbgmsg("SUE: Hunk out of file or cross sections\n");
free(file);
return 0;
}
i++;
}
va=(cli_readint32(buff-0x74)^bkey);
cli_dbgmsg("SUE: found OEP: @%x\n", va);
hunk=file+e_lfanew;
hunk[6]=sects&0xff;
hunk[7]=sects>>8;
cli_writeint32(hunk+0x28, va);
memset(hunk+0xf8+0x28*sects, 0, 0x28);
return file;
}
#endif

View file

@ -0,0 +1,30 @@
/*
* 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 CONFIG_EXPERIMENTAL
#ifndef __UNSUE_H
#define __UNSUE_H
#include "cltypes.h"
#include "rebuildpe.h"
char *sudecrypt(int, size_t, struct pe_image_section_hdr *, uint16_t, char *, uint32_t, uint32_t, uint32_t);
#endif
#endif