diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index ca1a33d9..2d27d9cc 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -229,8 +229,7 @@ void PackLinuxI386elf::pack1(OutputFile *fo, Filter &) fi->seek(ehdri.e_phoff, SEEK_SET); fi->readx(phdri, sz_phdrs); - generateElfHdr(fo, linux_i386elf_fold, phdri, ehdri.e_phnum, - getbrk(phdri, ehdri.e_phnum) ); + generateElfHdr(fo, linux_i386elf_fold, getbrk(phdri, ehdri.e_phnum) ); } void PackLinuxI386elf::pack2(OutputFile *fo, Filter &ft) diff --git a/src/p_lx_exc.cpp b/src/p_lx_exc.cpp index 79111379..a061abd4 100644 --- a/src/p_lx_exc.cpp +++ b/src/p_lx_exc.cpp @@ -79,43 +79,15 @@ const int *PackLinuxI386::getFilters() const return filters; } -Elf_LE32_Phdr const * -PackLinuxI386::find_DYNAMIC(Elf_LE32_Phdr const *phdr, unsigned n) -{ - if (n) do if (PT_DYNAMIC==phdr->p_type) { - return phdr; - } while (++phdr, 0!=--n); - return 0; -} - -unsigned -PackLinuxI386::find_file_offset( - unsigned const vaddr, - Elf_LE32_Phdr const *phdr, - unsigned e_phnum -) -{ - if (e_phnum) do { - unsigned t = vaddr - phdr->p_vaddr; - if (t < phdr->p_memsz) { - return t + phdr->p_offset; - } - } while (++phdr, 0!=--e_phnum); - return ~0u; -} - void PackLinuxI386::generateElfHdr( OutputFile *const fo, void const *const proto, - Elf_LE32_Phdr const *const phdr0, - unsigned e_phnum, unsigned const brka ) { cprElfHdr1 *const h1 = (cprElfHdr1 *)&elfout; cprElfHdr2 *const h2 = (cprElfHdr2 *)&elfout; - cprElfHdr3 *const h3 = (cprElfHdr3 *)&elfout; memcpy(h2, proto, sizeof(*h2)); assert(h2->ehdr.e_phoff == sizeof(Elf_LE32_Ehdr)); @@ -147,12 +119,9 @@ PackLinuxI386::generateElfHdr( fo->write(h1, sizeof(*h1)); } else if (ph.format==UPX_F_LINUX_ELF_i386) { - int const j = ((char *)&h3->phdr[2]) - (char *)h3; - memcpy(&h3->phdr[2], j + (char const *)proto, sizeof(h3->phdr[2])); - - assert(h3->ehdr.e_phnum==3); - memset(&h3->linfo, 0, sizeof(h3->linfo)); - fo->write(h3, sizeof(*h3)); + assert(h2->ehdr.e_phnum==2); + memset(&h2->linfo, 0, sizeof(h2->linfo)); + fo->write(h2, sizeof(*h2)); } else if (ph.format==UPX_F_LINUX_SH_i386) { assert(h2->ehdr.e_phnum==1); @@ -163,99 +132,6 @@ PackLinuxI386::generateElfHdr( else { assert(false); // unknown ph.format, PackUnix::generateElfHdr } - - Elf_LE32_Phdr const *const phdrdyn = find_DYNAMIC(phdr0, e_phnum); - if (phdrdyn) { // propagate DT_NEEDED - MemBuffer dynhdr(phdrdyn->p_memsz); - fi->seek(phdrdyn->p_offset, SEEK_SET); - fi->read(dynhdr, phdrdyn->p_memsz); - - unsigned strtabx = ~0u; - unsigned strsz = 0; - int j; - - Elf_LE32_Dyn const *p = (Elf_LE32_Dyn const *)(unsigned char *)dynhdr; - int so_needed = 0; - for (j = phdrdyn->p_memsz / sizeof(*p); --j>=0; ++p) { - if (p->d_tag==DT_NEEDED) { - so_needed++; - } - if (p->d_tag==DT_STRTAB) { - strtabx = find_file_offset(p->d_val, phdr0, e_phnum); - } - if (p->d_tag==DT_STRSZ) { - strsz= p->d_val; - } - } - - if (so_needed) { - assert(0!=strsz && ~0u!=strtabx); - MemBuffer strtab(strsz); - fi->seek(strtabx, SEEK_SET); - fi->read(strtab, strsz); - - int c_needed = 1; // index 0 is reserved - p = (Elf_LE32_Dyn const *)(unsigned char *)dynhdr; - for (j = phdrdyn->p_memsz / sizeof(*p); --j>=0; ++p) { - if (p->d_tag==DT_NEEDED) { - c_needed += 1+ strlen(p->d_val + strtab); - } - } - - MemBuffer newtab(c_needed); - unsigned char *cp = newtab; - *cp++ = 0; - p = (Elf_LE32_Dyn const *)(unsigned char *)dynhdr; - for (j = phdrdyn->p_memsz / sizeof(*p); --j>=0; ++p) { - if (p->d_tag==DT_NEEDED) { - unsigned char const *const str = p->d_val + strtab; - unsigned const len = 1+ strlen(str); - memcpy(cp, str, len); - cp += len; - } - } - Elf_LE32_Dyn outdyn[3 + so_needed], *q = &outdyn[0]; - q->d_tag = DT_STRSZ; - q->d_val = c_needed; // + identsize; - ++q; - q->d_tag = DT_STRTAB; - q->d_val = sizeof(*h3) + sizeof(outdyn) + h3->phdr[0].p_vaddr; - ++q; - cp = 1+ newtab; - for (j= so_needed; --j>=0; ++q) { - q->d_tag = DT_NEEDED; q->d_val = cp - newtab; - cp += 1+ strlen(cp); - } - q->d_tag = DT_NULL; q->d_val = 0; - h3->phdr[2].p_type = PT_DYNAMIC; - h3->phdr[2].p_offset = sizeof(*h3); - h3->phdr[2].p_vaddr = sizeof(*h3) + h3->phdr[0].p_vaddr; - h3->phdr[2].p_paddr = h3->phdr[2].p_vaddr; - h3->phdr[2].p_filesz = sizeof(outdyn) + c_needed; // + identsize; - h3->phdr[2].p_memsz = h3->phdr[2].p_filesz; - h3->phdr[2].p_flags = Elf_LE32_Phdr::PF_R; - h3->phdr[2].p_align = 4; - pt_dynamic.alloc(h3->phdr[2].p_filesz); - - j = 0; - memcpy(j + pt_dynamic, &outdyn[0], sizeof(outdyn)); - j += sizeof(outdyn); - memcpy(j + pt_dynamic, newtab, c_needed); - j += c_needed; -#if 0 //{ - memcpy(j + pt_dynamic, ident, identsize); - // FIXME ?? patchVersion(j + pt_dynamic, identsize); - j += identsize; -#endif //} - sz_dynamic = j; - -#if 0 //{ debugging: see the results early - fo->seek(0, SEEK_SET); - fo->write(h3, sizeof(*h3)); -#endif //} - fo->write(pt_dynamic, sz_dynamic); - } - } } void @@ -264,7 +140,7 @@ PackLinuxI386::pack1(OutputFile *fo, Filter &) // create a pseudo-unique program id for our paranoid stub progid = getRandomId(); - generateElfHdr(fo, linux_i386exec_fold, 0, 0, 0); + generateElfHdr(fo, linux_i386exec_fold, 0); } void diff --git a/src/p_lx_exc.h b/src/p_lx_exc.h index 20d0bd6e..4903cb6a 100644 --- a/src/p_lx_exc.h +++ b/src/p_lx_exc.h @@ -42,8 +42,6 @@ public: virtual void generateElfHdr( OutputFile *, void const *proto, - Elf_LE32_Phdr const *const phdr0, - unsigned e_phnum, unsigned brka ); virtual int getFormat() const { return UPX_F_LINUX_i386; } @@ -60,13 +58,6 @@ protected: // virtual void pack3(OutputFile *, Filter &); // append loader virtual void pack4(OutputFile *, Filter &); // append PackHeader - unsigned find_file_offset( - unsigned vaddr, - Elf_LE32_Phdr const *phdr, - unsigned e_phnum - ); - Elf_LE32_Phdr const *find_DYNAMIC(Elf_LE32_Phdr const *phdr, unsigned n); - // loader util virtual int getLoaderPrefixSize() const; virtual int buildLinuxLoader( diff --git a/src/p_lx_sh.cpp b/src/p_lx_sh.cpp index 6b5a6c8d..30cf7e4f 100644 --- a/src/p_lx_sh.cpp +++ b/src/p_lx_sh.cpp @@ -134,7 +134,7 @@ bool PackLinuxI386sh::canPack() void PackLinuxI386sh::pack1(OutputFile *fo, Filter &) { - generateElfHdr(fo, linux_i386sh_fold, 0, 0, 0x08048000); + generateElfHdr(fo, linux_i386sh_fold, 0x08048000); } /* diff --git a/src/stub/fold_elf86.asm b/src/stub/fold_elf86.asm index 4bec2919..2d5f0802 100644 --- a/src/stub/fold_elf86.asm +++ b/src/stub/fold_elf86.asm @@ -28,6 +28,7 @@ %define szElf32_Phdr 8*4 %define e_entry (16 + 2*2 + 4) %define p_memsz 5*4 +%define szb_info 12 %define szl_info 12 %define szp_info 12 %define a_val 4 @@ -57,19 +58,20 @@ fold_begin: ; enter: %ebx= &Elf32_Ehdr of this program mov edi, esp call do_auxv - mov eax, [p_memsz + 2*szElf32_Phdr + szElf32_Ehdr + ebx] ; size of PT_DYNAMIC + push ebx ; save &Elf32_Ehdr of this stub sub esp, dword MAX_ELF_HDR + OVERHEAD - mov ecx, [e_entry + ebx] ; beyond compressed data - push esp ; argument: temp space - lea eax, [szElf32_Ehdr + 3*szElf32_Phdr + szl_info + szp_info + ebx + eax] ; 1st &b_info - push edi ; argument: AT_next - sub ecx, eax ; length of compressed data - push ebp ; argument: &decompress - push ecx ; argument: sz_compressed - push eax ; argument: 1st &b_info + lea eax, [szElf32_Ehdr + 2*szElf32_Phdr + szl_info + szp_info + ebx] ; 1st &b_info + mov esi, [e_entry + ebx] ; beyond compressed data + sub esi, eax ; length of compressed data + mov ebx, [ eax] ; length of uncompressed ELF headers + mov edx, esp ; + mov ecx, [4+ eax] ; length of compressed ELF headers + add ecx, byte szb_info + pusha ; (AT_next, sz_cpr, f_expand, &tmp_ehdr, {sz_unc, &tmp}, {sz_cpr, &b1st_info} ) EXTERN upx_main - call upx_main ; entry = upx_main(b1st_info, sz_cpr, &decompress, AT_next, tmp_ehdr) - add esp, dword 5*4 + MAX_ELF_HDR + OVERHEAD ; remove 5 params, temp space + call upx_main ; returns entry address + add esp, dword 8*4 + MAX_ELF_HDR + OVERHEAD ; remove 8 params, temp space + pop ebx ; &Elf32_Ehdr of this stub push eax ; save entry address mov edi, [a_val + edi] ; AT_PHDR diff --git a/src/stub/l_lx_elf.c b/src/stub/l_lx_elf.c index f227761d..6a27626e 100644 --- a/src/stub/l_lx_elf.c +++ b/src/stub/l_lx_elf.c @@ -316,35 +316,30 @@ ERR_LAB **************************************************************************/ void *upx_main( - char /*const*/ *const b1st_info, + Elf32_auxv_t *const av, unsigned const sz_compressed, f_expand *const f_decompress, - Elf32_auxv_t *const av, - Elf32_Ehdr *const ehdr + Elf32_Ehdr *const ehdr, + struct Extent xo, + struct Extent xi ) __asm__("upx_main"); void *upx_main( - char /*const*/ *const b1st_info, + Elf32_auxv_t *const av, unsigned const sz_compressed, f_expand *const f_decompress, - Elf32_auxv_t *const av, - Elf32_Ehdr *const ehdr // temp char[MAX_ELF_HDR+OVERHEAD] + Elf32_Ehdr *const ehdr, // temp char[MAX_ELF_HDR+OVERHEAD] + struct Extent xo, // {sz_unc, ehdr} for ELF headers + struct Extent xi // {sz_cpr, &b_info} for ELF headers ) { - Elf32_Phdr const *phdr = (Elf32_Phdr const *)(1+ehdr); + Elf32_Phdr const *phdr = (Elf32_Phdr const *)(1+ ehdr); Elf32_Addr entry; - struct Extent xo; - struct Extent xi = { 0, b1st_info }; // location of 1st b_info - - // sizeof(Ehdr+Phdrs), uncompressed - size_t const sz_elfhdrs = ((size_t *)xi.buf)[0]; // sizeof(Ehdr+Phdrs), compressed; including b_info header - size_t const sz_pckhdrs = sizeof(struct b_info) + ((size_t *)xi.buf)[1]; + size_t const sz_pckhdrs = xi.size; // Uncompress Ehdr and Phdrs. - xo.size = sz_elfhdrs; xo.buf = (char *)ehdr; - xi.size = sz_pckhdrs; unpackExtent(&xi, &xo, f_decompress, 0); // Prepare to decompress the Elf headers again, into the first PT_LOAD. diff --git a/src/stub/l_lx_elf86.lds b/src/stub/l_lx_elf86.lds index 9f0f088d..6a3eb780 100644 --- a/src/stub/l_lx_elf86.lds +++ b/src/stub/l_lx_elf86.lds @@ -32,7 +32,8 @@ PHDRS { text PT_LOAD FILEHDR PHDRS ; data PT_LOAD ; /* for setting brk(0) */ - null PT_NULL; /* changed to PT_DYNAMIC for ldd */ + /* 3rd Phdr was not worth it; use "upx -d" first, then apply ldd */ + /*null PT_NULL;*/ /* changed to PT_DYNAMIC for ldd */ } SECTIONS {