📄 i386-linux.elf-main.c
字号:
/* i386-linux.elf-main.c -- stub loader for Linux x86 ELF executable 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) 2000-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 "include/linux.h"void *mmap(void *, size_t, int, int, int, off_t);ssize_t write(int, void const *, size_t);/*************************************************************************// configuration section**************************************************************************/// In order to make it much easier to move this code at runtime and execute// it at an address different from it load address: there must be no// static data, and no string constants.#if 1 /*{*/#define DPRINTF(a) /* empty: no debug drivel */#else /*}{*/#if 0#include "stdarg.h"#else#define va_arg __builtin_va_arg#define va_end __builtin_va_end#define va_list __builtin_va_list#define va_start __builtin_va_start#endifstatic intunsimal(unsigned x, char *ptr, int n){ if (10<=x) { n = unsimal(x/10, ptr, n); x %= 10; } ptr[n] = '0' + x; return 1+ n;}static intdecimal(int x, char *ptr, int n){ if (x < 0) { *ptr++ = '-'; ++n; x = -x; } return unsimal(x, ptr, n);}extern char const *STR_hex(void);static intheximal(unsigned x, char *ptr, int n){ if (16<=x) { n = heximal(x>>4, ptr, n); x &= 0xf; } ptr[n] = STR_hex()[x]; return 1+ n;}#define DPRINTF(a) dprintf aextern char const *STR_0x(void);extern char const *STR_xread(void);extern char const *STR_unpackExtent(void);extern char const *STR_make_hatch_arm(void);extern char const *STR_auxv_up(void);extern char const *STR_xfind_pages(void);extern char const *STR_do_xmap(void);extern char const *STR_upx_main(void);static intdprintf(char const *fmt, ...){ char c; int n= 0; char *ptr; char buf[20]; va_list va; va_start(va, fmt); ptr= &buf[0]; while (0!=(c= *fmt++)) if ('%'!=c) goto literal; else switch (c= *fmt++) { default: {literal: n+= write(2, fmt-1, 1); } break; case 0: goto done; /* early */ case 'u': { n+= write(2, buf, unsimal(va_arg(va, unsigned), buf, 0)); } break; case 'd': { n+= write(2, buf, decimal(va_arg(va, int), buf, 0)); } break; case 'p': /* same as 'x'; relies on sizeof(int)==sizeof(void *) */ case 'x': { buf[0] = '0'; buf[1] = 'x'; n+= write(2, buf, heximal(va_arg(va, int), buf, 2)); } break; }done: va_end(va); return n;}#endif /*}*/#define MAX_ELF_HDR 512 // Elf32_Ehdr + n*Elf32_Phdr must fit in this/*************************************************************************// "file" util**************************************************************************/typedef struct { size_t size; // must be first to match size[0] uncompressed size char *buf;} Extent;static void#if (ACC_CC_GNUC >= 0x030300) && defined(__i386__) /*{*/__attribute__((__noinline__, __used__, regparm(3), stdcall))#endif /*}*/xread(Extent *x, char *buf, size_t count){ char *p=x->buf, *q=buf; size_t j; DPRINTF((STR_xread(), x, x->size, x->buf, buf, count)); if (x->size < count) { exit(127); } for (j = count; 0!=j--; ++p, ++q) { *q = *p; } x->buf += count; x->size -= count;}/*************************************************************************// util**************************************************************************/#if 1 //{ save space#define ERR_LAB error: exit(127);#define err_exit(a) goto error#else //}{ save debugging time#define ERR_LABstatic void __attribute__ ((__noreturn__))err_exit(int a){ (void)a; // debugging convenience exit(127);}#endif //}static void *do_brk(void *addr){ return brk(addr);}/*************************************************************************// UPX & NRV stuff**************************************************************************/typedef void f_unfilter( nrv_byte *, // also addvalue nrv_uint, unsigned cto8, // junk in high 24 bits unsigned ftid);typedef int f_expand( const nrv_byte *, nrv_uint, nrv_byte *, nrv_uint *, unsigned );static voidunpackExtent( Extent *const xi, // input Extent *const xo, // output f_expand *const f_decompress, f_unfilter *f_unf){ DPRINTF((STR_unpackExtent(), xi, xi->size, xi->buf, xo, xo->size, xo->buf, f_decompress, f_unf)); while (xo->size) { struct b_info h; // Note: if h.sz_unc == h.sz_cpr then the block was not // compressible and is stored in its uncompressed form. // Read and check block sizes. xread(xi, (char *)&h, sizeof(h)); if (h.sz_unc == 0) { // uncompressed size 0 -> EOF if (h.sz_cpr != UPX_MAGIC_LE32) // h.sz_cpr must be h->magic err_exit(2); if (xi->size != 0) // all bytes must be written err_exit(3); break; } if (h.sz_cpr <= 0) { err_exit(4);ERR_LAB } if (h.sz_cpr > h.sz_unc || h.sz_unc > xo->size ) { err_exit(5); } // Now we have: // assert(h.sz_cpr <= h.sz_unc); // assert(h.sz_unc > 0 && h.sz_unc <= blocksize); // assert(h.sz_cpr > 0 && h.sz_cpr <= blocksize); if (h.sz_cpr < h.sz_unc) { // Decompress block nrv_uint out_len = h.sz_unc; // EOF for lzma int const j = (*f_decompress)((unsigned char *)xi->buf, h.sz_cpr, (unsigned char *)xo->buf, &out_len, *(int *)(void *)&h.b_method ); if (j != 0 || out_len != (nrv_uint)h.sz_unc) err_exit(7); // Skip Ehdr+Phdrs: separate 1st block, not filtered if (h.b_ftid!=0 && f_unf // have filter && ((512 < out_len) // this block is longer than Ehdr+Phdrs || (xo->size==(unsigned)h.sz_unc) ) // block is last in Extent ) { (*f_unf)((unsigned char *)xo->buf, out_len, h.b_cto8, h.b_ftid); } xi->buf += h.sz_cpr; xi->size -= h.sz_cpr; } else { // copy literal block xread(xi, xo->buf, h.sz_cpr); } xo->buf += h.sz_unc; xo->size -= h.sz_unc; }}#if defined(__i386__) /*{*/// Create (or find) an escape hatch to use when munmapping ourselves the stub.// Called by do_xmap to create it; remembered in AT_NULL.d_valstatic void *make_hatch_x86(Elf32_Phdr const *const phdr, unsigned const reloc){ unsigned *hatch = 0; if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) { // The format of the 'if' is // if ( ( (hatch = loc1), test_loc1 ) // || ( (hatch = loc2), test_loc2 ) ) { // action // } // which uses the comma to save bytes when test_locj involves locj // and the action is the same when either test succeeds. // Try page fragmentation just beyond .text . if ( ( (hatch = (void *)(phdr->p_memsz + phdr->p_vaddr + reloc)), ( phdr->p_memsz==phdr->p_filesz // don't pollute potential .bss && 4<=(~PAGE_MASK & -(int)hatch) ) ) // space left on page // Try Elf32_Ehdr.e_ident[12..15] . warning: 'const' cast away || ( (hatch = (void *)(&((Elf32_Ehdr *)phdr->p_vaddr + reloc)->e_ident[12])), (phdr->p_offset==0) ) ) { // Omitting 'const' saves repeated literal in gcc. unsigned /*const*/ escape = 0xc36180cd; // "int $0x80; popa; ret" // Don't store into read-only page if value is already there. if (* (volatile unsigned*) hatch != escape) { * hatch = escape; } } else { hatch = 0; } } return hatch;}#elif defined(__arm__) /*}{*/static void *make_hatch_arm(Elf32_Phdr const *const phdr, unsigned const reloc){ unsigned *hatch = 0; DPRINTF((STR_make_hatch_arm(),phdr,reloc)); if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) { // The format of the 'if' is // if ( ( (hatch = loc1), test_loc1 ) // || ( (hatch = loc2), test_loc2 ) ) { // action // } // which uses the comma to save bytes when test_locj involves locj // and the action is the same when either test succeeds. // Try page fragmentation just beyond .text . if ( ( (hatch = (void *)(phdr->p_memsz + phdr->p_vaddr + reloc)), ( phdr->p_memsz==phdr->p_filesz // don't pollute potential .bss && (2*4)<=(~PAGE_MASK & -(int)hatch) ) ) // space left on page // Try Elf32_Ehdr.e_ident[8..15] . warning: 'const' cast away || ( (hatch = (void *)(&((Elf32_Ehdr *)phdr->p_vaddr + reloc)->e_ident[8])), (phdr->p_offset==0) ) ) { hatch[0]= 0xef90005b; // syscall __NR_unmap hatch[1]= 0xe1a0f00e; // mov pc,lr } else { hatch = 0; } } return hatch;}#elif defined(__mips__) /*}{*/static void *make_hatch_mips( Elf32_Phdr const *const phdr, unsigned const reloc, unsigned const frag_mask){ unsigned *hatch = 0; DPRINTF((STR_make_hatch_arm(),phdr,reloc)); if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -