mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
Fix Elf_auxv table. upx was duplicating AT_PHDR (and others)
because Linux 2.4.5 supplies many more AT_ entries than before. First noticed by Sebastian <scut@nb.in-berlin.de>. fold_elf86.asm fold_sh86.asm l_lx_sep86.asm l_lx_elf.c l_lx_sh.c l_lx_sep.c committer: jreiser <jreiser> 994871296 +0000
This commit is contained in:
parent
caca5ffa12
commit
ef17dc10ca
|
@ -24,6 +24,7 @@
|
||||||
; markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
; markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||||
;
|
;
|
||||||
|
|
||||||
|
%define PAGE_SIZE ( 1<<12)
|
||||||
%define szElf32_Ehdr 0x34
|
%define szElf32_Ehdr 0x34
|
||||||
%define szElf32_Phdr 8*4
|
%define szElf32_Phdr 8*4
|
||||||
%define e_entry (16 + 2*2 + 4)
|
%define e_entry (16 + 2*2 + 4)
|
||||||
|
@ -31,7 +32,9 @@
|
||||||
%define szb_info 12
|
%define szb_info 12
|
||||||
%define szl_info 12
|
%define szl_info 12
|
||||||
%define szp_info 12
|
%define szp_info 12
|
||||||
|
%define a_type 0
|
||||||
%define a_val 4
|
%define a_val 4
|
||||||
|
%define sz_auxv 8
|
||||||
|
|
||||||
%define __NR_munmap 91
|
%define __NR_munmap 91
|
||||||
|
|
||||||
|
@ -46,17 +49,59 @@ fold_begin: ; enter: %ebx= &Elf32_Ehdr of this program
|
||||||
pop eax ; discard &sz_uncompressed
|
pop eax ; discard &sz_uncompressed
|
||||||
pop eax ; discard sz_uncompressed
|
pop eax ; discard sz_uncompressed
|
||||||
|
|
||||||
; Move argc,argv,envp down so that we can insert more Elf_auxv entries.
|
; Move argc,argv,envp down to make room for complete Elf_auxv table.
|
||||||
|
; Linux kernel 2.4.2 and earlier give only AT_HWCAP and AT_PLATFORM
|
||||||
|
; because we have no PT_INTERP. Linux kernel 2.4.5 (and later?)
|
||||||
|
; give not quite everything. It is simpler and smaller code for us
|
||||||
|
; to generate a "complete" table where Elf_auxv[k -1].a_type = k.
|
||||||
; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance
|
; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance
|
||||||
|
|
||||||
%define PAGE_SIZE ( 1<<12)
|
%define AT_NULL 0
|
||||||
%define OVERHEAD 2048
|
%define AT_IGNORE 1
|
||||||
%define MAX_ELF_HDR 512
|
%define AT_PHDR 3
|
||||||
|
%define AT_NUMBER 20
|
||||||
|
|
||||||
mov esi, esp
|
mov esi, esp
|
||||||
sub esp, byte 6*8 ; AT_PHENT, AT_PHNUM, AT_PAGESZ, AT_ENTRY, AT_PHDR, AT_NULL
|
sub esp, sz_auxv * AT_NUMBER ; more than 128 bytes
|
||||||
mov edi, esp
|
mov edi, esp
|
||||||
call do_auxv
|
do_auxv: ; entry: %esi=src = &argc; %edi=dst. exit: %edi= &AT_NULL
|
||||||
|
; cld
|
||||||
|
|
||||||
|
L10: ; move argc+argv
|
||||||
|
lodsd
|
||||||
|
stosd
|
||||||
|
test eax,eax
|
||||||
|
jne L10
|
||||||
|
|
||||||
|
L20: ; move envp
|
||||||
|
lodsd
|
||||||
|
stosd
|
||||||
|
test eax,eax
|
||||||
|
jne L20
|
||||||
|
|
||||||
|
; complete Elf_auxv table full of AT_IGNORE
|
||||||
|
push edi ; save base of resulting table
|
||||||
|
inc eax ; convert 0 to AT_IGNORE
|
||||||
|
mov ecx, 2 * (AT_NUMBER -1)
|
||||||
|
rep stosd
|
||||||
|
dec eax ; convert AT_IGNORE into AT_NULL
|
||||||
|
stosd ; terminate Elf_auxv
|
||||||
|
stosd
|
||||||
|
pop edi ; base of resulting table
|
||||||
|
|
||||||
|
L30: ; distribute existing Elf32_auxv into new table
|
||||||
|
lodsd
|
||||||
|
test eax,eax ; AT_NULL ?
|
||||||
|
xchg eax,edx
|
||||||
|
lodsd
|
||||||
|
je L40
|
||||||
|
mov [a_type + sz_auxv*(edx -1) + edi], edx
|
||||||
|
mov [a_val + sz_auxv*(edx -1) + edi], eax
|
||||||
|
jmp L30
|
||||||
|
L40:
|
||||||
|
|
||||||
|
%define OVERHEAD 2048
|
||||||
|
%define MAX_ELF_HDR 512
|
||||||
|
|
||||||
push ebx ; save &Elf32_Ehdr of this stub
|
push ebx ; save &Elf32_Ehdr of this stub
|
||||||
sub esp, dword MAX_ELF_HDR + OVERHEAD
|
sub esp, dword MAX_ELF_HDR + OVERHEAD
|
||||||
|
@ -67,14 +112,14 @@ fold_begin: ; enter: %ebx= &Elf32_Ehdr of this program
|
||||||
mov edx, esp ;
|
mov edx, esp ;
|
||||||
mov ecx, [4+ eax] ; length of compressed ELF headers
|
mov ecx, [4+ eax] ; length of compressed ELF headers
|
||||||
add ecx, byte szb_info
|
add ecx, byte szb_info
|
||||||
pusha ; (AT_next, sz_cpr, f_expand, &tmp_ehdr, {sz_unc, &tmp}, {sz_cpr, &b1st_info} )
|
pusha ; (AT_table, sz_cpr, f_expand, &tmp_ehdr, {sz_unc, &tmp}, {sz_cpr, &b1st_info} )
|
||||||
EXTERN upx_main
|
EXTERN upx_main
|
||||||
call upx_main ; returns entry address
|
call upx_main ; returns entry address
|
||||||
add esp, dword 8*4 + MAX_ELF_HDR + OVERHEAD ; remove 8 params, temp space
|
add esp, dword 8*4 + MAX_ELF_HDR + OVERHEAD ; remove 8 params, temp space
|
||||||
pop ebx ; &Elf32_Ehdr of this stub
|
pop ebx ; &Elf32_Ehdr of this stub
|
||||||
push eax ; save entry address
|
push eax ; save entry address
|
||||||
|
|
||||||
mov edi, [a_val + edi] ; AT_PHDR
|
mov edi, [a_val + sz_auxv * (AT_PHDR -1) + edi]
|
||||||
find_hatch:
|
find_hatch:
|
||||||
push edi
|
push edi
|
||||||
EXTERN make_hatch
|
EXTERN make_hatch
|
||||||
|
@ -104,31 +149,5 @@ EXTERN make_hatch
|
||||||
mov eax, __NR_munmap ; do not dirty the stack with push byte + pop
|
mov eax, __NR_munmap ; do not dirty the stack with push byte + pop
|
||||||
jmp edx ; unmap ourselves via escape hatch, then goto entry
|
jmp edx ; unmap ourselves via escape hatch, then goto entry
|
||||||
|
|
||||||
do_auxv: ; entry: %esi=src = &argc; %edi=dst. exit: %edi= &AT_NULL
|
|
||||||
; cld
|
|
||||||
|
|
||||||
L10: ; move argc+argv
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
test eax,eax
|
|
||||||
jne L10
|
|
||||||
|
|
||||||
L20: ; move envp
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
test eax,eax
|
|
||||||
jne L20
|
|
||||||
|
|
||||||
L30: ; move existing Elf32_auxv
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
test eax,eax ; AT_NULL ?
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
jne L30
|
|
||||||
|
|
||||||
sub edi, byte 8 ; point to AT_NULL
|
|
||||||
ret
|
|
||||||
|
|
||||||
; vi:ts=8:et:nowrap
|
; vi:ts=8:et:nowrap
|
||||||
|
|
||||||
|
|
|
@ -30,29 +30,75 @@
|
||||||
BITS 32
|
BITS 32
|
||||||
SECTION .text
|
SECTION .text
|
||||||
|
|
||||||
|
%define PAGE_SIZE ( 1<<12)
|
||||||
%define szElf32_Ehdr 0x34
|
%define szElf32_Ehdr 0x34
|
||||||
%define szElf32_Phdr 8*4
|
%define szElf32_Phdr 8*4
|
||||||
%define e_entry (16 + 2*2 + 4)
|
%define e_entry (16 + 2*2 + 4)
|
||||||
%define p_memsz 5*4
|
%define p_memsz 5*4
|
||||||
%define szl_info 12
|
%define szl_info 12
|
||||||
%define szp_info 12
|
%define szp_info 12
|
||||||
|
%define a_type 0
|
||||||
|
%define a_val 4
|
||||||
|
%define sz_auxv 8
|
||||||
|
|
||||||
fold_begin: ; enter: %ebx= uncDst
|
fold_begin: ; enter: %ebx= uncDst
|
||||||
; also edx= szElf32_Ehdr + 2*szElf32_Phdr + &Elf32_Ehdr
|
; also edx= szElf32_Ehdr + 2*szElf32_Phdr + &Elf32_Ehdr
|
||||||
pop eax ; discard &sz_uncompressed
|
pop eax ; discard &sz_uncompressed
|
||||||
pop eax ; discard sz_uncompressed
|
pop eax ; discard sz_uncompressed
|
||||||
|
|
||||||
; Move argc,argv,envp down so that we can insert more Elf_auxv entries.
|
; Move argc,argv,envp down to make room for complete Elf_auxv table.
|
||||||
|
; Linux kernel 2.4.2 and earlier give only AT_HWCAP and AT_PLATFORM
|
||||||
|
; because we have no PT_INTERP. Linux kernel 2.4.5 (and later?)
|
||||||
|
; give not quite everything. It is simpler and smaller code for us
|
||||||
|
; to generate a "complete" table where Elf_auxv[k -1].a_type = k.
|
||||||
; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance
|
; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance
|
||||||
|
|
||||||
|
%define AT_NULL 0
|
||||||
|
%define AT_IGNORE 1
|
||||||
|
%define AT_PHDR 3
|
||||||
|
%define AT_NUMBER 20
|
||||||
|
|
||||||
|
mov esi, esp
|
||||||
|
sub esp, sz_auxv * AT_NUMBER ; more than 128 bytes
|
||||||
|
mov edi, esp
|
||||||
|
do_auxv: ; entry: %esi=src = &argc; %edi=dst. exit: %edi= &AT_NULL
|
||||||
|
; cld
|
||||||
|
|
||||||
|
L10: ; move argc+argv
|
||||||
|
lodsd
|
||||||
|
stosd
|
||||||
|
test eax,eax
|
||||||
|
jne L10
|
||||||
|
|
||||||
|
L20: ; move envp
|
||||||
|
lodsd
|
||||||
|
stosd
|
||||||
|
test eax,eax
|
||||||
|
jne L20
|
||||||
|
|
||||||
|
; complete Elf_auxv table full of AT_IGNORE
|
||||||
|
push edi ; save base of resulting table
|
||||||
|
inc eax ; convert 0 to AT_IGNORE
|
||||||
|
mov ecx, 2 * (AT_NUMBER -1)
|
||||||
|
rep stosd
|
||||||
|
dec eax ; convert AT_IGNORE into AT_NULL
|
||||||
|
stosd ; terminate Elf_auxv
|
||||||
|
stosd
|
||||||
|
pop edi ; base of resulting table
|
||||||
|
|
||||||
|
L30: ; distribute existing Elf32_auxv into new table
|
||||||
|
lodsd
|
||||||
|
test eax,eax ; AT_NULL ?
|
||||||
|
xchg eax,edx
|
||||||
|
lodsd
|
||||||
|
je L40
|
||||||
|
mov [a_type + sz_auxv*(edx -1) + edi], edx
|
||||||
|
mov [a_val + sz_auxv*(edx -1) + edi], eax
|
||||||
|
jmp L30
|
||||||
|
L40:
|
||||||
|
|
||||||
%define OVERHEAD 2048
|
%define OVERHEAD 2048
|
||||||
%define MAX_ELF_HDR 512
|
%define MAX_ELF_HDR 512
|
||||||
%define PAGE_SIZE ( 1<<12)
|
|
||||||
|
|
||||||
mov esi, esp
|
|
||||||
sub esp, byte 6*8 ; AT_PHENT, AT_PHNUM, AT_PAGESZ, AT_ENTRY, AT_PHDR, AT_NULL
|
|
||||||
mov edi, esp
|
|
||||||
call do_auxv ; edi= &AT_NEXT
|
|
||||||
|
|
||||||
sub esp, dword MAX_ELF_HDR + OVERHEAD
|
sub esp, dword MAX_ELF_HDR + OVERHEAD
|
||||||
|
|
||||||
|
@ -61,7 +107,7 @@ fold_begin: ; enter: %ebx= uncDst
|
||||||
mov ecx, [ edx] ; sz_unc
|
mov ecx, [ edx] ; sz_unc
|
||||||
mov ebx, [4+ edx] ; sz_cpr
|
mov ebx, [4+ edx] ; sz_cpr
|
||||||
mov esi, eax ; extra copy of uncDst
|
mov esi, eax ; extra copy of uncDst
|
||||||
pusha ; (&AT_NEXT,uncDst,f_decpr,&ehdr,{sz_cpr,cprSrc},{sz_unc,uncDst})
|
pusha ; (AT_table,uncDst,f_decpr,&ehdr,{sz_cpr,cprSrc},{sz_unc,uncDst})
|
||||||
EXTERN upx_main
|
EXTERN upx_main
|
||||||
call upx_main ; entry = upx_main(...)
|
call upx_main ; entry = upx_main(...)
|
||||||
pop ecx ; junk
|
pop ecx ; junk
|
||||||
|
@ -108,32 +154,6 @@ EXTERN upx_main
|
||||||
popa
|
popa
|
||||||
ret
|
ret
|
||||||
|
|
||||||
do_auxv: ; entry: %esi=src = &argc; %edi=dst. exit: %edi= &AT_NULL
|
|
||||||
; cld
|
|
||||||
|
|
||||||
L10: ; move argc+argv
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
test eax,eax
|
|
||||||
jne L10
|
|
||||||
|
|
||||||
L20: ; move envp
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
test eax,eax
|
|
||||||
jne L20
|
|
||||||
|
|
||||||
L30: ; move existing Elf32_auxv
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
test eax,eax ; AT_NULL ?
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
jne L30
|
|
||||||
|
|
||||||
sub edi, byte 8 ; point to AT_NULL
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
; vi:ts=8:et:nowrap
|
; vi:ts=8:et:nowrap
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@ bzero(char *p, size_t len)
|
||||||
|
|
||||||
static Elf32_Addr // entry address
|
static Elf32_Addr // entry address
|
||||||
do_xmap(int const fdi, Elf32_Ehdr const *const ehdr, struct Extent *const xi,
|
do_xmap(int const fdi, Elf32_Ehdr const *const ehdr, struct Extent *const xi,
|
||||||
Elf32_auxv_t *const a)
|
Elf32_auxv_t *const av)
|
||||||
{
|
{
|
||||||
Elf32_Phdr const *phdr = (Elf32_Phdr const *) (ehdr->e_phoff +
|
Elf32_Phdr const *phdr = (Elf32_Phdr const *) (ehdr->e_phoff +
|
||||||
(char const *)ehdr);
|
(char const *)ehdr);
|
||||||
|
@ -222,7 +222,7 @@ do_xmap(int const fdi, Elf32_Ehdr const *const ehdr, struct Extent *const xi,
|
||||||
int j;
|
int j;
|
||||||
for (j=0; j < ehdr->e_phnum; ++phdr, ++j)
|
for (j=0; j < ehdr->e_phnum; ++phdr, ++j)
|
||||||
if (PT_PHDR==phdr->p_type) {
|
if (PT_PHDR==phdr->p_type) {
|
||||||
a->a_un.a_val = phdr->p_vaddr;
|
av[AT_PHDR -1].a_un.a_val = phdr->p_vaddr;
|
||||||
}
|
}
|
||||||
else if (PT_LOAD==phdr->p_type) {
|
else if (PT_LOAD==phdr->p_type) {
|
||||||
struct Extent xo;
|
struct Extent xo;
|
||||||
|
@ -346,14 +346,12 @@ void *upx_main(
|
||||||
xi.buf -= sz_pckhdrs;
|
xi.buf -= sz_pckhdrs;
|
||||||
xi.size = sz_compressed;
|
xi.size = sz_compressed;
|
||||||
|
|
||||||
// av[0].a_un.a_val is set again by do_xmap if PT_PHDR is present.
|
// av[AT_PHDR -1].a_un.a_val is set again by do_xmap if PT_PHDR is present.
|
||||||
// Caller of upx_main assumes that AT_PHDR will be set into av[0] .
|
av[AT_PHDR -1].a_type = AT_PHDR ; av[AT_PHDR -1].a_un.a_ptr = 1+(Elf32_Ehdr *)phdr->p_vaddr;
|
||||||
av[0].a_type = AT_PHDR; av[0].a_un.a_ptr = 1+(Elf32_Ehdr *)phdr->p_vaddr;
|
av[AT_PHENT -1].a_type = AT_PHENT ; av[AT_PHENT -1].a_un.a_val = ehdr->e_phentsize;
|
||||||
av[1].a_type = AT_PHENT; av[1].a_un.a_val = ehdr->e_phentsize;
|
av[AT_PHNUM -1].a_type = AT_PHNUM ; av[AT_PHNUM -1].a_un.a_val = ehdr->e_phnum;
|
||||||
av[2].a_type = AT_PHNUM; av[2].a_un.a_val = ehdr->e_phnum;
|
av[AT_PAGESZ -1].a_type = AT_PAGESZ; av[AT_PAGESZ -1].a_un.a_val = PAGE_SIZE;
|
||||||
av[3].a_type = AT_PAGESZ; av[3].a_un.a_val = PAGE_SIZE;
|
av[AT_ENTRY -1].a_type = AT_ENTRY ; av[AT_ENTRY -1].a_un.a_val = ehdr->e_entry;
|
||||||
av[4].a_type = AT_ENTRY; av[4].a_un.a_val = ehdr->e_entry;
|
|
||||||
av[5].a_type = AT_NULL;
|
|
||||||
entry = do_xmap((int)f_decompress, ehdr, &xi, av);
|
entry = do_xmap((int)f_decompress, ehdr, &xi, av);
|
||||||
|
|
||||||
{ // Map PT_INTERP program interpreter
|
{ // Map PT_INTERP program interpreter
|
||||||
|
|
|
@ -234,7 +234,7 @@ bzero(char *p, size_t len)
|
||||||
|
|
||||||
static Elf32_Addr // entry address
|
static Elf32_Addr // entry address
|
||||||
do_xmap(int fdi, Elf32_Ehdr const *const ehdr, f_expand *const f_decompress,
|
do_xmap(int fdi, Elf32_Ehdr const *const ehdr, f_expand *const f_decompress,
|
||||||
Elf32_auxv_t *const a)
|
Elf32_auxv_t *const av)
|
||||||
{
|
{
|
||||||
struct Extent x;
|
struct Extent x;
|
||||||
Elf32_Phdr const *phdr = (Elf32_Phdr const *) (ehdr->e_phoff +
|
Elf32_Phdr const *phdr = (Elf32_Phdr const *) (ehdr->e_phoff +
|
||||||
|
@ -243,7 +243,7 @@ do_xmap(int fdi, Elf32_Ehdr const *const ehdr, f_expand *const f_decompress,
|
||||||
int j;
|
int j;
|
||||||
for (j=0; j < ehdr->e_phnum; ++phdr, ++j)
|
for (j=0; j < ehdr->e_phnum; ++phdr, ++j)
|
||||||
if (PT_PHDR==phdr->p_type) {
|
if (PT_PHDR==phdr->p_type) {
|
||||||
a->a_un.a_val = phdr->p_vaddr;
|
av[AT_PHDR -1].a_un.a_val = phdr->p_vaddr;
|
||||||
}
|
}
|
||||||
else if (PT_LOAD==phdr->p_type) {
|
else if (PT_LOAD==phdr->p_type) {
|
||||||
size_t mlen = x.size = phdr->p_filesz;
|
size_t mlen = x.size = phdr->p_filesz;
|
||||||
|
@ -390,13 +390,12 @@ ERR_LAB
|
||||||
if (lseek(fdi, -(sizeof(xo) + sz_pckhdrs), SEEK_CUR) < 0) {
|
if (lseek(fdi, -(sizeof(xo) + sz_pckhdrs), SEEK_CUR) < 0) {
|
||||||
err_exit(17);
|
err_exit(17);
|
||||||
}
|
}
|
||||||
// av[0].a_un.a_val is set again by do_xmap if PT_PHDR is present
|
// av[AT_PHDR -1].a_un.a_val is set again by do_xmap if PT_PHDR is present.
|
||||||
av[0].a_type = AT_PHDR; av[0].a_un.a_ptr = 1+(Elf32_Ehdr *)phdr->p_vaddr;
|
av[AT_PHDR -1].a_type = AT_PHDR ; av[AT_PHDR -1].a_un.a_ptr = 1+(Elf32_Ehdr *)phdr->p_vaddr;
|
||||||
av[1].a_type = AT_PHENT; av[1].a_un.a_val = ehdr->e_phentsize;
|
av[AT_PHENT -1].a_type = AT_PHENT ; av[AT_PHENT -1].a_un.a_val = ehdr->e_phentsize;
|
||||||
av[2].a_type = AT_PHNUM; av[2].a_un.a_val = ehdr->e_phnum;
|
av[AT_PHNUM -1].a_type = AT_PHNUM ; av[AT_PHNUM -1].a_un.a_val = ehdr->e_phnum;
|
||||||
av[3].a_type = AT_PAGESZ; av[3].a_un.a_val = PAGE_SIZE;
|
av[AT_PAGESZ -1].a_type = AT_PAGESZ; av[AT_PAGESZ -1].a_un.a_val = PAGE_SIZE;
|
||||||
av[4].a_type = AT_ENTRY; av[4].a_un.a_val = ehdr->e_entry;
|
av[AT_ENTRY -1].a_type = AT_ENTRY ; av[AT_ENTRY -1].a_un.a_val = ehdr->e_entry;
|
||||||
av[5].a_type = AT_NULL;
|
|
||||||
entry = do_xmap(fdi, ehdr, f_decompress, av);
|
entry = do_xmap(fdi, ehdr, f_decompress, av);
|
||||||
|
|
||||||
// Map PT_INTERP program interpreter
|
// Map PT_INTERP program interpreter
|
||||||
|
|
|
@ -132,6 +132,9 @@ decompress:
|
||||||
|
|
||||||
%define PAGE_MASK (~0<<12)
|
%define PAGE_MASK (~0<<12)
|
||||||
%define PAGE_SIZE ( 1<<12)
|
%define PAGE_SIZE ( 1<<12)
|
||||||
|
%define a_type 0
|
||||||
|
%define a_val 4
|
||||||
|
%define sz_auxv 8
|
||||||
|
|
||||||
%define szElf32_Phdr 8*4
|
%define szElf32_Phdr 8*4
|
||||||
%define a_val 4
|
%define a_val 4
|
||||||
|
@ -141,26 +144,69 @@ main:
|
||||||
pop ebp ; &decompress
|
pop ebp ; &decompress
|
||||||
cld
|
cld
|
||||||
|
|
||||||
; Move argc,argv,envp down so that we can insert more Elf_auxv entries.
|
; Move argc,argv,envp down to make room for complete Elf_auxv table.
|
||||||
|
; Linux kernel 2.4.2 and earlier give only AT_HWCAP and AT_PLATFORM
|
||||||
|
; because we have no PT_INTERP. Linux kernel 2.4.5 (and later?)
|
||||||
|
; give not quite everything. It is simpler and smaller code for us
|
||||||
|
; to generate a "complete" table where Elf_auxv[k -1].a_type = k.
|
||||||
; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance
|
; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance
|
||||||
|
|
||||||
|
%define AT_NULL 0
|
||||||
|
%define AT_IGNORE 1
|
||||||
|
%define AT_PHDR 3
|
||||||
|
%define AT_NUMBER 20
|
||||||
|
|
||||||
|
mov esi, esp
|
||||||
|
sub esp, sz_auxv * AT_NUMBER ; more than 128 bytes
|
||||||
|
mov edi, esp
|
||||||
|
do_auxv: ; entry: %esi=src = &argc; %edi=dst. exit: %edi= &AT_NULL
|
||||||
|
; cld
|
||||||
|
|
||||||
|
L10: ; move argc+argv
|
||||||
|
lodsd
|
||||||
|
stosd
|
||||||
|
test eax,eax
|
||||||
|
jne L10
|
||||||
|
|
||||||
|
L20: ; move envp
|
||||||
|
lodsd
|
||||||
|
stosd
|
||||||
|
test eax,eax
|
||||||
|
jne L20
|
||||||
|
|
||||||
|
; complete Elf_auxv table full of AT_IGNORE
|
||||||
|
push edi ; save base of resulting table
|
||||||
|
inc eax ; convert 0 to AT_IGNORE
|
||||||
|
mov ecx, 2 * (AT_NUMBER -1)
|
||||||
|
rep stosd
|
||||||
|
dec eax ; convert AT_IGNORE into AT_NULL
|
||||||
|
stosd ; terminate Elf_auxv
|
||||||
|
stosd
|
||||||
|
pop edi ; base of resulting table
|
||||||
|
|
||||||
|
L30: ; distribute existing Elf32_auxv into new table
|
||||||
|
lodsd
|
||||||
|
test eax,eax ; AT_NULL ?
|
||||||
|
xchg eax,edx
|
||||||
|
lodsd
|
||||||
|
je L40
|
||||||
|
mov [a_type + sz_auxv*(edx -1) + edi], edx
|
||||||
|
mov [a_val + sz_auxv*(edx -1) + edi], eax
|
||||||
|
jmp L30
|
||||||
|
L40:
|
||||||
|
|
||||||
%define OVERHEAD 2048
|
%define OVERHEAD 2048
|
||||||
%define MAX_ELF_HDR 512
|
%define MAX_ELF_HDR 512
|
||||||
|
|
||||||
mov esi, esp
|
|
||||||
sub esp, byte 6*8 ; AT_PHENT, AT_PHNUM, AT_PAGESZ, AT_ENTRY, AT_PHDR, AT_NULL
|
|
||||||
mov edi, esp
|
|
||||||
call do_auxv ; edi= &AT_next
|
|
||||||
|
|
||||||
lea ecx, [4+esp] ; argv
|
lea ecx, [4+esp] ; argv
|
||||||
sub esp, dword MAX_ELF_HDR + OVERHEAD
|
sub esp, dword MAX_ELF_HDR + OVERHEAD
|
||||||
|
|
||||||
push esp ; argument: temp space
|
push esp ; argument: temp space
|
||||||
push edi ; argument: AT_next
|
push edi ; argument: AT_table
|
||||||
push ebp ; argument: &decompress
|
push ebp ; argument: &decompress
|
||||||
push ecx ; argument: argv
|
push ecx ; argument: argv
|
||||||
EXTERN upx_main
|
EXTERN upx_main
|
||||||
call upx_main ; entry = upx_main(argv, &decompress, AT_next, tmp_ehdr)
|
call upx_main ; entry = upx_main(argv, &decompress, AT_table, tmp_ehdr)
|
||||||
add esp, dword 4*4 + MAX_ELF_HDR + OVERHEAD ; remove temp space, args
|
add esp, dword 4*4 + MAX_ELF_HDR + OVERHEAD ; remove temp space, args
|
||||||
|
|
||||||
pop ecx ; argc
|
pop ecx ; argc
|
||||||
|
@ -169,7 +215,7 @@ EXTERN upx_main
|
||||||
push ecx
|
push ecx
|
||||||
push eax ; save entry address
|
push eax ; save entry address
|
||||||
|
|
||||||
mov edi, [a_val + edi] ; AT_PHDR
|
mov edi, [a_val + sz_auxv * (AT_PHDR -1) + edi]
|
||||||
find_hatch:
|
find_hatch:
|
||||||
push edi
|
push edi
|
||||||
EXTERN make_hatch
|
EXTERN make_hatch
|
||||||
|
@ -199,31 +245,6 @@ EXTERN make_hatch
|
||||||
mov eax, __NR_munmap ; do not dirty the stack with push byte + pop
|
mov eax, __NR_munmap ; do not dirty the stack with push byte + pop
|
||||||
jmp edx ; unmap ourselves, then goto entry
|
jmp edx ; unmap ourselves, then goto entry
|
||||||
|
|
||||||
do_auxv: ; entry: %esi=src = &argc; %edi=dst. exit: %edi= &AT_NULL
|
|
||||||
; cld
|
|
||||||
|
|
||||||
L10: ; move argc+argv
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
test eax,eax
|
|
||||||
jne L10
|
|
||||||
|
|
||||||
L20: ; move envp
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
test eax,eax
|
|
||||||
jne L20
|
|
||||||
|
|
||||||
L30: ; move existing Elf32_auxv
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
test eax,eax ; AT_NULL ?
|
|
||||||
lodsd
|
|
||||||
stosd
|
|
||||||
jne L30
|
|
||||||
|
|
||||||
sub edi, byte 8 ; point to AT_NULL
|
|
||||||
ret
|
|
||||||
|
|
||||||
; vi:ts=8:et:nowrap
|
; vi:ts=8:et:nowrap
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,7 @@ bzero(char *p, size_t len)
|
||||||
// Notice there is no make_hatch(), either.
|
// Notice there is no make_hatch(), either.
|
||||||
|
|
||||||
static Elf32_Addr // entry address
|
static Elf32_Addr // entry address
|
||||||
do_xmap(int const fdi, Elf32_Ehdr const *const ehdr, Elf32_auxv_t *const a)
|
do_xmap(int const fdi, Elf32_Ehdr const *const ehdr, Elf32_auxv_t *const av)
|
||||||
{
|
{
|
||||||
Elf32_Phdr const *phdr = (Elf32_Phdr const *) (ehdr->e_phoff +
|
Elf32_Phdr const *phdr = (Elf32_Phdr const *) (ehdr->e_phoff +
|
||||||
(char const *)ehdr);
|
(char const *)ehdr);
|
||||||
|
@ -180,7 +180,7 @@ do_xmap(int const fdi, Elf32_Ehdr const *const ehdr, Elf32_auxv_t *const a)
|
||||||
int j;
|
int j;
|
||||||
for (j=0; j < ehdr->e_phnum; ++phdr, ++j)
|
for (j=0; j < ehdr->e_phnum; ++phdr, ++j)
|
||||||
if (PT_PHDR==phdr->p_type) {
|
if (PT_PHDR==phdr->p_type) {
|
||||||
a->a_un.a_val = phdr->p_vaddr;
|
av[AT_PHDR -1].a_un.a_val = phdr->p_vaddr;
|
||||||
}
|
}
|
||||||
else if (PT_LOAD==phdr->p_type) {
|
else if (PT_LOAD==phdr->p_type) {
|
||||||
struct Extent xo;
|
struct Extent xo;
|
||||||
|
@ -301,12 +301,12 @@ void *upx_main(
|
||||||
entry = getexec(fn, ehdr, av);
|
entry = getexec(fn, ehdr, av);
|
||||||
*efn = c; // replace terminator character
|
*efn = c; // replace terminator character
|
||||||
|
|
||||||
av[0].a_type = AT_PHDR; // av[0].a_un.a_val is set by do_xmap
|
// av[AT_PHDR -1].a_un.a_val is set again by do_xmap if PT_PHDR is present.
|
||||||
av[1].a_type = AT_PHENT; av[1].a_un.a_val = ehdr->e_phentsize;
|
av[AT_PHDR -1].a_type = AT_PHDR ; // av[AT_PHDR-1].a_un.a_val is set by do_xmap
|
||||||
av[2].a_type = AT_PHNUM; av[2].a_un.a_val = ehdr->e_phnum;
|
av[AT_PHENT -1].a_type = AT_PHENT ; av[AT_PHENT -1].a_un.a_val = ehdr->e_phentsize;
|
||||||
av[3].a_type = AT_PAGESZ; av[3].a_un.a_val = PAGE_SIZE;
|
av[AT_PHNUM -1].a_type = AT_PHNUM ; av[AT_PHNUM -1].a_un.a_val = ehdr->e_phnum;
|
||||||
av[4].a_type = AT_ENTRY; av[4].a_un.a_val = entry;
|
av[AT_PAGESZ -1].a_type = AT_PAGESZ; av[AT_PAGESZ -1].a_un.a_val = PAGE_SIZE;
|
||||||
av[5].a_type = AT_NULL;
|
av[AT_ENTRY -1].a_type = AT_ENTRY ; av[AT_ENTRY -1].a_un.a_val = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Map PT_INTERP program interpreter
|
{ // Map PT_INTERP program interpreter
|
||||||
|
|
Loading…
Reference in New Issue
Block a user