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 "packer.h"
#include "p_vmlinx.h"
#include "linker.h"
static const
#include "stub/i386-linux.kernel.vmlinux.h"
@ -153,6 +154,13 @@ bool PackVmlinuxI386::canPack()
return 0 < n_ptload;
}
Linker* PackVmlinuxI386::newLinker() const
{
return new ElfLinkerX86;
}
int PackVmlinuxI386::buildLoader(const Filter *ft)
{
// 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)
{
unsigned fo_off = 0;
@ -226,13 +248,18 @@ void PackVmlinuxI386::pack(OutputFile *fo)
compressWithFilters(&ft, 512, 0, NULL, &cconf);
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);
memcpy(loader, getLoader(), lsize);
patchPackHeader(loader, lsize);
patchDecompressor(loader, lsize);
patch_le32(loader, lsize, "ULEN", ph.u_len);
patchFilter32(loader, lsize, &ft);
while (0!=*p++) ;
shdro[1].sh_name = ptr_diff(p, shstrtab);

View File

@ -55,6 +55,7 @@ public:
protected:
virtual int buildLoader(const Filter *ft);
virtual Linker* newLinker() const;
// virtual const upx_byte *getLoader() const;
// virtual int getLoaderSize() const;

View File

@ -32,6 +32,7 @@
#include "filter.h"
#include "packer.h"
#include "p_vmlinz.h"
#include "linker.h"
#include <zlib.h>
static const
@ -242,6 +243,12 @@ void PackVmlinuzI386::readKernel()
}
Linker* PackVmlinuzI386::newLinker() const
{
return new ElfLinkerX86;
}
/*************************************************************************
// 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)
{
readKernel();
@ -283,17 +303,18 @@ void PackVmlinuzI386::pack(OutputFile *fo)
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
compressWithFilters(&ft, 512, 0, NULL, &cconf);
freezeLoader();
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);
memcpy(loader, getLoader(), 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);
bs->sys_size = ALIGN_UP(lsize + ph.c_len, 16) / 16;
@ -327,10 +348,15 @@ int PackBvmlinuzI386::buildLoader(const Filter *ft)
addLoader("LINUZ000",
(0x40==(0xf0 & ft->id)) ? "LZCKLLT1" : (ft->id ? "LZCALLT1" : ""),
"LBZIMAGE,IDENTSTR",
"+40D++++", // align the stuff to 4 byte boundary
"+40", // align the stuff to 4 byte boundary
"UPX1HEAD", // 32 byte
"LZCUTPOI,+0000000",
getDecompressorSections(),
"LZCUTPOI",
NULL);
// fake alignment for the start of the decompressor
linker->defineSymbol("LZCUTPOI", 0x1000);
addLoader(getDecompressorSections(),
NULL
);
if (ft->id)
@ -370,12 +396,8 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
c_len = ALIGN_UP(c_len, 4);
const unsigned lsize = getLoaderSize();
MemBuffer loader(lsize);
memcpy(loader, getLoader(), lsize);
patchPackHeader(loader, lsize);
patchFilter32(loader, lsize, &ft);
patchDecompressor(loader, lsize);
// FIXME patchDecompressor(loader, lsize);
const int e_len = getLoaderSectionStart("LZCUTPOI");
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 esi = ALIGN_UP(c_len + 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 - c_len);
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);
linker->defineSymbol("decompressor", decompr_pos);
linker->defineSymbol("src_for_decompressor", bzimage_offset + decompr_pos - c_len);
linker->defineSymbol("words_to_copy", copy_size / 4);
linker->defineSymbol("copy_dest", bzimage_offset + edi);
linker->defineSymbol("copy_source", bzimage_offset + esi);
defineFilterSymbols(linker, &ft);
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);
patch_le32(loader, e_len, "STAK", stack_offset_during_uncompression);
// FIXME patchDecompressor(loader, lsize);
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);
bs->sys_size = (ALIGN_UP(lsize + c_len, 16) / 16) & 0xffff;

View File

@ -57,6 +57,8 @@ protected:
virtual void readKernel();
virtual int buildLoader(const Filter *ft);
virtual Linker* newLinker() const;
// virtual const upx_byte *getLoader() 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%.h : $(srcdir)/src/$$T.asm
$(call tc,pp-nasm) --MMD=$@ $< -o tmp/$T.tmp1
$(call tc,app-nasm) tmp/$T.tmp1 tmp/$T.tmp2
$(call tc,nasm) -f bin -l tmp/$T.bin.lst tmp/$T.tmp2 -o tmp/$T.bin
$(call tc,gcc) -c -x assembler-with-cpp $< -o tmp/$T.bin
$(call tc,m-objcopy) --strip-unneeded 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 $@

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
jmps ctloop1
ctend:
section CTTHEEND
.endm
#if 0
/*
;; call/jump/jcc trick; also used more than once (and/or optionally), so
;; ecx has byte count (not count of applied instances), and
;; edi points to buffer.
%macro ckt32 2
; 1st param: effective addvalue (typically 0 or edi; any rvalue)
; 2nd param: where is cto8 (dl, bl, or literal)
*/
.macro ckt32 addvalue, cto8
// 1st param: effective addvalue (typically 0 or edi; any rvalue)
// 2nd param: where is cto8 (dl, bl, or literal)
section CKLLTR00
%ifnidn %1,0
mov esi, %1
%endif
section CKLLTR00
.ifnc \addvalue, 0
mov esi, \addvalue
.endif
jmps ckstart
ckloop3:
mov al, [edi]
add edi, byte 1
section CKLLTR10 Jcc only
cmp al, 0x80 ; lo of 6-byte Jcc
add edi, 1
section CKLLTR10 // Jcc only
cmp al, 0x80 // lo of 6-byte Jcc
jb ckloop2
cmp al, 0x8f ; hi of 6-byte Jcc
cmp al, 0x8f // hi of 6-byte Jcc
ja ckloop2
cmp byte [edi -2], 0x0F ; prefix of 6-byte Jcc
je ckmark
cmpb [edi -2], 0x0F // prefix of 6-byte Jcc
jes ckmark
ckloop2:
section CKLLTR20
section CKLLTR20
sub al, 0xE8
cmp al, 0xE9 - 0xE8
ja ckcount
jas ckcount
ckmark:
cmp byte [edi], %2 ; cto8
jnz ckcount
cmp [edi], \cto8
jnzs ckcount
mov eax, [edi]
shr ax, 8
rol eax, 16
xchg ah, al
; above 3 instr are equivalent to the following 2 instr:
; mov al, 0 ; clear cto8 [setup partial-write stall]
; bswap eax ; not on 386: need 486 and up
// above 3 instr are equivalent to the following 2 instr:
// mov al, 0 ; clear cto8 [setup partial-write stall]
// bswap eax ; not on 386: need 486 and up
sub eax, edi
%ifnidn %1,0
.ifnc \addvalue, 0
add eax, esi
%endif
.endif
mov [edi], eax
add edi, byte 4
add edi, 4
ckstart:
sub ecx, byte 4
section CKLLTR30 Jcc only
sub ecx, 4
section CKLLTR30 // Jcc only
mov al, [edi]
add edi, byte 1
loop ckloop2 ; prefix cannot overlap previous displacement
section CKLLTR40
add edi, 1
loop ckloop2 // prefix cannot overlap previous displacement
section CKLLTR40
ckcount:
sub ecx, byte 1
jg ckloop3
sub ecx, 1
jgs ckloop3
ckend:
%endmacro
#endif
.endm
// =============
// ============= 32-BIT RELOCATIONS
@ -301,7 +299,7 @@ reloc_endx:
section REL32END
.endm
#if 0
/*
;; =============
;; ============= 32-BIT CALL TRICK UNFILTER WITH MostRecentlyUsed BUFFER
;; =============
@ -312,90 +310,92 @@ section REL32END
;; MRUARBnn arbitrary number of entries in wheel
;; MRUBITSn power of 2 entries in wheel (smaller 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 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,
;; 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.
*/
section LXUNF000 enter at +0 for decompression; +2 for unfiltering
.macro ctojr32
section LXUNF000 // enter at +0 for decompression; +2 for unfiltering
jmps decompr0
section LXUNF002
;; 2+ address of decompress subroutine
;; unfilter(upx_byte *, length, cto8)
// 2+ address of decompress subroutine
// unfilter(upx_byte *, length, cto8)
lxunfilter:
pop edx ; return address
pop eax ; upx_byte *, same as addvalue
pop ecx ; length
xchg eax, edi ; edi= pointer; eax= saved_edi
pusha ; save C-convention ebx, ebp, esi, edi; also eax, edx
pop edx // return address
pop eax // upx_byte *, same as addvalue
pop ecx // length
xchg eax, edi // edi= pointer; eax= saved_edi
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
xor ebx, ebx ; zero
xor ebx, ebx // zero
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
push byte 0x0f ; prefix of 6-byte Jcc <d32>
push 0x0f // prefix of 6-byte Jcc <d32>
pop eax
mov ah, [esp + 8*4] ; cto8
mov ah, [esp + 8*4] // cto8
section LXMRU007 0==n_mru
push byte 0x0f ; prefix of 6-byte Jcc <d32>
push 0x0f // prefix of 6-byte Jcc <d32>
pop ebx
mov bh, [esp + 8*4] ; cto8
mov bh, [esp + 8*4] // cto8
section LXUNF008
mov dl, [esp + 8*4] ; cto8
mov dl, [esp + 8*4] // cto8
section LXUNF010
jmpn lxunf0
decompr0:
;; These %define are only if 0!=n_mru;
;; else 0x0F==bl && cto8==bh==dh && 0xE8==dl && addvalue==esi .
%define %$n_mru [esi]
%define %$n_mru1 [esi]
%define %$tail [esi + 4*1]
%define %$cto8_e8e9 [esi + 4*2]
%define %$cto8_0f [esi + 4*3]
%define %$addvalue [esi + 4*4]
%define %$tmp ebp
%define %$hand ebx
%define %$hand_l bl
%define %$kh edx
%define %$kh_l dl
// These #define are only if 0!=n_mru;
// else 0x0F==bl && cto8==bh==dh && 0xE8==dl && addvalue==esi .
#define __n_mru [esi]
#define __n_mru1 [esi]
#define __tail [esi + 4*1]
#define __cto8_e8e9 [esi + 4*2]
#define __cto8_0f [esi + 4*3]
#define __addvalue [esi + 4*4]
#define __tmp ebp
#define __hand ebx
#define __hand_l bl
#define __kh edx
#define __kh_l dl
section LXJCC010
lxunf2: ; have seen 0x80..0x8f of possible recoded 6-byte Jcc <d32>
movzx ebp, word [edi] ; 2 bytes, zero-extended
lxunf2: // have seen 0x80..0x8f of possible recoded 6-byte Jcc <d32>
movzx ebp, word [edi] // 2 bytes, zero-extended
section LXMRU045 0!=n_mru
sub ebp, %$cto8_0f
sub ebp, __cto8_0f
section LXMRU046 0==n_mru
sub ebp, ebx
section LXJCC020 0==n_mru, or Jcc excluded ('sub' of equals clears Carry)
jne unfcount
section LXJCC021 0!=n_mru and Jcc participates; must set Carry
sub ebp, byte 1 ; set Carry iff in range
section LXJCC021 0!=n_mru and Jcc participates// must set Carry
sub ebp, 1 // set Carry iff in range
jnb unfcount
section LXJCC023 found Jcc; re-swap 0x8Y opcode and 0x0f prefix
mov byte [edi -1], bl ; 0x0f prefix
dec ecx ; preserve Carry
mov byte [edi], al ; Jcc opcode
inc edi ; preserve Carry
section LXJCC023 found Jcc// re-swap 0x8Y opcode and 0x0f prefix
mov [edi -1], bl // 0x0f prefix
dec ecx // preserve Carry
mov [edi], al // Jcc opcode
inc edi // preserve Carry
section LXUNF037
%define %$jc eax
#define __jc eax
lxunf: ; in: Carry set iff we should apply mru and 0!=n_mru
mov eax, [edi] ; BE32 displacement with cto8 in low 8 bits
lxunf: // in: Carry set iff we should apply mru and 0!=n_mru
mov eax, [edi] // BE32 displacement with cto8 in low 8 bits
section LXUNF386 0!=n_mru && 386
pushf
@ -405,120 +405,120 @@ section LXUNF387 ==386
xchg ah, al
section LXUNF388 0!=n_mru && 386
popf
jnc unf_store ; do not apply mru
jnc unf_store // do not apply mru
section LXUNF486 >=486
mov al, byte 0
mov al, 0
CPU 486
bswap eax ; preserve Carry (2-byte instruction)
bswap eax // preserve Carry (2-byte instruction)
CPU 386
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
shr %$jc, 1 ; eax= jc, or mru index
jnc mru4 ; not 1st time for this jc
shr __jc, 1 // eax= jc, or mru index
jnc mru4 // not 1st time for this jc
section MRUBYTE3
dec %$hand_l
dec __hand_l
section MRUARB30
dec %$hand
dec __hand
section MRUBITS3
and %$hand, %$n_mru1
and __hand, __n_mru1
section MRUARB40
jge mru3
add %$hand, %$n_mru
add __hand, __n_mru
mru3:
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
mru4: ; not 1st time for this jc
lea %$kh, [%$jc + %$hand] ; kh = jc + hand
mru4: // not 1st time for this jc
lea __kh, [__jc + __hand] // kh = jc + hand
section MRUBYTE4
movzx %$kh, %$kh_l
movzx __kh, __kh_l
section MRUBITS4
and %$kh, %$n_mru1
and __kh, __n_mru1
section MRUARB50
cmp %$kh, %$n_mru
cmp __kh, __n_mru
jb mru5
sub %$kh, %$n_mru
sub __kh, __n_mru
mru5:
section LXMRU080
mov %$jc, [esp + 4*%$kh] ; jc = mru[kh]
mov __jc, [esp + 4*__kh] // jc = mru[kh]
section MRUBYTE5
dec %$hand_l
dec __hand_l
section MRUARB60
dec %$hand
dec __hand
section MRUBITS5
and %$hand, %$n_mru1
and __hand, __n_mru1
section MRUARB70
jge mru6
add %$hand, %$n_mru
add __hand, __n_mru
mru6:
section LXMRU090
mov %$tmp, [esp + 4*%$hand] ; tmp = mru[hand]
test %$tmp,%$tmp
mov __tmp, [esp + 4*__hand] // tmp = mru[hand]
test __tmp,__tmp
jnz mru8
push %$jc ; ran out of registers
mov eax, %$tail
push __jc // ran out of registers
mov eax, __tail
section MRUBYTE6
dec al
section MRUARB80
dec eax
section MRUBITS6
and eax, %$n_mru1
and eax, __n_mru1
section MRUARB90
jge mru7
add eax, %$n_mru
add eax, __n_mru
mru7:
section LXMRU100
xor %$tmp,%$tmp
mov %$tail, eax
xchg [4+ esp + 4*eax], %$tmp ; tmp = mru[tail]; mru[tail] = 0
pop %$jc
xor __tmp,__tmp
mov __tail, eax
xchg [4+ esp + 4*eax], __tmp // tmp = mru[tail]; mru[tail] = 0
pop __jc
mru8:
mov [esp + 4*%$kh ], %$tmp ; mru[kh] = tmp
mov [esp + 4*%$hand], %$jc ; mru[hand] = jc
mov [esp + 4*__kh ], __tmp // mru[kh] = tmp
mov [esp + 4*__hand], __jc // mru[hand] = jc
section LXUNF040
unf_store:
sub eax, edi
sub ecx, byte 4
sub ecx, 4
; one of the next2
// one of the next2
section LXMRU110 0!=n_mru
add eax, %$addvalue
add eax, __addvalue
section LXMRU111 0==n_mru
add eax, esi ; addvalue (same as initial pointer)
add eax, esi // addvalue (same as initial pointer)
section LXUNF041
mov [edi], eax
add edi, byte 4
add edi, 4
jmps unfcount
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
jmp lxunf0 ; this instr does not really go here!
jmp lxunf0 // this instr does not really go here!
section LXMRU010 0!=n_mru
push eax ; cto8_0f
push eax // cto8_0f
section LXJMPA00 only JMP, and not CALL, is filtered
mov al, 0xE9
section LXCALLB0 only CALL, or both CALL and JMP are filtered
mov al, 0xE8
section LXUNF021 common tail
push eax ; cto8_e8e9
push byte 0 ; tail
push ebx ; n_mru or n_mru1
mov esi, esp ; flat model "[esi]" saves a byte over "[ebp]"
push eax // cto8_e8e9
push 0 // tail
push ebx // n_mru or n_mru1
mov esi, esp // flat model "[esi]" saves a byte over "[ebp]"
section LXMRU022 0==n_mru
pop esi ; addvalue
mov edx, ebx ; dh= cto8
pop esi // addvalue
mov edx, ebx // dh= cto8
section LXJMPA01 only JMP, and not CALL, is filtered
mov dl, 0xE9
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
inc %$hand ; n_mru1 ==> n_mru
inc __hand // n_mru1 ==> n_mru
section LXMRU030
lxunf1: ; allocate and clear mru[]
push byte 0
lxunf1: // allocate and clear mru[]
push 0
; one of the next 2, if n_mru
// one of the next 2, if n_mru
section MRUBYTE1
dec %$hand_l
dec __hand_l
section MRUARB10
dec %$hand
dec __hand
section LXMRU040 0!=n_mru
jnz lxunf1 ; leaves 0=='hand'
jnz lxunf1 // leaves 0=='hand'
section LXUNF030
lxctloop:
movzx eax, word [edi] ; 2 bytes, zero extended
add edi, byte 1
movzx eax, word [edi] // 2 bytes, zero extended
add edi, 1
section LXJCC000
cmp al, 0x80 ; lo of Jcc <d32>
cmp al, 0x80 // lo of Jcc <d32>
jb lxct1
cmp al, 0x8f ; hi of Jcc <d32>
cmp al, 0x8f // hi of Jcc <d32>
jbe lxunf2
lxct1:
section LXCJ0MRU 0==n_mru
sub eax, edx
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
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
je lxunf
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
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
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)
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)
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
clc
lxct3:
@ -583,19 +583,19 @@ lxct3:
section LXUNF034
unfcount:
sub ecx, byte 1
sub ecx, 1
jg lxctloop
section LXMRU055
mov edi, esp ; clear mru[] portion of stack
mov edi, esp // clear mru[] portion of stack
section MRUBYTE2
mov ecx, 4+ 256 ; unused, tail, cto8_e8e9, cto8_0f
mov ecx, 4+ 256 // unused, tail, cto8_e8e9, cto8_0f
section MRUBITS2
mov ecx, %$n_mru1
add ecx, byte 1+ 4 ; n_mru1, tail, cto8_e8e9, cto8_0f
mov ecx, __n_mru1
add ecx, 1+ 4 // n_mru1, tail, cto8_e8e9, cto8_0f
section MRUARB20
mov ecx, %$n_mru
add ecx, byte 4 ; n_mru, tail, cto8_e8e9, cto8_0f
mov ecx, __n_mru
add ecx, 4 // n_mru, tail, cto8_e8e9, cto8_0f
section LXMRU057
xor eax, eax
rep
@ -611,8 +611,6 @@ section LXUNF035
push eax
push edx
ret
%pop
%endmacro
#endif
.endm
// vi:ts=8:et:nowrap

