mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
vmlinuz/i386 support.
committer: ml1050 <ml1050> 976714560 +0000
This commit is contained in:
parent
c9430123d1
commit
de30026bbe
|
@ -59,7 +59,7 @@ OBJECTS1 = \
|
|||
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_sys$o p_tmt$o p_tos$o \
|
||||
p_unix$o p_w32pe$o p_wcle$o
|
||||
p_unix$o p_w32pe$o p_wcle$o p_vmlinz$o
|
||||
|
||||
# no exceptions or RTTI
|
||||
OBJECTS2 = \
|
||||
|
@ -164,7 +164,7 @@ DEFS += '-DUPX_CONFIG_H="config_h/linux.h"'
|
|||
##CFLAGS_M += -mno-schedule-prologue
|
||||
CFLAGS_M += -march=i386 -mcpu=pentium
|
||||
CFLAGS_WERROR = -Werror
|
||||
LDLIBS += -lmcheck
|
||||
LDLIBS += -lmcheck -lz
|
||||
|
||||
ifeq (1,2) # checkergcc
|
||||
CC = checkergcc
|
||||
|
@ -435,7 +435,7 @@ 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_sys.h p_tmt.h p_tos.h \
|
||||
p_unix.h p_vxd.h p_w32pe.h p_wcle.h
|
||||
p_unix.h p_vxd.h p_w32pe.h p_wcle.h p_vmlinz.h
|
||||
ui$o: packer.h ui.h
|
||||
work$o: packer.h ui.h packmast.h
|
||||
|
||||
|
@ -462,5 +462,7 @@ p_w32pe$o: packer.h p_w32pe.h \
|
|||
stub/l_w32pe.h
|
||||
p_wcle$o: packer.h p_wcle.h lefile.h \
|
||||
stub/l_wcle.h
|
||||
p_vmlinz$o: packer.h p_vmlinz.h \
|
||||
stub/l_vmlinz.h
|
||||
|
||||
# vi:nowrap
|
||||
|
|
211
src/p_vmlinz.cpp
Normal file
211
src/p_vmlinz.cpp
Normal file
|
@ -0,0 +1,211 @@
|
|||
/* p_vmlinz.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_vmlinz.h"
|
||||
#include <zlib.h>
|
||||
|
||||
static const
|
||||
#include "stub/l_vmlinz.h"
|
||||
|
||||
const unsigned kernel_entry = 0x100000;
|
||||
const unsigned stack_during_uncompression = 0x90000;
|
||||
|
||||
// from /usr/src/linux/arch/i386/boot/compressed/Makefile
|
||||
const unsigned bzimage_offset = 0x100000;
|
||||
const unsigned zimage_offset = 0x1000;
|
||||
|
||||
|
||||
PackvmlinuzI386::PackvmlinuzI386(InputFile *f) :
|
||||
super(f)
|
||||
{
|
||||
assert(sizeof(boot_sect_t) == 0x218);
|
||||
}
|
||||
|
||||
|
||||
int PackvmlinuzI386::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 ? M_NRV2D_LE32 : M_NRV2B_LE32;
|
||||
}
|
||||
|
||||
|
||||
const int *PackvmlinuzI386::getFilters() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool PackvmlinuzI386::canPack()
|
||||
{
|
||||
boot_sect_t h;
|
||||
fi->readx(&h, sizeof(h));
|
||||
if (h.boot_flag != 0xAA55)
|
||||
return false;
|
||||
|
||||
setup_size = (1 + (h.setup_sects ? h.setup_sects : 4)) * 0x200;
|
||||
if (setup_size > file_size)
|
||||
return false;
|
||||
|
||||
bzImage = memcmp(h.hdrs, "HdrS", 4) == 0 && (h.load_flags & 1) != 0;
|
||||
|
||||
obuf.alloc(file_size);
|
||||
fi->seek(0, SEEK_SET);
|
||||
fi->readx(obuf, file_size);
|
||||
|
||||
ibuf.alloc(3 * 1024 * 1024); // 3M should be enough
|
||||
|
||||
upx_bytep gzpos = obuf + setup_size;
|
||||
while (1)
|
||||
{
|
||||
int pos = find(gzpos, file_size - (gzpos - obuf), "\x1F\x8B", 2);
|
||||
if (pos < 0)
|
||||
return false;
|
||||
gzpos += pos;
|
||||
#if 0
|
||||
ulen = ibuf.getSize();
|
||||
if (::uncompress(ibuf, &ulen, gzpos, file_size - (gzpos - obuf)) == Z_OK)
|
||||
return true;
|
||||
gzpos++;
|
||||
#else
|
||||
fi->seek(gzpos - obuf, SEEK_SET);
|
||||
gzFile zf = gzdopen(fi->getFd(), "r");
|
||||
if (zf == 0)
|
||||
return false;
|
||||
ulen = gzread(zf, ibuf, ibuf.getSize());
|
||||
return ulen > (unsigned) file_size;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void PackvmlinuzI386::pack(OutputFile *fo)
|
||||
{
|
||||
MemBuffer setupbuf(setup_size);
|
||||
memcpy(setupbuf, obuf, setup_size);
|
||||
|
||||
obuf.free();
|
||||
obuf.allocForCompression(ibuf.getSize());
|
||||
|
||||
// FILE *f1 = fopen("kernel.img", "wb"); fwrite(ibuf, 1, ulen, f1); fclose(f1);
|
||||
|
||||
ph.u_len = ulen;
|
||||
if (!compress(ibuf, obuf))
|
||||
throwNotCompressible();
|
||||
|
||||
initLoader(nrv_loader, sizeof(nrv_loader));
|
||||
|
||||
const unsigned overlapoh = bzImage ? findOverlapOverhead(obuf, 512) : 0;
|
||||
unsigned clen = ph.c_len;
|
||||
|
||||
if (bzImage)
|
||||
{
|
||||
// align everything to dword boundary - it is easier to handle
|
||||
memset(obuf + clen, 0, 4);
|
||||
clen = ALIGN_UP(clen, 4);
|
||||
|
||||
addLoader("LINUZ000""LBZIMAGE""IDENTSTR",
|
||||
"+40D++++", // align the stuff to 4 byte boundary
|
||||
"UPX1HEAD", // 32 byte
|
||||
"LZCUTPOI""+0000000",
|
||||
getDecompressor(),
|
||||
"LINUZ990",
|
||||
NULL
|
||||
);
|
||||
}
|
||||
else
|
||||
addLoader("LINUZ000""LZIMAGE0",
|
||||
getDecompressor(),
|
||||
"LINUZ990""IDENTSTR""UPX1HEAD",
|
||||
NULL
|
||||
);
|
||||
|
||||
const unsigned lsize = getLoaderSize();
|
||||
MemBuffer loader(lsize);
|
||||
memcpy(loader, getLoader(), lsize);
|
||||
|
||||
int e_len = bzImage ? getLoaderSection("LZCUTPOI") : lsize;
|
||||
patchPackHeader(loader, lsize);
|
||||
|
||||
if (bzImage)
|
||||
{
|
||||
assert(e_len > 0);
|
||||
|
||||
const unsigned d_len4 = ALIGN_UP(lsize - e_len, 4);
|
||||
const unsigned decompr_pos = ALIGN_UP(ulen + overlapoh, 16);
|
||||
const unsigned copy_size = clen + d_len4;
|
||||
const unsigned edi = decompr_pos + d_len4 - 4; // copy to
|
||||
const unsigned esi = ALIGN_UP(clen + lsize, 4) - 4; // copy from
|
||||
|
||||
unsigned jpos = find_le32(loader, e_len, get_le32("JMPD"));
|
||||
patch_le32(loader, e_len, "JMPD", decompr_pos - jpos - 4);
|
||||
|
||||
patch_le32(loader, e_len, "ESI1", bzimage_offset + decompr_pos - clen);
|
||||
patch_le32(loader, e_len, "ECX0", copy_size / 4);
|
||||
patch_le32(loader, e_len, "EDI0", bzimage_offset + edi);
|
||||
patch_le32(loader, e_len, "ESI0", bzimage_offset + esi);
|
||||
}
|
||||
else
|
||||
patch_le32(loader, lsize, "ESI1", zimage_offset + lsize);
|
||||
|
||||
patch_le32(loader, e_len, "KEIP", kernel_entry);
|
||||
patch_le32(loader, e_len, "STAK", stack_during_uncompression);
|
||||
|
||||
((boot_sect_t *)((unsigned char *)setupbuf))->sys_size = ALIGN_UP(lsize + clen, 16) / 16;
|
||||
|
||||
fo->write(setupbuf, setupbuf.getSize());
|
||||
fo->write(loader, e_len);
|
||||
fo->write(obuf, clen);
|
||||
fo->write(loader + e_len, lsize - e_len);
|
||||
|
||||
//if (!checkCompressionRatio(file_size, fo->getBytesWritten()))
|
||||
// throwNotCompressible();
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int PackvmlinuzI386::canUnpack()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void PackvmlinuzI386::unpack(OutputFile *)
|
||||
{
|
||||
// no uncompression support for this format, so
|
||||
// it is possible to remove the original deflate code (>10KB)
|
||||
throwCantUnpack("build a new kernel instead :-)");
|
||||
}
|
77
src/p_vmlinz.h
Normal file
77
src/p_vmlinz.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* p_vmlinz.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
|
||||
*/
|
||||
|
||||
/*************************************************************************
|
||||
// vmlinuz/i386 (zlib compressed Linux kernel image)
|
||||
**************************************************************************/
|
||||
|
||||
class PackvmlinuzI386 : public Packer
|
||||
{
|
||||
typedef Packer super;
|
||||
public:
|
||||
PackvmlinuzI386(InputFile *f);
|
||||
virtual int getVersion() const { return 1; }
|
||||
virtual int getFormat() const { return UPX_F_VMLINUZ_i386; }
|
||||
virtual const char *getName() const { return "vmlinuz/386"; }
|
||||
virtual int getCompressionMethod() const;
|
||||
virtual const int *getFilters() const;
|
||||
|
||||
virtual void pack(OutputFile *fo);
|
||||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
// virtual const upx_byte *getLoader() const;
|
||||
// virtual int getLoaderSize() const;
|
||||
|
||||
struct boot_sect_t
|
||||
{
|
||||
char _[0x1f1];
|
||||
char setup_sects;
|
||||
char _1[2];
|
||||
LE16 sys_size;
|
||||
char _2[8];
|
||||
LE16 boot_flag; // 0xAA55
|
||||
// 0x200
|
||||
char _3[2];
|
||||
char hdrs[4]; // "HdrS"
|
||||
LE16 version; // boot protocol
|
||||
char _4[9];
|
||||
char load_flags;
|
||||
char _5[2];
|
||||
LE32 code32_start;
|
||||
|
||||
// some more uninteresting fields here ...
|
||||
// see /usr/src/linux/Documentation/i386/
|
||||
};
|
||||
|
||||
off_t setup_size;
|
||||
bool bzImage;
|
||||
unsigned long ulen;
|
||||
};
|
|
@ -45,6 +45,7 @@
|
|||
#include "p_tmt.h"
|
||||
#include "p_vxd.h"
|
||||
#include "p_w32pe.h"
|
||||
#include "p_vmlinz.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -124,7 +125,7 @@ static Packer* try_unpack(Packer *p, InputFile *f)
|
|||
// FIXME - could stop testing all other unpackers at this time
|
||||
// see canUnpack() in packer.h
|
||||
}
|
||||
} catch (IOException&) {
|
||||
} catch (const IOException&) {
|
||||
} catch (...) {
|
||||
delete p;
|
||||
throw;
|
||||
|
@ -177,6 +178,8 @@ static Packer* try_packers(InputFile *f, try_function func)
|
|||
if ((p = func(new PackBvmlinuxI386(f),f)) != NULL)
|
||||
return p;
|
||||
#endif
|
||||
if ((p = func(new PackvmlinuzI386(f),f)) != NULL)
|
||||
return p;
|
||||
if ((p = func(new PackLinuxI386(f),f)) != NULL)
|
||||
return p;
|
||||
if ((p = func(new PackSys(f),f)) != NULL)
|
||||
|
|
|
@ -33,7 +33,8 @@ STUBS = \
|
|||
l_w32pe.h \
|
||||
l_lx_n2b.h l_lx_n2d.h \
|
||||
l_le_n2b.h l_le_n2d.h \
|
||||
l_sh_n2b.h l_sh_n2d.h
|
||||
l_sh_n2b.h l_sh_n2d.h \
|
||||
l_vmlinz.h
|
||||
|
||||
|
||||
# util var for use in the rules - basename of the current target
|
||||
|
@ -196,6 +197,10 @@ l_w32pe.h: l_w32pe.asx
|
|||
$(NASM) -f bin -o $T.bin $<
|
||||
$(BIN2H) $T.bin nrv_loader $@
|
||||
|
||||
l_vmlinz.h: l_vmlinz.asx
|
||||
$(NASM) -f bin -o $T.bin $<
|
||||
$(BIN2H) $T.bin nrv_loader $@
|
||||
|
||||
|
||||
# /***********************************************************************
|
||||
# // linux rules (exec, elf, sh, sep)
|
||||
|
@ -299,6 +304,7 @@ l_tmt.h: n2b_d32.asy n2d_d32.asy $(DEPS2)
|
|||
l_vxd.h: n2b_d32.asy n2d_d32.asy $(DEPS2)
|
||||
l_wcle.h: n2b_d32.asy n2d_d32.asy $(DEPS2)
|
||||
l_w32pe.h: n2b_d32.asy n2d_d32.asy $(DEPS2)
|
||||
l_vmlinz.h: n2b_d32.asy n2d_d32.asy $(DEPS2)
|
||||
|
||||
l_xe_n2b.o: n2b_d32.ash $(DEPS1)
|
||||
l_6e_n2b.o: n2b_d32.ash $(DEPS1)
|
||||
|
|
111
src/stub/l_vmlinz.asm
Normal file
111
src/stub/l_vmlinz.asm
Normal file
|
@ -0,0 +1,111 @@
|
|||
; l_vmlinz.asm -- loader & decompressor for the vmlinuz/i386 format
|
||||
;
|
||||
; 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
|
||||
;
|
||||
|
||||
|
||||
%define jmps jmp short
|
||||
%define jmpn jmp near
|
||||
%include "macros.ash"
|
||||
|
||||
BITS 32
|
||||
SECTION .text
|
||||
ORG 0
|
||||
|
||||
; =============
|
||||
; ============= ENTRY POINT
|
||||
; =============
|
||||
|
||||
start:
|
||||
; __LINUZ000__
|
||||
cli
|
||||
xor eax, eax
|
||||
mov al, 0x18
|
||||
mov ds, eax
|
||||
mov es, eax
|
||||
mov ss, eax
|
||||
mov esp, 'STAK' ; 0x90000
|
||||
|
||||
mov eax, 'KEIP' ; 0x100000 - address of startup_32
|
||||
push eax
|
||||
push edi
|
||||
push esi
|
||||
or ebp, byte -1
|
||||
|
||||
%ifdef __LBZIMAGE__
|
||||
mov esi, 'ESI0'
|
||||
mov edi, 'EDI0'
|
||||
mov ecx, 'ECX0'
|
||||
|
||||
std
|
||||
rep
|
||||
movsd
|
||||
cld
|
||||
|
||||
mov esi, 'ESI1'
|
||||
xchg eax, edi
|
||||
jmp .1 + 'JMPD' ; jump to the copied decompressor
|
||||
.1:
|
||||
%else; __LZIMAGE0__
|
||||
|
||||
cld
|
||||
mov esi, 'ESI1'
|
||||
xchg eax, edi
|
||||
|
||||
; this checka20 stuff looks very unneccessary to me
|
||||
checka20:
|
||||
inc eax
|
||||
mov [ebp + 1], eax
|
||||
cmp [edi], eax
|
||||
je checka20
|
||||
|
||||
%endif; __LZCUTPOI__
|
||||
|
||||
; =============
|
||||
; ============= DECOMPRESSION
|
||||
; =============
|
||||
|
||||
%include "n2b_d32.ash"
|
||||
%include "n2d_d32.ash"
|
||||
|
||||
; =============
|
||||
; __LINUZ990__
|
||||
pop esi
|
||||
pop edi
|
||||
xor ebx, ebx ; booting the 1st cpu
|
||||
retn
|
||||
|
||||
; =============
|
||||
; ============= CUT HERE
|
||||
; =============
|
||||
|
||||
%include "header.ash"
|
||||
|
||||
eof:
|
||||
; __LITHEEND__
|
||||
section .data
|
||||
dd -1
|
||||
dw eof
|
||||
|
|
@ -80,6 +80,7 @@ typedef unsigned upx_uint32;
|
|||
#define UPX_F_LINUX_ELF_i386 12
|
||||
#define UPX_F_LINUX_SEP_i386 13
|
||||
#define UPX_F_LINUX_SH_i386 14
|
||||
#define UPX_F_VMLINUZ_i386 15
|
||||
#define UPX_F_ATARI_TOS 129
|
||||
#define UPX_F_SOLARIS_SPARC 130
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user