1
0
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:
Markus F.X.J. Oberhumer 2000-06-27 17:22:34 +00:00
parent 87a1b66847
commit 51c6566092
24 changed files with 109 additions and 56 deletions

View File

@ -63,6 +63,13 @@ void throwAlreadyPacked(const char *msg)
throw AlreadyPackedException(msg); throw AlreadyPackedException(msg);
} }
void throwAlreadyPackedByUPX(const char *msg)
{
if (msg == NULL)
msg = "already packed by UPX";
throwAlreadyPacked(msg);
}
/************************************************************************* /*************************************************************************
// decompression // decompression
@ -109,7 +116,15 @@ void throwBadLoader()
void throwIOException(const char *msg, int e) 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);
} }
@ -119,9 +134,9 @@ void throwIOException(const char *msg, int e)
const char *prettyName(const char *n) const char *prettyName(const char *n)
{ {
while (*n >= '0' && *n <= '9') // gcc / egcs while (*n >= '0' && *n <= '9') // gcc / egcs
n++; n++;
if (strlen(n) > 6 && memcmp(n, "class ", 6) == 0) // Visual C++ if (strncmp(n, "class ", 6) == 0) // Visual C++
n += 6; n += 6;
return n; return n;
} }

View File

@ -192,8 +192,9 @@ public:
// util // util
**************************************************************************/ **************************************************************************/
#undef NORET
#if 0 && defined(__GNUC__) #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)) #define NORET __attribute__((noreturn))
#else #else
#define NORET #define NORET
@ -203,6 +204,7 @@ void throwCantPack(const char *msg) NORET;
void throwUnknownExecutableFormat(const char *msg = 0, bool warn = false) NORET; void throwUnknownExecutableFormat(const char *msg = 0, bool warn = false) NORET;
void throwNotCompressible(const char *msg = 0) NORET; void throwNotCompressible(const char *msg = 0) NORET;
void throwAlreadyPacked(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 throwCantUnpack(const char *msg) NORET;
void throwNotPacked(const char *msg = 0) NORET; void throwNotPacked(const char *msg = 0) NORET;
void throwFilterException() NORET; void throwFilterException() NORET;
@ -211,6 +213,7 @@ void throwChecksumError() NORET;
void throwCompressedDataViolation() NORET; void throwCompressedDataViolation() NORET;
void throwInternalError(const char *msg) NORET; void throwInternalError(const char *msg) NORET;
void throwIOException(const char *msg = 0, int e = 0) NORET; void throwIOException(const char *msg = 0, int e = 0) NORET;
void throwEOFException(const char *msg = 0, int e = 0) NORET;
#undef NORET #undef NORET

View File

@ -137,7 +137,7 @@ int FileBase::readx(void *buf, int len)
{ {
int l = this->read(buf,len); int l = this->read(buf,len);
if (l != len) if (l != len)
throw EOFException(); throwEOFException();
return l; return l;
} }

View File

@ -220,7 +220,7 @@ void PackCom::pack(OutputFile *fo)
// //
**************************************************************************/ **************************************************************************/
bool PackCom::canUnpack() int PackCom::canUnpack()
{ {
if (!readPackHeader(128, 0)) if (!readPackHeader(128, 0))
return false; return false;

View File

@ -48,7 +48,7 @@ public:
virtual void unpack(OutputFile *fo); virtual void unpack(OutputFile *fo);
virtual bool canPack(); virtual bool canPack();
virtual bool canUnpack(); virtual int canUnpack();
protected: protected:
virtual const unsigned getCallTrickOffset() const { return 0x100; } virtual const unsigned getCallTrickOffset() const { return 0x100; }

View File

@ -368,13 +368,13 @@ void PackDjgpp2::pack(OutputFile *fo)
// //
**************************************************************************/ **************************************************************************/
bool PackDjgpp2::canUnpack() int PackDjgpp2::canUnpack()
{ {
if (!readFileHeader()) if (!readFileHeader())
return false; return false;
if (is_dlm(fi,coff_offset)) if (is_dlm(fi,coff_offset))
throwCantUnpack("can't handle DLM"); throwCantUnpack("can't handle DLM");
return readPackHeader(1024, coff_offset); return readPackHeader(1024, coff_offset) ? 1 : -1;
} }

View File

@ -49,7 +49,7 @@ public:
virtual void unpack(OutputFile *fo); virtual void unpack(OutputFile *fo);
virtual bool canPack(); virtual bool canPack();
virtual bool canUnpack(); virtual int canUnpack();
protected: protected:
virtual int buildLoader(const Filter *ft); virtual int buildLoader(const Filter *ft);

View File

@ -71,7 +71,7 @@ const int *PackExe::getFilters() const
// //
**************************************************************************/ **************************************************************************/
bool PackExe::readExeHeader() bool PackExe::readFileHeader()
{ {
ih_exesize = ih_imagesize = ih_overlay = 0; ih_exesize = ih_imagesize = ih_overlay = 0;
fi->readx(&ih,sizeof(ih)); fi->readx(&ih,sizeof(ih));
@ -95,7 +95,7 @@ bool PackExe::canPack()
{ {
if (fn_has_ext(fi->getName(),"sys")) if (fn_has_ext(fi->getName(),"sys"))
return false; return false;
if (!readExeHeader()) if (!readFileHeader())
return false; return false;
if (file_size < 1024) if (file_size < 1024)
throwCantPack("file is too small"); 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; return false;
const off_t off = ih.headsize16*16; const off_t off = ih.headsize16*16;
bool b = readPackHeader(128, off); bool b = readPackHeader(128, off);

View File

@ -48,7 +48,7 @@ public:
virtual void unpack(OutputFile *fo); virtual void unpack(OutputFile *fo);
virtual bool canPack(); virtual bool canPack();
virtual bool canUnpack(); virtual int canUnpack();
// unpacker capabilities // unpacker capabilities
virtual bool canUnpackVersion(int version) const virtual bool canUnpackVersion(int version) const
@ -62,7 +62,7 @@ public:
} }
protected: protected:
virtual bool readExeHeader(void); virtual bool readFileHeader(void);
struct exe_header_t struct exe_header_t
{ {

View File

@ -343,7 +343,7 @@ void PackLinuxI386elf::pack(OutputFile *fo)
} }
if ((off_t)total_in != file_size) if ((off_t)total_in != file_size)
throw EOFException(); throwEOFException();
// write block end marker (uncompressed size 0) // write block end marker (uncompressed size 0)
fo->write("\x00\x00\x00\x00", 4); fo->write("\x00\x00\x00\x00", 4);
@ -492,7 +492,7 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
// all bytes must be written // all bytes must be written
if (total_out != orig_file_size) if (total_out != orig_file_size)
throw EOFException(); throwEOFException();
// finally test the checksums // finally test the checksums
if (ph.c_adler != c_adler || ph.u_adler != u_adler) if (ph.c_adler != c_adler || ph.u_adler != u_adler)

View File

@ -46,11 +46,11 @@ public:
virtual const char *getName() const { return "linux/elf386"; } virtual const char *getName() const { return "linux/elf386"; }
virtual const int *getFilters() const { return NULL; } virtual const int *getFilters() const { return NULL; }
virtual bool canPack();
virtual bool canUnpackFormat(int format) const;
virtual void pack(OutputFile *fo); virtual void pack(OutputFile *fo);
virtual void unpack(OutputFile *fo); virtual void unpack(OutputFile *fo);
virtual bool canPack();
virtual bool canUnpackFormat(int format) const;
virtual bool canUnpackVersion(int version) const virtual bool canUnpackVersion(int version) const
{ return (version >= 11); } { return (version >= 11); }

View File

@ -264,11 +264,11 @@ void PackTmt::pack(OutputFile *fo)
} }
bool PackTmt::canUnpack() int PackTmt::canUnpack()
{ {
if (!PackTmt::readFileHeader()) if (!PackTmt::readFileHeader())
return false; return false;
return readPackHeader(512,adam_offset); return readPackHeader(512,adam_offset) ? 1 : -1;
} }

View File

@ -48,7 +48,7 @@ public:
virtual void unpack(OutputFile *fo); virtual void unpack(OutputFile *fo);
virtual bool canPack(); virtual bool canPack();
virtual bool canUnpack(); virtual int canUnpack();
protected: protected:
bool readFileHeader(); bool readFileHeader();

View File

@ -126,7 +126,7 @@ int PackTos::getLoaderSize() const
// util // util
**************************************************************************/ **************************************************************************/
bool PackTos::readExeHeader() bool PackTos::readFileHeader()
{ {
fi->seek(0,SEEK_SET); fi->seek(0,SEEK_SET);
fi->readx(&ih, FH_SIZE); fi->readx(&ih, FH_SIZE);
@ -138,7 +138,7 @@ bool PackTos::readExeHeader()
} }
bool PackTos::checkExeHeader() bool PackTos::checkFileHeader()
{ {
const unsigned f = ih.fh_flag; 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); //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() bool PackTos::canPack()
{ {
if (!readExeHeader()) if (!readFileHeader())
return false; return false;
unsigned char buf[512]; unsigned char buf[512];
@ -243,7 +243,7 @@ bool PackTos::canPack()
if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32)) if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32))
throwAlreadyPacked(); throwAlreadyPacked();
if (!checkExeHeader()) if (!checkFileHeader())
throwCantPack("unsupported header flags"); throwCantPack("unsupported header flags");
if (file_size < 256) if (file_size < 256)
throwCantPack("program too small"); throwCantPack("program too small");
@ -253,7 +253,7 @@ bool PackTos::canPack()
void PackTos::fileInfo() void PackTos::fileInfo()
{ {
if (!readExeHeader()) if (!readFileHeader())
return; return;
con_fprintf(stdout, " text: %d, data: %d, sym: %d, bss: %d, flags=0x%x\n", 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); (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; return false;
if (!readExeHeader()) if (!readPackHeader(512, 0))
return false; return false;
// check header as set by packer // check header as set by packer
if ((ih.fh_text & 3) != 0 || (ih.fh_data & 3) != 0 || (ih.fh_bss & 3) != 0 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) || ih.fh_sym != 0 || ih.fh_reserved != 0 || ih.fh_reloc > 1)
throwCantUnpack("file damaged"); throwCantUnpack("file damaged");
if (!checkExeHeader()) if (!checkFileHeader())
throwCantUnpack("unsupported header flags"); throwCantUnpack("unsupported header flags");
return true; return true;
} }

View File

@ -48,7 +48,7 @@ public:
virtual void unpack(OutputFile *fo); virtual void unpack(OutputFile *fo);
virtual bool canPack(); virtual bool canPack();
virtual bool canUnpack(); virtual int canUnpack();
virtual void fileInfo(); virtual void fileInfo();
@ -56,8 +56,8 @@ protected:
virtual const upx_byte *getLoader() const; virtual const upx_byte *getLoader() const;
virtual int getLoaderSize() const; virtual int getLoaderSize() const;
bool readExeHeader(); bool readFileHeader();
bool checkExeHeader(); bool checkFileHeader();
struct tos_header_t struct tos_header_t
{ {

View File

@ -172,7 +172,7 @@ void PackUnix::pack(OutputFile *fo)
total_out += ph.c_len; total_out += ph.c_len;
} }
if ((off_t)total_in != file_size) if ((off_t)total_in != file_size)
throw EOFException(); throwEOFException();
// write block end marker (uncompressed size 0) // write block end marker (uncompressed size 0)
fo->write("\x00\x00\x00\x00", 4); fo->write("\x00\x00\x00\x00", 4);
@ -203,7 +203,7 @@ void PackUnix::pack(OutputFile *fo)
// Generic Unix canUnpack(). // Generic Unix canUnpack().
**************************************************************************/ **************************************************************************/
bool PackUnix::canUnpack() int PackUnix::canUnpack()
{ {
upx_byte buf[128]; upx_byte buf[128];
const int bufsize = sizeof(buf); const int bufsize = sizeof(buf);
@ -310,7 +310,7 @@ void PackUnix::unpack(OutputFile *fo)
// all bytes must be written // all bytes must be written
if (ph.version > 8 && total_out != orig_file_size) if (ph.version > 8 && total_out != orig_file_size)
throw EOFException(); throwEOFException();
// finally test the checksums // finally test the checksums
if (ph.c_adler != c_adler || ph.u_adler != u_adler) if (ph.c_adler != c_adler || ph.u_adler != u_adler)

View File

@ -47,7 +47,7 @@ public:
virtual void unpack(OutputFile *fo); virtual void unpack(OutputFile *fo);
virtual bool canPack(); virtual bool canPack();
virtual bool canUnpack(); virtual int canUnpack();
protected: protected:
// called by the generic pack() // called by the generic pack()
@ -175,7 +175,7 @@ public:
virtual void unpack(OutputFile *fo); virtual void unpack(OutputFile *fo);
virtual bool canPack(); virtual bool canPack();
virtual bool canUnpack(); virtual int canUnpack();
protected: protected:
// virtual const upx_byte *getLoader() const; // virtual const upx_byte *getLoader() const;

View File

@ -137,7 +137,7 @@ void PackBvmlinuxI386::pack(OutputFile *fo)
// //
**************************************************************************/ **************************************************************************/
bool PackBvmlinuxI386::canUnpack() int PackBvmlinuxI386::canUnpack()
{ {
return false; return false;
} }

View File

@ -56,15 +56,15 @@ public:
virtual void unpack(OutputFile *fo); virtual void unpack(OutputFile *fo);
virtual bool canPack(); virtual bool canPack();
virtual bool canUnpack(); virtual int canUnpack();
// unpacker capabilities // unpacker capabilities
virtual bool canUnpackVersion(int version) const virtual bool canUnpackVersion(int version) const
{ { return (version == 12); }
return (version == 12);
}
protected: protected:
virtual bool testUnpackVersion(int version) const;
unsigned pe_offset; unsigned pe_offset;
bool isrtm; bool isrtm;
bool readFileHeader(); bool readFileHeader();

View File

@ -740,12 +740,12 @@ void PackWcle::decodeEntryTable()
} }
bool PackWcle::canUnpack() int PackWcle::canUnpack()
{ {
if (!LeFile::readFileHeader()) if (!LeFile::readFileHeader())
return false; return false;
// FIXME: 1024 could be too large for some files // 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;
} }

View File

@ -48,7 +48,7 @@ public:
virtual void unpack(OutputFile *fo); virtual void unpack(OutputFile *fo);
virtual bool canPack(); virtual bool canPack();
virtual bool canUnpack(); virtual int canUnpack();
protected: protected:
virtual void handleStub(OutputFile *fo); virtual void handleStub(OutputFile *fo);

View File

@ -39,7 +39,7 @@
**************************************************************************/ **************************************************************************/
Packer::Packer(InputFile *f) : 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), uip(NULL), pass(0), total_passes(0), linker(NULL),
last_patch(NULL), last_patch_offset(0) 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 // 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 // Some formats might be able to unpack old versions because
// their implementation hasn't changed. Ask them. // their implementation hasn't changed. Ask them.
if (opt->cmd != CMD_FILEINFO) if (opt->cmd != CMD_FILEINFO)
if (!canUnpackVersion(ph.version)) if (!testUnpackVersion(ph.version))
throwCantUnpack("I am not compatible with older versions of UPX"); return false;
if (ph.c_len >= ph.u_len || (off_t)ph.c_len >= file_size if (ph.c_len >= ph.u_len || (off_t)ph.c_len >= file_size
|| ph.version <= 0 || ph.version >= 0xff) || 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"); throwCantUnpack("unknown compression method");
// Some formats might be able to unpack "subformats". Ask them. // Some formats might be able to unpack "subformats". Ask them.
if (!canUnpackFormat(ph.format)) if (!testUnpackFormat(ph.format))
return false; return false;
return true; return true;

View File

@ -119,6 +119,11 @@ public:
virtual bool canUnpackFormat(int format) const virtual bool canUnpackFormat(int format) const
{ return (format == getFormat()); } { return (format == getFormat()); }
protected:
// unpacker tests - these may throw exceptions
virtual bool testUnpackVersion(int version) const;
virtual bool testUnpackFormat(int format) const;
protected: protected:
virtual void pack(OutputFile *fo) = 0; virtual void pack(OutputFile *fo) = 0;
virtual void unpack(OutputFile *fo) = 0; virtual void unpack(OutputFile *fo) = 0;
@ -127,10 +132,14 @@ protected:
virtual void fileInfo(); virtual void fileInfo();
public: 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 canPack() = 0;
virtual bool canUnpack() = 0; virtual int canUnpack() = 0;
virtual bool canTest() { return canUnpack(); } virtual int canTest() { return canUnpack(); }
virtual bool canList() { return canUnpack(); } virtual int canList() { return canUnpack(); }
protected: protected:
// main compression drivers // main compression drivers
@ -215,6 +224,8 @@ protected:
InputFile *fi; InputFile *fi;
off_t file_size; // will get set by constructor off_t file_size; // will get set by constructor
PackHeader ph; // must be filled by canUnpack() PackHeader ph; // must be filled by canUnpack()
int ph_format;
int ph_version;
// compression buffers // compression buffers
MemBuffer ibuf; // input MemBuffer ibuf; // input

View File

@ -112,11 +112,17 @@ static Packer* try_unpack(Packer *p, InputFile *f)
try { try {
p->initPackHeader(); p->initPackHeader();
f->seek(0,SEEK_SET); f->seek(0,SEEK_SET);
if (p->canUnpack()) int r = p->canUnpack();
if (r > 0)
{ {
f->seek(0,SEEK_SET); f->seek(0,SEEK_SET);
return p; return p;
} }
if (r < 0)
{
// FIXME - could stop testing all other unpackers at this time
// see canUnpack() in packer.h
}
} catch (IOException&) { } catch (IOException&) {
} catch (...) { } catch (...) {
delete p; delete p;