Skip to content

Commit

Permalink
stop fetching memory blocks when an elf is found (#1996)
Browse files Browse the repository at this point in the history
When scanning multiple memory blocks, we should stop as soon as a valid
elf is found. This was broken as the "break" applies to the switch, and
not the outer loop. Fix this by reworking the code to remove the switch.

This bug had two repercutions:

- instead of parsing the first memory block that contains an elf, it
  returned the last one, or actually even worse, a mix of all elfs
  depending on which values are set again or not. This however should
  not manifest in normal situations, notably during process scanning, as
  I suppose only one memory region would contain an elf executable.

- the module caused the fetch of all memory blocks instead of stopping
  as soon as one was found, which is worse performance wise.
  • Loading branch information
vthib authored Dec 7, 2023
1 parent 2d103d3 commit 6cdc3fd
Showing 1 changed file with 60 additions and 72 deletions.
132 changes: 60 additions & 72 deletions libyara/modules/elf/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,91 +1124,79 @@ int module_load(
return ERROR_INSUFFICIENT_MEMORY;

module_object->data = elf;
switch (get_elf_class_data(block_data, block->size))
int class_data = get_elf_class_data(block_data, block->size);

if (class_data == CLASS_DATA(ELF_CLASS_32, ELF_DATA_2LSB) &&
block->size > sizeof(elf32_header_t))
{
case CLASS_DATA(ELF_CLASS_32, ELF_DATA_2LSB):
elf_header32 = (elf32_header_t*) block_data;

if (block->size > sizeof(elf32_header_t))
if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
yr_le16toh(elf_header32->type) == ELF_ET_EXEC)
{
elf_header32 = (elf32_header_t*) block_data;

if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
yr_le16toh(elf_header32->type) == ELF_ET_EXEC)
{
parse_result = parse_elf_header_32_le(
elf,
elf_header32,
block->base,
block->size,
context->flags,
module_object);
}
parse_result = parse_elf_header_32_le(
elf,
elf_header32,
block->base,
block->size,
context->flags,
module_object);
break;
}
} else if (
class_data == CLASS_DATA(ELF_CLASS_32, ELF_DATA_2MSB) &&
block->size > sizeof(elf32_header_t))
{
elf_header32 = (elf32_header_t*) block_data;

break;

case CLASS_DATA(ELF_CLASS_32, ELF_DATA_2MSB):

if (block->size > sizeof(elf32_header_t))
if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
yr_be16toh(elf_header32->type) == ELF_ET_EXEC)
{
elf_header32 = (elf32_header_t*) block_data;

if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
yr_be16toh(elf_header32->type) == ELF_ET_EXEC)
{
parse_result = parse_elf_header_32_be(
elf,
elf_header32,
block->base,
block->size,
context->flags,
module_object);
}
parse_result = parse_elf_header_32_be(
elf,
elf_header32,
block->base,
block->size,
context->flags,
module_object);
break;
}
} else if (
class_data == CLASS_DATA(ELF_CLASS_64, ELF_DATA_2LSB) &&
block->size > sizeof(elf64_header_t))
{
elf_header64 = (elf64_header_t*) block_data;

break;

case CLASS_DATA(ELF_CLASS_64, ELF_DATA_2LSB):

if (block->size > sizeof(elf64_header_t))
if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
yr_le16toh(elf_header64->type) == ELF_ET_EXEC)
{
elf_header64 = (elf64_header_t*) block_data;

if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
yr_le16toh(elf_header64->type) == ELF_ET_EXEC)
{
parse_result = parse_elf_header_64_le(
elf,
elf_header64,
block->base,
block->size,
context->flags,
module_object);
}
parse_result = parse_elf_header_64_le(
elf,
elf_header64,
block->base,
block->size,
context->flags,
module_object);
break;
}
} else if (
class_data == CLASS_DATA(ELF_CLASS_64, ELF_DATA_2MSB) &&
block->size > sizeof(elf64_header_t))
{
elf_header64 = (elf64_header_t*) block_data;

break;

case CLASS_DATA(ELF_CLASS_64, ELF_DATA_2MSB):

if (block->size > sizeof(elf64_header_t))
if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
yr_be16toh(elf_header64->type) == ELF_ET_EXEC)
{
elf_header64 = (elf64_header_t*) block_data;

if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
yr_be16toh(elf_header64->type) == ELF_ET_EXEC)
{
parse_result = parse_elf_header_64_be(
elf,
elf_header64,
block->base,
block->size,
context->flags,
module_object);
}
parse_result = parse_elf_header_64_be(
elf,
elf_header64,
block->base,
block->size,
context->flags,
module_object);
break;
}

break;
}
}

Expand Down

0 comments on commit 6cdc3fd

Please sign in to comment.