From 7b8e5d41801c96beb8fea3f911a3e71cec1d9771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20Moln=C3=A1r?= Date: Wed, 5 Mar 2014 23:59:53 +0100 Subject: [PATCH] pe: remove some dead code --- src/p_armpe.cpp | 513 +------------- src/p_w32pe.cpp | 673 ------------------ src/p_w64pep.cpp | 653 ----------------- src/packmast.cpp | 1 - src/pepfile.cpp | 1738 ---------------------------------------------- src/pepfile.h | 387 ----------- 6 files changed, 1 insertion(+), 3964 deletions(-) delete mode 100644 src/pepfile.cpp delete mode 100644 src/pepfile.h diff --git a/src/p_armpe.cpp b/src/p_armpe.cpp index bdf2061e..788ec16b 100644 --- a/src/p_armpe.cpp +++ b/src/p_armpe.cpp @@ -39,59 +39,6 @@ static const static const #include "stub/arm.v4t-wince.pe.h" -#define FILLVAL 0 - -/************************************************************************* -// -**************************************************************************/ - -#if defined(__BORLANDC__) -# undef strcpy -# define strcpy(a,b) strcpy((char *)(a),(const char *)(b)) -#endif - -#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 - -#if 0 -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!"); -} - -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) - - /************************************************************************* // **************************************************************************/ @@ -103,8 +50,7 @@ PackArmPe::PackArmPe(InputFile *f) : super(f) PackArmPe::~PackArmPe() -{ -} +{} const int *PackArmPe::getCompressionMethods(int method, int level) const @@ -306,463 +252,6 @@ void PackArmPe::setOhHeaderSize(const pe_section_t *osection) void PackArmPe::pack(OutputFile *fo) { super::pack0(fo, 1U << 9, 0x10000, true); -#if 0 - // FIXME: we need to think about better support for --exact - if (opt->exact) - throwCantPackExact(); - - const unsigned objs = ih.objects; - isection = new pe_section_t[objs]; - fi->seek(pe_offset+sizeof(ih),SEEK_SET); - fi->readx(isection,sizeof(pe_section_t)*objs); - - rvamin = isection[0].vaddr; - - infoHeader("[Processing %s, format %s, %d sections]", fn_basename(fi->getName()), getName(), objs); - - // check the PE header - // FIXME: add more checks - if (!opt->force && ( - (ih.cpu != 0x1c0 && ih.cpu != 0x1c2) - || (ih.opthdrsize != 0xe0) - || ((ih.flags & EXECUTABLE) == 0) - || (ih.subsystem != 9) - || (ih.entry == 0 /*&& !isdll*/) - || (ih.ddirsentries != 16) -// || IDSIZE(PEDIR_EXCEPTION) // is this used on arm? -// || IDSIZE(PEDIR_COPYRIGHT) - )) - throwCantPack("unexpected value in PE header (try --force)"); - - if (IDSIZE(PEDIR_SEC)) - IDSIZE(PEDIR_SEC) = IDADDR(PEDIR_SEC) = 0; - // throwCantPack("compressing certificate info is not supported"); - - if (IDSIZE(PEDIR_COMRT)) - throwCantPack(".NET files (win32/net) are not yet supported"); - - if (isdll) - opt->win32_pe.strip_relocs = false; - else if (opt->win32_pe.strip_relocs < 0) - opt->win32_pe.strip_relocs = (ih.imagebase >= 0x10000); - if (opt->win32_pe.strip_relocs) - { - if (ih.imagebase < 0x10000) - throwCantPack("--strip-relocs is not allowed when imagebase < 0x10000"); - else - ih.flags |= RELOCS_STRIPPED; - } - - if (memcmp(isection[0].name,"UPX",3) == 0) - throwAlreadyPackedByUPX(); - if (!opt->force && IDSIZE(15)) - throwCantPack("file is possibly packed/protected (try --force)"); - if (ih.entry && ih.entry < rvamin) - throwCantPack("run a virus scanner on this file!"); - if (!opt->force && ih.subsystem == 1) - throwCantPack("subsystem 'native' is not supported (try --force)"); - if (ih.filealign < 0x200) - throwCantPack("filealign < 0x200 is not yet supported"); - - handleStub(fi,fo,pe_offset); - const unsigned usize = ih.imagesize; - const unsigned xtrasize = UPX_MAX(ih.datasize, 65536u) + IDSIZE(PEDIR_IMPORT) + IDSIZE(PEDIR_BOUNDIM) + IDSIZE(PEDIR_IAT) + IDSIZE(PEDIR_DELAYIMP) + IDSIZE(PEDIR_RELOC); - ibuf.alloc(usize + xtrasize); - - // BOUND IMPORT support. FIXME: is this ok? - fi->seek(0,SEEK_SET); - fi->readx(ibuf,isection[0].rawdataptr); - - Interval holes(ibuf); - - unsigned ic,jc,overlaystart = 0; - ibuf.clear(0, usize); - for (ic = jc = 0; ic < objs; ic++) - { - if (isection[ic].rawdataptr && overlaystart < isection[ic].rawdataptr + isection[ic].size) - overlaystart = ALIGN_UP(isection[ic].rawdataptr + isection[ic].size,ih.filealign); - if (isection[ic].vsize == 0) - isection[ic].vsize = isection[ic].size; - if ((isection[ic].flags & PEFL_BSS) || isection[ic].rawdataptr == 0 - || (isection[ic].flags & PEFL_INFO)) - { - holes.add(isection[ic].vaddr,isection[ic].vsize); - continue; - } - if (isection[ic].vaddr + isection[ic].size > usize) - throwCantPack("section size problem"); - if (((isection[ic].flags & (PEFL_WRITE|PEFL_SHARED)) - == (PEFL_WRITE|PEFL_SHARED))) - if (!opt->force) - throwCantPack("writable shared sections not supported (try --force)"); - if (jc && isection[ic].rawdataptr - jc > ih.filealign) - throwCantPack("superfluous data between sections"); - fi->seek(isection[ic].rawdataptr,SEEK_SET); - jc = isection[ic].size; - if (jc > isection[ic].vsize) - jc = isection[ic].vsize; - if (isection[ic].vsize == 0) // hack for some tricky programs - may this break other progs? - jc = isection[ic].vsize = isection[ic].size; - if (isection[ic].vaddr + jc > ibuf.getSize()) - throwInternalError("buffer too small 1"); - fi->readx(ibuf + isection[ic].vaddr,jc); - jc += isection[ic].rawdataptr; - } - - // check for NeoLite - if (find(ibuf + ih.entry, 64+7, "NeoLite", 7) >= 0) - throwCantPack("file is already compressed with another packer"); - - unsigned overlay = file_size - stripDebug(overlaystart); - if (overlay >= (unsigned) file_size) - { -#if 0 - if (overlay < file_size + ih.filealign) - overlay = 0; - else if (!opt->force) - throwNotCompressible("overlay problem (try --force)"); -#endif - overlay = 0; - } - checkOverlay(overlay); - - Resource res; - Interval tlsiv(ibuf); - Export xport((char*)(unsigned char*)ibuf); - - const unsigned dllstrings = PeFile32::processImports(); - processTls(&tlsiv); // call before processRelocs!! - processResources(&res); - processExports(&xport); - processRelocs(); - - //OutputFile::dump("x1", ibuf, usize); - - // some checks for broken linkers - disable filter if necessary - bool allow_filter = true; - if (ih.codebase == ih.database - || ih.codebase + ih.codesize > ih.imagesize - || (isection[virta2objnum(ih.codebase,isection,objs)].flags & PEFL_CODE) == 0) - allow_filter = false; - - const unsigned oam1 = ih.objectalign - 1; - - // FIXME: disabled: the uncompressor would not allocate enough memory - //objs = tryremove(IDADDR(PEDIR_RELOC),objs); - - // FIXME: if the last object has a bss then this won't work - // newvsize = (isection[objs-1].vaddr + isection[objs-1].size + oam1) &~ oam1; - // temporary solution: - unsigned newvsize = (isection[objs-1].vaddr + isection[objs-1].vsize + oam1) &~ oam1; - - //fprintf(stderr,"newvsize=%x objs=%d\n",newvsize,objs); - if (newvsize + soimport + sorelocs > ibuf.getSize()) - throwInternalError("buffer too small 2"); - memcpy(ibuf+newvsize,oimport,soimport); - memcpy(ibuf+newvsize+soimport,orelocs,sorelocs); - - cimports = newvsize - rvamin; // rva of preprocessed imports - crelocs = cimports + soimport; // rva of preprocessed fixups - - ph.u_len = newvsize + soimport + sorelocs; - - // some extra data for uncompression support - unsigned s = 0; - upx_byte * const p1 = ibuf + ph.u_len; - memcpy(p1 + s,&ih,sizeof (ih)); - s += sizeof (ih); - memcpy(p1 + s,isection,ih.objects * sizeof(*isection)); - s += ih.objects * sizeof(*isection); - if (soimport) - { - set_le32(p1 + s,cimports); - set_le32(p1 + s + 4,dllstrings); - s += 8; - } - if (sorelocs) - { - set_le32(p1 + s,crelocs); - p1[s + 4] = (unsigned char) (big_relocs & 6); - s += 5; - } - if (soresources) - { - set_le16(p1 + s,icondir_count); - s += 2; - } - // end of extra data - set_le32(p1 + s,ptr_diff(p1,ibuf) - rvamin); - s += 4; - ph.u_len += s; - obuf.allocForCompression(ph.u_len); - - // prepare packheader - ph.u_len -= rvamin; - // prepare filter - Filter ft(ph.level); - ft.buf_len = ih.codesize; - ft.addvalue = ih.codebase - rvamin; - // compress - int filter_strategy = allow_filter ? 0 : -3; - - // disable filters for files with broken headers - if (ih.codebase + ih.codesize > ph.u_len) - { - ft.buf_len = 1; - filter_strategy = -3; - } - - // limit stack size needed for runtime decompression - upx_compress_config_t cconf; cconf.reset(); - cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack - compressWithFilters(&ft, 2048, &cconf, filter_strategy, - ih.codebase, rvamin, 0, NULL, 0); -// info: see buildLoader() - newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1; - /* - if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4) - tlsindex = 0; - */ - - const unsigned lsize = getLoaderSize(); - - int identsize = 0; - const unsigned codesize = getLoaderSection("IDENTSTR",&identsize); - assert(identsize > 0); - getLoaderSection("UPX1HEAD",(int*)&ic); - identsize += ic; - - pe_section_t osection[4]; - // section 0 : bss - // 1 : [ident + header] + packed_data + unpacker + tls - // 2 : not compressed data - // 3 : resource data -- wince 5 needs a new section for this - - // identsplit - number of ident + (upx header) bytes to put into the PE header - int identsplit = pe_offset + sizeof(osection) + sizeof(oh); - if ((identsplit & 0x1ff) == 0) - identsplit = 0; - else if (((identsplit + identsize) ^ identsplit) < 0x200) - identsplit = identsize; - else - identsplit = ALIGN_GAP(identsplit, 0x200); - ic = identsize - identsplit; - - const unsigned c_len = ((ph.c_len + ic) & 15) == 0 ? ph.c_len : ph.c_len + 16 - ((ph.c_len + ic) & 15); - obuf.clear(ph.c_len, c_len - ph.c_len); - - const unsigned s1size = ALIGN_UP(ic + c_len + codesize,4u) + sotls; - const unsigned s1addr = (newvsize - (ic + c_len) + oam1) &~ oam1; - - const unsigned ncsection = (s1addr + s1size + oam1) &~ oam1; - const unsigned upxsection = s1addr + ic + c_len; - - Reloc rel(1024); // new relocations are put here - static const char* symbols_to_relocate[] = { - "ONAM", "BIMP", "BREL", "FIBE", "FIBS", "ENTR", "DST0", "SRC0" - }; - for (unsigned s2r = 0; s2r < TABLESIZE(symbols_to_relocate); s2r++) - { - unsigned off = linker->getSymbolOffset(symbols_to_relocate[s2r]); - if (off != 0xdeaddead) - rel.add(off + upxsection, 3); - } - - // new PE header - memcpy(&oh,&ih,sizeof(oh)); - oh.filealign = 0x200; // identsplit depends on this - memset(osection,0,sizeof(osection)); - - oh.entry = upxsection; - oh.objects = 4; - oh.chksum = 0; - - // fill the data directory - ODADDR(PEDIR_DEBUG) = 0; - ODSIZE(PEDIR_DEBUG) = 0; - ODADDR(PEDIR_IAT) = 0; - ODSIZE(PEDIR_IAT) = 0; - ODADDR(PEDIR_BOUNDIM) = 0; - ODSIZE(PEDIR_BOUNDIM) = 0; - - // tls is put into section 1 - ic = s1addr + s1size - sotls; -// super::processTls(&rel,&tlsiv,ic); - ODADDR(PEDIR_TLS) = sotls ? ic : 0; - ODSIZE(PEDIR_TLS) = sotls ? 0x18 : 0; - ic += sotls; - - // these are put into section 2 - - ic = ncsection; - - // wince wants relocation data at the beginning of a section - PeFile::processRelocs(&rel); - ODADDR(PEDIR_RELOC) = soxrelocs ? ic : 0; - ODSIZE(PEDIR_RELOC) = soxrelocs; - ic += soxrelocs; - - processImports(ic, linker->getSymbolOffset("IATT") + upxsection); - ODADDR(PEDIR_IMPORT) = ic; - ODSIZE(PEDIR_IMPORT) = soimpdlls; - ic += soimpdlls; - - processExports(&xport,ic); - ODADDR(PEDIR_EXPORT) = soexport ? ic : 0; - ODSIZE(PEDIR_EXPORT) = soexport; - if (!isdll && opt->win32_pe.compress_exports) - { - ODADDR(PEDIR_EXPORT) = IDADDR(PEDIR_EXPORT); - ODSIZE(PEDIR_EXPORT) = IDSIZE(PEDIR_EXPORT); - } - ic += soexport; - - ic = (ic + oam1) &~ oam1; - const unsigned res_start = ic; - if (soresources) - processResources(&res,ic); - ODADDR(PEDIR_RESOURCE) = soresources ? ic : 0; - ODSIZE(PEDIR_RESOURCE) = soresources; - ic += soresources; - - const unsigned onam = ncsection + soxrelocs + ih.imagebase; - linker->defineSymbol("start_of_dll_names", onam); - linker->defineSymbol("start_of_imports", ih.imagebase + rvamin + cimports); - linker->defineSymbol("start_of_relocs", crelocs + rvamin + ih.imagebase); - linker->defineSymbol("filter_buffer_end", ih.imagebase + ih.codebase + ih.codesize); - linker->defineSymbol("filter_buffer_start", ih.imagebase + ih.codebase); - linker->defineSymbol("original_entry", ih.entry + ih.imagebase); - linker->defineSymbol("uncompressed_length", ph.u_len); - linker->defineSymbol("start_of_uncompressed", ih.imagebase + rvamin); - linker->defineSymbol("compressed_length", ph.c_len); - linker->defineSymbol("start_of_compressed", ih.imagebase + s1addr + identsize - identsplit); - defineDecompressorSymbols(); - relocateLoader(); - - MemBuffer loader(lsize); - memcpy(loader, getLoader(), lsize); - patchPackHeader(loader, lsize); - - // this is computed here, because soxrelocs changes some lines above - const unsigned ncsize = soxrelocs + soimpdlls + soexport; - const unsigned fam1 = oh.filealign - 1; - - // fill the sections - strcpy(osection[0].name,"UPX0"); - strcpy(osection[1].name,"UPX1"); - strcpy(osection[2].name, "UPX2"); - strcpy(osection[3].name, ".rsrc"); - - osection[0].vaddr = rvamin; - osection[1].vaddr = s1addr; - osection[2].vaddr = ncsection; - osection[3].vaddr = res_start; - - osection[0].size = 0; - osection[1].size = (s1size + fam1) &~ fam1; - osection[2].size = (ncsize + fam1) &~ fam1; - osection[3].size = (soresources + fam1) &~ fam1; - - osection[0].vsize = osection[1].vaddr - osection[0].vaddr; - //osection[1].vsize = (osection[1].size + oam1) &~ oam1; - //osection[2].vsize = (osection[2].size + oam1) &~ oam1; - osection[1].vsize = osection[1].size; - osection[2].vsize = osection[2].size; - osection[3].vsize = osection[3].size; - - osection[0].rawdataptr = 0; - osection[1].rawdataptr = (pe_offset + sizeof(oh) + sizeof(osection) + fam1) &~ fam1; - osection[2].rawdataptr = osection[1].rawdataptr + osection[1].size; - osection[3].rawdataptr = osection[2].rawdataptr + osection[2].size; - - osection[0].flags = (unsigned) (PEFL_BSS|PEFL_EXEC|PEFL_WRITE|PEFL_READ); - osection[1].flags = (unsigned) (PEFL_DATA|PEFL_EXEC|PEFL_WRITE|PEFL_READ); - osection[2].flags = (unsigned) (PEFL_DATA|PEFL_READ); - osection[3].flags = (unsigned) (PEFL_DATA|PEFL_READ); - - oh.imagesize = (osection[3].vaddr + osection[3].vsize + oam1) &~ oam1; - oh.bsssize = osection[0].vsize; - oh.datasize = osection[2].vsize + osection[3].vsize; - oh.database = osection[2].vaddr; - oh.codesize = osection[1].vsize; - oh.codebase = osection[1].vaddr; - oh.headersize = osection[1].rawdataptr; - if (rvamin < osection[0].rawdataptr) - throwCantPack("object alignment too small"); - - if (opt->win32_pe.strip_relocs && !isdll) - oh.flags |= RELOCS_STRIPPED; - - //for (ic = 0; ic < oh.filealign; ic += 4) - // set_le32(ibuf + ic,get_le32("UPX ")); - ibuf.clear(0, oh.filealign); - - info("Image size change: %u -> %u KiB", - ih.imagesize / 1024, oh.imagesize / 1024); - - infoHeader("[Writing compressed file]"); - - if (soresources == 0) - { - oh.objects = 3; - memset(&osection[3], 0, sizeof(osection[3])); - } - // write loader + compressed file - fo->write(&oh,sizeof(oh)); - fo->write(osection,sizeof(osection)); - // some alignment - if (identsplit == identsize) - { - unsigned n = osection[1].rawdataptr - fo->getBytesWritten() - identsize; - assert(n <= oh.filealign); - fo->write(ibuf, n); - } - fo->write(loader + codesize,identsize); - infoWriting("loader", fo->getBytesWritten()); - fo->write(obuf,c_len); - infoWriting("compressed data", c_len); - fo->write(loader,codesize); - if (opt->debug.dump_stub_loader) - OutputFile::dump(opt->debug.dump_stub_loader, loader, codesize); - if ((ic = fo->getBytesWritten() & 3) != 0) - fo->write(ibuf,4 - ic); - fo->write(otls,sotls); - if ((ic = fo->getBytesWritten() & fam1) != 0) - fo->write(ibuf,oh.filealign - ic); - fo->write(oxrelocs,soxrelocs); - fo->write(oimpdlls,soimpdlls); - fo->write(oexport,soexport); - - if ((ic = fo->getBytesWritten() & fam1) != 0) - fo->write(ibuf,oh.filealign - ic); - - fo->write(oresources,soresources); - if ((ic = fo->getBytesWritten() & fam1) != 0) - fo->write(ibuf,oh.filealign - ic); - -#if 0 - printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh)); - printf("%-13s: sections : %8ld bytes\n", getName(), (long) sizeof(osection)); - printf("%-13s: ident : %8ld bytes\n", getName(), (long) identsize); - printf("%-13s: compressed : %8ld bytes\n", getName(), (long) c_len); - printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) codesize); - printf("%-13s: tls : %8ld bytes\n", getName(), (long) sotls); - printf("%-13s: resources : %8ld bytes\n", getName(), (long) soresources); - printf("%-13s: imports : %8ld bytes\n", getName(), (long) soimpdlls); - printf("%-13s: exports : %8ld bytes\n", getName(), (long) soexport); - printf("%-13s: relocs : %8ld bytes\n", getName(), (long) soxrelocs); -#endif - - // verify - verifyOverlappingDecompression(); - - // copy the overlay - copyOverlay(fo, overlay, &obuf); - - // finally check the compression ratio - if (!checkFinalCompressionRatio(fo)) - throwNotCompressible(); -#endif } /* diff --git a/src/p_w32pe.cpp b/src/p_w32pe.cpp index beff26a3..d9104bf3 100644 --- a/src/p_w32pe.cpp +++ b/src/p_w32pe.cpp @@ -37,71 +37,6 @@ static const #include "stub/i386-win32.pe.h" -/************************************************************************* -// -**************************************************************************/ - -#if defined(__BORLANDC__) -# undef strcpy -# define strcpy(a,b) strcpy((char *)(a),(const char *)(b)) -#endif - -#if 0 -//static -unsigned my_strlen(const char *s) -{ - size_t l = strlen((const char*)s); assert((unsigned) l == l); return (unsigned) l; -} -static unsigned my_strlen(const unsigned char *s) -{ - size_t l = strlen((const char*)s); assert((unsigned) l == l); return (unsigned) l; -} -#undef strlen -#define strlen my_strlen -#endif - - -#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 - -#if 0 -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!"); -} -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) - - /************************************************************************* // **************************************************************************/ @@ -227,12 +162,6 @@ void PackW32Pe::buildLoader(const Filter *ft) if (use_clear_dirty_stack) addLoader("CLEARSTACK", NULL); addLoader("PEMAIN21", NULL); -#if 0 - addLoader(ih.entry ? "PEDOJUMP" : "PERETURN", - "IDENTSTR,UPX1HEAD", - NULL - ); -#endif //NEW: last loader sections split up to insert TLS callback handler - Stefan Widmann addLoader(ih.entry ? "PEDOJUMP" : "PERETURN", NULL); @@ -361,608 +290,6 @@ void PackW32Pe::setOhHeaderSize(const pe_section_t *) void PackW32Pe::pack(OutputFile *fo) { super::pack0(fo, 0x0c, 0x400000, false); -#if 0 - // FIXME: we need to think about better support for --exact - if (opt->exact) - throwCantPackExact(); - - const unsigned objs = ih.objects; - isection = new pe_section_t[objs]; - fi->seek(pe_offset+sizeof(ih),SEEK_SET); - fi->readx(isection,sizeof(pe_section_t)*objs); - - rvamin = isection[0].vaddr; - - infoHeader("[Processing %s, format %s, %d sections]", fn_basename(fi->getName()), getName(), objs); - - // check the PE header - // FIXME: add more checks - //NEW: subsystem check moved to switch ... case below, check of COFF magic, 32 bit machine flag check - Stefan Widmann - if (!opt->force && ( - (ih.cpu < 0x14c || ih.cpu > 0x150) - || (ih.opthdrsize != 0xe0) - || ((ih.flags & EXECUTABLE) == 0) - || ((ih.flags & BITS_32_MACHINE) == 0) //NEW: 32 bit machine flag must be set - Stefan Widmann - || (ih.coffmagic != 0x10B) //COFF magic is 0x10B in PE files, 0x20B in PE32+ files - Stefan Widmann - || (ih.entry == 0 && !isdll) - || (ih.ddirsentries != 16) - || IDSIZE(PEDIR_EXCEPTION) // is this used on i386? -// || IDSIZE(PEDIR_COPYRIGHT) - )) - throwCantPack("unexpected value in PE header (try --force)"); - - switch(ih.subsystem) //let's take a closer look at the subsystem - { - case 1: //NATIVE - { - if(!opt->force) - { - throwCantPack("win32/native applications are not yet supported"); - } - break; - } - case 2: //GUI - { - //fine, continue - break; - } - case 3: //CONSOLE - { - //fine, continue - break; - } - case 5: //OS2 - { - throwCantPack("win32/os2 files are not yet supported"); - break; - } - case 7: //POSIX - do x32/posix files exist? - { - throwCantPack("win32/posix files are not yet supported"); - break; - } - case 9: //WINCE x86 files - { - throwCantPack("PE32/wince files are not yet supported"); - break; - } - case 10: //EFI APPLICATION - { - throwCantPack("PE32/EFIapplication files are not yet supported"); - break; - } - case 11: //EFI BOOT SERVICE DRIVER - { - throwCantPack("PE32/EFIbootservicedriver files are not yet supported"); - break; - } - case 12: //EFI RUNTIME DRIVER - { - throwCantPack("PE32/EFIruntimedriver files are not yet supported"); - break; - } - case 13: //EFI ROM - { - throwCantPack("PE32/EFIROM files are not yet supported"); - break; - } - case 14: //XBOX - will we ever see a XBOX file? - { - throwCantPack("PE32/xbox files are not yet supported"); - break; - } - case 16: //WINDOWS BOOT APPLICATION - { - throwCantPack("PE32/windowsbootapplication files are not yet supported"); - break; - } - default: //UNKNOWN SUBSYSTEM - { - throwCantPack("PE32/? unknown subsystem"); - break; - } - } - - //remove certificate directory entry - if (IDSIZE(PEDIR_SEC)) - IDSIZE(PEDIR_SEC) = IDADDR(PEDIR_SEC) = 0; - - //check CLR Runtime Header directory entry - if (IDSIZE(PEDIR_COMRT)) - throwCantPack(".NET files (win32/.net) are not yet supported"); - - //NEW: disable reloc stripping if ASLR is enabled - if(ih.dllflags & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE) - opt->win32_pe.strip_relocs = false; - else if (isdll) //do never strip relocations from DLLs - opt->win32_pe.strip_relocs = false; - else if (opt->win32_pe.strip_relocs < 0) - opt->win32_pe.strip_relocs = (ih.imagebase >= 0x400000); - if (opt->win32_pe.strip_relocs) - { - if (ih.imagebase < 0x400000) - throwCantPack("--strip-relocs is not allowed when imagebase < 0x400000"); - else - ih.flags |= RELOCS_STRIPPED; - } - - if (memcmp(isection[0].name,"UPX",3) == 0) - throwAlreadyPackedByUPX(); - if (!opt->force && IDSIZE(15)) - throwCantPack("file is possibly packed/protected (try --force)"); - if (ih.entry && ih.entry < rvamin) - throwCantPack("run a virus scanner on this file!"); -#if 0 //subsystem check moved to switch ... case above - Stefan Widmann - if (!opt->force && ih.subsystem == 1) - throwCantPack("subsystem 'native' is not supported (try --force)"); -#endif - if (ih.filealign < 0x200) - throwCantPack("filealign < 0x200 is not yet supported"); - - handleStub(fi,fo,pe_offset); - const unsigned usize = ih.imagesize; - const unsigned xtrasize = UPX_MAX(ih.datasize, 65536u) + IDSIZE(PEDIR_IMPORT) + IDSIZE(PEDIR_BOUNDIM) + IDSIZE(PEDIR_IAT) + IDSIZE(PEDIR_DELAYIMP) + IDSIZE(PEDIR_RELOC); - ibuf.alloc(usize + xtrasize); - - // BOUND IMPORT support. FIXME: is this ok? - fi->seek(0,SEEK_SET); - fi->readx(ibuf,isection[0].rawdataptr); - - Interval holes(ibuf); - - unsigned ic,jc,overlaystart = 0; - ibuf.clear(0, usize); - for (ic = jc = 0; ic < objs; ic++) - { - if (isection[ic].rawdataptr && overlaystart < isection[ic].rawdataptr + isection[ic].size) - overlaystart = ALIGN_UP(isection[ic].rawdataptr + isection[ic].size,ih.filealign); - if (isection[ic].vsize == 0) - isection[ic].vsize = isection[ic].size; - if ((isection[ic].flags & PEFL_BSS) || isection[ic].rawdataptr == 0 - || (isection[ic].flags & PEFL_INFO)) - { - holes.add(isection[ic].vaddr,isection[ic].vsize); - continue; - } - if (isection[ic].vaddr + isection[ic].size > usize) - throwCantPack("section size problem"); - if (!isrtm && ((isection[ic].flags & (PEFL_WRITE|PEFL_SHARED)) - == (PEFL_WRITE|PEFL_SHARED))) - if (!opt->force) - throwCantPack("writable shared sections not supported (try --force)"); - if (jc && isection[ic].rawdataptr - jc > ih.filealign) - throwCantPack("superfluous data between sections"); - fi->seek(isection[ic].rawdataptr,SEEK_SET); - jc = isection[ic].size; - if (jc > isection[ic].vsize) - jc = isection[ic].vsize; - if (isection[ic].vsize == 0) // hack for some tricky programs - may this break other progs? - jc = isection[ic].vsize = isection[ic].size; - if (isection[ic].vaddr + jc > ibuf.getSize()) - throwInternalError("buffer too small 1"); - fi->readx(ibuf + isection[ic].vaddr,jc); - jc += isection[ic].rawdataptr; - } - - // check for NeoLite - if (find(ibuf + ih.entry, 64+7, "NeoLite", 7) >= 0) - throwCantPack("file is already compressed with another packer"); - - unsigned overlay = file_size - stripDebug(overlaystart); - if (overlay >= (unsigned) file_size) - { -#if 0 - if (overlay < file_size + ih.filealign) - overlay = 0; - else if (!opt->force) - throwNotCompressible("overlay problem (try --force)"); -#endif - overlay = 0; - } - checkOverlay(overlay); - - Resource res; - Interval tlsiv(ibuf); - Interval loadconfiv(ibuf); - Export xport((char*)(unsigned char*)ibuf); - - const unsigned dllstrings = processImports(); - processTls(&tlsiv); // call before processRelocs!! - processLoadConf(&loadconfiv); - processResources(&res); - processExports(&xport); - processRelocs(); - - //OutputFile::dump("x1", ibuf, usize); - - // some checks for broken linkers - disable filter if necessary - bool allow_filter = true; - if (ih.codebase == ih.database - || ih.codebase + ih.codesize > ih.imagesize - || (isection[virta2objnum(ih.codebase,isection,objs)].flags & PEFL_CODE) == 0) - allow_filter = false; - - const unsigned oam1 = ih.objectalign - 1; - - // FIXME: disabled: the uncompressor would not allocate enough memory - //objs = tryremove(IDADDR(PEDIR_RELOC),objs); - - // FIXME: if the last object has a bss then this won't work - // newvsize = (isection[objs-1].vaddr + isection[objs-1].size + oam1) &~ oam1; - // temporary solution: - unsigned newvsize = (isection[objs-1].vaddr + isection[objs-1].vsize + oam1) &~ oam1; - - //fprintf(stderr,"newvsize=%x objs=%d\n",newvsize,objs); - if (newvsize + soimport + sorelocs > ibuf.getSize()) - throwInternalError("buffer too small 2"); - memcpy(ibuf+newvsize,oimport,soimport); - memcpy(ibuf+newvsize+soimport,orelocs,sorelocs); - - cimports = newvsize - rvamin; // rva of preprocessed imports - crelocs = cimports + soimport; // rva of preprocessed fixups - - ph.u_len = newvsize + soimport + sorelocs; - - // some extra data for uncompression support - unsigned s = 0; - upx_byte * const p1 = ibuf + ph.u_len; - memcpy(p1 + s,&ih,sizeof (ih)); - s += sizeof (ih); - memcpy(p1 + s,isection,ih.objects * sizeof(*isection)); - s += ih.objects * sizeof(*isection); - if (soimport) - { - set_le32(p1 + s,cimports); - set_le32(p1 + s + 4,dllstrings); - s += 8; - } - if (sorelocs) - { - set_le32(p1 + s,crelocs); - p1[s + 4] = (unsigned char) (big_relocs & 6); - s += 5; - } - if (soresources) - { - set_le16(p1 + s,icondir_count); - s += 2; - } - // end of extra data - set_le32(p1 + s,ptr_diff(p1,ibuf) - rvamin); - s += 4; - ph.u_len += s; - obuf.allocForCompression(ph.u_len); - - // prepare packheader - ph.u_len -= rvamin; - // prepare filter - Filter ft(ph.level); - ft.buf_len = ih.codesize; - ft.addvalue = ih.codebase - rvamin; - // compress - int filter_strategy = allow_filter ? 0 : -3; - - // disable filters for files with broken headers - if (ih.codebase + ih.codesize > ph.u_len) - { - ft.buf_len = 1; - filter_strategy = -3; - } - - compressWithFilters(&ft, 2048, NULL_cconf, filter_strategy, - ih.codebase, rvamin, 0, NULL, 0); -// info: see buildLoader() - newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1; - if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4) - tlsindex = 0; - - int identsize = 0; - const unsigned codesize = getLoaderSection("IDENTSTR",&identsize); - assert(identsize > 0); - getLoaderSection("UPX1HEAD",(int*)&ic); - identsize += ic; - - pe_section_t osection[3]; - // section 0 : bss - // 1 : [ident + header] + packed_data + unpacker + tls + loadconf - // 2 : not compressed data - - // section 2 should start with the resource data, because lots of lame - // windoze codes assume that resources starts on the beginning of a section - - // note: there should be no data in section 2 which needs fixup - - // identsplit - number of ident + (upx header) bytes to put into the PE header - int identsplit = pe_offset + sizeof(osection) + sizeof(oh); - if ((identsplit & 0x1ff) == 0) - identsplit = 0; - else if (((identsplit + identsize) ^ identsplit) < 0x200) - identsplit = identsize; - else - identsplit = ALIGN_GAP(identsplit, 0x200); - ic = identsize - identsplit; - - const unsigned c_len = ((ph.c_len + ic) & 15) == 0 ? ph.c_len : ph.c_len + 16 - ((ph.c_len + ic) & 15); - obuf.clear(ph.c_len, c_len - ph.c_len); - - const unsigned s1size = ALIGN_UP(ic + c_len + codesize,4u) + sotls + soloadconf; - const unsigned s1addr = (newvsize - (ic + c_len) + oam1) &~ oam1; - - const unsigned ncsection = (s1addr + s1size + oam1) &~ oam1; - const unsigned upxsection = s1addr + ic + c_len; - const unsigned myimport = ncsection + soresources - rvamin; - - // patch loader - linker->defineSymbol("original_entry", ih.entry); - if (use_dep_hack) - { - // This works around a "protection" introduced in MSVCRT80, which - // works like this: - // When the compiler detects that it would link in some code from its - // C runtime library which references some data in a read only - // section then it compiles in a runtime check whether that data is - // still in a read only section by looking at the pe header of the - // file. If this check fails the runtime does "interesting" things - // like not running the floating point initialization code - the result - // is a R6002 runtime error. - // These supposed to be read only addresses are covered by the sections - // UPX0 & UPX1 in the compressed files, so we have to patch the PE header - // in the memory. And the page on which the PE header is stored is read - // only so we must make it rw, fix the flags (i.e. clear - // PEFL_WRITE of osection[x].flags), and make it ro again. - - // rva of the most significant byte of member "flags" in section "UPX0" - const unsigned swri = pe_offset + sizeof(oh) + sizeof(pe_section_t) - 1; - // make sure we only touch the minimum number of pages - const unsigned addr = 0u - rvamin + swri; - linker->defineSymbol("swri", addr & 0xfff); // page offset - // check whether osection[0].flags and osection[1].flags - // are on the same page - linker->defineSymbol("vp_size", ((addr & 0xfff) + 0x28 >= 0x1000) ? - 0x2000 : 0x1000); // 2 pages or 1 page - linker->defineSymbol("vp_base", addr &~ 0xfff); // page mask - linker->defineSymbol("VirtualProtect", myimport + get_le32(oimpdlls + 16) + 8); - } - linker->defineSymbol("reloc_delt", 0u - (unsigned) ih.imagebase - rvamin); - linker->defineSymbol("start_of_relocs", crelocs); - linker->defineSymbol("ExitProcess", myimport + get_le32(oimpdlls + 16) + 20); - linker->defineSymbol("GetProcAddress", myimport + get_le32(oimpdlls + 16) + 4); - linker->defineSymbol("kernel32_ordinals", myimport); - linker->defineSymbol("LoadLibraryA", myimport + get_le32(oimpdlls + 16)); - linker->defineSymbol("start_of_imports", myimport); - linker->defineSymbol("compressed_imports", cimports); -#if 0 - linker->defineSymbol("VirtualAlloc", myimport + get_le32(oimpdlls + 16) + 12); - linker->defineSymbol("VirtualFree", myimport + get_le32(oimpdlls + 16) + 16); -#endif - - defineDecompressorSymbols(); - defineFilterSymbols(&ft); - linker->defineSymbol("filter_buffer_start", ih.codebase - rvamin); - - // in case of overlapping decompression, this hack is needed, - // because windoze zeroes the word pointed by tlsindex before - // it starts programs - linker->defineSymbol("tls_value", (tlsindex + 4 > s1addr) ? - get_le32(obuf + tlsindex - s1addr - ic) : 0); - linker->defineSymbol("tls_address", tlsindex - rvamin); - - linker->defineSymbol("icon_delta", icondir_count - 1); - linker->defineSymbol("icon_offset", ncsection + icondir_offset - rvamin); - - const unsigned esi0 = s1addr + ic; - linker->defineSymbol("start_of_uncompressed", 0u - esi0 + rvamin); - linker->defineSymbol("start_of_compressed", esi0 + ih.imagebase); - - //NEW: TLS callback support - Stefan Widmann - ic = s1addr + s1size - sotls - soloadconf; //moved here, we need the address of the new TLS! - if(use_tls_callbacks) - { - //esi is ih.imagebase + rvamin - linker->defineSymbol("tls_callbacks_ptr", tlscb_ptr); - //linker->defineSymbol("tls_callbacks_off", ic + sotls - 8 - rvamin); - linker->defineSymbol("tls_module_base", 0u - rvamin); - } - - linker->defineSymbol(isdll ? "PEISDLL1" : "PEMAIN01", upxsection); - //linker->dumpSymbols(); - relocateLoader(); - - const unsigned lsize = getLoaderSize(); - MemBuffer loader(lsize); - memcpy(loader,getLoader(),lsize); - patchPackHeader(loader, lsize); - - Reloc rel(1024); // new relocations are put here - rel.add(linker->getSymbolOffset("PEMAIN01") + 2, 3); - - // new PE header - memcpy(&oh,&ih,sizeof(oh)); - oh.filealign = 0x200; // identsplit depends on this - memset(osection,0,sizeof(osection)); - - oh.entry = upxsection; - oh.objects = 3; - oh.chksum = 0; - - // fill the data directory - ODADDR(PEDIR_DEBUG) = 0; - ODSIZE(PEDIR_DEBUG) = 0; - ODADDR(PEDIR_IAT) = 0; - ODSIZE(PEDIR_IAT) = 0; - ODADDR(PEDIR_BOUNDIM) = 0; - ODSIZE(PEDIR_BOUNDIM) = 0; - - // tls & loadconf are put into section 1 - - //ic = s1addr + s1size - sotls - soloadconf; //ATTENTION: moved upwards to TLS callback handling - Stefan Widmann - //get address of TLS callback handler - if (use_tls_callbacks) - { - tls_handler_offset = linker->getSymbolOffset("PETLSC2"); - //add relocation entry for TLS callback handler - rel.add(tls_handler_offset + 4, 3); - } - - processTls(&rel,&tlsiv,ic); - ODADDR(PEDIR_TLS) = sotls ? ic : 0; - ODSIZE(PEDIR_TLS) = sotls ? 0x18 : 0; - ic += sotls; - - processLoadConf(&rel, &loadconfiv, ic); - ODADDR(PEDIR_LOADCONF) = soloadconf ? ic : 0; - ODSIZE(PEDIR_LOADCONF) = soloadconf; - ic += soloadconf; - - // these are put into section 2 - - ic = ncsection; - if (soresources) - processResources(&res,ic); - ODADDR(PEDIR_RESOURCE) = soresources ? ic : 0; - ODSIZE(PEDIR_RESOURCE) = soresources; - ic += soresources; - - PeFile::processImports(ic, 0); - ODADDR(PEDIR_IMPORT) = ic; - ODSIZE(PEDIR_IMPORT) = soimpdlls; - ic += soimpdlls; - - processExports(&xport,ic); - ODADDR(PEDIR_EXPORT) = soexport ? ic : 0; - ODSIZE(PEDIR_EXPORT) = soexport; - if (!isdll && opt->win32_pe.compress_exports) - { - ODADDR(PEDIR_EXPORT) = IDADDR(PEDIR_EXPORT); - ODSIZE(PEDIR_EXPORT) = IDSIZE(PEDIR_EXPORT); - } - ic += soexport; - - PeFile::processRelocs(&rel); - ODADDR(PEDIR_RELOC) = soxrelocs ? ic : 0; - ODSIZE(PEDIR_RELOC) = soxrelocs; - ic += soxrelocs; - - // this is computed here, because soxrelocs changes some lines above - const unsigned ncsize = soresources + soimpdlls + soexport + soxrelocs; - ic = oh.filealign - 1; - - // this one is tricky: it seems windoze touches 4 bytes after - // the end of the relocation data - so we have to increase - // the virtual size of this section - const unsigned ncsize_virt_increase = (ncsize & oam1) == 0 ? 8 : 0; - - // fill the sections - strcpy(osection[0].name,"UPX0"); - strcpy(osection[1].name,"UPX1"); - // after some windoze debugging I found that the name of the sections - // DOES matter :( .rsrc is used by oleaut32.dll (TYPELIBS) - // and because of this lame dll, the resource stuff must be the - // first in the 3rd section - the author of this dll seems to be - // too idiot to use the data directories... M$ suxx 4 ever! - // ... even worse: exploder.exe in NiceTry also depends on this to - // locate version info - - strcpy(osection[2].name,soresources ? ".rsrc" : "UPX2"); - - osection[0].vaddr = rvamin; - osection[1].vaddr = s1addr; - osection[2].vaddr = ncsection; - - osection[0].size = 0; - osection[1].size = (s1size + ic) &~ ic; - osection[2].size = (ncsize + ic) &~ ic; - - osection[0].vsize = osection[1].vaddr - osection[0].vaddr; - osection[1].vsize = (osection[1].size + oam1) &~ oam1; - osection[2].vsize = (osection[2].size + ncsize_virt_increase + oam1) &~ oam1; - - osection[0].rawdataptr = (pe_offset + sizeof(oh) + sizeof(osection) + ic) &~ ic; - osection[1].rawdataptr = osection[0].rawdataptr; - osection[2].rawdataptr = osection[1].rawdataptr + osection[1].size; - - osection[0].flags = (unsigned) (PEFL_BSS|PEFL_EXEC|PEFL_WRITE|PEFL_READ); - osection[1].flags = (unsigned) (PEFL_DATA|PEFL_EXEC|PEFL_WRITE|PEFL_READ); - osection[2].flags = (unsigned) (PEFL_DATA|PEFL_WRITE|PEFL_READ); - - oh.imagesize = osection[2].vaddr + osection[2].vsize; - oh.bsssize = osection[0].vsize; - oh.datasize = osection[2].vsize; - oh.database = osection[2].vaddr; - oh.codesize = osection[1].vsize; - oh.codebase = osection[1].vaddr; - // oh.headersize = osection[0].rawdataptr; - oh.headersize = rvamin; - if (rvamin < osection[0].rawdataptr) - throwCantPack("object alignment too small"); - - if (opt->win32_pe.strip_relocs && !isdll) - oh.flags |= RELOCS_STRIPPED; - - //for (ic = 0; ic < oh.filealign; ic += 4) - // set_le32(ibuf + ic,get_le32("UPX ")); - ibuf.clear(0, oh.filealign); - - info("Image size change: %u -> %u KiB", - ih.imagesize / 1024, oh.imagesize / 1024); - - infoHeader("[Writing compressed file]"); - - // write loader + compressed file - fo->write(&oh,sizeof(oh)); - fo->write(osection,sizeof(osection)); - // some alignment - if (identsplit == identsize) - { - unsigned n = osection[0].rawdataptr - fo->getBytesWritten() - identsize; - assert(n <= oh.filealign); - fo->write(ibuf, n); - } - fo->write(loader + codesize,identsize); - infoWriting("loader", fo->getBytesWritten()); - fo->write(obuf,c_len); - infoWriting("compressed data", c_len); - fo->write(loader,codesize); - if (opt->debug.dump_stub_loader) - OutputFile::dump(opt->debug.dump_stub_loader, loader, codesize); - if ((ic = fo->getBytesWritten() & 3) != 0) - fo->write(ibuf,4 - ic); - fo->write(otls,sotls); - fo->write(oloadconf, soloadconf); - if ((ic = fo->getBytesWritten() & (oh.filealign-1)) != 0) - fo->write(ibuf,oh.filealign - ic); - fo->write(oresources,soresources); - fo->write(oimpdlls,soimpdlls); - fo->write(oexport,soexport); - fo->write(oxrelocs,soxrelocs); - - if ((ic = fo->getBytesWritten() & (oh.filealign-1)) != 0) - fo->write(ibuf,oh.filealign - ic); - -#if 0 - printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh)); - printf("%-13s: sections : %8ld bytes\n", getName(), (long) sizeof(osection)); - printf("%-13s: ident : %8ld bytes\n", getName(), (long) identsize); - printf("%-13s: compressed : %8ld bytes\n", getName(), (long) c_len); - printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) codesize); - printf("%-13s: tls : %8ld bytes\n", getName(), (long) sotls); - printf("%-13s: resources : %8ld bytes\n", getName(), (long) soresources); - printf("%-13s: imports : %8ld bytes\n", getName(), (long) soimpdlls); - printf("%-13s: exports : %8ld bytes\n", getName(), (long) soexport); - printf("%-13s: relocs : %8ld bytes\n", getName(), (long) soxrelocs); - printf("%-13s: loadconf : %8ld bytes\n", getName(), (long) soloadconf); -#endif - - // verify - verifyOverlappingDecompression(); - - // copy the overlay - copyOverlay(fo, overlay, &obuf); - - // finally check the compression ratio - if (!checkFinalCompressionRatio(fo)) - throwNotCompressible(); -#endif } /* diff --git a/src/p_w64pep.cpp b/src/p_w64pep.cpp index f33cda2c..c7e67622 100644 --- a/src/p_w64pep.cpp +++ b/src/p_w64pep.cpp @@ -42,71 +42,6 @@ static const #include "stub/amd64-win64.pep.h" -/************************************************************************* -// -**************************************************************************/ - -#if defined(__BORLANDC__) -# undef strcpy -# define strcpy(a,b) strcpy((char *)(a),(const char *)(b)) -#endif - -#if 0 //NEW: Stefan Widmann -//static -unsigned my_strlen(const char *s) -{ - size_t l = strlen((const char*)s); assert((unsigned) l == l); return (unsigned) l; -} -static unsigned my_strlen(const unsigned char *s) -{ - size_t l = strlen((const char*)s); assert((unsigned) l == l); return (unsigned) l; -} -#undef strlen -#define strlen my_strlen -#endif - - -#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 - -#if 0 -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!"); -} -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) - - /************************************************************************* // **************************************************************************/ @@ -341,594 +276,6 @@ void PackW64Pep::pack(OutputFile *fo) // FIXME: Relocation stripping disabled for now - Stefan Widmann opt->win32_pe.strip_relocs = false; super::pack0(fo, 0x0c, 0x0000000140000000ULL); -#if 0 - // FIXME: we need to think about better support for --exact - if (opt->exact) - throwCantPackExact(); - - const unsigned objs = ih.objects; - isection = new pe_section_t[objs]; - fi->seek(pe_offset+sizeof(ih),SEEK_SET); - fi->readx(isection,sizeof(pe_section_t)*objs); - - rvamin = isection[0].vaddr; - - infoHeader("[Processing %s, format %s, %d sections]", fn_basename(fi->getName()), getName(), objs); - - // check the PE header - // FIXME: add more checks - // subsystem check moved to switch ... case below - if (!opt->force && ( - (ih.cpu != 0x8664) //CPU magic of AMD64 is 0x8664 - || (ih.opthdrsize != 0xF0) //optional header size is 0xF0 in PE32+ files - Stefan Widmann - || (ih.coffmagic != 0x20B) //COFF magic is 0x20B in PE+ files, 0x10B in "normal" 32 bit PE files - Stefan Widmann - || ((ih.flags & EXECUTABLE) == 0) - || ((ih.flags & BITS_32_MACHINE) == 1) //NEW: 32 bit machine flag may not be set - Stefan Widmann - || (ih.entry == 0 && !isdll) - || (ih.ddirsentries != 16) - )) - throwCantPack("unexpected value in PE header (try --force)"); - - switch(ih.subsystem) //let's take a closer look at the subsystem - { - case 1: //NATIVE - { - throwCantPack("win64/native applications are not yet supported"); - break; - } - case 2: //GUI - { - //fine, continue - break; - } - case 3: //CONSOLE - { - //fine, continue - break; - } - case 5: //OS2 - are there any x64/os2 files? - { - throwCantPack("win64/os2 files are not yet supported"); - break; - } - case 7: //POSIX - do win64/posix files exist? - { - throwCantPack("win64/posix files are not yet supported"); - break; - } - case 9: //WINCE - same question: do they exist? - { - throwCantPack("PE32+/wince files are not yet supported"); - break; - } - case 10: //EFI APPLICATION - { - throwCantPack("PE32+/EFIapplication files are not yet supported"); - break; - } - case 11: //EFI BOOT SERVICE DRIVER - { - throwCantPack("PE32+/EFIbootservicedriver files are not yet supported"); - break; - } - case 12: //EFI RUNTIME DRIVER - { - throwCantPack("PE32+/EFIruntimedriver files are not yet supported"); - break; - } - case 13: //EFI ROM - { - throwCantPack("PE32+/EFIROM files are not yet supported"); - break; - } - case 14: //XBOX - will there ever be PE32+ xbox files? - { - throwCantPack("PE32+/xbox files are not yet supported"); - break; - } - case 16: //WINDOWS BOOT APPLICATION - { - throwCantPack("win64/windowsbootapplication files are not yet supported"); - break; - } - default: //UNKNOWN SUBSYSTEM - { - throwCantPack("PE32+/? unknown subsystem"); - break; - } - } - - //remove certificate pointers from directory table - if (IDSIZE(PEDIR_SEC)) - IDSIZE(PEDIR_SEC) = IDADDR(PEDIR_SEC) = 0; - - //check if we have a CLR Runtime Header pointer - if (IDSIZE(PEDIR_COMRT)) - throwCantPack(".NET files (win64/.net) are not yet supported"); - - //FIXME: Relocation stripping disabled yet - Stefan Widmann - opt->win32_pe.strip_relocs = false; -#if 0 //removed - Stefan Widmann - if (isdll) - opt->win32_pe.strip_relocs = false; - else if (opt->win32_pe.strip_relocs < 0) - opt->win32_pe.strip_relocs = (ih.imagebase >= 0x0000000140000000ULL); - if (opt->win32_pe.strip_relocs) - { - if (ih.imagebase < 0x0000000140000000ULL) - throwCantPack("--strip-relocs is not allowed when imagebase < 0x0000000140000000"); - else - ih.flags |= RELOCS_STRIPPED; - } -#endif - - //check if first section's name is "UPX" - if (memcmp(isection[0].name,"UPX",3) == 0) - throwAlreadyPackedByUPX(); - if (!opt->force && IDSIZE(15)) - throwCantPack("file is possibly packed/protected (try --force)"); - if (ih.entry && ih.entry < rvamin) - throwCantPack("run a virus scanner on this file!"); -#if 0 //subsystem check moved to switch ... case above - Stefan Widmann - if (!opt->force && ih.subsystem == 1) - throwCantPack("subsystem 'native' is not supported (try --force)"); -#endif - if (ih.filealign < 0x200) - throwCantPack("filealign < 0x200 is not yet supported"); - - handleStub(fi,fo,pe_offset); - const unsigned usize = ih.imagesize; - const unsigned xtrasize = UPX_MAX(ih.datasize, 65536u) + IDSIZE(PEDIR_IMPORT) + IDSIZE(PEDIR_BOUNDIM) + IDSIZE(PEDIR_IAT) + IDSIZE(PEDIR_DELAYIMP) + IDSIZE(PEDIR_RELOC); - ibuf.alloc(usize + xtrasize); - - // BOUND IMPORT support. FIXME: is this ok? - fi->seek(0,SEEK_SET); - fi->readx(ibuf,isection[0].rawdataptr); - - Interval holes(ibuf); - - unsigned ic,jc,overlaystart = 0; - ibuf.clear(0, usize); - for (ic = jc = 0; ic < objs; ic++) - { - if (isection[ic].rawdataptr && overlaystart < isection[ic].rawdataptr + isection[ic].size) - overlaystart = ALIGN_UP(isection[ic].rawdataptr + isection[ic].size,ih.filealign); - if (isection[ic].vsize == 0) - isection[ic].vsize = isection[ic].size; - if ((isection[ic].flags & PEFL_BSS) || isection[ic].rawdataptr == 0 - || (isection[ic].flags & PEFL_INFO)) - { - holes.add(isection[ic].vaddr,isection[ic].vsize); - continue; - } - if (isection[ic].vaddr + isection[ic].size > usize) - throwCantPack("section size problem"); - if (!isrtm && ((isection[ic].flags & (PEFL_WRITE|PEFL_SHARED)) - == (PEFL_WRITE|PEFL_SHARED))) - if (!opt->force) - throwCantPack("writable shared sections not supported (try --force)"); - if (jc && isection[ic].rawdataptr - jc > ih.filealign) - throwCantPack("superfluous data between sections"); - fi->seek(isection[ic].rawdataptr,SEEK_SET); - jc = isection[ic].size; - if (jc > isection[ic].vsize) - jc = isection[ic].vsize; - if (isection[ic].vsize == 0) // hack for some tricky programs - may this break other progs? - jc = isection[ic].vsize = isection[ic].size; - if (isection[ic].vaddr + jc > ibuf.getSize()) - throwInternalError("buffer too small 1"); - fi->readx(ibuf + isection[ic].vaddr,jc); - jc += isection[ic].rawdataptr; - } - - unsigned overlay = file_size - stripDebug(overlaystart); - if (overlay >= (unsigned) file_size) - { -#if 0 - if (overlay < file_size + ih.filealign) - overlay = 0; - else if (!opt->force) - throwNotCompressible("overlay problem (try --force)"); -#endif - overlay = 0; - } - checkOverlay(overlay); - - Resource res; - Interval tlsiv(ibuf); - Interval loadconfiv(ibuf); - Export xport((char*)(unsigned char*)ibuf); - - const unsigned dllstrings = processImports(); - processTls(&tlsiv); // call before processRelocs!! - processLoadConf(&loadconfiv); - processResources(&res); - processExports(&xport); - processRelocs(); - - //OutputFile::dump("x1", ibuf, usize); - - // some checks for broken linkers - disable filter if necessary - bool allow_filter = true; - if (ih.codebase + ih.codesize > ih.imagesize - || (isection[virta2objnum(ih.codebase,isection,objs)].flags & PEFL_CODE) == 0) - allow_filter = false; - - const unsigned oam1 = ih.objectalign - 1; - - // FIXME: disabled: the uncompressor would not allocate enough memory - //objs = tryremove(IDADDR(PEDIR_RELOC),objs); - - // FIXME: if the last object has a bss then this won't work - // newvsize = (isection[objs-1].vaddr + isection[objs-1].size + oam1) &~ oam1; - // temporary solution: - unsigned newvsize = (isection[objs-1].vaddr + isection[objs-1].vsize + oam1) &~ oam1; - - //fprintf(stderr,"newvsize=%x objs=%d\n",newvsize,objs); - if (newvsize + soimport + sorelocs > ibuf.getSize()) - throwInternalError("buffer too small 2"); - memcpy(ibuf+newvsize,oimport,soimport); - memcpy(ibuf+newvsize+soimport,orelocs,sorelocs); - - cimports = newvsize - rvamin; // rva of preprocessed imports - crelocs = cimports + soimport; // rva of preprocessed fixups - - ph.u_len = newvsize + soimport + sorelocs; - - // some extra data for uncompression support - unsigned s = 0; - upx_byte * const p1 = ibuf + ph.u_len; - memcpy(p1 + s,&ih,sizeof (ih)); - s += sizeof (ih); - memcpy(p1 + s,isection,ih.objects * sizeof(*isection)); - s += ih.objects * sizeof(*isection); - if (soimport) - { - set_le32(p1 + s,cimports); - set_le32(p1 + s + 4,dllstrings); - s += 8; - } - if (sorelocs) - { - set_le32(p1 + s,crelocs); - p1[s + 4] = (unsigned char) (big_relocs & 6); - s += 5; - } - if (soresources) - { - set_le16(p1 + s,icondir_count); - s += 2; - } - // end of extra data - set_le32(p1 + s,ptr_diff(p1,ibuf) - rvamin); - s += 4; - ph.u_len += s; - obuf.allocForCompression(ph.u_len); - - // prepare packheader - ph.u_len -= rvamin; - // prepare filter - Filter ft(ph.level); - ft.buf_len = ih.codesize; - ft.addvalue = ih.codebase - rvamin; - // compress - int filter_strategy = allow_filter ? 0 : -3; - - // disable filters for files with broken headers - if (ih.codebase + ih.codesize > ph.u_len) - { - ft.buf_len = 1; - filter_strategy = -3; - } - - compressWithFilters(&ft, 2048, NULL_cconf, filter_strategy, - ih.codebase, rvamin, 0, NULL, 0); -// info: see buildLoader() - newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1; - if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4) - tlsindex = 0; - - int identsize = 0; - const unsigned codesize = getLoaderSection("IDENTSTR",&identsize); - assert(identsize > 0); - getLoaderSection("UPX1HEAD",(int*)&ic); - identsize += ic; - - pe_section_t osection[3]; - // section 0 : bss - // 1 : [ident + header] + packed_data + unpacker + tls + loadconf - // 2 : not compressed data - - // section 2 should start with the resource data, because lots of lame - // windoze codes assume that resources starts on the beginning of a section - - // note: there should be no data in section 2 which needs fixup - - // identsplit - number of ident + (upx header) bytes to put into the PE header - int identsplit = pe_offset + sizeof(osection) + sizeof(oh); - if ((identsplit & 0x1ff) == 0) - identsplit = 0; - else if (((identsplit + identsize) ^ identsplit) < 0x200) - identsplit = identsize; - else - identsplit = ALIGN_GAP(identsplit, 0x200); - ic = identsize - identsplit; - - const unsigned c_len = ((ph.c_len + ic) & 15) == 0 ? ph.c_len : ph.c_len + 16 - ((ph.c_len + ic) & 15); - obuf.clear(ph.c_len, c_len - ph.c_len); - - const unsigned s1size = ALIGN_UP(ic + c_len + codesize,8u) + sotls + soloadconf; - const unsigned s1addr = (newvsize - (ic + c_len) + oam1) &~ oam1; - - const unsigned ncsection = (s1addr + s1size + oam1) &~ oam1; - const unsigned upxsection = s1addr + ic + c_len; - const unsigned myimport = ncsection + soresources - rvamin; - - // patch loader - linker->defineSymbol("original_entry", ih.entry); - if (use_dep_hack) - { - // This works around a "protection" introduced in MSVCRT80, which - // works like this: - // When the compiler detects that it would link in some code from its - // C runtime library which references some data in a read only - // section then it compiles in a runtime check whether that data is - // still in a read only section by looking at the pe header of the - // file. If this check fails the runtime does "interesting" things - // like not running the floating point initialization code - the result - // is a R6002 runtime error. - // These supposed to be read only addresses are covered by the sections - // UPX0 & UPX1 in the compressed files, so we have to patch the PE header - // in the memory. And the page on which the PE header is stored is read - // only so we must make it rw, fix the flags (i.e. clear - // PEFL_WRITE of osection[x].flags), and make it ro again. - - // rva of the most significant byte of member "flags" in section "UPX0" - const unsigned swri = pe_offset + sizeof(oh) + sizeof(pe_section_t) - 1; - // make sure we only touch the minimum number of pages - const unsigned addr = 0u - rvamin + swri; - linker->defineSymbol("swri", addr & 0xfff); // page offset - // check whether osection[0].flags and osection[1].flags - // are on the same page - linker->defineSymbol("vp_size", ((addr & 0xfff) + 0x28 >= 0x1000) ? - 0x2000 : 0x1000); // 2 pages or 1 page - linker->defineSymbol("vp_base", addr &~ 0xfff); // page mask - linker->defineSymbol("VirtualProtect", myimport + - ilinkerGetAddress("kernel32.dll", "VirtualProtect")); - } - linker->defineSymbol("start_of_relocs", crelocs); - if (!isdll) - linker->defineSymbol("ExitProcess", myimport + - ilinkerGetAddress("kernel32.dll", "ExitProcess")); - linker->defineSymbol("GetProcAddress", myimport + - ilinkerGetAddress("kernel32.dll", "GetProcAddress")); - linker->defineSymbol("kernel32_ordinals", myimport); - linker->defineSymbol("LoadLibraryA", myimport + - ilinkerGetAddress("kernel32.dll", "LoadLibraryA")); - linker->defineSymbol("start_of_imports", myimport); - linker->defineSymbol("compressed_imports", cimports); - - if (M_IS_LZMA(ph.method)) - { - linker->defineSymbol("lzma_c_len", ph.c_len - 2); - linker->defineSymbol("lzma_u_len", ph.u_len); - } - defineFilterSymbols(&ft); - linker->defineSymbol("filter_buffer_start", ih.codebase - rvamin); - - // in case of overlapping decompression, this hack is needed, - // because windoze zeroes the word pointed by tlsindex before - // it starts programs - linker->defineSymbol("tls_value", (tlsindex + 4 > s1addr) ? - get_le32(obuf + tlsindex - s1addr - ic) : 0); - linker->defineSymbol("tls_address", tlsindex - rvamin); - - linker->defineSymbol("icon_delta", icondir_count - 1); - linker->defineSymbol("icon_offset", ncsection + icondir_offset - rvamin); - - const unsigned esi0 = s1addr + ic; - linker->defineSymbol("start_of_uncompressed", 0u - esi0 + rvamin); - linker->defineSymbol("start_of_compressed", esi0); - //NEW: TLS callback support - Stefan Widmann - ic = s1addr + s1size - sotls - soloadconf; //moved here, we need the address of the new TLS! - if (use_tls_callbacks) - { - linker->defineSymbol("tls_callbacks_ptr", tlscb_ptr - ih.imagebase); - linker->defineSymbol("tls_module_base", 0u - rvamin); - } - - linker->defineSymbol("START", upxsection); - //linker->dumpSymbols(); - relocateLoader(); - - const unsigned lsize = getLoaderSize(); - MemBuffer loader(lsize); - memcpy(loader,getLoader(),lsize); - patchPackHeader(loader, lsize); - - Reloc rel(1024); // new relocations are put here - - // new PE header - memcpy(&oh,&ih,sizeof(oh)); - oh.filealign = 0x200; // identsplit depends on this - memset(osection,0,sizeof(osection)); - - oh.entry = upxsection; - oh.objects = 3; - oh.chksum = 0; - - // fill the data directory - ODADDR(PEDIR_DEBUG) = 0; //remove debug data - ODSIZE(PEDIR_DEBUG) = 0; - ODADDR(PEDIR_IAT) = 0; //remove IAT pointer - ODSIZE(PEDIR_IAT) = 0; - ODADDR(PEDIR_BOUNDIM) = 0; //remove bound import table - ODSIZE(PEDIR_BOUNDIM) = 0; - - // tls & loadconf are put into section 1 - - //ic = s1addr + s1size - sotls - soloadconf; //ATTENTION: moved upwards to TLS callback handling - Stefan Widmann - if (use_tls_callbacks) - tls_handler_offset = linker->getSymbolOffset("PETLSC2"); - - processTls(&rel,&tlsiv,ic); - ODADDR(PEDIR_TLS) = sotls ? ic : 0; - ODSIZE(PEDIR_TLS) = sotls ? 0x28 : 0; // size of TLS is 0x28 in PE32+ - Stefan Widmann - ic += sotls; - - processLoadConf(&rel, &loadconfiv, ic); - ODADDR(PEDIR_LOADCONF) = soloadconf ? ic : 0; - ODSIZE(PEDIR_LOADCONF) = soloadconf; - ic += soloadconf; - - // these are put into section 2 - - ic = ncsection; - if (soresources) - processResources(&res,ic); - ODADDR(PEDIR_RESOURCE) = soresources ? ic : 0; - ODSIZE(PEDIR_RESOURCE) = soresources; - ic += soresources; - - PeFile::processImports(ic, 0); - ODADDR(PEDIR_IMPORT) = ic; - ODSIZE(PEDIR_IMPORT) = soimpdlls; - ic += soimpdlls; - - processExports(&xport,ic); - ODADDR(PEDIR_EXPORT) = soexport ? ic : 0; - ODSIZE(PEDIR_EXPORT) = soexport; - if (!isdll && opt->win32_pe.compress_exports) - { - ODADDR(PEDIR_EXPORT) = IDADDR(PEDIR_EXPORT); - ODSIZE(PEDIR_EXPORT) = IDSIZE(PEDIR_EXPORT); - } - ic += soexport; - - PeFile::processRelocs(&rel); - ODADDR(PEDIR_RELOC) = soxrelocs ? ic : 0; - ODSIZE(PEDIR_RELOC) = soxrelocs; - ic += soxrelocs; - - // this is computed here, because soxrelocs changes some lines above - const unsigned ncsize = soresources + soimpdlls + soexport + soxrelocs; - ic = oh.filealign - 1; - - // this one is tricky: it seems windoze touches 4 bytes after - // the end of the relocation data - so we have to increase - // the virtual size of this section - const unsigned ncsize_virt_increase = (ncsize & oam1) == 0 ? 8 : 0; - - // fill the sections - strcpy(osection[0].name,"UPX0"); - strcpy(osection[1].name,"UPX1"); - // after some windoze debugging I found that the name of the sections - // DOES matter :( .rsrc is used by oleaut32.dll (TYPELIBS) - // and because of this lame dll, the resource stuff must be the - // first in the 3rd section - the author of this dll seems to be - // too idiot to use the data directories... M$ suxx 4 ever! - // ... even worse: exploder.exe in NiceTry also depends on this to - // locate version info - - strcpy(osection[2].name,soresources ? ".rsrc" : "UPX2"); - - osection[0].vaddr = rvamin; - osection[1].vaddr = s1addr; - osection[2].vaddr = ncsection; - - osection[0].size = 0; - osection[1].size = (s1size + ic) &~ ic; - osection[2].size = (ncsize + ic) &~ ic; - - osection[0].vsize = osection[1].vaddr - osection[0].vaddr; - osection[1].vsize = (osection[1].size + oam1) &~ oam1; - osection[2].vsize = (osection[2].size + ncsize_virt_increase + oam1) &~ oam1; - - osection[0].rawdataptr = (pe_offset + sizeof(oh) + sizeof(osection) + ic) &~ ic; - osection[1].rawdataptr = osection[0].rawdataptr; - osection[2].rawdataptr = osection[1].rawdataptr + osection[1].size; - - osection[0].flags = (unsigned) (PEFL_BSS|PEFL_EXEC|PEFL_WRITE|PEFL_READ); - osection[1].flags = (unsigned) (PEFL_DATA|PEFL_EXEC|PEFL_WRITE|PEFL_READ); - osection[2].flags = (unsigned) (PEFL_DATA|PEFL_WRITE|PEFL_READ); - - oh.imagesize = osection[2].vaddr + osection[2].vsize; - oh.bsssize = osection[0].vsize; - oh.datasize = osection[2].vsize; - //oh.database = osection[2].vaddr; //no base of data in PE32+ files - Stefan Widmann - oh.codesize = osection[1].vsize; - oh.codebase = osection[1].vaddr; - // oh.headersize = osection[0].rawdataptr; - oh.headersize = rvamin; - if (rvamin < osection[0].rawdataptr) - throwCantPack("object alignment too small"); - - if (opt->win32_pe.strip_relocs && !isdll) - oh.flags |= RELOCS_STRIPPED; - - //for (ic = 0; ic < oh.filealign; ic += 4) - // set_le32(ibuf + ic,get_le32("UPX ")); - ibuf.clear(0, oh.filealign); - - info("Image size change: %u -> %u KiB", - ih.imagesize / 1024, oh.imagesize / 1024); - - infoHeader("[Writing compressed file]"); - - // write loader + compressed file - fo->write(&oh,sizeof(oh)); - fo->write(osection,sizeof(osection)); - // some alignment - if (identsplit == identsize) - { - unsigned n = osection[0].rawdataptr - fo->getBytesWritten() - identsize; - assert(n <= oh.filealign); - fo->write(ibuf, n); - } - fo->write(loader + codesize,identsize); - infoWriting("loader", fo->getBytesWritten()); - fo->write(obuf,c_len); - infoWriting("compressed data", c_len); - fo->write(loader,codesize); - if (opt->debug.dump_stub_loader) - OutputFile::dump(opt->debug.dump_stub_loader, loader, codesize); - if ((ic = fo->getBytesWritten() & 7) != 0) - fo->write(ibuf,8 - ic); - fo->write(otls,sotls); - fo->write(oloadconf, soloadconf); - if ((ic = fo->getBytesWritten() & (oh.filealign-1)) != 0) - fo->write(ibuf,oh.filealign - ic); - fo->write(oresources,soresources); - fo->write(oimpdlls,soimpdlls); - fo->write(oexport,soexport); - fo->write(oxrelocs,soxrelocs); - - if ((ic = fo->getBytesWritten() & (oh.filealign-1)) != 0) - fo->write(ibuf,oh.filealign - ic); - -#if 0 - printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh)); - printf("%-13s: sections : %8ld bytes\n", getName(), (long) sizeof(osection)); - printf("%-13s: ident : %8ld bytes\n", getName(), (long) identsize); - printf("%-13s: compressed : %8ld bytes\n", getName(), (long) c_len); - printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) codesize); - printf("%-13s: tls : %8ld bytes\n", getName(), (long) sotls); - printf("%-13s: resources : %8ld bytes\n", getName(), (long) soresources); - printf("%-13s: imports : %8ld bytes\n", getName(), (long) soimpdlls); - printf("%-13s: exports : %8ld bytes\n", getName(), (long) soexport); - printf("%-13s: relocs : %8ld bytes\n", getName(), (long) soxrelocs); - printf("%-13s: loadconf : %8ld bytes\n", getName(), (long) soloadconf); -#endif - - // verify - verifyOverlappingDecompression(); - - // copy the overlay - copyOverlay(fo, overlay, &obuf); - - if (!checkFinalCompressionRatio(fo)) - throwNotCompressible(); -#endif } /* diff --git a/src/packmast.cpp b/src/packmast.cpp index 5c2cf9ee..cfb398d0 100644 --- a/src/packmast.cpp +++ b/src/packmast.cpp @@ -32,7 +32,6 @@ #include "packer.h" #include "lefile.h" #include "pefile.h" -#include "pepfile.h" #include "p_elf.h" #include "p_com.h" diff --git a/src/pepfile.cpp b/src/pepfile.cpp deleted file mode 100644 index 1ca98819..00000000 --- a/src/pepfile.cpp +++ /dev/null @@ -1,1738 +0,0 @@ -/* pepfile.cpp -- - - This file is part of the UPX executable compressor. - - Copyright (C) 1996-2013 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996-2013 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 - - - ------------------------------------------------------------------- - - PE+ format extension changes (C) 2010 Stefan Widmann - changes in: - */ - -#if 0 -#include "conf.h" -#include "file.h" -#include "filter.h" -#include "packer.h" -#include "pepfile.h" - -#define IDSIZE(x) ih.ddirs[x].size -#define IDADDR(x) ih.ddirs[x].vaddr -#define ODSIZE(x) oh.ddirs[x].size -#define ODADDR(x) oh.ddirs[x].vaddr - -#define isdll ((ih.flags & DLL_FLAG) != 0) - -#define FILLVAL 0 - -/************************************************************************* -// -**************************************************************************/ - -#if defined(__BORLANDC__) -# undef strcpy -# define strcpy(a,b) strcpy((char *)(a),(const char *)(b)) -#endif - -#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) -{ - if (!p) - throwCantUnpack("unexpected NULL pointer; take care!"); -} -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) - - -/************************************************************************* -// -**************************************************************************/ - -PepFile::PepFile(InputFile *f) : super(f) -{ - bele = &N_BELE_RTP::le_policy; - //printf("pe_header_t %d\n", (int) sizeof(pe_header_t)); - //printf("pe_section_t %d\n", (int) sizeof(pe_section_t)); - COMPILE_TIME_ASSERT(sizeof(pe_header_t) == 264) - COMPILE_TIME_ASSERT(sizeof(pe_header_t::ddirs_t) == 8) - COMPILE_TIME_ASSERT(sizeof(pe_section_t) == 40) - COMPILE_TIME_ASSERT_ALIGNED1(pe_header_t) - COMPILE_TIME_ASSERT_ALIGNED1(pe_header_t::ddirs_t) - COMPILE_TIME_ASSERT_ALIGNED1(pe_section_t) - COMPILE_TIME_ASSERT(RT_LAST == TABLESIZE(opt->win32_pe.compress_rt)) - - isection = NULL; - oimport = NULL; - oimpdlls = NULL; - orelocs = NULL; - oexport = NULL; - otls = NULL; - oresources = NULL; - oxrelocs = NULL; - icondir_offset = 0; - icondir_count = 0; - importbyordinal = false; - kernel32ordinal = false; - tlsindex = 0; - big_relocs = 0; - sorelocs = 0; - soxrelocs = 0; - sotls = 0; -} - - -PepFile::~PepFile() -{ - delete [] isection; - delete [] orelocs; - delete [] oimport; - delete [] oimpdlls; - delete [] oexport; - delete [] otls; - delete [] oresources; - delete [] oxrelocs; - //delete res; -} - - -bool PepFile::testUnpackVersion(int version) const -{ - if (version != ph_version && ph_version != -1) - throwCantUnpack("program has been modified; run a virus checker!"); - if (!canUnpackVersion(version)) - throwCantUnpack("this program is packed with an obsolete version and cannot be unpacked"); - return true; -} - - -/************************************************************************* -// util -**************************************************************************/ - -int PepFile::readFileHeader() -{ - __packed_struct(exe_header_t) - LE16 mz; - LE16 m512; - LE16 p512; - char _[18]; - LE16 relocoffs; - char __[34]; - LE32 nexepos; - __packed_struct_end() - - COMPILE_TIME_ASSERT(sizeof(exe_header_t) == 64) - COMPILE_TIME_ASSERT_ALIGNED1(exe_header_t) - COMPILE_TIME_ASSERT(sizeof(((exe_header_t*)0)->_) == 18) - COMPILE_TIME_ASSERT(sizeof(((exe_header_t*)0)->__) == 34) - - exe_header_t h; - int ic; - pe_offset = 0; - - for (ic = 0; ic < 20; ic++) - { - fi->seek(pe_offset,SEEK_SET); - fi->readx(&h,sizeof(h)); - - if (h.mz == 'M' + 'Z'*256) // dos exe - { - if (h.relocoffs >= 0x40) // new format exe - pe_offset += h.nexepos; - else - pe_offset += h.p512*512+h.m512 - h.m512 ? 512 : 0; - } - else if (get_le32(&h) == 'P' + 'E'*256) - break; - else - return 0; - } - if (ic == 20) - return 0; - fi->seek(pe_offset,SEEK_SET); - fi->readx(&ih,sizeof(ih)); - fi->seek(0x200,SEEK_SET); - fi->readx(&h,6); - return getFormat(); -} - - -/************************************************************************* -// interval handling -**************************************************************************/ - -PepFile::Interval::Interval(void *b) : capacity(0),base(b),ivarr(NULL),ivnum(0) -{} - -PepFile::Interval::~Interval() -{ - free(ivarr); -} - -void PepFile::Interval::add(const void *start,unsigned len) -{ - add(ptr_diff(start,base),len); -} - -void PepFile::Interval::add(const void *start,const void *end) -{ - add(ptr_diff(start,base),ptr_diff(end,start)); -} - -int __acc_cdecl_qsort PepFile::Interval::compare(const void *p1,const void *p2) -{ - const interval *i1 = (const interval*) p1; - const interval *i2 = (const interval*) p2; - if (i1->start < i2->start) return -1; - if (i1->start > i2->start) return 1; - if (i1->len < i2->len) return 1; - if (i1->len > i2->len) return -1; - return 0; -} - -void PepFile::Interval::add(unsigned start,unsigned len) -{ - if (ivnum == capacity) - ivarr = (interval*) realloc(ivarr,(capacity += 15) * sizeof (interval)); - ivarr[ivnum].start = start; - ivarr[ivnum++].len = len; -} - -void PepFile::Interval::add(const Interval *iv) -{ - for (unsigned ic = 0; ic < iv->ivnum; ic++) - add(iv->ivarr[ic].start,iv->ivarr[ic].len); -} - -void PepFile::Interval::flatten() -{ - if (!ivnum) - return; - qsort(ivarr,ivnum,sizeof (interval),Interval::compare); - for (unsigned ic = 0; ic < ivnum - 1; ic++) - { - unsigned jc; - for (jc = ic + 1; jc < ivnum && ivarr[ic].start + ivarr[ic].len >= ivarr[jc].start; jc++) - if (ivarr[ic].start + ivarr[ic].len < ivarr[jc].start + ivarr[jc].len) - ivarr[ic].len = ivarr[jc].start + ivarr[jc].len - ivarr[ic].start; - if (jc > ic + 1) - { - memmove(ivarr + ic + 1, ivarr + jc,sizeof(interval) * (ivnum - jc)); - ivnum -= jc - ic - 1; - } - } -} - -void PepFile::Interval::clear() -{ - for (unsigned ic = 0; ic < ivnum; ic++) - memset((char*) base + ivarr[ic].start,0,ivarr[ic].len); -} - -void PepFile::Interval::dump() const -{ - printf("%d intervals:\n",ivnum); - for (unsigned ic = 0; ic < ivnum; ic++) - printf("%x %x\n",ivarr[ic].start,ivarr[ic].len); -} - - -/************************************************************************* -// relocation handling -**************************************************************************/ - -__packed_struct(PepFile::Reloc::reloc) - LE32 pagestart; - LE32 size; -__packed_struct_end() - -void PepFile::Reloc::newRelocPos(void *p) -{ - rel = (reloc*) p; - rel1 = (LE16*) ((char*) p + sizeof (reloc)); -} - -PepFile::Reloc::Reloc(upx_byte *s,unsigned si) : - start(s), size(si), rel(NULL), rel1(NULL) -{ - COMPILE_TIME_ASSERT(sizeof(reloc) == 8) - COMPILE_TIME_ASSERT_ALIGNED1(reloc) - memset(counts,0,sizeof(counts)); - unsigned pos,type; - while (next(pos,type)) - counts[type]++; -} - -PepFile::Reloc::Reloc(unsigned rnum) : - start(NULL), size(0), rel(NULL), rel1(NULL) -{ - start = new upx_byte[rnum * 4 + 8192]; - counts[0] = 0; -} - -bool PepFile::Reloc::next(unsigned &pos,unsigned &type) -{ - if (!rel) - newRelocPos(start); - if (ptr_diff(rel, start) >= (int) size || rel->pagestart == 0) - return rel = 0,false; // rewind - - pos = rel->pagestart + (*rel1 & 0xfff); - type = *rel1++ >> 12; - //printf("%x %d\n",pos,type); - if (ptr_diff(rel1,rel) >= (int) rel->size) - newRelocPos(rel1); - return type == 0 ? next(pos,type) : true; -} - -void PepFile::Reloc::add(unsigned pos,unsigned type) -{ - set_le32(start + 1024 + 4 * counts[0]++,(pos << 4) + type); -} - -void PepFile::Reloc::finish(upx_byte *&p,unsigned &siz) -{ - unsigned prev = 0xffffffff; - set_le32(start + 1024 + 4 * counts[0]++,0xf0000000); - qsort(start + 1024,counts[0],4,le32_compare); - - rel = (reloc*) start; - rel1 = (LE16*) start; - for (unsigned ic = 0; ic < counts[0]; ic++) - { - unsigned pos = get_le32(start + 1024 + 4 * ic); - if ((pos ^ prev) >= 0x10000) - { - prev = pos; - *rel1 = 0; - rel->size = ALIGN_UP(ptr_diff(rel1,rel),4); - newRelocPos((char *)rel + rel->size); - rel->pagestart = (pos >> 4) &~ 0xfff; - } - *rel1++ = (pos << 12) + ((pos >> 4) & 0xfff); - } - p = start; - siz = ptr_diff(rel1,start) &~ 3; - siz -= 8; - //NEW: we do not need any relocs in 64 bit long mode, an empty reloc table is fine - Stefan Widmann - //assert(siz > 0); - start = 0; // safety -} - -void PepFile::processRelocs(Reloc *rel) // pass2 -{ - rel->finish(oxrelocs,soxrelocs); - if (opt->win32_pe.strip_relocs && !isdll) - soxrelocs = 0; -} - -void PepFile::processRelocs() // pass1 -{ - big_relocs = 0; - - Reloc rel(ibuf + IDADDR(PEDIR_RELOC),IDSIZE(PEDIR_RELOC)); - const unsigned *counts = rel.getcounts(); - unsigned rnum = 0; - - unsigned ic; - for (ic = 1; ic < 16; ic++) - rnum += counts[ic]; - - if ((opt->win32_pe.strip_relocs && !isdll) || rnum == 0) - { - if (IDSIZE(PEDIR_RELOC)) - ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL); - orelocs = new upx_byte [1]; - sorelocs = 0; - return; - } - - for (ic = 15; ic; ic--) - if (ic != 10 && counts[ic]) - infoWarning("skipping unsupported relocation type %d (%d)",ic,counts[ic]); - - LE32 *fix[16]; - for (ic = 15; ic; ic--) - fix[ic] = new LE32 [counts[ic]]; - - unsigned xcounts[16]; - memset(xcounts, 0, sizeof(xcounts)); - - // prepare sorting - unsigned pos,type; - while (rel.next(pos,type)) - { - // FIXME add check for relocations which try to modify the - // PE header or other relocation records - - if (pos >= ih.imagesize) - continue; // skip out-of-bounds record - if (type < 16) - fix[type][xcounts[type]++] = pos - rvamin; - } - - // remove duplicated records - for (ic = 1; ic <= 15; ic++) - { - qsort(fix[ic], xcounts[ic], 4, le32_compare); - unsigned prev = ~0; - unsigned jc = 0; - for (unsigned kc = 0; kc < xcounts[ic]; kc++) - if (fix[ic][kc] != prev) - prev = fix[ic][jc++] = fix[ic][kc]; - - //printf("xcounts[%u] %u->%u\n", ic, xcounts[ic], jc); - xcounts[ic] = jc; - } - - // preprocess "type 10" relocation records - for (ic = 0; ic < xcounts[10]; ic++) - { - pos = fix[10][ic] + rvamin; - set_le64(ibuf + pos, get_le64(ibuf + pos) - ih.imagebase - rvamin); - } - - ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL); - orelocs = new upx_byte [rnum * 4 + 1024]; // 1024 - safety - sorelocs = ptr_diff(optimizeReloc64((upx_byte*) fix[10], xcounts[10], - orelocs, ibuf + rvamin,1, &big_relocs), - orelocs); - - for (ic = 15; ic; ic--) - delete [] fix[ic]; - -#if 0 - // Malware that hides behind UPX often has PE header info that is - // deliberately corrupt. Sometimes it is even tuned to cause us trouble! - // Use an extra check to avoid AccessViolation (SIGSEGV) when appending - // the relocs into one array. - if ((rnum * 4 + 1024) < (sorelocs + 4*(2 + xcounts[2] + xcounts[1]))) - throwCantUnpack("Invalid relocs"); - - // append relocs type "LOW" then "HIGH" - for (ic = 2; ic ; ic--) - { - memcpy(orelocs + sorelocs,fix[ic],4 * xcounts[ic]); - sorelocs += 4 * xcounts[ic]; - delete [] fix[ic]; - - set_le32(orelocs + sorelocs,0); - if (xcounts[ic]) - { - sorelocs += 4; - big_relocs |= 2 * ic; - } - } -#endif - info("Relocations: original size: %u bytes, preprocessed size: %u bytes",(unsigned) IDSIZE(PEDIR_RELOC),sorelocs); -} - - -/************************************************************************* -// import handling -**************************************************************************/ - -__packed_struct(import_desc) - LE32 oft; // orig first thunk - char _[8]; - LE32 dllname; - LE32 iat; // import address table -__packed_struct_end() - -void PepFile::processImports(unsigned myimport, unsigned iat_off) // pass 2 -{ - COMPILE_TIME_ASSERT(sizeof(import_desc) == 20) - COMPILE_TIME_ASSERT_ALIGNED1(import_desc) - - // adjust import data - for (import_desc *im = (import_desc*) oimpdlls; im->dllname; im++) - { - if (im->dllname < myimport) - im->dllname += myimport; - LE64 *p = (LE64*) (oimpdlls + im->iat); - im->iat += myimport; - im->oft = im->iat; - - while (*p) - if ((*p++ & 0x8000000000000000ULL) == 0) // import by name? - p[-1] += myimport; - - im->iat = im == (import_desc*) oimpdlls ? iat_off : iat_off + 12; - } -} - -unsigned PepFile::processImports() // pass 1 -{ - static const unsigned char kernel32dll[] = "COREDLL.dll"; - static const char llgpa[] = "\x0\x0""LoadLibraryW\x0\x0" - "GetProcAddressA\x0\x0\x0" - "CacheSync"; - //static const char exitp[] = "ExitProcess\x0\x0\x0"; - - unsigned dllnum = 0; - import_desc *im = (import_desc*) (ibuf + IDADDR(PEDIR_IMPORT)); - import_desc * const im_save = im; - if (IDADDR(PEDIR_IMPORT)) - { - while (im->dllname) - dllnum++, im++; - im = im_save; - } - - struct udll - { - const upx_byte *name; - const upx_byte *shname; - unsigned ordinal; - unsigned iat; - LE32 *lookupt; - unsigned npos; - bool isk32; - - static int __acc_cdecl_qsort compare(const void *p1, const void *p2) - { - const udll *u1 = * (const udll * const *) p1; - const udll *u2 = * (const udll * const *) p2; - if (u1->isk32) return -1; - if (u2->isk32) return 1; - int rc = strcasecmp(u1->name,u2->name); - if (rc) return rc; - if (u1->ordinal) return -1; - if (u2->ordinal) return 1; - if (!u1->shname) return 1; - if (!u2->shname) return -1; - return strlen(u1->shname) - strlen(u2->shname); - } - }; - - // +1 for dllnum=0 - Array(struct udll, dlls, dllnum+1); - Array(struct udll *, idlls, dllnum+1); - - soimport = 1024; // safety - - unsigned ic,k32o; - for (ic = k32o = 0; dllnum && im->dllname; ic++, im++) - { - idlls[ic] = dlls + ic; - dlls[ic].name = ibuf + im->dllname; - dlls[ic].shname = NULL; - dlls[ic].ordinal = 0; - dlls[ic].iat = im->iat; - dlls[ic].lookupt = (LE32*) (ibuf + (im->oft ? im->oft : im->iat)); - dlls[ic].npos = 0; - dlls[ic].isk32 = strcasecmp(kernel32dll,dlls[ic].name) == 0; - - soimport += strlen(dlls[ic].name) + 1 + 4; - - for (LE32 *tarr = dlls[ic].lookupt; *tarr; tarr++) - { - if (*tarr & 0x80000000) - { - importbyordinal = true; - soimport += 2; // ordinal num: 2 bytes - dlls[ic].ordinal = *tarr & 0xffff; - //if (dlls[ic].isk32) - // kernel32ordinal = true,k32o++; - } - else - { - unsigned len = strlen(ibuf + *tarr + 2); - soimport += len + 1; - if (dlls[ic].shname == NULL || len < strlen (dlls[ic].shname)) - dlls[ic].shname = ibuf + *tarr + 2; - } - soimport++; // separator - } - } - oimport = new upx_byte[soimport]; - memset(oimport,0,soimport); - oimpdlls = new upx_byte[soimport]; - memset(oimpdlls,0,soimport); - - qsort(idlls,dllnum,sizeof (udll*),udll::compare); - - unsigned dllnamelen = sizeof (kernel32dll); - unsigned dllnum2 = 1; - for (ic = 0; ic < dllnum; ic++) - if (!idlls[ic]->isk32 && (ic == 0 || strcasecmp(idlls[ic - 1]->name,idlls[ic]->name))) - { - dllnum2++; - dllnamelen += strlen(idlls[ic]->name) + 1; - } - //fprintf(stderr,"dllnum=%d dllnum2=%d soimport=%d\n",dllnum,dllnum2,soimport); // - - info("Processing imports: %d DLLs", dllnum); - - // create the new import table - im = (import_desc*) oimpdlls; - - LE32 *ordinals = (LE32*) (oimpdlls + (dllnum2 + 1) * sizeof(import_desc)); - LE32 *lookuptable = ordinals + 4;// + k32o + (isdll ? 0 : 1); - upx_byte *dllnames = ((upx_byte*) lookuptable) + (dllnum2 - 1) * 8; - upx_byte *importednames = dllnames + (dllnamelen &~ 1); - - unsigned k32namepos = ptr_diff(dllnames,oimpdlls); - - memcpy(importednames, llgpa, ALIGN_UP((unsigned) sizeof(llgpa), 2u)); - strcpy(dllnames,kernel32dll); - im->dllname = k32namepos; - im->iat = ptr_diff(ordinals,oimpdlls); - *ordinals++ = ptr_diff(importednames,oimpdlls); // LoadLibraryW - *ordinals++ = ptr_diff(importednames,oimpdlls) + 14; // GetProcAddressA - *ordinals++ = ptr_diff(importednames,oimpdlls) + 14 + 18; // CacheSync - dllnames += sizeof(kernel32dll); - importednames += sizeof(llgpa); - - im++; - for (ic = 0; ic < dllnum; ic++) - if (idlls[ic]->isk32) - { - idlls[ic]->npos = k32namepos; - /* - if (idlls[ic]->ordinal) - for (LE32 *tarr = idlls[ic]->lookupt; *tarr; tarr++) - if (*tarr & 0x80000000) - *ordinals++ = *tarr; - */ - } - else if (ic && strcasecmp(idlls[ic-1]->name,idlls[ic]->name) == 0) - idlls[ic]->npos = idlls[ic-1]->npos; - else - { - im->dllname = idlls[ic]->npos = ptr_diff(dllnames,oimpdlls); - im->iat = ptr_diff(lookuptable,oimpdlls); - - strcpy(dllnames,idlls[ic]->name); - dllnames += strlen(idlls[ic]->name)+1; - if (idlls[ic]->ordinal) - *lookuptable = idlls[ic]->ordinal + 0x80000000; - else if (idlls[ic]->shname) - { - if (ptr_diff(importednames,oimpdlls) & 1) - importednames--; - *lookuptable = ptr_diff(importednames,oimpdlls); - importednames += 2; - strcpy(importednames,idlls[ic]->shname); - importednames += strlen(idlls[ic]->shname) + 1; - } - lookuptable += 2; - im++; - } - soimpdlls = ALIGN_UP(ptr_diff(importednames,oimpdlls),4); - - Interval names(ibuf),iats(ibuf),lookups(ibuf); - // create the preprocessed data - //ordinals -= k32o; - upx_byte *ppi = oimport; // preprocessed imports - for (ic = 0; ic < dllnum; ic++) - { - LE32 *tarr = idlls[ic]->lookupt; - if (!*tarr) // no imports from this dll - continue; - set_le32(ppi,idlls[ic]->npos); - set_le32(ppi+4,idlls[ic]->iat - rvamin); - ppi += 8; - for (; *tarr; tarr++) - if (*tarr & 0x80000000) - { - /*if (idlls[ic]->isk32) - { - *ppi++ = 0xfe; // signed + odd parity - set_le32(ppi,ptr_diff(ordinals,oimpdlls)); - ordinals++; - ppi += 4; - } - else*/ - { - *ppi++ = 0xff; - set_le16(ppi,*tarr & 0xffff); - ppi += 2; - } - } - else - { - *ppi++ = 1; - unsigned len = strlen(ibuf + *tarr + 2) + 1; - memcpy(ppi,ibuf + *tarr + 2,len); - ppi += len; - names.add(*tarr,len + 2 + 1); - } - ppi++; - - unsigned esize = ptr_diff((char *)tarr, (char *)idlls[ic]->lookupt); - lookups.add(idlls[ic]->lookupt,esize); - if (ptr_diff(ibuf + idlls[ic]->iat, (char *)idlls[ic]->lookupt)) - { - memcpy(ibuf + idlls[ic]->iat, idlls[ic]->lookupt, esize); - iats.add(idlls[ic]->iat,esize); - } - names.add(idlls[ic]->name,strlen(idlls[ic]->name) + 1 + 1); - } - ppi += 4; - assert(ppi < oimport+soimport); - soimport = ptr_diff(ppi,oimport); - - if (soimport == 4) - soimport = 0; - - //OutputFile::dump("x0.imp", oimport, soimport); - //OutputFile::dump("x1.imp", oimpdlls, soimpdlls); - - unsigned ilen = 0; - names.flatten(); - if (names.ivnum > 1) - { - // The area occupied by the dll and imported names is not continuous - // so to still support uncompression, I can't zero the iat area. - // This decreases compression ratio, so FIXME somehow. - infoWarning("can't remove unneeded imports"); - ilen += sizeof(import_desc) * dllnum; -#if defined(DEBUG) - if (opt->verbose > 3) - names.dump(); -#endif - // do some work for the unpacker - im = im_save; - for (ic = 0; ic < dllnum; ic++, im++) - { - memset(im,FILLVAL,sizeof(*im)); - im->dllname = ptr_diff(idlls[ic]->name,ibuf); // I only need this info - } - } - else - { - iats.add(im_save,sizeof(import_desc) * dllnum); - // zero unneeded data - iats.clear(); - lookups.clear(); - } - names.clear(); - - iats.add(&names); - iats.add(&lookups); - iats.flatten(); - for (ic = 0; ic < iats.ivnum; ic++) - ilen += iats.ivarr[ic].len; - - info("Imports: original size: %u bytes, preprocessed size: %u bytes",ilen,soimport); - return names.ivnum == 1 ? names.ivarr[0].start : 0; -} - - -/************************************************************************* -// export handling -**************************************************************************/ - -PepFile::Export::Export(char *_base) : base(_base), iv(_base) -{ - COMPILE_TIME_ASSERT(sizeof(export_dir_t) == 40) - COMPILE_TIME_ASSERT_ALIGNED1(export_dir_t) - ename = functionptrs = ordinals = NULL; - names = NULL; - memset(&edir,0,sizeof(edir)); - size = 0; -} - -PepFile::Export::~Export() -{ - free(ename); - delete [] functionptrs; - delete [] ordinals; - for (unsigned ic = 0; ic < edir.names + edir.functions; ic++) - free(names[ic]); - delete [] names; -} - -void PepFile::Export::convert(unsigned eoffs,unsigned esize) -{ - memcpy(&edir,base + eoffs,sizeof(export_dir_t)); - size = sizeof(export_dir_t); - iv.add(eoffs,size); - - unsigned len = strlen(base + edir.name) + 1; - ename = strdup(base + edir.name); - size += len; - iv.add(edir.name,len); - - len = 4 * edir.functions; - functionptrs = new char[len + 1]; - memcpy(functionptrs,base + edir.addrtable,len); - size += len; - iv.add(edir.addrtable,len); - - unsigned ic; - names = new char* [edir.names + edir.functions + 1]; - for (ic = 0; ic < edir.names; ic++) - { - char *n = base + get_le32(base + edir.nameptrtable + ic * 4); - len = strlen(n) + 1; - names[ic] = strdup(n); - size += len; - iv.add(get_le32(base + edir.nameptrtable + ic * 4),len); - } - iv.add(edir.nameptrtable,4 * edir.names); - size += 4 * edir.names; - - LE32 *fp = (LE32*) functionptrs; - // export forwarders - for (ic = 0; ic < edir.functions; ic++) - if (fp[ic] >= eoffs && fp[ic] < eoffs + esize) - { - char *forw = base + fp[ic]; - len = strlen(forw) + 1; - iv.add(forw,len); - size += len; - names[ic + edir.names] = strdup(forw); - } - else - names[ic + edir.names] = NULL; - - len = 2 * edir.names; - ordinals = new char[len + 1]; - memcpy(ordinals,base + edir.ordinaltable,len); - size += len; - iv.add(edir.ordinaltable,len); - iv.flatten(); - if (iv.ivnum == 1) - iv.clear(); -#if defined(DEBUG) - else - iv.dump(); -#endif -} - -void PepFile::Export::build(char *newbase, unsigned newoffs) -{ - char * const functionp = newbase + sizeof(edir); - char * const namep = functionp + 4 * edir.functions; - char * const ordinalp = namep + 4 * edir.names; - char * const enamep = ordinalp + 2 * edir.names; - char * exports = enamep + strlen(ename) + 1; - - edir.addrtable = newoffs + ptr_diff(functionp, newbase); - edir.ordinaltable = newoffs + ptr_diff(ordinalp, newbase); - memcpy(ordinalp,ordinals,2 * edir.names); - - edir.name = newoffs + ptr_diff(enamep, newbase); - strcpy(enamep,ename); - edir.nameptrtable = newoffs + ptr_diff(namep, newbase); - unsigned ic; - for (ic = 0; ic < edir.names; ic++) - { - strcpy(exports,names[ic]); - set_le32(namep + 4 * ic,newoffs + ptr_diff(exports, newbase)); - exports += strlen(exports) + 1; - } - - memcpy(functionp,functionptrs,4 * edir.functions); - for (ic = 0; ic < edir.functions; ic++) - if (names[edir.names + ic]) - { - strcpy(exports,names[edir.names + ic]); - set_le32(functionp + 4 * ic,newoffs + ptr_diff(exports, newbase)); - exports += strlen(exports) + 1; - } - - memcpy(newbase,&edir,sizeof(edir)); - assert(exports - newbase == (int) size); -} - -void PepFile::processExports(Export *xport) // pass1 -{ - soexport = ALIGN_UP(IDSIZE(PEDIR_EXPORT),4); - if (soexport == 0) - return; - if (!isdll && opt->win32_pe.compress_exports) - { - infoWarning("exports compressed, --compress-exports=0 might be needed"); - soexport = 0; - return; - } - xport->convert(IDADDR(PEDIR_EXPORT),IDSIZE(PEDIR_EXPORT)); - soexport = ALIGN_UP(xport->getsize(), 4u); - oexport = new upx_byte[soexport]; - memset(oexport, 0, soexport); -} - -void PepFile::processExports(Export *xport,unsigned newoffs) // pass2 -{ - if (soexport) - xport->build((char*) oexport,newoffs); -} - -/************************************************************************* -// resource handling -**************************************************************************/ - -__packed_struct(PepFile::Resource::res_dir_entry) - LE32 tnl; // Type | Name | Language id - depending on level - LE32 child; -__packed_struct_end() - -__packed_struct(PepFile::Resource::res_dir) - char _[12]; // flags, timedate, version - LE16 namedentr; - LE16 identr; - - unsigned Sizeof() const { return 16 + sizeof(res_dir_entry)*(namedentr + identr); } - res_dir_entry entries[1]; - // it's usually safe to assume that every res_dir contains - // at least one res_dir_entry - check() complains otherwise -__packed_struct_end() - -__packed_struct(PepFile::Resource::res_data) - LE32 offset; - LE32 size; - char _[8]; // codepage, reserved -__packed_struct_end() - -struct PepFile::Resource::upx_rnode -{ - unsigned id; - upx_byte *name; - upx_rnode *parent; -}; - -struct PepFile::Resource::upx_rbranch : public PepFile::Resource::upx_rnode -{ - unsigned nc; - upx_rnode **children; - res_dir data; -}; - -struct PepFile::Resource::upx_rleaf : public PepFile::Resource::upx_rnode -{ - upx_rleaf *next; - unsigned newoffset; - res_data data; -}; - -PepFile::Resource::Resource() : root(NULL) -{} - -PepFile::Resource::Resource(const upx_byte *p) -{ - init(p); - -} - -PepFile::Resource::~Resource() -{ - if (root) destroy (root,0); -} - -unsigned PepFile::Resource::dirsize() const -{ - return ALIGN_UP(dsize + ssize, 4u); -} - -bool PepFile::Resource::next() -{ - // wow, builtin autorewind... :-) - return (current = current ? current->next : head) != NULL; -} - -unsigned PepFile::Resource::itype() const -{ - return current->parent->parent->id; -} - -const upx_byte *PepFile::Resource::ntype() const -{ - return current->parent->parent->name; -} - -unsigned PepFile::Resource::size() const -{ - return ALIGN_UP(current->data.size,4); -} - -unsigned PepFile::Resource::offs() const -{ - return current->data.offset; -} - -unsigned &PepFile::Resource::newoffs() -{ - return current->newoffset; -} - -void PepFile::Resource::dump() const -{ - dump(root,0); -} - -unsigned PepFile::Resource::iname() const -{ - return current->parent->id; -} - -const upx_byte *PepFile::Resource::nname() const -{ - return current->parent->name; -} - -/* - unsigned ilang() const {return current->id;} - const upx_byte *nlang() const {return current->name;} -*/ - -void PepFile::Resource::init(const upx_byte *res) -{ - COMPILE_TIME_ASSERT(sizeof(res_dir_entry) == 8) - COMPILE_TIME_ASSERT(sizeof(res_dir) == 16 + 8) - COMPILE_TIME_ASSERT(sizeof(res_data) == 16) - COMPILE_TIME_ASSERT_ALIGNED1(res_dir_entry) - COMPILE_TIME_ASSERT_ALIGNED1(res_dir) - COMPILE_TIME_ASSERT_ALIGNED1(res_data) - - start = res; - root = head = current = NULL; - dsize = ssize = 0; - check((const res_dir*) start,0); - root = convert(start,NULL,0); -} - -void PepFile::Resource::check(const res_dir *node,unsigned level) -{ - int ic = node->identr + node->namedentr; - if (ic == 0) - return; - for (const res_dir_entry *rde = node->entries; --ic >= 0; rde++) - if (((rde->child & 0x80000000) == 0) ^ (level == 2)) - throwCantPack("unsupported resource structure"); - else if (level != 2) - check((const res_dir*) (start + (rde->child & 0x7fffffff)),level + 1); -} - -PepFile::Resource::upx_rnode *PepFile::Resource::convert(const void *rnode, - upx_rnode *parent, - unsigned level) -{ - if (level == 3) - { - const res_data *node = (const res_data *) rnode; - upx_rleaf *leaf = new upx_rleaf; - leaf->name = NULL; - leaf->parent = parent; - leaf->next = head; - leaf->newoffset = 0; - leaf->data = *node; - - head = leaf; // append node to a linked list for traversal - dsize += sizeof(res_data); - return leaf; - } - - const res_dir *node = (const res_dir *) rnode; - int ic = node->identr + node->namedentr; - if (ic == 0) - return NULL; - - upx_rbranch *branch = new upx_rbranch; - branch->name = NULL; - branch->parent = parent; - branch->nc = ic; - branch->children = new upx_rnode*[ic]; - branch->data = *node; - - for (const res_dir_entry *rde = node->entries + ic - 1; --ic >= 0; rde--) - { - upx_rnode *child = convert(start + (rde->child & 0x7fffffff),branch,level + 1); - xcheck(child); - branch->children[ic] = child; - child->id = rde->tnl; - if (child->id & 0x80000000) - { - const upx_byte *p = start + (child->id & 0x7fffffff); - const unsigned len = 2 + 2 * get_le16(p); - child->name = new upx_byte[len]; - memcpy(child->name,p,len); // copy unicode string - ssize += len; // size of unicode strings - } - } - dsize += node->Sizeof(); - return branch; -} - -void PepFile::Resource::build(const upx_rnode *node, unsigned &bpos, - unsigned &spos, unsigned level) -{ - if (level == 3) - { - res_data *l = (res_data*) (newstart + bpos); - const upx_rleaf *leaf = (const upx_rleaf*) node; - *l = leaf->data; - if (leaf->newoffset) - l->offset = leaf->newoffset; - bpos += sizeof(*l); - return; - } - res_dir * const b = (res_dir*) (newstart + bpos); - const upx_rbranch *branch = (const upx_rbranch*) node; - *b = branch->data; - bpos += b->Sizeof(); - res_dir_entry *be = b->entries; - for (unsigned ic = 0; ic < branch->nc; ic++, be++) - { - be->tnl = branch->children[ic]->id; - be->child = bpos + ((level < 2) ? 0x80000000 : 0); - - const upx_byte *p; - if ((p = branch->children[ic]->name) != 0) - { - be->tnl = spos + 0x80000000; - memcpy(newstart + spos,p,get_le16(p) * 2 + 2); - spos += get_le16(p) * 2 + 2; - } - - build(branch->children[ic],bpos,spos,level + 1); - } -} - -upx_byte *PepFile::Resource::build() -{ - newstart = new upx_byte [dirsize()]; - unsigned bpos = 0,spos = dsize; - build(root,bpos,spos,0); - - // dirsize() is 4 bytes aligned, so we may need to zero - // up to 2 bytes to make valgrind happy - while (spos < dirsize()) - newstart[spos++] = 0; - - return newstart; -} - -void PepFile::Resource::destroy(upx_rnode *node,unsigned level) -{ - xcheck(node); - delete [] node->name; node->name = NULL; - if (level != 3) - { - upx_rbranch * const branch = (upx_rbranch *) node; - for (int ic = branch->nc; --ic >= 0; ) - destroy(branch->children[ic],level + 1); - delete [] branch->children; branch->children = NULL; - } - delete node; -} - -static void lame_print_unicode(const upx_byte *p) -{ - for (unsigned ic = 0; ic < get_le16(p); ic++) - printf("%c",(char)p[ic * 2 + 2]); -} - -void PepFile::Resource::dump(const upx_rnode *node,unsigned level) const -{ - if (level) - { - for (unsigned ic = 1; ic < level; ic++) - printf("\t\t"); - if (node->name) - lame_print_unicode(node->name); - else - printf("0x%x",node->id); - printf("\n"); - } - if (level == 3) - return; - const upx_rbranch * const branch = (const upx_rbranch *) node; - for (unsigned ic = 0; ic < branch->nc; ic++) - dump(branch->children[ic],level + 1); -} - -void PepFile::Resource::clear(upx_byte *node,unsigned level,Interval *iv) -{ - if (level == 3) - iv->add(node,sizeof (res_data)); - else - { - const res_dir * const rd = (res_dir*) node; - const unsigned n = rd->identr + rd->namedentr; - const res_dir_entry *rde = rd->entries; - for (unsigned ic = 0; ic < n; ic++, rde++) - clear(newstart + (rde->child & 0x7fffffff),level + 1,iv); - iv->add(rd,rd->Sizeof()); - } -} - -bool PepFile::Resource::clear() -{ - newstart = const_cast (start); - Interval iv(newstart); - clear(newstart,0,&iv); - iv.flatten(); - if (iv.ivnum == 1) - iv.clear(); -#if defined(DEBUG) - if (opt->verbose > 3) - iv.dump(); -#endif - return iv.ivnum == 1; -} - -void PepFile::processResources(Resource *res,unsigned newaddr) -{ - if (IDSIZE(PEDIR_RESOURCE) == 0) - return; - while (res->next()) - if (res->newoffs()) - res->newoffs() += newaddr; - upx_byte *p = res->build(); - memcpy(oresources,p,res->dirsize()); - delete [] p; -} - -static bool match(unsigned itype, const unsigned char *ntype, - unsigned iname, const unsigned char *nname, - const char *keep) -{ - // format of string keep: type1[/name1],type2[/name2], .... - // typex and namex can be string or number - // hopefully resource names do not have '/' or ',' characters inside - - struct helper - { - static bool match(unsigned num, const unsigned char *unistr, - const char *mkeep) - { - if (!unistr) - return (unsigned) atoi(mkeep) == num; - - unsigned ic; - for (ic = 0; ic < get_le16(unistr); ic++) - if (unistr[2 + ic * 2] != (unsigned char) mkeep[ic]) - return false; - return mkeep[ic] == 0 || mkeep[ic] == ',' || mkeep[ic] == '/'; - } - }; - - // FIXME this comparison is not too exact - while (1) - { - char const *delim1 = strchr(keep, '/'); - char const *delim2 = strchr(keep, ','); - if (helper::match(itype, ntype, keep)) - { - if (!delim1) - return true; - if (delim2 && delim2 < delim1) - return true; - if (helper::match(iname, nname, delim1 + 1)) - return true; - } - - if (delim2 == NULL) - break; - keep = delim2 + 1; - } - return false; -} - -void PepFile::processResources(Resource *res) -{ - const unsigned vaddr = IDADDR(PEDIR_RESOURCE); - if ((soresources = IDSIZE(PEDIR_RESOURCE)) == 0) - return; - - // setup default options for resource compression - if (opt->win32_pe.compress_resources < 0) - opt->win32_pe.compress_resources = true; - if (!opt->win32_pe.compress_resources) - { - opt->win32_pe.compress_icons = false; - for (int i = 0; i < RT_LAST; i++) - opt->win32_pe.compress_rt[i] = false; - } - if (opt->win32_pe.compress_rt[RT_STRING] < 0) - { - // by default, don't compress RT_STRINGs of screensavers (".scr") - opt->win32_pe.compress_rt[RT_STRING] = true; - if (fn_has_ext(fi->getName(),"scr")) - opt->win32_pe.compress_rt[RT_STRING] = false; - } - - res->init(ibuf + vaddr); - - for (soresources = res->dirsize(); res->next(); soresources += 4 + res->size()) - ; - oresources = new upx_byte[soresources]; - upx_byte *ores = oresources + res->dirsize(); - - char *keep_icons = NULL; // icon ids in the first icon group - unsigned iconsin1stdir = 0; - if (opt->win32_pe.compress_icons == 2) - while (res->next()) // there is no rewind() in Resource - if (res->itype() == RT_GROUP_ICON && iconsin1stdir == 0) - { - iconsin1stdir = get_le16(ibuf + res->offs() + 4); - keep_icons = new char[1 + iconsin1stdir * 9]; - *keep_icons = 0; - for (unsigned ic = 0; ic < iconsin1stdir; ic++) - upx_snprintf(keep_icons + strlen(keep_icons), 9, "3/%u,", - get_le16(ibuf + res->offs() + 6 + ic * 14 + 12)); - if (*keep_icons) - keep_icons[strlen(keep_icons) - 1] = 0; - } - - // the icon id which should not be compressed when compress_icons == 1 - unsigned first_icon_id = (unsigned) -1; - if (opt->win32_pe.compress_icons == 1) - while (res->next()) - if (res->itype() == RT_GROUP_ICON && first_icon_id == (unsigned) -1) - first_icon_id = get_le16(ibuf + res->offs() + 6 + 12); - - bool compress_icon = opt->win32_pe.compress_icons > 1; - bool compress_idir = opt->win32_pe.compress_icons == 3; - - // some statistics - unsigned usize = 0; - unsigned csize = 0; - unsigned unum = 0; - unsigned cnum = 0; - - while (res->next()) - { - const unsigned rtype = res->itype(); - bool do_compress = true; - if (!opt->win32_pe.compress_resources) - do_compress = false; - else if (rtype == RT_ICON) // icon - { - if (opt->win32_pe.compress_icons == 0) - do_compress = false; - else if (opt->win32_pe.compress_icons == 1) - if ((first_icon_id == (unsigned) -1 - || first_icon_id == res->iname())) - do_compress = compress_icon; - } - else if (rtype == RT_GROUP_ICON) // icon directory - do_compress = compress_idir && opt->win32_pe.compress_icons; - else if (rtype > 0 && rtype < RT_LAST) - do_compress = opt->win32_pe.compress_rt[rtype] ? true : false; - - if (keep_icons) - do_compress &= !match(res->itype(), res->ntype(), res->iname(), - res->nname(), keep_icons); - do_compress &= !match(res->itype(), res->ntype(), res->iname(), - res->nname(), "TYPELIB,REGISTRY,16"); - do_compress &= !match(res->itype(), res->ntype(), res->iname(), - res->nname(), opt->win32_pe.keep_resource); - - if (do_compress) - { - csize += res->size(); - cnum++; - continue; - } - - usize += res->size(); - unum++; - - 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); - if (rtype == RT_ICON && opt->win32_pe.compress_icons == 1) - compress_icon = true; - else if (rtype == RT_GROUP_ICON) - { - if (opt->win32_pe.compress_icons == 1) - { - icondir_offset = 4 + ptr_diff(ores,oresources); - icondir_count = get_le16(oresources + icondir_offset); - set_le16(oresources + icondir_offset,1); - } - compress_idir = true; - } - ores += res->size(); - } - soresources = ptr_diff(ores,oresources); - - delete[] keep_icons; - if (!res->clear()) - { - // The area occupied by the resource directory is not continuous - // so to still support uncompression, I can't zero this area. - // This decreases compression ratio, so FIXME somehow. - infoWarning("can't remove unneeded resource directory"); - } - info("Resources: compressed %u (%u bytes), not compressed %u (%u bytes)",cnum,csize,unum,usize); -} - - -unsigned PepFile::virta2objnum(unsigned addr,pe_section_t *sect,unsigned objs) -{ - unsigned ic; - for (ic = 0; ic < objs; ic++) - { - if (sect->vaddr <= addr && sect->vaddr + sect->vsize > addr) - return ic; - sect++; - } - //throwCantPack("virta2objnum() failed"); - return ic; -} - - -unsigned PepFile::tryremove (unsigned vaddr,unsigned objs) -{ - unsigned ic = virta2objnum(vaddr,isection,objs); - if (ic && ic == objs - 1) - { - //fprintf(stderr,"removed section: %d size: %lx\n",ic,(long)isection[ic].size); - info("removed section: %d size: 0x%lx",ic,(long)isection[ic].size); - objs--; - } - return objs; -} - - -unsigned PepFile::stripDebug(unsigned overlaystart) -{ - if (IDADDR(PEDIR_DEBUG) == 0) - return overlaystart; - - __packed_struct(debug_dir_t) - char _[16]; // flags, time/date, version, type - LE32 size; - char __[4]; // rva - LE32 fpos; - __packed_struct_end() - - COMPILE_TIME_ASSERT(sizeof(debug_dir_t) == 28) - COMPILE_TIME_ASSERT_ALIGNED1(debug_dir_t) - COMPILE_TIME_ASSERT(sizeof(((debug_dir_t*)0)->_) == 16) - COMPILE_TIME_ASSERT(sizeof(((debug_dir_t*)0)->__) == 4) - - const debug_dir_t *dd = (const debug_dir_t*) (ibuf + IDADDR(PEDIR_DEBUG)); - for (unsigned ic = 0; ic < IDSIZE(PEDIR_DEBUG) / sizeof(debug_dir_t); ic++, dd++) - if (overlaystart == dd->fpos) - overlaystart += dd->size; - ibuf.fill(IDADDR(PEDIR_DEBUG), IDSIZE(PEDIR_DEBUG), FILLVAL); - return overlaystart; -} - - -/************************************************************************* -// pack -**************************************************************************/ - - -/************************************************************************* -// unpack -**************************************************************************/ - -void PepFile::rebuildRelocs(upx_byte *& extrainfo) -{ - if (!ODADDR(PEDIR_RELOC) || !ODSIZE(PEDIR_RELOC) || (oh.flags & RELOCS_STRIPPED)) - return; - - if (ODSIZE(PEDIR_RELOC) == 8) // some tricky dlls use this - { - omemcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin, "\x0\x0\x0\x0\x8\x0\x0\x0", 8); - return; - } - - upx_byte *rdata = obuf + get_le32(extrainfo); - const upx_byte big = extrainfo[4]; - extrainfo += 5; - -// upx_byte *p = rdata; - OPTR_I(upx_byte, p, rdata); - MemBuffer wrkmem; - unsigned relocn = unoptimizeReloc64(&rdata,obuf,&wrkmem,1); - unsigned r16 = 0; - if (big & 6) // 16 bit relocations - { - const LE32 *q = (LE32*) rdata; - while (*q++) - r16++; - if ((big & 6) == 6) - while (*++q) - r16++; - } - Reloc rel(relocn + r16); - - if (big & 6) - { - LE32 *q = (LE32*) rdata; - while (*q) - rel.add(*q++ + rvamin,(big & 4) ? 2 : 1); - if ((big & 6) == 6) - while (*++q) - rel.add(*q + rvamin,1); - rdata = (upx_byte*) q; - } - - //memset(p,0,rdata - p); - - for (unsigned ic = 0; ic < relocn; ic++) - { - p = obuf + get_le32(wrkmem + 4 * ic); - set_le64(p, get_le64((unsigned char *)p) + oh.imagebase + rvamin); - rel.add(rvamin + get_le32(wrkmem + 4 * ic),10); - } - rel.finish (oxrelocs,soxrelocs); - - if (opt->win32_pe.strip_relocs && !isdll) - { - obuf.clear(ODADDR(PEDIR_RELOC) - rvamin, ODSIZE(PEDIR_RELOC)); - ODADDR(PEDIR_RELOC) = 0; - soxrelocs = 0; - // FIXME: try to remove the original relocation section somehow - } - else - omemcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs); - delete [] oxrelocs; oxrelocs = NULL; - wrkmem.dealloc(); - - ODSIZE(PEDIR_RELOC) = soxrelocs; -} - -void PepFile::rebuildExports() -{ - if (ODSIZE(PEDIR_EXPORT) == 0 || ODADDR(PEDIR_EXPORT) == IDADDR(PEDIR_EXPORT)) - return; // nothing to do - - opt->win32_pe.compress_exports = 0; - Export xport((char*)(unsigned char*) ibuf - isection[2].vaddr); - processExports(&xport); - processExports(&xport,ODADDR(PEDIR_EXPORT)); - omemcpy(obuf + ODADDR(PEDIR_EXPORT) - rvamin,oexport,soexport); -} - -void PepFile::rebuildTls() -{ - // this is an easy one : just do nothing ;-) -} - -void PepFile::rebuildResources(upx_byte *& extrainfo) -{ - if (ODSIZE(PEDIR_RESOURCE) == 0 || IDSIZE(PEDIR_RESOURCE) == 0) - return; - - icondir_count = get_le16(extrainfo); - extrainfo += 2; - - const unsigned vaddr = IDADDR(PEDIR_RESOURCE); - const upx_byte *r = ibuf - isection[ih.objects - 1].vaddr; - Resource res(r + vaddr); - while (res.next()) - if (res.offs() > vaddr) - { - unsigned origoffs = get_le32(r + res.offs() - 4); - res.newoffs() = origoffs; - 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); - icondir_count = 0; - } - } - upx_byte *p = res.build(); - OCHECK(obuf + ODADDR(PEDIR_RESOURCE) - rvamin, 16); - // write back when the original is zeroed - if (get_le32(obuf + ODADDR(PEDIR_RESOURCE) - rvamin + 12) == 0) - omemcpy(obuf + ODADDR(PEDIR_RESOURCE) - rvamin,p,res.dirsize()); - delete [] p; -} - -void PepFile::unpack(OutputFile *fo) -{ - //infoHeader("[Processing %s, format %s, %d sections]", fn_basename(fi->getName()), getName(), objs); - - handleStub(fi,fo,pe_offset); - - const unsigned iobjs = ih.objects; - const unsigned overlay = file_size - ALIGN_UP(isection[iobjs - 1].rawdataptr - + isection[iobjs - 1].size, - ih.filealign); - checkOverlay(overlay); - - ibuf.alloc(ph.c_len); - obuf.allocForUncompression(ph.u_len); - fi->seek(isection[1].rawdataptr - 64 + ph.buf_offset + ph.getPackHeaderSize(),SEEK_SET); - fi->readx(ibuf,ph.c_len); - - // decompress - decompress(ibuf,obuf); - upx_byte *extrainfo = obuf + get_le32(obuf + ph.u_len - 4); - //upx_byte * const eistart = extrainfo; - - memcpy(&oh, extrainfo, sizeof (oh)); - extrainfo += sizeof (oh); - unsigned objs = oh.objects; - - if ((int) objs <= 0) - throwCantUnpack("unexpected value in the PE header"); - Array(pe_section_t, osection, objs); - memcpy(osection,extrainfo,sizeof(pe_section_t) * objs); - rvamin = osection[0].vaddr; - extrainfo += sizeof(pe_section_t) * objs; - - // read the noncompressed section - ibuf.dealloc(); - ibuf.alloc(isection[2].size); - fi->seek(isection[2].rawdataptr,SEEK_SET); - fi->readx(ibuf,isection[2].size); - - // unfilter - if (ph.filter) - { - Filter ft(ph.level); - ft.init(ph.filter,oh.codebase - rvamin); - ft.cto = (unsigned char) ph.filter_cto; - OCHECK(obuf + oh.codebase - rvamin, oh.codesize); - ft.unfilter(obuf + oh.codebase - rvamin, oh.codesize); - } - - rebuildImports(extrainfo); - rebuildRelocs(extrainfo); - rebuildTls(); - rebuildExports(); - - if (iobjs == 4) - { - // read the resource section if present - ibuf.dealloc(); - ibuf.alloc(isection[3].size); - fi->seek(isection[3].rawdataptr,SEEK_SET); - fi->readx(ibuf,isection[3].size); - } - - rebuildResources(extrainfo); - - //FIXME: this does bad things if the relocation section got removed - // during compression ... - //memset(eistart,0,extrainfo - eistart + 4); - - // fill the data directory - ODADDR(PEDIR_DEBUG) = 0; - ODSIZE(PEDIR_DEBUG) = 0; - ODADDR(PEDIR_IAT) = 0; - ODSIZE(PEDIR_IAT) = 0; - ODADDR(PEDIR_BOUNDIM) = 0; - ODSIZE(PEDIR_BOUNDIM) = 0; - - // oh.headersize = osection[0].rawdataptr; - // oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(pe_section_t) * objs, oh.filealign); - oh.headersize = rvamin; - oh.chksum = 0; - - //NEW: disable reloc stripping if ASLR is enabled - if(ih.dllflags & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE) - opt->win32_pe.strip_relocs = false; - - // FIXME: ih.flags is checked here because of a bug in UPX 0.92 - if ((opt->win32_pe.strip_relocs && !isdll) || (ih.flags & RELOCS_STRIPPED)) - { - oh.flags |= RELOCS_STRIPPED; - ODADDR(PEDIR_RELOC) = 0; - ODSIZE(PEDIR_RELOC) = 0; - } - - // write decompressed file - if (fo) - { - unsigned ic; - for (ic = 0; ic < objs && osection[ic].rawdataptr == 0; ic++) - ; - - ibuf.dealloc(); - ibuf.alloc(osection[ic].rawdataptr); - ibuf.clear(); - infoHeader("[Writing uncompressed file]"); - - // write loader + compressed file - fo->write(&oh,sizeof(oh)); - fo->write(osection,objs * sizeof(pe_section_t)); - fo->write(ibuf,osection[ic].rawdataptr - fo->getBytesWritten()); - for (ic = 0; ic < objs; ic++) - if (osection[ic].rawdataptr) - fo->write(obuf + osection[ic].vaddr - rvamin,ALIGN_UP(osection[ic].size,oh.filealign)); - copyOverlay(fo, overlay, &obuf); - } - ibuf.dealloc(); -} - -/* - extra info added to help uncompression: - - - - - optional \ - - opt / - - optional \ - - optional / - - optional - -*/ - -#endif -/* -vi:ts=4:et -*/ - diff --git a/src/pepfile.h b/src/pepfile.h deleted file mode 100644 index 2bca0129..00000000 --- a/src/pepfile.h +++ /dev/null @@ -1,387 +0,0 @@ -/* pepfile.h -- - - This file is part of the UPX executable compressor. - - Copyright (C) 1996-2013 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996-2013 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 - - - ------------------------------------------------------------------- - - PE+ format extension changes (C) 2010 Stefan Widmann - changes in: - - pe_header_t - */ - - -#ifndef __UPX_PEPFILE_H -#define __UPX_PEPFILE_H 1 - -#if 0 -/************************************************************************* -// general/pe handling -**************************************************************************/ - -class PepFile : public Packer -{ - typedef Packer super; -protected: - class Interval; - class Reloc; - class Resource; - class Export; - - PepFile(InputFile *f); - virtual ~PepFile(); - virtual int getVersion() const { return 13; } - - virtual void unpack(OutputFile *fo); - - // unpacker capabilities - virtual bool canUnpackVersion(int version) const - { return (version >= 12 && version <= 13); } - -protected: - virtual int readFileHeader(); - virtual bool testUnpackVersion(int version) const; - - unsigned pe_offset; - - virtual unsigned processImports() = 0; - virtual void processImports(unsigned, unsigned) = 0; - virtual void rebuildImports(upx_byte *&) = 0; - upx_byte *oimport; - unsigned soimport; - upx_byte *oimpdlls; - unsigned soimpdlls; - - void processRelocs(); - void processRelocs(Reloc *); - void rebuildRelocs(upx_byte *&); - upx_byte *orelocs; - unsigned sorelocs; - upx_byte *oxrelocs; - unsigned soxrelocs; - - void processExports(Export *); - void processExports(Export *,unsigned); - void rebuildExports(); - upx_byte *oexport; - unsigned soexport; - - void processResources(Resource *); - void processResources(Resource *, unsigned); - void rebuildResources(upx_byte *&); - upx_byte *oresources; - unsigned soresources; - - // virtual void processTls(Interval *); - // void processTls(Reloc *, const Interval *, unsigned); - void rebuildTls(); - upx_byte *otls; - unsigned sotls; - unsigned tlsindex; - - unsigned stripDebug(unsigned); - - unsigned icondir_offset; - int icondir_count; - - bool importbyordinal; - bool kernel32ordinal; - unsigned rvamin; - unsigned cimports; // rva of preprocessed imports - unsigned crelocs; // rva of preprocessed fixups - int big_relocs; - - __packed_struct(pe_header_t) - // 0x0 - char _[4]; // pemagic - LE16 cpu; - LE16 objects; // number of sections - char __[12]; // timestamp + reserved - LE16 opthdrsize; - LE16 flags; // characteristics - // optional header - LE16 coffmagic; // NEW: Stefan Widmann - char ___[2]; // linkerversion - LE32 codesize; - // 0x20 - LE32 datasize; - LE32 bsssize; - LE32 entry; // still a 32 bit RVA - LE32 codebase; - // 0x30 - //LE32 database; // field does not exist in PE+! - // nt specific fields - LE64 imagebase; // LE32 -> LE64 - Stefan Widmann standard is 0x0000000140000000 - LE32 objectalign; - LE32 filealign; // should set to 0x200 ? - // 0x40 - char ____[16]; // versions - // 0x50 - LE32 imagesize; - LE32 headersize; - LE32 chksum; // should set to 0 - LE16 subsystem; - LE16 dllflags; - // 0x60 - char _____[36]; // stack + heap sizes + loader flag - // 0x84 - LE32 ddirsentries; // usually 16 - - __packed_struct(ddirs_t) - LE32 vaddr; // dir RVAs and sizes are still 32 bit - LE32 size; - __packed_struct_end() - - ddirs_t ddirs[16]; - __packed_struct_end() - - __packed_struct(pe_section_t) // no change in section description structures - char name[8]; - LE32 vsize; - LE32 vaddr; - LE32 size; - LE32 rawdataptr; - char _[12]; - LE32 flags; - __packed_struct_end() - - pe_header_t ih, oh; - pe_section_t *isection; - - static unsigned virta2objnum (unsigned, pe_section_t *, unsigned); - unsigned tryremove (unsigned, unsigned); - - enum { - PEDIR_EXPORT = 0, - PEDIR_IMPORT = 1, - PEDIR_RESOURCE = 2, - PEDIR_EXCEPTION = 3, // Exception table - PEDIR_SEC = 4, // Certificate table (file pointer) - PEDIR_RELOC = 5, - PEDIR_DEBUG = 6, - PEDIR_COPYRIGHT = 7, // Architecture-specific data - PEDIR_GLOBALPTR = 8, // Global pointer - PEDIR_TLS = 9, - PEDIR_LOADCONF = 10, // Load Config Table - PEDIR_BOUNDIM = 11, - PEDIR_IAT = 12, - PEDIR_DELAYIMP = 13, // Delay Import Descriptor - PEDIR_COMRT = 14 // Com+ Runtime Header - }; - - enum { - PEFL_CODE = 0x20, - PEFL_DATA = 0x40, - PEFL_BSS = 0x80, - PEFL_INFO = 0x200, - PEFL_EXTRELS = 0x01000000, // extended relocations - PEFL_DISCARD = 0x02000000, - PEFL_NOCACHE = 0x04000000, - PEFL_NOPAGE = 0x08000000, - PEFL_SHARED = 0x10000000, - PEFL_EXEC = 0x20000000, - PEFL_READ = 0x40000000, - PEFL_WRITE = 0x80000000 - }; - - enum { - RELOCS_STRIPPED = 0x0001, - EXECUTABLE = 0x0002, - LNUM_STRIPPED = 0x0004, - LSYMS_STRIPPED = 0x0008, - AGGRESSIVE_TRIM = 0x0010, - TWO_GIGS_AWARE = 0x0020, - FLITTLE_ENDIAN = 0x0080, - BITS_32_MACHINE = 0x0100, - DEBUG_STRIPPED = 0x0200, - REMOVABLE_SWAP = 0x0400, - SYSTEM_PROGRAM = 0x1000, - DLL_FLAG = 0x2000, - FBIG_ENDIAN = 0x8000 - }; - - //NEW: DLL characteristics definition for ASLR, ... - Stefan Widmann - enum { - IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040, - IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080, - IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, - IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200, - IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400, - IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800, - IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000, - IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 - }; - - // predefined resource types - enum { - RT_CURSOR = 1, RT_BITMAP, RT_ICON, RT_MENU, RT_DIALOG, RT_STRING, - RT_FONTDIR, RT_FONT, RT_ACCELERATOR, RT_RCDATA, RT_MESSAGETABLE, - RT_GROUP_CURSOR, RT_GROUP_ICON = 14, RT_VERSION = 16, RT_DLGINCLUDE, - RT_PLUGPLAY = 19, RT_VXD, RT_ANICURSOR, RT_ANIICON, RT_HTML, - RT_MANIFEST, RT_LAST - }; - - class Interval : private noncopyable - { - unsigned capacity; - void *base; - public: - struct interval - { - unsigned start, len; - } *ivarr; - - unsigned ivnum; - - Interval(void *b); - ~Interval(); - - void add(unsigned start,unsigned len); - void add(const void *start,unsigned len); - void add(const void *start,const void *end); - void add(const Interval *iv); - void flatten(); - - void clear(); - void dump() const; - - private: - static int __acc_cdecl_qsort compare(const void *p1,const void *p2); - }; - - class Reloc : private noncopyable - { - upx_byte *start; - unsigned size; - - void newRelocPos(void *p); - - struct reloc; - reloc *rel; - LE16 *rel1; - unsigned counts[16]; - - public: - Reloc(upx_byte *,unsigned); - Reloc(unsigned rnum); - // - bool next(unsigned &pos,unsigned &type); - const unsigned *getcounts() const { return counts; } - // - void add(unsigned pos,unsigned type); - void finish(upx_byte *&p,unsigned &size); - }; - - class Resource : private noncopyable - { - struct res_dir_entry; - struct res_dir; - struct res_data; - struct upx_rnode; - struct upx_rbranch; - struct upx_rleaf; - - const upx_byte *start; - upx_byte *newstart; - upx_rnode *root; - upx_rleaf *head; - upx_rleaf *current; - unsigned dsize; - unsigned ssize; - - void check(const res_dir*,unsigned); - upx_rnode *convert(const void *,upx_rnode *,unsigned); - void build(const upx_rnode *,unsigned &,unsigned &,unsigned); - void clear(upx_byte *,unsigned,Interval *); - void dump(const upx_rnode *,unsigned) const; - void destroy(upx_rnode *urd,unsigned level); - - public: - Resource(); - Resource(const upx_byte *p); - ~Resource(); - void init(const upx_byte *); - - unsigned dirsize() const; - bool next(); - - unsigned itype() const; - const upx_byte *ntype() const; - unsigned size() const; - unsigned offs() const; - unsigned &newoffs(); - - upx_byte *build(); - bool clear(); - - void dump() const; - unsigned iname() const; - const upx_byte *nname() const; - /* - unsigned ilang() const {return current->id;} - const upx_byte *nlang() const {return current->name;} - */ - }; - - class Export : private noncopyable - { - __packed_struct(export_dir_t) - char _[12]; // flags, timedate, version - LE32 name; - char __[4]; // ordinal base - LE32 functions; - LE32 names; - LE32 addrtable; - LE32 nameptrtable; - LE32 ordinaltable; - __packed_struct_end() - - export_dir_t edir; - char *ename; - char *functionptrs; - char *ordinals; - char **names; - - char *base; - unsigned size; - Interval iv; - - public: - Export(char *_base); - ~Export(); - - void convert(unsigned eoffs,unsigned esize); - void build(char *base,unsigned newoffs); - unsigned getsize() const { return size; } - }; - -}; - -#endif -#endif /* already included */ - - -/* -vi:ts=4:et -*/