View File

@ -1,3 +1,4 @@
/*
; l_vmlinx.asm -- loader & decompressor for the vmlinux/i386 format
;
; This file is part of the UPX executable compressor.
@ -27,122 +28,108 @@
;
; John Reiser
; <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
; =============
start:
; In:
; %eax= &uncompressed [and final entry]; %ds= %es= __BOOT_DS
; %esp: &compressed; __BOOT_CS
; __LINUX000__
pop edx ; &compressed; length at -4(%edx)
; #eax= &uncompressed [and final entry]; #ds= #es= __BOOT_DS
; #esp: &compressed; __BOOT_CS
*/
section LINUX000
pop edx // &compressed; length at -4(#edx)
push eax ; MATCH00(1/2) entry address; __BOOT_CS
push edi ; MATCH01 save
push esi ; MATCH02 save
push eax // MATCH00(1/2) entry address; __BOOT_CS
push edi // MATCH01 save
push esi // MATCH02 save
%ifdef __LXCALLT1__
push eax ; MATCH03 src unfilter
%endif; __LXDUMMY0__
%ifdef __LXCKLLT1__
push eax ; MATCH03 src unfilter
push byte '?' ; MATCH04 cto unfilter
%endif; __LXMOVEUP__
push 'ULEN' ; MATCH05 uncompressed length
call move_up ; MATCH06
section LXCALLT1
push eax // MATCH03 src unfilter
section LXCKLLT1
push eax // MATCH03 src unfilter
//push offset filter_cto // MATCH04 cto unfilter
.byte 0x6a, filter_cto // MATCH04 cto unfilter
section LXMOVEUP
push offset filter_length // MATCH05 uncompressed length
call move_up // MATCH06
; =============
; ============= DECOMPRESSION
; =============
// =============
// ============= DECOMPRESSION
// =============
%include "arch/i386/nrv2b_d32.ash"
%include "arch/i386/nrv2d_d32.ash"
%include "arch/i386/nrv2e_d32.ash"
%include "arch/i386/lzma_d.ash"
//#include "arch/i386/nrv2b_d32.ash"
//#include "arch/i386/nrv2d_d32.ash"
//#include "arch/i386/nrv2e_d32.ash"
#include "arch/i386/nrv2e_d32_2.ash"
//#include "arch/i386/lzma_d.ash"
; =============
; ============= UNFILTER
; =============
// =============
// ============= UNFILTER
// =============
%ifdef __LXCKLLT9__
pop ecx ; MATCH05 len
pop edx ; MATCH04 cto
pop edi ; MATCH03 src
section LXCKLLT9
pop ecx // MATCH05 len
pop edx // MATCH04 cto
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,
;and actual origin of destination at unfilter.
;Filter.addvalue is 0: destination origin is unknown at filter time.
;The input data is still relocatable, and address is assigned later
;[as of 2004-12-15 it is 'always' 0x100000].
*/
%endif; __LXDUMMY2__
%ifdef __LXCALLT9__
pop ecx ; MATCH05 len
pop edi ; MATCH03 src
section LXCALLT9
pop ecx // MATCH05 len
pop edi // MATCH03 src
cjt32 0
%endif; __LINUX990__
pop esi ; MATCH02 restore
pop edi ; MATCH01 restore
xor ebx, ebx ; booting the 1st cpu
retf ; MATCH00 set cs
section LINUX990
pop esi // MATCH02 restore
pop edi // MATCH01 restore
xor ebx, ebx // booting the 1st cpu
lret // MATCH00 set cs
%define UNLAP 0x10
%define ALIGN (~0<<4)
; must have 0==(UNLAP &~ ALIGN)
#define UNLAP 0x10
#define ALIGN (~0<<4)
// must have 0==(UNLAP &~ ALIGN)
move_up:
pop esi ; MATCH06 &decompressor
mov ecx,[-4+ esi] ; length of decompressor+unfilter
mov ebp,eax ; &uncompressed
add eax,[esp] ; MATCH05 ULEN + base; entry to decompressor
add eax, byte ~ALIGN + UNLAP
and eax, byte ALIGN
pop esi // MATCH06 &decompressor
mov ecx,[-4+ esi] // length of decompressor+unfilter
mov ebp,eax // &uncompressed
add eax,[esp] // MATCH05 ULEN + base; entry to decompressor
add eax, ~ALIGN + UNLAP
and eax, ALIGN
std
; copy decompressor
lea esi,[-1+ ecx + esi] ; unmoved top -1 of decompressor
lea edi,[-1+ ecx + eax] ; moved top -1 of decompressor
// copy decompressor
lea esi,[-1+ ecx + esi] // unmoved top -1 of decompressor
lea edi,[-1+ ecx + eax] // moved top -1 of decompressor
rep
movsb
mov ecx,[-4+ edx] ; length of compressed data
add ecx, byte 3
shr ecx,2 ; count of .long
; copy compressed data
lea esi,[-4+ 4*ecx + edx] ; unmoved top -4 of compressed data
lea edi,[-4+ eax] ; moved top -4 of compressed data
mov ecx,[-4+ edx] // length of compressed data
add ecx, 3
shr ecx,2 // count of .long
// copy compressed data
lea esi,[-4+ 4*ecx + edx] // unmoved top -4 of compressed data
lea edi,[-4+ eax] // moved top -4 of compressed data
rep
movsd
cld
lea esi,[4+ edi] ; &compressed [after move]
mov edi,ebp ; &uncompressed
or ebp, byte -1 ; decompressor assumption
jmp eax ; enter moved decompressor
lea esi,[4+ edi] // &compressed [after move]
mov edi,ebp // &uncompressed
or ebp, -1 // decompressor assumption
jmp eax // enter moved decompressor
; =============
; ============= CUT HERE
; =============
#include "include/header2.ash"
%include "include/header.ash"
eof:
; __LITHEEND__
section .data
dd -1
dw eof
; vi:ts=8:et:nowrap
// vi:ts=8:et:nowrap

