📄 p_w32pe.cpp
字号:
// 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); 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; 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; 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; 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 kBytes", 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();}/*************************************************************************// unpack**************************************************************************/int PackW32Pe::canUnpack(){ if (!readFileHeader()) 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)); 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 PackW32Pe::rebuildImports(upx_byte *& extrainfo){ if (ODADDR(PEDIR_IMPORT) == 0 || ODSIZE(PEDIR_IMPORT) <= sizeof(import_desc)) 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; ICHECK(dname, 1); 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, 2u); 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; upx_byte * const importednames_start = importednames; for (p = idata; get_le32(p) != 0; ++p) { // restore the name of the dll const upx_byte *dname = get_le32(p) + import; ICHECK(dname, 1); 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->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, importednames_start) & 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);}/* extra info added to help uncompression: <ih sizeof(pe_head)> <pe_section_t objs*sizeof(pe_section_t)> <start of compressed imports 4> - optional \ <start of the names from uncompressed imports> - opt / <start of compressed relocs 4> - optional \ <relocation type indicator 1> - optional / <icondir_count 2> - optional <offset of extra info 4>*//*vi:ts=4:et*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -