1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00

Moved the generic linux/386 format into the new p_lx_exc.{h,cpp} files.

committer: mfx <mfx> 977423460 +0000
This commit is contained in:
Markus F.X.J. Oberhumer 2000-12-21 18:31:00 +00:00
parent 5d74b7252d
commit 1d948c839d
9 changed files with 321 additions and 230 deletions

View File

@ -61,7 +61,8 @@ OBJECTS1 = \
compress$o except$o file$o lefile$o \
filter$o mem$o msg$o stdcxx$o work$o ui$o \
packer$o packhead$o packmast$o \
p_com$o p_djgpp2$o p_exe$o p_lx_elf$o p_lx_sep$o p_lx_sh$o \
p_com$o p_djgpp2$o p_exe$o \
p_lx_elf$o p_lx_exc$o p_lx_sep$o p_lx_sh$o \
p_sys$o p_tmt$o p_tos$o \
p_unix$o p_vmlinz$o p_w32pe$o p_wcle$o
@ -446,7 +447,8 @@ mygetopt$o: mygetopt.h
packer$o: packer.h filter.h linker.h ui.h version.h
packhead$o: packer.h
packmast$o: packmast.h packer.h lefile.h \
p_com.h p_djgpp2.h p_exe.h p_lx_elf.h p_lx_sep.h p_lx_sh.h \
p_com.h p_djgpp2.h p_exe.h \
p_lx_elf.h p_lx_exc.h p_lx_sep.h p_lx_sh.h \
p_sys.h p_tmt.h p_tos.h \
p_unix.h p_vmlinz.h p_vxd.h p_w32pe.h p_wcle.h
ui$o: packer.h ui.h
@ -458,10 +460,12 @@ p_djgpp2$o: packer.h p_djgpp2.h stub/stubify.h \
stub/l_djgpp2.h
p_exe$o: packer.h p_exe.h \
stub/l_exe.h
p_lx_elf$o: packer.h p_lx_elf.h p_unix.h p_elf.h \
p_lx_elf$o: packer.h p_unix.h p_elf.h p_lx_exc.h p_lx_elf.h \
stub/l_le_n2b.h stub/l_le_n2d.h
p_lx_sep$o: packer.h p_lx_sep.h p_lx_elf.h p_unix.h p_elf.h
p_lx_sh$o: packer.h p_lx_sh.h p_unix.h p_elf.h \
p_lx_exc$o: packer.h p_unix.h p_elf.h p_lx_exc.h \
stub/l_lx_n2b.h stub/l_lx_n2d.h
p_lx_sep$o: packer.h p_unix.h p_elf.h p_lx_exc.h p_lx_elf.h p_lx_sep.h
p_lx_sh$o: packer.h p_unix.h p_elf.h p_lx_exc.h p_lx_sh.h \
stub/l_sh_n2b.h stub/l_sh_n2d.h
p_sys$o: packer.h p_sys.h p_com.h \
stub/l_sys.h
@ -470,8 +474,7 @@ p_tmt$o: packer.h p_tmt.h \
p_tos$o: packer.h p_tos.h \
stub/l_t_n2b.h stub/l_t_n2bs.h \
stub/l_t_n2d.h stub/l_t_n2ds.h
p_unix$o: packer.h p_unix.h p_elf.h \
stub/l_lx_n2b.h stub/l_lx_n2d.h
p_unix$o: packer.h p_unix.h p_elf.h
p_vmlinz$o: packer.h p_vmlinz.h \
stub/l_vmlinz.h
p_w32pe$o: packer.h p_w32pe.h \

View File

@ -36,6 +36,7 @@
#include "packer.h"
#include "p_elf.h"
#include "p_unix.h"
#include "p_lx_exc.h"
#include "p_lx_elf.h"

237
src/p_lx_exc.cpp Normal file
View File

