mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 18:33:16 +00:00
UPX decompression
git-svn: trunk@601
This commit is contained in:
parent
ac75a532b4
commit
342e27a516
6 changed files with 429 additions and 27 deletions
|
@ -1,3 +1,11 @@
|
|||
Sat Jun 12 02:11:12 CEST 2004 (tk)
|
||||
----------------------------------
|
||||
* libclamav: pe: integrate with UPX decompressor from aCaB <acab*clamav.net>
|
||||
(with support for NRV2B, NRV2D and NRV2E compression).
|
||||
To protect against compressed files with hacked headers,
|
||||
the PE parser tries to find a signature of the UPX
|
||||
decompression routine at EP + 0x78.
|
||||
|
||||
Fri Jun 11 22:11:31 CEST 2004 (tk)
|
||||
----------------------------------
|
||||
* libclamav: pe: add dumper; RVA calculation; fix error codes
|
||||
|
|
|
@ -94,6 +94,8 @@ libclamav_la_SOURCES = \
|
|||
mspack/qtmd.c \
|
||||
mspack/qtm.h \
|
||||
mspack/system.c \
|
||||
mspack/system.h
|
||||
mspack/system.h \
|
||||
upx.c \
|
||||
upx.h
|
||||
|
||||
lib_LTLIBRARIES = libclamav.la
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Makefile.in generated by automake 1.6.3 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.6.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
|
||||
|
@ -66,7 +66,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
|||
INSTALL_DATA = @INSTALL_DATA@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = @program_transform_name@
|
||||
|
@ -196,7 +195,9 @@ libclamav_la_SOURCES = \
|
|||
mspack/qtmd.c \
|
||||
mspack/qtm.h \
|
||||
mspack/system.c \
|
||||
mspack/system.h
|
||||
mspack/system.h \
|
||||
upx.c \
|
||||
upx.h
|
||||
|
||||
|
||||
lib_LTLIBRARIES = libclamav.la
|
||||
|
@ -212,7 +213,7 @@ am_libclamav_la_OBJECTS = matcher.lo md5.lo others.lo readdb.lo cvd.lo \
|
|||
zzip-file.lo zzip-info.lo zzip-io.lo zzip-stat.lo zzip-zip.lo \
|
||||
strc.lo blob.lo mbox.lo message.lo snprintf.lo strrcpy.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
|
||||
pe.lo cabd.lo lzxd.lo mszipd.lo qtmd.lo system.lo upx.lo
|
||||
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
|
||||
|
||||
DEFS = @DEFS@
|
||||
|
@ -234,7 +235,7 @@ am__depfiles_maybe = depfiles
|
|||
@AMDEP_TRUE@ ./$(DEPDIR)/str.Plo ./$(DEPDIR)/strc.Plo \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/strrcpy.Plo ./$(DEPDIR)/system.Plo \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/table.Plo ./$(DEPDIR)/text.Plo \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/unrarlib.Plo \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/unrarlib.Plo ./$(DEPDIR)/upx.Plo \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/vba_extract.Plo \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/zzip-dir.Plo ./$(DEPDIR)/zzip-err.Plo \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/zzip-file.Plo ./$(DEPDIR)/zzip-info.Plo \
|
||||
|
@ -285,12 +286,6 @@ uninstall-libLTLIBRARIES:
|
|||
|
||||
clean-libLTLIBRARIES:
|
||||
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
|
||||
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
|
||||
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
|
||||
test -z "$dir" && dir=.; \
|
||||
echo "rm -f \"$${dir}/so_locations\""; \
|
||||
rm -f "$${dir}/so_locations"; \
|
||||
done
|
||||
zzip-dir.lo: zziplib/zzip-dir.c
|
||||
zzip-err.lo: zziplib/zzip-err.c
|
||||
zzip-file.lo: zziplib/zzip-file.c
|
||||
|
@ -338,6 +333,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/table.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrarlib.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upx.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vba_extract.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip-dir.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip-err.Plo@am__quote@
|
||||
|
@ -672,7 +668,7 @@ top_distdir = ..
|
|||
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@list='$(DISTFILES)'; for file in $$list; do \
|
||||
@for file in $(DISTFILES); do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
|
@ -718,7 +714,7 @@ mostlyclean-generic:
|
|||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
|
|
|
@ -35,11 +35,16 @@
|
|||
#include "cltypes.h"
|
||||
#include "clamav.h"
|
||||
#include "others.h"
|
||||
#include "upx.h"
|
||||
|
||||
#define IMAGE_DOS_SIGNATURE 0x5a4d /* MZ */
|
||||
#define IMAGE_NT_SIGNATURE 0x00004550
|
||||
#define IMAGE_OPTIONAL_SIGNATURE 0x010b
|
||||
|
||||
#define UPX_NRV2B "\x11\xc9\x75\x20\x41\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x01\xdb\x73\xef\x75\x09"
|
||||
#define UPX_NRV2D "\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x75\x20"
|
||||
#define UPX_NRV2E "\x83\xf0\xff\x74\x75\xd1\xf8\x89\xc5\xeb\x0b\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x72\xcc"
|
||||
|
||||
struct pe_image_file_hdr {
|
||||
uint32_t Magic;
|
||||
uint16_t Machine;
|
||||
|
@ -109,7 +114,6 @@ struct pe_image_section_hdr {
|
|||
uint32_t Characteristics;
|
||||
};
|
||||
|
||||
|
||||
static uint32_t cli_rawaddr(uint32_t rva, struct pe_image_section_hdr *shp, uint16_t nos)
|
||||
{
|
||||
int i, found = 0;
|
||||
|
@ -140,19 +144,19 @@ static int cli_ddump(int desc, int offset, int size, const char *file)
|
|||
|
||||
if((pos = lseek(desc, 0, SEEK_CUR)) == -1) {
|
||||
cli_dbgmsg("Invalid descriptor\n");
|
||||
return -1;
|
||||
return CL_EIO;
|
||||
}
|
||||
|
||||
if(lseek(desc, offset, SEEK_SET) == -1) {
|
||||
cli_dbgmsg("lseek() failed\n");
|
||||
lseek(desc, pos, SEEK_SET);
|
||||
return -1;
|
||||
return CL_EIO;
|
||||
}
|
||||
|
||||
if((ndesc = open(file, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
|
||||
cli_dbgmsg("Can't create file %s\n", file);
|
||||
lseek(desc, pos, SEEK_SET);
|
||||
return -1;
|
||||
return CL_EIO;
|
||||
}
|
||||
|
||||
while((bread = read(desc, buff, FILEBUFF)) > 0) {
|
||||
|
@ -162,7 +166,7 @@ static int cli_ddump(int desc, int offset, int size, const char *file)
|
|||
lseek(desc, pos, SEEK_SET);
|
||||
close(ndesc);
|
||||
unlink(file);
|
||||
return -1;
|
||||
return CL_EIO;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
|
@ -171,7 +175,7 @@ static int cli_ddump(int desc, int offset, int size, const char *file)
|
|||
lseek(desc, pos, SEEK_SET);
|
||||
close(ndesc);
|
||||
unlink(file);
|
||||
return -1;
|
||||
return CL_EIO;
|
||||
}
|
||||
}
|
||||
sum += bread;
|
||||
|
@ -191,8 +195,9 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
|||
struct pe_image_optional_hdr optional_hdr;
|
||||
struct pe_image_section_hdr *section_hdr;
|
||||
struct stat sb;
|
||||
char sname[9];
|
||||
int i;
|
||||
char sname[9], buff[24], *tempfile;
|
||||
int i, found;
|
||||
int (*upxfn)(char *, int , char *, int) = NULL;
|
||||
|
||||
|
||||
if(read(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
|
||||
|
@ -321,8 +326,9 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
|||
|
||||
if(read(desc, §ion_hdr[i], sizeof(struct pe_image_section_hdr)) != sizeof(struct pe_image_section_hdr)) {
|
||||
cli_dbgmsg("Can't read section header\n");
|
||||
cli_warnmsg("Possibly broken PE file\n");
|
||||
free(section_hdr);
|
||||
return -1;
|
||||
return CL_CLEAN;
|
||||
}
|
||||
|
||||
strncpy(sname, section_hdr[i].Name, 8);
|
||||
|
@ -364,7 +370,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
|||
if(fstat(desc, &sb) == -1) {
|
||||
cli_dbgmsg("fstat failed\n");
|
||||
free(section_hdr);
|
||||
return -1;
|
||||
return CL_EIO;
|
||||
}
|
||||
|
||||
ep = cli_rawaddr(optional_hdr.AddressOfEntryPoint, section_hdr, file_hdr.NumberOfSections);
|
||||
|
@ -372,13 +378,114 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
|||
if(section_hdr[i].PointerToRawData + section_hdr[i].SizeOfRawData > sb.st_size || ep == -1) {
|
||||
cli_warnmsg("Possibly broken PE file\n");
|
||||
free(section_hdr);
|
||||
return -1;
|
||||
return CL_CLEAN;
|
||||
}
|
||||
|
||||
cli_dbgmsg("EntryPoint: 0x%x (%d)\n", ep, ep);
|
||||
cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", ep, ep);
|
||||
|
||||
if(lseek(desc, ep + 0x78, SEEK_SET) == -1) {
|
||||
cli_dbgmsg("lseek() failed\n");
|
||||
free(section_hdr);
|
||||
return CL_EIO;
|
||||
}
|
||||
|
||||
if(read(desc, buff, 24) != 24) {
|
||||
cli_dbgmsg("Can't read 24 bytes at 0x%x (%d)\n", ep + 0x78, ep + 0x78);
|
||||
} else {
|
||||
if(!memcmp(buff, UPX_NRV2B, 24)) {
|
||||
cli_dbgmsg("UPX: NRV2B decompressor detected\n");
|
||||
upxfn = upx_inflate2b;
|
||||
} else if(!memcmp(buff, UPX_NRV2D, 24)) {
|
||||
cli_dbgmsg("UPX: NRV2D decompressor detected\n");
|
||||
upxfn = upx_inflate2d;
|
||||
} else if(!memcmp(buff, UPX_NRV2E, 24)) {
|
||||
cli_dbgmsg("UPX: NRV2E decompressor detected\n");
|
||||
upxfn = upx_inflate2e;
|
||||
}
|
||||
}
|
||||
|
||||
if(upxfn) {
|
||||
/* try to find the first section with physical size == 0 */
|
||||
found = 0;
|
||||
for(i = 0; i < file_hdr.NumberOfSections; i++) {
|
||||
if(!section_hdr[i].SizeOfRawData) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(found) {
|
||||
uint32_t ssize, dsize;
|
||||
char *src, *dest;
|
||||
|
||||
/* we assume (i + 1) is UPX1 */
|
||||
if(strncmp(section_hdr[i].Name, "UPX0", 4) || strncmp(section_hdr[i + 1].Name, "UPX1", 4))
|
||||
cli_dbgmsg("Possibly hacked UPX section headers\n");
|
||||
|
||||
/* FIXME: use file operations in case of big files */
|
||||
ssize = section_hdr[i + 1].SizeOfRawData;
|
||||
dsize = section_hdr[i].VirtualSize + section_hdr[i + 1].VirtualSize;
|
||||
if((src = (char *) malloc(ssize)) == NULL) {
|
||||
free(section_hdr);
|
||||
return CL_EMEM;
|
||||
}
|
||||
|
||||
if((dest = (char *) malloc(dsize)) == NULL) {
|
||||
free(section_hdr);
|
||||
free(src);
|
||||
return CL_EMEM;
|
||||
}
|
||||
|
||||
lseek(desc, section_hdr[i + 1].PointerToRawData, SEEK_SET);
|
||||
if(read(desc, src, ssize) != ssize) {
|
||||
cli_dbgmsg("Can't read raw data of section %d\n", i + 1);
|
||||
free(section_hdr);
|
||||
free(src);
|
||||
free(dest);
|
||||
return CL_EMEM;
|
||||
}
|
||||
|
||||
if(upxfn(src, ssize, dest, dsize)) {
|
||||
cli_dbg("UPX decompression failed\n");
|
||||
} else {
|
||||
int ndesc;
|
||||
|
||||
tempfile = cl_gentemp(NULL);
|
||||
|
||||
if((ndesc = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
|
||||
cli_dbgmsg("Can't create file %s\n", tempfile);
|
||||
free(section_hdr);
|
||||
free(src);
|
||||
free(dest);
|
||||
return CL_EIO;
|
||||
}
|
||||
|
||||
if(write(ndesc, dest, dsize) != dsize) {
|
||||
cli_dbgmsg("Can't write %d bytes\n", dsize);
|
||||
free(section_hdr);
|
||||
free(src);
|
||||
free(dest);
|
||||
return CL_EIO;
|
||||
}
|
||||
|
||||
close(ndesc);
|
||||
|
||||
/* TODO: scan and unlink file */
|
||||
|
||||
/* unlink(tempfile); */
|
||||
free(tempfile);
|
||||
}
|
||||
|
||||
free(src);
|
||||
free(dest);
|
||||
|
||||
} else {
|
||||
cli_dbgmsg("UPX sections not found\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* to be continued ... */
|
||||
|
||||
free(section_hdr);
|
||||
return 0;
|
||||
return CL_CLEAN;
|
||||
}
|
||||
|
|
263
clamav-devel/libclamav/upx.c
Normal file
263
clamav-devel/libclamav/upx.c
Normal file
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* Copyright (C) 2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
** upxdec.c
|
||||
**
|
||||
** 05/05/2k4 - 1st attempt
|
||||
** 08/05/2k4 - Now works as a charm :D
|
||||
** 09/05/2k4 - Moved code outta main(), got rid of globals for thread safety, added bound checking, minor cleaning
|
||||
** 04/06/2k4 - Now we handle 2B, 2D and 2E :D
|
||||
*/
|
||||
|
||||
/*
|
||||
** This code unpacks a dumped UPX1 section to a file.
|
||||
** It was written reversing the loader found on some Win32 UPX compressed trojans; while porting
|
||||
** it to C i've kinda followed the asm flow so it will probably be a bit hard to read.
|
||||
** This code DOES NOT revert the uncompressed section to its original state as no E8/E9 fixup and
|
||||
** of cause no IAT rebuild are performed.
|
||||
**
|
||||
** The Win32 asm unpacker is really a little programming jewel, pretty damn rare in these days of
|
||||
** bloatness. My gratitude to whoever wrote it.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
/* [doubleebx] */
|
||||
|
||||
static int doubleebx(char *src, int *myebx, int *scur, int ssize)
|
||||
{
|
||||
int oldebx = *myebx;
|
||||
|
||||
*myebx*=2;
|
||||
if ( !(oldebx & 0x7fffffff)) {
|
||||
if (*scur<0 || ssize-*scur<4)
|
||||
return 0;
|
||||
oldebx = *(int*)(src+*scur);
|
||||
*myebx = oldebx*2+1;
|
||||
*scur+=4;
|
||||
}
|
||||
return (oldebx>>31)&1;
|
||||
}
|
||||
|
||||
/* [inflate] */
|
||||
|
||||
int upx_inflate2b(char *src, int ssize, char *dst, int dsize)
|
||||
{
|
||||
int backbytes, backsize, unp_offset = -1, i;
|
||||
int myebx = 0;
|
||||
int scur=0, dcur=0;
|
||||
|
||||
while (1) {
|
||||
while (doubleebx(src, &myebx, &scur, ssize)) {
|
||||
if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize)
|
||||
return -1;
|
||||
dst[dcur++] = src[scur++];
|
||||
}
|
||||
|
||||
backbytes = 1;
|
||||
|
||||
while (1) {
|
||||
backbytes = backbytes*2+doubleebx(src, &myebx, &scur, ssize);
|
||||
if (doubleebx(src, &myebx, &scur, ssize))
|
||||
break;
|
||||
}
|
||||
|
||||
backsize = 0;
|
||||
backbytes-=3;
|
||||
|
||||
if ( backbytes >= 0 ) {
|
||||
|
||||
if (scur<0 || scur>=ssize)
|
||||
return -1;
|
||||
backbytes<<=8;
|
||||
backbytes+=(unsigned char)(src[scur++]);
|
||||
backbytes^=0xffffffff;
|
||||
|
||||
if (!backbytes)
|
||||
break;
|
||||
unp_offset = backbytes;
|
||||
}
|
||||
|
||||
backsize = doubleebx(src, &myebx, &scur, ssize);
|
||||
backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize);
|
||||
if (!backsize) {
|
||||
backsize++;
|
||||
do {
|
||||
backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize);
|
||||
} while (!doubleebx(src, &myebx, &scur, ssize));
|
||||
backsize+=2;
|
||||
}
|
||||
|
||||
if ( (unsigned int)unp_offset < 0xfffff300 )
|
||||
backsize++;
|
||||
|
||||
backsize++;
|
||||
for (i = 0; i < backsize; i++) {
|
||||
if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize)
|
||||
return -1;
|
||||
dst[dcur + i] = dst[dcur + unp_offset + i];
|
||||
}
|
||||
dcur+=backsize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int upx_inflate2d(char *src, int ssize, char *dst, int dsize)
|
||||
{
|
||||
int backbytes, backsize, unp_offset = -1, i;
|
||||
int myebx = 0;
|
||||
int scur=0, dcur=0;
|
||||
|
||||
while (1) {
|
||||
while (doubleebx(src, &myebx, &scur, ssize)) {
|
||||
if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize)
|
||||
return -1;
|
||||
dst[dcur++] = src[scur++];
|
||||
}
|
||||
|
||||
backbytes = 1;
|
||||
|
||||
while (1) {
|
||||
backbytes = backbytes*2+doubleebx(src, &myebx, &scur, ssize);
|
||||
if (doubleebx(src, &myebx, &scur, ssize))
|
||||
break;
|
||||
backbytes--;
|
||||
backbytes=backbytes*2+doubleebx(src, &myebx, &scur, ssize);
|
||||
}
|
||||
|
||||
backsize = 0;
|
||||
backbytes-=3;
|
||||
|
||||
if ( backbytes >= 0 ) {
|
||||
|
||||
if (scur<0 || scur>=ssize)
|
||||
return -1;
|
||||
backbytes<<=8;
|
||||
backbytes+=(unsigned char)(src[scur++]);
|
||||
backbytes^=0xffffffff;
|
||||
|
||||
if (!backbytes)
|
||||
break;
|
||||
backsize = backbytes & 1;
|
||||
backbytes>>=1;
|
||||
unp_offset = backbytes;
|
||||
}
|
||||
else
|
||||
backsize = doubleebx(src, &myebx, &scur, ssize);
|
||||
|
||||
backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize);
|
||||
if (!backsize) {
|
||||
backsize++;
|
||||
do {
|
||||
backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize);
|
||||
} while (!doubleebx(src, &myebx, &scur, ssize));
|
||||
backsize+=2;
|
||||
}
|
||||
|
||||
if ( (unsigned int)unp_offset < 0xfffffb00 )
|
||||
backsize++;
|
||||
|
||||
backsize++;
|
||||
for (i = 0; i < backsize; i++) {
|
||||
if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize)
|
||||
return -1;
|
||||
dst[dcur + i] = dst[dcur + unp_offset + i];
|
||||
}
|
||||
dcur+=backsize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int upx_inflate2e(char *src, int ssize, char *dst, int dsize)
|
||||
{
|
||||
int backbytes, backsize, unp_offset = -1, i;
|
||||
int myebx = 0;
|
||||
int scur=0, dcur=0;
|
||||
|
||||
while (1) {
|
||||
while (doubleebx(src, &myebx, &scur, ssize)) {
|
||||
if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize)
|
||||
return -1;
|
||||
dst[dcur++] = src[scur++];
|
||||
}
|
||||
|
||||
backbytes = 1;
|
||||
|
||||
while (1) {
|
||||
backbytes = backbytes*2+doubleebx(src, &myebx, &scur, ssize);
|
||||
if (doubleebx(src, &myebx, &scur, ssize))
|
||||
break;
|
||||
backbytes--;
|
||||
backbytes=backbytes*2+doubleebx(src, &myebx, &scur, ssize);
|
||||
}
|
||||
|
||||
backsize = 0;
|
||||
backbytes-=3;
|
||||
|
||||
if ( backbytes >= 0 ) {
|
||||
|
||||
if (scur<0 || scur>=ssize)
|
||||
return -1;
|
||||
backbytes<<=8;
|
||||
backbytes+=(unsigned char)(src[scur++]);
|
||||
backbytes^=0xffffffff;
|
||||
|
||||
if (!backbytes)
|
||||
break;
|
||||
backsize = backbytes & 1; /* Using backsize to carry on the shifted out bit (UPX uses CF) */
|
||||
backbytes>>=1;
|
||||
unp_offset = backbytes;
|
||||
}
|
||||
else
|
||||
backsize = doubleebx(src, &myebx, &scur, ssize); /* Using backsize to carry on the doubleebx result (UPX uses CF) */
|
||||
|
||||
if (backsize) { /* i.e. IF ( last sar shifted out 1 bit || last doubleebx()==1 ) */
|
||||
backsize = doubleebx(src, &myebx, &scur, ssize);
|
||||
}
|
||||
else {
|
||||
backsize = 1;
|
||||
if (doubleebx(src, &myebx, &scur, ssize))
|
||||
backsize = 2 + doubleebx(src, &myebx, &scur, ssize);
|
||||
else {
|
||||
do {
|
||||
backsize = backsize * 2 + doubleebx(src, &myebx, &scur, ssize);
|
||||
} while (!doubleebx(src, &myebx, &scur, ssize));
|
||||
backsize+=2;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (unsigned int)unp_offset < 0xfffffb00 )
|
||||
backsize++;
|
||||
|
||||
backsize+=2;
|
||||
for (i = 0; i < backsize; i++) {
|
||||
if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize)
|
||||
return -1;
|
||||
dst[dcur + i] = dst[dcur + unp_offset + i];
|
||||
}
|
||||
dcur+=backsize;
|
||||
}
|
||||
return 0;
|
||||
}
|
26
clamav-devel/libclamav/upx.h
Normal file
26
clamav-devel/libclamav/upx.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (C) 2004 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __UPX_H
|
||||
#define __UPX_H
|
||||
|
||||
int upx_inflate2b(char *, int , char *, int);
|
||||
int upx_inflate2d(char *, int , char *, int);
|
||||
int upx_inflate2e(char *, int , char *, int);
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue