📄 p_vmlinz.cpp
字号:
/* p_vmlinz.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 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.com ml1050@users.sourceforge.net */#include "conf.h"#include "file.h"#include "filter.h"#include "packer.h"#include "p_vmlinz.h"#include "linker.h"#include <zlib.h>static const#include "stub/i386-linux.kernel.vmlinuz.h"static const unsigned stack_offset_during_uncompression = 0x9000;// add to "real mode pointer" in %esi; total 0x99000 is typical// from /usr/src/linux/arch/i386/boot/compressed/Makefilestatic const unsigned zimage_offset = 0x1000;static const unsigned bzimage_offset = 0x100000;/*************************************************************************//**************************************************************************/PackVmlinuzI386::PackVmlinuzI386(InputFile *f) : super(f), physical_start(0x100000){ bele = &N_BELE_RTP::le_policy; COMPILE_TIME_ASSERT(sizeof(boot_sect_t) == 0x218);}const int *PackVmlinuzI386::getCompressionMethods(int method, int level) const{ return Packer::getDefaultCompressionMethods_le32(method, level);}const int *PackVmlinuzI386::getFilters() const{ static const int filters[] = { 0x26, 0x24, 0x49, 0x46, 0x16, 0x13, 0x14, 0x11, FT_ULTRA_BRUTE, 0x25, 0x15, 0x12, FT_END }; return filters;}bool PackVmlinuzI386::canPack(){ return readFileHeader() == getFormat();}/*************************************************************************// common util routines**************************************************************************/int PackVmlinuzI386::readFileHeader(){ boot_sect_t h; setup_size = 0; fi->readx(&h, sizeof(h)); if (h.boot_flag != 0xAA55) return 0; const bool hdrs = (memcmp(h.hdrs, "HdrS", 4) == 0); setup_size = (1 + (h.setup_sects ? h.setup_sects : 4)) * 0x200; if (setup_size <= 0 || setup_size >= file_size) return 0; int format = UPX_F_VMLINUZ_i386; unsigned sys_size = ALIGN_UP((unsigned) file_size, 16u) - setup_size; const unsigned char *p = (const unsigned char *) &h + 0x1e3; if (hdrs && memcmp(p, "\x0d\x0a\x07""ELKS", 7) == 0) { format = UPX_F_ELKS_8086; } else if (hdrs && (h.load_flags & 1) != 0) { format = UPX_F_BVMLINUZ_i386; // account for 16-bit h.sys_size, wrap around at 20 bits sys_size &= (1 << 20) - 1; } if (16u * h.sys_size != sys_size) return 0; // FIXME: add more checks for a valid kernel return format;}// read full kernel into obuf[], gzip-decompress into ibuf[],// return decompressed sizeint PackVmlinuzI386::decompressKernel(){ // read whole kernel image obuf.alloc(file_size); fi->seek(0, SEEK_SET); fi->readx(obuf, file_size); // See startup_32: in linux/arch/i386/boot/compressed/head.S char const *p = (char const *)&obuf[setup_size]; for (int j= 0; j < 0x200; ++j, ++p) { if (0==memcmp("\xE8\x00\x00\x00\x00\x5D", p, 6)) { /* "call 1f; 1f: pop %ebp" determines actual execution address; */ /* linux-2.6.21 (spring 2007) and later; upx stub needs work. */ throwCantPack("Relocatable kernel is not yet supported"); } // Find "ljmp $__BOOT_CS,$__PHYSICAL_START" if any. if (0==memcmp("\xEA\x00\x00", p, 3) && 0==(0xf & p[3]) && 0==p[4]) { /* whole megabyte < 16MB */ physical_start = get_le32(1+ p); break; } } checkAlreadyPacked(obuf + setup_size, UPX_MIN(file_size - setup_size, (off_t)1024)); for (int gzoff = setup_size; gzoff < file_size; gzoff++) { // find gzip header (2 bytes magic + 1 byte method "deflated") int off = find(obuf + gzoff, file_size - gzoff, "\x1F\x8B\x08", 3); if (off < 0) break; gzoff += off; const int gzlen = file_size - gzoff; if (gzlen < 256) break; // check gzip flag byte unsigned char flags = obuf[gzoff + 3]; if ((flags & 0xe0) != 0) // reserved bits set continue; //printf("found gzip header at offset %d\n", gzoff); // try to decompress int klen; int fd; off_t fd_pos; for (;;) { klen = -1; fd = -1; fd_pos = -1; // open fi->seek(gzoff, SEEK_SET); fd = dup(fi->getFd()); if (fd < 0) break; gzFile zf = gzdopen(fd, "rb"); if (zf == NULL) break; // estimate gzip-decompressed kernel size & alloc buffer if (ibuf.getSize() == 0) ibuf.alloc(gzlen * 3); // decompress klen = gzread(zf, ibuf, ibuf.getSize()); fd_pos = lseek(fd, 0, SEEK_CUR); gzclose(zf); fd = -1; if (klen != (int)ibuf.getSize()) break; // realloc and try again unsigned s = ibuf.getSize(); ibuf.dealloc(); ibuf.alloc(3 * s / 2); } if (fd >= 0) (void) close(fd); if (klen <= 0) continue; if (klen <= gzlen) continue; if (opt->force > 0) return klen; // some checks if (fd_pos != file_size) { //printf("fd_pos: %ld, file_size: %ld\n", (long)fd_pos, (long)file_size); // linux-2.6.21.5/arch/i386/boot/compressed/vmlinux.lds // puts .data.compressed ahead of .text, .rodata, etc; // so piggy.o need not be last in bzImage. Alas. //throwCantPack("trailing bytes after kernel image; use option '-f' to force packing"); } // see /usr/src/linux/arch/i386/kernel/head.S // 2.4.x: [cli;] cld; mov $...,%eax if (memcmp(ibuf, "\xFC\xB8", 2) == 0) goto head_ok; if (memcmp(ibuf, "\xFA\xFC\xB8", 3) == 0) goto head_ok; // 2.6.21.5 CONFIG_PARAVIRT mov %cs,%eax; test $3,%eax; jne ...; if (memcmp(ibuf, "\x8c\xc8\xa9\x03\x00\x00\x00\x0f\x85", 9) == 0) goto head_ok; if (memcmp(ibuf, "\x8c\xc8\xa8\x03\x0f\x85", 6) == 0) goto head_ok; // 2.6.x: [cli;] cld; lgdt ... if (memcmp(ibuf, "\xFC\x0F\x01", 3) == 0) goto head_ok; if (memcmp(ibuf, "\xFA\xFC\x0F\x01", 4) == 0) goto head_ok; // 2.6.x+grsecurity+strongswan+openwall+trustix: ljmp $0x10,... if (ibuf[0] == 0xEA && memcmp(ibuf+5, "\x10\x00", 2) == 0) goto head_ok; // x86_64 2.6.x if (0xB8==ibuf[0] // mov $...,%eax && 0x8E==ibuf[5] && 0xD8==ibuf[6] // mov %eax,%ds && 0x0F==ibuf[7] && 0x01==ibuf[8] && 020==(070 & ibuf[9]) // lgdtl && 0xB8==ibuf[14] // mov $...,%eax && 0x0F==ibuf[19] && 0xA2==ibuf[20] // cpuid ) goto head_ok; throwCantPack("unrecognized kernel architecture; use option '-f' to force packing"); head_ok: // FIXME: more checks for special magic bytes in ibuf ??? // FIXME: more checks for kernel architecture ??? return klen; } return 0;}void PackVmlinuzI386::readKernel(){ int klen = decompressKernel(); if (klen <= 0) throwCantPack("kernel decompression failed"); //OutputFile::dump("kernel.img", ibuf, klen); // copy the setup boot code
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -