Stricter check of some PE values.
committer: mfx <mfx> 1088532595 +0000
This commit is contained in:
+119
@@ -0,0 +1,119 @@
|
|||||||
|
/* bptr.h --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2004 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them 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; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __UPX_BPTR_H
|
||||||
|
#define __UPX_BPTR_H
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// BoundedPtr
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class BoundedPtr
|
||||||
|
{
|
||||||
|
// typedef BoundedPtr<T> Self;
|
||||||
|
public:
|
||||||
|
typedef T* StoredType;
|
||||||
|
typedef T* PointerType;
|
||||||
|
typedef T& ReferenceType;
|
||||||
|
|
||||||
|
~BoundedPtr() { }
|
||||||
|
|
||||||
|
explicit BoundedPtr(void* base, unsigned size, T* ptr=0)
|
||||||
|
: ptr_(ptr), base_(base), size_(size) { check(); }
|
||||||
|
BoundedPtr& operator= (const BoundedPtr& other) {
|
||||||
|
assert(base_ == other.base_); assert(size_ == other.size_);
|
||||||
|
ptr_ = other.ptr_; check(); return *this;
|
||||||
|
}
|
||||||
|
BoundedPtr& operator= (T* other) {
|
||||||
|
ptr_ = other; check(); return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator T* () { check(); return ptr_; }
|
||||||
|
operator const T* () const { check(); return ptr_; }
|
||||||
|
|
||||||
|
BoundedPtr& operator += (size_t n) {
|
||||||
|
checkStrict(); ptr_ += n; checkStrict(); return *this;
|
||||||
|
}
|
||||||
|
BoundedPtr& operator -= (size_t n) {
|
||||||
|
checkStrict(); ptr_ -= n; checkStrict(); return *this;
|
||||||
|
}
|
||||||
|
BoundedPtr& operator ++ (void) {
|
||||||
|
checkStrict(); ptr_ += 1; checkStrict(); return *this;
|
||||||
|
}
|
||||||
|
// T* operator ++ (int) {
|
||||||
|
// T* p = ptr_; checkStrict(); ptr_ += 1; checkStrict(); return p;
|
||||||
|
// }
|
||||||
|
// BoundedPtr& operator -- (void) {
|
||||||
|
// checkStrict(); ptr_ -= 1; checkStrict(); return *this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void checkNULL() const {
|
||||||
|
if (!ptr_)
|
||||||
|
throwCantUnpack("unexpected NULL pointer; take care!");
|
||||||
|
}
|
||||||
|
void checkRange(size_t extra=0) const {
|
||||||
|
size_t off = (const char *) ptr_ - (const char *) base_;
|
||||||
|
if (off > size_ || off + extra > size_)
|
||||||
|
throwCantUnpack("pointer out of range; take care!");
|
||||||
|
}
|
||||||
|
void checkStrict(size_t extra=0) const {
|
||||||
|
checkNULL();
|
||||||
|
checkRange(extra);
|
||||||
|
}
|
||||||
|
void check(size_t extra=0) const {
|
||||||
|
if (ptr_) checkRange(extra);
|
||||||
|
}
|
||||||
|
|
||||||
|
void throwBoundedPtr(const char *msg) const {
|
||||||
|
throwCantPack(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
T* ptr_;
|
||||||
|
void* base_;
|
||||||
|
size_t size_;
|
||||||
|
|
||||||
|
// disable copy
|
||||||
|
BoundedPtr(const BoundedPtr&); // {}
|
||||||
|
// BoundedPtr& operator= (const BoundedPtr&); // { return *this; }
|
||||||
|
|
||||||
|
// disable dynamic allocation
|
||||||
|
DISABLE_NEW_DELETE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* already included */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et
|
||||||
|
*/
|
||||||
|
|
||||||
+91
-30
@@ -21,8 +21,8 @@
|
|||||||
If not, write to the Free Software Foundation, Inc.,
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -78,6 +78,47 @@ static bool ustrsame(const void *s1, const void *s2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (__ACC_CXX_HAVE_PLACEMENT_DELETE) || defined(__DJGPP__)
|
||||||
|
#include "bptr.h"
|
||||||
|
#define IPTR(type, var) BoundedPtr<type> var(ibuf, ibuf.getSize())
|
||||||
|
#define OPTR(type, var) BoundedPtr<type> var(obuf, obuf.getSize())
|
||||||
|
#define IPTR_I(type, var, v) BoundedPtr<type> var(ibuf, ibuf.getSize(), v)
|
||||||
|
#define OPTR_I(type, var, v) BoundedPtr<type> var(obuf, obuf.getSize(), v)
|
||||||
|
#define IPTR_C(type, var, v) const BoundedPtr<type> var(ibuf, ibuf.getSize(), v)
|
||||||
|
#define OPTR_C(type, var, v) const BoundedPtr<type> var(obuf, obuf.getSize(), v)
|
||||||
|
#else
|
||||||
|
#define IPTR(type, var) type* var = 0
|
||||||
|
#define OPTR(type, var) type* var = 0
|
||||||
|
#define IPTR_I(type, var, v) type* var = (v)
|
||||||
|
#define OPTR_I(type, var, v) type* var = (v)
|
||||||
|
#define IPTR_C(type, var, v) type* const var = (v)
|
||||||
|
#define OPTR_C(type, var, v) type* const var = (v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
|
||||||
|
{
|
||||||
|
const char *pp = (const char *) p;
|
||||||
|
const char *bb = (const char *) b;
|
||||||
|
if (pp < bb || pp > bb + blen || pp + plen > bb + blen)
|
||||||
|
throwCantUnpack("pointer out of range; take care!");
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen)
|
||||||
|
{
|
||||||
|
ACC_UNUSED(b);
|
||||||
|
if (poff > blen || poff + plen > blen)
|
||||||
|
throwCantUnpack("pointer out of range; take care!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#define ICHECK(x, size) xcheck(x, size, ibuf, ibuf.getSize())
|
||||||
|
#define OCHECK(x, size) xcheck(x, size, obuf, obuf.getSize())
|
||||||
|
|
||||||
|
#define imemset(a,b,c) ICHECK(a,c), memset(a,b,c)
|
||||||
|
#define omemset(a,b,c) OCHECK(a,c), memset(a,b,c)
|
||||||
|
#define imemcpy(a,b,c) ICHECK(a,c), memcpy(a,b,c)
|
||||||
|
#define omemcpy(a,b,c) OCHECK(a,c), memcpy(a,b,c)
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@@ -1391,6 +1432,7 @@ void PackW32Pe::processResources(Resource *res)
|
|||||||
|
|
||||||
set_le32(ores,res->offs()); // save original offset
|
set_le32(ores,res->offs()); // save original offset
|
||||||
ores += 4;
|
ores += 4;
|
||||||
|
ICHECK(ibuf + res->offs(), res->size());
|
||||||
memcpy(ores, ibuf + res->offs(), res->size());
|
memcpy(ores, ibuf + res->offs(), res->size());
|
||||||
ibuf.fill(res->offs(), res->size(), FILLVAL);
|
ibuf.fill(res->offs(), res->size(), FILLVAL);
|
||||||
res->newoffs() = ptr_diff(ores,oresources);
|
res->newoffs() = ptr_diff(ores,oresources);
|
||||||
@@ -2068,18 +2110,25 @@ void PackW32Pe::rebuildImports(upx_byte *& extrainfo)
|
|||||||
if (ODADDR(PEDIR_IMPORT) == 0)
|
if (ODADDR(PEDIR_IMPORT) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const upx_byte * const idata = obuf + get_le32(extrainfo);
|
// const upx_byte * const idata = obuf + get_le32(extrainfo);
|
||||||
|
OPTR_C(const upx_byte, idata, obuf + get_le32(extrainfo));
|
||||||
const unsigned inamespos = get_le32(extrainfo + 4);
|
const unsigned inamespos = get_le32(extrainfo + 4);
|
||||||
extrainfo += 8;
|
extrainfo += 8;
|
||||||
|
|
||||||
unsigned sdllnames = 0;
|
unsigned sdllnames = 0;
|
||||||
|
|
||||||
const upx_byte *import = ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr;
|
// const upx_byte *import = ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr;
|
||||||
const upx_byte *p = idata;
|
// const upx_byte *p;
|
||||||
|
IPTR_I(const upx_byte, import, ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr);
|
||||||
|
OPTR(const upx_byte, p);
|
||||||
|
|
||||||
while (get_le32(p) != 0)
|
for (p = idata; get_le32(p) != 0; ++p)
|
||||||
{
|
{
|
||||||
sdllnames += strlen(get_le32(p) + import) + 1;
|
const upx_byte *dname = get_le32(p) + import;
|
||||||
|
const unsigned dlen = strlen(dname);
|
||||||
|
ICHECK(dname, dlen + 1);
|
||||||
|
|
||||||
|
sdllnames += dlen + 1;
|
||||||
for (p += 8; *p;)
|
for (p += 8; *p;)
|
||||||
if (*p == 1)
|
if (*p == 1)
|
||||||
p += strlen(++p) + 1;
|
p += strlen(++p) + 1;
|
||||||
@@ -2087,8 +2136,6 @@ void PackW32Pe::rebuildImports(upx_byte *& extrainfo)
|
|||||||
p += 3; // ordinal
|
p += 3; // ordinal
|
||||||
else
|
else
|
||||||
p += 5;
|
p += 5;
|
||||||
|
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
sdllnames = ALIGN_UP(sdllnames,2);
|
sdllnames = ALIGN_UP(sdllnames,2);
|
||||||
|
|
||||||
@@ -2098,40 +2145,53 @@ void PackW32Pe::rebuildImports(upx_byte *& extrainfo)
|
|||||||
upx_byte *dllnames = Obuf + inamespos;
|
upx_byte *dllnames = Obuf + inamespos;
|
||||||
upx_byte *importednames = dllnames + sdllnames;
|
upx_byte *importednames = dllnames + sdllnames;
|
||||||
|
|
||||||
for (p = idata; get_le32(p) != 0; p++)
|
for (p = idata; get_le32(p) != 0; ++p)
|
||||||
{
|
{
|
||||||
// restore the name of the dll
|
// restore the name of the dll
|
||||||
|
const upx_byte *dname = get_le32(p) + import;
|
||||||
|
const unsigned dlen = strlen(dname);
|
||||||
|
ICHECK(dname, dlen + 1);
|
||||||
|
|
||||||
const unsigned iatoffs = get_le32(p + 4) + rvamin;
|
const unsigned iatoffs = get_le32(p + 4) + rvamin;
|
||||||
if (inamespos)
|
if (inamespos)
|
||||||
{
|
{
|
||||||
// now I rebuild the dll names
|
// now I rebuild the dll names
|
||||||
|
OCHECK(dllnames, dlen + 1);
|
||||||
|
strcpy(dllnames, dname);
|
||||||
im->dllname = ptr_diff(dllnames,Obuf);
|
im->dllname = ptr_diff(dllnames,Obuf);
|
||||||
strcpy(dllnames,get_le32(p) + import);
|
|
||||||
//;;;printf("\ndll: %s:",dllnames);
|
//;;;printf("\ndll: %s:",dllnames);
|
||||||
dllnames += strlen(dllnames) + 1;
|
dllnames += dlen + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
strcpy(Obuf + im->dllname,get_le32(p) + import);
|
{
|
||||||
|
OCHECK(Obuf + im->dllname, dlen + 1);
|
||||||
|
strcpy(Obuf + im->dllname, dname);
|
||||||
|
}
|
||||||
im->iat = iatoffs;
|
im->iat = iatoffs;
|
||||||
LE32 *newiat = (LE32 *) (Obuf + iatoffs);
|
|
||||||
|
// LE32 *newiat = (LE32 *) (Obuf + iatoffs);
|
||||||
|
OPTR_I(LE32, newiat, (LE32 *) (Obuf + iatoffs));
|
||||||
|
|
||||||
// restore the imported names+ordinals
|
// restore the imported names+ordinals
|
||||||
for (p += 8; *p; newiat++)
|
for (p += 8; *p; ++newiat)
|
||||||
if (*p == 1)
|
if (*p == 1)
|
||||||
{
|
{
|
||||||
unsigned len = strlen(++p) + 1;
|
const unsigned ilen = strlen(++p) + 1;
|
||||||
if (inamespos)
|
if (inamespos)
|
||||||
{
|
{
|
||||||
if (ptr_diff(importednames,oimpdlls) & 1)
|
if (ptr_diff(importednames,oimpdlls) & 1)
|
||||||
importednames--;
|
importednames -= 1;
|
||||||
memcpy(importednames + 2,p,len);
|
omemcpy(importednames + 2, p, ilen);
|
||||||
//;;;printf(" %s",importednames+2);
|
//;;;printf(" %s",importednames+2);
|
||||||
*newiat = ptr_diff(importednames,Obuf);
|
*newiat = ptr_diff(importednames, Obuf);
|
||||||
importednames += 2 + len;
|
importednames += 2 + ilen;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
strcpy(Obuf + *newiat + 2,p);
|
{
|
||||||
p += len;
|
OCHECK(Obuf + *newiat + 2, ilen + 1);
|
||||||
|
strcpy(Obuf + *newiat + 2, p);
|
||||||
|
}
|
||||||
|
p += ilen;
|
||||||
}
|
}
|
||||||
else if (*p == 0xff)
|
else if (*p == 0xff)
|
||||||
{
|
{
|
||||||
@@ -2158,7 +2218,7 @@ void PackW32Pe::rebuildRelocs(upx_byte *& extrainfo)
|
|||||||
|
|
||||||
if (ODSIZE(PEDIR_RELOC) == 8) // some tricky dlls use this
|
if (ODSIZE(PEDIR_RELOC) == 8) // some tricky dlls use this
|
||||||
{
|
{
|
||||||
memcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin, "\x0\x0\x0\x0\x8\x0\x0\x0", 8);
|
omemcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin, "\x0\x0\x0\x0\x8\x0\x0\x0", 8);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2166,13 +2226,14 @@ void PackW32Pe::rebuildRelocs(upx_byte *& extrainfo)
|
|||||||
const upx_byte big = extrainfo[4];
|
const upx_byte big = extrainfo[4];
|
||||||
extrainfo += 5;
|
extrainfo += 5;
|
||||||
|
|
||||||
upx_byte *p = rdata;
|
// upx_byte *p = rdata;
|
||||||
|
OPTR_I(upx_byte, p, rdata);
|
||||||
MemBuffer wrkmem;
|
MemBuffer wrkmem;
|
||||||
unsigned relocn = unoptimizeReloc32(&rdata,obuf,&wrkmem,1);
|
unsigned relocn = unoptimizeReloc32(&rdata,obuf,&wrkmem,1);
|
||||||
unsigned r16 = 0;
|
unsigned r16 = 0;
|
||||||
if (big & 6) // 16 bit relocations
|
if (big & 6) // 16 bit relocations
|
||||||
{
|
{
|
||||||
LE32 *q = (LE32*) rdata;
|
const LE32 *q = (LE32*) rdata;
|
||||||
while (*q++)
|
while (*q++)
|
||||||
r16++;
|
r16++;
|
||||||
if ((big & 6) == 6)
|
if ((big & 6) == 6)
|
||||||
@@ -2197,7 +2258,7 @@ void PackW32Pe::rebuildRelocs(upx_byte *& extrainfo)
|
|||||||
for (unsigned ic = 0; ic < relocn; ic++)
|
for (unsigned ic = 0; ic < relocn; ic++)
|
||||||
{
|
{
|
||||||
p = obuf + get_le32(wrkmem + 4 * ic);
|
p = obuf + get_le32(wrkmem + 4 * ic);
|
||||||
set_le32(p,get_le32(p) + oh.imagebase + rvamin);
|
set_le32(p, get_le32((unsigned char *)p) + oh.imagebase + rvamin);
|
||||||
rel.add(rvamin + get_le32(wrkmem + 4 * ic),3);
|
rel.add(rvamin + get_le32(wrkmem + 4 * ic),3);
|
||||||
}
|
}
|
||||||
rel.finish (oxrelocs,soxrelocs);
|
rel.finish (oxrelocs,soxrelocs);
|
||||||
@@ -2210,7 +2271,7 @@ void PackW32Pe::rebuildRelocs(upx_byte *& extrainfo)
|
|||||||
// FIXME: try to remove the original relocation section somehow
|
// FIXME: try to remove the original relocation section somehow
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memcpy (obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs);
|
omemcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs);
|
||||||
delete [] oxrelocs; oxrelocs = NULL;
|
delete [] oxrelocs; oxrelocs = NULL;
|
||||||
wrkmem.dealloc();
|
wrkmem.dealloc();
|
||||||
|
|
||||||
@@ -2226,7 +2287,7 @@ void PackW32Pe::rebuildExports()
|
|||||||
Export xport((char*)(unsigned char*) ibuf - isection[2].vaddr);
|
Export xport((char*)(unsigned char*) ibuf - isection[2].vaddr);
|
||||||
processExports(&xport);
|
processExports(&xport);
|
||||||
processExports(&xport,ODADDR(PEDIR_EXPORT));
|
processExports(&xport,ODADDR(PEDIR_EXPORT));
|
||||||
memcpy(obuf + ODADDR(PEDIR_EXPORT) - rvamin,oexport,soexport);
|
omemcpy(obuf + ODADDR(PEDIR_EXPORT) - rvamin,oexport,soexport);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackW32Pe::rebuildTls()
|
void PackW32Pe::rebuildTls()
|
||||||
@@ -2250,7 +2311,7 @@ void PackW32Pe::rebuildResources(upx_byte *& extrainfo)
|
|||||||
{
|
{
|
||||||
unsigned origoffs = get_le32(r + res.offs() - 4);
|
unsigned origoffs = get_le32(r + res.offs() - 4);
|
||||||
res.newoffs() = origoffs;
|
res.newoffs() = origoffs;
|
||||||
memcpy(obuf + origoffs - rvamin,r + res.offs(),res.size());
|
omemcpy(obuf + origoffs - rvamin,r + res.offs(),res.size());
|
||||||
if (icondir_count && res.itype() == RT_GROUP_ICON)
|
if (icondir_count && res.itype() == RT_GROUP_ICON)
|
||||||
{
|
{
|
||||||
set_le16(obuf + origoffs - rvamin + 4,icondir_count);
|
set_le16(obuf + origoffs - rvamin + 4,icondir_count);
|
||||||
@@ -2260,7 +2321,7 @@ void PackW32Pe::rebuildResources(upx_byte *& extrainfo)
|
|||||||
upx_byte *p = res.build();
|
upx_byte *p = res.build();
|
||||||
// write back when the original is zeroed
|
// write back when the original is zeroed
|
||||||
if (get_le32(obuf + ODADDR(PEDIR_RESOURCE) - rvamin + 12) == 0)
|
if (get_le32(obuf + ODADDR(PEDIR_RESOURCE) - rvamin + 12) == 0)
|
||||||
memcpy(obuf + ODADDR(PEDIR_RESOURCE) - rvamin,p,res.dirsize());
|
omemcpy(obuf + ODADDR(PEDIR_RESOURCE) - rvamin,p,res.dirsize());
|
||||||
delete [] p;
|
delete [] p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user