View File

@ -1,3 +1,4 @@
/*
; l_vmlinz.asm -- loader & decompressor for the vmlinuz/i386 format
;
; This file is part of the UPX executable compressor.
@ -24,32 +25,29 @@
; Markus F.X.J. Oberhumer Laszlo Molnar
; <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
;
*/
%define jmps jmp short
%define jmpn jmp near
%include "arch/i386/macros.ash"
#include "arch/i386/macros2.ash"
BITS 32
SECTION .text
ORG 0
// =============
// ============= ENTRY POINT
// =============
; =============
; ============= ENTRY POINT
; =============
start:
; __LINUZ000__
;cli ;this must be true already
section LINUZ000
//cli // this must be true already
/*
; 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;
; the next segment after %cs is a valid "flat" data segment, but
; no segment register designates it yet.
*/
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 es, eax
/*
; fs, gs set by startup_32 in arch/i386/kernel/head.S
; 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.
; 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
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
push 0
popf // BIOS can leave random flags (such as NT)
push byte 0
popf ; BIOS can leave random flags (such as NT)
// do not clear .bss: at this point, .bss comes only from
// arch/i386/boot/compressed/*.o which we are replacing entirely
; do not clear .bss: at this point, .bss comes only from
; arch/i386/boot/compressed/*.o which we are replacing entirely
or ebp, -1 // decompressor assumption
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
mov eax, 'KEIP' ; 0x100000 : address of startup_32
push cs ; MATCH00
push eax ; MATCH00 entry address
push edi ; MATCH01 save
push esi ; MATCH02 save
%ifdef __LZCALLT1__
push eax ; MATCH03 src unfilter
%endif; __LZDUMMY0__
%ifdef __LZCKLLT1__
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'
section LZCALLT1
push eax // MATCH03 src unfilter
section LZCKLLT1
push eax // MATCH03 src unfilter
//push offset filter_cto // MATCH04 cto unfilter
.byte 0x6a, filter_cto // MATCH04 cto unfilter
push offset filter_length // MATCH05 len unfilter
section LBZIMAGE
mov esi, offset copy_source
mov edi, offset copy_dest
mov ecx, offset words_to_copy
std
rep
movsd
cld
mov esi, 'ESI1' ; esi = src for decompressor
xchg eax, edi ; edi = dst for decompressor = 0x100000
jmp .1 + 'JMPD' ; jump to the copied decompressor
.1:
%else; __LZIMAGE0__
mov esi, offset src_for_decompressor
xchg eax, edi // edi = dst for decompressor = 0x100000
jmp decompressor // jump to the copied decompressor
; this checka20 stuff looks very unneccessary to me
section LZIMAGE0
// this checka20 stuff looks very unneccessary to me
checka20:
inc edi ; change value
mov [1 + ebp], edi ; store to 0x000000 (even megabyte)
cmp [eax], edi ; compare 0x100000 ( odd megabyte)
je checka20 ; addresses are [still] aliased
inc edi // change value
mov [1 + ebp], edi // store to 0x000000 (even megabyte)
cmp [eax], edi // compare 0x100000 ( odd megabyte)
je checka20 // addresses are [still] aliased
cld
mov esi, 'ESI1'
xchg eax, edi ; edi = dst for decompressor = 0x100000
mov esi, offset src_for_decompressor
xchg eax, edi // edi = dst for decompressor = 0x100000
%endif; __LZCUTPOI__
section LZCUTPOI
; =============
; ============= DECOMPRESSION
; =============
// =============
// ============= DECOMPRESSION
// =============
%include "arch/i386/nrv2b_d32.ash"
%include "arch/i386/nrv2d_d32.ash"
%include "arch/i386/nrv2e_d32.ash"
%include "arch/i386/lzma_d.ash"
//#include "arch/i386/nrv2b_d32.ash"
//#include "arch/i386/nrv2d_d32.ash"
//#include "arch/i386/nrv2e_d32.ash"
#include "arch/i386/nrv2e_d32_2.ash"
//#include "arch/i386/lzma_d.ash"
; =============
; ============= UNFILTER
; =============
// =============
// ============= UNFILTER
// =============
%ifdef __LZCKLLT9__
pop ecx ; MATCH05 len
pop edx ; MATCH04 cto
pop edi ; MATCH03 src
section LZCKLLT9
pop ecx // MATCH05 len
pop edx // MATCH04 cto
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
;[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.
;If .addvalue was 0, then use 'edi' instead of 0 in call to ckt32,
;to compensate for difference in origin of buffer.
*/
%endif; __LZDUMMY2__
%ifdef __LZCALLT9__
pop edi ; MATCH03 src
section LZCALLT9
pop edi // MATCH03 src
cjt32 0
%endif; __LINUZ990__
pop esi ; MATCH02 restore
pop edi ; MATCH01 restore
xor ebx, ebx ; booting the 1st cpu
retf ; MATCH00 set cs
; =============
; ============= CUT HERE
; =============
section LINUZ990
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:
; __LITHEEND__
section .data
dd -1
dw eof
; vi:ts=8:et:nowrap
// vi:ts=8:et:nowrap