コード例 #1
0
ファイル: pe_utils.c プロジェクト: jbremer/yara
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;
}
コード例 #2
0
ファイル: pe.c プロジェクト: codingdream/yara
void pe_parse(
    PE* pe,
    size_t base_address,
    int flags)
{
  PIMAGE_SECTION_HEADER section;

  char section_name[IMAGE_SIZEOF_SHORT_NAME + 1];

#define OptionalHeader(field) \
  (pe->header->FileHeader.Machine == 0x8664 ? \
   ((PIMAGE_NT_HEADERS64) pe->header)->OptionalHeader.field : \
     pe->header->OptionalHeader.field)

  set_integer(
      pe->header->FileHeader.Machine,
      pe->object, "machine");

  set_integer(
      pe->header->FileHeader.NumberOfSections,
      pe->object, "number_of_sections");

  set_integer(
      pe->header->FileHeader.TimeDateStamp,
      pe->object, "timestamp");

  set_integer(
      pe->header->FileHeader.Characteristics,
      pe->object, "characteristics");

  set_integer(
      flags & SCAN_FLAGS_PROCESS_MEMORY ?
        base_address + OptionalHeader(AddressOfEntryPoint) :
        pe_rva_to_offset(pe, OptionalHeader(AddressOfEntryPoint)),
      pe->object, "entry_point");

  set_integer(
      OptionalHeader(ImageBase),
      pe->object, "image_base");

  set_integer(
      OptionalHeader(MajorLinkerVersion),
      pe->object, "linker_version.major");

  set_integer(
      OptionalHeader(MinorLinkerVersion),
      pe->object, "linker_version.minor");

  set_integer(
      OptionalHeader(MajorOperatingSystemVersion),
      pe->object, "os_version.major");

  set_integer(
      OptionalHeader(MinorOperatingSystemVersion),
      pe->object, "os_version.minor");

  set_integer(
      OptionalHeader(MajorImageVersion),
      pe->object, "image_version.major");

  set_integer(
      OptionalHeader(MinorImageVersion),
      pe->object, "image_version.minor");

  set_integer(
      OptionalHeader(MajorSubsystemVersion),
      pe->object, "subsystem_version.major");

  set_integer(
      OptionalHeader(MinorSubsystemVersion),
      pe->object, "subsystem_version.minor");

  set_integer(
      OptionalHeader(Subsystem),
      pe->object, "subsystem");

  pe_iterate_resources(
      pe,
      (RESOURCE_CALLBACK_FUNC) pe_find_version_info_cb,
      (void*) pe);

  section = IMAGE_FIRST_SECTION(pe);

  int scount = min(pe->header->FileHeader.NumberOfSections, MAX_PE_SECTIONS);

  for (int i = 0; i < scount; i++)
  {
    if ((uint8_t*) section -
        (uint8_t*) pe + sizeof(IMAGE_SECTION_HEADER) >= pe->data_size)
    {
      break;
    }

    strlcpy(section_name, (char*) section->Name, IMAGE_SIZEOF_SHORT_NAME + 1);

    set_string(
        section_name,
        pe->object, "sections[%i].name", i);

    set_integer(
        section->Characteristics,
        pe->object, "sections[%i].characteristics", i);

    set_integer(section->SizeOfRawData,
        pe->object, "sections[%i].raw_data_size", i);

    set_integer(section->PointerToRawData,
        pe->object, "sections[%i].raw_data_offset", i);

    set_integer(section->VirtualAddress,
        pe->object, "sections[%i].virtual_address", i);

    set_integer(
        section->Misc.VirtualSize,
        pe->object, "sections[%i].virtual_size", i);

    section++;
  }
}
コード例 #3
0
bool FindProtectorSection(types::simple_ptr<unsigned char> ImgBase, ProtectorSectionInfo & info)
{
    // if the section is already found?
    for(UINT x = 0; x<ProtectorSections.size(); x++)
    {
        if (ProtectorSections[x].ImgBase == ImgBase)
        {
            if (ProtectorSections[x].pProtectorSection != NULL)
            {
                info = ProtectorSections[x];
                return true;
            }
            return false; // caller section is found, but the .ipn1 section is not. the caller assembly is not protected
        }
    }

    // if not - find the section
    types::simple_ptr<IMAGE_DOS_HEADER> DosHeader(reinterpret_cast<IMAGE_DOS_HEADER*>((unsigned char*)ImgBase));
    types::simple_ptr<IMAGE_FILE_HEADER> FileHeader(reinterpret_cast<IMAGE_FILE_HEADER*>(ImgBase + DosHeader->e_lfanew + sizeof(IMAGE_NT_SIGNATURE)));
    types::simple_ptr<IMAGE_OPTIONAL_HEADER> OptionalHeader(reinterpret_cast<IMAGE_OPTIONAL_HEADER*>(ImgBase + sizeof(IMAGE_FILE_HEADER)));

    types::simple_ptr<unsigned char> SectHeadersOffset(ImgBase + DosHeader->e_lfanew + sizeof(IMAGE_NT_SIGNATURE) + sizeof (IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));

    types::simple_ptr<unsigned char> SectionHeaderStart;
    types::simple_ptr<IMAGE_SECTION_HEADER> SectionHeader;
    for(unsigned short i = 0; i < FileHeader->NumberOfSections; i++ )
    {
        SectionHeaderStart = types::simple_ptr<unsigned char> (SectHeadersOffset + i * sizeof(IMAGE_SECTION_HEADER));
        SectionHeader = reinterpret_cast<IMAGE_SECTION_HEADER*>((unsigned char*)SectionHeaderStart);

        if (strcmp(const_cast<const char*>(reinterpret_cast<char*>(&SectionHeader->Name[0])), ".ipn1") == 0)
        {
            info.ImgBase = ImgBase;
            info.pProtectorSection = reinterpret_cast<unsigned char*>(SectionHeader->VirtualAddress);
            types::simple_ptr<unsigned char> position(SectionHeader->VirtualAddress + ImgBase);

            ReadProtectorSectionData(position, info);


            // Move the offset according to the RVA not the physical offset
            // 1. Find the correct section for the physical offset
            for(unsigned int j =0; j < FileHeader->NumberOfSections; j++)
            {
                SectionHeaderStart  = types::simple_ptr<unsigned char>(SectHeadersOffset + j * sizeof(IMAGE_SECTION_HEADER));
                SectionHeader = types::simple_ptr<IMAGE_SECTION_HEADER>(reinterpret_cast<IMAGE_SECTION_HEADER*>((unsigned char*)SectionHeaderStart));

                if ((SectionHeader->PointerToRawData < info.w32HookCoreNameOffset)
                        && (info.w32HookCoreNameOffset < SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData ))
                {
                    // 2. Section found. update references
                    unsigned int w32SectionStartRva = info.w32HookCoreNameOffset - SectionHeader->PointerToRawData;
                    unsigned int x64SectionStartRva = info.x64HookCoreNameOffset - SectionHeader->PointerToRawData;

                    // 3. Set the offset from the ImageBase with taking into account section virtual address
                    info.w32HookCoreNameOffset = (unsigned int)(SectionHeader->VirtualAddress + w32SectionStartRva);
                    info.x64HookCoreNameOffset = (unsigned int)(SectionHeader->VirtualAddress + x64SectionStartRva);
                    break;
                }
            }

            return true;
        }
    }

    info.ImgBase = ImgBase;

    return false;
}