mirror of
https://github.com/VirusTotal/yara.git
synced 2026-10-11 22:49:58 +00:00
byte-swap sh_entry_count in elf symtab/dynsym link check (#2214)
Missing byte swap in the ELF symtab/dynsym link check The SHT_SYMTAB and SHT_DYNSYM string table check compares sh_link against the raw e_shnum (sh_entry_count) while every other use in the macro byte-swaps it, so on a little-endian host reading a big-endian ELF the check accepts a link past the real section count and parses the symbol string table from an out-of-range section header. Swapped it to match the sibling reads, and added a regression test scanning a crafted big-endian ELF whose only symtab carries an out-of-range sh_link.
This commit is contained in:
@@ -559,7 +559,8 @@ static const char* str_table_entry(
|
||||
} \
|
||||
\
|
||||
if (yr_##bo##32toh(section->type) == ELF_SHT_SYMTAB && \
|
||||
yr_##bo##32toh(section->link) < elf->sh_entry_count) \
|
||||
yr_##bo##32toh(section->link) < \
|
||||
yr_##bo##16toh(elf->sh_entry_count)) \
|
||||
{ \
|
||||
elf##bits##_section_header_t* string_section = section_table + \
|
||||
yr_##bo##32toh( \
|
||||
@@ -577,7 +578,8 @@ static const char* str_table_entry(
|
||||
} \
|
||||
\
|
||||
if (yr_##bo##32toh(section->type) == ELF_SHT_DYNSYM && \
|
||||
yr_##bo##32toh(section->link) < elf->sh_entry_count) \
|
||||
yr_##bo##32toh(section->link) < \
|
||||
yr_##bo##16toh(elf->sh_entry_count)) \
|
||||
{ \
|
||||
elf##bits##_section_header_t* dynstr_section = section_table + \
|
||||
yr_##bo##32toh( \
|
||||
|
||||
@@ -2139,6 +2139,39 @@ unsigned char ELF_x64_FILE[] = {
|
||||
};
|
||||
|
||||
|
||||
// Synthetic big-endian (ELFDATA2MSB) ELF32 used to exercise the symtab/dynsym
|
||||
// sh_link bounds check. The only SHT_SYMTAB section has sh_link = 4, which is
|
||||
// >= the real section count (3) but below the un-byteswapped count, so a
|
||||
// little-endian host that fails to byte-swap e_shnum would treat an
|
||||
// out-of-range section header as the symbol string table.
|
||||
unsigned char ELF32_BE_BAD_SYMTAB_LINK[] = {
|
||||
0x7f, 0x45, 0x4c, 0x46, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
|
||||
0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x42, 0x43, 0x44,
|
||||
0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t MACHO_X86_FILE[] = {
|
||||
0xce, 0xfa, 0xed, 0xfe, 0x07, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
|
||||
@@ -171,6 +171,18 @@ int main(int argc, char** argv)
|
||||
}",
|
||||
ELF32_MIPS_FILE);
|
||||
|
||||
// A big-endian symtab whose sh_link is past the real section count must not
|
||||
// be parsed against an out-of-range section header. Before the e_shnum byte
|
||||
// swap fix a little-endian host accepted the bogus link and reported a
|
||||
// phantom symbol named "ABCD".
|
||||
assert_false_rule_blob(
|
||||
"import \"elf\" \
|
||||
rule test { \
|
||||
condition: \
|
||||
elf.symtab_entries == 1 and elf.symtab[0].name == \"ABCD\" \
|
||||
}",
|
||||
ELF32_BE_BAD_SYMTAB_LINK);
|
||||
|
||||
assert_true_rule_blob(
|
||||
"import \"elf\" \
|
||||
rule test { \
|
||||
|
||||
Reference in New Issue
Block a user