@ -0,0 +1,237 @@
/* p_lx_exc.cpp --
This file is part of the UPX executable compressor.
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996-2000 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
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
*/
#include "conf.h"
#include "file.h"
#include "packer.h"
#include "p_elf.h"
#include "p_unix.h"
#include "p_lx_exc.h"
/*************************************************************************
// linux/386 (generic "execve" format)
**************************************************************************/
static const
#include "stub/l_lx_n2b.h"
static const
#include "stub/l_lx_n2d.h"
int PackLinuxI386::getCompressionMethod() const
{
if (M_IS_NRV2B(opt->method))
return M_NRV2B_LE32;
if (M_IS_NRV2D(opt->method))
return M_NRV2D_LE32;
return opt->level > 1 && file_size >= 512*1024 ? M_NRV2D_LE32 : M_NRV2B_LE32;
}
const upx_byte *PackLinuxI386::getLoader() const
{
if (M_IS_NRV2B(opt->method))
return linux_i386exec_nrv2b_loader;
if (M_IS_NRV2D(opt->method))
return linux_i386exec_nrv2d_loader;
return NULL;
}
int PackLinuxI386::getLoaderSize() const
{
if (0!=lsize) {
return lsize;
}
if (M_IS_NRV2B(opt->method))
return sizeof(linux_i386exec_nrv2b_loader);
if (M_IS_NRV2D(opt->method))
return sizeof(linux_i386exec_nrv2d_loader);
return 0;
}
int PackLinuxI386::getLoaderPrefixSize() const
{
return 116;
}
/*************************************************************************
//
**************************************************************************/
bool PackLinuxI386::canPack()
{
if (exetype != 0)
return super::canPack();
Elf_LE32_Ehdr ehdr;
unsigned char *buf = ehdr.e_ident;
fi->readx(&ehdr, sizeof(ehdr));
fi->seek(0, SEEK_SET);
exetype = 0;
const unsigned l = get_le32(buf);
#if 0
// NOTE: ELF executables are now handled by p_lx_elf.cpp.
if (!memcmp(buf, "\x7f\x45\x4c\x46\x01\x01\x01", 7)) // ELF 32-bit LSB
{
// FIXME: add special checks for uncompresed "vmlinux" kernel
exetype = 1;
// now check the ELF header
if (!memcmp(buf+8, "FreeBSD", 7)) // branded
exetype = 0;
if (ehdr.e_type != 2) // executable
exetype = 0;
if (ehdr.e_machine != 3 && ehdr.e_machine != 6) // Intel 80[34]86
exetype = 0;
if (ehdr.e_version != 1) // version
exetype = 0;
}
else
#endif
if (l == 0x00640107 || l == 0x00640108 || l == 0x0064010b || l == 0x006400cc)
{
// OMAGIC / NMAGIC / ZMAGIC / QMAGIC
exetype = 2;
// FIXME: N_TRSIZE, N_DRSIZE
// FIXME: check for aout shared libraries
}
#if defined(__linux__)
// only compress scripts when running under Linux
else if (!memcmp(buf, "#!/", 3)) // #!/bin/sh
exetype = -1;
else if (!memcmp(buf, "#! /", 4)) // #! /bin/sh
exetype = -1;
else if (!memcmp(buf, "\xca\xfe\xba\xbe", 4)) // Java bytecode
exetype = -2;
#endif
return super::canPack();
}
void PackLinuxI386::patchLoader()
{
lsize = getLoaderSize();
// patch loader
// note: we only can use /proc/<pid>/fd when exetype > 0.
// also, we sleep much longer when compressing a script.
patch_le32(loader,lsize,"UPX4",exetype > 0 ? 3 : 15); // sleep time
patch_le32(loader,lsize,"UPX3",exetype > 0 ? 0 : 0x7fffffff);
patch_le32(loader,lsize,"UPX2",progid);
patchVersion(loader,lsize);
Elf_LE32_Ehdr *const ehdr = (Elf_LE32_Ehdr *)(void *)loader;
Elf_LE32_Phdr *const phdr = (Elf_LE32_Phdr *)(1+ehdr);
// stub/scripts/setfold.pl puts address of 'fold_begin' in phdr[1].p_offset
off_t const fold_begin = phdr[1].p_offset;
assert(fold_begin > 0);
assert(fold_begin < (off_t)lsize);
MemBuffer cprLoader(lsize);
// compress compiled C-code portion of loader
upx_uint const uncLsize = lsize - fold_begin;
upx_uint cprLsize;
int r = upx_compress(loader + fold_begin, uncLsize, cprLoader, &cprLsize,
NULL, opt->method, 10, NULL, NULL);
if (r != UPX_E_OK || cprLsize >= uncLsize)
throwInternalError("loaded compression failed");
memcpy(fold_begin+loader, cprLoader, cprLsize);
lsize = fold_begin + cprLsize;
phdr->p_filesz = lsize;
// phdr->p_memsz is the decompressed size
// The beginning of our loader consists of a elf_hdr (52 bytes) and
// one section elf_phdr (32 byte) now,
// another section elf_phdr (32 byte) later, so we have 12 free bytes
// from offset 116 to the program start at offset 128.
// These 12 bytes are used for l_info by ::patchLoaderChecksum().
assert(get_le32(loader + 28) == 52); // e_phoff
assert(get_le32(loader + 32) == 0); // e_shoff
assert(get_le16(loader + 40) == 52); // e_ehsize
assert(get_le16(loader + 42) == 32); // e_phentsize
assert(get_le16(loader + 44) == 1); // e_phnum
assert(get_le16(loader + 48) == 0); // e_shnum
assert(lsize > 128 && lsize < 4096);
patchLoaderChecksum();
}
void PackLinuxI386::patchLoaderChecksum()
{
l_info *const lp = (l_info *)(loader + getLoaderPrefixSize());
// checksum for loader + p_info
lp->l_checksum = 0; // (this checksum is currently unused)
lp->l_magic = UPX_ELF_MAGIC;
lp->l_lsize = (unsigned short) lsize;
lp->l_version = (unsigned char) ph.version;
lp->l_format = (unsigned char) ph.format;
unsigned adler = upx_adler32(0,NULL,0);
adler = upx_adler32(adler, loader, lsize + sizeof(p_info));
lp->l_checksum = adler;
}
void PackLinuxI386::updateLoader(OutputFile *fo)
{
#define PAGE_MASK (~0<<12)
Elf_LE32_Ehdr *ehdr = (Elf_LE32_Ehdr *)(unsigned char *)loader;
ehdr->e_phnum = 2;
// The first Phdr maps the stub (instructions, data, bss) rwx.
// The second Phdr maps the overlay r--,
// to defend against /usr/bin/strip removing the overlay.
Elf_LE32_Phdr *const phdro = 1+(Elf_LE32_Phdr *)(1+ehdr);
phdro->p_type = PT_LOAD;
phdro->p_offset = lsize;
phdro->p_paddr = phdro->p_vaddr = 0x00400000 + (lsize &~ PAGE_MASK);
phdro->p_memsz = phdro->p_filesz = fo->getBytesWritten() - lsize;
phdro->p_flags = PF_R;
phdro->p_align = -PAGE_MASK;
patchLoaderChecksum();
fo->seek(0, SEEK_SET);
fo->rewrite(loader, 0x80);
#undef PAGE_MASK
}
/*
vi:ts=4:et
*/

