1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00

more ELF shlib when no DT_INIT (especially Android): hook DT_INIT_ARRAY[0]

https://github.com/upx/upx/issues/191  [partial, not finished]
	modified:   p_lx_elf.cpp
	modified:   p_lx_elf.h
	modified:   stub/src/arm.v4a-linux.shlib-init.S
	modified:   stub/src/arm.v4t-linux.shlib-init.S
This commit is contained in:
John Reiser 2018-03-26 16:30:52 -07:00
parent 9b990c4eae
commit 5e9b6bd69d
8 changed files with 1734 additions and 1757 deletions

View File

@ -330,7 +330,7 @@ off_t PackLinuxElf::pack3(OutputFile *fo, Filter &ft) // return length of output
if (xct_off) { // is_shlib
upx_uint64_t const firstpc_va = (jni_onload_va
? jni_onload_va
: elf_unsigned_dynamic(upx_dt_init) );
: user_init_va);
set_te32(&disp, firstpc_va - load_va);
fo->write(&disp, sizeof(disp)); // DT_INIT.d_val
len += sizeof(disp);
@ -401,11 +401,12 @@ off_t PackLinuxElf32::pack3(OutputFile *fo, Filter &ft)
set_te32(&elfout.phdr[1].p_flags, Elf32_Phdr::PF_W|Elf32_Phdr::PF_R);
}
if (0!=xct_off) { // shared library
unsigned word = (Elf32_Ehdr::EM_ARM==e_machine) + load_va + sz_pack2; // Thumb mode
set_te32(&file_image[user_init_off], word); // set the hook
unsigned off = fo->st_size();
Elf32_Phdr *phdr = (Elf32_Phdr *)lowmem.subref(
"bad e_phoff", e_phoff, e_phnum * sizeof(Elf32_Phdr));
unsigned off = fo->st_size();
unsigned off_init = 0; // where in file
unsigned va_init = sz_pack2; // virtual address
so_slide = 0;
for (unsigned j = 0; j < e_phnum; ++j, ++phdr) {
unsigned const len = get_te32(&phdr->p_filesz);
@ -435,36 +436,15 @@ off_t PackLinuxElf32::pack3(OutputFile *fo, Filter &ft)
set_te32(&phdr->p_offset, so_slide + ioff);
}
else { // Change length of first PT_LOAD.
va_init += get_te32(&phdr->p_vaddr);
set_te32(&phdr->p_filesz, sz_pack2 + lsize);
set_te32(&phdr->p_memsz, sz_pack2 + lsize);
}
continue; // all done with this PT_LOAD
}
// Compute new offset of &DT_INIT.d_val.
if (Elf32_Phdr::PT_DYNAMIC==type) {
off_init = ioff + ((xct_off < ioff) ? so_slide : 0);
Elf32_Dyn *dyn = (Elf32_Dyn *)(void *)&file_image[ioff];
for (int j2 = len; j2 > 0; ++dyn, j2 -= sizeof(*dyn)) {
if (get_te32(&dyn->d_tag) == upx_dt_init) {
off_init += (unsigned char *)&dyn->d_val
- (unsigned char *)&file_image[ioff];
break;
}
}
// fall through to relocate .p_offset
}
if (xct_off < ioff)
set_te32(&phdr->p_offset, so_slide + ioff);
} // end each Phdr
if (off_init) { // change DT_INIT.d_val
fo->seek(off_init, SEEK_SET);
va_init |= (Elf32_Ehdr::EM_ARM==e_machine); // THUMB mode
unsigned word; set_te32(&word, va_init);
fo->rewrite(&word, sizeof(word));
flen = fo->seek(0, SEEK_END);
}
if (opt->o_unix.android_shlib) {
// Update {DYNAMIC}.sh_offset by so_slide.
Elf32_Shdr *shdr = (Elf32_Shdr *)lowmem.subref(
@ -1892,20 +1872,33 @@ bool PackLinuxElf32::canPack()
xct_va = ~0u;
if (e_shnum) {
for (int j= e_shnum; --j>=0; ++shdr) {
unsigned const sh_type = get_te32(&shdr->sh_type);
if (Elf32_Shdr::SHF_EXECINSTR & get_te32(&shdr->sh_flags)) {
xct_va = umin(xct_va, get_te32(&shdr->sh_addr));
}
// Hook the first slot of DT_PREINIT_ARRAY or DT_INIT_ARRAY.
if (( Elf32_Dyn::DT_PREINIT_ARRAY==upx_dt_init
&& Elf32_Shdr::SHT_PREINIT_ARRAY==sh_type)
|| ( Elf32_Dyn::DT_INIT_ARRAY ==upx_dt_init
&& Elf32_Shdr::SHT_INIT_ARRAY ==sh_type) ) {
user_init_off = get_te32(&shdr->sh_offset);
user_init_va = get_te32(&file_image[user_init_off]);
}
// By default /usr/bin/ld leaves 4 extra DT_NULL to support pre-linking.
// Take one if DT_INIT is not present.
if (Elf32_Shdr::SHT_DYNAMIC == get_te32(&shdr->sh_type)
&& Elf32_Dyn::DT_INIT != upx_dt_init) {
// Take one as a last resort.
if ((Elf32_Dyn::DT_INIT==upx_dt_init || !upx_dt_init)
&& Elf32_Shdr::SHT_DYNAMIC == sh_type) {
unsigned const n = get_te32(&shdr->sh_size) / sizeof(Elf32_Dyn);
Elf32_Dyn *dynp = const_cast<Elf32_Dyn *>(dynseg);
for (; Elf32_Dyn::DT_NULL != dynp->d_tag; ++dynp) /* empty */ ;
Elf32_Dyn *dynp = (Elf32_Dyn *)&file_image[shdr->sh_offset];
for (; Elf32_Dyn::DT_NULL != dynp->d_tag; ++dynp) {
if (upx_dt_init == get_te32(&dynp->d_tag)) {
break; // re-found DT_INIT
}
}
if ((1+ dynp) < (n+ dynseg)) { // not the terminator, so take it
set_te32(&dynp->d_tag, Elf32_Dyn::DT_INIT);
dynp->d_val = 0;
upx_dt_init = Elf32_Dyn::DT_INIT;
user_init_va = get_te32(&dynp->d_val); // 0 if (0==upx_dt_init)
set_te32(&dynp->d_tag, upx_dt_init = Elf32_Dyn::DT_INIT);
user_init_off = (char const *)&dynp->d_val - (char const *)&file_image[0];
}
}
}

View File

@ -88,6 +88,8 @@ protected:
upx_uint64_t load_va; // PT_LOAD[0].p_vaddr
upx_uint64_t xct_va; // minimum SHT_EXECINSTR virtual address
upx_uint64_t jni_onload_va; // runtime &JNI_OnLoad
upx_uint64_t user_init_va;
unsigned user_init_off; // within file_image
upx_uint16_t e_machine;
unsigned char ei_class;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -90,6 +90,7 @@ _start: .globl _start
stmdb sp!,{arg1,arg2,arg3, eax,ecx,r6,r7, fp,lr,pc}
mov fp,sp
o_uinit= (3+4+2)*4 // pc
str lr,[fp,#o_uinit] // default for empty user_init
bl main // push &f_decompress
f_decompress:
@ -185,7 +186,8 @@ main:
sub tmp,esi,tmp // &b_info
lodsl; cmp eax,#0; beq 0f
add eax,ecx,eax // reloc DT_INIT for step 12
0: str eax,[fp,#o_uinit]
str eax,[fp,#o_uinit]
0:
lodsl; add eax,ecx,eax; push eax // reloc &hatch for step 10
o_hatch= -1*4
lodsl; add edi,ecx,eax // &l_info; also destination for decompress
@ -310,18 +312,11 @@ supervise:
error ARMEL_EABI4, ARM_OLDABI
#endif //}
ldmia sp!,{arg1,arg2,arg3, eax,ecx,r6,r7, fp,lr,pc}
hatch_empty:
ret
L620: // Implant escape hatch at end of .text
ldr eax,[fp,#o_hatch]
ldmia lr,{arg1,arg2,arg3}
ldmia lr,{arg1,arg2}
stmia eax,{arg1,arg2}
ldr tmp,[fp,#o_uinit]
cmp tmp,#0; bne 0f
str arg3,[eax]
str eax,[fp,#o_uinit]
0:
//p_unflt
ldmia sp!,{arg1,arg2,arg3,arg4, eax, r12} // r12= w_fragment [toss]

View File

@ -143,10 +143,11 @@ here:
sub tmp,edi // offset(b_info)
sub ecx,eax; //str ecx,[SP(o_reloc)]
lsl edi,#12 // asl_delta
ldr eax,[esi,#2*NBPW]; cmp eax,#0; beq 0f
ldr eax,[esi,#2*NBPW]; cmp eax,#0; beq 0f // empty user_init
add eax,ecx // reloc DT_INIT for step 12
add eax,edi
0: str eax,[SP(o_uinit)]
str eax,[SP(o_uinit)]
0:
ldr edi,[esi,#4*NBPW]; add edi,ecx // dst for f_exp
add esi,tmp,ecx // &b_info src for f_exp
@ -156,7 +157,7 @@ o_hatch=_ // 10
_=2+_ // param space: munmap temp pages (step 9)
p_unmap=_ // 12
push_ lr
push_ lr // will be lr at entry to user_init
o_lr=_ // 13
ldr eax,[esi,#sz_cpr]; add esi,#sz_b_info
add esi,eax // skip unpack helper block
@ -348,13 +349,6 @@ _=-5+_ // 22
bic edi,tmp // round_up(2, .p_memsz + .p_vaddr)
ldr tmp,hatch // the 2 instructions
str tmp,[edi]
ldr tmp,[SP(o_uinit)]
cmp tmp,#0; bne 0f
ldrh tmp,hatch_empty
strh tmp,[edi,#2*2]
add tmp,edi,#2*2
str tmp,[SP(o_uinit)]
0:
add edi,#1 // thumb mode
str edi,[SP(o_hatch)]
@ -390,8 +384,6 @@ _=-3+_ // 9
hatch:
swi 0 // 0xdf00; munmap
pop {r0,r1,r2,r3,r4,r5,r6,r7,pc} // 0xbdff; goto user DT_INIT
hatch_empty:
ret
.thumb_func
movsl_subr:

View File

@ -2,18 +2,18 @@ file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn Flags
0 ELFMAINX 00000010 00000000 00000000 00000034 2**0 CONTENTS, RELOC, READONLY
1 NRV_HEAD 00000000 00000000 00000000 00000044 2**0 CONTENTS, READONLY
2 NRV_TAIL 00000000 00000000 00000000 00000044 2**0 CONTENTS, READONLY
3 NRV2E 0000013c 00000000 00000000 00000044 2**0 CONTENTS, RELOC, READONLY
4 NRV2D 00000128 00000000 00000000 00000180 2**0 CONTENTS, RELOC, READONLY
5 NRV2B 000000ec 00000000 00000000 000002a8 2**0 CONTENTS, RELOC, READONLY
6 LZMA_ELF00 000000b8 00000000 00000000 00000394 2**0 CONTENTS, RELOC, READONLY
7 LZMA_DEC20 00000938 00000000 00000000 0000044c 2**0 CONTENTS, RELOC, READONLY
8 LZMA_DEC10 00000478 00000000 00000000 00000d84 2**0 CONTENTS, RELOC, READONLY
9 LZMA_DEC30 00000000 00000000 00000000 000011fc 2**0 CONTENTS, READONLY
10 ELFMAINY 0000003e 00000000 00000000 000011fc 2**0 CONTENTS, READONLY
11 ELFMAINZ 00000328 00000000 00000000 0000123a 2**0 CONTENTS, RELOC, READONLY
0 ELFMAINX 00000014 00000000 00000000 00000034 2**0 CONTENTS, RELOC, READONLY
1 NRV_HEAD 00000000 00000000 00000000 00000048 2**0 CONTENTS, READONLY
2 NRV_TAIL 00000000 00000000 00000000 00000048 2**0 CONTENTS, READONLY
3 NRV2E 0000013c 00000000 00000000 00000048 2**0 CONTENTS, RELOC, READONLY
4 NRV2D 00000128 00000000 00000000 00000184 2**0 CONTENTS, RELOC, READONLY
5 NRV2B 000000ec 00000000 00000000 000002ac 2**0 CONTENTS, RELOC, READONLY
6 LZMA_ELF00 000000b8 00000000 00000000 00000398 2**0 CONTENTS, RELOC, READONLY
7 LZMA_DEC20 00000938 00000000 00000000 00000450 2**0 CONTENTS, RELOC, READONLY
8 LZMA_DEC10 00000478 00000000 00000000 00000d88 2**0 CONTENTS, RELOC, READONLY
9 LZMA_DEC30 00000000 00000000 00000000 00001200 2**0 CONTENTS, READONLY
10 ELFMAINY 0000003e 00000000 00000000 00001200 2**0 CONTENTS, READONLY
11 ELFMAINZ 00000310 00000000 00000000 0000123e 2**0 CONTENTS, RELOC, READONLY
SYMBOL TABLE:
00000000 l d NRV2E 00000000 NRV2E
00000000 l d NRV2D 00000000 NRV2D
@ -36,7 +36,7 @@ SYMBOL TABLE:
RELOCATION RECORDS FOR [ELFMAINX]:
OFFSET TYPE VALUE
0000000c R_ARM_PC24 ELFMAINZ
00000010 R_ARM_PC24 ELFMAINZ
RELOCATION RECORDS FOR [NRV2E]:
OFFSET TYPE VALUE
@ -258,15 +258,14 @@ OFFSET TYPE VALUE
00000164 R_ARM_PC24 ELFMAINZ
00000174 R_ARM_PC24 ELFMAINZ
00000184 R_ARM_PC24 ELFMAINZ
000001a8 R_ARM_PC24 ELFMAINZ
000001bc R_ARM_PC24 ELFMAINZ
00000218 R_ARM_PC24 ELFMAINZ
00000220 R_ARM_PC24 ELFMAINZ
00000234 R_ARM_PC24 ELFMAINZ
00000248 R_ARM_PC24 ELFMAINZ
00000270 R_ARM_PC24 ELFMAINZ
00000284 R_ARM_PC24 ELFMAINZ
000002ac R_ARM_PC24 ELFMAINZ
000001a4 R_ARM_PC24 ELFMAINZ
00000200 R_ARM_PC24 ELFMAINZ
00000208 R_ARM_PC24 ELFMAINZ
0000021c R_ARM_PC24 ELFMAINZ
00000230 R_ARM_PC24 ELFMAINZ
00000258 R_ARM_PC24 ELFMAINZ
0000026c R_ARM_PC24 ELFMAINZ
00000294 R_ARM_PC24 ELFMAINZ
000002a4 R_ARM_PC24 ELFMAINZ
000002b0 R_ARM_PC24 ELFMAINZ
000002bc R_ARM_PC24 ELFMAINZ
000002c8 R_ARM_PC24 ELFMAINZ
000002d4 R_ARM_PC24 ELFMAINZ

View File

@ -13,7 +13,7 @@ Idx Name Size VMA LMA File off Algn Flags
8 LZMA_DEC10 00000478 00000000 00000000 00000e14 2**0 CONTENTS, RELOC, READONLY
9 LZMA_DEC30 00000000 00000000 00000000 0000128c 2**0 CONTENTS, READONLY
10 ELFMAINY 0000003e 00000000 00000000 0000128c 2**0 CONTENTS, READONLY
11 ELFMAINZ 00000194 00000000 00000000 000012cc 2**2 CONTENTS, RELOC, READONLY
11 ELFMAINZ 00000184 00000000 00000000 000012cc 2**2 CONTENTS, RELOC, READONLY
SYMBOL TABLE:
00000000 l ELFMAINX 00000000 .real_start_ofELFMAINX
00000000 l d NRV2E 00000000 NRV2E
@ -255,12 +255,12 @@ OFFSET TYPE VALUE
00000028 R_ARM_THM_CALL .real_start_ofELFMAINZ
00000030 R_ARM_THM_CALL .real_start_ofELFMAINZ
00000050 R_ARM_THM_CALL .real_start_ofELFMAINZ
0000008a R_ARM_THM_CALL .real_start_ofELFMAINZ
000000aa R_ARM_THM_CALL .real_start_ofELFMAINZ
000000dc R_ARM_PC24 ELFMAINZ
000000fa R_ARM_THM_CALL .real_start_ofELFMAINZ
00000120 R_ARM_THM_CALL .real_start_ofELFMAINZ
00000138 R_ARM_THM_CALL .real_start_ofELFMAINZ
00000142 R_ARM_THM_CALL .real_start_ofELFMAINZ
0000014c R_ARM_THM_CALL .real_start_ofELFMAINZ
00000154 R_ARM_THM_CALL .real_start_ofELFMAINZ
0000007c R_ARM_THM_CALL .real_start_ofELFMAINZ
0000009c R_ARM_THM_CALL .real_start_ofELFMAINZ
000000cc R_ARM_PC24 ELFMAINZ
000000ea R_ARM_THM_CALL .real_start_ofELFMAINZ
00000110 R_ARM_THM_CALL .real_start_ofELFMAINZ
00000128 R_ARM_THM_CALL .real_start_ofELFMAINZ
00000132 R_ARM_THM_CALL .real_start_ofELFMAINZ
0000013c R_ARM_THM_CALL .real_start_ofELFMAINZ
00000144 R_ARM_THM_CALL .real_start_ofELFMAINZ