From 5349bd0b2abcb7e832b697e2ab6d68f017c87fb4 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Tue, 29 Jun 2004 18:09:55 +0000 Subject: [PATCH] Stricter check of some PE values. committer: mfx 1088532595 +0000 --- src/bptr.h | 119 +++++++++++++++++++++++++++++++++++++++++++++++ src/p_w32pe.cpp | 121 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 210 insertions(+), 30 deletions(-) create mode 100644 src/bptr.h diff --git a/src/bptr.h b/src/bptr.h new file mode 100644 index 00000000..16165ae6 --- /dev/null +++ b/src/bptr.h @@ -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 + + */ + + +#ifndef __UPX_BPTR_H +#define __UPX_BPTR_H + + +/************************************************************************* +// BoundedPtr +**************************************************************************/ + +template +class BoundedPtr +{ +// typedef BoundedPtr 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 +*/ + diff --git a/src/p_w32pe.cpp b/src/p_w32pe.cpp index fd00184b..30c18b49 100644 --- a/src/p_w32pe.cpp +++ b/src/p_w32pe.cpp @@ -21,8 +21,8 @@ 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 - markus@oberhumer.com ml1050@cdata.tvnet.hu + Markus F.X.J. Oberhumer Laszlo Molnar + */ @@ -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 var(ibuf, ibuf.getSize()) +#define OPTR(type, var) BoundedPtr var(obuf, obuf.getSize()) +#define IPTR_I(type, var, v) BoundedPtr var(ibuf, ibuf.getSize(), v) +#define OPTR_I(type, var, v) BoundedPtr var(obuf, obuf.getSize(), v) +#define IPTR_C(type, var, v) const BoundedPtr var(ibuf, ibuf.getSize(), v) +#define OPTR_C(type, var, v) const BoundedPtr 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 ores += 4; + ICHECK(ibuf + res->offs(), res->size()); memcpy(ores, ibuf + res->offs(), res->size()); ibuf.fill(res->offs(), res->size(), FILLVAL); res->newoffs() = ptr_diff(ores,oresources); @@ -2068,18 +2110,25 @@ void PackW32Pe::rebuildImports(upx_byte *& extrainfo) if (ODADDR(PEDIR_IMPORT) == 0) 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); extrainfo += 8; unsigned sdllnames = 0; - const upx_byte *import = ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr; - const upx_byte *p = idata; +// const upx_byte *import = ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr; +// 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;) if (*p == 1) p += strlen(++p) + 1; @@ -2087,8 +2136,6 @@ void PackW32Pe::rebuildImports(upx_byte *& extrainfo) p += 3; // ordinal else p += 5; - - p++; } sdllnames = ALIGN_UP(sdllnames,2); @@ -2098,40 +2145,53 @@ void PackW32Pe::rebuildImports(upx_byte *& extrainfo) upx_byte *dllnames = Obuf + inamespos; 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 + 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; if (inamespos) { // now I rebuild the dll names + OCHECK(dllnames, dlen + 1); + strcpy(dllnames, dname); im->dllname = ptr_diff(dllnames,Obuf); - strcpy(dllnames,get_le32(p) + import); //;;;printf("\ndll: %s:",dllnames); - dllnames += strlen(dllnames) + 1; + dllnames += dlen + 1; } else - strcpy(Obuf + im->dllname,get_le32(p) + import); + { + OCHECK(Obuf + im->dllname, dlen + 1); + strcpy(Obuf + im->dllname, dname); + } 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 - for (p += 8; *p; newiat++) + for (p += 8; *p; ++newiat) if (*p == 1) { - unsigned len = strlen(++p) + 1; + const unsigned ilen = strlen(++p) + 1; if (inamespos) { if (ptr_diff(importednames,oimpdlls) & 1) - importednames--; - memcpy(importednames + 2,p,len); + importednames -= 1; + omemcpy(importednames + 2, p, ilen); //;;;printf(" %s",importednames+2); - *newiat = ptr_diff(importednames,Obuf); - importednames += 2 + len; + *newiat = ptr_diff(importednames, Obuf); + importednames += 2 + ilen; } 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) { @@ -2158,7 +2218,7 @@ void PackW32Pe::rebuildRelocs(upx_byte *& extrainfo) 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; } @@ -2166,13 +2226,14 @@ void PackW32Pe::rebuildRelocs(upx_byte *& extrainfo) const upx_byte big = extrainfo[4]; extrainfo += 5; - upx_byte *p = rdata; +// upx_byte *p = rdata; + OPTR_I(upx_byte, p, rdata); MemBuffer wrkmem; unsigned relocn = unoptimizeReloc32(&rdata,obuf,&wrkmem,1); unsigned r16 = 0; if (big & 6) // 16 bit relocations { - LE32 *q = (LE32*) rdata; + const LE32 *q = (LE32*) rdata; while (*q++) r16++; if ((big & 6) == 6) @@ -2197,7 +2258,7 @@ void PackW32Pe::rebuildRelocs(upx_byte *& extrainfo) for (unsigned ic = 0; ic < relocn; 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.finish (oxrelocs,soxrelocs); @@ -2210,7 +2271,7 @@ void PackW32Pe::rebuildRelocs(upx_byte *& extrainfo) // FIXME: try to remove the original relocation section somehow } else - memcpy (obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs); + omemcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs); delete [] oxrelocs; oxrelocs = NULL; wrkmem.dealloc(); @@ -2226,7 +2287,7 @@ void PackW32Pe::rebuildExports() Export xport((char*)(unsigned char*) ibuf - isection[2].vaddr); processExports(&xport); processExports(&xport,ODADDR(PEDIR_EXPORT)); - memcpy(obuf + ODADDR(PEDIR_EXPORT) - rvamin,oexport,soexport); + omemcpy(obuf + ODADDR(PEDIR_EXPORT) - rvamin,oexport,soexport); } void PackW32Pe::rebuildTls() @@ -2250,7 +2311,7 @@ void PackW32Pe::rebuildResources(upx_byte *& extrainfo) { unsigned origoffs = get_le32(r + res.offs() - 4); 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) { set_le16(obuf + origoffs - rvamin + 4,icondir_count); @@ -2260,7 +2321,7 @@ void PackW32Pe::rebuildResources(upx_byte *& extrainfo) upx_byte *p = res.build(); // write back when the original is zeroed 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; }