filters for unix(linux)

Modified Files:
	filteri.cpp filter/ctojr.h linker.cpp linker.h mem.cpp mem.h
	p_lx_elf.cpp p_lx_elf.h
	p_lx_exc.cpp p_lx_exc.h
	p_lx_sh.cpp  p_lx_sh.h
	p_unix.cpp packer.cpp packer.h packhead.cpp
	stub/Makefile    stub/macros.ash
	stub/l_lx_elf.c  stub/l_lx_elf86.asm  stub/l_lx_elf86.lds
	stub/l_lx_exec.c stub/l_lx_exec86.asm stub/l_lx_exec86.lds
	                 stub/l_lx_sh86.asm   stub/l_lx_sh86.lds
Added Files:
	filter/ctok.h
	stub/fold_elf86.asm stub/fold_exec86.asm stub/fold_sh86.asm

committer: jreiser <jreiser> 979796725 +0000
This commit is contained in:
John Reiser
2001-01-18 05:45:25 +00:00
parent 4d45677160
commit df9db96bd1
30 changed files with 2014 additions and 1105 deletions
+199 -71
View File
@@ -4,6 +4,7 @@
Copyright (C) 1996-2001 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996-2001 Laszlo Molnar
Copyright (C) 2001 John F. Reiser
All Rights Reserved.
UPX and the UCL library are free software; you can redistribute them
@@ -21,14 +22,16 @@
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.com ml1050@cdata.tvnet.hu
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
*/
#include "conf.h"
#include "file.h"
#include "filter.h"
#include "linker.h"
#include "packer.h"
#include "p_elf.h"
#include "p_unix.h"
@@ -42,9 +45,9 @@
**************************************************************************/
static const
#include "stub/l_lx_n2b.h"
#include "stub/l_lx_exec86.h"
static const
#include "stub/l_lx_n2d.h"
#include "stub/fold_exec86.h"
const int *PackLinuxI386::getCompressionMethods(int method, int level) const
@@ -61,29 +64,196 @@ const int *PackLinuxI386::getCompressionMethods(int method, int level) const
return m_nrv2d;
}
const upx_byte *PackLinuxI386::getLoader() const
int const *
PackLinuxI386::getFilters() const
{
if (M_IS_NRV2B(ph.method))
return linux_i386exec_nrv2b_loader;
if (M_IS_NRV2D(ph.method))
return linux_i386exec_nrv2d_loader;
return NULL;
static const int filters[] = {
0x49, 0x46,
0x83, 0x86, 0x80, 0x84, 0x87, 0x81, 0x82, 0x85,
0x24, 0x16, 0x13, 0x14, 0x11, 0x25, 0x15, 0x12,
-1 };
return filters;
}
struct cprElfhdr {
struct Elf_LE32_Ehdr ehdr;
struct Elf_LE32_Phdr phdr[2];
struct PackUnix::l_info linfo;
};
int PackLinuxI386::getLoaderSize() const
int
PackLinuxI386::buildLinuxLoader(
upx_byte const *const proto,
unsigned const szproto,
upx_byte const *const fold,
unsigned const szfold,
Filter const *ft,
unsigned const brka
)
{
if (0!=lsize) {
return lsize;
initLoader(proto, szproto);
struct cprElfhdr elfhdr = *(struct cprElfhdr const *)fold;
memset(&elfhdr.linfo, 0, sizeof(elfhdr.linfo));
// Info for OS kernel to set the brk()
if (brka) {
assert(ph.format==UPX_F_LINUX_ELF_i386
|| ph.format==UPX_F_LINUX_SH_i386 );
if (ph.format==UPX_F_LINUX_SH_i386) {
assert(elfhdr.ehdr.e_phnum==1);
elfhdr.ehdr.e_phnum = 2;
}
elfhdr.phdr[1].p_offset = 0xfff&brka;
elfhdr.phdr[1].p_vaddr = brka;
elfhdr.phdr[1].p_paddr = brka;
elfhdr.phdr[1].p_filesz = 0;
elfhdr.phdr[1].p_memsz = 0;
}
if (M_IS_NRV2B(ph.method))
return sizeof(linux_i386exec_nrv2b_loader);
if (M_IS_NRV2D(ph.method))
return sizeof(linux_i386exec_nrv2d_loader);
return 0;
// The beginning of our loader consists of a elf_hdr (52 bytes) and
// two sections elf_phdr (2 * 32 byte), so we have 12 free bytes
// from offset 116 to the program start at offset 128.
assert(elfhdr.ehdr.e_phoff == sizeof(Elf_LE32_Ehdr));
assert(elfhdr.ehdr.e_shoff == 0);
assert(elfhdr.ehdr.e_ehsize == sizeof(Elf_LE32_Ehdr));
assert(elfhdr.ehdr.e_phentsize == sizeof(Elf_LE32_Phdr));
assert(elfhdr.ehdr.e_phnum == (unsigned)(1+ (0!=brka)));
assert(elfhdr.ehdr.e_shnum == 0);
linker->addSection("ELFHEADX", (unsigned char const *)&elfhdr, sizeof(elfhdr));
addLoader("ELFHEADX", 0);
struct {
upx_uint sz_unc; // uncompressed
upx_uint sz_cpr; // compressed
} h = {
szfold - sizeof(elfhdr), 0
};
unsigned char const *const uncLoader = (unsigned char const *)(1+
(struct cprElfhdr const *)fold );
unsigned char *const cprLoader = new unsigned char[sizeof(h) + h.sz_unc];
int r = upx_compress(uncLoader, h.sz_unc, sizeof(h) + cprLoader, &h.sz_cpr,
NULL, ph.method, 10, NULL, NULL );
if (r != UPX_E_OK || h.sz_cpr >= h.sz_unc)
throwInternalError("loader compression failed");
memcpy(cprLoader, &h, sizeof(h));
linker->addSection("FOLDEXEC", cprLoader, sizeof(h) + h.sz_cpr);
delete cprLoader;
n_mru = ft->n_mru;
addLoader("IDENTSTR", 0);
addLoader("LEXEC000", 0);
if (ft->id) {
if (ph.format==UPX_F_LINUX_ELF_i386) { // decompr, unfilter are separate
addLoader("LXUNF000", 0);
addLoader("LXUNF002", 0);
if (0x80==(ft->id & 0xF0)) {
if (256==n_mru) {
addLoader("MRUBYTE0", 0);
}
else if (n_mru) {
addLoader("LXMRU005", 0);
}
if (n_mru) {
addLoader("LXMRU006", 0);
}
else {
addLoader("LXMRU007", 0);
}
}
else if (0x40==(ft->id & 0xF0)) {
addLoader("LXUNF008", 0);
}
addLoader("LXUNF010", 0);
}
if (n_mru) {
addLoader("LEXEC009", 0);
}
}
addLoader("LEXEC010", 0);
addLoader(getDecompressor(), 0);
addLoader("LEXEC015", 0);
if (ft->id) {
if (ph.format==UPX_F_LINUX_ELF_i386) { // decompr, unfilter are separate
if (0x80!=(ft->id & 0xF0)) {
addLoader("LXUNF042", 0);
}
}
else { // decompr, unfilter not separate
if (0x80==(ft->id & 0xF0)) {
addLoader("LEXEC110", 0);
if (n_mru) {
addLoader("LEXEC100", 0);
}
// bug in APP: jmp and label must be in same .asx/.asy
addLoader("LEXEC016", 0);
}
}
addFilter32(ft->id);
if (ph.format==UPX_F_LINUX_ELF_i386) { // decompr, unfilter are separate
if (0x80==(ft->id & 0xF0)) {
if (0==n_mru) {
addLoader("LXMRU058", 0);
}
}
addLoader("LXUNF035", 0);
}
else { // decompr always unfilters
addLoader("LEXEC017", 0);
}
}
addLoader("LEXEC020", 0);
addLoader("FOLDEXEC", 0);
struct Elf_LE32_Ehdr *const ldrEhdr =
(struct Elf_LE32_Ehdr *)const_cast<unsigned char *>(getLoader());
unsigned e_entry = getLoaderSectionStart("LEXEC000");
ldrEhdr->e_entry = e_entry + elfhdr.phdr[0].p_vaddr;
char *ptr_cto = e_entry + (char *)ldrEhdr;
int sz_cto = getLoaderSize() - e_entry;
if (0x20==(ft->id & 0xF0) || 0x30==(ft->id & 0xF0)) { // push byte '?' ; cto8
patch_le16(ptr_cto, sz_cto, "\x6a?", 0x6a + (ft->cto << 8));
}
// FIXME ?? patchVersion((char *)ldrEhdr, e_entry);
return getLoaderSize();
}
int
PackLinuxI386::buildLoader(Filter const *ft)
{
unsigned const sz_fold = sizeof(linux_i386exec_fold);
MemBuffer buf(sz_fold);
memcpy(buf, linux_i386exec_fold, sz_fold);
// patch loader
// note: we only can use /proc/<pid>/fd when exetype > 0.
// also, we sleep much longer when compressing a script.
checkPatch(0,0,0,0); // reset
patch_le32(buf,sz_fold,"UPX4",exetype > 0 ? 3 : 15); // sleep time
patch_le32(buf,sz_fold,"UPX3",progid);
patch_le32(buf,sz_fold,"UPX2",exetype > 0 ? 0 : 0x7fffffff);
// get fresh filter
Filter fold_ft = *ft;
fold_ft.init(ft->id, ft->addvalue);
int preferred_ctos[2] = {ft->cto, -1};
fold_ft.preferred_ctos = preferred_ctos;
// filter
optimizeFilter(&fold_ft, buf, sz_fold);
bool success = fold_ft.filter(buf + sizeof(cprElfhdr), sz_fold - sizeof(cprElfhdr));
(void)success;
return buildLinuxLoader(
linux_i386exec_loader, sizeof(linux_i386exec_loader),
buf, sz_fold, ft, 0 );
}
int PackLinuxI386::getLoaderPrefixSize() const
{
@@ -198,58 +368,13 @@ bool PackLinuxI386::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, ph.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());
unsigned char *const ptr = const_cast<unsigned char *>(getLoader());
l_info *const lp = (l_info *)(ptr + getLoaderPrefixSize());
// checksum for loader + p_info
lp->l_checksum = 0;
lp->l_magic = UPX_ELF_MAGIC;
@@ -258,7 +383,7 @@ void PackLinuxI386::patchLoaderChecksum()
lp->l_format = (unsigned char) ph.format;
// INFO: lp->l_checksum is currently unused
unsigned adler = upx_adler32(0,NULL,0);
adler = upx_adler32(adler, loader, lsize + sizeof(p_info));
adler = upx_adler32(adler, ptr, lsize + sizeof(p_info));
lp->l_checksum = adler;
}
@@ -266,13 +391,18 @@ void PackLinuxI386::patchLoaderChecksum()
void PackLinuxI386::updateLoader(OutputFile *fo)
{
#define PAGE_MASK (~0<<12)
Elf_LE32_Ehdr *const ehdr = (Elf_LE32_Ehdr *)(unsigned char *)loader;
Elf_LE32_Ehdr *const ehdr = (Elf_LE32_Ehdr *)const_cast<upx_byte *>(getLoader());
Elf_LE32_Phdr *const phdr = (Elf_LE32_Phdr *)(1+ehdr);
ehdr->e_phnum = 2;
phdr->p_filesz = lsize;
// phdr->p_memsz is the decompressed size
assert(lsize > 128 && lsize < 4096);
// 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);
Elf_LE32_Phdr *const phdro = 1+phdr;
phdro->p_type = PT_LOAD;
phdro->p_offset = lsize;
@@ -282,8 +412,6 @@ void PackLinuxI386::updateLoader(OutputFile *fo)
phdro->p_align = (unsigned) (-PAGE_MASK);
patchLoaderChecksum();
fo->seek(0, SEEK_SET);
fo->rewrite(loader, 0x80);
#undef PAGE_MASK
}