Fix use of memfd_create for shlib stubs, espcially Android
Also relocation of init_array[0] for Elf32 shlib.
https://github.com/upx/upx/issues/220
https://github.com/upx/upx/issues/609
https://github.com/upx/upx/issues/680
modified: stub/src/amd64-linux.elf-so_main.c
modified: stub/src/i386-linux.elf-so_main.c
modified: p_lx_elf.cpp
modified: stub/src/arm.v4a-linux.elf-so_fold.S
modified: stub/src/arm64-linux.elf-so_entry.S
modified: stub/src/arm64-linux.elf-so_fold.S
modified: stub/src/i386-linux.elf-so_fold.S
modified: stub/amd64-linux.elf-so_fold.h
modified: stub/arm.v4a-linux.elf-so_fold.h
modified: stub/arm.v5a-linux.elf-so_fold.h
modified: stub/arm64-linux.elf-so_entry.h
modified: stub/arm64-linux.elf-so_fold.h
modified: stub/i386-linux.elf-so_fold.h
modified: stub/tmp/amd64-linux.elf-so_fold.bin.dump
This commit is contained in:
parent
efbc93229a
commit
2684e815e0
@ -502,6 +502,7 @@ off_t PackLinuxElf32::pack3(OutputFile *fo, Filter &ft)
|
||||
|
||||
total_out = super::pack3(fo, ft); // loader follows compressed PT_LOADs
|
||||
if (fo && xct_off && Elf32_Dyn::DT_INIT != upx_dt_init) { // patch user_init_rp
|
||||
// init_array[0] must have R_$(ARCH)_RELATIVE relocation.
|
||||
fo->seek((char *)user_init_rp - (char *)&file_image[0], SEEK_SET);
|
||||
Elf32_Rel rel(*(Elf32_Rel const *)user_init_rp);
|
||||
u32_t r_info = get_te32(&((Elf32_Rel const *)user_init_rp)->r_info);
|
||||
@ -512,12 +513,10 @@ off_t PackLinuxElf32::pack3(OutputFile *fo, Filter &ft)
|
||||
: 0;
|
||||
set_te32(&rel.r_info, ELF32_R_INFO(ELF32_R_SYM(r_info), r_type));
|
||||
fo->rewrite(&rel, sizeof(rel));
|
||||
|
||||
fo->seek((char *)user_init_rp - (char *)&file_image[0], SEEK_SET);
|
||||
u32_t disp; set_te32(&disp, sz_pack2); // entry to decompressor
|
||||
fo->rewrite(&disp, sizeof(disp));
|
||||
|
||||
fo->seek(0, SEEK_END);
|
||||
|
||||
// Value of init_array[0] will be changed later.
|
||||
// See write() of 'cpr_entry' below.
|
||||
}
|
||||
// NOTE: PackLinuxElf::pack3 adjusted xct_off for the extra page
|
||||
|
||||
|
||||
2139
src/stub/amd64-linux.elf-so_fold.h
generated
2139
src/stub/amd64-linux.elf-so_fold.h
generated
File diff suppressed because it is too large
Load Diff
3118
src/stub/arm.v4a-linux.elf-so_fold.h
generated
3118
src/stub/arm.v4a-linux.elf-so_fold.h
generated
File diff suppressed because it is too large
Load Diff
3130
src/stub/arm.v5a-linux.elf-so_fold.h
generated
3130
src/stub/arm.v5a-linux.elf-so_fold.h
generated
File diff suppressed because it is too large
Load Diff
6
src/stub/arm64-linux.elf-so_entry.h
generated
6
src/stub/arm64-linux.elf-so_entry.h
generated
@ -32,15 +32,15 @@
|
||||
|
||||
|
||||
#define STUB_ARM64_LINUX_ELF_SO_ENTRY_SIZE 1891
|
||||
#define STUB_ARM64_LINUX_ELF_SO_ENTRY_ADLER32 0x75cc7776
|
||||
#define STUB_ARM64_LINUX_ELF_SO_ENTRY_CRC32 0x9c79c3e7
|
||||
#define STUB_ARM64_LINUX_ELF_SO_ENTRY_ADLER32 0x7bdd7753
|
||||
#define STUB_ARM64_LINUX_ELF_SO_ENTRY_CRC32 0x9ab682dd
|
||||
|
||||
unsigned char stub_arm64_linux_elf_so_entry[1891] = {
|
||||
/* 0x0000 */ 127, 69, 76, 70, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 0x0010 */ 1, 0,183, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 0x0020 */ 0, 0, 0, 0, 0, 0, 0, 0, 48, 3, 0, 0, 0, 0, 0, 0,
|
||||
/* 0x0030 */ 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 64, 0, 7, 0, 4, 0,
|
||||
/* 0x0040 */ 31, 32, 3,213,224, 7,190,169,226,123, 1,169,255, 67, 0,209,
|
||||
/* 0x0040 */ 0, 0, 32,212,224, 7,190,169,226,123, 1,169,255, 67, 0,209,
|
||||
/* 0x0050 */ 0, 0, 0,148,238, 3, 0,145,192, 3, 64,185,192, 5, 0,249,
|
||||
/* 0x0060 */ 224, 99, 32,203, 31,236,124,146,195, 33, 0,145,226, 3, 0,145,
|
||||
/* 0x0070 */ 193, 7, 64,185,192, 51, 0,145, 28, 0, 0,148, 1, 0,128, 82,
|
||||
|
||||
1930
src/stub/arm64-linux.elf-so_fold.h
generated
1930
src/stub/arm64-linux.elf-so_fold.h
generated
File diff suppressed because it is too large
Load Diff
1701
src/stub/i386-linux.elf-so_fold.h
generated
1701
src/stub/i386-linux.elf-so_fold.h
generated
File diff suppressed because it is too large
Load Diff
@ -33,9 +33,11 @@
|
||||
#include "include/linux.h"
|
||||
|
||||
// Pprotect is mprotect, but page-aligned on the lo end (Linux requirement)
|
||||
unsigned Pprotect(void *, size_t, unsigned);
|
||||
void *Pmap(void *, size_t, unsigned, unsigned, int, size_t);
|
||||
int Punmap(void *, size_t);
|
||||
extern unsigned Pprotect(void *, size_t, unsigned);
|
||||
extern void *Pmap(void *, size_t, unsigned, unsigned, int, size_t);
|
||||
extern int Punmap(void *, size_t);
|
||||
extern size_t Pwrite(unsigned, void const *, size_t);
|
||||
extern int ftruncate(int fd, off_t length);
|
||||
|
||||
extern void f_int3(int arg);
|
||||
|
||||
@ -245,29 +247,26 @@ extern int memfd_create(const char *name, unsigned int flags);
|
||||
static char *
|
||||
make_hatch_x86_64(
|
||||
Elf64_Phdr const *const phdr,
|
||||
char *base,
|
||||
char *next_unc,
|
||||
char *mfd_addr,
|
||||
unsigned frag_mask
|
||||
)
|
||||
{
|
||||
char *hatch = 0;
|
||||
DPRINTF("make_hatch %%p %%p %%p %%p %%x\\n", phdr, base, next_unc, mfd_addr, frag_mask);
|
||||
DPRINTF("make_hatch %%p %%p %%x\\n", phdr, next_unc, frag_mask);
|
||||
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
|
||||
next_unc += phdr->p_memsz - phdr->p_filesz; // Skip over local .bss
|
||||
frag_mask &= -(long)next_unc; // bytes left on pge
|
||||
frag_mask &= -(long)next_unc; // bytes left on page
|
||||
if (6 <= frag_mask) {
|
||||
hatch = next_unc;
|
||||
(( long *)hatch)[0] = 0x5e5f050f; // syscall; pop %arg1{%rdi}; pop %arg2{%rsi}
|
||||
((short *)hatch)[2] = 0xc35a; // pop %arg3{%rdx}; ret
|
||||
hatch += phdr->p_vaddr + (base - mfd_addr); // relocate to eventual address
|
||||
}
|
||||
else { // Does not fit at hi end of .text, so must use a new page "permanently"
|
||||
int mfd = memfd_create(addr_string("upx"), 0); // the directory entry
|
||||
write(mfd, addr_string("\x0f\x05\x5f\x5e\x5a\xc3"), 6);
|
||||
mfd_addr = mmap(0, 6, PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
|
||||
ftruncate(mfd, 6);
|
||||
Pwrite(mfd, addr_string("\x0f\x05\x5f\x5e\x5a\xc3"), 6);
|
||||
hatch = Pmap(0, 6, PROT_READ|PROT_EXEC, MAP_SHARED, mfd, 0);
|
||||
close(mfd);
|
||||
hatch = mfd_addr;
|
||||
}
|
||||
}
|
||||
DPRINTF("hatch=%%p\\n", hatch);
|
||||
@ -283,9 +282,7 @@ ORRX(unsigned ra, unsigned rs, unsigned rb) // or ra,rs,rb
|
||||
static char *
|
||||
make_hatch_ppc64(
|
||||
Elf64_Phdr const *const phdr,
|
||||
char *base,
|
||||
char *next_unc,
|
||||
char *mfd_addr,
|
||||
unsigned frag_mask
|
||||
)
|
||||
{
|
||||
@ -296,25 +293,23 @@ make_hatch_ppc64(
|
||||
0x4e800020, // blr
|
||||
};
|
||||
unsigned *hatch = 0;
|
||||
DPRINTF("make_hatch %%p %%p %%p %%p %%x\\n", phdr, base, next_unc, mfd_addr, frag_mask);
|
||||
DPRINTF("make_hatch %%p %%p %%x\\n", phdr, next_unc, frag_mask);
|
||||
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
|
||||
next_unc += phdr->p_memsz - phdr->p_filesz; // Skip over local .bss
|
||||
frag_mask &= -(long)next_unc; // bytes left on pge
|
||||
frag_mask &= -(long)next_unc; // bytes left on page
|
||||
if (4*4 <= frag_mask) {
|
||||
hatch = (unsigned *)(void *)next_unc;
|
||||
hatch = (unsigned *)(void *)(~3ul & (long)(3+ next_unc);
|
||||
hatch[0]= code[0];
|
||||
hatch[1]= code[1];
|
||||
hatch[2]= code[2];
|
||||
hatch[3]= code[3];
|
||||
char *t = (phdr->p_vaddr + base) + ((char *)hatch - mfd_addr);
|
||||
hatch = (unsigned *)(void *)t;
|
||||
}
|
||||
else { // Does not fit at hi end of .text, so must use a new page "permanently"
|
||||
int mfd = memfd_create(addr_string("upx"), 0); // the directory entry
|
||||
write(mfd, code, sizeof(code));
|
||||
mfd_addr = mmap(0, sizeof(code), PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
|
||||
ftruncate(mfd,sizeof(code));
|
||||
Pwrite(mfd, code, sizeof(code));
|
||||
hatch = Pmap(0, sizeof(code), PROT_READ|PROT_EXEC, MAP_SHARED, mfd, 0);
|
||||
close(mfd);
|
||||
hatch = mfd_addr;
|
||||
}
|
||||
}
|
||||
DPRINTF("hatch=%%p\\n", hatch);
|
||||
@ -324,9 +319,7 @@ make_hatch_ppc64(
|
||||
static char *
|
||||
make_hatch_arm64(
|
||||
Elf64_Phdr const *const phdr,
|
||||
char *base,
|
||||
char *next_unc,
|
||||
char *mfd_addr,
|
||||
unsigned frag_mask
|
||||
)
|
||||
{
|
||||
@ -337,25 +330,26 @@ make_hatch_arm64(
|
||||
0xd61f03c0, // br x30
|
||||
};
|
||||
unsigned *hatch = 0;
|
||||
DPRINTF("make_hatch %%p %%p %%p %%p %%x\\n", phdr, base, next_unc, mfd_addr, frag_mask);
|
||||
DPRINTF("make_hatch phdr=%%p next_unc=%%p frag_mask= %%x\\n",
|
||||
phdr, next_unc, frag_mask);
|
||||
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
|
||||
next_unc += phdr->p_memsz - phdr->p_filesz; // Skip over local .bss
|
||||
frag_mask &= -(long)next_unc; // bytes left on pge
|
||||
frag_mask &= -(long)next_unc; // bytes left on page
|
||||
if (4*4 <= frag_mask) {
|
||||
hatch = (unsigned *)(void *)next_unc;
|
||||
hatch = (unsigned *)(void *)(~3ul & (long)(3+ next_unc));
|
||||
hatch[0]= code[0];
|
||||
hatch[1]= code[1];
|
||||
hatch[2]= code[2];
|
||||
hatch[3]= code[3];
|
||||
char *t = (phdr->p_vaddr + base) + ((char *)hatch - mfd_addr);
|
||||
hatch = (unsigned *)(void *)t;
|
||||
hatch = (unsigned *)&hatch[0];
|
||||
}
|
||||
else { // Does not fit at hi end of .text, so must use a new page "permanently"
|
||||
int mfd = memfd_create(addr_string("upx"), 0); // the directory entry
|
||||
write(mfd, code, sizeof(code));
|
||||
mfd_addr = mmap(0, sizeof(code), PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
|
||||
ftruncate(mfd, sizeof(code));
|
||||
Pwrite(mfd, code, sizeof(code));
|
||||
void *mfd_addr = Pmap(0, sizeof(code), PROT_READ|PROT_EXEC, MAP_SHARED, mfd, 0);
|
||||
close(mfd);
|
||||
hatch = (unsigned *)(void *)mfd_addr;
|
||||
hatch = (unsigned *)mfd_addr;
|
||||
}
|
||||
}
|
||||
DPRINTF("hatch=%%p\\n", hatch);
|
||||
@ -418,8 +412,6 @@ extern void
|
||||
underlay(unsigned size, char *ptr, unsigned len);
|
||||
#endif //}
|
||||
|
||||
extern int ftruncate(int fd, off_t length);
|
||||
|
||||
// Exchange the bits with values 4 (PF_R, PROT_EXEC) and 1 (PF_X, PROT_READ)
|
||||
// Use table lookup into a PIC-string that pre-computes the result.
|
||||
unsigned PF_to_PROT(Elf64_Phdr const *phdr)
|
||||
@ -506,12 +498,13 @@ upx_so_main( // returns &escape_hatch
|
||||
if (phdr->p_flags & PF_X) {
|
||||
int mfd = memfd_create(addr_string("upx"), 0);
|
||||
unsigned mfd_len = 0ul - PAGE_MASK;
|
||||
write(mfd, elf_tmp, binfo->sz_unc); // de-compressed Elf_Ehdr and Elf_Phdrs
|
||||
write(mfd, binfo->sz_unc + va_load, mfd_len - binfo->sz_unc); // rest of 1st page
|
||||
ftruncate(mfd, mfd_len);
|
||||
Pwrite(mfd, elf_tmp, binfo->sz_unc); // de-compressed Elf_Ehdr and Elf_Phdrs
|
||||
Pwrite(mfd, binfo->sz_unc + va_load, mfd_len - binfo->sz_unc); // rest of 1st page
|
||||
|
||||
munmap(va_load, mfd_len); // make SELinux forget any previous protection
|
||||
Elf64_Addr va_mfd = (Elf64_Addr)mmap(va_load, mfd_len, PF_to_PROT(phdr),
|
||||
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, mfd, 0); (void)va_mfd;
|
||||
Punmap(va_load, mfd_len); // make SELinux forget any previous protection
|
||||
Elf64_Addr va_mfd = (Elf64_Addr)Pmap(va_load, mfd_len, PF_to_PROT(phdr),
|
||||
MAP_FIXED|MAP_SHARED, mfd, 0); (void)va_mfd;
|
||||
close(mfd);
|
||||
}
|
||||
|
||||
@ -556,16 +549,10 @@ upx_so_main( // returns &escape_hatch
|
||||
// to hold the contents.
|
||||
mfd = memfd_create(addr_string("upx"), 0); // the directory entry
|
||||
ftruncate(mfd, x1.size); // Allocate the pages in the file.
|
||||
write(mfd, x1.buf, frag); // Save lo fragment of contents on first page.
|
||||
mfd_addr = mmap(0, x1.size, PROT_READ|PROT_WRITE, MAP_SHARED, mfd, 0);
|
||||
DPRINTF("mfd_addr= %%p\\n", mfd_addr); // Now "somewhere" in RAM,
|
||||
// and ready to receive de-compressed bytes, and remember them in the
|
||||
// file (MAP_SHARED) so that they can be mmap() according to *phdr.
|
||||
|
||||
// Must keep the original compressed data until now, in order to
|
||||
// prevent the mmap(0, ...) from stealing that address range.
|
||||
Punmap(x1.buf, x1.size); // Discard original page frames in RAM.
|
||||
x1.buf = mfd_addr; // will add frag soon
|
||||
Pwrite(mfd, x1.buf, frag); // Save lo fragment of contents on first page.
|
||||
Punmap(x1.buf, x1.size);
|
||||
mfd_addr = Pmap(x1.buf, x1.size, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_SHARED, mfd, 0);
|
||||
DPRINTF("mfd_addr= %%p\\n", mfd_addr); // Re-use the address space
|
||||
}
|
||||
else {
|
||||
underlay(x1.size, x1.buf, frag); // also makes PROT_WRITE
|
||||
@ -580,20 +567,20 @@ upx_so_main( // returns &escape_hatch
|
||||
|
||||
if (!hatch && phdr->p_flags & PF_X) {
|
||||
#if defined(__x86_64) //{
|
||||
hatch = make_hatch_x86_64(phdr, (char *)base, x1.buf, mfd_addr, ~PAGE_MASK);
|
||||
hatch = make_hatch_x86_64(phdr, x1.buf, ~PAGE_MASK);
|
||||
#elif defined(__powerpc64__) //}{
|
||||
hatch = make_hatch_ppc64(phdr, (char *)base, x1.buf, mfd_addr, ~PAGE_MASK);
|
||||
hatch = make_hatch_ppc64(phdr, x1.buf, ~PAGE_MASK);
|
||||
#elif defined(__aarch64__) //}{
|
||||
hatch = make_hatch_arm64(phdr, (char *)base, x1.buf, mfd_addr, ~PAGE_MASK);
|
||||
hatch = make_hatch_arm64(phdr, x1.buf, ~PAGE_MASK);
|
||||
#endif //}
|
||||
}
|
||||
|
||||
if (phdr->p_flags & PF_X) { // SELinux
|
||||
// Map the contents of mfd as per *phdr.
|
||||
DPRINTF("mfd mmap addr=%%p len=%%p\\n", (phdr->p_vaddr + base + pfx), al_bi.sz_unc);
|
||||
munmap(mfd_addr, frag + al_bi.sz_unc); // Discard RW mapping; mfd has the bytes
|
||||
Punmap(mfd_addr, frag + al_bi.sz_unc); // Discard RW mapping; mfd has the bytes
|
||||
Pmap((char *)(phdr->p_vaddr + base + pfx), al_bi.sz_unc, PF_to_PROT(phdr),
|
||||
MAP_FIXED|MAP_PRIVATE, mfd, 0);
|
||||
MAP_FIXED|MAP_SHARED, mfd, 0);
|
||||
close(mfd);
|
||||
}
|
||||
else { // easy
|
||||
@ -601,7 +588,7 @@ upx_so_main( // returns &escape_hatch
|
||||
}
|
||||
}
|
||||
|
||||
munmap(sideaddr, cpr_len);
|
||||
Punmap(sideaddr, cpr_len);
|
||||
DPRINTF("calling user DT_INIT %%p\\n", dt_init);
|
||||
dt_init(so_args->argc, so_args->argv, so_args->envp);
|
||||
|
||||
|
||||
@ -154,8 +154,9 @@ exit:
|
||||
read:
|
||||
do_sys __NR_read; ret
|
||||
|
||||
.globl write
|
||||
write:
|
||||
Pwrite: .globl Pwrite
|
||||
//int3
|
||||
write: .globl write
|
||||
do_sys __NR_write; ret
|
||||
|
||||
.globl open
|
||||
|
||||
@ -93,7 +93,7 @@ arg6w .req w5
|
||||
|
||||
.balign 4
|
||||
_start: .globl _start
|
||||
nop // bkpt // DEBUG
|
||||
bkpt // DEBUG
|
||||
PUSH4 (x0,x1,x2,lr) // MATCH_00
|
||||
|
||||
sub sp,sp,#2*NBPW // space for ADRU, LENU
|
||||
|
||||
@ -118,6 +118,7 @@ memfd_create: .globl memfd_create; do_sys __NR_memfd_create; ret
|
||||
read:
|
||||
do_sys __NR_read; ret
|
||||
|
||||
Pwrite: .globl Pwrite
|
||||
.globl write
|
||||
write:
|
||||
do_sys __NR_write; ret
|
||||
|
||||
@ -183,7 +183,6 @@ Punmap: .globl Punmap // from C
|
||||
ret
|
||||
|
||||
memfd_create: .globl memfd_create
|
||||
int3
|
||||
push $__NR_memfd_create; 5: jmp 5f
|
||||
mprotect: .globl mprotect
|
||||
mov %ebx,%eax; and $-1+ (1<<12),%eax
|
||||
@ -196,6 +195,7 @@ close: .globl close
|
||||
push $__NR_close; 5: jmp 5f
|
||||
munmap: .globl munmap
|
||||
push $ __NR_munmap; 5: jmp 5f
|
||||
Pwrite: .globl Pwrite
|
||||
write: .globl write
|
||||
push $__NR_write; 5:
|
||||
pop %eax
|
||||
|
||||
@ -49,6 +49,7 @@ int Punmap(void *, size_t);
|
||||
void *mmap_privanon(void *, size_t, int, int);
|
||||
#endif //}
|
||||
ssize_t write(int, void const *, size_t);
|
||||
ssize_t Pwrite(int, void const *, size_t);
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
@ -270,29 +271,26 @@ ERR_LAB
|
||||
static char *
|
||||
make_hatch_i386(
|
||||
Elf32_Phdr const *const phdr,
|
||||
char *base,
|
||||
char *next_unc,
|
||||
char *mfd_addr,
|
||||
unsigned frag_mask
|
||||
)
|
||||
{
|
||||
char *hatch = 0;
|
||||
DPRINTF("make_hatch %%p %%p %%p %%p %%x\\n", phdr, base, next_unc, mfd_addr, frag_mask);
|
||||
DPRINTF("make_hatch %%p %%p %%x\\n", phdr, next_unc, frag_mask);
|
||||
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
|
||||
next_unc += phdr->p_memsz - phdr->p_filesz; // Skip over local .bss
|
||||
frag_mask &= -(long)next_unc; // bytes left on pge
|
||||
frag_mask &= -(long)next_unc; // bytes left on page
|
||||
unsigned /*const*/ escape = 0xc36180cd; // "int $0x80; popa; ret"
|
||||
if (4 <= frag_mask) {
|
||||
hatch = next_unc;
|
||||
*(long *)&hatch[0] = escape;
|
||||
hatch += phdr->p_vaddr + (base - mfd_addr); // relocate to eventual address
|
||||
}
|
||||
else { // Does not fit at hi end of .text, so must use a new page "permanently"
|
||||
int mfd = memfd_create(addr_string("upx"), 0); // the directory entry
|
||||
//ftruncate(mfd, 4);
|
||||
write(mfd, &escape, 4);
|
||||
mfd_addr = mmap(0, 4, PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
|
||||
hatch = mmap(0, 4, PROT_READ|PROT_EXEC, MAP_SHARED, mfd, 0);
|
||||
close(mfd);
|
||||
hatch = mfd_addr;
|
||||
}
|
||||
}
|
||||
DPRINTF("hatch=%%p\\n", hatch);
|
||||
@ -304,9 +302,7 @@ extern unsigned get_sys_munmap(void);
|
||||
static void *
|
||||
make_hatch_arm32(
|
||||
Elf32_Phdr const *const phdr,
|
||||
char *base,
|
||||
char *next_unc,
|
||||
char *mfd_addr,
|
||||
unsigned frag_mask
|
||||
)
|
||||
{
|
||||
@ -316,25 +312,23 @@ make_hatch_arm32(
|
||||
0xe8bd80ff, // ldmia sp!,{r0,r1,r2,r3,r4,r5,r6,r7,pc}
|
||||
};
|
||||
unsigned *hatch = 0;
|
||||
DPRINTF("make_hatch %%p %%p %%p %%p %%x\\n", phdr, base, next_unc, mfd_addr, frag_mask);
|
||||
DPRINTF("make_hatch %%p %%p %%x\\n", phdr, next_unc, frag_mask);
|
||||
|
||||
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
|
||||
next_unc += phdr->p_memsz - phdr->p_filesz; // Skip over local .bss
|
||||
frag_mask &= -(long)next_unc; // bytes left on pge
|
||||
frag_mask &= -(long)next_unc; // bytes left on page
|
||||
if (2*4 <= frag_mask) {
|
||||
hatch = (unsigned *)(void *)next_unc;
|
||||
hatch = (unsigned *)(void *)(~3ul & (long)(3+ next_unc));
|
||||
hatch[0]= code[0];
|
||||
hatch[1]= code[1];
|
||||
char *t = (phdr->p_vaddr + base) + ((char *)hatch - mfd_addr);
|
||||
__clear_cache(&hatch[0], &hatch[2]);
|
||||
hatch = (unsigned *)(void *)t;
|
||||
}
|
||||
else { // Does not fit at hi end of .text, so must use a new page "permanently"
|
||||
int mfd = memfd_create(addr_string("upx"), 0); // the directory entry
|
||||
//ftruncate(mfd, 2*4);
|
||||
write(mfd, &code, 2*4);
|
||||
mfd_addr = mmap(0, 2*4, PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
|
||||
hatch = Pmap(0, 2*4, PROT_READ|PROT_EXEC, MAP_SHARED, mfd, 0);
|
||||
close(mfd);
|
||||
hatch = (unsigned *)(void *)mfd_addr;
|
||||
}
|
||||
}
|
||||
DPRINTF("hatch=%%p\\n", hatch);
|
||||
@ -561,12 +555,14 @@ upx_so_main( // returns &escape_hatch
|
||||
if (phdr->p_flags & PF_X) {
|
||||
int mfd = memfd_create(addr_string("upx"), 0);
|
||||
unsigned mfd_len = 0ul - page_mask;
|
||||
write(mfd, elf_tmp, binfo->sz_unc); // de-compressed Elf_Ehdr and Elf_Phdrs
|
||||
write(mfd, binfo->sz_unc + va_load, mfd_len - binfo->sz_unc); // rest of 1st page
|
||||
ftruncate(mfd, mfd_len);
|
||||
Pwrite(mfd, elf_tmp, binfo->sz_unc); // de-compressed Elf_Ehdr and Elf_Phdrs
|
||||
Pwrite(mfd, binfo->sz_unc + va_load, mfd_len - binfo->sz_unc); // rest of 1st page
|
||||
|
||||
Punmap(va_load, mfd_len); // make SELinux forget any previous protection
|
||||
Elf32_Addr va_mfd = (Elf32_Addr)Pmap(va_load, mfd_len, PF_to_PROT(phdr),
|
||||
MAP_FIXED|MAP_SHARED, mfd, 0); (void)va_mfd;
|
||||
|
||||
munmap(va_load, mfd_len); // make SELinux forget any previous protection
|
||||
Elf32_Addr va_mfd = (Elf32_Addr)mmap(va_load, mfd_len, PF_to_PROT(phdr),
|
||||
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, mfd, 0); (void)va_mfd;
|
||||
close(mfd);
|
||||
}
|
||||
|
||||
@ -595,7 +591,7 @@ upx_so_main( // returns &escape_hatch
|
||||
|
||||
// Using .p_memsz implicitly handles .bss via MAP_ANONYMOUS.
|
||||
// Omit any non-tcompressed prefix (below xct_off)
|
||||
x1.buf = (char *)(phdr->p_vaddr + pfx + base);
|
||||
x1.buf = (char *)(pfx + phdr->p_vaddr + base);
|
||||
x1.size = phdr->p_memsz - pfx;
|
||||
|
||||
unsigned const frag = (phdr->p_vaddr + pfx) & ~page_mask; // lo fragment on page
|
||||
@ -611,16 +607,11 @@ upx_so_main( // returns &escape_hatch
|
||||
// to hold the contents.
|
||||
mfd = memfd_create(addr_string("upx"), 0); // the directory entry
|
||||
ftruncate(mfd, x1.size); // Allocate the pages in the file.
|
||||
write(mfd, x1.buf, frag); // Save lo fragment of contents on first page.
|
||||
mfd_addr = mmap(0, x1.size, PROT_READ|PROT_WRITE, MAP_SHARED, mfd, 0);
|
||||
DPRINTF("mfd_addr= %%p\\n", mfd_addr); // Now "somewhere" in RAM,
|
||||
// and ready to receive de-compressed bytes, and remember them in the
|
||||
// file (MAP_SHARED) so that they can be mmap() according to *phdr.
|
||||
Pwrite(mfd, x1.buf, frag); // Save lo fragment of contents on first page.
|
||||
Punmap(x1.buf, x1.size);
|
||||
mfd_addr = Pmap(x1.buf, x1.size, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_SHARED, mfd, 0);
|
||||
DPRINTF("mfd_addr= %%p\\n", mfd_addr); // Re-use the address space
|
||||
|
||||
// Must keep the original compressed data until now, in order to
|
||||
// prevent the mmap(0, ...) from stealing that address range.
|
||||
munmap(x1.buf, x1.size); // Discard original page frames in RAM.
|
||||
x1.buf = mfd_addr; // will add pfx soon
|
||||
}
|
||||
else {
|
||||
underlay(x1.size, x1.buf, frag, phdr->p_flags); // also makes PROT_WRITE
|
||||
@ -635,21 +626,21 @@ upx_so_main( // returns &escape_hatch
|
||||
|
||||
if (!hatch && phdr->p_flags & PF_X) {
|
||||
#if defined(__i386__) //{
|
||||
hatch = make_hatch_i386(phdr, (char *)base, x1.buf, mfd_addr, ~page_mask);
|
||||
hatch = make_hatch_i386(phdr, x1.buf, ~page_mask);
|
||||
#elif defined(__arm__) //}{
|
||||
hatch = make_hatch_arm32(phdr, (char *)base, x1.buf, mfd_addr, ~page_mask);
|
||||
hatch = make_hatch_arm32(phdr, x1.buf, ~page_mask);
|
||||
|
||||
#elif defined(__powerpc32__) //}{
|
||||
hatch = make_hatch_ppc32(phdr, (char *)base, x1.buf, mfd_addr, ~page_mask);
|
||||
hatch = make_hatch_ppc32(phdr, x1.buf, ~page_mask);
|
||||
#endif //}
|
||||
}
|
||||
|
||||
if (phdr->p_flags & PF_X) { // SELinux
|
||||
// Map the contents of mfd as per *phdr.
|
||||
DPRINTF("mfd mmap addr=%%p len=%%p\\n", (phdr->p_vaddr + base + pfx), al_bi.sz_unc);
|
||||
munmap(mfd_addr, pfx + al_bi.sz_unc); // Discard RW mapping; mfd has the bytes
|
||||
Punmap(mfd_addr, frag + al_bi.sz_unc); // Discard RW mapping; mfd has the bytes
|
||||
Pmap((char *)(phdr->p_vaddr + base + pfx), al_bi.sz_unc, PF_to_PROT(phdr),
|
||||
MAP_FIXED|MAP_PRIVATE, mfd, 0);
|
||||
MAP_FIXED|MAP_SHARED, mfd, 0);
|
||||
close(mfd);
|
||||
}
|
||||
else { // easy
|
||||
@ -657,7 +648,7 @@ upx_so_main( // returns &escape_hatch
|
||||
}
|
||||
}
|
||||
|
||||
munmap(sideaddr, cpr_len);
|
||||
Punmap(sideaddr, cpr_len);
|
||||
DPRINTF("calling user DT_INIT %%p\\n", dt_init);
|
||||
dt_init(so_args->argc, so_args->argv, so_args->envp);
|
||||
|
||||
|
||||
95
src/stub/tmp/amd64-linux.elf-so_fold.bin.dump
generated
vendored
95
src/stub/tmp/amd64-linux.elf-so_fold.bin.dump
generated
vendored
@ -2,19 +2,19 @@ file format elf64-x86-64
|
||||
|
||||
Sections:
|
||||
Idx Name Size VMA LMA File off Algn Flags
|
||||
0 SO_MAIN 07b2 0 0 040 2**4 CONTENTS
|
||||
1 EXP_HEAD 0e0 0 0 07f2 2**0 CONTENTS
|
||||
2 NRV2E 0e5 0 0 08d2 2**0 CONTENTS
|
||||
3 NRV2D 0d7 0 0 09b7 2**0 CONTENTS
|
||||
4 NRV2B 0c1 0 0 0a8e 2**0 CONTENTS
|
||||
5 SO_HEAD 02c 0 0 0b4f 2**0 CONTENTS
|
||||
6 ptr_NEXT 0 0 0 0b7b 2**0 CONTENTS
|
||||
7 SO_TAIL 098 0 0 0b7b 2**0 CONTENTS
|
||||
8 LZMA_ELF00 064 0 0 0c13 2**0 CONTENTS
|
||||
9 LZMA_DEC10 09f7 0 0 0c77 2**0 CONTENTS
|
||||
10 LZMA_DEC20 09f7 0 0 0166e 2**0 CONTENTS
|
||||
11 LZMA_DEC30 018 0 0 02065 2**0 CONTENTS
|
||||
12 EXP_TAIL 0c 0 0 0207d 2**0 CONTENTS
|
||||
0 SO_MAIN 07a0 0 0 040 2**4 CONTENTS
|
||||
1 EXP_HEAD 0e0 0 0 07e0 2**0 CONTENTS
|
||||
2 NRV2E 0e5 0 0 08c0 2**0 CONTENTS
|
||||
3 NRV2D 0d7 0 0 09a5 2**0 CONTENTS
|
||||
4 NRV2B 0c1 0 0 0a7c 2**0 CONTENTS
|
||||
5 SO_HEAD 02c 0 0 0b3d 2**0 CONTENTS
|
||||
6 ptr_NEXT 0 0 0 0b69 2**0 CONTENTS
|
||||
7 SO_TAIL 098 0 0 0b69 2**0 CONTENTS
|
||||
8 LZMA_ELF00 064 0 0 0c01 2**0 CONTENTS
|
||||
9 LZMA_DEC10 09f7 0 0 0c65 2**0 CONTENTS
|
||||
10 LZMA_DEC20 09f7 0 0 0165c 2**0 CONTENTS
|
||||
11 LZMA_DEC30 018 0 0 02053 2**0 CONTENTS
|
||||
12 EXP_TAIL 0c 0 0 0206b 2**0 CONTENTS
|
||||
SYMBOL TABLE:
|
||||
0000000000000000 l d EXP_HEAD 0 EXP_HEAD
|
||||
0000000000000000 l d LZMA_DEC30 0 LZMA_DEC30
|
||||
@ -38,18 +38,19 @@ SYMBOL TABLE:
|
||||
000000000000003f g SO_TAIL 0 mmap
|
||||
0000000000000000 g F SO_TAIL 0 eof
|
||||
000000000000007d g SO_TAIL 0 write
|
||||
000000000000038e g F SO_MAIN 01d PF_to_PROT
|
||||
0000000000000380 g F SO_MAIN 01d PF_to_PROT
|
||||
000000000000006b g SO_TAIL 0 memfd_create
|
||||
0000000000000081 g SO_TAIL 0 read
|
||||
0000000000000013 g SO_TAIL 0 memset
|
||||
0000000000000011 g SO_TAIL 0 my_bkpt
|
||||
0000000000000085 g SO_TAIL 0 Pprotect
|
||||
0000000000000000 *UND* 0 Pwrite
|
||||
0000000000000051 g SO_TAIL 0 Punmap
|
||||
0000000000000063 g SO_TAIL 0 exit
|
||||
0000000000000076 g SO_TAIL 0 openat
|
||||
0000000000000094 g SO_TAIL 0 mprotect
|
||||
0000000000000072 g SO_TAIL 0 close
|
||||
00000000000003ab g F SO_MAIN 0407 upx_so_main
|
||||
000000000000039d g F SO_MAIN 0403 upx_so_main
|
||||
|
||||
RELOCATION RECORDS FOR [SO_MAIN]:
|
||||
OFFSET TYPE VALUE
|
||||
@ -57,37 +58,39 @@ OFFSET TYPE VALUE
|
||||
0000000000000017 R_X86_64_PLT32 exit+0xfffffffffffffffc
|
||||
000000000000002e R_X86_64_PLT32 exit+0xfffffffffffffffc
|
||||
000000000000010e R_X86_64_PLT32 f_expand+0xfffffffffffffffc
|
||||
00000000000001e9 R_X86_64_PLT32 memfd_create+0xfffffffffffffffc
|
||||
0000000000000204 R_X86_64_PLT32 write+0xfffffffffffffffc
|
||||
0000000000000226 R_X86_64_PLT32 mmap+0xfffffffffffffffc
|
||||
0000000000000230 R_X86_64_PLT32 close+0xfffffffffffffffc
|
||||
0000000000000291 R_X86_64_PLT32 openat+0xfffffffffffffffc
|
||||
00000000000002a9 R_X86_64_PLT32 read+0xfffffffffffffffc
|
||||
00000000000002b7 R_X86_64_PLT32 close+0xfffffffffffffffc
|
||||
0000000000000333 R_X86_64_PLT32 memcpy+0xfffffffffffffffc
|
||||
0000000000000354 R_X86_64_PLT32 mmap+0xfffffffffffffffc
|
||||
0000000000000362 R_X86_64_PLT32 memcpy+0xfffffffffffffffc
|
||||
000000000000042e R_X86_64_PLT32 mmap+0xfffffffffffffffc
|
||||
0000000000000441 R_X86_64_PLT32 memcpy+0xfffffffffffffffc
|
||||
00000000000004e3 R_X86_64_PLT32 memfd_create+0xfffffffffffffffc
|
||||
00000000000004fc R_X86_64_PLT32 write+0xfffffffffffffffc
|
||||
0000000000000510 R_X86_64_PLT32 write+0xfffffffffffffffc
|
||||
000000000000051f R_X86_64_PLT32 munmap+0xfffffffffffffffc
|
||||
0000000000000527 R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
|
||||
0000000000000542 R_X86_64_PLT32 mmap+0xfffffffffffffffc
|
||||
0000000000000549 R_X86_64_PLT32 close+0xfffffffffffffffc
|
||||
000000000000062d R_X86_64_PLT32 memfd_create+0xfffffffffffffffc
|
||||
000000000000063d R_X86_64_PLT32 ftruncate+0xfffffffffffffffc
|
||||
000000000000064e R_X86_64_PLT32 write+0xfffffffffffffffc
|
||||
0000000000000672 R_X86_64_PLT32 mmap+0xfffffffffffffffc
|
||||
0000000000000684 R_X86_64_PLT32 Punmap+0xfffffffffffffffc
|
||||
000000000000070f R_X86_64_PLT32 munmap+0xfffffffffffffffc
|
||||
0000000000000717 R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
|
||||
000000000000073f R_X86_64_PLT32 Pmap+0xfffffffffffffffc
|
||||
0000000000000748 R_X86_64_PLT32 close+0xfffffffffffffffc
|
||||
0000000000000752 R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
|
||||
0000000000000768 R_X86_64_PLT32 Pprotect+0xfffffffffffffffc
|
||||
0000000000000783 R_X86_64_PLT32 munmap+0xfffffffffffffffc
|
||||
00000000000001d2 R_X86_64_PLT32 memfd_create+0xfffffffffffffffc
|
||||
00000000000001e0 R_X86_64_PLT32 ftruncate+0xfffffffffffffffc
|
||||
00000000000001f9 R_X86_64_PLT32 Pwrite+0xfffffffffffffffc
|
||||
000000000000021b R_X86_64_PLT32 Pmap+0xfffffffffffffffc
|
||||
0000000000000225 R_X86_64_PLT32 close+0xfffffffffffffffc
|
||||
0000000000000283 R_X86_64_PLT32 openat+0xfffffffffffffffc
|
||||
000000000000029b R_X86_64_PLT32 read+0xfffffffffffffffc
|
||||
00000000000002a9 R_X86_64_PLT32 close+0xfffffffffffffffc
|
||||
0000000000000325 R_X86_64_PLT32 memcpy+0xfffffffffffffffc
|
||||
0000000000000346 R_X86_64_PLT32 mmap+0xfffffffffffffffc
|
||||
0000000000000354 R_X86_64_PLT32 memcpy+0xfffffffffffffffc
|
||||
0000000000000425 R_X86_64_PLT32 mmap+0xfffffffffffffffc
|
||||
0000000000000438 R_X86_64_PLT32 memcpy+0xfffffffffffffffc
|
||||
00000000000004de R_X86_64_PLT32 memfd_create+0xfffffffffffffffc
|
||||
00000000000004f7 R_X86_64_PLT32 ftruncate+0xfffffffffffffffc
|
||||
0000000000000505 R_X86_64_PLT32 Pwrite+0xfffffffffffffffc
|
||||
000000000000051d R_X86_64_PLT32 Pwrite+0xfffffffffffffffc
|
||||
000000000000052a R_X86_64_PLT32 Punmap+0xfffffffffffffffc
|
||||
0000000000000532 R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
|
||||
000000000000054f R_X86_64_PLT32 Pmap+0xfffffffffffffffc
|
||||
0000000000000556 R_X86_64_PLT32 close+0xfffffffffffffffc
|
||||
0000000000000633 R_X86_64_PLT32 memfd_create+0xfffffffffffffffc
|
||||
0000000000000642 R_X86_64_PLT32 ftruncate+0xfffffffffffffffc
|
||||
0000000000000652 R_X86_64_PLT32 Pwrite+0xfffffffffffffffc
|
||||
0000000000000661 R_X86_64_PLT32 Punmap+0xfffffffffffffffc
|
||||
0000000000000683 R_X86_64_PLT32 Pmap+0xfffffffffffffffc
|
||||
0000000000000703 R_X86_64_PLT32 Punmap+0xfffffffffffffffc
|
||||
000000000000070b R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
|
||||
0000000000000730 R_X86_64_PLT32 Pmap+0xfffffffffffffffc
|
||||
0000000000000738 R_X86_64_PLT32 close+0xfffffffffffffffc
|
||||
0000000000000742 R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
|
||||
0000000000000756 R_X86_64_PLT32 Pprotect+0xfffffffffffffffc
|
||||
0000000000000771 R_X86_64_PLT32 Punmap+0xfffffffffffffffc
|
||||
|
||||
RELOCATION RECORDS FOR [NRV2E]:
|
||||
OFFSET TYPE VALUE
|
||||
|
||||
Loading…
Reference in New Issue
Block a user