69
src/p_lx_exc.h Normal file
View File

@ -0,0 +1,69 @@
/* p_lx_exc.h --
This file is part of the UPX executable compressor.
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996-2000 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
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
*/
#ifndef __UPX_P_LX_EXC_H
#define __UPX_P_LX_EXC_H
/*************************************************************************
// linux/386 (generic "execve" format)
**************************************************************************/
class PackLinuxI386 : public PackUnixLe32
{
typedef PackUnixLe32 super;
public:
PackLinuxI386(InputFile *f) : super(f) { }
virtual int getFormat() const { return UPX_F_LINUX_i386; }
virtual const char *getName() const { return "linux/386"; }
virtual int getCompressionMethod() const;
virtual bool canPack();
protected:
virtual const upx_byte *getLoader() const;
virtual int getLoaderSize() const;
virtual int getLoaderPrefixSize() const;
virtual void patchLoader();
virtual void patchLoaderChecksum();
virtual void updateLoader(OutputFile *);
enum {
UPX_ELF_MAGIC = 0x5850557f // "\x7fUPX"
};
};
#endif /* already included */
/*
vi:ts=4:et
*/

View File

@ -36,6 +36,7 @@
#include "packer.h"
#include "p_elf.h"
#include "p_unix.h"
#include "p_lx_exc.h"
#include "p_lx_elf.h"
#include "p_lx_sep.h"

View File

@ -36,6 +36,7 @@
#include "packer.h"
#include "p_elf.h"
#include "p_unix.h"
#include "p_lx_exc.h"
#include "p_lx_sh.h"
static const

