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); 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) { if (opt->o_unix.preserve_build_id) {
// calc e_shoff here and write shdrout, then o_shstrtab // calc e_shoff here and write shdrout, then o_shstrtab
//NOTE: these are pushed last to ensure nothing is stepped on //NOTE: these are pushed last to ensure nothing is stepped on
//for the UPX structure. //for the UPX structure.
unsigned const len = fpad4(fo, total_out); 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); 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 // Cannot pre-round .p_memsz. If .p_filesz < .p_memsz, then kernel
// tries to make .bss, which requires PF_W. // tries to make .bss, which requires PF_W.
// But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X. // But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X.
set_te32(&elfout.phdr[C_TEXT].p_filesz, sz_pack2 + lsize); set_te32(&eho->phdr[C_TEXT].p_filesz, sz_pack2 + lsize);
elfout.phdr[C_TEXT].p_memsz = elfout.phdr[C_TEXT].p_filesz; 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 // 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. // 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 if (0!=xct_off) { // shared library
{ // Shouldn't this special case be handled earlier? { // Shouldn't this special case be handled earlier?
if (overlay_offset < xct_off) { 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)); set_te32(&phdro->p_flags, Elf32_Phdr::PF_X | get_te32(&phdro->p_flags));
} }
} }
if (!sec_arm_attr && !saved_opt_android_shlib) { if (!sec_arm_attr && !saved_opt_android_shlib) {
// Make it abunantly clear that there are no Elf32_Shdr in this shlib // Make it abunantly clear that there are no Elf32_Shdr in this shlib
elfout.ehdr.e_shoff = 0; eho->ehdr.e_shoff = 0;
set_te16(&elfout.ehdr.e_shentsize, sizeof(Elf32_Shdr)); // Android bug: cannot use 0 set_te16(&eho->ehdr.e_shentsize, sizeof(Elf32_Shdr)); // Android bug: cannot use 0
elfout.ehdr.e_shnum = 0; eho->ehdr.e_shnum = 0;
elfout.ehdr.e_shstrndx = 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->seek(linfo_off, SEEK_SET);
fo->rewrite(&linfo, sizeof(linfo)); // new info: l_checksum, l_size fo->rewrite(&linfo, sizeof(linfo)); // new info: l_checksum, l_size
if (jni_onload_va) { // FIXME Does this apply to 64-bit, too? if (jni_onload_va) {
unsigned tmp = sz_pack2 + get_te32(&elfout.phdr[C_TEXT].p_vaddr); unsigned tmp = sz_pack2 + get_te32(&eho->phdr[C_TEXT].p_vaddr);
tmp |= (Elf32_Ehdr::EM_ARM==e_machine); // THUMB mode tmp |= (Elf32_Ehdr::EM_ARM==e_machine); // THUMB mode
set_te32(&tmp, tmp); set_te32(&tmp, tmp);
fo->seek(ptr_udiff_bytes(&jni_onload_sym->st_value, file_image), SEEK_SET); 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 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)) { 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, set_te32( &phdr->p_vaddr,
reloc + get_te32(&phdr->p_vaddr)); reloc + get_te32(&phdr->p_vaddr));
set_te32( &phdr->p_paddr, set_te32( &phdr->p_paddr,
reloc + get_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)); // FIXME fo->rewrite(&elfnote, sizeof(elfnote));
} }
else { else {
fo->rewrite(&elfout, sz_elf_hdrs); fo->rewrite(eho, sz_elf_hdrs);
} }
fo->rewrite(&linfo, sizeof(linfo)); fo->rewrite(&linfo, sizeof(linfo));
} }
@ -6006,13 +6010,17 @@ void PackLinuxElf64::pack4(OutputFile *fo, Filter &ft)
overlay_offset = sz_elf_hdrs + sizeof(linfo); 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) { if (opt->o_unix.preserve_build_id) {
// calc e_shoff here and write shdrout, then o_shstrtab // calc e_shoff here and write shdrout, then o_shstrtab
//NOTE: these are pushed last to ensure nothing is stepped on //NOTE: these are pushed last to ensure nothing is stepped on
//for the UPX structure. //for the UPX structure.
unsigned const len = fpad4(fo, total_out); 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); 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 // Cannot pre-round .p_memsz. If .p_filesz < .p_memsz, then kernel
// tries to make .bss, which requires PF_W. // tries to make .bss, which requires PF_W.
// But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X. // But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X.
set_te64(&elfout.phdr[C_TEXT].p_filesz, sz_pack2 + lsize); set_te64(&eho->phdr[C_TEXT].p_filesz, sz_pack2 + lsize);
elfout.phdr[C_TEXT].p_memsz = elfout.phdr[C_TEXT].p_filesz; 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 // 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. // 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 if (0!=xct_off) { // shared library
{ // Shouldn't this special case be handled earlier? { // Shouldn't this special case be handled earlier?
if (overlay_offset < xct_off) { 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)); set_te32(&phdro->p_flags, Elf64_Phdr::PF_X | get_te32(&phdro->p_flags));
} }
} }
if (!sec_arm_attr && !saved_opt_android_shlib) { if (!sec_arm_attr && !saved_opt_android_shlib) {
// Make it abunantly clear that there are no Elf64_Shdr in this shlib // Make it abunantly clear that there are no Elf64_Shdr in this shlib
elfout.ehdr.e_shoff = 0; eho->ehdr.e_shoff = 0;
set_te16(&elfout.ehdr.e_shentsize, sizeof(Elf64_Shdr)); // Android bug: cannot use 0 set_te16(&eho->ehdr.e_shentsize, sizeof(Elf64_Shdr)); // Android bug: cannot use 0
elfout.ehdr.e_shnum = 0; eho->ehdr.e_shnum = 0;
elfout.ehdr.e_shstrndx = 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->seek(linfo_off, SEEK_SET);
fo->rewrite(&linfo, sizeof(linfo)); // new info: l_checksum, l_size fo->rewrite(&linfo, sizeof(linfo)); // new info: l_checksum, l_size
if (jni_onload_va) { // FIXME Does this apply to 64-bit, too? 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 tmp |= (Elf64_Ehdr::EM_ARM==e_machine); // THUMB mode; no-op for 64-bit
set_te64(&tmp, tmp); set_te64(&tmp, tmp);
fo->seek(ptr_udiff_bytes(&jni_onload_sym->st_value, file_image), SEEK_SET); fo->seek(ptr_udiff_bytes(&jni_onload_sym->st_value, file_image), SEEK_SET);
fo->rewrite(&tmp, sizeof(tmp)); fo->rewrite(&tmp, sizeof(tmp));
} }
} }
else { else { // not shlib
Elf64_Phdr *phdr = &elfout.phdr[C_NOTE]; Elf64_Phdr *phdr = &eho->phdr[C_NOTE];
if (PT_NOTE64 == get_te32(&phdr->p_type)) { 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, set_te64( &phdr->p_vaddr,
reloc + get_te64(&phdr->p_vaddr)); reloc + get_te64(&phdr->p_vaddr));
set_te64( &phdr->p_paddr, set_te64( &phdr->p_paddr,
reloc + get_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)); // FIXME fo->rewrite(&elfnote, sizeof(elfnote));
} }
else { else {
fo->rewrite(&elfout, sz_elf_hdrs); fo->rewrite(eho, sz_elf_hdrs);
} }
fo->rewrite(&linfo, sizeof(linfo)); fo->rewrite(&linfo, sizeof(linfo));
} }

View File

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