Check symbol number and .st_name
https://github.com/upx/upx/issues/235 POC1,POC3,POC7,POC9 modified: p_elf_enum.h modified: p_lx_elf.h modified: p_lx_elf.cpp
This commit is contained in:
parent
75c31dff1d
commit
606ad08dd1
@ -155,12 +155,14 @@
|
||||
DT_RELA = 7, /* Relocations which do contain an addend */
|
||||
DT_RELASZ = 8, /* Total size of Rela relocs */
|
||||
DT_RELAENT = 9, /* Size of one RELA relocation */
|
||||
DT_STRSZ = 10, /* Size of string table */
|
||||
DT_SYMENT = 11, /* Size of one symbol table entry */
|
||||
DT_INIT = 12, /* Address of init function */
|
||||
DT_FINI = 13, /* Address of termination function */
|
||||
|
||||
DT_REL = 17, /* Relocations which contain no addend */
|
||||
DT_RELSZ = 18, /* Total size of Rel relocs */
|
||||
DT_RELENT = 19, /* Size of one Rel relocation */
|
||||
DT_STRSZ = 10, /* Sizeof string table */
|
||||
DT_PLTREL = 20, /* Type of reloc in PLT */
|
||||
DT_TEXTREL = 22, /* Reloc might modify .text */
|
||||
DT_JMPREL = 23, /* Address of PLT relocs */
|
||||
|
||||
@ -672,6 +672,7 @@ PackLinuxElf32::PackLinuxElf32(InputFile *f)
|
||||
jni_onload_sym(NULL),
|
||||
shstrtab(NULL),
|
||||
sec_strndx(NULL), sec_dynsym(NULL), sec_dynstr(NULL)
|
||||
, symnum_end(0)
|
||||
{
|
||||
memset(&ehdri, 0, sizeof(ehdri));
|
||||
if (f) {
|
||||
@ -693,6 +694,7 @@ PackLinuxElf64::PackLinuxElf64(InputFile *f)
|
||||
jni_onload_sym(NULL),
|
||||
shstrtab(NULL),
|
||||
sec_strndx(NULL), sec_dynsym(NULL), sec_dynstr(NULL)
|
||||
, symnum_end(0)
|
||||
{
|
||||
memset(&ehdri, 0, sizeof(ehdri));
|
||||
if (f) {
|
||||
@ -1558,6 +1560,7 @@ PackLinuxElf32::invert_pt_dynamic(Elf32_Dyn const *dynp)
|
||||
if (dt_table[Elf32_Dyn::DT_NULL]) {
|
||||
return; // not 1st time; do not change upx_dt_init
|
||||
}
|
||||
Elf32_Dyn const *const dynp0 = dynp;
|
||||
unsigned ndx = 1+ 0;
|
||||
if (dynp)
|
||||
for (; ; ++ndx, ++dynp) {
|
||||
@ -1573,6 +1576,28 @@ PackLinuxElf32::invert_pt_dynamic(Elf32_Dyn const *dynp)
|
||||
if (dt_table[Elf32_Dyn::DT_INIT]) upx_dt_init = Elf32_Dyn::DT_INIT;
|
||||
else if (dt_table[Elf32_Dyn::DT_PREINIT_ARRAY]) upx_dt_init = Elf32_Dyn::DT_PREINIT_ARRAY;
|
||||
else if (dt_table[Elf32_Dyn::DT_INIT_ARRAY]) upx_dt_init = Elf32_Dyn::DT_INIT_ARRAY;
|
||||
|
||||
unsigned const z_str = dt_table[Elf32_Dyn::DT_STRSZ];
|
||||
if (z_str) {
|
||||
strtab_end = get_te32(&dynp0[-1+ z_str].d_val);
|
||||
if (file_size <= strtab_end) { // FIXME: not tight enough
|
||||
char msg[50]; snprintf(msg, sizeof(msg),
|
||||
"bad DT_STRSZ %#x", strtab_end);
|
||||
throwCantPack(msg);
|
||||
}
|
||||
}
|
||||
unsigned const x_sym = dt_table[Elf32_Dyn::DT_SYMTAB];
|
||||
unsigned const x_str = dt_table[Elf32_Dyn::DT_STRTAB];
|
||||
if (x_sym && x_str) {
|
||||
upx_uint32_t const v_sym = get_te32(&dynp0[-1+ x_sym].d_val);
|
||||
upx_uint32_t const v_str = get_te32(&dynp0[-1+ x_str].d_val);
|
||||
unsigned const z_sym = dt_table[Elf32_Dyn::DT_SYMENT];
|
||||
unsigned const sz_sym = !z_sym ? sizeof(Elf32_Sym)
|
||||
: get_te32(&dynp0[-1+ z_sym].d_val);
|
||||
if (v_sym < v_str) {
|
||||
symnum_end = (v_str - v_sym) / sz_sym;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Elf32_Phdr const *
|
||||
@ -1666,14 +1691,30 @@ Elf64_Shdr const *PackLinuxElf64::elf_find_section_type(
|
||||
return 0;
|
||||
}
|
||||
|
||||
char const *PackLinuxElf64::get_dynsym_name(unsigned symnum, unsigned relnum) const
|
||||
{
|
||||
if (symnum_end <= symnum) {
|
||||
char msg[50]; snprintf(msg, sizeof(msg),
|
||||
"bad symnum %#x in Elf64_Rel[%d]\n", symnum, relnum);
|
||||
throwCantPack(msg);
|
||||
}
|
||||
unsigned st_name = get_te64(&dynsym[symnum].st_name);
|
||||
if (strtab_end <= st_name) {
|
||||
char msg[50]; snprintf(msg, sizeof(msg),
|
||||
"bad .st_name %#x in DT_STRTAB[%d]\n", st_name, symnum);
|
||||
throwCantPack(msg);
|
||||
}
|
||||
return &dynstr[st_name];
|
||||
}
|
||||
|
||||
bool PackLinuxElf64::calls_crt1(Elf64_Rela const *rela, int sz)
|
||||
{
|
||||
if (!dynsym || !dynstr) {
|
||||
return false;
|
||||
}
|
||||
for (; 0 < sz; (sz -= sizeof(Elf64_Rela)), ++rela) {
|
||||
for (unsigned relnum= 0; 0 < sz; (sz -= sizeof(Elf64_Rela)), ++rela, ++relnum) {
|
||||
unsigned const symnum = get_te64(&rela->r_info) >> 32;
|
||||
char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr;
|
||||
char const *const symnam = get_dynsym_name(symnum, relnum);
|
||||
if (0==strcmp(symnam, "__libc_start_main") // glibc
|
||||
|| 0==strcmp(symnam, "__libc_init") // Android
|
||||
|| 0==strcmp(symnam, "__uClibc_main")
|
||||
@ -1683,14 +1724,30 @@ bool PackLinuxElf64::calls_crt1(Elf64_Rela const *rela, int sz)
|
||||
return false;
|
||||
}
|
||||
|
||||
char const *PackLinuxElf32::get_dynsym_name(unsigned symnum, unsigned relnum) const
|
||||
{
|
||||
if (symnum_end <= symnum) {
|
||||
char msg[50]; snprintf(msg, sizeof(msg),
|
||||
"bad symnum %#x in Elf32_Rel[%d]\n", symnum, relnum);
|
||||
throwCantPack(msg);
|
||||
}
|
||||
unsigned st_name = get_te32(&dynsym[symnum].st_name);
|
||||
if (strtab_end <= st_name) {
|
||||
char msg[50]; snprintf(msg, sizeof(msg),
|
||||
"bad .st_name %#x in DT_STRTAB[%d]\n", st_name, symnum);
|
||||
throwCantPack(msg);
|
||||
}
|
||||
return &dynstr[st_name];
|
||||
}
|
||||
|
||||
bool PackLinuxElf32::calls_crt1(Elf32_Rel const *rel, int sz)
|
||||
{
|
||||
if (!dynsym || !dynstr) {
|
||||
return false;
|
||||
}
|
||||
for (; 0 < sz; (sz -= sizeof(Elf32_Rel)), ++rel) {
|
||||
for (unsigned relnum= 0; 0 < sz; (sz -= sizeof(Elf32_Rel)), ++rel, ++relnum) {
|
||||
unsigned const symnum = get_te32(&rel->r_info) >> 8;
|
||||
char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr;
|
||||
char const *const symnam = get_dynsym_name(symnum, relnum);
|
||||
if (0==strcmp(symnam, "__libc_start_main") // glibc
|
||||
|| 0==strcmp(symnam, "__libc_init") // Android
|
||||
|| 0==strcmp(symnam, "__uClibc_main")
|
||||
@ -4574,6 +4631,7 @@ PackLinuxElf64::invert_pt_dynamic(Elf64_Dyn const *dynp)
|
||||
if (dt_table[Elf64_Dyn::DT_NULL]) {
|
||||
return; // not 1st time; do not change upx_dt_init
|
||||
}
|
||||
Elf64_Dyn const *const dynp0 = dynp;
|
||||
unsigned ndx = 1+ 0;
|
||||
if (dynp)
|
||||
for (; ; ++ndx, ++dynp) {
|
||||
@ -4589,6 +4647,28 @@ PackLinuxElf64::invert_pt_dynamic(Elf64_Dyn const *dynp)
|
||||
if (dt_table[Elf64_Dyn::DT_INIT]) upx_dt_init = Elf64_Dyn::DT_INIT;
|
||||
else if (dt_table[Elf64_Dyn::DT_PREINIT_ARRAY]) upx_dt_init = Elf64_Dyn::DT_PREINIT_ARRAY;
|
||||
else if (dt_table[Elf64_Dyn::DT_INIT_ARRAY]) upx_dt_init = Elf64_Dyn::DT_INIT_ARRAY;
|
||||
|
||||
unsigned const z_str = dt_table[Elf64_Dyn::DT_STRSZ];
|
||||
if (z_str) {
|
||||
strtab_end = get_te64(&dynp0[-1+ z_str].d_val);
|
||||
if (file_size <= strtab_end) { // FIXME: not tight enough
|
||||
char msg[50]; snprintf(msg, sizeof(msg),
|
||||
"bad DT_STRSZ %#x", strtab_end);
|
||||
throwCantPack(msg);
|
||||
}
|
||||
}
|
||||
unsigned const x_sym = dt_table[Elf64_Dyn::DT_SYMTAB];
|
||||
unsigned const x_str = dt_table[Elf64_Dyn::DT_STRTAB];
|
||||
if (x_sym && x_str) {
|
||||
upx_uint64_t const v_sym = get_te64(&dynp0[-1+ x_sym].d_val);
|
||||
upx_uint64_t const v_str = get_te64(&dynp0[-1+ x_str].d_val);
|
||||
unsigned const z_sym = dt_table[Elf64_Dyn::DT_SYMENT];
|
||||
unsigned const sz_sym = !z_sym ? sizeof(Elf64_Sym)
|
||||
: get_te64(&dynp0[-1+ z_sym].d_val);
|
||||
if (v_sym < v_str) {
|
||||
symnum_end = (v_str - v_sym) / sz_sym;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void const *
|
||||
@ -4653,7 +4733,7 @@ Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const
|
||||
unsigned const m = elf_hash(name) % nbucket;
|
||||
unsigned si;
|
||||
for (si= get_te32(&buckets[m]); 0!=si; si= get_te32(&chains[si])) {
|
||||
char const *const p= get_te32(&dynsym[si].st_name) + dynstr;
|
||||
char const *const p= get_dynsym_name(si, 0);
|
||||
if (0==strcmp(name, p)) {
|
||||
return &dynsym[si];
|
||||
}
|
||||
@ -4702,7 +4782,7 @@ Elf64_Sym const *PackLinuxElf64::elf_lookup(char const *name) const
|
||||
unsigned const m = elf_hash(name) % nbucket;
|
||||
unsigned si;
|
||||
for (si= get_te32(&buckets[m]); 0!=si; si= get_te32(&chains[si])) {
|
||||
char const *const p= get_te64(&dynsym[si].st_name) + dynstr;
|
||||
char const *const p= get_dynsym_name(si, 0);
|
||||
if (0==strcmp(name, p)) {
|
||||
return &dynsym[si];
|
||||
}
|
||||
|
||||
@ -163,6 +163,7 @@ protected:
|
||||
virtual upx_uint64_t elf_unsigned_dynamic(unsigned) const;
|
||||
virtual int adjABS(Elf32_Sym *sym, unsigned delta);
|
||||
|
||||
char const *get_dynsym_name(unsigned symnum, unsigned relnum) const;
|
||||
protected:
|
||||
Elf32_Ehdr ehdri; // from input file
|
||||
MemBuffer lowmem; // especially for shlib
|
||||
@ -189,6 +190,8 @@ protected:
|
||||
Elf32_Shdr *sec_strndx;
|
||||
Elf32_Shdr const *sec_dynsym;
|
||||
Elf32_Shdr const *sec_dynstr;
|
||||
unsigned symnum_end;
|
||||
unsigned strtab_end;
|
||||
|
||||
__packed_struct(cprElfHdr1)
|
||||
Elf32_Ehdr ehdr;
|
||||
@ -295,6 +298,7 @@ protected:
|
||||
virtual upx_uint64_t elf_unsigned_dynamic(unsigned) const;
|
||||
virtual int adjABS(Elf64_Sym *sym, unsigned delta);
|
||||
|
||||
char const *get_dynsym_name(unsigned symnum, unsigned relnum) const;
|
||||
protected:
|
||||
Elf64_Ehdr ehdri; // from input file
|
||||
MemBuffer lowmem; // especially for shlib
|
||||
@ -321,6 +325,8 @@ protected:
|
||||
Elf64_Shdr *sec_strndx;
|
||||
Elf64_Shdr const *sec_dynsym;
|
||||
Elf64_Shdr const *sec_dynstr;
|
||||
unsigned symnum_end;
|
||||
unsigned strtab_end;
|
||||
|
||||
__packed_struct(cprElfHdr1)
|
||||
Elf64_Ehdr ehdr;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user