diff --git a/src/p_armpe.cpp b/src/p_armpe.cpp index 9c245e33..de8b39cc 100644 --- a/src/p_armpe.cpp +++ b/src/p_armpe.cpp @@ -160,6 +160,7 @@ PackArmPe::PackArmPe(InputFile *f) : super(f) big_relocs = 0; sorelocs = 0; soxrelocs = 0; + use_thumb_stub = false; } @@ -181,8 +182,13 @@ const int *PackArmPe::getCompressionMethods(int method, int level) const { static const int m_nrv2b[] = { M_NRV2B_8, M_NRV2E_8, -1 }; static const int m_nrv2e[] = { M_NRV2E_8, M_NRV2B_8, -1 }; + static const int m_nrv2e_v4[] = { M_NRV2E_8, -1 }; UNUSED(level); + // FIXME this when we have v4 mode nrv2b + if (!use_thumb_stub) + return m_nrv2e_v4; + if (M_IS_NRV2B(method)) return m_nrv2b; if (M_IS_NRV2E(method)) @@ -348,7 +354,7 @@ void Interval::dump() const /************************************************************************* // relocation handling **************************************************************************/ -#if 0 + class Reloc { upx_byte *start; @@ -513,7 +519,7 @@ void PackArmPe::processRelocs() // pass1 delete [] fix[3]; info("Relocations: original size: %u bytes, preprocessed size: %u bytes",(unsigned) IDSIZE(PEDIR_RELOC),sorelocs); } -#endif + /************************************************************************* // import handling @@ -806,7 +812,6 @@ unsigned PackArmPe::processImports() // pass 1 /************************************************************************* // export handling **************************************************************************/ -#if 0 class Export { struct export_dir_t @@ -1013,6 +1018,9 @@ void PackArmPe::processTls(Interval *iv) // pass 1 if ((sotls = ALIGN_UP(IDSIZE(PEDIR_TLS),4)) == 0) return; + // never should happen on wince + throwCantPack("Static TLS entries found. Send a report please."); + const tls * const tlsp = (const tls*) (ibuf + IDADDR(PEDIR_TLS)); // note: TLS callbacks are not implemented in Windows 95/98/ME if (tlsp->callbacks) @@ -1080,7 +1088,6 @@ void PackArmPe::processTls(Reloc *rel,const Interval *iv,unsigned newaddr) // pa tlsp->dataend = newaddr + sotls + ih.imagebase; tlsp->callbacks = 0; // note: TLS callbacks are not implemented in Windows 95/98/ME } -#endif /************************************************************************* // resource handling @@ -1536,6 +1543,7 @@ bool PackArmPe::canPack() { if (!readFileHeader() || (ih.cpu != 0x1c0 && ih.cpu != 0x1c2)) return false; + use_thumb_stub |= ih.cpu == 0x1c2; return true; } @@ -1545,10 +1553,18 @@ int PackArmPe::buildLoader(const Filter *ft) UNUSED(ft); // prepare loader initLoader(nrv_loader, sizeof(nrv_loader), -1, 2); - if (ph.method == M_NRV2E_8) - addLoader("ARMWPE2E", NULL); - else if (ph.method == M_NRV2B_8) - addLoader("ARMWPE2B", NULL); + if (use_thumb_stub) + { + if (ph.method == M_NRV2E_8) + addLoader("ARMWPE2E", NULL); + else if (ph.method == M_NRV2B_8) + addLoader("ARMWPE2B", NULL); + } + else if (!isdll) + addLoader("ARMWPE2EV4", NULL); // FIXME this when we have v4 mode nrv2b + else + addLoader("ARMWPE2EV4DLL", NULL); + addLoader("IDENTSTR,UPX1HEAD", NULL); return getLoaderSize(); } @@ -1572,7 +1588,7 @@ void PackArmPe::pack(OutputFile *fo) || (ih.opthdrsize != 0xe0) || ((ih.flags & EXECUTABLE) == 0) || (ih.subsystem != 9) - || (ih.entry == 0 && !isdll) + || (ih.entry == 0 /*&& !isdll*/) || (ih.ddirsentries != 16) // || IDSIZE(PEDIR_EXCEPTION) // is this used on arm? // || IDSIZE(PEDIR_COPYRIGHT) @@ -1585,23 +1601,14 @@ void PackArmPe::pack(OutputFile *fo) if (IDSIZE(PEDIR_COMRT)) throwCantPack(".NET files (win32/net) are not yet supported"); -#if 1 - if (IDSIZE(PEDIR_EXPORT)) - IDSIZE(PEDIR_EXPORT) = IDADDR(PEDIR_EXPORT) = 0; -#else - if (IDSIZE(PEDIR_EXPORT)) - throwCantPack("exports not yet supported"); -#endif - if (IDSIZE(PEDIR_RELOC)) - throwCantPack("relocations 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 >= 0x400000); + opt->win32_pe.strip_relocs = (ih.imagebase >= 0x10000); if (opt->win32_pe.strip_relocs) - if (ih.imagebase < 0x400000) - throwCantPack("--strip-relocs is not allowed when imagebase < 0x400000"); + if (ih.imagebase < 0x10000) + throwCantPack("--strip-relocs is not allowed when imagebase < 0x10000"); else ih.flags |= RELOCS_STRIPPED; @@ -1680,13 +1687,13 @@ void PackArmPe::pack(OutputFile *fo) Resource res; Interval tlsiv(ibuf); - //Export xport((char*)(unsigned char*)ibuf); + Export xport((char*)(unsigned char*)ibuf); const unsigned dllstrings = processImports(); - //processTls(&tlsiv); // call before processRelocs!! + processTls(&tlsiv); // call before processRelocs!! processResources(&res); - //processExports(&xport); - //processRelocs(); + processExports(&xport); + processRelocs(); //OutputFile::dump("x1", ibuf, usize); @@ -1800,9 +1807,15 @@ void PackArmPe::pack(OutputFile *fo) const unsigned ncsection = (s1addr + s1size + oam1) &~ oam1; const unsigned upxsection = s1addr + ic + clen; - const unsigned myimport = ncsection + soresources - rvamin; + + // FIXME + const unsigned assumed_soxrelocs = isdll ? 0x18 : 0; + const unsigned myimport = ncsection + assumed_soxrelocs + soresources - rvamin; + + const int src0_offset = find(loader, lsize, "SRC0", 4); // patch loader + patch_le32(loader, codesize, "BREL", crelocs + rvamin + ih.imagebase); patch_le32(loader, codesize, "ENTR", ih.entry + ih.imagebase); patch_le32(loader, codesize, "LOAD", ih.imagebase + rvamin + myimport + get_le32(oimpdlls + 16)); patch_le32(loader, codesize, "GETP", ih.imagebase + rvamin + myimport + get_le32(oimpdlls + 16) + 4); @@ -1811,7 +1824,8 @@ void PackArmPe::pack(OutputFile *fo) patch_le32(loader, codesize, "DSTL", ph.u_len); patch_le32(loader, codesize, "DST0", ih.imagebase + rvamin); patch_le32(loader, codesize, "SRCL", ph.c_len); - patch_le32(loader, codesize, "SRC0", ih.imagebase + s1addr + ic); + patch_le32(loader, codesize, "SRC0", ih.imagebase + s1addr + identsize - identsplit); + #if 0 if (ih.entry) { @@ -1861,10 +1875,16 @@ void PackArmPe::pack(OutputFile *fo) const unsigned esi0 = s1addr + ic; patch_le32(loader,codesize,"EDI0", 0u - esi0 + rvamin); patch_le32(loader,codesize,"ESI0", esi0 + ih.imagebase); - ic = getLoaderSection("PEMAIN01") + 2 + upxsection; #endif - //Reloc rel(1024); // new relocations are put here - //rel.add(ic,3); + Reloc rel(1024); // new relocations are put here + rel.add(upxsection + src0_offset, 3); + rel.add(upxsection + src0_offset + 8, 3); + rel.add(upxsection + src0_offset + 16, 3); + rel.add(upxsection + src0_offset + 20, 3); + rel.add(upxsection + src0_offset + 24, 3); + rel.add(upxsection + src0_offset + 28, 3); + rel.add(upxsection + src0_offset + 32, 3); + rel.add(upxsection + src0_offset + 36, 3); // new PE header memcpy(&oh,&ih,sizeof(oh)); @@ -1886,7 +1906,7 @@ void PackArmPe::pack(OutputFile *fo) // tls is put into section 1 ic = s1addr + s1size - sotls; - //processTls(&rel,&tlsiv,ic); + processTls(&rel,&tlsiv,ic); ODADDR(PEDIR_TLS) = sotls ? ic : 0; ODSIZE(PEDIR_TLS) = sotls ? 0x18 : 0; ic += sotls; @@ -1894,6 +1914,12 @@ void PackArmPe::pack(OutputFile *fo) // these are put into section 2 ic = ncsection; + + processRelocs(&rel); + ODADDR(PEDIR_RELOC) = soxrelocs ? ic : 0; + ODSIZE(PEDIR_RELOC) = soxrelocs; + ic += soxrelocs; + if (soresources) processResources(&res,ic); ODADDR(PEDIR_RESOURCE) = soresources ? ic : 0; @@ -1905,7 +1931,7 @@ void PackArmPe::pack(OutputFile *fo) ODSIZE(PEDIR_IMPORT) = soimpdlls; ic += soimpdlls; - //processExports(&xport,ic); + processExports(&xport,ic); ODADDR(PEDIR_EXPORT) = soexport ? ic : 0; ODSIZE(PEDIR_EXPORT) = soexport; if (!isdll && opt->win32_pe.compress_exports) @@ -1915,13 +1941,11 @@ void PackArmPe::pack(OutputFile *fo) } ic += soexport; - //processRelocs(&rel); - ODADDR(PEDIR_RELOC) = soxrelocs ? ic : 0; - ODSIZE(PEDIR_RELOC) = soxrelocs; - ic += soxrelocs; + if (isdll && soxrelocs != assumed_soxrelocs) + throwInternalError("FIXME: soxrelocs != assumed_soxrelocs"); // this is computed here, because soxrelocs changes some lines above - const unsigned ncsize = soresources + soimpdlls + soexport + soxrelocs; + const unsigned ncsize = soxrelocs + soresources + soimpdlls + soexport; ic = oh.filealign - 1; // this one is tricky: it seems windoze touches 4 bytes after @@ -2004,10 +2028,10 @@ void PackArmPe::pack(OutputFile *fo) fo->write(otls,sotls); if ((ic = fo->getBytesWritten() & (oh.filealign-1)) != 0) fo->write(ibuf,oh.filealign - ic); + fo->write(oxrelocs,soxrelocs); 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); @@ -2043,11 +2067,379 @@ void PackArmPe::pack(OutputFile *fo) int PackArmPe::canUnpack() { + if (!readFileHeader() || (ih.cpu != 0x1c0 && ih.cpu != 0x1c2)) + return false; + + 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); + if (ih.objects < 3) + return -1; + bool is_packed = (ih.objects == 3 && + (IDSIZE(15) || ih.entry > isection[1].vaddr)); + bool found_ph = false; + if (memcmp(isection[0].name,"UPX",3) == 0) + { + // current version + fi->seek(isection[1].rawdataptr - 64, SEEK_SET); + found_ph = readPackHeader(1024); + if (!found_ph) + { + // old versions + fi->seek(isection[2].rawdataptr, SEEK_SET); + found_ph = readPackHeader(1024); + } + } + if (is_packed && found_ph) + return true; + if (!is_packed && !found_ph) + return -1; + if (is_packed && ih.entry < isection[2].vaddr) + { + unsigned char buf[256]; + bool x = false; + + memset(buf, 0, sizeof(buf)); + try { + fi->seek(ih.entry - isection[1].vaddr + isection[1].rawdataptr, SEEK_SET); + fi->read(buf, sizeof(buf)); + + // FIXME this is for x86 + static const unsigned char magic[] = "\x8b\x1e\x83\xee\xfc\x11\xdb"; + // mov ebx, [esi]; sub esi, -4; adc ebx,ebx + + int offset = find(buf, sizeof(buf), magic, 7); + if (offset >= 0 && find(buf + offset + 1, sizeof(buf) - offset - 1, magic, 7) >= 0) + x = true; + } catch (...) { + //x = true; + } + if (x) + throwCantUnpack("file is modified/hacked/protected; take care!!!"); + else + throwCantUnpack("file is possibly modified/hacked/protected; take care!"); + return false; // not reached + } + + // FIXME: what should we say here ? + //throwCantUnpack("file is possibly modified/hacked/protected; take care!"); return false; } -void PackArmPe::unpack(OutputFile *) + +void PackArmPe::rebuildImports(upx_byte *& extrainfo) { + if (ODADDR(PEDIR_IMPORT) == 0) + return; + +// const upx_byte * const idata = obuf + get_le32(extrainfo); + OPTR_C(const upx_byte, idata, obuf + get_le32(extrainfo)); + const unsigned inamespos = get_le32(extrainfo + 4); + extrainfo += 8; + + unsigned sdllnames = 0; + +// const upx_byte *import = ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr; +// const upx_byte *p; + IPTR_I(const upx_byte, import, ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr); + OPTR(const upx_byte, p); + + for (p = idata; get_le32(p) != 0; ++p) + { + const upx_byte *dname = get_le32(p) + import; + const unsigned dlen = strlen(dname); + ICHECK(dname, dlen + 1); + + sdllnames += dlen + 1; + for (p += 8; *p;) + if (*p == 1) + p += strlen(++p) + 1; + else if (*p == 0xff) + p += 3; // ordinal + else + p += 5; + } + sdllnames = ALIGN_UP(sdllnames,2); + + upx_byte * const Obuf = obuf - rvamin; + import_desc * const im0 = (import_desc*) (Obuf + ODADDR(PEDIR_IMPORT)); + import_desc *im = im0; + upx_byte *dllnames = Obuf + inamespos; + upx_byte *importednames = dllnames + sdllnames; + + for (p = idata; get_le32(p) != 0; ++p) + { + // restore the name of the dll + const upx_byte *dname = get_le32(p) + import; + const unsigned dlen = strlen(dname); + ICHECK(dname, dlen + 1); + + const unsigned iatoffs = get_le32(p + 4) + rvamin; + if (inamespos) + { + // now I rebuild the dll names + OCHECK(dllnames, dlen + 1); + strcpy(dllnames, dname); + im->dllname = ptr_diff(dllnames,Obuf); + //;;;printf("\ndll: %s:",dllnames); + dllnames += dlen + 1; + } + else + { + OCHECK(Obuf + im->dllname, dlen + 1); + strcpy(Obuf + im->dllname, dname); + } + im->oft = im->iat = iatoffs; + +// LE32 *newiat = (LE32 *) (Obuf + iatoffs); + OPTR_I(LE32, newiat, (LE32 *) (Obuf + iatoffs)); + + // restore the imported names+ordinals + for (p += 8; *p; ++newiat) + if (*p == 1) + { + const unsigned ilen = strlen(++p) + 1; + if (inamespos) + { + if (ptr_diff(importednames,oimpdlls) & 1) + importednames -= 1; + omemcpy(importednames + 2, p, ilen); + //;;;printf(" %s",importednames+2); + *newiat = ptr_diff(importednames, Obuf); + importednames += 2 + ilen; + } + else + { + OCHECK(Obuf + *newiat + 2, ilen + 1); + strcpy(Obuf + *newiat + 2, p); + } + p += ilen; + } + else if (*p == 0xff) + { + *newiat = get_le16(p + 1) + 0x80000000; + //;;;printf(" %x",(unsigned)*newiat); + p += 3; + } + else + { + *newiat = get_le32(get_le32(p + 1) + import); + assert(*newiat & 0x80000000); + p += 5; + } + *newiat = 0; + im++; + } + //memset(idata,0,p - idata); +} + +void PackArmPe::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 = unoptimizeReloc32(&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_le32(p, get_le32((unsigned char *)p) + oh.imagebase + rvamin); + rel.add(rvamin + get_le32(wrkmem + 4 * ic),3); + } + 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 PackArmPe::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 PackArmPe::rebuildTls() +{ + // this is an easy one : just do nothing ;-) +} + +void PackArmPe::rebuildResources(upx_byte *& extrainfo) +{ + if (ODSIZE(PEDIR_RESOURCE) == 0) + return; + + icondir_count = get_le16(extrainfo); + extrainfo += 2; + + const unsigned vaddr = IDADDR(PEDIR_RESOURCE); + const upx_byte *r = ibuf - isection[2].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(); + // 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 PackArmPe::unpack(OutputFile *fo) +{ + //infoHeader("[Processing %s, format %s, %d sections]", fn_basename(fi->getName()), getName(), objs); + + handleStub(fi,fo,pe_offset); + + const unsigned overlay = file_size - ALIGN_UP(isection[2].rawdataptr + isection[2].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; + + 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; + ft.unfilter(obuf + oh.codebase - rvamin, oh.codesize); + } + + rebuildImports(extrainfo); + rebuildRelocs(extrainfo); + rebuildTls(); + rebuildExports(); + 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; + + // 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) + { + ibuf.dealloc(); + ibuf.alloc(osection[0].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[0].rawdataptr - fo->getBytesWritten()); + for(unsigned 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(); } diff --git a/src/p_armpe.h b/src/p_armpe.h index 4902a27d..08fc6e03 100644 --- a/src/p_armpe.h +++ b/src/p_armpe.h @@ -37,7 +37,7 @@ class PackArmPe_Export; /************************************************************************* -// w32/pe +// arm/pe **************************************************************************/ class PackArmPe : public Packer @@ -61,7 +61,7 @@ public: // unpacker capabilities virtual bool canUnpackVersion(int version) const - { UNUSED(version); return false; } + { return version == 13; } protected: virtual int readFileHeader(); @@ -118,6 +118,8 @@ protected: unsigned crelocs; // rva of preprocessed fixups int big_relocs; + bool use_thumb_stub; + struct pe_header_t { // 0x0 diff --git a/src/stub/Makefile b/src/stub/Makefile index bbe7e913..c8d19464 100644 --- a/src/stub/Makefile +++ b/src/stub/Makefile @@ -224,8 +224,9 @@ GCC_AMD64 += -Wall -W -Wcast-align -Wcast-qual -Wwrite-strings -Werror ### ARM-PE-WINCE ### -GCC_ARM := arm-9tdmi-linux-gnu-gcc -march=armv4t -nostdinc -MMD +GCC_ARM := arm-9tdmi-linux-gnu-gcc -march=armv4 -nostdinc -MMD GCC_ARM += -Wall -W -Wcast-align -Wcast-qual -Wwrite-strings -Werror +GCC_ARM_T := $(GCC_ARM) -march=armv4t -mthumb-interwork -mthumb LD_ARM := arm-9tdmi-linux-gnu-ld OBJCOPY_ARM := arm-9tdmi-linux-gnu-objcopy BIN2H_WINCE := perl -ne 'print "db\t", join(",", map { sprintf "%\#02x", $$_ } unpack("C*", $$_)), "\n"' @@ -554,16 +555,26 @@ upxd: l_lx_sep.o l_lx_sep86.asm $(STRIPELF_LINUX_I386) $@ $(BRANDELF) $@ -l_armpe.h: l_armpe.asx l_armpe_s.S l_armpe_c.c arm_nrv2e_d8.S arm_nrv2b_d8.S $(MAKEFILE_LIST) - $(GCC_ARM) -mthumb-interwork -c l_armpe_s.S arm_nrv2e_d8.S arm_nrv2b_d8.S - $(GCC_ARM) -mthumb -mthumb-interwork -Os -c l_armpe_c.c -DNRV2E +l_armpe.h: l_armpe.asx l_armpe_s.S l_armpe_c.c arm_nrv2e_d8.S arm_nrv2b_d8.S armv4_n2e_d8.S $(MAKEFILE_LIST) + $(GCC_ARM_T) -c l_armpe_s.S arm_nrv2e_d8.S arm_nrv2b_d8.S + $(GCC_ARM_T) -Os -c l_armpe_c.c -DUCL_DECOMPRESS=thumb_nrv2e_d8 $(LD_ARM) -o l_armpe2e.out l_armpe_s.o l_armpe_c.o arm_nrv2e_d8.o $(OBJCOPY_ARM) --only-section .text -O binary l_armpe2e.out l_armpe2e.bin $(BIN2H_WINCE) l_armpe2e.ah - $(GCC_ARM) -mthumb -mthumb-interwork -Os -c l_armpe_c.c -DNRV2B + $(GCC_ARM_T) -Os -c l_armpe_c.c -DUCL_DECOMPRESS=go_thumb_n2b $(LD_ARM) -o l_armpe2b.out l_armpe_s.o l_armpe_c.o arm_nrv2b_d8.o $(OBJCOPY_ARM) --only-section .text -O binary l_armpe2b.out l_armpe2b.bin $(BIN2H_WINCE) l_armpe2b.ah + $(GCC_ARM) -Os -S l_armpe_c.c -DUCL_DECOMPRESS=ucl_nrv2e_decompress_8 + $(GCC_ARM) -c armv4_n2e_d8.S l_armpe_s.S + $(LD_ARM) -o l_armpe2e_v4.out l_armpe_s.o armv4_n2e_d8.o + $(OBJCOPY_ARM) --only-section .text -O binary l_armpe2e_v4.out l_armpe2e_v4.bin + $(BIN2H_WINCE) l_armpe2e_v4.ah + $(GCC_ARM) -DSTUB_FOR_DLL -Os -S l_armpe_c.c -DUCL_DECOMPRESS=ucl_nrv2e_decompress_8 + $(GCC_ARM) -DSTUB_FOR_DLL -c armv4_n2e_d8.S l_armpe_s.S + $(LD_ARM) -o l_armpe2e_v4dll.out l_armpe_s.o armv4_n2e_d8.o + $(OBJCOPY_ARM) --only-section .text -O binary l_armpe2e_v4dll.out l_armpe2e_v4dll.bin + $(BIN2H_WINCE) l_armpe2e_v4dll.ah $(NASM) -f bin -o $T.bin $< $(BIN2H) $T.bin nrv_loader $@ diff --git a/src/stub/armv4_n2e_d8.S b/src/stub/armv4_n2e_d8.S new file mode 100644 index 00000000..471617b8 --- /dev/null +++ b/src/stub/armv4_n2e_d8.S @@ -0,0 +1,181 @@ +/* armv4_n2e_d8.S -- ARM decompressor for NRV2E + + This file is part of the UPX executable compressor. + + Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996-2004 Laszlo Molnar + Copyright (C) 2000-2006 John F. Reiser + 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 + + + John F. Reiser + +*/ +#define SAFE 0 /* 1 for src+dst bounds checking: cost 76 bytes */ + +#define src r0 +#define len r1 /* overlaps 'cnt' */ +#define dst r2 +#define tmp r3 +#define bits r4 +#define off r5 +/* r6 UNUSED in ARM code unless DEBUG mode */ +#define srclim r7 +#if 1==SAFE /*{*/ +#define dstlim r12 +#endif /*}*/ + +#define cnt r1 /* overlaps 'len' while reading an offset */ + +/* macros reduce "noise" when comparing this ARM code to corresponding THUMB code */ +#define PUSH stmdb sp!, +#define POP ldmia sp!, +#define ADD2( dst,src) add dst,dst,src +#define ADD2S(dst,src) adds dst,dst,src +#define ADC2( dst,src) adc dst,dst,src +#define ADC2S(dst,src) adcs dst,dst,src +#define SUB2( dst,src) sub dst,dst,src +#define SUB2S(dst,src) subs dst,dst,src +#define LDRB3(reg,psrc,incr) ldrb reg,psrc,incr +#define STRB3(reg,pdst,incr) strb reg,pdst,incr + +#if 1==SAFE /*{*/ +#define CHECK_SRC cmp srclim,src; bls bad_src_n2e /* Out: 1==Carry for get8_n2e */ +#define CHECK_DST cmp dst,dstlim; bhs bad_dst_n2e +#else /*}{*/ +#define CHECK_SRC /*empty*/ +#define CHECK_DST /*empty*/ +#endif /*}*/ + +#if 0 /*{ DEBUG only: check newly-decompressed against original dst */ +#define CHECK_BYTE \ + ldrb r6,[dst]; \ + cmp r6,tmp; beq 0f; bkpt; 0: +#else /*}{*/ +#define CHECK_BYTE /*empty*/ +#endif /*}*/ + +#define GETBIT ADD2S(bits,bits); bleq get8_n2e + +#define getnextb(reg) GETBIT; ADC2(reg,reg) /* Out: condition code not changed */ +#define jnextb0 GETBIT; bcc +#define jnextb1 GETBIT; bcs + +ucl_nrv2e_decompress_8: .globl ucl_nrv2e_decompress_8 @ ARM mode + .type ucl_nrv2e_decompress_8, %function +/* error = (*)(char const *src, int len_src, char *dst, int *plen_dst) + Actual decompressed length is stored through plen_dst. + For SAFE mode: at call, *plen_dst must be allowed length of output buffer. +*/ + PUSH {r2,r3, r4,r5,r6,r7, lr} +#define sp_DST0 0 /* stack offset of original dst */ + add srclim,len,src @ srclim= eof_src; +#if 1==SAFE /*{*/ + ldr tmp,[r3] @ len_dst + add dstlim,tmp,dst +#endif /*}*/ + mvn off,#~-1 @ off= -1 initial condition + mov bits,#1<<31 @ refill next time + b top_n2e + +#if 1==SAFE /*{*/ +bad_dst_n2e: # return value will be 2 +bkpt + add src,srclim,#1 +bad_src_n2e: # return value will be 1 + ADD2(src,#1) +#endif /*}*/ +eof_n2e: + POP {r3,r4} @ r3= orig_dst; r4= plen_dst + SUB2(src,srclim) @ 0 if actual src length equals expected length + SUB2(dst,r3) @ actual dst length + str dst,[r4] + POP {r4,r5,r6,r7 ,pc} + +get8_n2e: @ In: Carry set [from adding 0x80000000 (1<<31) to itself] + CHECK_SRC; LDRB3(bits,[src],#1) @ zero-extend next byte + adc bits,bits,bits @ double and insert CarryIn as low bit + movs bits,bits,lsl #24 @ move to top byte, and set CarryOut from old bit 8 + mov pc,lr + +lit_n2e: + CHECK_SRC; LDRB3(tmp,[src],#1) + CHECK_BYTE + CHECK_DST; STRB3(tmp,[dst],#1) +top_n2e: + jnextb1 lit_n2e + mov cnt,#1; b getoff_n2e + +off_n2e: + SUB2(cnt,#1) + getnextb(cnt) +getoff_n2e: + getnextb(cnt) + jnextb0 off_n2e + + subs tmp,cnt,#3 @ set Carry + mov len,#0 @ Carry unaffected + blo offprev_n2e @ cnt was 2; tests Carry only + CHECK_SRC; LDRB3(off,[src],#1) @ low 7+1 bits + orr off,off,tmp,lsl #8 + mvns off,off; beq eof_n2e @ off= ~off + movs off,off,asr #1; bcs lenlast_n2e + b lenmore_n2e + +offprev_n2e: + jnextb1 lenlast_n2e +lenmore_n2e: + mov len,#1 + jnextb1 lenlast_n2e +len_n2e: + getnextb(len) + jnextb0 len_n2e + ADD2(len,#6-2) + b gotlen_n2e + +lenlast_n2e: + getnextb(len) @ 0,1,2,3 + ADD2(len,#2) +gotlen_n2e: @ 'cmn': add the inputs, set condition codes, discard the sum + cmn off,#5<<8; bcs near_n2e @ within M2_MAX_OFFSET + ADD2(len,#1) @ too far away, so minimum match length is 3 +near_n2e: +#if 1==SAFE /*{*/ + ldr tmp,[sp,#sp_DST0] + SUB2( tmp,dst) + SUB2S(tmp,off); bhi bad_dst_n2e @ reaching back too far + + add tmp,dst,cnt + cmp tmp,dstlim; bhi bad_dst_n2e @ too much output +#endif /*}*/ + ldrb tmp,[dst] @ force cacheline allocate +copy_n2e: + ldrb tmp,[dst,off] + CHECK_BYTE + STRB3(tmp,[dst],#1) + SUB2S(len,#1); bne copy_n2e + b top_n2e + + .size ucl_nrv2e_decompress_8, .-ucl_nrv2e_decompress_8 + +/* +vi:ts=8:et:nowrap + */ + diff --git a/src/stub/l_armpe.asm b/src/stub/l_armpe.asm index a31e93c9..69701815 100644 --- a/src/stub/l_armpe.asm +++ b/src/stub/l_armpe.asm @@ -42,6 +42,10 @@ ; __ARMWPE2E__ start: %include "l_armpe2e.ah" +; __ARMWPE2EV4__ +%include "l_armpe2e_v4.ah" +; __ARMWPE2EV4DLL__ +%include "l_armpe2e_v4dll.ah" ; __ARMWPE2B__ %include "l_armpe2b.ah" ; __ARMWPEHE__ diff --git a/src/stub/l_armpe.h b/src/stub/l_armpe.h index 71311c5d..a6065826 100644 --- a/src/stub/l_armpe.h +++ b/src/stub/l_armpe.h @@ -1,4 +1,4 @@ -/* l_armpe.h -- created from l_armpe.bin, 1039 (0x40f) bytes +/* l_armpe.h -- created from l_armpe.bin, 2472 (0x9a8) bytes This file is part of the UPX executable compressor. @@ -27,74 +27,164 @@ */ -#define NRV_LOADER_SIZE 1039 -#define NRV_LOADER_ADLER32 0xa2a48332 -#define NRV_LOADER_CRC32 0x9e9a3347 +#define NRV_LOADER_SIZE 2472 +#define NRV_LOADER_ADLER32 0xf7af0ea2 +#define NRV_LOADER_CRC32 0x70a87499 -unsigned char nrv_loader[1039] = { +unsigned char nrv_loader[2472] = { 15, 64, 45,233, 72, 0,143,226, 14, 0,144,232, 2, 16,129,224, /* 0x 0 */ 0, 32,147,229, 1, 58,131,226, 1, 0, 83,225,251,255,255,154, /* 0x 10 */ 4,224,143,226, 23,192,143,226, 28,255, 47,225, 15, 64,189,232, /* 0x 20 */ 60,192,159,229, 28,255, 47,225, 12, 75, 27,104, 24, 71, 12, 75, /* 0x 30 */ -251,231, 25,224, 3, 33, 67, 92, 18, 2,210, 24, 1, 57,250,213, /* 0x 40 */ +251,231, 27,224, 3, 33, 67, 92, 18, 2,210, 24, 1, 57,250,213, /* 0x 40 */ 16, 28,112, 71, 83, 82, 67, 48, 83, 82, 67, 76, 68, 83, 84, 48, /* 0x 50 */ 68, 83, 84, 76, 66, 73, 77, 80, 79, 78, 65, 77, 71, 69, 84, 80, /* 0x 60 */ - 76, 79, 65, 68, 69, 78, 84, 82,240,181,163,176, 0, 34, 2,146, /* 0x 70 */ -130,104, 1,146, 66,105, 3, 28, 4,105, 0,146, 89,104, 0,104, /* 0x 80 */ - 1,154, 2,171, 0,240, 76,248, 37, 28, 40, 28,255,247,210,255, /* 0x 90 */ - 4, 30, 61,208, 0,155, 40, 29,228, 24,255,247,203,255, 1,154, /* 0x a0 */ -134, 24, 3,168, 2, 28, 35,120, 27, 6, 0, 43, 4,208, 27, 14, /* 0x b0 */ - 19,128, 1, 52, 2, 50,246,231, 0, 35, 19,128,255,247,183,255, /* 0x c0 */ - 8, 53, 7, 28, 43,120, 27, 6, 0, 43, 31,208, 27, 14, 1, 53, /* 0x d0 */ - 1, 43, 2,208,255, 43, 13,208,244,231, 56, 28, 41, 28,255,247, /* 0x e0 */ -163,255, 52, 28, 32, 96, 4, 54, 43,120, 27, 6, 1, 53, 0, 43, /* 0x f0 */ -250,209,231,231,105,120, 43,120, 9, 2, 56, 28, 89, 24,255,247, /* 0x 100 */ -147,255, 52, 28, 2, 53, 4, 54, 32, 96,219,231, 1, 53,188,231, /* 0x 110 */ - 35,176,240,188, 1,188, 0, 71, 1,192,143,226, 28,255, 47,225, /* 0x 120 */ -252,181, 15, 24, 1, 36,101, 66,228, 7, 5, 38, 54, 2, 15,224, /* 0x 130 */ - 24,188,192, 27,210, 26, 34, 96,240,188, 2,188, 8, 71, 4,120, /* 0x 140 */ -100, 65, 1, 48, 36, 6,247, 70, 3,120, 1, 48, 19,112, 1, 50, /* 0x 150 */ - 36, 25,254, 70,243,208,247,210, 1, 33, 4,224, 1, 57, 36, 25, /* 0x 160 */ -254, 70,236,208, 73, 65, 36, 25,254, 70,232,208, 73, 65, 36, 25, /* 0x 170 */ -254, 70,228,208,242,211,203, 30, 0, 33, 8,211, 27, 2, 5,120, /* 0x 180 */ - 1, 48, 29, 67,237, 67,211,208,109, 16, 19,210, 3,224, 36, 25, /* 0x 190 */ -254, 70,212,208, 14,210, 1, 33, 36, 25,254, 70,207,208, 9,210, /* 0x 1a0 */ - 36, 25,254, 70,203,208, 73, 65, 36, 25,254, 70,199,208,247,211, /* 0x 1b0 */ - 4, 49, 4,224, 36, 25,254, 70,193,208, 73, 65, 2, 49,238, 66, /* 0x 1c0 */ - 0,210, 1, 49, 19,120, 83, 93, 19,112, 1, 50, 1, 57,250,209, /* 0x 1d0 */ -190,231, 0, 0, 15, 64, 45,233, 72, 0,143,226, 14, 0,144,232, /* 0x 1e0 */ - 2, 16,129,224, 0, 32,147,229, 1, 58,131,226, 1, 0, 83,225, /* 0x 1f0 */ -251,255,255,154, 4,224,143,226, 23,192,143,226, 28,255, 47,225, /* 0x 200 */ - 15, 64,189,232, 60,192,159,229, 28,255, 47,225, 12, 75, 27,104, /* 0x 210 */ - 24, 71, 12, 75,251,231, 25,224, 3, 33, 67, 92, 18, 2,210, 24, /* 0x 220 */ - 1, 57,250,213, 16, 28,112, 71, 83, 82, 67, 48, 83, 82, 67, 76, /* 0x 230 */ - 68, 83, 84, 48, 68, 83, 84, 76, 66, 73, 77, 80, 79, 78, 65, 77, /* 0x 240 */ - 71, 69, 84, 80, 76, 79, 65, 68, 69, 78, 84, 82,240,181,163,176, /* 0x 250 */ - 0, 34, 2,146,130,104, 1,146, 66,105, 3, 28, 4,105, 0,146, /* 0x 260 */ - 89,104, 0,104, 1,154, 2,171, 0,240, 76,248, 37, 28, 40, 28, /* 0x 270 */ -255,247,210,255, 4, 30, 61,208, 0,155, 40, 29,228, 24,255,247, /* 0x 280 */ -203,255, 1,154,134, 24, 3,168, 2, 28, 35,120, 27, 6, 0, 43, /* 0x 290 */ - 4,208, 27, 14, 19,128, 1, 52, 2, 50,246,231, 0, 35, 19,128, /* 0x 2a0 */ -255,247,183,255, 8, 53, 7, 28, 43,120, 27, 6, 0, 43, 31,208, /* 0x 2b0 */ - 27, 14, 1, 53, 1, 43, 2,208,255, 43, 13,208,244,231, 56, 28, /* 0x 2c0 */ - 41, 28,255,247,163,255, 52, 28, 32, 96, 4, 54, 43,120, 27, 6, /* 0x 2d0 */ - 1, 53, 0, 43,250,209,231,231,105,120, 43,120, 9, 2, 56, 28, /* 0x 2e0 */ - 89, 24,255,247,147,255, 52, 28, 2, 53, 4, 54, 32, 96,219,231, /* 0x 2f0 */ - 1, 53,188,231, 35,176,240,188, 1,188, 0, 71, 1,192,143,226, /* 0x 300 */ - 28,255, 47,225, 9, 24,254,181, 1, 36,101, 66,228, 7, 13, 39, /* 0x 310 */ - 63, 2, 13,224, 26,188, 64, 26,210, 26, 34, 96,240,189, 4,120, /* 0x 320 */ -100, 65, 1, 48, 36, 6,247, 70, 3,120, 1, 48, 19,112, 1, 50, /* 0x 330 */ - 36, 25,254, 70,243,208,247,210, 1, 33, 36, 25,254, 70,238,208, /* 0x 340 */ - 73, 65, 36, 25,254, 70,234,208,247,211,203, 30, 0, 33, 5,211, /* 0x 350 */ - 27, 2, 5,120, 1, 48, 29, 67,237, 67,219,208, 36, 25,254, 70, /* 0x 360 */ -221,208, 73, 65, 36, 25,254, 70,217,208, 73, 65, 9,209, 1, 33, /* 0x 370 */ - 36, 25,254, 70,211,208, 73, 65, 36, 25,254, 70,207,208,247,211, /* 0x 380 */ - 2, 49, 1, 49,253, 66, 0,210, 1, 49, 19,120, 83, 93, 19,112, /* 0x 390 */ - 1, 50, 1, 57,250,209,203,231, 85, 80, 88, 33,161,216,208,213, /* 0x 3a0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x 3b0 */ - 0, 0, 0, 0, 0, 0, 0, 45, 65, 82, 77, 87, 80, 69, 50, 69, /* 0x 3c0 */ - 0, 0, 0, 0, 0, 65, 82, 77, 87, 80, 69, 50, 66, 0,228, 1, /* 0x 3d0 */ - 0, 0, 65, 82, 77, 87, 80, 69, 72, 69, 0,168, 3, 0, 0, 85, /* 0x 3e0 */ - 80, 88, 49, 72, 69, 65, 68, 0,168, 3, 0, 0, 65, 82, 77, 87, /* 0x 3f0 */ - 80, 69, 57, 57, 0,200, 3, 0, 0,255,255,255,255,200, 3 /* 0x 400 */ + 76, 79, 65, 68, 69, 78, 84, 82, 66, 82, 69, 76,240,181,163,176, /* 0x 70 */ + 0, 34, 2,146,130,104, 1,146, 66,105, 3, 28, 4,105, 0,146, /* 0x 80 */ + 89,104, 0,104, 1,154, 2,171, 0,240, 76,248, 37, 28, 40, 28, /* 0x 90 */ +255,247,208,255, 4, 30, 61,208, 0,155, 40, 29,228, 24,255,247, /* 0x a0 */ +201,255, 1,154,134, 24, 3,168, 2, 28, 35,120, 27, 6, 0, 43, /* 0x b0 */ + 4,208, 27, 14, 19,128, 1, 52, 2, 50,246,231, 0, 35, 19,128, /* 0x c0 */ +255,247,181,255, 8, 53, 7, 28, 43,120, 27, 6, 0, 43, 31,208, /* 0x d0 */ + 27, 14, 1, 53, 1, 43, 2,208,255, 43, 13,208,244,231, 56, 28, /* 0x e0 */ + 41, 28,255,247,161,255, 52, 28, 32, 96, 4, 54, 43,120, 27, 6, /* 0x f0 */ + 1, 53, 0, 43,250,209,231,231,105,120, 43,120, 9, 2, 56, 28, /* 0x 100 */ + 89, 24,255,247,145,255, 52, 28, 2, 53, 4, 54, 32, 96,219,231, /* 0x 110 */ + 1, 53,188,231, 35,176,240,188, 1,188, 0, 71, 1,192,143,226, /* 0x 120 */ + 28,255, 47,225,252,181, 15, 24, 1, 36,101, 66,228, 7, 5, 38, /* 0x 130 */ + 54, 2, 15,224, 24,188,192, 27,210, 26, 34, 96,240,188, 2,188, /* 0x 140 */ + 8, 71, 4,120,100, 65, 1, 48, 36, 6,247, 70, 3,120, 1, 48, /* 0x 150 */ + 19,112, 1, 50, 36, 25,254, 70,243,208,247,210, 1, 33, 4,224, /* 0x 160 */ + 1, 57, 36, 25,254, 70,236,208, 73, 65, 36, 25,254, 70,232,208, /* 0x 170 */ + 73, 65, 36, 25,254, 70,228,208,242,211,203, 30, 0, 33, 8,211, /* 0x 180 */ + 27, 2, 5,120, 1, 48, 29, 67,237, 67,211,208,109, 16, 19,210, /* 0x 190 */ + 3,224, 36, 25,254, 70,212,208, 14,210, 1, 33, 36, 25,254, 70, /* 0x 1a0 */ +207,208, 9,210, 36, 25,254, 70,203,208, 73, 65, 36, 25,254, 70, /* 0x 1b0 */ +199,208,247,211, 4, 49, 4,224, 36, 25,254, 70,193,208, 73, 65, /* 0x 1c0 */ + 2, 49,238, 66, 0,210, 1, 49, 19,120, 83, 93, 19,112, 1, 50, /* 0x 1d0 */ + 1, 57,250,209,190,231, 0, 0, 15, 64, 45,233, 52, 0,143,226, /* 0x 1e0 */ + 22, 0, 0,235, 15, 64,189,232, 72,240,159,229, 64, 48,159,229, /* 0x 1f0 */ + 0,240,147,229, 52, 48,159,229, 0,240,147,229, 3, 32,160,227, /* 0x 200 */ + 2, 48,208,231, 1, 32, 82,226, 1, 20,131,224,251,255,255, 90, /* 0x 210 */ + 1, 0,160,225, 14,240,160,225, 83, 82, 67, 48, 83, 82, 67, 76, /* 0x 220 */ + 68, 83, 84, 48, 68, 83, 84, 76, 66, 73, 77, 80, 79, 78, 65, 77, /* 0x 230 */ + 71, 69, 84, 80, 76, 79, 65, 68, 69, 78, 84, 82, 66, 82, 69, 76, /* 0x 240 */ +240, 65, 45,233, 0,224,160,227, 8,112,144,229,132,208, 77,226, /* 0x 250 */ + 0,192,160,225, 3, 0,144,232, 0,224,141,229, 7, 32,160,225, /* 0x 260 */ + 13, 48,160,225, 16, 64,140,226, 16, 1,148,232, 52, 0, 0,235, /* 0x 270 */ + 4, 0,160,225,224,255,255,235, 0, 80, 80,226, 46, 0, 0, 10, /* 0x 280 */ + 4, 0,132,226,220,255,255,235, 8, 80,133,224, 0, 48,213,229, /* 0x 290 */ + 4, 16,141,226, 0, 0, 83,227, 7, 96,128,224, 1, 32,160,225, /* 0x 2a0 */ + 3, 0, 0, 10,178, 48,194,224, 1, 48,245,229, 0, 0, 83,227, /* 0x 2b0 */ +250,255,255,234, 0, 48,160,227,176, 48,194,225, 1, 0,160,225, /* 0x 2c0 */ +201,255,255,235, 8, 48,244,229, 0, 80,160,225, 0, 0, 83,227, /* 0x 2d0 */ + 23, 0, 0, 10,255, 48, 3,226, 1, 0, 83,227, 1, 64,132,226, /* 0x 2e0 */ + 2, 0, 0, 10,255, 0, 83,227, 8, 0, 0, 10, 14, 0, 0,234, /* 0x 2f0 */ + 5, 0,160,225, 4, 16,160,225,189,255,255,235, 4, 0,134,228, /* 0x 300 */ + 1, 48,212,228, 0, 0, 83,227,252,255,255, 26, 6, 0, 0,234, /* 0x 310 */ + 0, 48,212,229, 1, 16,212,229, 5, 0,160,225, 1, 20,131,224, /* 0x 320 */ +179,255,255,235, 2, 64,132,226, 4, 0,134,228, 0, 48,212,229, /* 0x 330 */ +229,255,255,234, 1, 64,132,226,204,255,255,234,132,208,141,226, /* 0x 340 */ +240,129,189,232,252, 64, 45,233, 0,112,129,224, 0, 80,224,227, /* 0x 350 */ + 2, 65,160,227, 10, 0, 0,234, 24, 0,189,232, 7, 0, 64,224, /* 0x 360 */ + 3, 32, 66,224, 0, 32,132,229,240,128,189,232, 1, 64,208,228, /* 0x 370 */ + 4, 64,164,224, 4, 76,176,225, 14,240,160,225, 1, 48,208,228, /* 0x 380 */ + 1, 48,194,228, 4, 64,148,224,247,255,255, 11,250,255,255, 42, /* 0x 390 */ + 1, 16,160,227, 3, 0, 0,234, 1, 16, 65,226, 4, 64,148,224, /* 0x 3a0 */ +241,255,255, 11, 1, 16,161,224, 4, 64,148,224,238,255,255, 11, /* 0x 3b0 */ + 1, 16,161,224, 4, 64,148,224,235,255,255, 11,245,255,255, 58, /* 0x 3c0 */ + 3, 48, 81,226, 0, 16,160,227, 6, 0, 0, 58, 1, 80,208,228, /* 0x 3d0 */ + 3, 84,133,225, 5, 80,240,225,222,255,255, 10,197, 80,176,225, /* 0x 3e0 */ + 15, 0, 0, 42, 2, 0, 0,234, 4, 64,148,224,222,255,255, 11, /* 0x 3f0 */ + 11, 0, 0, 42, 1, 16,160,227, 4, 64,148,224,218,255,255, 11, /* 0x 400 */ + 7, 0, 0, 42, 4, 64,148,224,215,255,255, 11, 1, 16,161,224, /* 0x 410 */ + 4, 64,148,224,212,255,255, 11,249,255,255, 58, 4, 16,129,226, /* 0x 420 */ + 3, 0, 0,234, 4, 64,148,224,207,255,255, 11, 1, 16,161,224, /* 0x 430 */ + 2, 16,129,226, 5, 12,117,227, 0, 0, 0, 42, 1, 16,129,226, /* 0x 440 */ + 0, 48,210,229, 5, 48,210,231, 1, 48,194,228, 1, 16, 81,226, /* 0x 450 */ +251,255,255, 26,202,255,255,234, 1, 0, 81,227, 3, 0, 0, 26, /* 0x 460 */ + 15, 64, 45,233,148, 0,143,226, 46, 0, 0,235, 15, 64,189,232, /* 0x 470 */ +168,240,159,229,160, 48,159,229, 0,240,147,229,148, 48,159,229, /* 0x 480 */ + 0,240,147,229, 3, 32,160,227, 2, 48,208,231, 1, 32, 82,226, /* 0x 490 */ + 1, 20,131,224,251,255,255, 90, 1, 0,160,225, 14,240,160,225, /* 0x 4a0 */ +124, 0,159,229, 92, 32,159,229, 4, 16, 66,226, 1, 48,208,228, /* 0x 4b0 */ + 0, 0, 83,227,248,255,255, 10,240, 0, 83,227,240,192,195, 35, /* 0x 4c0 */ + 1, 48,208, 37, 12,196,131, 32, 2, 48,208, 36, 12, 52,131, 32, /* 0x 4d0 */ + 3, 16,129,224, 0, 48,209,229, 12,196,131,224, 1, 48,209,229, /* 0x 4e0 */ + 12,196,131,224, 2, 48,209,229, 12,196,131,224, 3, 48,209,229, /* 0x 4f0 */ + 12,196,131,224, 2,192,140,224, 0,192,129,229,234,255,255,234, /* 0x 500 */ + 83, 82, 67, 48, 83, 82, 67, 76, 68, 83, 84, 48, 68, 83, 84, 76, /* 0x 510 */ + 66, 73, 77, 80, 79, 78, 65, 77, 71, 69, 84, 80, 76, 79, 65, 68, /* 0x 520 */ + 69, 78, 84, 82, 66, 82, 69, 76,240, 65, 45,233, 0,224,160,227, /* 0x 530 */ + 8,112,144,229,132,208, 77,226, 0,192,160,225, 3, 0,144,232, /* 0x 540 */ + 0,224,141,229, 7, 32,160,225, 13, 48,160,225, 16, 64,140,226, /* 0x 550 */ + 16, 1,148,232, 53, 0, 0,235, 4, 0,160,225,200,255,255,235, /* 0x 560 */ + 0, 80, 80,226, 46, 0, 0, 10, 4, 0,132,226,196,255,255,235, /* 0x 570 */ + 8, 80,133,224, 0, 48,213,229, 4, 16,141,226, 0, 0, 83,227, /* 0x 580 */ + 7, 96,128,224, 1, 32,160,225, 3, 0, 0, 10,178, 48,194,224, /* 0x 590 */ + 1, 48,245,229, 0, 0, 83,227,250,255,255,234, 0, 48,160,227, /* 0x 5a0 */ +176, 48,194,225, 1, 0,160,225,177,255,255,235, 8, 48,244,229, /* 0x 5b0 */ + 0, 80,160,225, 0, 0, 83,227, 23, 0, 0, 10,255, 48, 3,226, /* 0x 5c0 */ + 1, 0, 83,227, 1, 64,132,226, 2, 0, 0, 10,255, 0, 83,227, /* 0x 5d0 */ + 8, 0, 0, 10, 14, 0, 0,234, 5, 0,160,225, 4, 16,160,225, /* 0x 5e0 */ +165,255,255,235, 4, 0,134,228, 1, 48,212,228, 0, 0, 83,227, /* 0x 5f0 */ +252,255,255, 26, 6, 0, 0,234, 0, 48,212,229, 1, 16,212,229, /* 0x 600 */ + 5, 0,160,225, 1, 20,131,224,155,255,255,235, 2, 64,132,226, /* 0x 610 */ + 4, 0,134,228, 0, 48,212,229,229,255,255,234, 1, 64,132,226, /* 0x 620 */ +204,255,255,234,157,255,255,235,132,208,141,226,240,129,189,232, /* 0x 630 */ +252, 64, 45,233, 0,112,129,224, 0, 80,224,227, 2, 65,160,227, /* 0x 640 */ + 10, 0, 0,234, 24, 0,189,232, 7, 0, 64,224, 3, 32, 66,224, /* 0x 650 */ + 0, 32,132,229,240,128,189,232, 1, 64,208,228, 4, 64,164,224, /* 0x 660 */ + 4, 76,176,225, 14,240,160,225, 1, 48,208,228, 1, 48,194,228, /* 0x 670 */ + 4, 64,148,224,247,255,255, 11,250,255,255, 42, 1, 16,160,227, /* 0x 680 */ + 3, 0, 0,234, 1, 16, 65,226, 4, 64,148,224,241,255,255, 11, /* 0x 690 */ + 1, 16,161,224, 4, 64,148,224,238,255,255, 11, 1, 16,161,224, /* 0x 6a0 */ + 4, 64,148,224,235,255,255, 11,245,255,255, 58, 3, 48, 81,226, /* 0x 6b0 */ + 0, 16,160,227, 6, 0, 0, 58, 1, 80,208,228, 3, 84,133,225, /* 0x 6c0 */ + 5, 80,240,225,222,255,255, 10,197, 80,176,225, 15, 0, 0, 42, /* 0x 6d0 */ + 2, 0, 0,234, 4, 64,148,224,222,255,255, 11, 11, 0, 0, 42, /* 0x 6e0 */ + 1, 16,160,227, 4, 64,148,224,218,255,255, 11, 7, 0, 0, 42, /* 0x 6f0 */ + 4, 64,148,224,215,255,255, 11, 1, 16,161,224, 4, 64,148,224, /* 0x 700 */ +212,255,255, 11,249,255,255, 58, 4, 16,129,226, 3, 0, 0,234, /* 0x 710 */ + 4, 64,148,224,207,255,255, 11, 1, 16,161,224, 2, 16,129,226, /* 0x 720 */ + 5, 12,117,227, 0, 0, 0, 42, 1, 16,129,226, 0, 48,210,229, /* 0x 730 */ + 5, 48,210,231, 1, 48,194,228, 1, 16, 81,226,251,255,255, 26, /* 0x 740 */ +202,255,255,234, 15, 64, 45,233, 72, 0,143,226, 14, 0,144,232, /* 0x 750 */ + 2, 16,129,224, 0, 32,147,229, 1, 58,131,226, 1, 0, 83,225, /* 0x 760 */ +251,255,255,154, 4,224,143,226, 23,192,143,226, 28,255, 47,225, /* 0x 770 */ + 15, 64,189,232, 60,192,159,229, 28,255, 47,225, 12, 75, 27,104, /* 0x 780 */ + 24, 71, 12, 75,251,231, 27,224, 3, 33, 67, 92, 18, 2,210, 24, /* 0x 790 */ + 1, 57,250,213, 16, 28,112, 71, 83, 82, 67, 48, 83, 82, 67, 76, /* 0x 7a0 */ + 68, 83, 84, 48, 68, 83, 84, 76, 66, 73, 77, 80, 79, 78, 65, 77, /* 0x 7b0 */ + 71, 69, 84, 80, 76, 79, 65, 68, 69, 78, 84, 82, 66, 82, 69, 76, /* 0x 7c0 */ +240,181,163,176, 0, 34, 2,146,130,104, 1,146, 66,105, 3, 28, /* 0x 7d0 */ + 4,105, 0,146, 89,104, 0,104, 1,154, 2,171, 0,240, 76,248, /* 0x 7e0 */ + 37, 28, 40, 28,255,247,208,255, 4, 30, 61,208, 0,155, 40, 29, /* 0x 7f0 */ +228, 24,255,247,201,255, 1,154,134, 24, 3,168, 2, 28, 35,120, /* 0x 800 */ + 27, 6, 0, 43, 4,208, 27, 14, 19,128, 1, 52, 2, 50,246,231, /* 0x 810 */ + 0, 35, 19,128,255,247,181,255, 8, 53, 7, 28, 43,120, 27, 6, /* 0x 820 */ + 0, 43, 31,208, 27, 14, 1, 53, 1, 43, 2,208,255, 43, 13,208, /* 0x 830 */ +244,231, 56, 28, 41, 28,255,247,161,255, 52, 28, 32, 96, 4, 54, /* 0x 840 */ + 43,120, 27, 6, 1, 53, 0, 43,250,209,231,231,105,120, 43,120, /* 0x 850 */ + 9, 2, 56, 28, 89, 24,255,247,145,255, 52, 28, 2, 53, 4, 54, /* 0x 860 */ + 32, 96,219,231, 1, 53,188,231, 35,176,240,188, 1,188, 0, 71, /* 0x 870 */ + 1,192,143,226, 28,255, 47,225, 9, 24,254,181, 1, 36,101, 66, /* 0x 880 */ +228, 7, 13, 39, 63, 2, 15,224, 26,188, 64, 26,210, 26, 34, 96, /* 0x 890 */ +240,188, 2,188, 8, 71, 4,120,100, 65, 1, 48, 36, 6,247, 70, /* 0x 8a0 */ + 3,120, 1, 48, 19,112, 1, 50, 36, 25,254, 70,243,208,247,210, /* 0x 8b0 */ + 1, 33, 36, 25,254, 70,238,208, 73, 65, 36, 25,254, 70,234,208, /* 0x 8c0 */ +247,211,203, 30, 0, 33, 5,211, 27, 2, 5,120, 1, 48, 29, 67, /* 0x 8d0 */ +237, 67,217,208, 36, 25,254, 70,221,208, 73, 65, 36, 25,254, 70, /* 0x 8e0 */ +217,208, 73, 65, 9,209, 1, 33, 36, 25,254, 70,211,208, 73, 65, /* 0x 8f0 */ + 36, 25,254, 70,207,208,247,211, 2, 49, 1, 49,253, 66, 0,210, /* 0x 900 */ + 1, 49, 19,120, 83, 93, 19,112, 1, 50, 1, 57,250,209,203,231, /* 0x 910 */ + 85, 80, 88, 33,161,216,208,213, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x 920 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, /* 0x 930 */ + 65, 82, 77, 87, 80, 69, 50, 69, 0, 0, 0, 0, 0, 65, 82, 77, /* 0x 940 */ + 87, 80, 69, 50, 69, 86, 52, 0,232, 1, 0, 0, 65, 82, 77, 87, /* 0x 950 */ + 80, 69, 50, 69, 86, 52, 68, 76, 76, 0,104, 4, 0, 0, 65, 82, /* 0x 960 */ + 77, 87, 80, 69, 50, 66, 0, 84, 7, 0, 0, 65, 82, 77, 87, 80, /* 0x 970 */ + 69, 72, 69, 0, 32, 9, 0, 0, 85, 80, 88, 49, 72, 69, 65, 68, /* 0x 980 */ + 0, 32, 9, 0, 0, 65, 82, 77, 87, 80, 69, 57, 57, 0, 64, 9, /* 0x 990 */ + 0, 0,255,255,255,255, 64, 9 /* 0x 9a0 */ }; diff --git a/src/stub/l_armpe_c.c b/src/stub/l_armpe_c.c index 3bdb14d8..d5c5651d 100644 --- a/src/stub/l_armpe_c.c +++ b/src/stub/l_armpe_c.c @@ -29,20 +29,17 @@ */ -#ifdef NRV2E -int thumb_nrv2e_d8(const unsigned char * src, unsigned src_len, - unsigned char * dst, unsigned * dst_len); -#define ucl_decompress thumb_nrv2e_d8 -#elif defined(NRV2B) -int go_thumb_n2b(const unsigned char * src, unsigned src_len, - unsigned char * dst, unsigned * dst_len); -#define ucl_decompress go_thumb_n2b +#ifndef UCL_DECOMPRESS +# error please define UCL_DECOMPRESS #endif +int UCL_DECOMPRESS(const unsigned char * src, unsigned src_len, + unsigned char * dst, unsigned * dst_len); void *LoadLibraryW(const unsigned short *); void *GetProcAddressA(const void *, const void *); void *get_le32(const void *); +void reloc_main(); static void handle_imports(const unsigned char *imp, unsigned name_offset, unsigned iat_offset) @@ -130,9 +127,13 @@ void upx_main(const unsigned *info) #ifdef SAFE dlen = info[3]; #endif - //WRITEFILE2('0', (void*) 0x11000, load + 256 - 0x11000); - ucl_decompress((void *) src0, srcl, (void *) dst0, &dlen); - //WRITEFILE2('1', (void*) 0x11000, load + 256 - 0x11000); + //WRITEFILE2('0', (void*) dst0, info[7] + 256 - dst0); + UCL_DECOMPRESS((void *) src0, srcl, (void *) dst0, &dlen); + //WRITEFILE2('1', (void*) dst0, info[7] + 256 - dst0); handle_imports((void *) bimp, onam, dst0); - //WRITEFILE2('2', (void*) 0x11000, load + 256 - 0x11000); + //WRITEFILE2('2', (void*) dst0, info[7] + 256 - dst0); +#ifdef STUB_FOR_DLL + reloc_main(); + //WRITEFILE2('3', (void*) dst0, info[7] + 256 - dst0); +#endif } diff --git a/src/stub/l_armpe_s.S b/src/stub/l_armpe_s.S index bd14bf9b..c920a97b 100644 --- a/src/stub/l_armpe_s.S +++ b/src/stub/l_armpe_s.S @@ -29,11 +29,18 @@ */ + +#undef STUB_IN_THUMB_MODE +#if defined(__ARM_ARCH_4T__) || defined(__ARM_ARCH_5T__) +# define STUB_IN_THUMB_MODE +#endif + .text .align 0 .globl upx_main .globl _start +#ifdef STUB_IN_THUMB_MODE _start: stmfd sp!, {r0 - r3, lr} @@ -41,27 +48,28 @@ _start: @ otherwise the THUMB mode stuff fails adr r0, SRC0 + ldmia r0, {r1, r2, r3} @ r1 - src, r2 - slen, r3 - dst add r1, r1, r2 -L01: +.L01: ldr r2, [r3] add r3, r3, #4096 cmp r3, r1 - bls L01 + bls .L01 -#ifdef __ARM_ARCH_4T__ - adr lr, armret +# ifdef __ARM_ARCH_4T__ + adr lr, .Larmret adr ip, call_upxmain + 1 bx ip -armret: +.Larmret: ldmfd sp!, {r0 - r3, lr} ldr ip, ENTR bx ip -#else +# else blx upx_main @ call thumb armv5t style ldmfd sp!, {r0 - r3, lr} ldr pc, ENTR @ original entry -#endif +# endif @@@@@@@@@@@@@@@@ @@ -71,7 +79,7 @@ armret: GetProcAddressA: ldr r3, GETP -t_callr3: +.Lcallr3: ldr r3, [r3] bx r3 @@ -82,12 +90,12 @@ t_callr3: LoadLibraryW: ldr r3, LLIB - b t_callr3 + b .Lcallr3 -#ifdef __ARM_ARCH_4T__ +# ifdef __ARM_ARCH_4T__ call_upxmain: b upx_main -#endif +# endif @@@@@@@@@@@@@@@@ @@ -95,16 +103,16 @@ call_upxmain: .thumb_func get_le32: @ optimized for size mov r1, #3 -g0: +.Lg0: ldrb r3, [r0, r1] lsl r2, r2, #8 add r2, r2, r3 sub r1, #1 - bpl g0 + bpl .Lg0 mov r0, r2 bx lr -#if 0 +# if 0 // debugging stuff - helpers for dumping memory to a file or deleting a file @@ -159,8 +167,123 @@ writefile: filename: .byte '\\', 0, 'r', 0, 0, 0 +# endif + +#else // stub in ARM mode + +_start: +# ifdef STUB_FOR_DLL + cmp r1, #1 + bne .Lstart_orig +# endif + stmfd sp!, {r0 - r3, lr} + adr r0, SRC0 + bl upx_main + ldmfd sp!, {r0 - r3, lr} +.Lstart_orig: + ldr pc, ENTR + + .global LoadLibraryW +LoadLibraryW: + ldr r3, LLIB + ldr pc, [r3] + + .global GetProcAddressA +GetProcAddressA: + ldr r3, GETP + ldr pc, [r3] + + .global get_le32 +get_le32: @ optimized for size + mov r2, #3 +.Lg0: + ldrb r3, [r0, r2] + subs r2, r2, #1 + add r1, r3, r1, asl #8 + bpl .Lg0 + mov r0, r1 +gret: + mov pc, lr + +# ifdef STUB_FOR_DLL + .global reloc_main + buffer .req r0 + dest .req r1 + addval .req r2 + +reloc_main: + ldr buffer, BREL + ldr addval, DST0 + sub dest, addval, #4 + +.Lreloc_loop: + ldrb r3, [buffer], #1 + cmp r3, #0 + beq gret + cmp r3, #0xf0 + + bichs ip, r3, #0xf0 + ldrhsb r3, [buffer, #1] @ get_le16 + addhs ip, r3, ip, lsl #8 + ldrhsb r3, [buffer], #2 + addhs r3, r3, ip, lsl #8 + + add dest, dest, r3 + ldrb r3, [dest] @ get_be32 + add ip, r3, ip, lsl #8 + ldrb r3, [dest, #1] + add ip, r3, ip, lsl #8 + ldrb r3, [dest, #2] + add ip, r3, ip, lsl #8 + ldrb r3, [dest, #3] + add ip, r3, ip, lsl #8 + add ip, ip, addval + str ip, [dest] + b .Lreloc_loop +# endif + +# if 0 + +// debugging stuff - helpers for dumping memory to a file or deleting a file + +// !!!!! check the lines with "system dependent" below before trying + + .global CFwrap +CFwrap: + ldr pc, createfilew + + .global WFwrap +WFwrap: + ldr pc, writefile + + .global CHwrap +CHwrap: + ldr pc, closehandle + + .global DelFile +DelFile: + adr r1, filename + strb r0, [r1, #2] + mov r0, r1 + ldr pc, deleteffilew + + .code 32 +createfilew: + .word 0x1f7927c @ system dependent +closehandle: + .word 0x1f71594 @ system dependent +deleteffilew: + .word 0x1f7b920 @ system dependent +writefile: + .word 0x1f79434 @ system dependent +filename: + .byte '\\', 0, 'r', 0, 0, 0 + +# endif + #endif + @@@@@@@@@@@@@@@@ paramater area for UPX .code 32 @@ -173,3 +296,8 @@ DST0: .ascii "DST0" GETP: .ascii "GETP" LLIB: .ascii "LOAD" ENTR: .ascii "ENTR" +BREL: .ascii "BREL" + +#ifndef STUB_IN_THUMB_MODE +# include "l_armpe_c.s" +#endif