pe_image_reader.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_WIN_PE_IMAGE_READER_H_
  5. #define BASE_WIN_PE_IMAGE_READER_H_
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <windows.h>
  9. #include <memory>
  10. #include "base/base_export.h"
  11. #include "base/macros.h"
  12. namespace base {
  13. namespace win {
  14. // Parses headers and various data from a PE image. This parser is safe for use
  15. // on untrusted data and works on PE files with different bitness from the
  16. // current process. The PeImageReader is initialized after construction by
  17. // passing the address and size of a PE file that has been read into memory -
  18. // not loaded by the OS as an image. Parsing of a PE file that has been loaded
  19. // as an image can be done with PEImage.
  20. class BASE_EXPORT PeImageReader {
  21. public:
  22. enum WordSize {
  23. WORD_SIZE_32,
  24. WORD_SIZE_64,
  25. };
  26. // A callback invoked by EnumCertificates once for each attribute certificate
  27. // entry in the image's attribute certificate table. |revision| and
  28. // |certificate_type| identify the contents of |certificate_data| (which is of
  29. // |certificate_data_size| bytes). |context| is the value provided by the
  30. // caller to EnumCertificates(). Implementations must return true to continue
  31. // the enumeration, or false to abort.
  32. typedef bool (*EnumCertificatesCallback)(uint16_t revision,
  33. uint16_t certificate_type,
  34. const uint8_t* certificate_data,
  35. size_t certificate_data_size,
  36. void* context);
  37. PeImageReader();
  38. ~PeImageReader();
  39. // Returns false if the given data does not appear to be a valid PE image.
  40. bool Initialize(const uint8_t* image_data, size_t image_size);
  41. // Returns the machine word size for the image.
  42. WordSize GetWordSize();
  43. const IMAGE_DOS_HEADER* GetDosHeader();
  44. const IMAGE_FILE_HEADER* GetCoffFileHeader();
  45. // Returns a pointer to the optional header and its size.
  46. const uint8_t* GetOptionalHeaderData(size_t* optional_data_size);
  47. size_t GetNumberOfSections();
  48. const IMAGE_SECTION_HEADER* GetSectionHeaderAt(size_t index);
  49. // Returns a pointer to the image's export data (.edata) section and its size,
  50. // or nullptr if the section is not present.
  51. const uint8_t* GetExportSection(size_t* section_size);
  52. size_t GetNumberOfDebugEntries();
  53. const IMAGE_DEBUG_DIRECTORY* GetDebugEntry(size_t index,
  54. const uint8_t** raw_data,
  55. size_t* raw_data_size);
  56. // Invokes |callback| once per attribute certificate entry. |context| is a
  57. // caller-specific value that is passed to |callback|. Returns true if all
  58. // certificate entries are visited (even if there are no such entries) and
  59. // |callback| returns true for each. Conversely, returns |false| if |callback|
  60. // returns false or if the image is malformed in any way.
  61. bool EnumCertificates(EnumCertificatesCallback callback, void* context);
  62. // Returns the size of the image file.
  63. DWORD GetSizeOfImage();
  64. private:
  65. // Bits indicating what portions of the image have been validated.
  66. enum ValidationStages {
  67. VALID_DOS_HEADER = 1 << 0,
  68. VALID_PE_SIGNATURE = 1 << 1,
  69. VALID_COFF_FILE_HEADER = 1 << 2,
  70. VALID_OPTIONAL_HEADER = 1 << 3,
  71. VALID_SECTION_HEADERS = 1 << 4,
  72. };
  73. // An interface to an image's optional header.
  74. class OptionalHeader {
  75. public:
  76. virtual ~OptionalHeader() {}
  77. virtual WordSize GetWordSize() = 0;
  78. // Returns the offset of the DataDirectory member relative to the start of
  79. // the optional header.
  80. virtual size_t GetDataDirectoryOffset() = 0;
  81. // Returns the number of entries in the data directory.
  82. virtual DWORD GetDataDirectorySize() = 0;
  83. // Returns a pointer to the first data directory entry.
  84. virtual const IMAGE_DATA_DIRECTORY* GetDataDirectoryEntries() = 0;
  85. // Returns the size of the image file.
  86. virtual DWORD GetSizeOfImage() = 0;
  87. };
  88. template <class OPTIONAL_HEADER_TYPE>
  89. class OptionalHeaderImpl;
  90. void Clear();
  91. bool ValidateDosHeader();
  92. bool ValidatePeSignature();
  93. bool ValidateCoffFileHeader();
  94. bool ValidateOptionalHeader();
  95. bool ValidateSectionHeaders();
  96. // Return a pointer to the first byte of the image's optional header.
  97. const uint8_t* GetOptionalHeaderStart();
  98. size_t GetOptionalHeaderSize();
  99. // Returns the desired directory entry, or nullptr if |index| is out of
  100. // bounds.
  101. const IMAGE_DATA_DIRECTORY* GetDataDirectoryEntryAt(size_t index);
  102. // Returns the header for the section that contains the given address, or
  103. // nullptr if the address is out of bounds or the image does not contain the
  104. // section.
  105. const IMAGE_SECTION_HEADER* FindSectionFromRva(uint32_t relative_address);
  106. // Returns a pointer to the |data_length| bytes referenced by the |index|'th
  107. // data directory entry.
  108. const uint8_t* GetImageData(size_t index, size_t* data_length);
  109. // Populates |structure| with a pointer to a desired structure of type T at
  110. // the given offset if the image is sufficiently large to contain it. Returns
  111. // false if the structure does not fully fit within the image at the given
  112. // offset.
  113. template <typename T>
  114. bool GetStructureAt(size_t offset, const T** structure) {
  115. return GetStructureAt(offset, sizeof(**structure), structure);
  116. }
  117. // Populates |structure| with a pointer to a desired structure of type T at
  118. // the given offset if the image is sufficiently large to contain
  119. // |structure_size| bytes. Returns false if the structure does not fully fit
  120. // within the image at the given offset.
  121. template <typename T>
  122. bool GetStructureAt(size_t offset,
  123. size_t structure_size,
  124. const T** structure) {
  125. if (offset > image_size_)
  126. return false;
  127. if (structure_size > image_size_ - offset)
  128. return false;
  129. *structure = reinterpret_cast<const T*>(image_data_ + offset);
  130. return true;
  131. }
  132. const uint8_t* image_data_;
  133. size_t image_size_;
  134. uint32_t validation_state_;
  135. std::unique_ptr<OptionalHeader> optional_header_;
  136. DISALLOW_COPY_AND_ASSIGN(PeImageReader);
  137. };
  138. } // namespace win
  139. } // namespace base
  140. #endif // BASE_WIN_PE_IMAGE_READER_H_