Rewrote PackHeader handling. In particuliar, Packer::putPackHeader()

was renamed to patchPackHeader(), and it is now under control of
the usual checkPatch() patch-order.

committer: mfx <mfx> 976601615 +0000
This commit is contained in:
Markus F.X.J. Oberhumer
2000-12-12 06:13:35 +00:00
parent a8eac4f2f8
commit c6481575f9
16 changed files with 175 additions and 175 deletions
+2 -2
View File
@@ -17,7 +17,7 @@ ifeq ($(strip $(UCLDIR)),)
UCLDIR = $(HOME)/local/src/ucl-0.92 UCLDIR = $(HOME)/local/src/ucl-0.92
endif endif
DEBUG = 0 DEBUG = 1
# ------------------------------------------------------- # -------------------------------------------------------
@@ -172,7 +172,7 @@ ifeq (1,2) # checkergcc
else else
ifeq ($(DEBUG),1) ifeq ($(DEBUG),1)
##CFLAGS += -O0 -gstabs+3 ##CFLAGS += -O0 -gstabs+3
CFLAGS += -O0 -gstabs+3 CFLAGS += -O0 -gdwarf-2
else else
##LDFLAGS += -static ##LDFLAGS += -static
STUBEDIT_EXE = objcopy -S -R .comment -R .note $@ && perl $(srcdir)/stub/scripts/brandelf.pl $@ && chmod 755 $@ STUBEDIT_EXE = objcopy -S -R .comment -R .note $@ && perl $(srcdir)/stub/scripts/brandelf.pl $@ && chmod 755 $@
+4 -2
View File
@@ -78,7 +78,7 @@ bool PackCom::canPack()
return false; return false;
if (!fn_has_ext(fi->getName(),"com")) if (!fn_has_ext(fi->getName(),"com"))
return false; return false;
if (find_le32(buf,128,UPX_MAGIC_LE32)) if (find_le32(buf,128,UPX_MAGIC_LE32) >= 0)
throwAlreadyPacked(); throwAlreadyPacked();
if (file_size < 1024) if (file_size < 1024)
throwCantPack("file is too small"); throwCantPack("file is too small");
@@ -111,6 +111,9 @@ void PackCom::patchLoader(OutputFile *fo,
assert(calls > 0); assert(calls > 0);
patch_le16(loader,lsize,"CT",calls); patch_le16(loader,lsize,"CT",calls);
} }
patchPackHeader(loader,e_len);
// NOTE: Depends on: decompr_start == cutpoint+1 !!! // NOTE: Depends on: decompr_start == cutpoint+1 !!!
patch_le16(loader,e_len,"JM",upper_end - 0xff - d_len - getLoaderSection("UPX1HEAD")); patch_le16(loader,e_len,"JM",upper_end - 0xff - d_len - getLoaderSection("UPX1HEAD"));
loader[getLoaderSection("COMSUBSI") - 1] = (upx_byte) -e_len; loader[getLoaderSection("COMSUBSI") - 1] = (upx_byte) -e_len;
@@ -212,7 +215,6 @@ void PackCom::pack(OutputFile *fo)
const int lsize = getLoaderSize(); const int lsize = getLoaderSize();
MemBuffer loader(lsize); MemBuffer loader(lsize);
memcpy(loader,getLoader(),lsize); memcpy(loader,getLoader(),lsize);
putPackHeader(loader,lsize);
const unsigned calls = ft.id % 3 ? ft.lastcall - 2 * ft.calls : ft.calls; const unsigned calls = ft.id % 3 ? ft.lastcall - 2 * ft.calls : ft.calls;
patchLoader(fo, loader, lsize, calls, overlapoh); patchLoader(fo, loader, lsize, calls, overlapoh);
+1 -1
View File
@@ -327,7 +327,7 @@ void PackDjgpp2::pack(OutputFile *fo)
memcpy(loader,getLoader(),lsize); memcpy(loader,getLoader(),lsize);
// patch loader // patch loader
putPackHeader(loader,lsize); patchPackHeader(loader,lsize);
patch_le32(loader,lsize,"ENTR",coff_hdr.a_entry); patch_le32(loader,lsize,"ENTR",coff_hdr.a_entry);
if (ft.id) if (ft.id)
{ {
+16 -24
View File
@@ -229,14 +229,7 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
set_le16 (crel_save,ones); set_le16 (crel_save,ones);
set_le16 (crel_save+2,seg_high); set_le16 (crel_save+2,seg_high);
#if 0 // def TESTING //OutputFile::dump("x.rel", crel_save, crel - crel_save);
//if (opt->debug >= 3)
{
FILE *f1=fopen ("x.rel","wb");
fwrite (crel_save,crel-crel_save,1,f1);
fclose (f1);
}
#endif
return crel - crel_save; return crel - crel_save;
} }
@@ -250,7 +243,7 @@ void PackExe::pack(OutputFile *fo)
unsigned ic; unsigned ic;
unsigned char flag = 0; unsigned char flag = 0;
char extra_info[32]; unsigned char extra_info[32];
unsigned eisize = 0; unsigned eisize = 0;
// //
@@ -271,7 +264,7 @@ void PackExe::pack(OutputFile *fo)
fi->seek(ih.headsize16*16,SEEK_SET); fi->seek(ih.headsize16*16,SEEK_SET);
fi->readx(ibuf,imagesize); fi->readx(ibuf,imagesize);
if (find_le32(ibuf,imagesize < 127 ? imagesize : 127, UPX_MAGIC_LE32)) if (find_le32(ibuf, UPX_MAX(imagesize, 127u), UPX_MAGIC_LE32) >= 0)
throwAlreadyPacked(); throwAlreadyPacked();
// relocations // relocations
@@ -420,7 +413,6 @@ void PackExe::pack(OutputFile *fo)
//OutputFile::dump("xxloader.dat", loader, lsize); //OutputFile::dump("xxloader.dat", loader, lsize);
// patch loader // patch loader
putPackHeader(loader,lsize);
const unsigned e_len = getLoaderSection("EXECUTPO"); const unsigned e_len = getLoaderSection("EXECUTPO");
const unsigned d_len = lsize - e_len; const unsigned d_len = lsize - e_len;
assert((e_len&15) == 0); assert((e_len&15) == 0);
@@ -452,21 +444,25 @@ void PackExe::pack(OutputFile *fo)
flag |= MAXMEM; flag |= MAXMEM;
} }
putPackHeader(loader,lsize);
// upx_bytep p = find_le32(loader,lsize,get_le32("IPCS"));
upx_bytep p = NULL;
if (p == NULL)
throwBadLoader();
if (flag & USEJUMP) if (flag & USEJUMP)
{ {
memcpy(p,&ih.ip,4); // I use a relocation entry to set the original cs
unsigned n = find_le32(loader,lsize,get_le32("IPCS"));
patch_le32(loader,lsize,get_le32("IPCS"), ih.cs*0x10000 + ih.ip);
n += packedsize + 2;
oh.relocs = 1;
oh.firstreloc = (n&0xf) + ((n>>4)<<16);
} }
else else
{ {
patch_le16(loader,lsize,"IP",ih.ip); patch_le16(loader,lsize,"IP",ih.ip);
if (ih.cs) if (ih.cs)
patch_le16(loader,lsize,"CS",ih.cs); patch_le16(loader,lsize,"CS",ih.cs);
oh.relocs = 0;
oh.firstreloc = ih.cs*0x10000 + ih.ip;
} }
oh.relocoffs = offsetof(exe_header_t, firstreloc);
if (flag & SP) if (flag & SP)
patch_le16(loader,lsize,"SP",ih.sp); patch_le16(loader,lsize,"SP",ih.sp);
if (flag & SS) if (flag & SS)
@@ -474,6 +470,8 @@ void PackExe::pack(OutputFile *fo)
if (relocsize) if (relocsize)
patch_le16(loader,lsize,"RS",(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? 0 : MAXRELOCS) - relocsize); patch_le16(loader,lsize,"RS",(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? 0 : MAXRELOCS) - relocsize);
patchPackHeader(loader,e_len);
patch_le16(loader,e_len,"BX",0x800F + 0x10*((packedsize&15)+1) - 0x10); patch_le16(loader,e_len,"BX",0x800F + 0x10*((packedsize&15)+1) - 0x10);
patch_le16(loader,e_len,"BP",(packedsize&15)+1); patch_le16(loader,e_len,"BP",(packedsize&15)+1);
@@ -485,13 +483,6 @@ void PackExe::pack(OutputFile *fo)
// finish --stub support // finish --stub support
//if (ih.relocoffs >= 0x40 && memcmp(&ih.relocoffs,">TIPPACH",8)) //if (ih.relocoffs >= 0x40 && memcmp(&ih.relocoffs,">TIPPACH",8))
// throwCantPack("FIXME"); // throwCantPack("FIXME");
// I use a relocation entry to set the original cs
oh.relocs = (flag & USEJUMP) ? 1 : 0;
oh.relocoffs = (char*)(&oh.firstreloc)-(char*)&oh;
oh.firstreloc = (p-loader) + packedsize + 2;
oh.firstreloc = (oh.firstreloc&0xf)+((oh.firstreloc>>4)<<16);
if (!(flag & USEJUMP))
oh.firstreloc = ih.cs*0x10000 + ih.ip;
extra_info[eisize++] = flag; extra_info[eisize++] = flag;
const unsigned outputlen = sizeof(oh)+lsize+packedsize+eisize; const unsigned outputlen = sizeof(oh)+lsize+packedsize+eisize;
@@ -510,6 +501,7 @@ void PackExe::pack(OutputFile *fo)
fo->write(obuf,packedsize); fo->write(obuf,packedsize);
fo->write(loader+e_len,d_len); // decompressor fo->write(loader+e_len,d_len); // decompressor
fo->write(extra_info,eisize); fo->write(extra_info,eisize);
assert(eisize <= 9);
#if 0 #if 0
printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh)); printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh));
printf("%-13s: entry : %8ld bytes\n", getName(), (long) e_len); printf("%-13s: entry : %8ld bytes\n", getName(), (long) e_len);
+1 -1
View File
@@ -351,7 +351,7 @@ void PackLinuxI386elf::pack(OutputFile *fo)
// write header // write header
const int hsize = ph.getPackHeaderSize(); const int hsize = ph.getPackHeaderSize();
set_le32(obuf, ph.magic); // note: always le32 set_le32(obuf, ph.magic); // note: always le32
putPackHeader(obuf, hsize); patchPackHeader(obuf, hsize);
fo->write(obuf, hsize); fo->write(obuf, hsize);
// write overlay offset (needed for decompression) // write overlay offset (needed for decompression)
+1 -1
View File
@@ -50,7 +50,7 @@ bool PackSys::canPack()
return false; return false;
if (!fn_has_ext(fi->getName(),"sys")) if (!fn_has_ext(fi->getName(),"sys"))
return false; return false;
if (find_le32(buf,128,UPX_MAGIC_LE32)) if (find_le32(buf,128,UPX_MAGIC_LE32) >= 0)
throwAlreadyPacked(); throwAlreadyPacked();
if (file_size < 1024) if (file_size < 1024)
throwCantPack("file is too small"); throwCantPack("file is too small");
+4 -2
View File
@@ -152,7 +152,7 @@ void PackTmt::pack(OutputFile *fo)
fi->readx(wrkmem+4,rsize); fi->readx(wrkmem+4,rsize);
const unsigned overlay = file_size - fi->tell(); const unsigned overlay = file_size - fi->tell();
if (find_le32(ibuf,128,get_le32("UPX "))) if (find_le32(ibuf,128,get_le32("UPX ")) >= 0)
throwAlreadyPacked(); throwAlreadyPacked();
if (rsize == 0) if (rsize == 0)
throwCantPack("file is already compressed with another packer"); throwCantPack("file is already compressed with another packer");
@@ -232,13 +232,15 @@ void PackTmt::pack(OutputFile *fo)
patch_le32(loader,lsize,"TEXL",(ft.id & 0xf) % 3 == 0 ? ft.calls : patch_le32(loader,lsize,"TEXL",(ft.id & 0xf) % 3 == 0 ? ft.calls :
ft.lastcall - ft.calls * 4); ft.lastcall - ft.calls * 4);
} }
patchPackHeader(loader,e_len);
const unsigned jmp_pos = find_le32(loader,e_len,get_le32("JMPD")); const unsigned jmp_pos = find_le32(loader,e_len,get_le32("JMPD"));
patch_le32(loader,e_len,"JMPD",ph.u_len+overlapoh-jmp_pos-4); patch_le32(loader,e_len,"JMPD",ph.u_len+overlapoh-jmp_pos-4);
patch_le32(loader,e_len,"ECX0",ph.c_len+d_len); patch_le32(loader,e_len,"ECX0",ph.c_len+d_len);
patch_le32(loader,e_len,"EDI0",ph.u_len+overlapoh+d_len-1); patch_le32(loader,e_len,"EDI0",ph.u_len+overlapoh+d_len-1);
patch_le32(loader,e_len,"ESI0",ph.c_len+e_len+d_len-1); patch_le32(loader,e_len,"ESI0",ph.c_len+e_len+d_len-1);
putPackHeader(loader,e_len);
//fprintf(stderr,"\nelen=%x dlen=%x copy_len=%x copy_to=%x oo=%x jmp_pos=%x ulen=%x clen=%x \n\n", //fprintf(stderr,"\nelen=%x dlen=%x copy_len=%x copy_to=%x oo=%x jmp_pos=%x ulen=%x clen=%x \n\n",
// e_len,d_len,copy_len,copy_to,overlapoh,jmp_pos,ph.u_len,ph.c_len); // e_len,d_len,copy_len,copy_to,overlapoh,jmp_pos,ph.u_len,ph.c_len);
+2 -3
View File
@@ -295,7 +295,7 @@ bool PackTos::canPack()
unsigned char buf[512]; unsigned char buf[512];
fi->readx(buf,sizeof(buf)); fi->readx(buf,sizeof(buf));
if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32)) if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32) >= 0)
throwAlreadyPacked(); throwAlreadyPacked();
if (!checkFileHeader()) if (!checkFileHeader())
@@ -467,6 +467,7 @@ void PackTos::pack(OutputFile *fo)
memcpy(loader,getLoader(),o_text); memcpy(loader,getLoader(),o_text);
// patch loader // patch loader
patchPackHeader(loader,o_text);
if (!opt->small) if (!opt->small)
patchVersion(loader,o_text); patchVersion(loader,o_text);
// patch "subq.l #1,d0" or "subq.w #1,d0" - see "up41" below // patch "subq.l #1,d0" or "subq.w #1,d0" - see "up41" below
@@ -494,8 +495,6 @@ void PackTos::pack(OutputFile *fo)
patch_be32(loader,o_text,"up12",i_data); // p_dlen patch_be32(loader,o_text,"up12",i_data); // p_dlen
patch_be32(loader,o_text,"up11",i_text); // p_tlen patch_be32(loader,o_text,"up11",i_text); // p_tlen
putPackHeader(loader,o_text);
// patch decompressor // patch decompressor
upx_byte *p = obuf + d_off; upx_byte *p = obuf + d_off;
// patch "moveq.l #1,d3" or "jmp (a5)" // patch "moveq.l #1,d3" or "jmp (a5)"
+2 -2
View File
@@ -69,7 +69,7 @@ bool PackUnix::canPack()
unsigned char buf[256]; unsigned char buf[256];
fi->seek(-(long)sizeof(buf), SEEK_END); fi->seek(-(long)sizeof(buf), SEEK_END);
fi->readx(buf,sizeof(buf)); fi->readx(buf,sizeof(buf));
if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32)) // note: always le32 if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32) >= 0) // note: always le32
throwAlreadyPacked(); throwAlreadyPacked();
return true; return true;
@@ -187,7 +187,7 @@ void PackUnix::pack(OutputFile *fo)
// write packheader // write packheader
const int hsize = ph.getPackHeaderSize(); const int hsize = ph.getPackHeaderSize();
set_le32(obuf, ph.magic); // note: always le32 set_le32(obuf, ph.magic); // note: always le32
putPackHeader(obuf, hsize); patchPackHeader(obuf, hsize);
fo->write(obuf, hsize); fo->write(obuf, hsize);
// write overlay offset (needed for decompression) // write overlay offset (needed for decompression)
+5 -13
View File
@@ -665,14 +665,9 @@ unsigned PackW32Pe::processImports() // pass 1
if (soimport == 4) if (soimport == 4)
soimport = 0; soimport = 0;
#if 0
FILE *f1=fopen("x0.imp","wb"); //OutputFile::dump("x0.imp", oimport, soimport);
fwrite(oimport,1,soimport,f1); //OutputFile::dump("x1.imp", oimpdlls, soimpdlss);
fclose(f1);
f1=fopen("x1.imp","wb");
fwrite(oimpdlls,1,soimpdlls,f1);
fclose(f1);
#endif
unsigned ilen = 0; unsigned ilen = 0;
names.flatten(); names.flatten();
@@ -1558,9 +1553,7 @@ void PackW32Pe::pack(OutputFile *fo)
processExports(&xport); processExports(&xport);
processRelocs(); processRelocs();
//FILE *f1=fopen("x1","wb"); //OutputFile::dump("x1", ibuf, usize);
//fwrite(ibuf,1,usize,f1);
//fclose(f1);
// some checks for broken linkers - disable filter if neccessary // some checks for broken linkers - disable filter if neccessary
bool allow_filter = true; bool allow_filter = true;
@@ -1670,6 +1663,7 @@ void PackW32Pe::pack(OutputFile *fo)
const unsigned lsize = getLoaderSize(); const unsigned lsize = getLoaderSize();
MemBuffer loader(lsize); MemBuffer loader(lsize);
memcpy(loader,getLoader(),lsize); memcpy(loader,getLoader(),lsize);
patchPackHeader(loader, lsize);
int identsize = 0; int identsize = 0;
const unsigned codesize = getLoaderSection("IDENTSTR",&identsize); const unsigned codesize = getLoaderSection("IDENTSTR",&identsize);
@@ -1763,8 +1757,6 @@ void PackW32Pe::pack(OutputFile *fo)
Reloc rel(1024); // new relocations are put here Reloc rel(1024); // new relocations are put here
rel.add(ic,3); rel.add(ic,3);
putPackHeader(loader,lsize);
// new PE header // new PE header
memcpy(&oh,&ih,sizeof(oh)); memcpy(&oh,&ih,sizeof(oh));
oh.filealign = 0x200; // identsplit depends on this oh.filealign = 0x200; // identsplit depends on this
+3 -2
View File
@@ -418,7 +418,7 @@ void PackWcle::pack(OutputFile *fo)
readImage(); readImage();
readNonResidentNames(); readNonResidentNames();
if (find_le32(iimage,20,get_le32("UPX "))) if (find_le32(iimage,20,get_le32("UPX ")) >= 0)
throwAlreadyPacked(); throwAlreadyPacked();
if (ih.init_ss_object != objects) if (ih.init_ss_object != objects)
@@ -526,6 +526,8 @@ void PackWcle::pack(OutputFile *fo)
} }
patch_le32(p,d_len,"RELO",mps*pages); patch_le32(p,d_len,"RELO",mps*pages);
patchPackHeader(oimage,e_len);
unsigned jpos = find_le32(oimage,e_len,get_le32("JMPD")); unsigned jpos = find_le32(oimage,e_len,get_le32("JMPD"));
patch_le32(oimage,e_len,"JMPD",ic-jpos-4); patch_le32(oimage,e_len,"JMPD",ic-jpos-4);
@@ -533,7 +535,6 @@ void PackWcle::pack(OutputFile *fo)
patch_le32(oimage,e_len,"ECX0",jpos); patch_le32(oimage,e_len,"ECX0",jpos);
patch_le32(oimage,e_len,"EDI0",((ic+d_len+3)&~3)-4); patch_le32(oimage,e_len,"EDI0",((ic+d_len+3)&~3)-4);
patch_le32(oimage,e_len,"ESI0",e_len+jpos*4-4); patch_le32(oimage,e_len,"ESI0",e_len+jpos*4-4);
putPackHeader(oimage,e_len);
writeFile(fo, opt->wcle.le); writeFile(fo, opt->wcle.le);
+14 -8
View File
@@ -562,10 +562,18 @@ void Packer::updatePackHeader()
} }
void Packer::putPackHeader(upx_bytep buf, unsigned len) int Packer::patchPackHeader(void *b, int blen)
{ {
const int size = ph.getPackHeaderSize();
assert(isValidFilter(ph.filter)); assert(isValidFilter(ph.filter));
ph.putPackHeader(buf, len);
int boff = find_le32(b, blen, ph.magic);
checkPatch(b, blen, boff, size);
unsigned char *p = (unsigned char *)b + boff;
ph.putPackHeader(p);
return boff;
} }
@@ -590,8 +598,6 @@ bool Packer::readPackHeader(unsigned len, off_t seek_offset, upx_byte *buf)
if (!ph.fillPackHeader(buf, len)) if (!ph.fillPackHeader(buf, len))
return false; return false;
if (!ph.checkPackHeader(buf + ph.buf_offset, len - ph.buf_offset))
return false;
if (ph.version > getVersion()) if (ph.version > getVersion())
throwCantUnpack("need a newer version of UPX"); throwCantUnpack("need a newer version of UPX");
@@ -641,7 +647,7 @@ void Packer::checkPatch(void *b, int blen, int boff, int size)
} }
if (b == NULL || blen <= 0 || boff < 0 || size <= 0) if (b == NULL || blen <= 0 || boff < 0 || size <= 0)
throwBadLoader(); throwBadLoader();
if (boff + size < 0 || boff + size > blen) if (boff + size <= 0 || boff + size > blen)
throwBadLoader(); throwBadLoader();
//printf("checkPatch: %p %5d %5d %d\n", b, blen, boff, size); //printf("checkPatch: %p %5d %5d %d\n", b, blen, boff, size);
if (b == last_patch) if (b == last_patch)
@@ -913,7 +919,7 @@ void Packer::addSection(const char *sname, const char *sdata, unsigned len)
int Packer::getLoaderSection(const char *name, int *slen) int Packer::getLoaderSection(const char *name, int *slen)
{ {
int ostart = linker->getSection(name, slen); int ostart = linker->getSection(name, slen);
if (ostart < 0) if (ostart <= 0)
throwBadLoader(); throwBadLoader();
return ostart; return ostart;
} }
@@ -923,7 +929,7 @@ const upx_byte *Packer::getLoader() const
{ {
int size = -1; int size = -1;
const char *oloader = linker->getLoader(&size); const char *oloader = linker->getLoader(&size);
if (oloader == NULL || size < 0) if (oloader == NULL || size <= 0)
throwBadLoader(); throwBadLoader();
return (const upx_byte *) oloader; return (const upx_byte *) oloader;
} }
@@ -933,7 +939,7 @@ int Packer::getLoaderSize() const
{ {
int size = -1; int size = -1;
const char *oloader = linker->getLoader(&size); const char *oloader = linker->getLoader(&size);
if (oloader == NULL || size < 0) if (oloader == NULL || size <= 0)
throwBadLoader(); throwBadLoader();
return size; return size;
} }
+6 -4
View File
@@ -48,11 +48,13 @@ class Filter;
class PackHeader class PackHeader
{ {
public: public:
bool fillPackHeader(upx_bytep buf, unsigned len); PackHeader();
bool checkPackHeader(const upx_bytep hbuf, int hlen) const;
void putPackHeader(upx_bytep buf, unsigned len);
int getPackHeaderSize() const; int getPackHeaderSize() const;
void putPackHeader(upx_bytep p);
bool fillPackHeader(const upx_bytep b, int blen);
public: public:
// fields stored in compressed file // fields stored in compressed file
unsigned magic; // UPX_MAGIC_LE32 unsigned magic; // UPX_MAGIC_LE32
@@ -173,7 +175,7 @@ protected:
// packheader handling // packheader handling
virtual void putPackHeader(upx_byte *buf, unsigned len); virtual int patchPackHeader(void *b, int blen);
virtual bool readPackHeader(unsigned len, off_t seek_offset, virtual bool readPackHeader(unsigned len, off_t seek_offset,
upx_byte *buf=NULL); upx_byte *buf=NULL);
+92 -88
View File
@@ -31,13 +31,22 @@
/************************************************************************* /*************************************************************************
// packheader // PackHeader
// //
// We try to be able to unpack UPX 0.7x (versions 8 & 9) and at // We try to be able to unpack UPX 0.7x (versions 8 & 9) and at
// least to detect older versions, so this is a little bit messy. // least to detect older versions, so this is a little bit messy.
**************************************************************************/ **************************************************************************/
PackHeader::PackHeader() :
version(-1), format(-1)
{
}
/*************************************************************************
// simple checksum for the header itself (since version 10) // simple checksum for the header itself (since version 10)
**************************************************************************/
static unsigned char get_packheader_checksum(const upx_bytep buf, int len) static unsigned char get_packheader_checksum(const upx_bytep buf, int len)
{ {
assert(get_le32(buf) == UPX_MAGIC_LE32); assert(get_le32(buf) == UPX_MAGIC_LE32);
@@ -57,8 +66,11 @@ static unsigned char get_packheader_checksum(const upx_bytep buf, int len)
// //
**************************************************************************/ **************************************************************************/
static int get_packheader_size(int version, int format) int PackHeader::getPackHeaderSize() const
{ {
if (format < 0 || version < 0)
throwInternalError("getPackHeaderSize");
int n = 0; int n = 0;
if (version <= 3) if (version <= 3)
n = 24; n = 24;
@@ -80,80 +92,71 @@ static int get_packheader_size(int version, int format)
else else
n = 32; n = 32;
} }
if (n == 0) if (n < 20)
throwCantUnpack("unknown header version"); throwCantUnpack("unknown header version");
return n; return n;
} }
int PackHeader::getPackHeaderSize() const
{
return get_packheader_size(version, format);
}
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackHeader::putPackHeader(upx_bytep buf, unsigned len) void PackHeader::putPackHeader(upx_bytep p)
{ {
#if defined(UNUPX) #if defined(UNUPX)
throwBadLoader(); throwBadLoader();
#else #else
int offset = find_le32(buf,len,magic); assert(get_le32(p) == UPX_MAGIC_LE32);
if (offset < 0)
throwBadLoader();
upx_bytep l = buf + offset;
l[4] = (unsigned char) version; p[4] = (unsigned char) version;
l[5] = (unsigned char) format; p[5] = (unsigned char) format;
l[6] = (unsigned char) method; p[6] = (unsigned char) method;
l[7] = (unsigned char) level; p[7] = (unsigned char) level;
// the new variable length header // the new variable length header
if (format < 128) if (format < 128)
{ {
set_le32(l+8,u_adler); set_le32(p+8,u_adler);
set_le32(l+12,c_adler); set_le32(p+12,c_adler);
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS) if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
{ {
set_le16(l+16,u_len); set_le16(p+16,u_len);
set_le16(l+18,c_len); set_le16(p+18,c_len);
l[20] = (unsigned char) filter; p[20] = (unsigned char) filter;
} }
else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH) else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH)
{ {
set_le24(l+16,u_len); set_le24(p+16,u_len);
set_le24(l+19,c_len); set_le24(p+19,c_len);
set_le24(l+22,u_file_size); set_le24(p+22,u_file_size);
l[25] = (unsigned char) filter; p[25] = (unsigned char) filter;
} }
else else
{ {
set_le32(l+16,u_len); set_le32(p+16,u_len);
set_le32(l+20,c_len); set_le32(p+20,c_len);
set_le32(l+24,u_file_size); set_le32(p+24,u_file_size);
l[28] = (unsigned char) filter; p[28] = (unsigned char) filter;
l[29] = (unsigned char) filter_cto; p[29] = (unsigned char) filter_cto;
l[30] = 0; p[30] = 0;
} }
} }
else else
{ {
set_be32(l+8,u_len); set_be32(p+8,u_len);
set_be32(l+12,c_len); set_be32(p+12,c_len);
set_be32(l+16,u_adler); set_be32(p+16,u_adler);
set_be32(l+20,c_adler); set_be32(p+20,c_adler);
set_be32(l+24,u_file_size); set_be32(p+24,u_file_size);
l[28] = (unsigned char) filter; p[28] = (unsigned char) filter;
l[29] = (unsigned char) filter_cto; p[29] = (unsigned char) filter_cto;
l[30] = 0; p[30] = 0;
} }
// store header_checksum // store header_checksum
const int hs = getPackHeaderSize(); const int size = getPackHeaderSize();
l[hs - 1] = get_packheader_checksum(l, hs - 1); p[size - 1] = get_packheader_checksum(p, size - 1);
#endif /* UNUPX */ #endif /* UNUPX */
} }
@@ -162,70 +165,72 @@ void PackHeader::putPackHeader(upx_bytep buf, unsigned len)
// //
**************************************************************************/ **************************************************************************/
bool PackHeader::fillPackHeader(upx_bytep buf, unsigned len) bool PackHeader::fillPackHeader(const upx_bytep buf, int blen)
{ {
int offset = find_le32(buf,len,magic); int boff = find_le32(buf, blen, magic);
if (offset < 0) if (boff < 0)
return false;
const int hlen = len - offset;
if (hlen < 8)
return false; return false;
upx_bytep l = buf + offset; if (boff + 8 <= 0 || boff + 8 > blen)
buf_offset = offset; throwCantUnpack("header corrupted 1");
version = l[4]; const upx_bytep p = buf + boff;
format = l[5];
method = l[6]; version = p[4];
level = l[7]; format = p[5];
method = p[6];
level = p[7];
filter_cto = 0; filter_cto = 0;
const int hs = getPackHeaderSize(); const int size = getPackHeaderSize();
if (hs > hlen) if (boff + size <= 0 || boff + size > blen)
throwCantUnpack("header corrupted"); throwCantUnpack("header corrupted 2");
//
// decode the new variable length header
//
// the new variable length header
int off_filter = 0; int off_filter = 0;
if (format < 128) if (format < 128)
{ {
u_adler = get_le32(l+8); u_adler = get_le32(p+8);
c_adler = get_le32(l+12); c_adler = get_le32(p+12);
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS) if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
{ {
u_len = get_le16(l+16); u_len = get_le16(p+16);
c_len = get_le16(l+18); c_len = get_le16(p+18);
u_file_size = u_len; u_file_size = u_len;
off_filter = 20; off_filter = 20;
} }
else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH) else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH)
{ {
u_len = get_le24(l+16); u_len = get_le24(p+16);
c_len = get_le24(l+19); c_len = get_le24(p+19);
u_file_size = get_le24(l+22); u_file_size = get_le24(p+22);
off_filter = 25; off_filter = 25;
} }
else else
{ {
u_len = get_le32(l+16); u_len = get_le32(p+16);
c_len = get_le32(l+20); c_len = get_le32(p+20);
u_file_size = get_le32(l+24); u_file_size = get_le32(p+24);
off_filter = 28; off_filter = 28;
filter_cto = l[29]; filter_cto = p[29];
} }
} }
else else
{ {
u_len = get_be32(l+8); u_len = get_be32(p+8);
c_len = get_be32(l+12); c_len = get_be32(p+12);
u_adler = get_be32(l+16); u_adler = get_be32(p+16);
c_adler = get_be32(l+20); c_adler = get_be32(p+20);
u_file_size = get_be32(l+24); u_file_size = get_be32(p+24);
off_filter = 28; off_filter = 28;
filter_cto = l[29]; filter_cto = p[29];
} }
if (version >= 10) if (version >= 10)
filter = l[off_filter]; filter = p[off_filter];
else if ((level & 128) == 0) else if ((level & 128) == 0)
filter = 0; filter = 0;
else else
@@ -239,24 +244,23 @@ bool PackHeader::fillPackHeader(upx_bytep buf, unsigned len)
} }
level &= 15; level &= 15;
return true; //
} // now some checks
//
bool PackHeader::checkPackHeader(const upx_bytep hbuf, int hlen) const
{
if (version == 0xff) if (version == 0xff)
throwCantUnpack("cannot unpack UPX ;-)"); throwCantUnpack("cannot unpack UPX ;-)");
const int hs = getPackHeaderSize();
if (hlen <= 0 || hs > hlen)
throwCantUnpack("header corrupted");
// check header_checksum // check header_checksum
if (version > 9) if (version > 9)
if (hbuf[hs - 1] != get_packheader_checksum(hbuf, hs - 1)) if (p[size - 1] != get_packheader_checksum(p, size - 1))
throwCantUnpack("header corrupted"); throwCantUnpack("header corrupted 3");
//
// success
//
this->buf_offset = boff;
return true; return true;
} }
+20 -20
View File
@@ -362,7 +362,7 @@ bool maketempname(char *ofilename, const char *ifilename,
const char *ext, bool force) const char *ext, bool force)
{ {
char *ofext = NULL, *ofname; char *ofext = NULL, *ofname;
int ofile; int ofile = -1;
strcpy(ofilename, ifilename); strcpy(ofilename, ifilename);
for (ofname = fn_basename(ofilename); *ofname; ofname++) for (ofname = fn_basename(ofilename); *ofname; ofname++)
@@ -373,15 +373,15 @@ bool maketempname(char *ofilename, const char *ifilename,
if (ofext == NULL) if (ofext == NULL)
ofext = ofilename + strlen(ofilename); ofext = ofilename + strlen(ofilename);
strcpy(ofext, ext); strcpy(ofext, ext);
if (!force)
return true; while (ofile < 1000)
if (file_exists(ofilename)) {
for (ofile = 0; ofile < 999; ofile++) if (!file_exists(ofilename))
{ return true;
sprintf(ofext, ".%03d", ofile); if (!force)
if (!file_exists(ofilename)) break;
return true; sprintf(ofext, ".%03d", ++ofile);
} }
ofilename[0] = 0; ofilename[0] = 0;
return false; return false;
@@ -391,7 +391,7 @@ bool maketempname(char *ofilename, const char *ifilename,
bool makebakname(char *ofilename, const char *ifilename, bool force) bool makebakname(char *ofilename, const char *ifilename, bool force)
{ {
char *ofext = NULL, *ofname; char *ofext = NULL, *ofname;
int ofile; int ofile = -1;
strcpy(ofilename, ifilename); strcpy(ofilename, ifilename);
for (ofname = fn_basename(ofilename); *ofname; ofname++) for (ofname = fn_basename(ofilename); *ofname; ofname++)
@@ -408,15 +408,15 @@ bool makebakname(char *ofilename, const char *ifilename, bool force)
strcat(ofilename, "~"); strcat(ofilename, "~");
else else
ofext[strlen(ofext)-1] = '~'; ofext[strlen(ofext)-1] = '~';
if (!force)
return true; while (ofile < 1000)
if (file_exists(ofilename)) {
for (ofile = 0; ofile < 999; ofile++) if (!file_exists(ofilename))
{ return true;
sprintf(ofext, ".%03d", ofile); if (!force)
if (!file_exists(ofilename)) break;
return true; sprintf(ofext, ".%03d", ++ofile);
} }
ofilename[0] = 0; ofilename[0] = 0;
return false; return false;
+2 -2
View File
@@ -1,2 +1,2 @@
#define UPX_VERSION_STRING "1.09.4" #define UPX_VERSION_STRING "1.09.5"
#define UPX_VERSION_DATE "Nov 13th 2000" #define UPX_VERSION_DATE "Dec 12th 2000"