1
0
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:
László Molnár 2006-07-04 17:36:54 +02:00
parent db7086b5e6
commit f0d5a6ebac
10 changed files with 2411 additions and 1533 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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