read dotnet and pe file fields through unaligned helpers (#2210)

This commit is contained in:
jmestwa-coder
2026-06-24 11:49:17 +02:00
committed by GitHub
parent b607da77f4
commit 1d58245c8e
4 changed files with 57 additions and 36 deletions
+43 -34
View File
@@ -1707,9 +1707,9 @@ void dotnet_parse_guid(
sprintf(
guid,
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
yr_le32toh(*(uint32_t*) guid_offset),
yr_le16toh(*(uint16_t*) (guid_offset + 4)),
yr_le16toh(*(uint16_t*) (guid_offset + 6)),
yr_le32toh(yr_unaligned_u32(guid_offset)),
yr_le16toh(yr_unaligned_u16(guid_offset + 4)),
yr_le16toh(yr_unaligned_u16(guid_offset + 6)),
*(guid_offset + 8),
*(guid_offset + 9),
*(guid_offset + 10),
@@ -2192,10 +2192,10 @@ void dotnet_parse_tilde_2(
blob_offset = ((uint8_t*) constant_table) + 2 + index_size;
if (index_sizes.blob == 4)
blob_index = *(DWORD*) blob_offset;
blob_index = yr_unaligned_u32(blob_offset);
else
// Cast the value (index into blob table) to a 32bit value.
blob_index = (DWORD) (*(WORD*) blob_offset);
blob_index = (DWORD) (yr_unaligned_u16(blob_offset));
// Everything checks out. Make sure the index into the blob field
// is valid (non-null and within range).
@@ -2294,7 +2294,7 @@ void dotnet_parse_tilde_2(
// Low 5 bits tell us what this is an index into. Remaining bits
// tell us the index value.
// Parent must be an index into the Assembly (0x0E) table.
if ((*(DWORD*) customattribute_table & 0x1F) != 0x0E)
if ((yr_unaligned_u32(customattribute_table) & 0x1F) != 0x0E)
{
row_ptr += row_size;
continue;
@@ -2305,7 +2305,7 @@ void dotnet_parse_tilde_2(
// Low 5 bits tell us what this is an index into. Remaining bits
// tell us the index value.
// Parent must be an index into the Assembly (0x0E) table.
if ((*(WORD*) customattribute_table & 0x1F) != 0x0E)
if ((yr_unaligned_u16(customattribute_table) & 0x1F) != 0x0E)
{
row_ptr += row_size;
continue;
@@ -2321,27 +2321,27 @@ void dotnet_parse_tilde_2(
// Low 3 bits tell us what this is an index into. Remaining bits
// tell us the index value. Only values 2 and 3 are defined.
// Type must be an index into the MemberRef table.
if ((*(DWORD*) customattribute_table & 0x07) != 0x03)
if ((yr_unaligned_u32(customattribute_table) & 0x07) != 0x03)
{
row_ptr += row_size;
continue;
}
type_index = *(DWORD*) customattribute_table >> 3;
type_index = yr_unaligned_u32(customattribute_table) >> 3;
}
else
{
// Low 3 bits tell us what this is an index into. Remaining bits
// tell us the index value. Only values 2 and 3 are defined.
// Type must be an index into the MemberRef table.
if ((*(WORD*) customattribute_table & 0x07) != 0x03)
if ((yr_unaligned_u16(customattribute_table) & 0x07) != 0x03)
{
row_ptr += row_size;
continue;
}
// Cast the index to a 32bit value.
type_index = (DWORD) ((*(WORD*) customattribute_table >> 3));
type_index = (DWORD) (yr_unaligned_u16(customattribute_table) >> 3);
}
if (type_index > 0)
@@ -2358,27 +2358,27 @@ void dotnet_parse_tilde_2(
// Low 3 bits tell us what this is an index into. Remaining bits
// tell us the index value. Class must be an index into the
// TypeRef table.
if ((*(DWORD*) memberref_row & 0x07) != 0x01)
if ((yr_unaligned_u32(memberref_row) & 0x07) != 0x01)
{
row_ptr += row_size;
continue;
}
class_index = *(DWORD*) memberref_row >> 3;
class_index = yr_unaligned_u32(memberref_row) >> 3;
}
else
{
// Low 3 bits tell us what this is an index into. Remaining bits
// tell us the index value. Class must be an index into the
// TypeRef table.
if ((*(WORD*) memberref_row & 0x07) != 0x01)
if ((yr_unaligned_u16(memberref_row) & 0x07) != 0x01)
{
row_ptr += row_size;
continue;
}
// Cast the index to a 32bit value.
class_index = (DWORD) (*(WORD*) memberref_row >> 3);
class_index = (DWORD) (yr_unaligned_u16(memberref_row) >> 3);
}
if (class_index > 0)
@@ -2407,12 +2407,18 @@ void dotnet_parse_tilde_2(
if (index_sizes.string == 4)
{
name = pe_get_dotnet_string(
pe, string_offset, str_heap_size, *(DWORD*) typeref_row);
pe,
string_offset,
str_heap_size,
yr_unaligned_u32(typeref_row));
}
else
{
name = pe_get_dotnet_string(
pe, string_offset, str_heap_size, *(WORD*) typeref_row);
pe,
string_offset,
str_heap_size,
yr_unaligned_u16(typeref_row));
}
if (name != NULL && strncmp(name, "GuidAttribute", 13) != 0)
@@ -2427,10 +2433,10 @@ void dotnet_parse_tilde_2(
index_size2);
if (index_sizes.blob == 4)
blob_index = *(DWORD*) customattribute_table;
blob_index = yr_unaligned_u32(customattribute_table);
else
// Cast the value (index into blob table) to a 32bit value.
blob_index = (DWORD) (*(WORD*) customattribute_table);
blob_index = (DWORD) (yr_unaligned_u16(customattribute_table));
// Everything checks out. Make sure the index into the blob field
// is valid (non-null and within range).
@@ -2468,7 +2474,7 @@ void dotnet_parse_tilde_2(
}
// Custom attributes MUST have a 16 bit prolog of 0x0001
if (*(WORD*) blob_offset != 0x0001)
if (yr_unaligned_u16(blob_offset) != 0x0001)
{
row_ptr += row_size;
continue;
@@ -2745,15 +2751,16 @@ void dotnet_parse_tilde_2(
pe,
string_offset,
str_heap_size,
yr_le32toh(*(DWORD*) (row_ptr + 4 + 2 + 2 + 2 + 2 + 4 +
index_sizes.blob)));
yr_le32toh(yr_unaligned_u32(
row_ptr + 4 + 2 + 2 + 2 + 2 + 4 + index_sizes.blob)));
else
name = pe_get_dotnet_string(
pe,
string_offset,
str_heap_size,
yr_le16toh(
*(WORD*) (row_ptr + 4 + 2 + 2 + 2 + 2 + 4 + index_sizes.blob)));
yr_unaligned_u16(
row_ptr + 4 + 2 + 2 + 2 + 2 + 4 + index_sizes.blob)));
if (name != NULL)
yr_set_string(name, pe->object, "assembly.name");
@@ -2765,8 +2772,9 @@ void dotnet_parse_tilde_2(
pe,
string_offset,
str_heap_size,
yr_le32toh(*(DWORD*) (row_ptr + 4 + 2 + 2 + 2 + 2 + 4 +
index_sizes.blob + index_sizes.string)));
yr_le32toh(yr_unaligned_u32(
row_ptr + 4 + 2 + 2 + 2 + 2 + 4 + index_sizes.blob +
index_sizes.string)));
}
else
{
@@ -2774,8 +2782,9 @@ void dotnet_parse_tilde_2(
pe,
string_offset,
str_heap_size,
yr_le16toh(*(WORD*) (row_ptr + 4 + 2 + 2 + 2 + 2 + 4 +
index_sizes.blob + index_sizes.string)));
yr_le16toh(yr_unaligned_u16(
row_ptr + 4 + 2 + 2 + 2 + 2 + 4 + index_sizes.blob +
index_sizes.string)));
}
// Sometimes it will be a zero length string. This is technically
@@ -2868,15 +2877,15 @@ void dotnet_parse_tilde_2(
pe,
string_offset,
str_heap_size,
yr_le32toh(
*(DWORD*) (row_ptr + 2 + 2 + 2 + 2 + 4 + index_sizes.blob)));
yr_le32toh(yr_unaligned_u32(
row_ptr + 2 + 2 + 2 + 2 + 4 + index_sizes.blob)));
else
name = pe_get_dotnet_string(
pe,
string_offset,
str_heap_size,
yr_le16toh(
*(WORD*) (row_ptr + 2 + 2 + 2 + 2 + 4 + index_sizes.blob)));
yr_le16toh(yr_unaligned_u16(
row_ptr + 2 + 2 + 2 + 2 + 4 + index_sizes.blob)));
if (name != NULL)
yr_set_string(name, pe->object, "assembly_refs[%i].name", i);
@@ -2943,10 +2952,10 @@ void dotnet_parse_tilde_2(
if (index_size == 4)
implementation = yr_le32toh(
*(DWORD*) (row_ptr + 4 + 4 + index_sizes.string));
yr_unaligned_u32(row_ptr + 4 + 4 + index_sizes.string));
else
implementation = yr_le16toh(
*(WORD*) (row_ptr + 4 + 4 + index_sizes.string));
yr_unaligned_u16(row_ptr + 4 + 4 + index_sizes.string));
row_ptr += row_size;
@@ -2971,7 +2980,7 @@ void dotnet_parse_tilde_2(
continue;
resource_size = yr_le32toh(
*(DWORD*) (pe->data + resource_base + resource_offset));
yr_unaligned_u32(pe->data + resource_base + resource_offset));
// Add 4 to skip the size.
yr_set_integer(
+3 -2
View File
@@ -45,6 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <yara/pe.h>
#include <yara/pe_utils.h>
#include <yara/strutils.h>
#include <yara/unaligned.h>
#include <yara/utils.h>
#define MODULE_NAME pe
@@ -1311,9 +1312,9 @@ uint64_t pe_parse_delay_import_pointer(
return YR_UNDEFINED;
if (IS_64BITS_PE(pe))
return yr_le64toh(*(uint64_t*) data);
return yr_le64toh(yr_unaligned_u64(data));
else
return yr_le32toh(*(uint32_t*) data);
return yr_le32toh(yr_unaligned_u32(data));
}
static void* pe_parse_delayed_imports(PE* pe)
Binary file not shown.
+11
View File
@@ -141,6 +141,17 @@ int main(int argc, char** argv)
"tests/data/"
"bad_dotnet_pe");
// #GUID stream offset is not 4-byte aligned, the guid is read through the
// unaligned helpers so this must parse cleanly (traps under -fsanitize=
// alignment otherwise).
assert_true_rule_file(
"import \"dotnet\" \
rule test { \
condition: \
dotnet.is_dotnet \
}",
"tests/data/dotnet_misaligned_guid");
yr_finalize();
YR_DEBUG_FPRINTF(