View File

@ -322,198 +322,6 @@ void PackUnix::unpack(OutputFile *fo)
}
/*************************************************************************
// linux/i386 (generic "execve" format)
**************************************************************************/
static const
#include "stub/l_lx_n2b.h"
static const
#include "stub/l_lx_n2d.h"
int PackLinuxI386::getCompressionMethod() const
{
if (M_IS_NRV2B(opt->method))
return M_NRV2B_LE32;
if (M_IS_NRV2D(opt->method))
return M_NRV2D_LE32;
return opt->level > 1 && file_size >= 512*1024 ? M_NRV2D_LE32 : M_NRV2B_LE32;
}
const upx_byte *PackLinuxI386::getLoader() const
{
if (M_IS_NRV2B(opt->method))
return linux_i386exec_nrv2b_loader;
if (M_IS_NRV2D(opt->method))
return linux_i386exec_nrv2d_loader;
return NULL;
}
int PackLinuxI386::getLoaderSize() const
{
if (0!=lsize) {
return lsize;
}
if (M_IS_NRV2B(opt->method))
return sizeof(linux_i386exec_nrv2b_loader);
if (M_IS_NRV2D(opt->method))
return sizeof(linux_i386exec_nrv2d_loader);
return 0;
}
int PackLinuxI386::getLoaderPrefixSize() const
{
return 116;
}
bool PackLinuxI386::canPack()
{
if (exetype != 0)
return super::canPack();
Elf_LE32_Ehdr ehdr;
unsigned char *buf = ehdr.e_ident;
fi->readx(&ehdr, sizeof(ehdr));
fi->seek(0, SEEK_SET);
exetype = 0;
const unsigned l = get_le32(buf);
#if 0
// NOTE: ELF executables are now handled by p_lx_elf.cpp.
if (!memcmp(buf, "\x7f\x45\x4c\x46\x01\x01\x01", 7)) // ELF 32-bit LSB
{
// FIXME: add special checks for uncompresed "vmlinux" kernel
exetype = 1;
// now check the ELF header
if (!memcmp(buf+8, "FreeBSD", 7)) // branded
exetype = 0;
if (ehdr.e_type != 2) // executable
exetype = 0;
if (ehdr.e_machine != 3 && ehdr.e_machine != 6) // Intel 80[34]86
exetype = 0;
if (ehdr.e_version != 1) // version
exetype = 0;
}
else
#endif
if (l == 0x00640107 || l == 0x00640108 || l == 0x0064010b || l == 0x006400cc)
{
// OMAGIC / NMAGIC / ZMAGIC / QMAGIC
exetype = 2;
// FIXME: N_TRSIZE, N_DRSIZE
// FIXME: check for aout shared libraries
}
#if defined(__linux__)
// only compress scripts when running under Linux
else if (!memcmp(buf, "#!/", 3)) // #!/bin/sh
exetype = -1;
else if (!memcmp(buf, "#! /", 4)) // #! /bin/sh
exetype = -1;
else if (!memcmp(buf, "\xca\xfe\xba\xbe", 4)) // Java bytecode
exetype = -2;
#endif
return super::canPack();
}
void PackLinuxI386::patchLoader()
{
lsize = getLoaderSize();
// patch loader
// note: we only can use /proc/<pid>/fd when exetype > 0.
// also, we sleep much longer when compressing a script.
patch_le32(loader,lsize,"UPX4",exetype > 0 ? 3 : 15); // sleep time
patch_le32(loader,lsize,"UPX3",exetype > 0 ? 0 : 0x7fffffff);
patch_le32(loader,lsize,"UPX2",progid);
patchVersion(loader,lsize);
Elf_LE32_Ehdr *const ehdr = (Elf_LE32_Ehdr *)(void *)loader;
Elf_LE32_Phdr *const phdr = (Elf_LE32_Phdr *)(1+ehdr);
// stub/scripts/setfold.pl puts address of 'fold_begin' in phdr[1].p_offset
off_t const fold_begin = phdr[1].p_offset;
assert(fold_begin > 0);
assert(fold_begin < (off_t)lsize);
MemBuffer cprLoader(lsize);
// compress compiled C-code portion of loader
upx_uint const uncLsize = lsize - fold_begin;
upx_uint cprLsize;
int r = upx_compress(loader + fold_begin, uncLsize, cprLoader, &cprLsize,
NULL, opt->method, 10, NULL, NULL);
if (r != UPX_E_OK || cprLsize >= uncLsize)
throwInternalError("loaded compression failed");
memcpy(fold_begin+loader, cprLoader, cprLsize);
lsize = fold_begin + cprLsize;
phdr->p_filesz = lsize;
// phdr->p_memsz is the decompressed size
// The beginning of our loader consists of a elf_hdr (52 bytes) and
// one section elf_phdr (32 byte) now,
// another section elf_phdr (32 byte) later, so we have 12 free bytes
// from offset 116 to the program start at offset 128.
// These 12 bytes are used for l_info by ::patchLoaderChecksum().
assert(get_le32(loader + 28) == 52); // e_phoff
assert(get_le32(loader + 32) == 0); // e_shoff
assert(get_le16(loader + 40) == 52); // e_ehsize
assert(get_le16(loader + 42) == 32); // e_phentsize
assert(get_le16(loader + 44) == 1); // e_phnum
assert(get_le16(loader + 48) == 0); // e_shnum
assert(lsize > 128 && lsize < 4096);
patchLoaderChecksum();
}
void PackLinuxI386::patchLoaderChecksum()
{
l_info *const lp = (l_info *)(loader + getLoaderPrefixSize());
// checksum for loader + p_info
lp->l_checksum = 0; // (this checksum is currently unused)
lp->l_magic = UPX_ELF_MAGIC;
lp->l_lsize = (unsigned short) lsize;
lp->l_version = (unsigned char) ph.version;
lp->l_format = (unsigned char) ph.format;
unsigned adler = upx_adler32(0,NULL,0);
adler = upx_adler32(adler, loader, lsize + sizeof(p_info));
lp->l_checksum = adler;
}
void PackLinuxI386::updateLoader(OutputFile *fo)
{
#define PAGE_MASK (~0<<12)
Elf_LE32_Ehdr *ehdr = (Elf_LE32_Ehdr *)(unsigned char *)loader;
ehdr->e_phnum = 2;
// The first Phdr maps the stub (instructions, data, bss) rwx.
// The second Phdr maps the overlay r--,
// to defend against /usr/bin/strip removing the overlay.
Elf_LE32_Phdr *const phdro = 1+(Elf_LE32_Phdr *)(1+ehdr);
phdro->p_type = PT_LOAD;
phdro->p_offset = lsize;
phdro->p_paddr = phdro->p_vaddr = 0x00400000 + (lsize &~ PAGE_MASK);
phdro->p_memsz = phdro->p_filesz = fo->getBytesWritten() - lsize;
phdro->p_flags = PF_R;
phdro->p_align = -PAGE_MASK;
patchLoaderChecksum();
fo->seek(0, SEEK_SET);
fo->rewrite(loader, 0x80);
#undef PAGE_MASK
}
/*
vi:ts=4:et
*/

View File

@ -126,36 +126,6 @@ protected:
};
/*************************************************************************
// linux/i386 (generic "execve" format)
**************************************************************************/
class PackLinuxI386 : public PackUnixLe32
{
typedef PackUnixLe32 super;
public:
PackLinuxI386(InputFile *f) : super(f) { }
virtual int getFormat() const { return UPX_F_LINUX_i386; }
virtual const char *getName() const { return "linux/386"; }
virtual int getCompressionMethod() const;
virtual bool canPack();
protected:
virtual const upx_byte *getLoader() const;
virtual int getLoaderSize() const;
virtual int getLoaderPrefixSize() const;
virtual void patchLoader();
virtual void patchLoaderChecksum();
virtual void updateLoader(OutputFile *);
enum {
UPX_ELF_MAGIC = 0x5850557f // "\x7fUPX"
};
};
/*************************************************************************
// solaris/sparc
**************************************************************************/

View File

@ -34,8 +34,9 @@
#include "p_com.h"
#include "p_djgpp2.h"
#include "p_exe.h"
#include "p_elf.h"
#include "p_unix.h"
#include "p_elf.h"
#include "p_lx_exc.h"
#include "p_lx_elf.h"
#include "p_lx_sep.h"
#include "p_lx_sh.h"