📄 p_wcle.cpp
字号:
/* p_wcle.cpp -- This file is part of the UPX executable compressor. Copyright (C) 1996-2007 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996-2007 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 <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net> */#include "conf.h"#include "file.h"#include "filter.h"#include "packer.h"#include "lefile.h"#include "p_wcle.h"#include "linker.h"static const#include "stub/i386-dos32.watcom.le.h"#define LEOF_READ (1<<0)#define LEOF_WRITE (1<<1)#define LEOF_EXEC (1<<2)#define LEOF_PRELOAD (1<<6)#define LEOF_HUGE32 (1<<13)#define IOT(x,y) iobject_table[x].y#define OOT(x,y) oobject_table[x].y#define LE_STUB_EDI (1)#ifdef TESTING# define dputc(x,y) do { if (opt->debug.debug_level) putc(x,y); } while (0)# define Opt_debug opt->debug.debug_level#else# define dputc(x,y) ((void)0)# define Opt_debug 0#endif#define my_base_address reserved#define objects ih.object_table_entries#define pages ih.memory_pages#define mps ih.memory_page_size#define opages oh.memory_pages/*************************************************************************//**************************************************************************/const int *PackWcle::getCompressionMethods(int method, int level) const{ return Packer::getDefaultCompressionMethods_le32(method, level);}const int *PackWcle::getFilters() const{ static const int filters[] = { 0x26, 0x24, 0x49, 0x46, 0x16, 0x13, 0x14, 0x11, FT_ULTRA_BRUTE, 0x25, 0x15, 0x12, FT_END }; return filters;}Linker* PackWcle::newLinker() const{ return new ElfLinkerX86;}void PackWcle::buildLoader(const Filter *ft){ // prepare loader initLoader(stub_i386_dos32_watcom_le, sizeof(stub_i386_dos32_watcom_le)); addLoader("IDENTSTR,WCLEMAIN", ph.first_offset_found == 1 ? "WCLEMAIN02" : "", "WCLEMAIN03,UPX1HEAD,WCLECUTP", NULL); // fake alignment for the start of the decompressor linker->defineSymbol("WCLECUTP", 0x1000); addLoader(getDecompressorSections(), "WCLEMAI2", NULL); if (ft->id) { assert(ft->calls > 0); addLoader(ft->addvalue ? "WCCTTPOS" : "WCCTTNUL", NULL); addFilter32(ft->id); }#if 1 // FIXME: if (has_relocation) { addLoader("WCRELOC1,RELOC320", big_relocs ? "REL32BIG" : "", "RELOC32J", NULL ); }#endif addLoader(has_extra_code ? "WCRELSEL" : "", "WCLEMAI4", NULL );}/*************************************************************************// util**************************************************************************/void PackWcle::handleStub(OutputFile *fo){ if (fo && !opt->watcom_le.le) Packer::handleStub(fi,fo,le_offset);}bool PackWcle::canPack(){ if (!LeFile::readFileHeader()) return false; return true;}/*************************************************************************//**************************************************************************/// IDEA: as all the entries go into object #1, I could create bundles with 255// elements (of course I still have to handle empty bundles)void PackWcle::encodeEntryTable(){ unsigned count,object,n; upx_byte *p = ientries; n = 0; while (*p) { count = *p; n += count; if (p[1] == 0) // unused bundle p += 2; else if (p[1] == 3) // 32-bit bundle { object = get_le16(p+2)-1; set_le16(p+2,1); p += 4; for (; count; count--, p += 5) set_le32(p+1,IOT(object,my_base_address) + get_le32(p+1)); } else throwCantPack("unsupported bundle type in entry table"); } //if (Opt_debug) printf("%d entries encoded.\n",n); UNUSED(n); soentries = ptr_diff(p, ientries) + 1; oentries = ientries; ientries = NULL;}void PackWcle::readObjectTable(){ LeFile::readObjectTable(); // temporary copy of the object descriptors iobject_desc.alloc(objects*sizeof(*iobject_table)); memcpy(iobject_desc,iobject_table,objects*sizeof(*iobject_table)); unsigned ic,jc,virtual_size; for (ic = jc = virtual_size = 0; ic < objects; ic++) { jc += IOT(ic,npages); IOT(ic,my_base_address) = virtual_size; virtual_size += (IOT(ic,virtual_size)+mps-1) &~ (mps-1); } if (pages != jc) throwCantPack("bad page number");}void PackWcle::encodeObjectTable(){ unsigned ic,jc; oobject_table = new le_object_table_entry_t[soobject_table = 2]; memset(oobject_table,0,soobject_table * sizeof(*oobject_table)); // object #1: OOT(0,base_address) = IOT(0,base_address); ic = IOT(objects-1,my_base_address)+IOT(objects-1,virtual_size); jc = pages*mps+sofixups+1024; if (ic < jc) ic = jc; unsigned csection = (ic + ph.overlap_overhead + mps-1) &~ (mps-1); OOT(0,virtual_size) = csection + mps; OOT(0,flags) = LEOF_READ|LEOF_EXEC|LEOF_HUGE32|LEOF_PRELOAD; OOT(0,pagemap_index) = 1; OOT(0,npages) = opages; // object #2: stack OOT(1,base_address) = (OOT(0,base_address) +OOT(0,virtual_size)+mps-1) & ~(mps-1); OOT(1,virtual_size) = mps + getDecompressorWrkmemSize(); OOT(1,flags) = LEOF_READ|LEOF_HUGE32|LEOF_WRITE; OOT(1,pagemap_index) = 1; oh.init_cs_object = 1; oh.init_eip_offset = neweip; oh.init_ss_object = 2; oh.init_esp_offset = OOT(1,virtual_size); oh.automatic_data_object = 2;}void PackWcle::encodePageMap(){ opm_entries = new le_pagemap_entry_t[sopm_entries = opages]; for (unsigned ic = 0; ic < sopm_entries; ic++) { opm_entries[ic].l = (unsigned char) (ic+1); opm_entries[ic].m = (unsigned char) ((ic+1)>>8); opm_entries[ic].h = 0; opm_entries[ic].type = 0; }}void PackWcle::encodeFixupPageTable(){ unsigned ic; ofpage_table = new unsigned[sofpage_table = 1 + opages]; for (ofpage_table[0] = ic = 0; ic < opages; ic++) set_le32(ofpage_table+ic+1,sofixups-FIXUP_EXTRA);}void PackWcle::encodeFixups(){ ofixups = new upx_byte[sofixups = 1*7 + FIXUP_EXTRA]; memset(ofixups,0,sofixups); ofixups[0] = 7; set_le16(ofixups+2,(LE_STUB_EDI + neweip) & (mps-1)); ofixups[4] = 1;}void PackWcle::preprocessFixups(){ big_relocs = 0; unsigned ic,jc; Array(unsigned, counts, objects+2); countFixups(counts); for (ic = jc = 0; ic < objects; ic++) jc += counts[ic]; if (jc == 0) { // FIXME: implement this throwCantPack("files without relocations are not supported"); } ByteArray(rl, jc); ByteArray(srf, counts[objects+0]+1); ByteArray(slf, counts[objects+1]+1); upx_byte *selector_fixups = srf; upx_byte *selfrel_fixups = slf; unsigned rc = 0; upx_byte *fix = ifixups; for (ic = jc = 0; ic < pages; ic++) { while ((unsigned)(fix - ifixups) < get_le32(ifpage_table+ic+1)) { const int fixp2 = get_le16_signed(fix+2); unsigned value; switch (*fix) { case 2: // selector fixup if (fixp2 < 0) { // cross page selector fixup dputc('S',stdout); fix += 5; break; } dputc('s',stdout); memcpy(selector_fixups,"\x8C\xCB\x66\x89\x9D",5); // mov bx, cs ; mov [xxx+ebp], bx if (IOT(fix[4]-1,flags) & LEOF_WRITE) selector_fixups[1] = 0xDB; // ds set_le32(selector_fixups+5,jc+fixp2); selector_fixups += 9; fix += 5; break; case 5: // 16-bit offset if ((unsigned)fixp2 < 4096 && IOT(fix[4]-1,my_base_address) == jc) dputc('6',stdout); else throwCantPack("unsupported 16-bit offset relocation"); fix += (fix[1] & 0x10) ? 9 : 7; break; case 6: // 16:32 pointer if (fixp2 < 0) { // cross page pointer fixup dputc('P',stdout); fix += (fix[1] & 0x10) ? 9 : 7; break; } dputc('p',stdout); memcpy(iimage+jc+fixp2,fix+5,(fix[1] & 0x10) ? 4 : 2); set_le32(rl+4*rc++,jc+fixp2); set_le32(iimage+jc+fixp2,get_le32(iimage+jc+fixp2)+IOT(fix[4]-1,my_base_address)); memcpy(selector_fixups,"\x8C\xCA\x66\x89\x95",5); if (IOT(fix[4]-1,flags) & LEOF_WRITE) selector_fixups[1] = 0xDA; // ds set_le32(selector_fixups+5,jc+fixp2+4); selector_fixups += 9; fix += (fix[1] & 0x10) ? 9 : 7; break; case 7: // 32-bit offset if (fixp2 < 0) { fix += (fix[1] & 0x10) ? 9 : 7; break; } //if (memcmp(iimage+jc+fixp2,fix+5,(fix[1] & 0x10) ? 4 : 2)) // throwCantPack("illegal fixup offset"); // work around an pmwunlite bug: remove duplicated fixups // FIXME: fix the other cases too if (rc == 0 || get_le32(rl+4*rc-4) != jc+fixp2) { set_le32(rl+4*rc++,jc+fixp2); set_le32(iimage+jc+fixp2,get_le32(iimage+jc+fixp2)+IOT(fix[4]-1,my_base_address)); } fix += (fix[1] & 0x10) ? 9 : 7; break; case 8: // 32-bit self relative fixup if (fixp2 < 0) { // cross page self relative fixup dputc('R',stdout); fix += (fix[1] & 0x10) ? 9 : 7; break; } value = get_le32(fix+5); if (fix[1] == 0) value &= 0xffff; set_le32(iimage+jc+fixp2,(value+IOT(fix[4]-1,my_base_address))-jc-fixp2-4); set_le32(selfrel_fixups,jc+fixp2); selfrel_fixups += 4; dputc('r',stdout); fix += (fix[1] & 0x10) ? 9 : 7; break; default: throwCantPack("unsupported fixup record"); } } jc += mps; } // resize ifixups if it's too small if (sofixups < 1000) { delete[] ifixups; ifixups = new upx_byte[1000]; } fix = optimizeReloc32 (rl,rc,ifixups,iimage,1,&big_relocs); has_extra_code = srf != selector_fixups; // FIXME: this could be removed if has_extra_code = false // but then we'll need a flag *selector_fixups++ = 0xC3; // ret memcpy(fix,srf,selector_fixups-srf); // copy selector fixup code fix += selector_fixups-srf; memcpy(fix,slf,selfrel_fixups-slf); // copy self-relative fixup positions fix += selfrel_fixups-slf; set_le32(fix,0xFFFFFFFFUL); fix += 4; sofixups = ptr_diff(fix, ifixups);}#define RESERVED 0x1000void PackWcle::encodeImage(Filter *ft){ // concatenate image & preprocessed fixups unsigned isize = soimage + sofixups; ibuf.alloc(isize); memcpy(ibuf,iimage,soimage); memcpy(ibuf+soimage,ifixups,sofixups); delete[] ifixups; ifixups = NULL; oimage.allocForCompression(isize, RESERVED+512); // prepare packheader
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -