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

forward_Shdrs: elfout for main, lowmem for shlib

Especially Android.
https://github.com/upx/upx/issues/680
	modified:   p_lx_elf.cpp
	modified:   p_lx_elf.h
This commit is contained in:
John Reiser 2023-07-29 13:43:33 -07:00 committed by Markus F.X.J. Oberhumer
parent c3327977da
commit 41e9f7985f
2 changed files with 46 additions and 32 deletions

View File

@ -5924,13 +5924,17 @@ void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft)
overlay_offset = sz_elf_hdrs + sizeof(linfo);
}
forward_Shdrs(fo, &elfout.ehdr);
cprElfHdr4 *eho = !xct_off
? (cprElfHdr4 *)(void *)&elfout // not shlib FIXME: ugly casting
: (cprElfHdr4 *)lowmem.getVoidPtr(); // shlib
forward_Shdrs(fo, &eho->ehdr);
if (opt->o_unix.preserve_build_id) {
// calc e_shoff here and write shdrout, then o_shstrtab
//NOTE: these are pushed last to ensure nothing is stepped on
//for the UPX structure.
unsigned const len = fpad4(fo, total_out);
set_te32(&elfout.ehdr.e_shoff,len);
set_te32(&eho->ehdr.e_shoff,len);
int const ssize = sizeof(shdrout);
@ -5946,8 +5950,8 @@ void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft)
// Cannot pre-round .p_memsz. If .p_filesz < .p_memsz, then kernel
// tries to make .bss, which requires PF_W.
// But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X.
set_te32(&elfout.phdr[C_TEXT].p_filesz, sz_pack2 + lsize);
elfout.phdr[C_TEXT].p_memsz = elfout.phdr[C_TEXT].p_filesz;
set_te32(&eho->phdr[C_TEXT].p_filesz, sz_pack2 + lsize);
eho->phdr[C_TEXT].p_memsz = eho->phdr[C_TEXT].p_filesz;
// ph.u_len and ph.c_len are leftover from earliest days when there was
// only one compressed extent. Use a good analogy for multiple extents.
@ -5959,23 +5963,23 @@ void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft)
if (0!=xct_off) { // shared library
{ // Shouldn't this special case be handled earlier?
if (overlay_offset < xct_off) {
Elf32_Phdr *phdro = (Elf32_Phdr *)(&lowmem[sizeof(Elf32_Ehdr)]);
Elf32_Phdr *phdro = (Elf32_Phdr *)&eho->phdr;
set_te32(&phdro->p_flags, Elf32_Phdr::PF_X | get_te32(&phdro->p_flags));
}
}
if (!sec_arm_attr && !saved_opt_android_shlib) {
// Make it abunantly clear that there are no Elf32_Shdr in this shlib
elfout.ehdr.e_shoff = 0;
set_te16(&elfout.ehdr.e_shentsize, sizeof(Elf32_Shdr)); // Android bug: cannot use 0
elfout.ehdr.e_shnum = 0;
elfout.ehdr.e_shstrndx = 0;
eho->ehdr.e_shoff = 0;
set_te16(&eho->ehdr.e_shentsize, sizeof(Elf32_Shdr)); // Android bug: cannot use 0
eho->ehdr.e_shnum = 0;
eho->ehdr.e_shstrndx = 0;
}
fo->rewrite(&lowmem[0], sizeof(ehdri) + e_phnum * sizeof(*phdri));
fo->rewrite(eho, sizeof(ehdri) + e_phnum * sizeof(*phdri));
fo->seek(linfo_off, SEEK_SET);
fo->rewrite(&linfo, sizeof(linfo)); // new info: l_checksum, l_size
if (jni_onload_va) { // FIXME Does this apply to 64-bit, too?
unsigned tmp = sz_pack2 + get_te32(&elfout.phdr[C_TEXT].p_vaddr);
if (jni_onload_va) {
unsigned tmp = sz_pack2 + get_te32(&eho->phdr[C_TEXT].p_vaddr);
tmp |= (Elf32_Ehdr::EM_ARM==e_machine); // THUMB mode
set_te32(&tmp, tmp);
fo->seek(ptr_udiff_bytes(&jni_onload_sym->st_value, file_image), SEEK_SET);
@ -5983,18 +5987,18 @@ void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft)
}
}
else { // not shlib
Elf32_Phdr *phdr = &elfout.phdr[C_NOTE];
Elf32_Phdr *phdr = &eho->phdr[C_NOTE];
if (PT_NOTE32== get_te32(&phdr->p_type)) {
upx_uint32_t const reloc = get_te32(&elfout.phdr[C_TEXT].p_vaddr);
upx_uint32_t const reloc = get_te32(&eho->phdr[C_TEXT].p_vaddr);
set_te32( &phdr->p_vaddr,
reloc + get_te32(&phdr->p_vaddr));
set_te32( &phdr->p_paddr,
reloc + get_te32(&phdr->p_paddr));
fo->rewrite(&elfout, sz_elf_hdrs);
fo->rewrite(eho, sz_elf_hdrs);
// FIXME fo->rewrite(&elfnote, sizeof(elfnote));
}
else {
fo->rewrite(&elfout, sz_elf_hdrs);
fo->rewrite(eho, sz_elf_hdrs);
}
fo->rewrite(&linfo, sizeof(linfo));
}
@ -6006,13 +6010,17 @@ void PackLinuxElf64::pack4(OutputFile *fo, Filter &ft)
overlay_offset = sz_elf_hdrs + sizeof(linfo);
}
forward_Shdrs(fo, &elfout.ehdr);
cprElfHdr4 *eho = !xct_off
? &elfout // not shlib
: (cprElfHdr4 *)lowmem.getVoidPtr(); // shlib
forward_Shdrs(fo, &eho->ehdr);
if (opt->o_unix.preserve_build_id) {
// calc e_shoff here and write shdrout, then o_shstrtab
//NOTE: these are pushed last to ensure nothing is stepped on
//for the UPX structure.
unsigned const len = fpad4(fo, total_out);
set_te64(&elfout.ehdr.e_shoff,len);
set_te64(&eho->ehdr.e_shoff,len);
int const ssize = sizeof(shdrout);
@ -6028,8 +6036,8 @@ void PackLinuxElf64::pack4(OutputFile *fo, Filter &ft)
// Cannot pre-round .p_memsz. If .p_filesz < .p_memsz, then kernel
// tries to make .bss, which requires PF_W.
// But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X.
set_te64(&elfout.phdr[C_TEXT].p_filesz, sz_pack2 + lsize);
elfout.phdr[C_TEXT].p_memsz = elfout.phdr[C_TEXT].p_filesz;
set_te64(&eho->phdr[C_TEXT].p_filesz, sz_pack2 + lsize);
eho->phdr[C_TEXT].p_memsz = eho->phdr[C_TEXT].p_filesz;
// ph.u_len and ph.c_len are leftover from earliest days when there was
// only one compressed extent. Use a good analogy for multiple extents.
@ -6041,43 +6049,43 @@ void PackLinuxElf64::pack4(OutputFile *fo, Filter &ft)
if (0!=xct_off) { // shared library
{ // Shouldn't this special case be handled earlier?
if (overlay_offset < xct_off) {
Elf64_Phdr *phdro = (Elf64_Phdr *)(&lowmem[sizeof(Elf64_Ehdr)]);
Elf64_Phdr *phdro = (Elf64_Phdr *)(&eho->phdr);
set_te32(&phdro->p_flags, Elf64_Phdr::PF_X | get_te32(&phdro->p_flags));
}
}
if (!sec_arm_attr && !saved_opt_android_shlib) {
// Make it abunantly clear that there are no Elf64_Shdr in this shlib
elfout.ehdr.e_shoff = 0;
set_te16(&elfout.ehdr.e_shentsize, sizeof(Elf64_Shdr)); // Android bug: cannot use 0
elfout.ehdr.e_shnum = 0;
elfout.ehdr.e_shstrndx = 0;
eho->ehdr.e_shoff = 0;
set_te16(&eho->ehdr.e_shentsize, sizeof(Elf64_Shdr)); // Android bug: cannot use 0
eho->ehdr.e_shnum = 0;
eho->ehdr.e_shstrndx = 0;
}
fo->rewrite(&lowmem[0], sizeof(ehdri) + e_phnum * sizeof(*phdri));
fo->rewrite(eho, sizeof(ehdri) + e_phnum * sizeof(*phdri));
fo->seek(linfo_off, SEEK_SET);
fo->rewrite(&linfo, sizeof(linfo)); // new info: l_checksum, l_size
if (jni_onload_va) { // FIXME Does this apply to 64-bit, too?
upx_uint64_t tmp = sz_pack2 + get_te64(&elfout.phdr[C_TEXT].p_vaddr);
upx_uint64_t tmp = sz_pack2 + get_te64(&eho->phdr[C_TEXT].p_vaddr);
tmp |= (Elf64_Ehdr::EM_ARM==e_machine); // THUMB mode; no-op for 64-bit
set_te64(&tmp, tmp);
fo->seek(ptr_udiff_bytes(&jni_onload_sym->st_value, file_image), SEEK_SET);
fo->rewrite(&tmp, sizeof(tmp));
}
}
else {
Elf64_Phdr *phdr = &elfout.phdr[C_NOTE];
else { // not shlib
Elf64_Phdr *phdr = &eho->phdr[C_NOTE];
if (PT_NOTE64 == get_te32(&phdr->p_type)) {
upx_uint64_t const reloc = get_te64(&elfout.phdr[C_TEXT].p_vaddr);
upx_uint64_t const reloc = get_te64(&eho->phdr[C_TEXT].p_vaddr);
set_te64( &phdr->p_vaddr,
reloc + get_te64(&phdr->p_vaddr));
set_te64( &phdr->p_paddr,
reloc + get_te64(&phdr->p_paddr));
fo->rewrite(&elfout, sz_elf_hdrs);
fo->rewrite(eho, sz_elf_hdrs);
// FIXME fo->rewrite(&elfnote, sizeof(elfnote));
}
else {
fo->rewrite(&elfout, sz_elf_hdrs);
fo->rewrite(eho, sz_elf_hdrs);
}
fo->rewrite(&linfo, sizeof(linfo));
}

View File

@ -260,6 +260,12 @@ protected:
l_info linfo;
__packed_struct_end()
__packed_struct(cprElfHdr4)
Elf32_Ehdr ehdr;
Elf32_Phdr phdr[4];
l_info linfo;
__packed_struct_end()
__packed_struct(cprElfHdrNetBSD)
Elf32_Ehdr ehdr;
Elf32_Phdr phdr[4];