[Forensics-changes] [yara] 51/192: Fix pe, elf module for big-endian architectures (related to #493) (#538)
Hilko Bengen
bengen at moszumanska.debian.org
Sat Jul 1 10:31:45 UTC 2017
This is an automated email from the git hooks/post-receive script.
bengen pushed a commit to annotated tag v3.6.0
in repository yara.
commit d272b9c742e15d6767f20a7f1c01579b468cceee
Author: Hilko Bengen <hillu at users.noreply.github.com>
Date: Sun Oct 16 13:01:31 2016 +0200
Fix pe, elf module for big-endian architectures (related to #493) (#538)
* Fix pe module for big-endian architectures
* No longer skip pe test on big-endian architectures
(The ifdef was wrong anyhow.)
* Add tests for elf module
* Fix elf module for big-endian architectures
---
Makefile.am | 4 +-
libyara/include/yara/pe_utils.h | 2 +-
libyara/modules/elf.c | 135 ++++++++++++++++------------
libyara/modules/pe.c | 195 ++++++++++++++++++++--------------------
libyara/modules/pe_utils.c | 78 ++++++++--------
tests/test-elf.c | 29 ++++++
tests/test-pe.c | 5 --
7 files changed, 248 insertions(+), 200 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 4d4f7fa..8c1652a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,12 +15,14 @@ yarac_SOURCES = args.c args.h yarac.c
yarac_LDADD = libyara/.libs/libyara.a
TESTS = $(check_PROGRAMS)
-check_PROGRAMS = test-alignment test-rules test-pe
+check_PROGRAMS = test-alignment test-rules test-pe test-elf
test_alignment_SOURCES = tests/test-alignment.c
test_rules_SOURCES = tests/test-rules.c tests/util.c
test_rules_LDADD = libyara/.libs/libyara.a
test_pe_SOURCES = tests/test-pe.c tests/util.c
test_pe_LDADD = libyara/.libs/libyara.a
+test_elf_SOURCES = tests/test-elf.c tests/util.c
+test_elf_LDADD = libyara/.libs/libyara.a
# man pages
man1_MANS = yara.man yarac.man
diff --git a/libyara/include/yara/pe_utils.h b/libyara/include/yara/pe_utils.h
index 88e5a61..86571c5 100644
--- a/libyara/include/yara/pe_utils.h
+++ b/libyara/include/yara/pe_utils.h
@@ -7,7 +7,7 @@
#define IS_64BITS_PE(pe) \
- (pe->header64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+ (yr_le16toh(pe->header64->OptionalHeader.Magic) == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
#define OptionalHeader(pe,field) \
diff --git a/libyara/modules/elf.c b/libyara/modules/elf.c
index ed4ccd1..08c3ce4 100644
--- a/libyara/modules/elf.c
+++ b/libyara/modules/elf.c
@@ -48,7 +48,7 @@ int get_elf_type(
elf_ident = (elf_ident_t*) buffer;
- if (elf_ident->magic == ELF_MAGIC)
+ if (yr_le32toh(elf_ident->magic) == ELF_MAGIC)
{
return elf_ident->_class;
}
@@ -58,11 +58,11 @@ int get_elf_type(
}
}
-#define SIZE_OF_SECTION_TABLE_32 \
- (sizeof(elf32_section_header_t) * elf_header->sh_entry_count)
+#define SIZE_OF_SECTION_TABLE_32(h) \
+ (sizeof(elf32_section_header_t) * yr_le16toh(h->sh_entry_count))
-#define SIZE_OF_SECTION_TABLE_64 \
- (sizeof(elf64_section_header_t) * elf_header->sh_entry_count)
+#define SIZE_OF_SECTION_TABLE_64(h) \
+ (sizeof(elf64_section_header_t) * yr_le16toh(h->sh_entry_count))
#define ELF_RVA_TO_OFFSET(bits) \
@@ -77,30 +77,34 @@ uint64_t elf_rva_to_offset_##bits( \
\
/* check that sh_offset doesn't wrap when added to SIZE_OF_SECTION_TABLE */ \
\
- if(ULONG_MAX - elf_header->sh_offset < SIZE_OF_SECTION_TABLE_##bits) \
+ if(ULONG_MAX - yr_le##bits##toh(elf_header->sh_offset) < \
+ SIZE_OF_SECTION_TABLE_##bits(elf_header)) \
{ \
return UNDEFINED; \
} \
\
- if (elf_header->sh_offset == 0 || \
- elf_header->sh_offset > elf_size || \
- elf_header->sh_offset + SIZE_OF_SECTION_TABLE_##bits > elf_size || \
- elf_header->sh_entry_count == 0) \
+ if (yr_le##bits##toh(elf_header->sh_offset) == 0 || \
+ yr_le##bits##toh(elf_header->sh_offset) > elf_size || \
+ yr_le##bits##toh(elf_header->sh_offset) + \
+ SIZE_OF_SECTION_TABLE_##bits(elf_header) > elf_size || \
+ yr_le16toh(elf_header->sh_entry_count) == 0) \
{ \
return UNDEFINED; \
} \
\
section = (elf##bits##_section_header_t*) \
- ((uint8_t*) elf_header + elf_header->sh_offset); \
+ ((uint8_t*) elf_header + yr_le##bits##toh(elf_header->sh_offset)); \
\
- for (i = 0; i < elf_header->sh_entry_count; i++) \
+ for (i = 0; i < yr_le16toh(elf_header->sh_entry_count); i++) \
{ \
- if (section->type != ELF_SHT_NULL && \
- section->type != ELF_SHT_NOBITS && \
- rva >= section->addr && \
- rva < section->addr + section->size) \
+ if (yr_le32toh(section->type) != ELF_SHT_NULL && \
+ yr_le32toh(section->type) != ELF_SHT_NOBITS && \
+ rva >= yr_le##bits##toh(section->addr) && \
+ rva < yr_le##bits##toh(section->addr) + \
+ yr_le##bits##toh(section->size)) \
{ \
- return section->offset + (rva - section->addr); \
+ return yr_le##bits##toh(section->offset) + \
+ (rva - yr_le##bits##toh(section->addr)); \
} \
\
section++; \
@@ -122,83 +126,96 @@ void parse_elf_header_##bits( \
elf##bits##_section_header_t* section; \
elf##bits##_program_header_t* segment; \
\
- set_integer(elf->type, elf_obj, "type"); \
- set_integer(elf->machine, elf_obj, "machine"); \
- set_integer(elf->sh_offset, elf_obj, "sh_offset"); \
- set_integer(elf->sh_entry_size, elf_obj, "sh_entry_size"); \
- set_integer(elf->sh_entry_count, elf_obj, "number_of_sections"); \
- set_integer(elf->ph_offset, elf_obj, "ph_offset"); \
- set_integer(elf->ph_entry_size, elf_obj, "ph_entry_size"); \
- set_integer(elf->ph_entry_count, elf_obj, "number_of_segments"); \
+ set_integer(yr_le16toh(elf->type), elf_obj, "type"); \
+ set_integer(yr_le16toh(elf->machine), elf_obj, "machine"); \
+ set_integer(yr_le##bits##toh(elf->sh_offset), elf_obj, "sh_offset"); \
+ set_integer(yr_le16toh(elf->sh_entry_size), elf_obj, "sh_entry_size"); \
+ set_integer(yr_le16toh(elf->sh_entry_count), elf_obj, "number_of_sections"); \
+ set_integer(yr_le##bits##toh(elf->ph_offset), elf_obj, "ph_offset"); \
+ set_integer(yr_le16toh(elf->ph_entry_size), elf_obj, "ph_entry_size"); \
+ set_integer(yr_le16toh(elf->ph_entry_count), elf_obj, "number_of_segments"); \
\
- if (elf->entry != 0) \
+ if (yr_le##bits##toh(elf->entry) != 0) \
{ \
set_integer( \
flags & SCAN_FLAGS_PROCESS_MEMORY ? \
- base_address + elf->entry : \
- elf_rva_to_offset_##bits(elf, elf->entry, elf_size), \
+ base_address + yr_le##bits##toh(elf->entry) : \
+ elf_rva_to_offset_##bits(elf, yr_le##bits##toh(elf->entry), elf_size), \
elf_obj, "entry_point"); \
} \
\
- if (elf->sh_entry_count < ELF_SHN_LORESERVE && \
- elf->sh_str_table_index < elf->sh_entry_count && \
- elf->sh_offset < elf_size && \
- elf->sh_offset + elf->sh_entry_count * \
+ if (yr_le16toh(elf->sh_entry_count) < ELF_SHN_LORESERVE && \
+ yr_le16toh(elf->sh_str_table_index) < yr_le16toh(elf->sh_entry_count) && \
+ yr_le##bits##toh(elf->sh_offset) < elf_size && \
+ yr_le##bits##toh(elf->sh_offset) + yr_le16toh(elf->sh_entry_count) * \
sizeof(elf##bits##_section_header_t) <= elf_size) \
{ \
char* str_table = NULL; \
\
section = (elf##bits##_section_header_t*) \
- ((uint8_t*) elf + elf->sh_offset); \
+ ((uint8_t*) elf + yr_le##bits##toh(elf->sh_offset)); \
\
- if (section[elf->sh_str_table_index].offset < elf_size) \
- str_table = (char*) elf + section[elf->sh_str_table_index].offset; \
+ if (section[yr_le16toh(elf->sh_str_table_index)].offset < elf_size) \
+ str_table = (char*) elf + \
+ yr_le##bits##toh(section[yr_le16toh(elf->sh_str_table_index)].offset); \
\
- for (i = 0; i < elf->sh_entry_count; i++) \
+ for (i = 0; i < yr_le16toh(elf->sh_entry_count); i++) \
{ \
- set_integer(section->type, elf_obj, "sections[%i].type", i); \
- set_integer(section->flags, elf_obj, "sections[%i].flags", i); \
- set_integer(section->size, elf_obj, "sections[%i].size", i); \
- set_integer(section->offset, elf_obj, "sections[%i].offset", i); \
+ set_integer(yr_le32toh(section->type), elf_obj, \
+ "sections[%i].type", i); \
+ set_integer(yr_le32toh(section->flags), elf_obj, \
+ "sections[%i].flags", i); \
+ set_integer(yr_le##bits##toh(section->size), elf_obj, \
+ "sections[%i].size", i); \
+ set_integer(yr_le##bits##toh(section->offset), elf_obj, \
+ "sections[%i].offset", i); \
\
- if (section->name < elf_size && \
+ if (yr_le##bits##toh(section->name) < elf_size && \
str_table > (char*) elf && \
- str_table + section->name < (char*) elf + elf_size) \
+ str_table + yr_le##bits##toh(section->name) < \
+ (char*) elf + elf_size) \
{ \
- set_string(str_table + section->name, elf_obj, "sections[%i].name", i);\
+ set_string(str_table + yr_le##bits##toh(section->name), elf_obj, \
+ "sections[%i].name", i); \
} \
\
section++; \
} \
} \
\
- if (elf->ph_entry_count > 0 && \
- elf->ph_entry_count < ELF_PN_XNUM && \
- elf->ph_offset < elf_size && \
- elf->ph_offset + elf->ph_entry_count * \
+ if (yr_le16toh(elf->ph_entry_count) > 0 && \
+ yr_le16toh(elf->ph_entry_count) < ELF_PN_XNUM && \
+ yr_le##bits##toh(elf->ph_offset) < elf_size && \
+ yr_le##bits##toh(elf->ph_offset) + yr_le16toh(elf->ph_entry_count) * \
sizeof(elf##bits##_program_header_t) <= elf_size) \
{ \
segment = (elf##bits##_program_header_t*) \
- ((uint8_t*) elf + elf->ph_offset); \
+ ((uint8_t*) elf + yr_le##bits##toh(elf->ph_offset)); \
\
- for (i = 0; i < elf->ph_entry_count; i++) \
+ for (i = 0; i < yr_le16toh(elf->ph_entry_count); i++) \
{ \
set_integer( \
- segment->type, elf_obj, "segments[%i].type", i); \
+ yr_le32toh(segment->type), elf_obj, "segments[%i].type", i); \
set_integer( \
- segment->flags, elf_obj, "segments[%i].flags", i); \
+ yr_le32toh(segment->flags), elf_obj, "segments[%i].flags", i); \
set_integer( \
- segment->offset, elf_obj, "segments[%i].offset", i); \
+ yr_le##bits##toh(segment->offset), elf_obj, \
+ "segments[%i].offset", i); \
set_integer( \
- segment->virt_addr, elf_obj, "segments[%i].virtual_address", i); \
+ yr_le##bits##toh(segment->virt_addr), elf_obj, \
+ "segments[%i].virtual_address", i); \
set_integer( \
- segment->phys_addr, elf_obj, "segments[%i].physical_address", i); \
+ yr_le##bits##toh(segment->phys_addr), elf_obj, \
+ "segments[%i].physical_address", i); \
set_integer( \
- segment->file_size, elf_obj, "segments[%i].file_size", i); \
+ yr_le##bits##toh(segment->file_size), elf_obj, \
+ "segments[%i].file_size", i); \
set_integer( \
- segment->mem_size, elf_obj, "segments[%i].memory_size", i); \
+ yr_le##bits##toh(segment->mem_size), elf_obj, \
+ "segments[%i].memory_size", i); \
set_integer( \
- segment->alignment, elf_obj, "segments[%i].alignment", i); \
+ yr_le##bits##toh(segment->alignment), elf_obj, \
+ "segments[%i].alignment", i); \
\
segment++; \
} \
@@ -398,7 +415,7 @@ int module_load(
elf_header32 = (elf32_header_t*) block_data;
if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
- elf_header32->type == ELF_ET_EXEC)
+ yr_le16toh(elf_header32->type) == ELF_ET_EXEC)
{
parse_elf_header_32(
elf_header32,
@@ -418,7 +435,7 @@ int module_load(
elf_header64 = (elf64_header_t*) block_data;
if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
- elf_header64->type == ELF_ET_EXEC)
+ yr_le16toh(elf_header64->type) == ELF_ET_EXEC)
{
parse_elf_header_64(
elf_header64,
diff --git a/libyara/modules/pe.c b/libyara/modules/pe.c
index 4908ba1..e8d4e13 100644
--- a/libyara/modules/pe.c
+++ b/libyara/modules/pe.c
@@ -156,13 +156,13 @@ void pe_parse_rich_signature(
mz_header = (PIMAGE_DOS_HEADER) pe->data;
- if (mz_header->e_magic != IMAGE_DOS_SIGNATURE)
+ if (yr_le16toh(mz_header->e_magic) != IMAGE_DOS_SIGNATURE)
return;
- if (mz_header->e_lfanew < 0)
+ if (yr_le32toh(mz_header->e_lfanew) < 0)
return;
- headers_size = mz_header->e_lfanew + \
+ headers_size = yr_le32toh(mz_header->e_lfanew) + \
sizeof(pe_header->Signature) + \
sizeof(IMAGE_FILE_HEADER);
@@ -177,9 +177,9 @@ void pe_parse_rich_signature(
rich_signature = (PRICH_SIGNATURE) (pe->data + 0x80);
- if (rich_signature->key1 != rich_signature->key2 ||
- rich_signature->key2 != rich_signature->key3 ||
- (rich_signature->dans ^ rich_signature->key1) != RICH_DANS)
+ if (yr_le32toh(rich_signature->key1) != yr_le32toh(rich_signature->key2) ||
+ yr_le32toh(rich_signature->key2) != yr_le32toh(rich_signature->key3) ||
+ (yr_le32toh(rich_signature->dans) ^ yr_le32toh(rich_signature->key1)) != RICH_DANS)
{
return;
}
@@ -188,7 +188,7 @@ void pe_parse_rich_signature(
rich_ptr <= (DWORD*) (pe->data + headers_size);
rich_ptr++)
{
- if (*rich_ptr == RICH_RICH)
+ if (yr_le32toh(*rich_ptr) == RICH_RICH)
{
// Multiple by 4 because we are counting in DWORDs.
rich_len = (rich_ptr - (DWORD*) rich_signature) * 4;
@@ -261,11 +261,11 @@ uint8_t* parse_resource_name(
// If high bit is set it is an offset relative to rsrc_data, which contains
// a resource directory string.
- if (entry->Name & 0x80000000)
+ if (yr_le32toh(entry->Name) & 0x80000000)
{
DWORD length;
- uint8_t* rsrc_str_ptr = rsrc_data + (entry->Name & 0x7FFFFFFF);
+ uint8_t* rsrc_str_ptr = rsrc_data + (yr_le32toh(entry->Name) & 0x7FFFFFFF);
// A resource directory string is 2 bytes for a string and then a variable
// length Unicode string. Make sure we at least have two bytes.
@@ -307,15 +307,15 @@ int _pe_iterate_resources(
// A few sanity checks to avoid corrupt files
- if (resource_dir->Characteristics != 0 ||
- resource_dir->NumberOfNamedEntries > 32768 ||
- resource_dir->NumberOfIdEntries > 32768)
+ if (yr_le32toh(resource_dir->Characteristics) != 0 ||
+ yr_le16toh(resource_dir->NumberOfNamedEntries) > 32768 ||
+ yr_le16toh(resource_dir->NumberOfIdEntries) > 32768)
{
return result;
}
- total_entries = resource_dir->NumberOfNamedEntries +
- resource_dir->NumberOfIdEntries;
+ total_entries = yr_le16toh(resource_dir->NumberOfNamedEntries) +
+ yr_le16toh(resource_dir->NumberOfIdEntries);
// The first directory entry is just after the resource directory,
// by incrementing resource_dir we skip sizeof(resource_dir) bytes
@@ -333,15 +333,15 @@ int _pe_iterate_resources(
switch(rsrc_tree_level)
{
case 0:
- *type = entry->Name;
+ *type = yr_le32toh(entry->Name);
type_string = parse_resource_name(pe, rsrc_data, entry);
break;
case 1:
- *id = entry->Name;
+ *id = yr_le32toh(entry->Name);
name_string = parse_resource_name(pe, rsrc_data, entry);
break;
case 2:
- *language = entry->Name;
+ *language = yr_le32toh(entry->Name);
lang_string = parse_resource_name(pe, rsrc_data, entry);
break;
}
@@ -425,11 +425,11 @@ int pe_iterate_resources(
PIMAGE_DATA_DIRECTORY directory = pe_get_directory_entry(
pe, IMAGE_DIRECTORY_ENTRY_RESOURCE);
- if (directory->VirtualAddress != 0)
+ if (yr_le32toh(directory->VirtualAddress) != 0)
{
PIMAGE_RESOURCE_DIRECTORY rsrc_dir;
- offset = pe_rva_to_offset(pe, directory->VirtualAddress);
+ offset = pe_rva_to_offset(pe, yr_le32toh(directory->VirtualAddress));
if (offset < 0)
return 0;
@@ -438,14 +438,14 @@ int pe_iterate_resources(
if (struct_fits_in_pe(pe, rsrc_dir, IMAGE_RESOURCE_DIRECTORY))
{
- set_integer(rsrc_dir->TimeDateStamp,
+ set_integer(yr_le32toh(rsrc_dir->TimeDateStamp),
pe->object,
"resource_timestamp");
- set_integer(rsrc_dir->MajorVersion,
+ set_integer(yr_le16toh(rsrc_dir->MajorVersion),
pe->object,
"resource_version.major");
- set_integer(rsrc_dir->MinorVersion,
+ set_integer(yr_le16toh(rsrc_dir->MinorVersion),
pe->object,
"resource_version.minor");
@@ -483,7 +483,7 @@ void pe_parse_version_info(
{
PVERSION_INFO version_info;
- int64_t version_info_offset = pe_rva_to_offset(pe, rsrc_data->OffsetToData);
+ int64_t version_info_offset = pe_rva_to_offset(pe, yr_le32toh(rsrc_data->OffsetToData));
if (version_info_offset < 0)
return;
@@ -504,16 +504,16 @@ void pe_parse_version_info(
while(fits_in_pe(pe, version_info->Key, sizeof("VarFileInfo") * 2) &&
strcmp_w(version_info->Key, "VarFileInfo") == 0 &&
- version_info->Length != 0)
+ yr_le16toh(version_info->Length) != 0)
{
version_info = ADD_OFFSET(
version_info,
- version_info->Length);
+ yr_le16toh(version_info->Length));
}
while(fits_in_pe(pe, version_info->Key, sizeof("StringFileInfo") * 2) &&
strcmp_w(version_info->Key, "StringFileInfo") == 0 &&
- version_info->Length != 0)
+ yr_le16toh(version_info->Length) != 0)
{
PVERSION_INFO string_table = ADD_OFFSET(
version_info,
@@ -521,11 +521,11 @@ void pe_parse_version_info(
version_info = ADD_OFFSET(
version_info,
- version_info->Length);
+ yr_le16toh(version_info->Length));
while (struct_fits_in_pe(pe, string_table, VERSION_INFO) &&
wide_string_fits_in_pe(pe, string_table->Key) &&
- string_table->Length != 0 &&
+ yr_le16toh(string_table->Length) != 0 &&
string_table < version_info)
{
PVERSION_INFO string = ADD_OFFSET(
@@ -534,11 +534,11 @@ void pe_parse_version_info(
string_table = ADD_OFFSET(
string_table,
- string_table->Length);
+ yr_le16toh(string_table->Length));
while (struct_fits_in_pe(pe, string, VERSION_INFO) &&
wide_string_fits_in_pe(pe, string->Key) &&
- string->Length != 0 &&
+ yr_le16toh(string->Length) != 0 &&
string < string_table)
{
if (string->ValueLength > 0)
@@ -577,9 +577,9 @@ int pe_collect_resources(
{
DWORD length;
- int64_t offset = pe_rva_to_offset(pe, rsrc_data->OffsetToData);
+ int64_t offset = pe_rva_to_offset(pe, yr_le32toh(rsrc_data->OffsetToData));
- if (offset < 0 || !fits_in_pe(pe, pe->data + offset, rsrc_data->Size))
+ if (offset < 0 || !fits_in_pe(pe, pe->data + offset, yr_le32toh(rsrc_data->Size)))
return RESOURCE_CALLBACK_CONTINUE;
set_integer(
@@ -589,7 +589,7 @@ int pe_collect_resources(
pe->resources);
set_integer(
- rsrc_data->Size,
+ yr_le32toh(rsrc_data->Size),
pe->object,
"resources[%i].length",
pe->resources);
@@ -669,13 +669,13 @@ IMPORTED_FUNCTION* pe_parse_import_descriptor(
int num_functions = 0;
int64_t offset = pe_rva_to_offset(
- pe, import_descriptor->OriginalFirstThunk);
+ pe, yr_le32toh(import_descriptor->OriginalFirstThunk));
// I've seen binaries where OriginalFirstThunk is zero. In this case
// use FirstThunk.
if (offset <= 0)
- offset = pe_rva_to_offset(pe, import_descriptor->FirstThunk);
+ offset = pe_rva_to_offset(pe, yr_le32toh(import_descriptor->FirstThunk));
if (offset < 0)
return NULL;
@@ -685,16 +685,16 @@ IMPORTED_FUNCTION* pe_parse_import_descriptor(
PIMAGE_THUNK_DATA64 thunks64 = (PIMAGE_THUNK_DATA64)(pe->data + offset);
while (struct_fits_in_pe(pe, thunks64, IMAGE_THUNK_DATA64) &&
- thunks64->u1.Ordinal != 0 && num_functions < MAX_PE_IMPORTS)
+ yr_le64toh(thunks64->u1.Ordinal) != 0 && num_functions < MAX_PE_IMPORTS)
{
char* name = NULL;
uint16_t ordinal = 0;
uint8_t has_ordinal = 0;
- if (!(thunks64->u1.Ordinal & IMAGE_ORDINAL_FLAG64))
+ if (!(yr_le64toh(thunks64->u1.Ordinal) & IMAGE_ORDINAL_FLAG64))
{
// If imported by name
- offset = pe_rva_to_offset(pe, thunks64->u1.Function);
+ offset = pe_rva_to_offset(pe, yr_le64toh(thunks64->u1.Function));
if (offset >= 0)
{
@@ -712,9 +712,9 @@ IMPORTED_FUNCTION* pe_parse_import_descriptor(
else
{
// If imported by ordinal. Lookup the ordinal.
- name = ord_lookup(dll_name, thunks64->u1.Ordinal & 0xFFFF);
+ name = ord_lookup(dll_name, yr_le64toh(thunks64->u1.Ordinal) & 0xFFFF);
// Also store the ordinal.
- ordinal = thunks64->u1.Ordinal & 0xFFFF;
+ ordinal = yr_le64toh(thunks64->u1.Ordinal) & 0xFFFF;
has_ordinal = 1;
}
@@ -752,16 +752,16 @@ IMPORTED_FUNCTION* pe_parse_import_descriptor(
PIMAGE_THUNK_DATA32 thunks32 = (PIMAGE_THUNK_DATA32)(pe->data + offset);
while (struct_fits_in_pe(pe, thunks32, IMAGE_THUNK_DATA32) &&
- thunks32->u1.Ordinal != 0 && num_functions < MAX_PE_IMPORTS)
+ yr_le32toh(thunks32->u1.Ordinal) != 0 && num_functions < MAX_PE_IMPORTS)
{
char* name = NULL;
uint16_t ordinal = 0;
uint8_t has_ordinal = 0;
- if (!(thunks32->u1.Ordinal & IMAGE_ORDINAL_FLAG32))
+ if (!(yr_le32toh(thunks32->u1.Ordinal) & IMAGE_ORDINAL_FLAG32))
{
// If imported by name
- offset = pe_rva_to_offset(pe, thunks32->u1.Function);
+ offset = pe_rva_to_offset(pe, yr_le32toh(thunks32->u1.Function));
if (offset >= 0)
{
@@ -779,9 +779,9 @@ IMPORTED_FUNCTION* pe_parse_import_descriptor(
else
{
// If imported by ordinal. Lookup the ordinal.
- name = ord_lookup(dll_name, thunks32->u1.Ordinal & 0xFFFF);
+ name = ord_lookup(dll_name, yr_le32toh(thunks32->u1.Ordinal) & 0xFFFF);
// Also store the ordinal.
- ordinal = thunks32->u1.Ordinal & 0xFFFF;
+ ordinal = yr_le32toh(thunks32->u1.Ordinal) & 0xFFFF;
has_ordinal = 1;
}
@@ -865,10 +865,10 @@ IMPORTED_DLL* pe_parse_imports(
PIMAGE_DATA_DIRECTORY directory = pe_get_directory_entry(
pe, IMAGE_DIRECTORY_ENTRY_IMPORT);
- if (directory->VirtualAddress == 0)
+ if (yr_le32toh(directory->VirtualAddress) == 0)
return NULL;
- offset = pe_rva_to_offset(pe, directory->VirtualAddress);
+ offset = pe_rva_to_offset(pe, yr_le32toh(directory->VirtualAddress));
if (offset < 0)
return NULL;
@@ -877,9 +877,9 @@ IMPORTED_DLL* pe_parse_imports(
(pe->data + offset);
while (struct_fits_in_pe(pe, imports, IMAGE_IMPORT_DESCRIPTOR) &&
- imports->Name != 0 && num_imports < MAX_PE_IMPORTS)
+ yr_le32toh(imports->Name) != 0 && num_imports < MAX_PE_IMPORTS)
{
- int64_t offset = pe_rva_to_offset(pe, imports->Name);
+ int64_t offset = pe_rva_to_offset(pe, yr_le32toh(imports->Name));
if (offset >= 0)
{
@@ -944,19 +944,19 @@ void pe_parse_certificates(
set_integer(0, pe->object, "number_of_signatures");
// directory->VirtualAddress is a file offset. Don't call pe_rva_to_offset().
- if (directory->VirtualAddress == 0 ||
- directory->VirtualAddress > pe->data_size ||
- directory->Size > pe->data_size ||
- directory->VirtualAddress + directory->Size > pe->data_size)
+ if (yr_le32toh(directory->VirtualAddress) == 0 ||
+ yr_le32toh(directory->VirtualAddress) > pe->data_size ||
+ yr_le32toh(directory->Size) > pe->data_size ||
+ yr_le32toh(directory->VirtualAddress) + yr_le32toh(directory->Size) > pe->data_size)
{
return;
}
// Store the end of directory, making comparisons easier.
- eod = pe->data + directory->VirtualAddress + directory->Size;
+ eod = pe->data + yr_le32toh(directory->VirtualAddress) + directory->Size;
win_cert = (PWIN_CERTIFICATE) \
- (pe->data + directory->VirtualAddress);
+ (pe->data + yr_le32toh(directory->VirtualAddress));
//
// Walk the directory, pulling out certificates.
@@ -970,10 +970,10 @@ void pe_parse_certificates(
//
while (struct_fits_in_pe(pe, win_cert, WIN_CERTIFICATE) &&
- win_cert->Length > sizeof(WIN_CERTIFICATE) &&
- fits_in_pe(pe, win_cert, win_cert->Length) &&
+ yr_le32toh(win_cert->Length) > sizeof(WIN_CERTIFICATE) &&
+ fits_in_pe(pe, win_cert, yr_le32toh(win_cert->Length)) &&
(uint8_t*) win_cert + sizeof(WIN_CERTIFICATE) < eod &&
- (uint8_t*) win_cert + win_cert->Length <= eod)
+ (uint8_t*) win_cert + yr_le32toh(win_cert->Length) <= eod)
{
BIO* cert_bio;
PKCS7* pkcs7;
@@ -981,9 +981,9 @@ void pe_parse_certificates(
// Some sanity checks
- if (win_cert->Length == 0 ||
- (win_cert->Revision != WIN_CERT_REVISION_1_0 &&
- win_cert->Revision != WIN_CERT_REVISION_2_0))
+ if (yr_le32toh(win_cert->Length) == 0 ||
+ (yr_le16toh(win_cert->Revision) != WIN_CERT_REVISION_1_0 &&
+ yr_le16toh(win_cert->Revision) != WIN_CERT_REVISION_2_0))
{
break;
}
@@ -991,16 +991,16 @@ void pe_parse_certificates(
// Don't support legacy revision for now.
// Make sure type is PKCS#7 too.
- if (win_cert->Revision != WIN_CERT_REVISION_2_0 ||
- win_cert->CertificateType != WIN_CERT_TYPE_PKCS_SIGNED_DATA)
+ if (yr_le16toh(win_cert->Revision) != WIN_CERT_REVISION_2_0 ||
+ yr_le16toh(win_cert->CertificateType) != WIN_CERT_TYPE_PKCS_SIGNED_DATA)
{
- uintptr_t end = (uintptr_t) ((uint8_t *) win_cert) + win_cert->Length;
+ uintptr_t end = (uintptr_t) ((uint8_t *) win_cert) + yr_le32toh(win_cert->Length);
win_cert = (PWIN_CERTIFICATE) (end + (end % 8));
continue;
}
- cert_bio = BIO_new_mem_buf(win_cert->Certificate, win_cert->Length);
+ cert_bio = BIO_new_mem_buf(win_cert->Certificate, yr_le32toh(win_cert->Length));
if (!cert_bio)
break;
@@ -1165,29 +1165,31 @@ void pe_parse_header(
uint64_t last_section_end;
set_integer(
- pe->header->FileHeader.Machine,
+ yr_le16toh(pe->header->FileHeader.Machine),
pe->object, "machine");
set_integer(
- pe->header->FileHeader.NumberOfSections,
+ yr_le16toh(pe->header->FileHeader.NumberOfSections),
pe->object, "number_of_sections");
set_integer(
- pe->header->FileHeader.TimeDateStamp,
+ yr_le32toh(pe->header->FileHeader.TimeDateStamp),
pe->object, "timestamp");
set_integer(
- pe->header->FileHeader.Characteristics,
+ yr_le16toh(pe->header->FileHeader.Characteristics),
pe->object, "characteristics");
set_integer(
flags & SCAN_FLAGS_PROCESS_MEMORY ?
- base_address + OptionalHeader(pe, AddressOfEntryPoint) :
- pe_rva_to_offset(pe, OptionalHeader(pe, AddressOfEntryPoint)),
+ base_address + yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint)) :
+ pe_rva_to_offset(pe, yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint))),
pe->object, "entry_point");
set_integer(
- OptionalHeader(pe, ImageBase),
+ IS_64BITS_PE(pe) ?
+ yr_le64toh(OptionalHeader(pe, ImageBase)) :
+ yr_le32toh(OptionalHeader(pe, ImageBase)),
pe->object, "image_base");
set_integer(
@@ -1199,35 +1201,35 @@ void pe_parse_header(
pe->object, "linker_version.minor");
set_integer(
- OptionalHeader(pe, MajorOperatingSystemVersion),
+ yr_le16toh(OptionalHeader(pe, MajorOperatingSystemVersion)),
pe->object, "os_version.major");
set_integer(
- OptionalHeader(pe, MinorOperatingSystemVersion),
+ yr_le16toh(OptionalHeader(pe, MinorOperatingSystemVersion)),
pe->object, "os_version.minor");
set_integer(
- OptionalHeader(pe, MajorImageVersion),
+ yr_le16toh(OptionalHeader(pe, MajorImageVersion)),
pe->object, "image_version.major");
set_integer(
- OptionalHeader(pe, MinorImageVersion),
+ yr_le16toh(OptionalHeader(pe, MinorImageVersion)),
pe->object, "image_version.minor");
set_integer(
- OptionalHeader(pe, MajorSubsystemVersion),
+ yr_le16toh(OptionalHeader(pe, MajorSubsystemVersion)),
pe->object, "subsystem_version.major");
set_integer(
- OptionalHeader(pe, MinorSubsystemVersion),
+ yr_le16toh(OptionalHeader(pe, MinorSubsystemVersion)),
pe->object, "subsystem_version.minor");
set_integer(
- OptionalHeader(pe, CheckSum),
+ yr_le32toh(OptionalHeader(pe, CheckSum)),
pe->object, "checksum");
set_integer(
- OptionalHeader(pe, Subsystem),
+ yr_le16toh(OptionalHeader(pe, Subsystem)),
pe->object, "subsystem");
pe_iterate_resources(
@@ -1239,7 +1241,7 @@ void pe_parse_header(
section = IMAGE_FIRST_SECTION(pe->header);
- scount = yr_min(pe->header->FileHeader.NumberOfSections, MAX_PE_SECTIONS);
+ scount = yr_min(yr_le16toh(pe->header->FileHeader.NumberOfSections), MAX_PE_SECTIONS);
for (i = 0; i < scount; i++)
{
@@ -1254,28 +1256,31 @@ void pe_parse_header(
pe->object, "sections[%i].name", i);
set_integer(
- section->Characteristics,
+ yr_le32toh(section->Characteristics),
pe->object, "sections[%i].characteristics", i);
- set_integer(section->SizeOfRawData,
+ set_integer(
+ yr_le32toh(section->SizeOfRawData),
pe->object, "sections[%i].raw_data_size", i);
- set_integer(section->PointerToRawData,
+ set_integer(
+ yr_le32toh(section->PointerToRawData),
pe->object, "sections[%i].raw_data_offset", i);
- set_integer(section->VirtualAddress,
+ set_integer(
+ yr_le32toh(section->VirtualAddress),
pe->object, "sections[%i].virtual_address", i);
set_integer(
- section->Misc.VirtualSize,
+ yr_le32toh(section->Misc.VirtualSize),
pe->object, "sections[%i].virtual_size", i);
// This will catch the section with the highest raw offset to help checking
// if overlay data is present
- if (section->PointerToRawData > highest_sec_ofs)
+ if (yr_le32toh(section->PointerToRawData) > highest_sec_ofs)
{
- highest_sec_ofs = section->PointerToRawData;
- highest_sec_siz = section->SizeOfRawData;
+ highest_sec_ofs = yr_le32toh(section->PointerToRawData);
+ highest_sec_siz = yr_le32toh(section->SizeOfRawData);
}
section++;
@@ -1403,7 +1408,7 @@ define_function(exports)
// If the PE doesn't export any functions, return FALSE
- if (directory->VirtualAddress == 0)
+ if (yr_le32toh(directory->VirtualAddress) == 0)
return_integer(0);
offset = pe_rva_to_offset(pe, directory->VirtualAddress);
@@ -1417,18 +1422,18 @@ define_function(exports)
if (!struct_fits_in_pe(pe, exports, IMAGE_EXPORT_DIRECTORY))
return_integer(0);
- offset = pe_rva_to_offset(pe, exports->AddressOfNames);
+ offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfNames));
if (offset < 0)
return_integer(0);
- if (exports->NumberOfNames > MAX_PE_EXPORTS ||
- exports->NumberOfNames * sizeof(DWORD) > pe->data_size - offset)
+ if (yr_le32toh(exports->NumberOfNames) > MAX_PE_EXPORTS ||
+ yr_le32toh(exports->NumberOfNames) * sizeof(DWORD) > pe->data_size - offset)
return_integer(0);
names = (DWORD*)(pe->data + offset);
- for (i = 0; i < exports->NumberOfNames; i++)
+ for (i = 0; i < yr_le32toh(exports->NumberOfNames); i++)
{
char* name;
offset = pe_rva_to_offset(pe, names[i]);
@@ -2376,7 +2381,7 @@ int module_load(
// Ignore DLLs while scanning a process
if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
- !(pe_header->FileHeader.Characteristics & IMAGE_FILE_DLL))
+ !(yr_le16toh(pe_header->FileHeader.Characteristics) & IMAGE_FILE_DLL))
{
pe = (PE*) yr_malloc(sizeof(PE));
diff --git a/libyara/modules/pe_utils.c b/libyara/modules/pe_utils.c
index ed69b80..9b80286 100644
--- a/libyara/modules/pe_utils.c
+++ b/libyara/modules/pe_utils.c
@@ -60,46 +60,46 @@ PIMAGE_NT_HEADERS32 pe_get_header(
mz_header = (PIMAGE_DOS_HEADER) data;
- if (mz_header->e_magic != IMAGE_DOS_SIGNATURE)
+ if (yr_le16toh(mz_header->e_magic) != IMAGE_DOS_SIGNATURE)
return NULL;
- if (mz_header->e_lfanew < 0)
+ if (yr_le32toh(mz_header->e_lfanew) < 0)
return NULL;
- headers_size = mz_header->e_lfanew + \
+ headers_size = yr_le32toh(mz_header->e_lfanew) + \
sizeof(pe_header->Signature) + \
sizeof(IMAGE_FILE_HEADER);
if (data_size < headers_size)
return NULL;
- pe_header = (PIMAGE_NT_HEADERS32) (data + mz_header->e_lfanew);
-
- headers_size += pe_header->FileHeader.SizeOfOptionalHeader;
-
- if (pe_header->Signature == IMAGE_NT_SIGNATURE &&
- (pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_UNKNOWN ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_AM33 ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_ARM ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_ARMNT ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_ARM64 ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_EBC ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_M32R ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_MIPS16 ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_MIPSFPU ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_MIPSFPU16 ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_POWERPC ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_POWERPCFP ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_R4000 ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_SH3 ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_SH3DSP ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_SH4 ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_SH5 ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_THUMB ||
- pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_WCEMIPSV2) &&
+ pe_header = (PIMAGE_NT_HEADERS32) (data + yr_le32toh(mz_header->e_lfanew));
+
+ headers_size += yr_le16toh(pe_header->FileHeader.SizeOfOptionalHeader);
+
+ if (yr_le32toh(pe_header->Signature) == IMAGE_NT_SIGNATURE &&
+ (yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_UNKNOWN ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_AM33 ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_AMD64 ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_ARM ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_ARMNT ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_ARM64 ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_EBC ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_I386 ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_IA64 ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_M32R ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_MIPS16 ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_MIPSFPU ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_MIPSFPU16 ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_POWERPC ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_POWERPCFP ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_R4000 ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_SH3 ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_SH3DSP ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_SH4 ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_SH5 ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_THUMB ||
+ yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_WCEMIPSV2) &&
data_size > headers_size)
{
return pe_header;
@@ -144,17 +144,17 @@ int64_t pe_rva_to_offset(
int alignment = 0;
int rest = 0;
- while(i < yr_min(pe->header->FileHeader.NumberOfSections, MAX_PE_SECTIONS))
+ while(i < yr_min(yr_le16toh(pe->header->FileHeader.NumberOfSections), MAX_PE_SECTIONS))
{
if (struct_fits_in_pe(pe, section, IMAGE_SECTION_HEADER))
{
- if (lowest_section_rva > section->VirtualAddress)
+ if (lowest_section_rva > yr_le32toh(section->VirtualAddress))
{
- lowest_section_rva = section->VirtualAddress;
+ lowest_section_rva = yr_le32toh(section->VirtualAddress);
}
- if (rva >= section->VirtualAddress &&
- section_rva <= section->VirtualAddress)
+ if (rva >= yr_le32toh(section->VirtualAddress) &&
+ section_rva <= yr_le32toh(section->VirtualAddress))
{
// Round section_offset
//
@@ -167,11 +167,11 @@ int64_t pe_rva_to_offset(
// If FileAlignment is >= 0x200, it is apparently ignored (see
// Ero Carreras's pefile.py, PE.adjust_FileAlignment).
- alignment = yr_min(OptionalHeader(pe, FileAlignment), 0x200);
+ alignment = yr_min(yr_le32toh(OptionalHeader(pe, FileAlignment)), 0x200);
- section_rva = section->VirtualAddress;
- section_offset = section->PointerToRawData;
- section_raw_size = section->SizeOfRawData;
+ section_rva = yr_le32toh(section->VirtualAddress);
+ section_offset = yr_le32toh(section->PointerToRawData);
+ section_raw_size = yr_le32toh(section->SizeOfRawData);
if (alignment)
{
diff --git a/tests/test-elf.c b/tests/test-elf.c
new file mode 100644
index 0000000..8d13b47
--- /dev/null
+++ b/tests/test-elf.c
@@ -0,0 +1,29 @@
+#include <yara.h>
+#include "util.h"
+#include "blob.h"
+
+int main(int argc, char** argv)
+{
+ yr_initialize();
+
+ assert_true_rule_blob("import \"elf\" rule test { condition: elf.type }", ELF32_FILE);
+ assert_true_rule_blob("import \"elf\" rule test { condition: elf.type }", ELF64_FILE);
+
+ assert_true_rule_blob("import \"elf\" rule test { condition: elf.machine == elf.EM_386 }", ELF32_FILE)
+ assert_true_rule_blob("import \"elf\" rule test { condition: elf.machine == elf.EM_X86_64 }", ELF64_FILE)
+
+ assert_true_rule_blob(
+ "import \"elf\" rule test { \
+ strings: $a = { b8 01 00 00 00 bb 2a } \
+ condition: $a at elf.entry_point }",
+ ELF32_FILE);
+
+ assert_true_rule_blob(
+ "import \"elf\" rule test { \
+ strings: $a = { b8 01 00 00 00 bb 2a } \
+ condition: $a at elf.entry_point }",
+ ELF64_FILE);
+
+ yr_finalize();
+ return 0;
+}
diff --git a/tests/test-pe.c b/tests/test-pe.c
index 20aa9de..a1129d0 100644
--- a/tests/test-pe.c
+++ b/tests/test-pe.c
@@ -5,7 +5,6 @@
int main(int argc, char** argv)
{
-#if (defined(HAVE_ENDIAN_H) && BYTE_ORDER == LITTLE_ENDIAN) || defined(_MSC)
yr_initialize();
assert_true_rule_file("import \"pe\" rule test { condition: pe.imports(\"KERNEL32.dll\", \"DeleteCriticalSection\") }",
@@ -27,9 +26,5 @@ int main(int argc, char** argv)
"tests/data/tiny-idata-51ff");
yr_finalize();
-#else
- puts("Not testing pe module on big-endian architectures ... yet");
- exit(77);
-#endif
return 0;
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git
More information about the forensics-changes
mailing list