📄 p_lx_exc.cpp
字号:
/* p_lx_exc.cpp -- This file is part of the UPX executable compressor. Copyright (C) 1996-2007 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996-2007 Laszlo Molnar Copyright (C) 2001-2007 John F. Reiser 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 <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net> John F. Reiser <jreiser@users.sourceforge.net> */#include "conf.h"#include "file.h"#include "filter.h"#include "linker.h"#include "packer.h"#include "p_elf.h"#include "p_unix.h"#include "p_lx_exc.h"#define PT_LOAD Elf32_Phdr::PT_LOAD#define PT_DYNAMIC Elf32_Phdr::PT_DYNAMIC#if 0 // UNUSED#define DT_NULL Elf32_Dyn::DT_NULL#define DT_NEEDED Elf32_Dyn::DT_NEEDED#define DT_STRTAB Elf32_Dyn::DT_STRTAB#define DT_STRSZ Elf32_Dyn::DT_STRSZ#endif/*************************************************************************// linux/386 (generic "execve" format)**************************************************************************/PackLinuxI386::PackLinuxI386(InputFile *f) : super(f), ei_osabi(Elf32_Ehdr::ELFOSABI_LINUX), osabi_note(NULL){ bele = &N_BELE_RTP::le_policy;}PackBSDI386::PackBSDI386(InputFile *f) : super(f){ // Shell scripts need help specifying the target operating system. // Elf input will override this with .e_ident[EI_OSABI] or PT_NOTE. // [2006-09-27: Today's only runtime stub for shell is for linux.] if (Elf32_Ehdr::ELFOSABI_LINUX==opt->o_unix.osabi0) { // Disallow an incompatibility. ei_osabi = Elf32_Ehdr::ELFOSABI_NONE; } else { ei_osabi = opt->o_unix.osabi0; // might be ELFOSABI_NONE }}static const#include "stub/i386-linux.elf.execve-entry.h"static const#include "stub/i386-linux.elf.execve-fold.h"static const#include "stub/i386-bsd.elf.execve-entry.h"static const#include "stub/i386-bsd.elf.execve-fold.h"const int *PackLinuxI386::getCompressionMethods(int method, int level) const{ return Packer::getDefaultCompressionMethods_le32(method, level);}const int *PackLinuxI386::getFilters() const{ static const int filters[] = { 0x49, 0x46, 0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,#if 0// 0x80..0x87 are regarded as "untested". 0x83, 0x86, 0x80, 0x84, 0x87, 0x81, 0x82, 0x85, 0x24, 0x16, 0x13, 0x14, 0x11, 0x25, 0x15, 0x12,#endif FT_END }; return filters;}static voidset_stub_brk(Elf_LE32_Phdr *const phdr1, unsigned brka){#define PAGE_MASK (~0ul<<12) // linux-2.6.14 binfmt_elf.c: SIGKILL if (0==.p_memsz) on a page boundary unsigned const brkb = brka | ((0==(~PAGE_MASK & brka)) ? 0x20 : 0); phdr1->p_type = PT_LOAD; // be sure phdr1->p_offset = ~PAGE_MASK & brkb; phdr1->p_vaddr = brkb; phdr1->p_paddr = brkb; phdr1->p_filesz = 0; phdr1->p_memsz = 0; if (0==phdr1->p_flags) { phdr1->p_flags = Elf32_Phdr::PF_R|Elf32_Phdr::PF_W; } if (0==phdr1->p_align) { phdr1->p_align = 0x1000; }#undef PAGE_MASK}voidPackLinuxI386::generateElfHdr( OutputFile *fo, void const *proto, unsigned const brka){ cprElfHdr2 *const h2 = (cprElfHdr2 *)&elfout; cprElfHdr3 *const h3 = (cprElfHdr3 *)&elfout; memcpy(h3, proto, sizeof(*h3)); // reads beyond, but OK assert(h2->ehdr.e_phoff == sizeof(Elf32_Ehdr)); assert(h2->ehdr.e_shoff == 0); assert(h2->ehdr.e_ehsize == sizeof(Elf32_Ehdr)); assert(h2->ehdr.e_phentsize == sizeof(Elf32_Phdr)); assert(h2->ehdr.e_shnum == 0);#if 0 //{ unsigned identsize; char const *const ident = getIdentstr(&identsize);#endif //} h2->phdr[0].p_filesz = sizeof(*h2); // + identsize; h2->phdr[0].p_memsz = h2->phdr[0].p_filesz; // Info for OS kernel to set the brk() if (brka) { set_stub_brk(&h2->phdr[1], brka); } if (ph.format==UPX_F_LINUX_i386 || ph.format==UPX_F_LINUX_SH_i386 || ph.format==UPX_F_BSD_i386 ) { // SELinux, PAx, grSecurity demand no PF_W if PF_X. // kernel-2.6.12-2.3.legacy_FC3 has a bug which demands // a PT_LOAD with PF_W, else SIGSEGV when clearing page fragment // on low page of ".bss", which is the high page of .text. // So the minimum number of PT_LOAD is 2. assert(h2->ehdr.e_phnum==2); memset(&h2->linfo, 0, sizeof(h2->linfo)); fo->write(h2, sizeof(*h2)); } else if (ph.format==UPX_F_LINUX_ELFI_i386) { assert(h3->ehdr.e_phnum==3); memset(&h3->linfo, 0, sizeof(h3->linfo)); fo->write(h3, sizeof(*h3)); } else { assert(false); // unknown ph.format, PackUnix::generateElfHdr }}voidPackLinuxI386::pack1(OutputFile *fo, Filter &){ // create a pseudo-unique program id for our paranoid stub progid = getRandomId(); generateElfHdr(fo, stub_i386_linux_elf_execve_fold, 0);}voidPackBSDI386::pack1(OutputFile *fo, Filter &){ // create a pseudo-unique program id for our paranoid stub progid = getRandomId(); generateElfHdr(fo, stub_i386_bsd_elf_execve_fold, 0);}voidPackLinuxI386::pack4(OutputFile *fo, Filter &ft){ overlay_offset = sizeof(elfout.ehdr) + (elfout.ehdr.e_phentsize * elfout.ehdr.e_phnum) + sizeof(l_info) + ((elfout.ehdr.e_phnum==3) ? (unsigned) elfout.phdr[2].p_memsz : 0) ; unsigned nw = fo->getBytesWritten(); elfout.phdr[0].p_filesz = nw; nw = 0u-((0u-elfout.phdr[0].p_align) & (0u-nw)); // ALIGN_UP super::pack4(fo, ft); // write PackHeader and overlay_offset set_stub_brk(&elfout.phdr[1], nw + elfout.phdr[0].p_vaddr);#if 0 // { // /usr/bin/strip from RedHat 8.0 (binutils-2.13.90.0.2-2) // generates a 92-byte [only] output, because the "linking view" // is empty. This code supplies a "linking view". // However, 'strip' then generates _plausible_ junk that gets // "Illegal instruction" because 'strip' changes p_hdr[1].p_align, // .p_offset, and .p_vaddr incorrectly. So the "cure" is worse than // the disease. It is obvious that a 92-byte file is bad, // but it is not obvious that the changed .p_align is bad. // Also, having a totally empty "linking view" is easier for 'strip' // to fix: just detect that, and do nothing. // So, we don't use this code for now [2003-01-11]. // Supply a "linking view" that covers everything, // so that 'strip' does not omit everything. Elf_LE32_Shdr shdr; // The section header string table. char const shstrtab[] = "\0.\0.shstrtab"; unsigned eod = elfout.phdr[0].p_filesz; elfout.ehdr.e_shoff = eod; elfout.ehdr.e_shentsize = sizeof(shdr); elfout.ehdr.e_shnum = 3; elfout.ehdr.e_shstrndx = 2; // An empty Elf32_Shdr for space as a null index. memset(&shdr, 0, sizeof(shdr)); shdr.sh_type = Elf32_Shdr::SHT_NULL; fo->write(&shdr, sizeof(shdr)); // Cover all the bits we need at runtime. memset(&shdr, 0, sizeof(shdr)); shdr.sh_name = 1; shdr.sh_type = Elf32_Shdr::SHT_PROGBITS; shdr.sh_flags = Elf32_Shdr::SHF_ALLOC; shdr.sh_addr = elfout.phdr[0].p_vaddr; shdr.sh_offset = overlay_offset; shdr.sh_size = eod - overlay_offset; shdr.sh_addralign = 4096; fo->write(&shdr, sizeof(shdr)); // A section header for the section header string table. memset(&shdr, 0, sizeof(shdr)); shdr.sh_name = 3; shdr.sh_type = Elf32_Shdr::SHT_STRTAB; shdr.sh_offset = 3*sizeof(shdr) + eod; shdr.sh_size = sizeof(shstrtab); fo->write(&shdr, sizeof(shdr)); fo->write(shstrtab, sizeof(shstrtab));#endif // } // Cannot pre-round .p_memsz. If .p_filesz < .p_memsz, then kernel // tries to make .bss, which requires PF_W. // But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X.#if 0 /*{*/#undef PAGE_MASK#define PAGE_MASK (~0u<<12) // pre-calculate for benefit of runtime disappearing act via munmap() elfout.phdr[0].p_memsz = PAGE_MASK & (~PAGE_MASK + elfout.phdr[0].p_filesz);#undef PAGE_MASK#else /*}{*/ elfout.phdr[0].p_memsz = elfout.phdr[0].p_filesz;#endif /*}*/ // rewrite Elf header fo->seek(0, SEEK_SET); fo->rewrite(&elfout, overlay_offset);}static unsignedumax(unsigned a, unsigned b){ if (a <= b) { return b; } return a;}Linker *PackLinuxI386::newLinker() const{ return new ElfLinkerX86;}voidPackLinuxI386::buildLinuxLoader( upx_byte const *const proto, unsigned const szproto, upx_byte const *const fold, unsigned const szfold, Filter const *ft){ initLoader(proto, szproto); unsigned fold_hdrlen = 0; if (0 < szfold) { cprElfHdr1 const *const hf = (cprElfHdr1 const *)fold; fold_hdrlen = sizeof(hf->ehdr) + hf->ehdr.e_phentsize * hf->ehdr.e_phnum +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -