Check de-compressed SHT_SYMTAB
https://github.com/upx/upx/issues/396 modified: p_lx_elf.cpp
This commit is contained in:
committed by
Markus F.X.J. Oberhumer
parent
cc60f03b2e
commit
77c914bce5
+24
-9
@@ -3134,8 +3134,8 @@ static char const abs_symbol_names[][14] = {
|
|||||||
int
|
int
|
||||||
PackLinuxElf32::adjABS(Elf32_Sym *sym, unsigned delta)
|
PackLinuxElf32::adjABS(Elf32_Sym *sym, unsigned delta)
|
||||||
{
|
{
|
||||||
for (int j = 0; abs_symbol_names[j][0]; ++j) {
|
|
||||||
unsigned st_name = get_te32(&sym->st_name);
|
unsigned st_name = get_te32(&sym->st_name);
|
||||||
|
for (int j = 0; abs_symbol_names[j][0]; ++j) {
|
||||||
if (!strcmp(abs_symbol_names[j], get_str_name(st_name, (unsigned)-1))) {
|
if (!strcmp(abs_symbol_names[j], get_str_name(st_name, (unsigned)-1))) {
|
||||||
sym->st_value += delta;
|
sym->st_value += delta;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -3147,8 +3147,8 @@ PackLinuxElf32::adjABS(Elf32_Sym *sym, unsigned delta)
|
|||||||
int
|
int
|
||||||
PackLinuxElf64::adjABS(Elf64_Sym *sym, unsigned delta)
|
PackLinuxElf64::adjABS(Elf64_Sym *sym, unsigned delta)
|
||||||
{
|
{
|
||||||
for (int j = 0; abs_symbol_names[j][0]; ++j) {
|
|
||||||
unsigned st_name = get_te32(&sym->st_name);
|
unsigned st_name = get_te32(&sym->st_name);
|
||||||
|
for (int j = 0; abs_symbol_names[j][0]; ++j) {
|
||||||
if (!strcmp(abs_symbol_names[j], get_str_name(st_name, (unsigned)-1))) {
|
if (!strcmp(abs_symbol_names[j], get_str_name(st_name, (unsigned)-1))) {
|
||||||
sym->st_value += delta;
|
sym->st_value += delta;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -4614,16 +4614,21 @@ void PackLinuxElf64::unpack(OutputFile *fo)
|
|||||||
xct_off = e_shoff;
|
xct_off = e_shoff;
|
||||||
}
|
}
|
||||||
// un-Relocate dynsym (DT_SYMTAB) which is below xct_off
|
// un-Relocate dynsym (DT_SYMTAB) which is below xct_off
|
||||||
dynseg = (Elf64_Dyn const *)ibuf.subref(
|
upx_uint64_t dyn_offset = get_te64(&dynhdr->p_offset);
|
||||||
"bad DYNAMIC", get_te64(&dynhdr->p_offset), get_te64(&dynhdr->p_filesz));
|
upx_uint64_t dyn_filesz = get_te64(&dynhdr->p_filesz);
|
||||||
|
if (orig_file_size < dyn_offset
|
||||||
|
|| (orig_file_size - dyn_offset) < dyn_filesz) {
|
||||||
|
throwCantUnpack("bad PT_DYNAMIC");
|
||||||
|
}
|
||||||
|
dynseg = (Elf64_Dyn const *)ibuf.subref("bad DYNAMIC", dyn_offset, dyn_filesz);
|
||||||
dynstr = (char const *)elf_find_dynamic(Elf64_Dyn::DT_STRTAB);
|
dynstr = (char const *)elf_find_dynamic(Elf64_Dyn::DT_STRTAB);
|
||||||
sec_dynsym = elf_find_section_type(Elf64_Shdr::SHT_DYNSYM);
|
sec_dynsym = elf_find_section_type(Elf64_Shdr::SHT_DYNSYM);
|
||||||
if (sec_dynsym) {
|
if (sec_dynsym) {
|
||||||
upx_uint64_t const off_dynsym = get_te64(&sec_dynsym->sh_offset);
|
upx_uint64_t const off_dynsym = get_te64(&sec_dynsym->sh_offset);
|
||||||
upx_uint64_t const sz_dynsym = get_te64(&sec_dynsym->sh_size);
|
upx_uint64_t const sz_dynsym = get_te64(&sec_dynsym->sh_size);
|
||||||
if ((upx_uint64_t)file_size < sz_dynsym
|
if (orig_file_size < sz_dynsym
|
||||||
|| (upx_uint64_t)file_size < off_dynsym
|
|| orig_file_size < off_dynsym
|
||||||
|| ((upx_uint64_t)file_size - off_dynsym) < sz_dynsym) {
|
|| (orig_file_size - off_dynsym) < sz_dynsym) {
|
||||||
throwCantUnpack("bad SHT_DYNSYM");
|
throwCantUnpack("bad SHT_DYNSYM");
|
||||||
}
|
}
|
||||||
Elf64_Sym *const sym0 = (Elf64_Sym *)ibuf.subref(
|
Elf64_Sym *const sym0 = (Elf64_Sym *)ibuf.subref(
|
||||||
@@ -5695,13 +5700,23 @@ void PackLinuxElf32::unpack(OutputFile *fo)
|
|||||||
xct_off = e_shoff;
|
xct_off = e_shoff;
|
||||||
}
|
}
|
||||||
// un-Relocate dynsym (DT_SYMTAB) which is below xct_off
|
// un-Relocate dynsym (DT_SYMTAB) which is below xct_off
|
||||||
dynseg = (Elf32_Dyn const *)ibuf.subref(
|
unsigned dyn_offset = get_te32(&dynhdr->p_offset);
|
||||||
"bad DYNAMIC", get_te32(&dynhdr->p_offset), get_te32(&dynhdr->p_filesz));
|
unsigned dyn_filesz = get_te32(&dynhdr->p_filesz);
|
||||||
|
if (orig_file_size < dyn_offset
|
||||||
|
|| (orig_file_size - dyn_offset) < dyn_filesz) {
|
||||||
|
throwCantUnpack("bad PT_DYNAMIC");
|
||||||
|
}
|
||||||
|
dynseg = (Elf32_Dyn const *)ibuf.subref("bad DYNAMIC", dyn_offset, dyn_filesz);
|
||||||
dynstr = (char const *)elf_find_dynamic(Elf32_Dyn::DT_STRTAB);
|
dynstr = (char const *)elf_find_dynamic(Elf32_Dyn::DT_STRTAB);
|
||||||
sec_dynsym = elf_find_section_type(Elf32_Shdr::SHT_DYNSYM);
|
sec_dynsym = elf_find_section_type(Elf32_Shdr::SHT_DYNSYM);
|
||||||
if (sec_dynsym) {
|
if (sec_dynsym) {
|
||||||
unsigned const off_dynsym = get_te32(&sec_dynsym->sh_offset);
|
unsigned const off_dynsym = get_te32(&sec_dynsym->sh_offset);
|
||||||
unsigned const sz_dynsym = get_te32(&sec_dynsym->sh_size);
|
unsigned const sz_dynsym = get_te32(&sec_dynsym->sh_size);
|
||||||
|
if (orig_file_size < sz_dynsym
|
||||||
|
|| orig_file_size < off_dynsym
|
||||||
|
|| (orig_file_size - off_dynsym) < sz_dynsym) {
|
||||||
|
throwCantUnpack("bad SHT_DYNSYM");
|
||||||
|
}
|
||||||
Elf32_Sym *const sym0 = (Elf32_Sym *)ibuf.subref(
|
Elf32_Sym *const sym0 = (Elf32_Sym *)ibuf.subref(
|
||||||
"bad dynsym", off_dynsym, sz_dynsym);
|
"bad dynsym", off_dynsym, sz_dynsym);
|
||||||
Elf32_Sym *sym = sym0;
|
Elf32_Sym *sym = sym0;
|
||||||
|
|||||||
Reference in New Issue
Block a user