mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
Packer::canUnpack() now can return -1.
committer: mfx <mfx> 962126554 +0000
This commit is contained in:
parent
87a1b66847
commit
51c6566092
|
@ -63,6 +63,13 @@ void throwAlreadyPacked(const char *msg)
|
|||
throw AlreadyPackedException(msg);
|
||||
}
|
||||
|
||||
void throwAlreadyPackedByUPX(const char *msg)
|
||||
{
|
||||
if (msg == NULL)
|
||||
msg = "already packed by UPX";
|
||||
throwAlreadyPacked(msg);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// decompression
|
||||
|
@ -109,7 +116,15 @@ void throwBadLoader()
|
|||
|
||||
void throwIOException(const char *msg, int e)
|
||||
{
|
||||
throw IOException(msg,e);
|
||||
throw IOException(msg, e);
|
||||
}
|
||||
|
||||
|
||||
void throwEOFException(const char *msg, int e)
|
||||
{
|
||||
if (msg == NULL && e == 0)
|
||||
msg = "premature end of file";
|
||||
throw EOFException(msg, e);
|
||||
}
|
||||
|
||||
|
||||
|
@ -121,7 +136,7 @@ const char *prettyName(const char *n)
|
|||
{
|
||||
while (*n >= '0' && *n <= '9') // gcc / egcs
|
||||
n++;
|
||||
if (strlen(n) > 6 && memcmp(n, "class ", 6) == 0) // Visual C++
|
||||
if (strncmp(n, "class ", 6) == 0) // Visual C++
|
||||
n += 6;
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -192,8 +192,9 @@ public:
|
|||
// util
|
||||
**************************************************************************/
|
||||
|
||||
#undef NORET
|
||||
#if 0 && defined(__GNUC__)
|
||||
// (noreturn) is probably not the correct semantics
|
||||
// (noreturn) is probably not the correct semantics for throwing exceptions
|
||||
#define NORET __attribute__((noreturn))
|
||||
#else
|
||||
#define NORET
|
||||
|
@ -203,6 +204,7 @@ void throwCantPack(const char *msg) NORET;
|
|||
void throwUnknownExecutableFormat(const char *msg = 0, bool warn = false) NORET;
|
||||
void throwNotCompressible(const char *msg = 0) NORET;
|
||||
void throwAlreadyPacked(const char *msg = 0) NORET;
|
||||
void throwAlreadyPackedByUPX(const char *msg = 0) NORET;
|
||||
void throwCantUnpack(const char *msg) NORET;
|
||||
void throwNotPacked(const char *msg = 0) NORET;
|
||||
void throwFilterException() NORET;
|
||||
|
@ -211,6 +213,7 @@ void throwChecksumError() NORET;
|
|||
void throwCompressedDataViolation() NORET;
|
||||
void throwInternalError(const char *msg) NORET;
|
||||
void throwIOException(const char *msg = 0, int e = 0) NORET;
|
||||
void throwEOFException(const char *msg = 0, int e = 0) NORET;
|
||||
|
||||
#undef NORET
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ int FileBase::readx(void *buf, int len)
|
|||
{
|
||||
int l = this->read(buf,len);
|
||||
if (l != len)
|
||||
throw EOFException();
|
||||
throwEOFException();
|
||||
return l;
|
||||
}
|
||||
|
||||
|
|
|
@ -220,7 +220,7 @@ void PackCom::pack(OutputFile *fo)
|
|||
//
|
||||
**************************************************************************/
|
||||
|
||||
bool PackCom::canUnpack()
|
||||
int PackCom::canUnpack()
|
||||
{
|
||||
if (!readPackHeader(128, 0))
|
||||
return false;
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual bool canUnpack();
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
virtual const unsigned getCallTrickOffset() const { return 0x100; }
|
||||
|
|
|
@ -368,13 +368,13 @@ void PackDjgpp2::pack(OutputFile *fo)
|
|||
//
|
||||
**************************************************************************/
|
||||
|
||||
bool PackDjgpp2::canUnpack()
|
||||
int PackDjgpp2::canUnpack()
|
||||
{
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
if (is_dlm(fi,coff_offset))
|
||||
throwCantUnpack("can't handle DLM");
|
||||
return readPackHeader(1024, coff_offset);
|
||||
return readPackHeader(1024, coff_offset) ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual bool canUnpack();
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
|
|
|
@ -71,7 +71,7 @@ const int *PackExe::getFilters() const
|
|||
//
|
||||
**************************************************************************/
|
||||
|
||||
bool PackExe::readExeHeader()
|
||||
bool PackExe::readFileHeader()
|
||||
{
|
||||
ih_exesize = ih_imagesize = ih_overlay = 0;
|
||||
fi->readx(&ih,sizeof(ih));
|
||||
|
@ -95,7 +95,7 @@ bool PackExe::canPack()
|
|||
{
|
||||
if (fn_has_ext(fi->getName(),"sys"))
|
||||
return false;
|
||||
if (!readExeHeader())
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
if (file_size < 1024)
|
||||
throwCantPack("file is too small");
|
||||
|
@ -519,9 +519,9 @@ void PackExe::pack(OutputFile *fo)
|
|||
//
|
||||
**************************************************************************/
|
||||
|
||||
bool PackExe::canUnpack()
|
||||
int PackExe::canUnpack()
|
||||
{
|
||||
if (!readExeHeader())
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
const off_t off = ih.headsize16*16;
|
||||
bool b = readPackHeader(128, off);
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual bool canUnpack();
|
||||
virtual int canUnpack();
|
||||
|
||||
// unpacker capabilities
|
||||
virtual bool canUnpackVersion(int version) const
|
||||
|
@ -62,7 +62,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
virtual bool readExeHeader(void);
|
||||
virtual bool readFileHeader(void);
|
||||
|
||||
struct exe_header_t
|
||||
{
|
||||
|
|
|
@ -343,7 +343,7 @@ void PackLinuxI386elf::pack(OutputFile *fo)
|
|||
}
|
||||
|
||||
if ((off_t)total_in != file_size)
|
||||
throw EOFException();
|
||||
throwEOFException();
|
||||
|
||||
// write block end marker (uncompressed size 0)
|
||||
fo->write("\x00\x00\x00\x00", 4);
|
||||
|
@ -492,7 +492,7 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
|
|||
|
||||
// all bytes must be written
|
||||
if (total_out != orig_file_size)
|
||||
throw EOFException();
|
||||
throwEOFException();
|
||||
|
||||
// finally test the checksums
|
||||
if (ph.c_adler != c_adler || ph.u_adler != u_adler)
|
||||
|
|
|
@ -46,11 +46,11 @@ public:
|
|||
virtual const char *getName() const { return "linux/elf386"; }
|
||||
virtual const int *getFilters() const { return NULL; }
|
||||
|
||||
virtual bool canPack();
|
||||
virtual bool canUnpackFormat(int format) const;
|
||||
virtual void pack(OutputFile *fo);
|
||||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual bool canUnpackFormat(int format) const;
|
||||
virtual bool canUnpackVersion(int version) const
|
||||
{ return (version >= 11); }
|
||||
|
||||
|
|
|
@ -264,11 +264,11 @@ void PackTmt::pack(OutputFile *fo)
|
|||
}
|
||||
|
||||
|
||||
bool PackTmt::canUnpack()
|
||||
int PackTmt::canUnpack()
|
||||
{
|
||||
if (!PackTmt::readFileHeader())
|
||||
return false;
|
||||
return readPackHeader(512,adam_offset);
|
||||
return readPackHeader(512,adam_offset) ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual bool canUnpack();
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
bool readFileHeader();
|
||||
|
|
|
@ -126,7 +126,7 @@ int PackTos::getLoaderSize() const
|
|||
// util
|
||||
**************************************************************************/
|
||||
|
||||
bool PackTos::readExeHeader()
|
||||
bool PackTos::readFileHeader()
|
||||
{
|
||||
fi->seek(0,SEEK_SET);
|
||||
fi->readx(&ih, FH_SIZE);
|
||||
|
@ -138,7 +138,7 @@ bool PackTos::readExeHeader()
|
|||
}
|
||||
|
||||
|
||||
bool PackTos::checkExeHeader()
|
||||
bool PackTos::checkFileHeader()
|
||||
{
|
||||
const unsigned f = ih.fh_flag;
|
||||
//printf("flags: 0x%x, text: %d, data: %d, bss: %d, sym: %d\n", f, (int)ih.fh_text, (int)ih.fh_data, (int)ih.fh_bss, (int)ih.fh_sym);
|
||||
|
@ -235,7 +235,7 @@ static int check_relocs(const upx_byte *relocs, unsigned rsize, unsigned isize,
|
|||
|
||||
bool PackTos::canPack()
|
||||
{
|
||||
if (!readExeHeader())
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
|
||||
unsigned char buf[512];
|
||||
|
@ -243,7 +243,7 @@ bool PackTos::canPack()
|
|||
if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32))
|
||||
throwAlreadyPacked();
|
||||
|
||||
if (!checkExeHeader())
|
||||
if (!checkFileHeader())
|
||||
throwCantPack("unsupported header flags");
|
||||
if (file_size < 256)
|
||||
throwCantPack("program too small");
|
||||
|
@ -253,7 +253,7 @@ bool PackTos::canPack()
|
|||
|
||||
void PackTos::fileInfo()
|
||||
{
|
||||
if (!readExeHeader())
|
||||
if (!readFileHeader())
|
||||
return;
|
||||
con_fprintf(stdout, " text: %d, data: %d, sym: %d, bss: %d, flags=0x%x\n",
|
||||
(int)ih.fh_text, (int)ih.fh_data, (int)ih.fh_sym, (int)ih.fh_bss, (int)ih.fh_flag);
|
||||
|
@ -490,17 +490,17 @@ void PackTos::pack(OutputFile *fo)
|
|||
//
|
||||
**************************************************************************/
|
||||
|
||||
bool PackTos::canUnpack()
|
||||
int PackTos::canUnpack()
|
||||
{
|
||||
if (!readPackHeader(512, 0))
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
if (!readExeHeader())
|
||||
if (!readPackHeader(512, 0))
|
||||
return false;
|
||||
// check header as set by packer
|
||||
if ((ih.fh_text & 3) != 0 || (ih.fh_data & 3) != 0 || (ih.fh_bss & 3) != 0
|
||||
|| ih.fh_sym != 0 || ih.fh_reserved != 0 || ih.fh_reloc > 1)
|
||||
throwCantUnpack("file damaged");
|
||||
if (!checkExeHeader())
|
||||
if (!checkFileHeader())
|
||||
throwCantUnpack("unsupported header flags");
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual bool canUnpack();
|
||||
virtual int canUnpack();
|
||||
|
||||
virtual void fileInfo();
|
||||
|
||||
|
@ -56,8 +56,8 @@ protected:
|
|||
virtual const upx_byte *getLoader() const;
|
||||
virtual int getLoaderSize() const;
|
||||
|
||||
bool readExeHeader();
|
||||
bool checkExeHeader();
|
||||
bool readFileHeader();
|
||||
bool checkFileHeader();
|
||||
|
||||
struct tos_header_t
|
||||
{
|
||||
|
|
|
@ -172,7 +172,7 @@ void PackUnix::pack(OutputFile *fo)
|
|||
total_out += ph.c_len;
|
||||
}
|
||||
if ((off_t)total_in != file_size)
|
||||
throw EOFException();
|
||||
throwEOFException();
|
||||
|
||||
// write block end marker (uncompressed size 0)
|
||||
fo->write("\x00\x00\x00\x00", 4);
|
||||
|
@ -203,7 +203,7 @@ void PackUnix::pack(OutputFile *fo)
|
|||
// Generic Unix canUnpack().
|
||||
**************************************************************************/
|
||||
|
||||
bool PackUnix::canUnpack()
|
||||
int PackUnix::canUnpack()
|
||||
{
|
||||
upx_byte buf[128];
|
||||
const int bufsize = sizeof(buf);
|
||||
|
@ -310,7 +310,7 @@ void PackUnix::unpack(OutputFile *fo)
|
|||
|
||||
// all bytes must be written
|
||||
if (ph.version > 8 && total_out != orig_file_size)
|
||||
throw EOFException();
|
||||
throwEOFException();
|
||||
|
||||
// finally test the checksums
|
||||
if (ph.c_adler != c_adler || ph.u_adler != u_adler)
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual bool canUnpack();
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
// called by the generic pack()
|
||||
|
@ -175,7 +175,7 @@ public:
|
|||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual bool canUnpack();
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
// virtual const upx_byte *getLoader() const;
|
||||
|
|
|
@ -137,7 +137,7 @@ void PackBvmlinuxI386::pack(OutputFile *fo)
|
|||
//
|
||||
**************************************************************************/
|
||||
|
||||
bool PackBvmlinuxI386::canUnpack()
|
||||
int PackBvmlinuxI386::canUnpack()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -56,15 +56,15 @@ public:
|
|||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual bool canUnpack();
|
||||
virtual int canUnpack();
|
||||
|
||||
// unpacker capabilities
|
||||
virtual bool canUnpackVersion(int version) const
|
||||
{
|
||||
return (version == 12);
|
||||
}
|
||||
{ return (version == 12); }
|
||||
|
||||
protected:
|
||||
virtual bool testUnpackVersion(int version) const;
|
||||
|
||||
unsigned pe_offset;
|
||||
bool isrtm;
|
||||
bool readFileHeader();
|
||||
|
|
|
@ -740,12 +740,12 @@ void PackWcle::decodeEntryTable()
|
|||
}
|
||||
|
||||
|
||||
bool PackWcle::canUnpack()
|
||||
int PackWcle::canUnpack()
|
||||
{
|
||||
if (!LeFile::readFileHeader())
|
||||
return false;
|
||||
// FIXME: 1024 could be too large for some files
|
||||
return super::readPackHeader(1024, ih.data_pages_offset+exe_offset);
|
||||
return readPackHeader(1024, ih.data_pages_offset+exe_offset) ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual bool canUnpack();
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
virtual void handleStub(OutputFile *fo);
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
**************************************************************************/
|
||||
|
||||
Packer::Packer(InputFile *f) :
|
||||
fi(f), file_size(-1),
|
||||
fi(f), file_size(-1), ph_format(-1), ph_version(-1),
|
||||
uip(NULL), pass(0), total_passes(0), linker(NULL),
|
||||
last_patch(NULL), last_patch_offset(0)
|
||||
{
|
||||
|
@ -119,6 +119,24 @@ void Packer::fileInfo()
|
|||
}
|
||||
|
||||
|
||||
bool Packer::testUnpackVersion(int version) const
|
||||
{
|
||||
if (version != ph_version && ph_version != -1)
|
||||
throwCantUnpack("program has been modified; run a virus checker!");
|
||||
if (!canUnpackVersion(version))
|
||||
throwCantUnpack("I am not compatible with older versions of UPX");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Packer::testUnpackFormat(int format) const
|
||||
{
|
||||
if (format != ph_format && ph_format != -1)
|
||||
throwCantUnpack("program has been modified; run a virus checker!");
|
||||
return canUnpackFormat(format);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// compress
|
||||
**************************************************************************/
|
||||
|
@ -575,8 +593,8 @@ bool Packer::readPackHeader(unsigned len, off_t seek_offset, upx_byte *buf)
|
|||
// Some formats might be able to unpack old versions because
|
||||
// their implementation hasn't changed. Ask them.
|
||||
if (opt->cmd != CMD_FILEINFO)
|
||||
if (!canUnpackVersion(ph.version))
|
||||
throwCantUnpack("I am not compatible with older versions of UPX");
|
||||
if (!testUnpackVersion(ph.version))
|
||||
return false;
|
||||
|
||||
if (ph.c_len >= ph.u_len || (off_t)ph.c_len >= file_size
|
||||
|| ph.version <= 0 || ph.version >= 0xff)
|
||||
|
@ -596,7 +614,7 @@ bool Packer::readPackHeader(unsigned len, off_t seek_offset, upx_byte *buf)
|
|||
throwCantUnpack("unknown compression method");
|
||||
|
||||
// Some formats might be able to unpack "subformats". Ask them.
|
||||
if (!canUnpackFormat(ph.format))
|
||||
if (!testUnpackFormat(ph.format))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
17
src/packer.h
17
src/packer.h
|
@ -119,6 +119,11 @@ public:
|
|||
virtual bool canUnpackFormat(int format) const
|
||||
{ return (format == getFormat()); }
|
||||
|
||||
protected:
|
||||
// unpacker tests - these may throw exceptions
|
||||
virtual bool testUnpackVersion(int version) const;
|
||||
virtual bool testUnpackFormat(int format) const;
|
||||
|
||||
protected:
|
||||
virtual void pack(OutputFile *fo) = 0;
|
||||
virtual void unpack(OutputFile *fo) = 0;
|
||||
|
@ -127,10 +132,14 @@ protected:
|
|||
virtual void fileInfo();
|
||||
|
||||
public:
|
||||
// canPack() should throw a cantPackException eplaining why it
|
||||
// cannot pack a recognized format.
|
||||
// canUnpack() can return -1 meaning "format recognized, but file
|
||||
// is definitely not packed" (see packmast.cpp).
|
||||
virtual bool canPack() = 0;
|
||||
virtual bool canUnpack() = 0;
|
||||
virtual bool canTest() { return canUnpack(); }
|
||||
virtual bool canList() { return canUnpack(); }
|
||||
virtual int canUnpack() = 0;
|
||||
virtual int canTest() { return canUnpack(); }
|
||||
virtual int canList() { return canUnpack(); }
|
||||
|
||||
protected:
|
||||
// main compression drivers
|
||||
|
@ -215,6 +224,8 @@ protected:
|
|||
InputFile *fi;
|
||||
off_t file_size; // will get set by constructor
|
||||
PackHeader ph; // must be filled by canUnpack()
|
||||
int ph_format;
|
||||
int ph_version;
|
||||
|
||||
// compression buffers
|
||||
MemBuffer ibuf; // input
|
||||
|
|
|
@ -112,11 +112,17 @@ static Packer* try_unpack(Packer *p, InputFile *f)
|
|||
try {
|
||||
p->initPackHeader();
|
||||
f->seek(0,SEEK_SET);
|
||||
if (p->canUnpack())
|
||||
int r = p->canUnpack();
|
||||
if (r > 0)
|
||||
{
|
||||
f->seek(0,SEEK_SET);
|
||||
return p;
|
||||
}
|
||||
if (r < 0)
|
||||
{
|
||||
// FIXME - could stop testing all other unpackers at this time
|
||||
// see canUnpack() in packer.h
|
||||
}
|
||||
} catch (IOException&) {
|
||||
} catch (...) {
|
||||
delete p;
|
||||
|
|
Loading…
Reference in New Issue
Block a user