mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
vmlinu[xz] using nrv2e converted to ElfLinker
This commit is contained in:
parent
db7086b5e6
commit
f0d5a6ebac
|
@ -36,6 +36,7 @@
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "packer.h"
|
#include "packer.h"
|
||||||
#include "p_vmlinx.h"
|
#include "p_vmlinx.h"
|
||||||
|
#include "linker.h"
|
||||||
|
|
||||||
static const
|
static const
|
||||||
#include "stub/i386-linux.kernel.vmlinux.h"
|
#include "stub/i386-linux.kernel.vmlinux.h"
|
||||||
|
@ -153,6 +154,13 @@ bool PackVmlinuxI386::canPack()
|
||||||
return 0 < n_ptload;
|
return 0 < n_ptload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Linker* PackVmlinuxI386::newLinker() const
|
||||||
|
{
|
||||||
|
return new ElfLinkerX86;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int PackVmlinuxI386::buildLoader(const Filter *ft)
|
int PackVmlinuxI386::buildLoader(const Filter *ft)
|
||||||
{
|
{
|
||||||
// prepare loader
|
// prepare loader
|
||||||
|
@ -180,6 +188,20 @@ int PackVmlinuxI386::buildLoader(const Filter *ft)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool defineFilterSymbols(Linker *linker, const Filter *ft)
|
||||||
|
{
|
||||||
|
if (ft->id == 0)
|
||||||
|
return false;
|
||||||
|
assert(ft->calls > 0);
|
||||||
|
|
||||||
|
linker->defineSymbol("filter_cto", ft->cto);
|
||||||
|
linker->defineSymbol("filter_length",
|
||||||
|
(ft->id & 0xf) % 3 == 0 ? ft->calls :
|
||||||
|
ft->lastcall - ft->calls * 4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PackVmlinuxI386::pack(OutputFile *fo)
|
void PackVmlinuxI386::pack(OutputFile *fo)
|
||||||
{
|
{
|
||||||
unsigned fo_off = 0;
|
unsigned fo_off = 0;
|
||||||
|
@ -226,13 +248,18 @@ void PackVmlinuxI386::pack(OutputFile *fo)
|
||||||
compressWithFilters(&ft, 512, 0, NULL, &cconf);
|
compressWithFilters(&ft, 512, 0, NULL, &cconf);
|
||||||
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
|
|
||||||
|
defineFilterSymbols(linker, &ft);
|
||||||
|
if (0x40==(0xf0 & ft.id)) {
|
||||||
|
linker->defineSymbol("filter_length", ph.u_len); // redefine
|
||||||
|
}
|
||||||
|
linker->relocate();
|
||||||
|
|
||||||
|
// FIXME patchDecompressor(loader, lsize);
|
||||||
|
|
||||||
MemBuffer loader(lsize);
|
MemBuffer loader(lsize);
|
||||||
memcpy(loader, getLoader(), lsize);
|
memcpy(loader, getLoader(), lsize);
|
||||||
|
|
||||||
patchPackHeader(loader, lsize);
|
patchPackHeader(loader, lsize);
|
||||||
patchDecompressor(loader, lsize);
|
|
||||||
patch_le32(loader, lsize, "ULEN", ph.u_len);
|
|
||||||
patchFilter32(loader, lsize, &ft);
|
|
||||||
|
|
||||||
while (0!=*p++) ;
|
while (0!=*p++) ;
|
||||||
shdro[1].sh_name = ptr_diff(p, shstrtab);
|
shdro[1].sh_name = ptr_diff(p, shstrtab);
|
||||||
|
|
|
@ -55,6 +55,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int buildLoader(const Filter *ft);
|
virtual int buildLoader(const Filter *ft);
|
||||||
|
virtual Linker* newLinker() const;
|
||||||
// virtual const upx_byte *getLoader() const;
|
// virtual const upx_byte *getLoader() const;
|
||||||
// virtual int getLoaderSize() const;
|
// virtual int getLoaderSize() const;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "packer.h"
|
#include "packer.h"
|
||||||
#include "p_vmlinz.h"
|
#include "p_vmlinz.h"
|
||||||
|
#include "linker.h"
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
static const
|
static const
|
||||||
|
@ -242,6 +243,12 @@ void PackVmlinuzI386::readKernel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Linker* PackVmlinuzI386::newLinker() const
|
||||||
|
{
|
||||||
|
return new ElfLinkerX86;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// vmlinuz specific
|
// vmlinuz specific
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
@ -268,6 +275,19 @@ int PackVmlinuzI386::buildLoader(const Filter *ft)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool defineFilterSymbols(Linker *linker, const Filter *ft)
|
||||||
|
{
|
||||||
|
if (ft->id == 0)
|
||||||
|
return false;
|
||||||
|
assert(ft->calls > 0);
|
||||||
|
|
||||||
|
linker->defineSymbol("filter_cto", ft->cto);
|
||||||
|
linker->defineSymbol("filter_length",
|
||||||
|
(ft->id & 0xf) % 3 == 0 ? ft->calls :
|
||||||
|
ft->lastcall - ft->calls * 4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void PackVmlinuzI386::pack(OutputFile *fo)
|
void PackVmlinuzI386::pack(OutputFile *fo)
|
||||||
{
|
{
|
||||||
readKernel();
|
readKernel();
|
||||||
|
@ -283,17 +303,18 @@ void PackVmlinuzI386::pack(OutputFile *fo)
|
||||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||||
compressWithFilters(&ft, 512, 0, NULL, &cconf);
|
compressWithFilters(&ft, 512, 0, NULL, &cconf);
|
||||||
|
|
||||||
freezeLoader();
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
|
|
||||||
|
defineFilterSymbols(linker, &ft);
|
||||||
|
// FIXME patchDecompressor(loader, lsize);
|
||||||
|
linker->defineSymbol("src_for_decompressor", zimage_offset + lsize);
|
||||||
|
linker->defineSymbol("original_entry", kernel_entry);
|
||||||
|
linker->defineSymbol("stack_offset", stack_offset_during_uncompression);
|
||||||
|
linker->relocate();
|
||||||
|
|
||||||
MemBuffer loader(lsize);
|
MemBuffer loader(lsize);
|
||||||
memcpy(loader, getLoader(), lsize);
|
memcpy(loader, getLoader(), lsize);
|
||||||
|
|
||||||
patchPackHeader(loader, lsize);
|
patchPackHeader(loader, lsize);
|
||||||
patchFilter32(loader, lsize, &ft);
|
|
||||||
patchDecompressor(loader, lsize);
|
|
||||||
patch_le32(loader, lsize, "ESI1", zimage_offset + lsize);
|
|
||||||
patch_le32(loader, lsize, "KEIP", kernel_entry);
|
|
||||||
patch_le32(loader, lsize, "STAK", stack_offset_during_uncompression);
|
|
||||||
|
|
||||||
boot_sect_t * const bs = (boot_sect_t *) ((unsigned char *) setup_buf);
|
boot_sect_t * const bs = (boot_sect_t *) ((unsigned char *) setup_buf);
|
||||||
bs->sys_size = ALIGN_UP(lsize + ph.c_len, 16) / 16;
|
bs->sys_size = ALIGN_UP(lsize + ph.c_len, 16) / 16;
|
||||||
|
@ -327,10 +348,15 @@ int PackBvmlinuzI386::buildLoader(const Filter *ft)
|
||||||
addLoader("LINUZ000",
|
addLoader("LINUZ000",
|
||||||
(0x40==(0xf0 & ft->id)) ? "LZCKLLT1" : (ft->id ? "LZCALLT1" : ""),
|
(0x40==(0xf0 & ft->id)) ? "LZCKLLT1" : (ft->id ? "LZCALLT1" : ""),
|
||||||
"LBZIMAGE,IDENTSTR",
|
"LBZIMAGE,IDENTSTR",
|
||||||
"+40D++++", // align the stuff to 4 byte boundary
|
"+40", // align the stuff to 4 byte boundary
|
||||||
"UPX1HEAD", // 32 byte
|
"UPX1HEAD", // 32 byte
|
||||||
"LZCUTPOI,+0000000",
|
"LZCUTPOI",
|
||||||
getDecompressorSections(),
|
NULL);
|
||||||
|
|
||||||
|
// fake alignment for the start of the decompressor
|
||||||
|
linker->defineSymbol("LZCUTPOI", 0x1000);
|
||||||
|
|
||||||
|
addLoader(getDecompressorSections(),
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
if (ft->id)
|
if (ft->id)
|
||||||
|
@ -370,12 +396,8 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||||
c_len = ALIGN_UP(c_len, 4);
|
c_len = ALIGN_UP(c_len, 4);
|
||||||
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
MemBuffer loader(lsize);
|
|
||||||
memcpy(loader, getLoader(), lsize);
|
|
||||||
|
|
||||||
patchPackHeader(loader, lsize);
|
// FIXME patchDecompressor(loader, lsize);
|
||||||
patchFilter32(loader, lsize, &ft);
|
|
||||||
patchDecompressor(loader, lsize);
|
|
||||||
|
|
||||||
const int e_len = getLoaderSectionStart("LZCUTPOI");
|
const int e_len = getLoaderSectionStart("LZCUTPOI");
|
||||||
assert(e_len > 0);
|
assert(e_len > 0);
|
||||||
|
@ -386,19 +408,24 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||||
const unsigned edi = decompr_pos + d_len4 - 4; // copy to
|
const unsigned edi = decompr_pos + d_len4 - 4; // copy to
|
||||||
const unsigned esi = ALIGN_UP(c_len + lsize, 4) - 4; // copy from
|
const unsigned esi = ALIGN_UP(c_len + lsize, 4) - 4; // copy from
|
||||||
|
|
||||||
unsigned jpos = find_le32(loader, e_len, get_le32("JMPD"));
|
linker->defineSymbol("decompressor", decompr_pos);
|
||||||
patch_le32(loader, e_len, "JMPD", decompr_pos - jpos - 4);
|
linker->defineSymbol("src_for_decompressor", bzimage_offset + decompr_pos - c_len);
|
||||||
|
linker->defineSymbol("words_to_copy", copy_size / 4);
|
||||||
patch_le32(loader, e_len, "ESI1", bzimage_offset + decompr_pos - c_len);
|
linker->defineSymbol("copy_dest", bzimage_offset + edi);
|
||||||
patch_le32(loader, e_len, "ECX0", copy_size / 4);
|
linker->defineSymbol("copy_source", bzimage_offset + esi);
|
||||||
patch_le32(loader, e_len, "EDI0", bzimage_offset + edi);
|
|
||||||
patch_le32(loader, e_len, "ESI0", bzimage_offset + esi);
|
|
||||||
|
|
||||||
|
defineFilterSymbols(linker, &ft);
|
||||||
if (0x40==(0xf0 & ft.id)) {
|
if (0x40==(0xf0 & ft.id)) {
|
||||||
patch_le32(loader, e_len, "ULEN", ph.u_len);
|
linker->defineSymbol("filter_length", ph.u_len); // redefine
|
||||||
}
|
}
|
||||||
patch_le32(loader, e_len, "KEIP", kernel_entry);
|
// FIXME patchDecompressor(loader, lsize);
|
||||||
patch_le32(loader, e_len, "STAK", stack_offset_during_uncompression);
|
linker->defineSymbol("original_entry", kernel_entry);
|
||||||
|
linker->defineSymbol("stack_offset", stack_offset_during_uncompression);
|
||||||
|
linker->relocate();
|
||||||
|
|
||||||
|
MemBuffer loader(lsize);
|
||||||
|
memcpy(loader, getLoader(), lsize);
|
||||||
|
patchPackHeader(loader, lsize);
|
||||||
|
|
||||||
boot_sect_t * const bs = (boot_sect_t *) ((unsigned char *) setup_buf);
|
boot_sect_t * const bs = (boot_sect_t *) ((unsigned char *) setup_buf);
|
||||||
bs->sys_size = (ALIGN_UP(lsize + c_len, 16) / 16) & 0xffff;
|
bs->sys_size = (ALIGN_UP(lsize + c_len, 16) / 16) & 0xffff;
|
||||||
|
|
|
@ -57,6 +57,8 @@ protected:
|
||||||
virtual void readKernel();
|
virtual void readKernel();
|
||||||
|
|
||||||
virtual int buildLoader(const Filter *ft);
|
virtual int buildLoader(const Filter *ft);
|
||||||
|
virtual Linker* newLinker() const;
|
||||||
|
|
||||||
// virtual const upx_byte *getLoader() const;
|
// virtual const upx_byte *getLoader() const;
|
||||||
// virtual int getLoaderSize() const;
|
// virtual int getLoaderSize() const;
|
||||||
|
|
||||||
|
|
|
@ -577,9 +577,11 @@ tmp/i386-linux.elf.shell-main.o : $(srcdir)/src/$$T.c
|
||||||
i386-linux.kernel.vmlin% : tc_list = arch-i386 default
|
i386-linux.kernel.vmlin% : tc_list = arch-i386 default
|
||||||
|
|
||||||
i386-linux.kernel%.h : $(srcdir)/src/$$T.asm
|
i386-linux.kernel%.h : $(srcdir)/src/$$T.asm
|
||||||
$(call tc,pp-nasm) --MMD=$@ $< -o tmp/$T.tmp1
|
$(call tc,gcc) -c -x assembler-with-cpp $< -o tmp/$T.bin
|
||||||
$(call tc,app-nasm) tmp/$T.tmp1 tmp/$T.tmp2
|
$(call tc,m-objcopy) --strip-unneeded tmp/$T.bin
|
||||||
$(call tc,nasm) -f bin -l tmp/$T.bin.lst tmp/$T.tmp2 -o tmp/$T.bin
|
$(call tc,m-objcopy) -R .text -R .data -R .bss tmp/$T.bin
|
||||||
|
$(call tc,m-objcopy) -R .note -R .comment tmp/$T.bin
|
||||||
|
$(call tc,m-objdump) -trwh tmp/$T.bin >> tmp/$T.bin
|
||||||
$(call tc,bin2h) --ident=nrv_loader tmp/$T.bin $@
|
$(call tc,bin2h) --ident=nrv_loader tmp/$T.bin $@
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -194,69 +194,67 @@ section CALLTR13
|
||||||
stosd
|
stosd
|
||||||
jmps ctloop1
|
jmps ctloop1
|
||||||
ctend:
|
ctend:
|
||||||
section CTTHEEND
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
#if 0
|
/*
|
||||||
|
|
||||||
;; call/jump/jcc trick; also used more than once (and/or optionally), so
|
;; call/jump/jcc trick; also used more than once (and/or optionally), so
|
||||||
;; ecx has byte count (not count of applied instances), and
|
;; ecx has byte count (not count of applied instances), and
|
||||||
;; edi points to buffer.
|
;; edi points to buffer.
|
||||||
%macro ckt32 2
|
*/
|
||||||
; 1st param: effective addvalue (typically 0 or edi; any rvalue)
|
.macro ckt32 addvalue, cto8
|
||||||
; 2nd param: where is cto8 (dl, bl, or literal)
|
// 1st param: effective addvalue (typically 0 or edi; any rvalue)
|
||||||
|
// 2nd param: where is cto8 (dl, bl, or literal)
|
||||||
|
|
||||||
section CKLLTR00
|
section CKLLTR00
|
||||||
%ifnidn %1,0
|
.ifnc \addvalue, 0
|
||||||
mov esi, %1
|
mov esi, \addvalue
|
||||||
%endif
|
.endif
|
||||||
jmps ckstart
|
jmps ckstart
|
||||||
ckloop3:
|
ckloop3:
|
||||||
mov al, [edi]
|
mov al, [edi]
|
||||||
add edi, byte 1
|
add edi, 1
|
||||||
section CKLLTR10 Jcc only
|
section CKLLTR10 // Jcc only
|
||||||
cmp al, 0x80 ; lo of 6-byte Jcc
|
cmp al, 0x80 // lo of 6-byte Jcc
|
||||||
jb ckloop2
|
jb ckloop2
|
||||||
cmp al, 0x8f ; hi of 6-byte Jcc
|
cmp al, 0x8f // hi of 6-byte Jcc
|
||||||
ja ckloop2
|
ja ckloop2
|
||||||
cmp byte [edi -2], 0x0F ; prefix of 6-byte Jcc
|
cmpb [edi -2], 0x0F // prefix of 6-byte Jcc
|
||||||
je ckmark
|
jes ckmark
|
||||||
ckloop2:
|
ckloop2:
|
||||||
section CKLLTR20
|
section CKLLTR20
|
||||||
sub al, 0xE8
|
sub al, 0xE8
|
||||||
cmp al, 0xE9 - 0xE8
|
cmp al, 0xE9 - 0xE8
|
||||||
ja ckcount
|
jas ckcount
|
||||||
ckmark:
|
ckmark:
|
||||||
cmp byte [edi], %2 ; cto8
|
cmp [edi], \cto8
|
||||||
jnz ckcount
|
jnzs ckcount
|
||||||
mov eax, [edi]
|
mov eax, [edi]
|
||||||
|
|
||||||
shr ax, 8
|
shr ax, 8
|
||||||
rol eax, 16
|
rol eax, 16
|
||||||
xchg ah, al
|
xchg ah, al
|
||||||
; above 3 instr are equivalent to the following 2 instr:
|
// above 3 instr are equivalent to the following 2 instr:
|
||||||
; mov al, 0 ; clear cto8 [setup partial-write stall]
|
// mov al, 0 ; clear cto8 [setup partial-write stall]
|
||||||
; bswap eax ; not on 386: need 486 and up
|
// bswap eax ; not on 386: need 486 and up
|
||||||
|
|
||||||
sub eax, edi
|
sub eax, edi
|
||||||
%ifnidn %1,0
|
.ifnc \addvalue, 0
|
||||||
add eax, esi
|
add eax, esi
|
||||||
%endif
|
.endif
|
||||||
mov [edi], eax
|
mov [edi], eax
|
||||||
add edi, byte 4
|
add edi, 4
|
||||||
ckstart:
|
ckstart:
|
||||||
sub ecx, byte 4
|
sub ecx, 4
|
||||||
section CKLLTR30 Jcc only
|
section CKLLTR30 // Jcc only
|
||||||
mov al, [edi]
|
mov al, [edi]
|
||||||
add edi, byte 1
|
add edi, 1
|
||||||
loop ckloop2 ; prefix cannot overlap previous displacement
|
loop ckloop2 // prefix cannot overlap previous displacement
|
||||||
section CKLLTR40
|
section CKLLTR40
|
||||||
ckcount:
|
ckcount:
|
||||||
sub ecx, byte 1
|
sub ecx, 1
|
||||||
jg ckloop3
|
jgs ckloop3
|
||||||
ckend:
|
ckend:
|
||||||
%endmacro
|
.endm
|
||||||
#endif
|
|
||||||
|
|
||||||
// =============
|
// =============
|
||||||
// ============= 32-BIT RELOCATIONS
|
// ============= 32-BIT RELOCATIONS
|
||||||
|
@ -301,7 +299,7 @@ reloc_endx:
|
||||||
section REL32END
|
section REL32END
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
#if 0
|
/*
|
||||||
;; =============
|
;; =============
|
||||||
;; ============= 32-BIT CALL TRICK UNFILTER WITH MostRecentlyUsed BUFFER
|
;; ============= 32-BIT CALL TRICK UNFILTER WITH MostRecentlyUsed BUFFER
|
||||||
;; =============
|
;; =============
|
||||||
|
@ -312,90 +310,92 @@ section REL32END
|
||||||
;; MRUARBnn arbitrary number of entries in wheel
|
;; MRUARBnn arbitrary number of entries in wheel
|
||||||
;; MRUBITSn power of 2 entries in wheel (smaller code)
|
;; MRUBITSn power of 2 entries in wheel (smaller code)
|
||||||
;; MRUBYTEn 256 entries in wheel (smallest code)
|
;; MRUBYTEn 256 entries in wheel (smallest code)
|
||||||
|
*/
|
||||||
|
|
||||||
%macro ctojr32 0
|
/*
|
||||||
%push ctojr32
|
|
||||||
|
|
||||||
;; I got confused by the syntactic sugar of the fake %ifdefs.
|
;; I got confused by the syntactic sugar of the fake %ifdefs.
|
||||||
;; I can read the section name more easily when it is at the left margin.
|
;; I can read the section name more easily when it is at the left margin.
|
||||||
;; Also, some of the logic to select the sections is not that simple,
|
;; Also, some of the logic to select the sections is not that simple,
|
||||||
;; and any mismatch between the logic and the %ifdefs is very confusing.
|
;; and any mismatch between the logic and the %ifdefs is very confusing.
|
||||||
;; Instead, I use comments after the section name, and blank lines for grouping.
|
;; Instead, I use comments after the section name, and blank lines for grouping.
|
||||||
|
*/
|
||||||
|
|
||||||
section LXUNF000 enter at +0 for decompression; +2 for unfiltering
|
.macro ctojr32
|
||||||
|
|
||||||
|
section LXUNF000 // enter at +0 for decompression; +2 for unfiltering
|
||||||
jmps decompr0
|
jmps decompr0
|
||||||
section LXUNF002
|
section LXUNF002
|
||||||
;; 2+ address of decompress subroutine
|
// 2+ address of decompress subroutine
|
||||||
;; unfilter(upx_byte *, length, cto8)
|
// unfilter(upx_byte *, length, cto8)
|
||||||
lxunfilter:
|
lxunfilter:
|
||||||
pop edx ; return address
|
pop edx // return address
|
||||||
pop eax ; upx_byte *, same as addvalue
|
pop eax // upx_byte *, same as addvalue
|
||||||
pop ecx ; length
|
pop ecx // length
|
||||||
xchg eax, edi ; edi= pointer; eax= saved_edi
|
xchg eax, edi // edi= pointer; eax= saved_edi
|
||||||
pusha ; save C-convention ebx, ebp, esi, edi; also eax, edx
|
pusha // save C-convention ebx, ebp, esi, edi; also eax, edx
|
||||||
|
|
||||||
; at most one of the next 2
|
// at most one of the next 2
|
||||||
section MRUBYTE0 256==n_mru
|
section MRUBYTE0 256==n_mru
|
||||||
xor ebx, ebx ; zero
|
xor ebx, ebx // zero
|
||||||
section LXMRU005 0!=n_mru
|
section LXMRU005 0!=n_mru
|
||||||
mov ebx, 'NMRU' ; modified N_MRU or N_MRU -1
|
mov ebx, offxset NMRU // modified N_MRU or N_MRU -1
|
||||||
|
|
||||||
section LXMRU006 0!=n_mru
|
section LXMRU006 0!=n_mru
|
||||||
push byte 0x0f ; prefix of 6-byte Jcc <d32>
|
push 0x0f // prefix of 6-byte Jcc <d32>
|
||||||
pop eax
|
pop eax
|
||||||
mov ah, [esp + 8*4] ; cto8
|
mov ah, [esp + 8*4] // cto8
|
||||||
section LXMRU007 0==n_mru
|
section LXMRU007 0==n_mru
|
||||||
push byte 0x0f ; prefix of 6-byte Jcc <d32>
|
push 0x0f // prefix of 6-byte Jcc <d32>
|
||||||
pop ebx
|
pop ebx
|
||||||
mov bh, [esp + 8*4] ; cto8
|
mov bh, [esp + 8*4] // cto8
|
||||||
|
|
||||||
section LXUNF008
|
section LXUNF008
|
||||||
mov dl, [esp + 8*4] ; cto8
|
mov dl, [esp + 8*4] // cto8
|
||||||
|
|
||||||
section LXUNF010
|
section LXUNF010
|
||||||
jmpn lxunf0
|
jmpn lxunf0
|
||||||
decompr0:
|
decompr0:
|
||||||
|
|
||||||
;; These %define are only if 0!=n_mru;
|
// These #define are only if 0!=n_mru;
|
||||||
;; else 0x0F==bl && cto8==bh==dh && 0xE8==dl && addvalue==esi .
|
// else 0x0F==bl && cto8==bh==dh && 0xE8==dl && addvalue==esi .
|
||||||
%define %$n_mru [esi]
|
#define __n_mru [esi]
|
||||||
%define %$n_mru1 [esi]
|
#define __n_mru1 [esi]
|
||||||
%define %$tail [esi + 4*1]
|
#define __tail [esi + 4*1]
|
||||||
%define %$cto8_e8e9 [esi + 4*2]
|
#define __cto8_e8e9 [esi + 4*2]
|
||||||
%define %$cto8_0f [esi + 4*3]
|
#define __cto8_0f [esi + 4*3]
|
||||||
%define %$addvalue [esi + 4*4]
|
#define __addvalue [esi + 4*4]
|
||||||
%define %$tmp ebp
|
#define __tmp ebp
|
||||||
%define %$hand ebx
|
#define __hand ebx
|
||||||
%define %$hand_l bl
|
#define __hand_l bl
|
||||||
%define %$kh edx
|
#define __kh edx
|
||||||
%define %$kh_l dl
|
#define __kh_l dl
|
||||||
|
|
||||||
section LXJCC010
|
section LXJCC010
|
||||||
lxunf2: ; have seen 0x80..0x8f of possible recoded 6-byte Jcc <d32>
|
lxunf2: // have seen 0x80..0x8f of possible recoded 6-byte Jcc <d32>
|
||||||
movzx ebp, word [edi] ; 2 bytes, zero-extended
|
movzx ebp, word [edi] // 2 bytes, zero-extended
|
||||||
|
|
||||||
section LXMRU045 0!=n_mru
|
section LXMRU045 0!=n_mru
|
||||||
sub ebp, %$cto8_0f
|
sub ebp, __cto8_0f
|
||||||
section LXMRU046 0==n_mru
|
section LXMRU046 0==n_mru
|
||||||
sub ebp, ebx
|
sub ebp, ebx
|
||||||
|
|
||||||
section LXJCC020 0==n_mru, or Jcc excluded ('sub' of equals clears Carry)
|
section LXJCC020 0==n_mru, or Jcc excluded ('sub' of equals clears Carry)
|
||||||
jne unfcount
|
jne unfcount
|
||||||
section LXJCC021 0!=n_mru and Jcc participates; must set Carry
|
section LXJCC021 0!=n_mru and Jcc participates// must set Carry
|
||||||
sub ebp, byte 1 ; set Carry iff in range
|
sub ebp, 1 // set Carry iff in range
|
||||||
jnb unfcount
|
jnb unfcount
|
||||||
|
|
||||||
section LXJCC023 found Jcc; re-swap 0x8Y opcode and 0x0f prefix
|
section LXJCC023 found Jcc// re-swap 0x8Y opcode and 0x0f prefix
|
||||||
mov byte [edi -1], bl ; 0x0f prefix
|
mov [edi -1], bl // 0x0f prefix
|
||||||
dec ecx ; preserve Carry
|
dec ecx // preserve Carry
|
||||||
mov byte [edi], al ; Jcc opcode
|
mov [edi], al // Jcc opcode
|
||||||
inc edi ; preserve Carry
|
inc edi // preserve Carry
|
||||||
|
|
||||||
section LXUNF037
|
section LXUNF037
|
||||||
%define %$jc eax
|
#define __jc eax
|
||||||
|
|
||||||
lxunf: ; in: Carry set iff we should apply mru and 0!=n_mru
|
lxunf: // in: Carry set iff we should apply mru and 0!=n_mru
|
||||||
mov eax, [edi] ; BE32 displacement with cto8 in low 8 bits
|
mov eax, [edi] // BE32 displacement with cto8 in low 8 bits
|
||||||
|
|
||||||
section LXUNF386 0!=n_mru && 386
|
section LXUNF386 0!=n_mru && 386
|
||||||
pushf
|
pushf
|
||||||
|
@ -405,120 +405,120 @@ section LXUNF387 ==386
|
||||||
xchg ah, al
|
xchg ah, al
|
||||||
section LXUNF388 0!=n_mru && 386
|
section LXUNF388 0!=n_mru && 386
|
||||||
popf
|
popf
|
||||||
jnc unf_store ; do not apply mru
|
jnc unf_store // do not apply mru
|
||||||
|
|
||||||
section LXUNF486 >=486
|
section LXUNF486 >=486
|
||||||
mov al, byte 0
|
mov al, 0
|
||||||
CPU 486
|
CPU 486
|
||||||
bswap eax ; preserve Carry (2-byte instruction)
|
bswap eax // preserve Carry (2-byte instruction)
|
||||||
CPU 386
|
CPU 386
|
||||||
section LXUNF487 0!=n_mru && >=486
|
section LXUNF487 0!=n_mru && >=486
|
||||||
jnc unf_store ; do not apply mru
|
jnc unf_store // do not apply mru
|
||||||
|
|
||||||
section LXMRU065 0!=n_mru
|
section LXMRU065 0!=n_mru
|
||||||
shr %$jc, 1 ; eax= jc, or mru index
|
shr __jc, 1 // eax= jc, or mru index
|
||||||
jnc mru4 ; not 1st time for this jc
|
jnc mru4 // not 1st time for this jc
|
||||||
section MRUBYTE3
|
section MRUBYTE3
|
||||||
dec %$hand_l
|
dec __hand_l
|
||||||
section MRUARB30
|
section MRUARB30
|
||||||
dec %$hand
|
dec __hand
|
||||||
section MRUBITS3
|
section MRUBITS3
|
||||||
and %$hand, %$n_mru1
|
and __hand, __n_mru1
|
||||||
section MRUARB40
|
section MRUARB40
|
||||||
jge mru3
|
jge mru3
|
||||||
add %$hand, %$n_mru
|
add __hand, __n_mru
|
||||||
mru3:
|
mru3:
|
||||||
section LXMRU070
|
section LXMRU070
|
||||||
|
|
||||||
mov [esp + 4*%$hand], %$jc ; 1st time: mru[hand] = jc
|
mov [esp + 4*__hand], __jc // 1st time: mru[hand] = jc
|
||||||
jmps unf_store
|
jmps unf_store
|
||||||
|
|
||||||
mru4: ; not 1st time for this jc
|
mru4: // not 1st time for this jc
|
||||||
lea %$kh, [%$jc + %$hand] ; kh = jc + hand
|
lea __kh, [__jc + __hand] // kh = jc + hand
|
||||||
section MRUBYTE4
|
section MRUBYTE4
|
||||||
movzx %$kh, %$kh_l
|
movzx __kh, __kh_l
|
||||||
section MRUBITS4
|
section MRUBITS4
|
||||||
and %$kh, %$n_mru1
|
and __kh, __n_mru1
|
||||||
section MRUARB50
|
section MRUARB50
|
||||||
cmp %$kh, %$n_mru
|
cmp __kh, __n_mru
|
||||||
jb mru5
|
jb mru5
|
||||||
sub %$kh, %$n_mru
|
sub __kh, __n_mru
|
||||||
mru5:
|
mru5:
|
||||||
section LXMRU080
|
section LXMRU080
|
||||||
mov %$jc, [esp + 4*%$kh] ; jc = mru[kh]
|
mov __jc, [esp + 4*__kh] // jc = mru[kh]
|
||||||
section MRUBYTE5
|
section MRUBYTE5
|
||||||
dec %$hand_l
|
dec __hand_l
|
||||||
section MRUARB60
|
section MRUARB60
|
||||||
dec %$hand
|
dec __hand
|
||||||
section MRUBITS5
|
section MRUBITS5
|
||||||
and %$hand, %$n_mru1
|
and __hand, __n_mru1
|
||||||
section MRUARB70
|
section MRUARB70
|
||||||
jge mru6
|
jge mru6
|
||||||
add %$hand, %$n_mru
|
add __hand, __n_mru
|
||||||
mru6:
|
mru6:
|
||||||
section LXMRU090
|
section LXMRU090
|
||||||
|
|
||||||
mov %$tmp, [esp + 4*%$hand] ; tmp = mru[hand]
|
mov __tmp, [esp + 4*__hand] // tmp = mru[hand]
|
||||||
test %$tmp,%$tmp
|
test __tmp,__tmp
|
||||||
jnz mru8
|
jnz mru8
|
||||||
|
|
||||||
push %$jc ; ran out of registers
|
push __jc // ran out of registers
|
||||||
mov eax, %$tail
|
mov eax, __tail
|
||||||
|
|
||||||
section MRUBYTE6
|
section MRUBYTE6
|
||||||
dec al
|
dec al
|
||||||
section MRUARB80
|
section MRUARB80
|
||||||
dec eax
|
dec eax
|
||||||
section MRUBITS6
|
section MRUBITS6
|
||||||
and eax, %$n_mru1
|
and eax, __n_mru1
|
||||||
section MRUARB90
|
section MRUARB90
|
||||||
jge mru7
|
jge mru7
|
||||||
add eax, %$n_mru
|
add eax, __n_mru
|
||||||
mru7:
|
mru7:
|
||||||
section LXMRU100
|
section LXMRU100
|
||||||
|
|
||||||
xor %$tmp,%$tmp
|
xor __tmp,__tmp
|
||||||
mov %$tail, eax
|
mov __tail, eax
|
||||||
xchg [4+ esp + 4*eax], %$tmp ; tmp = mru[tail]; mru[tail] = 0
|
xchg [4+ esp + 4*eax], __tmp // tmp = mru[tail]; mru[tail] = 0
|
||||||
pop %$jc
|
pop __jc
|
||||||
mru8:
|
mru8:
|
||||||
mov [esp + 4*%$kh ], %$tmp ; mru[kh] = tmp
|
mov [esp + 4*__kh ], __tmp // mru[kh] = tmp
|
||||||
mov [esp + 4*%$hand], %$jc ; mru[hand] = jc
|
mov [esp + 4*__hand], __jc // mru[hand] = jc
|
||||||
section LXUNF040
|
section LXUNF040
|
||||||
unf_store:
|
unf_store:
|
||||||
sub eax, edi
|
sub eax, edi
|
||||||
sub ecx, byte 4
|
sub ecx, 4
|
||||||
|
|
||||||
; one of the next2
|
// one of the next2
|
||||||
section LXMRU110 0!=n_mru
|
section LXMRU110 0!=n_mru
|
||||||
add eax, %$addvalue
|
add eax, __addvalue
|
||||||
section LXMRU111 0==n_mru
|
section LXMRU111 0==n_mru
|
||||||
add eax, esi ; addvalue (same as initial pointer)
|
add eax, esi // addvalue (same as initial pointer)
|
||||||
|
|
||||||
section LXUNF041
|
section LXUNF041
|
||||||
mov [edi], eax
|
mov [edi], eax
|
||||||
add edi, byte 4
|
add edi, 4
|
||||||
jmps unfcount
|
jmps unfcount
|
||||||
section LXUNF042
|
section LXUNF042
|
||||||
lxunf0: ;; continuation of entry prolog for unfilter
|
lxunf0: // continuation of entry prolog for unfilter
|
||||||
section LEXEC016 bug in APP: jmp and label must be in same .asx/.asy
|
section LEXEC016 bug in APP: jmp and label must be in same .asx/.asy
|
||||||
jmp lxunf0 ; this instr does not really go here!
|
jmp lxunf0 // this instr does not really go here!
|
||||||
|
|
||||||
section LXMRU010 0!=n_mru
|
section LXMRU010 0!=n_mru
|
||||||
push eax ; cto8_0f
|
push eax // cto8_0f
|
||||||
section LXJMPA00 only JMP, and not CALL, is filtered
|
section LXJMPA00 only JMP, and not CALL, is filtered
|
||||||
mov al, 0xE9
|
mov al, 0xE9
|
||||||
section LXCALLB0 only CALL, or both CALL and JMP are filtered
|
section LXCALLB0 only CALL, or both CALL and JMP are filtered
|
||||||
mov al, 0xE8
|
mov al, 0xE8
|
||||||
section LXUNF021 common tail
|
section LXUNF021 common tail
|
||||||
push eax ; cto8_e8e9
|
push eax // cto8_e8e9
|
||||||
push byte 0 ; tail
|
push 0 // tail
|
||||||
push ebx ; n_mru or n_mru1
|
push ebx // n_mru or n_mru1
|
||||||
mov esi, esp ; flat model "[esi]" saves a byte over "[ebp]"
|
mov esi, esp // flat model "[esi]" saves a byte over "[ebp]"
|
||||||
|
|
||||||
section LXMRU022 0==n_mru
|
section LXMRU022 0==n_mru
|
||||||
pop esi ; addvalue
|
pop esi // addvalue
|
||||||
mov edx, ebx ; dh= cto8
|
mov edx, ebx // dh= cto8
|
||||||
section LXJMPA01 only JMP, and not CALL, is filtered
|
section LXJMPA01 only JMP, and not CALL, is filtered
|
||||||
mov dl, 0xE9
|
mov dl, 0xE9
|
||||||
section LXCALLB1 only CALL, or both CALL and JMP are filtered
|
section LXCALLB1 only CALL, or both CALL and JMP are filtered
|
||||||
|
@ -526,56 +526,56 @@ section LXCALLB1 only CALL, or both CALL and JMP are filtered
|
||||||
|
|
||||||
|
|
||||||
section MRUBITS1
|
section MRUBITS1
|
||||||
inc %$hand ; n_mru1 ==> n_mru
|
inc __hand // n_mru1 ==> n_mru
|
||||||
section LXMRU030
|
section LXMRU030
|
||||||
lxunf1: ; allocate and clear mru[]
|
lxunf1: // allocate and clear mru[]
|
||||||
push byte 0
|
push 0
|
||||||
|
|
||||||
; one of the next 2, if n_mru
|
// one of the next 2, if n_mru
|
||||||
section MRUBYTE1
|
section MRUBYTE1
|
||||||
dec %$hand_l
|
dec __hand_l
|
||||||
section MRUARB10
|
section MRUARB10
|
||||||
dec %$hand
|
dec __hand
|
||||||
|
|
||||||
section LXMRU040 0!=n_mru
|
section LXMRU040 0!=n_mru
|
||||||
jnz lxunf1 ; leaves 0=='hand'
|
jnz lxunf1 // leaves 0=='hand'
|
||||||
|
|
||||||
section LXUNF030
|
section LXUNF030
|
||||||
lxctloop:
|
lxctloop:
|
||||||
movzx eax, word [edi] ; 2 bytes, zero extended
|
movzx eax, word [edi] // 2 bytes, zero extended
|
||||||
add edi, byte 1
|
add edi, 1
|
||||||
section LXJCC000
|
section LXJCC000
|
||||||
cmp al, 0x80 ; lo of Jcc <d32>
|
cmp al, 0x80 // lo of Jcc <d32>
|
||||||
jb lxct1
|
jb lxct1
|
||||||
cmp al, 0x8f ; hi of Jcc <d32>
|
cmp al, 0x8f // hi of Jcc <d32>
|
||||||
jbe lxunf2
|
jbe lxunf2
|
||||||
lxct1:
|
lxct1:
|
||||||
|
|
||||||
section LXCJ0MRU 0==n_mru
|
section LXCJ0MRU 0==n_mru
|
||||||
sub eax, edx
|
sub eax, edx
|
||||||
section LXCJ1MRU 0!=n_mru
|
section LXCJ1MRU 0!=n_mru
|
||||||
sub eax, %$cto8_e8e9
|
sub eax, __cto8_e8e9
|
||||||
|
|
||||||
; both CALL and JMP are filtered
|
// both CALL and JMP are filtered
|
||||||
section LXCALJMP
|
section LXCALJMP
|
||||||
sub eax, byte 1+ (0xE9 - 0xE8) ; set Carry iff in range (result: -2, -1)
|
sub eax, 1+ (0xE9 - 0xE8) // set Carry iff in range (result: -2, -1)
|
||||||
|
|
||||||
; only CALL, or only JMP, is filtered
|
// only CALL, or only JMP, is filtered
|
||||||
section LXCALL00 0==n_mru
|
section LXCALL00 0==n_mru
|
||||||
je lxunf
|
je lxunf
|
||||||
section LXCALL01 0!=n_rmu
|
section LXCALL01 0!=n_rmu
|
||||||
sub eax, byte 1 ; set Carry iff in range
|
sub eax, 1 // set Carry iff in range
|
||||||
|
|
||||||
section LXCJ2MRU 0==n_mru, or apply mru to all that are filtered here
|
section LXCJ2MRU 0==n_mru, or apply mru to all that are filtered here
|
||||||
jb lxunf ; only Carry (Borrow) matters
|
jb lxunf // only Carry (Borrow) matters
|
||||||
section LXCJ4MRU 0!=n_mru, but apply mru only to subset of filtered here
|
section LXCJ4MRU 0!=n_mru, but apply mru only to subset of filtered here
|
||||||
jnb unfcount ; was not filtered anyway: do not unfilter
|
jnb unfcount // was not filtered anyway: do not unfilter
|
||||||
|
|
||||||
;we will unfilter, and 0!=n_mru, but should we apply mru?
|
//we will unfilter, and 0!=n_mru, but should we apply mru?
|
||||||
section LXCJ6MRU apply mru to JMP only (0xFF==al)
|
section LXCJ6MRU apply mru to JMP only (0xFF==al)
|
||||||
jpe lxct3 ; jump if even number of 1 bits in al
|
jpe lxct3 // jump if even number of 1 bits in al
|
||||||
section LXCJ7MRU apply mru to CALL only (0xFE==al)
|
section LXCJ7MRU apply mru to CALL only (0xFE==al)
|
||||||
jpo lxct3 ; jump if odd number of 1 bits in al
|
jpo lxct3 // jump if odd number of 1 bits in al
|
||||||
section LXCJ8MRU do not apply mru to one or both
|
section LXCJ8MRU do not apply mru to one or both
|
||||||
clc
|
clc
|
||||||
lxct3:
|
lxct3:
|
||||||
|
@ -583,19 +583,19 @@ lxct3:
|
||||||
|
|
||||||
section LXUNF034
|
section LXUNF034
|
||||||
unfcount:
|
unfcount:
|
||||||
sub ecx, byte 1
|
sub ecx, 1
|
||||||
jg lxctloop
|
jg lxctloop
|
||||||
|
|
||||||
section LXMRU055
|
section LXMRU055
|
||||||
mov edi, esp ; clear mru[] portion of stack
|
mov edi, esp // clear mru[] portion of stack
|
||||||
section MRUBYTE2
|
section MRUBYTE2
|
||||||
mov ecx, 4+ 256 ; unused, tail, cto8_e8e9, cto8_0f
|
mov ecx, 4+ 256 // unused, tail, cto8_e8e9, cto8_0f
|
||||||
section MRUBITS2
|
section MRUBITS2
|
||||||
mov ecx, %$n_mru1
|
mov ecx, __n_mru1
|
||||||
add ecx, byte 1+ 4 ; n_mru1, tail, cto8_e8e9, cto8_0f
|
add ecx, 1+ 4 // n_mru1, tail, cto8_e8e9, cto8_0f
|
||||||
section MRUARB20
|
section MRUARB20
|
||||||
mov ecx, %$n_mru
|
mov ecx, __n_mru
|
||||||
add ecx, byte 4 ; n_mru, tail, cto8_e8e9, cto8_0f
|
add ecx, 4 // n_mru, tail, cto8_e8e9, cto8_0f
|
||||||
section LXMRU057
|
section LXMRU057
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
rep
|
rep
|
||||||
|
@ -611,8 +611,6 @@ section LXUNF035
|
||||||
push eax
|
push eax
|
||||||
push edx
|
push edx
|
||||||
ret
|
ret
|
||||||
%pop
|
.endm
|
||||||
%endmacro
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// vi:ts=8:et:nowrap
|
// vi:ts=8:et:nowrap
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/*
|
||||||
; l_vmlinx.asm -- loader & decompressor for the vmlinux/i386 format
|
; l_vmlinx.asm -- loader & decompressor for the vmlinux/i386 format
|
||||||
;
|
;
|
||||||
; This file is part of the UPX executable compressor.
|
; This file is part of the UPX executable compressor.
|
||||||
|
@ -27,122 +28,108 @@
|
||||||
;
|
;
|
||||||
; John Reiser
|
; John Reiser
|
||||||
; <jreiser@users.sourceforge.net>
|
; <jreiser@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/i386/macros2.ash"
|
||||||
|
|
||||||
%define jmps jmp short
|
/*
|
||||||
%define jmpn jmp near
|
|
||||||
%include "arch/i386/macros.ash"
|
|
||||||
|
|
||||||
BITS 32
|
|
||||||
SECTION .text
|
|
||||||
ORG 0
|
|
||||||
|
|
||||||
; =============
|
; =============
|
||||||
; ============= ENTRY POINT
|
; ============= ENTRY POINT
|
||||||
; =============
|
; =============
|
||||||
|
|
||||||
start:
|
|
||||||
; In:
|
; In:
|
||||||
; %eax= &uncompressed [and final entry]; %ds= %es= __BOOT_DS
|
; #eax= &uncompressed [and final entry]; #ds= #es= __BOOT_DS
|
||||||
; %esp: &compressed; __BOOT_CS
|
; #esp: &compressed; __BOOT_CS
|
||||||
; __LINUX000__
|
*/
|
||||||
pop edx ; &compressed; length at -4(%edx)
|
section LINUX000
|
||||||
|
pop edx // &compressed; length at -4(#edx)
|
||||||
|
|
||||||
push eax ; MATCH00(1/2) entry address; __BOOT_CS
|
push eax // MATCH00(1/2) entry address; __BOOT_CS
|
||||||
push edi ; MATCH01 save
|
push edi // MATCH01 save
|
||||||
push esi ; MATCH02 save
|
push esi // MATCH02 save
|
||||||
|
|
||||||
%ifdef __LXCALLT1__
|
section LXCALLT1
|
||||||
push eax ; MATCH03 src unfilter
|
push eax // MATCH03 src unfilter
|
||||||
%endif; __LXDUMMY0__
|
section LXCKLLT1
|
||||||
%ifdef __LXCKLLT1__
|
push eax // MATCH03 src unfilter
|
||||||
push eax ; MATCH03 src unfilter
|
//push offset filter_cto // MATCH04 cto unfilter
|
||||||
push byte '?' ; MATCH04 cto unfilter
|
.byte 0x6a, filter_cto // MATCH04 cto unfilter
|
||||||
%endif; __LXMOVEUP__
|
section LXMOVEUP
|
||||||
push 'ULEN' ; MATCH05 uncompressed length
|
push offset filter_length // MATCH05 uncompressed length
|
||||||
call move_up ; MATCH06
|
call move_up // MATCH06
|
||||||
|
|
||||||
; =============
|
// =============
|
||||||
; ============= DECOMPRESSION
|
// ============= DECOMPRESSION
|
||||||
; =============
|
// =============
|
||||||
|
|
||||||
%include "arch/i386/nrv2b_d32.ash"
|
//#include "arch/i386/nrv2b_d32.ash"
|
||||||
%include "arch/i386/nrv2d_d32.ash"
|
//#include "arch/i386/nrv2d_d32.ash"
|
||||||
%include "arch/i386/nrv2e_d32.ash"
|
//#include "arch/i386/nrv2e_d32.ash"
|
||||||
%include "arch/i386/lzma_d.ash"
|
#include "arch/i386/nrv2e_d32_2.ash"
|
||||||
|
//#include "arch/i386/lzma_d.ash"
|
||||||
|
|
||||||
; =============
|
// =============
|
||||||
; ============= UNFILTER
|
// ============= UNFILTER
|
||||||
; =============
|
// =============
|
||||||
|
|
||||||
%ifdef __LXCKLLT9__
|
section LXCKLLT9
|
||||||
pop ecx ; MATCH05 len
|
pop ecx // MATCH05 len
|
||||||
pop edx ; MATCH04 cto
|
pop edx // MATCH04 cto
|
||||||
pop edi ; MATCH03 src
|
pop edi // MATCH03 src
|
||||||
|
|
||||||
ckt32 edi, dl ; dl has cto8
|
ckt32 edi, dl // dl has cto8
|
||||||
|
/*
|
||||||
;edi: adjust for the difference between 0 origin of buffer at filter,
|
;edi: adjust for the difference between 0 origin of buffer at filter,
|
||||||
;and actual origin of destination at unfilter.
|
;and actual origin of destination at unfilter.
|
||||||
;Filter.addvalue is 0: destination origin is unknown at filter time.
|
;Filter.addvalue is 0: destination origin is unknown at filter time.
|
||||||
;The input data is still relocatable, and address is assigned later
|
;The input data is still relocatable, and address is assigned later
|
||||||
;[as of 2004-12-15 it is 'always' 0x100000].
|
;[as of 2004-12-15 it is 'always' 0x100000].
|
||||||
|
*/
|
||||||
|
|
||||||
%endif; __LXDUMMY2__
|
section LXCALLT9
|
||||||
%ifdef __LXCALLT9__
|
pop ecx // MATCH05 len
|
||||||
pop ecx ; MATCH05 len
|
pop edi // MATCH03 src
|
||||||
pop edi ; MATCH03 src
|
|
||||||
cjt32 0
|
cjt32 0
|
||||||
%endif; __LINUX990__
|
section LINUX990
|
||||||
pop esi ; MATCH02 restore
|
pop esi // MATCH02 restore
|
||||||
pop edi ; MATCH01 restore
|
pop edi // MATCH01 restore
|
||||||
xor ebx, ebx ; booting the 1st cpu
|
xor ebx, ebx // booting the 1st cpu
|
||||||
retf ; MATCH00 set cs
|
lret // MATCH00 set cs
|
||||||
|
|
||||||
%define UNLAP 0x10
|
#define UNLAP 0x10
|
||||||
%define ALIGN (~0<<4)
|
#define ALIGN (~0<<4)
|
||||||
; must have 0==(UNLAP &~ ALIGN)
|
// must have 0==(UNLAP &~ ALIGN)
|
||||||
|
|
||||||
move_up:
|
move_up:
|
||||||
pop esi ; MATCH06 &decompressor
|
pop esi // MATCH06 &decompressor
|
||||||
mov ecx,[-4+ esi] ; length of decompressor+unfilter
|
mov ecx,[-4+ esi] // length of decompressor+unfilter
|
||||||
mov ebp,eax ; &uncompressed
|
mov ebp,eax // &uncompressed
|
||||||
add eax,[esp] ; MATCH05 ULEN + base; entry to decompressor
|
add eax,[esp] // MATCH05 ULEN + base; entry to decompressor
|
||||||
add eax, byte ~ALIGN + UNLAP
|
add eax, ~ALIGN + UNLAP
|
||||||
and eax, byte ALIGN
|
and eax, ALIGN
|
||||||
|
|
||||||
std
|
std
|
||||||
; copy decompressor
|
// copy decompressor
|
||||||
lea esi,[-1+ ecx + esi] ; unmoved top -1 of decompressor
|
lea esi,[-1+ ecx + esi] // unmoved top -1 of decompressor
|
||||||
lea edi,[-1+ ecx + eax] ; moved top -1 of decompressor
|
lea edi,[-1+ ecx + eax] // moved top -1 of decompressor
|
||||||
rep
|
rep
|
||||||
movsb
|
movsb
|
||||||
|
|
||||||
mov ecx,[-4+ edx] ; length of compressed data
|
mov ecx,[-4+ edx] // length of compressed data
|
||||||
add ecx, byte 3
|
add ecx, 3
|
||||||
shr ecx,2 ; count of .long
|
shr ecx,2 // count of .long
|
||||||
; copy compressed data
|
// copy compressed data
|
||||||
lea esi,[-4+ 4*ecx + edx] ; unmoved top -4 of compressed data
|
lea esi,[-4+ 4*ecx + edx] // unmoved top -4 of compressed data
|
||||||
lea edi,[-4+ eax] ; moved top -4 of compressed data
|
lea edi,[-4+ eax] // moved top -4 of compressed data
|
||||||
rep
|
rep
|
||||||
movsd
|
movsd
|
||||||
|
|
||||||
cld
|
cld
|
||||||
lea esi,[4+ edi] ; &compressed [after move]
|
lea esi,[4+ edi] // &compressed [after move]
|
||||||
mov edi,ebp ; &uncompressed
|
mov edi,ebp // &uncompressed
|
||||||
or ebp, byte -1 ; decompressor assumption
|
or ebp, -1 // decompressor assumption
|
||||||
jmp eax ; enter moved decompressor
|
jmp eax // enter moved decompressor
|
||||||
|
|
||||||
; =============
|
#include "include/header2.ash"
|
||||||
; ============= CUT HERE
|
|
||||||
; =============
|
|
||||||
|
|
||||||
%include "include/header.ash"
|
// vi:ts=8:et:nowrap
|
||||||
|
|
||||||
eof:
|
|
||||||
; __LITHEEND__
|
|
||||||
section .data
|
|
||||||
dd -1
|
|
||||||
dw eof
|
|
||||||
|
|
||||||
|
|
||||||
; vi:ts=8:et:nowrap
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/*
|
||||||
; l_vmlinz.asm -- loader & decompressor for the vmlinuz/i386 format
|
; l_vmlinz.asm -- loader & decompressor for the vmlinuz/i386 format
|
||||||
;
|
;
|
||||||
; This file is part of the UPX executable compressor.
|
; This file is part of the UPX executable compressor.
|
||||||
|
@ -24,32 +25,29 @@
|
||||||
; Markus F.X.J. Oberhumer Laszlo Molnar
|
; Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
; <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
; <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
;
|
;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
%define jmps jmp short
|
#include "arch/i386/macros2.ash"
|
||||||
%define jmpn jmp near
|
|
||||||
%include "arch/i386/macros.ash"
|
|
||||||
|
|
||||||
BITS 32
|
// =============
|
||||||
SECTION .text
|
// ============= ENTRY POINT
|
||||||
ORG 0
|
// =============
|
||||||
|
|
||||||
; =============
|
section LINUZ000
|
||||||
; ============= ENTRY POINT
|
//cli // this must be true already
|
||||||
; =============
|
|
||||||
|
|
||||||
start:
|
|
||||||
; __LINUZ000__
|
|
||||||
;cli ;this must be true already
|
|
||||||
|
|
||||||
|
/*
|
||||||
; The only facts about segments here, that are true for all kernels:
|
; The only facts about segments here, that are true for all kernels:
|
||||||
; %cs is a valid "flat" code segment; no other segment reg is valid;
|
; %cs is a valid "flat" code segment; no other segment reg is valid;
|
||||||
; the next segment after %cs is a valid "flat" data segment, but
|
; the next segment after %cs is a valid "flat" data segment, but
|
||||||
; no segment register designates it yet.
|
; no segment register designates it yet.
|
||||||
|
*/
|
||||||
mov eax, cs
|
mov eax, cs
|
||||||
add eax, byte 1<<3 ; the next segment after %cs
|
add eax, 1<<3 // the next segment after %cs
|
||||||
mov ds, eax
|
mov ds, eax
|
||||||
mov es, eax
|
mov es, eax
|
||||||
|
/*
|
||||||
; fs, gs set by startup_32 in arch/i386/kernel/head.S
|
; fs, gs set by startup_32 in arch/i386/kernel/head.S
|
||||||
|
|
||||||
; Linux Documentation/i386/boot.txt "SAMPLE BOOT CONFIGURATION" says
|
; Linux Documentation/i386/boot.txt "SAMPLE BOOT CONFIGURATION" says
|
||||||
|
@ -61,108 +59,99 @@ start:
|
||||||
|
|
||||||
; In any case, avoid EBDA (Extended BIOS Data Area) below 0xA0000.
|
; In any case, avoid EBDA (Extended BIOS Data Area) below 0xA0000.
|
||||||
; boot.txt says 0x9A000 is the limit. LILO goes up to 0x9B000.
|
; boot.txt says 0x9A000 is the limit. LILO goes up to 0x9B000.
|
||||||
|
*/
|
||||||
|
lea ecx, [stack_offset + esi] // (0x9000 + 0x90000) typical
|
||||||
|
mov [-8 + ecx], ecx // 32-bit offset for stack pointer
|
||||||
|
mov [-4 + ecx], eax // segment for stack
|
||||||
|
lss esp, [-8 + ecx] // %ss:%esp= %ds:0x99000
|
||||||
|
|
||||||
lea ecx, ['STAK' + esi] ; (0x9000 + 0x90000) typical
|
push 0
|
||||||
mov [-8 + ecx], ecx ; 32-bit offset for stack pointer
|
popf // BIOS can leave random flags (such as NT)
|
||||||
mov [-4 + ecx], eax ; segment for stack
|
|
||||||
lss esp, [-8 + ecx] ; %ss:%esp= %ds:0x99000
|
|
||||||
|
|
||||||
push byte 0
|
// do not clear .bss: at this point, .bss comes only from
|
||||||
popf ; BIOS can leave random flags (such as NT)
|
// arch/i386/boot/compressed/*.o which we are replacing entirely
|
||||||
|
|
||||||
; do not clear .bss: at this point, .bss comes only from
|
or ebp, -1 // decompressor assumption
|
||||||
; arch/i386/boot/compressed/*.o which we are replacing entirely
|
mov eax, offset original_entry // 0x100000 : address of startup_32
|
||||||
|
push cs // MATCH00
|
||||||
|
push eax // MATCH00 entry address
|
||||||
|
push edi // MATCH01 save
|
||||||
|
push esi // MATCH02 save
|
||||||
|
|
||||||
or ebp, byte -1 ; decompressor assumption
|
section LZCALLT1
|
||||||
mov eax, 'KEIP' ; 0x100000 : address of startup_32
|
push eax // MATCH03 src unfilter
|
||||||
push cs ; MATCH00
|
section LZCKLLT1
|
||||||
push eax ; MATCH00 entry address
|
push eax // MATCH03 src unfilter
|
||||||
push edi ; MATCH01 save
|
//push offset filter_cto // MATCH04 cto unfilter
|
||||||
push esi ; MATCH02 save
|
.byte 0x6a, filter_cto // MATCH04 cto unfilter
|
||||||
|
push offset filter_length // MATCH05 len unfilter
|
||||||
%ifdef __LZCALLT1__
|
section LBZIMAGE
|
||||||
push eax ; MATCH03 src unfilter
|
mov esi, offset copy_source
|
||||||
%endif; __LZDUMMY0__
|
mov edi, offset copy_dest
|
||||||
%ifdef __LZCKLLT1__
|
mov ecx, offset words_to_copy
|
||||||
push eax ; MATCH03 src unfilter
|
|
||||||
push byte '?' ; MATCH04 cto unfilter
|
|
||||||
push 'ULEN' ; MATCH05 len unfilter
|
|
||||||
%endif; __LZDUMMY1__
|
|
||||||
%ifdef __LBZIMAGE__
|
|
||||||
mov esi, 'ESI0'
|
|
||||||
mov edi, 'EDI0'
|
|
||||||
mov ecx, 'ECX0'
|
|
||||||
|
|
||||||
std
|
std
|
||||||
rep
|
rep
|
||||||
movsd
|
movsd
|
||||||
cld
|
cld
|
||||||
|
|
||||||
mov esi, 'ESI1' ; esi = src for decompressor
|
mov esi, offset src_for_decompressor
|
||||||
xchg eax, edi ; edi = dst for decompressor = 0x100000
|
xchg eax, edi // edi = dst for decompressor = 0x100000
|
||||||
jmp .1 + 'JMPD' ; jump to the copied decompressor
|
jmp decompressor // jump to the copied decompressor
|
||||||
.1:
|
|
||||||
%else; __LZIMAGE0__
|
|
||||||
|
|
||||||
; this checka20 stuff looks very unneccessary to me
|
section LZIMAGE0
|
||||||
|
|
||||||
|
// this checka20 stuff looks very unneccessary to me
|
||||||
checka20:
|
checka20:
|
||||||
inc edi ; change value
|
inc edi // change value
|
||||||
mov [1 + ebp], edi ; store to 0x000000 (even megabyte)
|
mov [1 + ebp], edi // store to 0x000000 (even megabyte)
|
||||||
cmp [eax], edi ; compare 0x100000 ( odd megabyte)
|
cmp [eax], edi // compare 0x100000 ( odd megabyte)
|
||||||
je checka20 ; addresses are [still] aliased
|
je checka20 // addresses are [still] aliased
|
||||||
|
|
||||||
cld
|
cld
|
||||||
mov esi, 'ESI1'
|
mov esi, offset src_for_decompressor
|
||||||
xchg eax, edi ; edi = dst for decompressor = 0x100000
|
xchg eax, edi // edi = dst for decompressor = 0x100000
|
||||||
|
|
||||||
%endif; __LZCUTPOI__
|
section LZCUTPOI
|
||||||
|
|
||||||
; =============
|
// =============
|
||||||
; ============= DECOMPRESSION
|
// ============= DECOMPRESSION
|
||||||
; =============
|
// =============
|
||||||
|
|
||||||
%include "arch/i386/nrv2b_d32.ash"
|
//#include "arch/i386/nrv2b_d32.ash"
|
||||||
%include "arch/i386/nrv2d_d32.ash"
|
//#include "arch/i386/nrv2d_d32.ash"
|
||||||
%include "arch/i386/nrv2e_d32.ash"
|
//#include "arch/i386/nrv2e_d32.ash"
|
||||||
%include "arch/i386/lzma_d.ash"
|
#include "arch/i386/nrv2e_d32_2.ash"
|
||||||
|
//#include "arch/i386/lzma_d.ash"
|
||||||
|
|
||||||
; =============
|
// =============
|
||||||
; ============= UNFILTER
|
// ============= UNFILTER
|
||||||
; =============
|
// =============
|
||||||
|
|
||||||
%ifdef __LZCKLLT9__
|
section LZCKLLT9
|
||||||
pop ecx ; MATCH05 len
|
pop ecx // MATCH05 len
|
||||||
pop edx ; MATCH04 cto
|
pop edx // MATCH04 cto
|
||||||
pop edi ; MATCH03 src
|
pop edi // MATCH03 src
|
||||||
|
|
||||||
ckt32 0, dl ; dl has cto8
|
ckt32 0, dl // dl has cto8
|
||||||
|
/*
|
||||||
;0: Filter.addvalue = kernel_entry already did the 'add' at filter time
|
;0: Filter.addvalue = kernel_entry already did the 'add' at filter time
|
||||||
;[the runtime address of the destination was known], so we save 4 bytes
|
;[the runtime address of the destination was known], so we save 4 bytes
|
||||||
;(plus 1 cycle per instance) by not doing the 'add' when unfiltering.
|
;(plus 1 cycle per instance) by not doing the 'add' when unfiltering.
|
||||||
;If .addvalue was 0, then use 'edi' instead of 0 in call to ckt32,
|
;If .addvalue was 0, then use 'edi' instead of 0 in call to ckt32,
|
||||||
;to compensate for difference in origin of buffer.
|
;to compensate for difference in origin of buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
%endif; __LZDUMMY2__
|
section LZCALLT9
|
||||||
%ifdef __LZCALLT9__
|
pop edi // MATCH03 src
|
||||||
pop edi ; MATCH03 src
|
|
||||||
cjt32 0
|
cjt32 0
|
||||||
%endif; __LINUZ990__
|
|
||||||
pop esi ; MATCH02 restore
|
|
||||||
pop edi ; MATCH01 restore
|
|
||||||
xor ebx, ebx ; booting the 1st cpu
|
|
||||||
retf ; MATCH00 set cs
|
|
||||||
|
|
||||||
; =============
|
section LINUZ990
|
||||||
; ============= CUT HERE
|
pop esi // MATCH02 restore
|
||||||
; =============
|
pop edi // MATCH01 restore
|
||||||
|
xor ebx, ebx // booting the 1st cpu
|
||||||
|
lret // MATCH00 set cs
|
||||||
|
|
||||||
%include "include/header.ash"
|
#include "include/header2.ash"
|
||||||
|
|
||||||
eof:
|
// vi:ts=8:et:nowrap
|
||||||
; __LITHEEND__
|
|
||||||
section .data
|
|
||||||
dd -1
|
|
||||||
dw eof
|
|
||||||
|
|
||||||
|
|
||||||
; vi:ts=8:et:nowrap
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user