Skip to content

Wrong offset used when checking Version string of .net metadata #1708

@dangodangodango

Description

@dangodangodango

offset = metadata_root = pe_rva_to_offset(
pe, yr_le32toh(cli_header->MetaData.VirtualAddress));
if (!struct_fits_in_pe(pe, pe->data + offset, NET_METADATA))
return;
metadata = (PNET_METADATA) (pe->data + offset);
// Version length must be between 1 and 255, and be a multiple of 4.
// Also make sure it fits in pe.
md_len = yr_le32toh(metadata->Length);
if (md_len == 0 || md_len > 255 || md_len % 4 != 0 ||
!fits_in_pe(pe, pe->data + offset, md_len))
{
return;
}

int64_t metadata_root = pe_rva_to_offset(
pe, yr_le32toh(cli_header->MetaData.VirtualAddress));
if (!struct_fits_in_pe(pe, pe->data + metadata_root, NET_METADATA))
return false;
NET_METADATA* metadata = (NET_METADATA*) (pe->data + metadata_root);
if (yr_le32toh(metadata->Magic) != NET_METADATA_MAGIC)
return false;
// Version length must be between 1 and 255, and be a multiple of 4.
// Also make sure it fits in pe.
uint32_t md_len = yr_le32toh(metadata->Length);
if (md_len == 0 || md_len > 255 || md_len % 4 != 0 ||
!fits_in_pe(pe, pe->data + offset, md_len))
{
return false;
}

The above two places (line 1653 and line 1724) are checking whether metadata version string is fits in pe, Version string offset is pe->data + offset + sizeof(NET_METADATA), and size is md_len. But the above code checks the md_len bytes starting from offset (which is metadata_root)

The correct code should be as follows:

!fits_in_pe(pe, pe->data + offset + sizeof(NET_METADATA), md_len)

And in the function dotnet_is_dotnet, the variable offset is not updated to metadata_root, so in line 1653, offset is still the offset of CLI_HEADER, this is also a problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions