From 8a793d59429575f24fbf1b1f6fc5444a8b4a27b5 Mon Sep 17 00:00:00 2001 From: John Reiser Date: Wed, 4 Apr 2018 09:15:18 -0700 Subject: [PATCH] ELF shlib when no DT_INIT (especially --android-shlib) https://github.com/upx/upx/issues/191 modified: p_lx_elf.cpp modified: p_lx_elf.h --- src/p_lx_elf.cpp | 39 +++++++++++++++++++++++++++------------ src/p_lx_elf.h | 4 ++-- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index 14fc733f..75b8f4e3 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -226,6 +226,7 @@ PackLinuxElf::PackLinuxElf(InputFile *f) sz_phdrs(0), sz_elf_hdrs(0), sz_pack2(0), sz_pack2a(0), lg2_page(12), page_size(1u<=0; ++phdr) if (Elf32_Phdr::PT_DYNAMIC==get_te32(&phdr->p_type)) { dynseg= (Elf32_Dyn const *)(check_pt_dynamic(phdr) + file_image); - invert_pt_dynamic(); + invert_pt_dynamic(dynseg); break; } // elf_find_dynamic() returns 0 if 0==dynseg. @@ -758,7 +759,7 @@ PackLinuxElf64::PackLinuxElf64help1(InputFile *f) for (int j = e_phnum; --j>=0; ++phdr) if (Elf64_Phdr::PT_DYNAMIC==get_te64(&phdr->p_type)) { dynseg= (Elf64_Dyn const *)(check_pt_dynamic(phdr) + file_image); - invert_pt_dynamic(); + invert_pt_dynamic(dynseg); break; } // elf_find_dynamic() returns 0 if 0==dynseg. @@ -1539,15 +1540,20 @@ PackLinuxElf64arm::buildLoader(const Filter *ft) } void -PackLinuxElf32::invert_pt_dynamic() +PackLinuxElf32::invert_pt_dynamic(Elf32_Dyn const *dynp) { - Elf32_Dyn const *dynp= dynseg; + if (dt_table[Elf32_Dyn::DT_NULL]) { + return; // not 1st time; do not change upx_dt_init + } unsigned ndx = 1+ 0; if (dynp) - for (; Elf32_Dyn::DT_NULL != dynp->d_tag; ++ndx, ++dynp) { + for (; ; ++ndx, ++dynp) { if (dynp->d_tag < DT_NUM) { dt_table[dynp->d_tag] = ndx; } + if (Elf32_Dyn::DT_NULL == dynp->d_tag) { + break; // check here so that dt_table[DT_NULL] is set + } } upx_dt_init = 0; if (dt_table[Elf32_Dyn::DT_INIT]) upx_dt_init = Elf32_Dyn::DT_INIT; @@ -1804,7 +1810,7 @@ bool PackLinuxElf32::canPack() for (int j= e_phnum; --j>=0; ++phdr) if (Elf32_Phdr::PT_DYNAMIC==get_te32(&phdr->p_type)) { dynseg= (Elf32_Dyn const *)(check_pt_dynamic(phdr) + file_image); - invert_pt_dynamic(); + invert_pt_dynamic(dynseg); break; } // elf_find_dynamic() returns 0 if 0==dynseg. @@ -1891,6 +1897,8 @@ bool PackLinuxElf32::canPack() || (init == (strsz + strtab) && strtab == (relsz + rel )) ) { xct_va = init; + user_init_va = init; + user_init_off = elf_get_offset_from_address(init); } } // Rely on 0==elf_unsigned_dynamic(tag) if no such tag. @@ -2038,7 +2046,7 @@ PackLinuxElf64::canPack() for (int j= e_phnum; --j>=0; ++phdr) if (Elf64_Phdr::PT_DYNAMIC==get_te32(&phdr->p_type)) { dynseg= (Elf64_Dyn const *)(check_pt_dynamic(phdr) + file_image); - invert_pt_dynamic(); + invert_pt_dynamic(dynseg); break; } // elf_find_dynamic() returns 0 if 0==dynseg. @@ -2116,6 +2124,8 @@ PackLinuxElf64::canPack() || (init == (strsz + strtab) && strtab == (relsz + rel )) ) { xct_va = init; + user_init_va = init; + user_init_off = elf_get_offset_from_address(init); } } // Rely on 0==elf_unsigned_dynamic(tag) if no such tag. @@ -4051,7 +4061,7 @@ void PackLinuxElf64::unpack(OutputFile *fo) upx_uint64_t const dyn_len = get_te64(&dynhdr->p_filesz); Elf64_Dyn *dyn = (Elf64_Dyn *)((unsigned char *)ibuf + (dyn_off - load_off)); - dynseg = dyn; invert_pt_dynamic(); + dynseg = dyn; invert_pt_dynamic(dynseg); for (unsigned j2= 0; j2 < dyn_len; ++dyn, j2 += sizeof(*dyn)) { upx_uint64_t const tag = get_te64(&dyn->d_tag); upx_uint64_t val = get_te64(&dyn->d_val); @@ -4390,15 +4400,20 @@ PackLinuxElf64::check_pt_dynamic(Elf64_Phdr const *const phdr) } void -PackLinuxElf64::invert_pt_dynamic() +PackLinuxElf64::invert_pt_dynamic(Elf64_Dyn const *dynp) { - Elf64_Dyn const *dynp= dynseg; + if (dt_table[Elf64_Dyn::DT_NULL]) { + return; // not 1st time; do not change upx_dt_init + } unsigned ndx = 1+ 0; if (dynp) - for (; Elf64_Dyn::DT_NULL != dynp->d_tag; ++ndx, ++dynp) { + for (; ; ++ndx, ++dynp) { if (dynp->d_tag < DT_NUM) { dt_table[dynp->d_tag] = ndx; } + if (Elf64_Dyn::DT_NULL == dynp->d_tag) { + break; // check here so that dt_table[DT_NULL] is set + } } upx_dt_init = 0; if (dt_table[Elf64_Dyn::DT_INIT]) upx_dt_init = Elf64_Dyn::DT_INIT; @@ -4803,7 +4818,7 @@ void PackLinuxElf32::unpack(OutputFile *fo) unsigned const dyn_len = get_te32(&dynhdr->p_filesz); Elf32_Dyn *dyn = (Elf32_Dyn *)((unsigned char *)ibuf + (dyn_off - load_off)); - dynseg = dyn; invert_pt_dynamic(); + dynseg = dyn; invert_pt_dynamic(dynseg); for (unsigned j2= 0; j2 < dyn_len; ++dyn, j2 += sizeof(*dyn)) { unsigned const tag = get_te32(&dyn->d_tag); unsigned val = get_te32(&dyn->d_val); diff --git a/src/p_lx_elf.h b/src/p_lx_elf.h index d276f321..6cb4be43 100644 --- a/src/p_lx_elf.h +++ b/src/p_lx_elf.h @@ -157,7 +157,7 @@ protected: Elf32_Shdr const *elf_find_section_name(char const *) const; Elf32_Shdr const *elf_find_section_type(unsigned) const; unsigned check_pt_dynamic(Elf32_Phdr const *); - void invert_pt_dynamic(); + void invert_pt_dynamic(Elf32_Dyn const *); void const *elf_find_dynamic(unsigned) const; Elf32_Dyn const *elf_has_dynamic(unsigned) const; virtual upx_uint64_t elf_unsigned_dynamic(unsigned) const; @@ -288,7 +288,7 @@ protected: Elf64_Shdr const *elf_find_section_name(char const *) const; Elf64_Shdr const *elf_find_section_type(unsigned) const; upx_uint64_t check_pt_dynamic(Elf64_Phdr const *); - void invert_pt_dynamic(); + void invert_pt_dynamic(Elf64_Dyn const *); void const *elf_find_dynamic(unsigned) const; Elf64_Dyn const *elf_has_dynamic(unsigned) const; virtual upx_uint64_t elf_unsigned_dynamic(unsigned) const;