From 179f4b3439bb6a982bd16a264cf3f57d447fbb86 Mon Sep 17 00:00:00 2001 From: bitraid Date: Mon, 13 Apr 2020 21:38:22 +0300 Subject: [PATCH 1/6] Don't use --strip-reloc with -d Always restore the relocation section of Portable Executables on unpacking, if it exists in the compressed image. --- src/pefile.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/pefile.cpp b/src/pefile.cpp index 571c3529..1988321f 100644 --- a/src/pefile.cpp +++ b/src/pefile.cpp @@ -2693,15 +2693,7 @@ void PeFile::rebuildRelocs(upx_byte *& extrainfo, unsigned bits, } rel.finish (oxrelocs,soxrelocs); - if (opt->win32_pe.strip_relocs && !isdll) - { - obuf.clear(ODADDR(PEDIR_RELOC) - rvamin, ODSIZE(PEDIR_RELOC)); - ODADDR(PEDIR_RELOC) = 0; - soxrelocs = 0; - // FIXME: try to remove the original relocation section somehow - } - else - omemcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs); + omemcpy(obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs); delete [] oxrelocs; oxrelocs = NULL; wrkmem.dealloc(); @@ -2933,12 +2925,8 @@ void PeFile::unpack0(OutputFile *fo, const ht &ih, ht &oh, ft.unfilter(obuf + oh.codebase - rvamin, oh.codesize); } - //NEW: disable reloc stripping if ASLR is enabled - if(ih.dllflags & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE) - opt->win32_pe.strip_relocs = false; - // FIXME: ih.flags is checked here because of a bug in UPX 0.92 - if ((opt->win32_pe.strip_relocs && !isdll) || (ih.flags & RELOCS_STRIPPED)) + if (ih.flags & RELOCS_STRIPPED) { oh.flags |= RELOCS_STRIPPED; ODADDR(PEDIR_RELOC) = 0; From c8386ee47db1bb2ad702eadcdb8b13f2b2dc57d8 Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sat, 23 May 2020 09:41:41 -0700 Subject: [PATCH 2/6] More checking of DT_GNU_HASH and DT_HASH tables https://github.com/upx/upx/issues/380 modified: p_lx_elf.cpp --- src/p_lx_elf.cpp | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index fb3506bc..0ddf9798 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -312,6 +312,9 @@ PackLinuxElf32::PackLinuxElf32help1(InputFile *f) dynsym = (Elf32_Sym const *)elf_find_dynamic(Elf32_Dyn::DT_SYMTAB); gashtab = (unsigned const *)elf_find_dynamic(Elf32_Dyn::DT_GNU_HASH); hashtab = (unsigned const *)elf_find_dynamic(Elf32_Dyn::DT_HASH); + if (3& ((unsigned)(long)dynsym | (unsigned)(long)gashtab | (unsigned)(long)hashtab)) { + throwCantPack("unaligned DT_SYMTAB, DT_GNU_HASH, or DT_HASH/n"); + } jni_onload_sym = elf_lookup("JNI_OnLoad"); if (jni_onload_sym) { jni_onload_va = get_te32(&jni_onload_sym->st_value); @@ -802,6 +805,9 @@ PackLinuxElf64::PackLinuxElf64help1(InputFile *f) dynsym = (Elf64_Sym const *)elf_find_dynamic(Elf64_Dyn::DT_SYMTAB); gashtab = (unsigned const *)elf_find_dynamic(Elf64_Dyn::DT_GNU_HASH); hashtab = (unsigned const *)elf_find_dynamic(Elf64_Dyn::DT_HASH); + if (3& ((unsigned)(long)dynsym | (unsigned)(long)gashtab | (unsigned)(long)hashtab)) { + throwCantPack("unaligned DT_SYMTAB, DT_GNU_HASH, or DT_HASH/n"); + } jni_onload_sym = elf_lookup("JNI_OnLoad"); if (jni_onload_sym) { jni_onload_va = get_te64(&jni_onload_sym->st_value); @@ -5345,6 +5351,12 @@ Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const unsigned const *const buckets = &hashtab[2]; unsigned const *const chains = &buckets[nbucket]; unsigned const m = elf_hash(name) % nbucket; + if ((unsigned)(file_size - ((char const *)buckets - (char const *)(void const *)file_image)) + <= sizeof(unsigned)*nbucket ) { + char msg[80]; snprintf(msg, sizeof(msg), + "bad nbucket %#x\n", nbucket); + throwCantPack(msg); + } unsigned si; for (si= get_te32(&buckets[m]); 0!=si; si= get_te32(&chains[si])) { char const *const p= get_dynsym_name(si, (unsigned)-1); @@ -5361,6 +5373,12 @@ Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const unsigned const *const bitmask = &gashtab[4]; unsigned const *const buckets = &bitmask[n_bitmask]; unsigned const *const hasharr = &buckets[n_bucket]; + if ((unsigned)(file_size - ((char const *)bitmask - (char const *)(void const *)file_image)) + <= sizeof(unsigned)*n_bitmask ) { + char msg[80]; snprintf(msg, sizeof(msg), + "bad n_bitmask %#x\n", n_bitmask); + throwCantPack(msg); + } unsigned const h = gnu_hash(name); unsigned const hbit1 = 037& h; @@ -5385,7 +5403,9 @@ Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const if (0==strcmp(name, p)) { return dsp; } - } while (++dsp, 0==(1u& get_te32(hp++))); + } while (++dsp, + (char const *)hp < (char const *)&file_image[file_size] + && 0==(1u& get_te32(hp++))); } } } @@ -5400,6 +5420,12 @@ Elf64_Sym const *PackLinuxElf64::elf_lookup(char const *name) const unsigned const *const buckets = &hashtab[2]; unsigned const *const chains = &buckets[nbucket]; unsigned const m = elf_hash(name) % nbucket; + if ((unsigned)(file_size - ((char const *)buckets - (char const *)(void const *)file_image)) + <= sizeof(unsigned)*nbucket ) { + char msg[80]; snprintf(msg, sizeof(msg), + "bad nbucket %#x\n", nbucket); + throwCantPack(msg); + } unsigned si; for (si= get_te32(&buckets[m]); 0!=si; si= get_te32(&chains[si])) { char const *const p= get_dynsym_name(si, (unsigned)-1); @@ -5416,6 +5442,12 @@ Elf64_Sym const *PackLinuxElf64::elf_lookup(char const *name) const upx_uint64_t const *const bitmask = (upx_uint64_t const *)(void const *)&gashtab[4]; unsigned const *const buckets = (unsigned const *)&bitmask[n_bitmask]; unsigned const *const hasharr = &buckets[n_bucket]; + if ((unsigned)(file_size - ((char const *)bitmask - (char const *)(void const *)file_image)) + <= sizeof(unsigned)*n_bitmask ) { + char msg[80]; snprintf(msg, sizeof(msg), + "bad n_bitmask %#x\n", n_bitmask); + throwCantPack(msg); + } unsigned const h = gnu_hash(name); unsigned const hbit1 = 077& h; @@ -5440,7 +5472,9 @@ Elf64_Sym const *PackLinuxElf64::elf_lookup(char const *name) const if (0==strcmp(name, p)) { return dsp; } - } while (++dsp, 0==(1u& get_te32(hp++))); + } while (++dsp, + (char const *)hp < (char const *)&file_image[file_size] + && 0==(1u& get_te32(hp++))); } } } From da37435384dd5c277d83e8cbba47f4e8462e113b Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sat, 23 May 2020 10:04:38 -0700 Subject: [PATCH 3/6] More checking of DT_GNU_HASH and DT_HASH tables https://github.com/upx/upx/issues/381 modified: p_lx_elf.cpp --- src/p_lx_elf.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index 0ddf9798..bee683d7 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -5351,7 +5351,8 @@ Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const unsigned const *const buckets = &hashtab[2]; unsigned const *const chains = &buckets[nbucket]; unsigned const m = elf_hash(name) % nbucket; - if ((unsigned)(file_size - ((char const *)buckets - (char const *)(void const *)file_image)) + if (!nbucket + || (unsigned)(file_size - ((char const *)buckets - (char const *)(void const *)file_image)) <= sizeof(unsigned)*nbucket ) { char msg[80]; snprintf(msg, sizeof(msg), "bad nbucket %#x\n", nbucket); @@ -5373,7 +5374,14 @@ Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const unsigned const *const bitmask = &gashtab[4]; unsigned const *const buckets = &bitmask[n_bitmask]; unsigned const *const hasharr = &buckets[n_bucket]; - if ((unsigned)(file_size - ((char const *)bitmask - (char const *)(void const *)file_image)) + if (!n_bucket + || (void const *)&file_image[file_size] <= (void const *)hasharr) { + char msg[80]; snprintf(msg, sizeof(msg), + "bad n_bucket %#x\n", n_bucket); + throwCantPack(msg); + } + if (!n_bitmask + || (unsigned)(file_size - ((char const *)bitmask - (char const *)(void const *)file_image)) <= sizeof(unsigned)*n_bitmask ) { char msg[80]; snprintf(msg, sizeof(msg), "bad n_bitmask %#x\n", n_bitmask); @@ -5420,7 +5428,8 @@ Elf64_Sym const *PackLinuxElf64::elf_lookup(char const *name) const unsigned const *const buckets = &hashtab[2]; unsigned const *const chains = &buckets[nbucket]; unsigned const m = elf_hash(name) % nbucket; - if ((unsigned)(file_size - ((char const *)buckets - (char const *)(void const *)file_image)) + if (!nbucket + || (unsigned)(file_size - ((char const *)buckets - (char const *)(void const *)file_image)) <= sizeof(unsigned)*nbucket ) { char msg[80]; snprintf(msg, sizeof(msg), "bad nbucket %#x\n", nbucket); @@ -5442,7 +5451,14 @@ Elf64_Sym const *PackLinuxElf64::elf_lookup(char const *name) const upx_uint64_t const *const bitmask = (upx_uint64_t const *)(void const *)&gashtab[4]; unsigned const *const buckets = (unsigned const *)&bitmask[n_bitmask]; unsigned const *const hasharr = &buckets[n_bucket]; - if ((unsigned)(file_size - ((char const *)bitmask - (char const *)(void const *)file_image)) + if (!n_bucket + || (void const *)&file_image[file_size] <= (void const *)hasharr) { + char msg[80]; snprintf(msg, sizeof(msg), + "bad n_bucket %#x\n", n_bucket); + throwCantPack(msg); + } + if (!n_bitmask + || (unsigned)(file_size - ((char const *)bitmask - (char const *)(void const *)file_image)) <= sizeof(unsigned)*n_bitmask ) { char msg[80]; snprintf(msg, sizeof(msg), "bad n_bitmask %#x\n", n_bitmask); From 3d87b34754bbac3e171600be396ec652794b2cfa Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sat, 23 May 2020 10:51:03 -0700 Subject: [PATCH 4/6] invert_pt_dynamic() more checking https://github.com/upx/upx/issues/378 https://github.com/upx/upx/issues/379 modified: p_lx_elf.cpp --- src/p_lx_elf.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index bee683d7..c9778362 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -1687,6 +1687,12 @@ PackLinuxElf32::invert_pt_dynamic(Elf32_Dyn const *dynp) unsigned const *const bitmask = (unsigned const *)(void const *)&gashtab[4]; unsigned const *const buckets = (unsigned const *)&bitmask[n_bitmask]; unsigned const *const hasharr = &buckets[n_bucket]; (void)hasharr; + if (!n_bucket || (1u<<31) <= n_bucket /* fie on fuzzers */ + || (void const *)&file_image[file_size] <= (void const *)hasharr) { + char msg[80]; snprintf(msg, sizeof(msg), + "bad n_bucket %#x\n", n_bucket); + throwCantPack(msg); + } //unsigned const *const gashend = &hasharr[n_bucket]; // minimum, except: // Rust and Android trim unused zeroes from high end of hasharr[] unsigned bmax = 0; @@ -5238,6 +5244,12 @@ PackLinuxElf64::invert_pt_dynamic(Elf64_Dyn const *dynp) upx_uint64_t const *const bitmask = (upx_uint64_t const *)(void const *)&gashtab[4]; unsigned const *const buckets = (unsigned const *)&bitmask[n_bitmask]; unsigned const *const hasharr = &buckets[n_bucket]; (void)hasharr; + if (!n_bucket || (1u<<31) <= n_bucket /* fie on fuzzers */ + || (void const *)&file_image[file_size] <= (void const *)hasharr) { + char msg[80]; snprintf(msg, sizeof(msg), + "bad n_bucket %#x\n", n_bucket); + throwCantPack(msg); + } //unsigned const *const gashend = &hasharr[n_bucket]; // minimum, except: // Rust and Android trim unused zeroes from high end of hasharr[] unsigned bmax = 0; From a3594698e2a380b81b4b3c88a24e7dffdd4e27e4 Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sat, 23 May 2020 11:02:46 -0700 Subject: [PATCH 5/6] uintptr_t for MSVC modified: p_lx_elf.cpp --- src/p_lx_elf.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index c9778362..bfcbe809 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -312,7 +312,7 @@ PackLinuxElf32::PackLinuxElf32help1(InputFile *f) dynsym = (Elf32_Sym const *)elf_find_dynamic(Elf32_Dyn::DT_SYMTAB); gashtab = (unsigned const *)elf_find_dynamic(Elf32_Dyn::DT_GNU_HASH); hashtab = (unsigned const *)elf_find_dynamic(Elf32_Dyn::DT_HASH); - if (3& ((unsigned)(long)dynsym | (unsigned)(long)gashtab | (unsigned)(long)hashtab)) { + if (3& ((uintptr_t)dynsym | (uintptr_t)gashtab | (uintptr_t)hashtab)) { throwCantPack("unaligned DT_SYMTAB, DT_GNU_HASH, or DT_HASH/n"); } jni_onload_sym = elf_lookup("JNI_OnLoad"); @@ -805,7 +805,7 @@ PackLinuxElf64::PackLinuxElf64help1(InputFile *f) dynsym = (Elf64_Sym const *)elf_find_dynamic(Elf64_Dyn::DT_SYMTAB); gashtab = (unsigned const *)elf_find_dynamic(Elf64_Dyn::DT_GNU_HASH); hashtab = (unsigned const *)elf_find_dynamic(Elf64_Dyn::DT_HASH); - if (3& ((unsigned)(long)dynsym | (unsigned)(long)gashtab | (unsigned)(long)hashtab)) { + if (3& ((uintptr_t)dynsym | (uintptr_t)gashtab | (uintptr_t)hashtab)) { throwCantPack("unaligned DT_SYMTAB, DT_GNU_HASH, or DT_HASH/n"); } jni_onload_sym = elf_lookup("JNI_OnLoad"); From 78c3f58f508e6013c4707a4cc8d3cdad85f0b0cb Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Sat, 23 May 2020 20:07:23 +0200 Subject: [PATCH 6/6] Use "python2" instead of "python". --- src/p_lx_sh.cpp | 2 +- src/stub/Makefile | 2 +- src/stub/scripts/bin2h.py | 2 +- src/stub/scripts/brandelf.py | 2 +- src/stub/scripts/gpp_inc.py | 2 +- src/stub/scripts/xstrip.py | 2 +- src/stub/src/arch/i086/cleanasm.py | 2 +- src/stub/src/arch/i086/wdis2gas.py | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/p_lx_sh.cpp b/src/p_lx_sh.cpp index 70e6fdc3..30c60dcc 100644 --- a/src/p_lx_sh.cpp +++ b/src/p_lx_sh.cpp @@ -114,7 +114,7 @@ bool PackLinuxI386sh::getShellName(char *buf) buf[l_shname] = 0; static char const *const shname[] = { // known shells that accept "-c" arg "ash", "bash", "bsh", "csh", "ksh", "pdksh", "sh", "tcsh", "zsh", - "python", + "python", "python2", "python3", NULL }; const char *bname = strrchr(buf, '/'); diff --git a/src/stub/Makefile b/src/stub/Makefile index 0add5541..134e0b2c 100644 --- a/src/stub/Makefile +++ b/src/stub/Makefile @@ -206,7 +206,7 @@ tc_objdump_disasm_options = ECHO_e = /bin/echo -e ECHO_E = /bin/echo -E PERL = perl -PYTHON = python +PYTHON = python2 UNIX2DOS := $(PERL) -i -pe 's/$$/\r/;' # trim (strip) trailing whitespace diff --git a/src/stub/scripts/bin2h.py b/src/stub/scripts/bin2h.py index d47e73d5..b30e3c89 100644 --- a/src/stub/scripts/bin2h.py +++ b/src/stub/scripts/bin2h.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python2 ## vim:set ts=4 sw=4 et: -*- coding: utf-8 -*- # # bin2h.py -- diff --git a/src/stub/scripts/brandelf.py b/src/stub/scripts/brandelf.py index 508ee5f2..bcafb111 100644 --- a/src/stub/scripts/brandelf.py +++ b/src/stub/scripts/brandelf.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python2 ## vim:set ts=4 sw=4 et: -*- coding: utf-8 -*- # # brandelf.py -- diff --git a/src/stub/scripts/gpp_inc.py b/src/stub/scripts/gpp_inc.py index f183fa51..3c0a9083 100644 --- a/src/stub/scripts/gpp_inc.py +++ b/src/stub/scripts/gpp_inc.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python2 ## vim:set ts=4 sw=4 et: -*- coding: utf-8 -*- # # gpp_inc.py -- Generic PreProcessor: include diff --git a/src/stub/scripts/xstrip.py b/src/stub/scripts/xstrip.py index 29d2169f..2d8c07c3 100644 --- a/src/stub/scripts/xstrip.py +++ b/src/stub/scripts/xstrip.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python2 ## vim:set ts=4 sw=4 et: -*- coding: utf-8 -*- # # xstrip.py -- truncate ELF objects created by multiarch-objcopy-2.17 diff --git a/src/stub/src/arch/i086/cleanasm.py b/src/stub/src/arch/i086/cleanasm.py index c10f2f87..605b4db4 100644 --- a/src/stub/src/arch/i086/cleanasm.py +++ b/src/stub/src/arch/i086/cleanasm.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python2 ## vim:set ts=4 sw=4 et: -*- coding: utf-8 -*- # # cleanasm.py -- diff --git a/src/stub/src/arch/i086/wdis2gas.py b/src/stub/src/arch/i086/wdis2gas.py index b0a377d8..e99c7530 100644 --- a/src/stub/src/arch/i086/wdis2gas.py +++ b/src/stub/src/arch/i086/wdis2gas.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python2 ## vim:set ts=4 sw=4 et: -*- coding: utf-8 -*- # # wdis2gas.py --