From 6cdc3fdb93ab5b90be16533395e8ad76e1f7a7c5 Mon Sep 17 00:00:00 2001 From: Vincent Thiberville Date: Fri, 8 Dec 2023 00:14:40 +0100 Subject: [PATCH] stop fetching memory blocks when an elf is found (#1996) 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. --- libyara/modules/elf/elf.c | 132 +++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 72 deletions(-) diff --git a/libyara/modules/elf/elf.c b/libyara/modules/elf/elf.c index 488e6b0917..ff5418647f 100644 --- a/libyara/modules/elf/elf.c +++ b/libyara/modules/elf/elf.c @@ -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; } }