diff --git a/src/p_tmt.cpp b/src/p_tmt.cpp index 73e973dd..81e6def1 100644 --- a/src/p_tmt.cpp +++ b/src/p_tmt.cpp @@ -172,7 +172,18 @@ int PackTmt::readFileHeader() fi->seek(adam_offset,SEEK_SET); fi->readx(&ih,sizeof(ih)); - // FIXME: should add some checks for the values in 'ih' + // FIXME: should add more checks for the values in 'ih' + unsigned const imagesize = get_le32(&ih.imagesize); + unsigned const entry = get_le32(&ih.entry); + unsigned const relocsize = get_le32(&ih.relocsize); + if (!imagesize + || file_size <= imagesize + || file_size <= entry + || file_size <= relocsize) { + printWarn(getName(), "bad header; imagesize=%#x entry=%#x relocsize=%#x", + imagesize, entry, relocsize); + return 0; + } return UPX_F_TMT_ADAM; #undef H4 @@ -224,7 +235,9 @@ void PackTmt::pack(OutputFile *fo) { for (unsigned ic=4; ic<=rsize; ic+=4) set_le32(wrkmem+ic,get_le32(wrkmem+ic)-4); - relocsize = ptr_diff(optimizeReloc32(wrkmem+4,rsize/4,wrkmem,ibuf,1,&big_relocs), wrkmem); + relocsize = ptr_diff( + optimizeReloc32(wrkmem+4,rsize/4,wrkmem,ibuf,file_size,1,&big_relocs), + wrkmem); } wrkmem[relocsize++] = 0; diff --git a/src/p_wcle.cpp b/src/p_wcle.cpp index 365316c0..1d8958c1 100644 --- a/src/p_wcle.cpp +++ b/src/p_wcle.cpp @@ -399,7 +399,7 @@ void PackWcle::preprocessFixups() delete[] ifixups; ifixups = new upx_byte[1000]; } - fix = optimizeReloc32 (rl,rc,ifixups,iimage,1,&big_relocs); + fix = optimizeReloc32 (rl,rc,ifixups,iimage,file_size,1,&big_relocs); has_extra_code = srf != selector_fixups; // FIXME: this could be removed if has_extra_code = false // but then we'll need a flag diff --git a/src/packer.cpp b/src/packer.cpp index 7082d6a0..f3fef8d0 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -805,8 +805,12 @@ int Packer::patch_le32(void *b, int blen, const void *old, unsigned new_) { // relocation util **************************************************************************/ -upx_byte *Packer::optimizeReloc(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image, - int bswap, int *big, int bits) { +upx_byte *Packer::optimizeReloc( + upx_byte *in, unsigned relocnum, + upx_byte *out, + upx_byte *image, unsigned headway, + int bswap, int *big, int bits) +{ if (opt->exact) throwCantPackExact(); @@ -840,6 +844,11 @@ upx_byte *Packer::optimizeReloc(upx_byte *in, unsigned relocnum, upx_byte *out, fix += 4; } pc += oc; + if (headway <= pc) { + char msg[80]; snprintf(msg, sizeof(msg), + "bad reloc[%#x] = %#x", jc, oc); + throwCantPack(msg); + } if (bswap) { if (bits == 32) set_be32(image + pc, get_le32(image + pc)); @@ -853,14 +862,14 @@ upx_byte *Packer::optimizeReloc(upx_byte *in, unsigned relocnum, upx_byte *out, return fix; } -upx_byte *Packer::optimizeReloc32(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image, +upx_byte *Packer::optimizeReloc32(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image, unsigned headway, int bswap, int *big) { - return optimizeReloc(in, relocnum, out, image, bswap, big, 32); + return optimizeReloc(in, relocnum, out, image, headway, bswap, big, 32); } -upx_byte *Packer::optimizeReloc64(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image, +upx_byte *Packer::optimizeReloc64(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image, unsigned headway, int bswap, int *big) { - return optimizeReloc(in, relocnum, out, image, bswap, big, 64); + return optimizeReloc(in, relocnum, out, image, headway, bswap, big, 64); } unsigned Packer::unoptimizeReloc(upx_byte **in, upx_byte *image, MemBuffer *out, int bswap, diff --git a/src/packer.h b/src/packer.h index 0b9b2207..4c87684d 100644 --- a/src/packer.h +++ b/src/packer.h @@ -269,15 +269,22 @@ protected: void checkPatch(void *b, int blen, int boff, int size); // relocation util - static upx_byte *optimizeReloc(upx_byte *in, unsigned relocnum, upx_byte *out, upx_byte *image, - int bs, int *big, int bits); - static unsigned unoptimizeReloc(upx_byte **in, upx_byte *image, MemBuffer *out, int bs, - int bits); - static upx_byte *optimizeReloc32(upx_byte *in, unsigned relocnum, upx_byte *out, - upx_byte *image, int bs, int *big); + static upx_byte *optimizeReloc( + upx_byte *in, unsigned relocnum, + upx_byte *out, upx_byte *image, unsigned headway, + int bs, int *big, int bits); + static unsigned unoptimizeReloc(upx_byte **in, upx_byte *image, MemBuffer *out, int bs, int bits); + + static upx_byte *optimizeReloc32( + upx_byte *in, unsigned relocnum, + upx_byte *out, upx_byte *image, unsigned headway, + int bs, int *big); static unsigned unoptimizeReloc32(upx_byte **in, upx_byte *image, MemBuffer *out, int bs); - static upx_byte *optimizeReloc64(upx_byte *in, unsigned relocnum, upx_byte *out, - upx_byte *image, int bs, int *big); + + static upx_byte *optimizeReloc64( + upx_byte *in, unsigned relocnum, + upx_byte *out, upx_byte *image, unsigned headway, + int bs, int *big); static unsigned unoptimizeReloc64(upx_byte **in, upx_byte *image, MemBuffer *out, int bs); // target endianness abstraction diff --git a/src/pefile.cpp b/src/pefile.cpp index 1a8f974f..a977fb62 100644 --- a/src/pefile.cpp +++ b/src/pefile.cpp @@ -441,7 +441,7 @@ void PeFile32::processRelocs() // pass1 mb_orelocs.alloc(mem_size(4, rnum, 1024)); // 1024 - safety orelocs = (upx_byte *)mb_orelocs.getVoidPtr(); sorelocs = ptr_diff(optimizeReloc32((upx_byte*) fix[3], xcounts[3], - orelocs, ibuf + rvamin, 1, &big_relocs), + orelocs, ibuf + rvamin, file_size - rvamin, 1, &big_relocs), orelocs); delete [] fix[3]; @@ -547,7 +547,7 @@ void PeFile64::processRelocs() // pass1 mb_orelocs.alloc(mem_size(4, rnum, 1024)); // 1024 - safety orelocs = (upx_byte *)mb_orelocs.getVoidPtr(); sorelocs = ptr_diff(optimizeReloc64((upx_byte*) fix[10], xcounts[10], - orelocs, ibuf + rvamin, 1, &big_relocs), + orelocs, ibuf + rvamin, file_size - rvamin, 1, &big_relocs), orelocs); for (ic = 15; ic; ic--)