Esempio n. 1
0
PIMAGE_NT_HEADERS32 yr_get_pe_header(
    const uint8_t* buffer,
    size_t buffer_length)
{
  PIMAGE_DOS_HEADER mz_header;
  PIMAGE_NT_HEADERS32 pe_header;

  size_t headers_size = 0;

  if (buffer_length < sizeof(IMAGE_DOS_HEADER))
    return NULL;

  mz_header = (PIMAGE_DOS_HEADER) buffer;

  if (yr_le16toh(mz_header->e_magic) != IMAGE_DOS_SIGNATURE)
    return NULL;

  if ((int32_t) yr_le32toh(mz_header->e_lfanew) < 0)
    return NULL;

  headers_size = yr_le32toh(mz_header->e_lfanew) + \
                 sizeof(pe_header->Signature) + \
                 sizeof(IMAGE_FILE_HEADER);

  if (buffer_length < headers_size)
    return NULL;

  pe_header = (PIMAGE_NT_HEADERS32) (buffer + yr_le32toh(mz_header->e_lfanew));

  headers_size += sizeof(IMAGE_OPTIONAL_HEADER32);

  if (yr_le32toh(pe_header->Signature) == IMAGE_NT_SIGNATURE &&
      (yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_I386 ||
       yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_AMD64) &&
      buffer_length > headers_size)
  {
    return pe_header;
  }
  else
  {
    return NULL;
  }
}
Esempio n. 2
0
uint64_t yr_pe_rva_to_offset(
    PIMAGE_NT_HEADERS32 pe_header,
    uint64_t rva,
    size_t buffer_length)
{
  int i = 0;
  PIMAGE_SECTION_HEADER section;
  DWORD section_rva;
  DWORD section_offset;

  section = IMAGE_FIRST_SECTION(pe_header);
  section_rva = 0;
  section_offset = 0;

  while(i < MIN(yr_le16toh(pe_header->FileHeader.NumberOfSections), 60))
  {
    if ((uint8_t*) section - \
        (uint8_t*) pe_header + sizeof(IMAGE_SECTION_HEADER) < buffer_length)
    {
      if (rva >= section->VirtualAddress &&
          section_rva <= yr_le32toh(section->VirtualAddress))
      {
        section_rva = yr_le32toh(section->VirtualAddress);
        section_offset = yr_le32toh(section->PointerToRawData);
      }

      section++;
      i++;
    }
    else
    {
      return 0;
    }
  }

  return section_offset + (rva - section_rva);
}
Esempio n. 3
0
PIMAGE_NT_HEADERS32 pe_get_header(
    uint8_t* data,
    size_t data_size)
{
  PIMAGE_DOS_HEADER mz_header;
  PIMAGE_NT_HEADERS32 pe_header;

  size_t headers_size = 0;

  if (data_size < sizeof(IMAGE_DOS_HEADER))
    return NULL;

  mz_header = (PIMAGE_DOS_HEADER) data;

  if (yr_le16toh(mz_header->e_magic) != IMAGE_DOS_SIGNATURE)
    return NULL;

  if (yr_le32toh(mz_header->e_lfanew) < 0)
    return NULL;

  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 + 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;
  }
  else
  {
    return NULL;
  }
}
Esempio n. 4
0
static uint64_t yr_elf_rva_to_offset_64(
    elf64_header_t* elf_header,
    uint64_t rva,
    size_t buffer_length)
{
  // if the binary is an executable then prefer the program headers to resolve
  // the offset
  if (yr_le16toh(elf_header->type) == ELF_ET_EXEC)
  {
    int i;
    elf64_program_header_t* program;
    if (yr_le64toh(elf_header->ph_offset) == 0 ||
        yr_le16toh(elf_header->ph_entry_count == 0))
      return 0;

    // check that 'ph_offset' doesn't wrap when added to the
    // size of entries.
    if(ULONG_MAX - yr_le64toh(elf_header->ph_offset) <
     sizeof(elf64_program_header_t) * yr_le16toh(elf_header->ph_entry_count))
      return 0;

    // ensure we don't exceed the buffer size
    if (yr_le64toh(elf_header->ph_offset) + sizeof(elf64_program_header_t) *
        yr_le16toh(elf_header->ph_entry_count) > buffer_length)
      return 0;

    program = (elf64_program_header_t*)
      ((uint8_t*) elf_header + yr_le64toh(elf_header->ph_offset));

    for (i = 0; i < yr_le16toh(elf_header->ph_entry_count); i++)
    {
      if (rva >= yr_le64toh(program->virt_addr) &&
          rva <  yr_le64toh(program->virt_addr) + yr_le64toh(program->mem_size))
      {
        return yr_le64toh(program->offset) + (rva - yr_le64toh(program->virt_addr));
      }

      program++;
    }
  }
  else
  {
    int i;
    elf64_section_header_t* section;

    if (yr_le64toh(elf_header->sh_offset) == 0 ||
        yr_le16toh(elf_header->sh_entry_count) == 0)
      return 0;

    // check that 'sh_offset' doesn't wrap when added to the
    // size of entries.
    if(ULONG_MAX - yr_le64toh(elf_header->sh_offset) <
     sizeof(elf64_section_header_t) * yr_le16toh(elf_header->sh_entry_count))
      return 0;

    if (yr_le64toh(elf_header->sh_offset) + sizeof(elf64_section_header_t) *
        yr_le16toh(elf_header->sh_entry_count) > buffer_length)
      return 0;

    section = (elf64_section_header_t*)
      ((uint8_t*) elf_header + yr_le64toh(elf_header->sh_offset));

    for (i = 0; i < yr_le16toh(elf_header->sh_entry_count); i++)
    {
      if (yr_le32toh(section->type) != ELF_SHT_NULL &&
          yr_le32toh(section->type) != ELF_SHT_NOBITS &&
          rva >= yr_le64toh(section->addr) &&
          rva <  yr_le64toh(section->addr) + yr_le64toh(section->size))
      {
        return yr_le64toh(section->offset) + (rva - yr_le64toh(section->addr));
      }

      section++;
    }
  }

  return 0;
}
Esempio n. 5
0
int64_t pe_rva_to_offset(
    PE* pe,
    uint64_t rva)
{
  PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pe->header);

  DWORD lowest_section_rva = 0xffffffff;
  DWORD section_rva = 0;
  DWORD section_offset = 0;
  DWORD section_raw_size = 0;

  int64_t result;

  int i = 0;

  int alignment = 0;
  int rest = 0;

  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 > yr_le32toh(section->VirtualAddress))
      {
        lowest_section_rva = yr_le32toh(section->VirtualAddress);
      }

      if (rva >= yr_le32toh(section->VirtualAddress) &&
          section_rva <= yr_le32toh(section->VirtualAddress))
      {
        // Round section_offset
        //
        // Rounding everything less than 0x200 to 0 as discussed in
        // https://code.google.com/archive/p/corkami/wikis/PE.wiki#PointerToRawData
        // does not work for PE32_FILE from the test suite and for
        // some tinype samples where File Alignment = 4
        // (http://www.phreedom.org/research/tinype/).
        //
        // If FileAlignment is >= 0x200, it is apparently ignored (see
        // Ero Carreras's pefile.py, PE.adjust_FileAlignment).

        alignment = yr_min(yr_le32toh(OptionalHeader(pe, FileAlignment)), 0x200);

        section_rva = yr_le32toh(section->VirtualAddress);
        section_offset = yr_le32toh(section->PointerToRawData);
        section_raw_size = yr_le32toh(section->SizeOfRawData);

        if (alignment)
        {
          rest = section_offset % alignment;

          if (rest)
            section_offset -= rest;
        }
      }

      section++;
      i++;
    }
    else
    {
      return -1;
    }
  }

  // Everything before the first section seems to get mapped straight
  // relative to ImageBase.

  if (rva < lowest_section_rva)
  {
    section_rva = 0;
    section_offset = 0;
    section_raw_size = (DWORD) pe->data_size;
  }

  // Many sections, have a raw (on disk) size smaller than their in-memory size.
  // Check for rva's that map to this sparse space, and therefore have no valid
  // associated file offset.

  if ((rva - section_rva) >= section_raw_size)
    return -1;

  result = section_offset + (rva - section_rva);

  // Check that the offset fits within the file.
  if (result >= pe->data_size)
    return -1;

  return result;
}