image_interpreter.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #pragma once
  2. #include <type_traits>
  3. #include <array>
  4. #include <map>
  5. #include <windows.h>
  6. #include "exception.hpp"
  7. namespace nkg {
  8. class image_interpreter {
  9. public:
  10. using va_t = uintptr_t;
  11. using rva_t = uintptr_t;
  12. using fo_t = uintptr_t;
  13. private:
  14. PIMAGE_DOS_HEADER m_dos_header;
  15. PIMAGE_NT_HEADERS m_nt_headers;
  16. PIMAGE_SECTION_HEADER m_section_header_table;
  17. std::map<std::array<BYTE, 8>, PIMAGE_SECTION_HEADER> m_section_header_name_lookup_table;
  18. std::map<rva_t, PIMAGE_SECTION_HEADER> m_section_header_rva_lookup_table;
  19. std::map<fo_t, PIMAGE_SECTION_HEADER> m_section_header_fo_lookup_table;
  20. std::map<rva_t, size_t> m_relocation_rva_lookup_table;
  21. std::map<rva_t, std::pair<PIMAGE_IMPORT_DESCRIPTOR, PIMAGE_THUNK_DATA>> m_iat_rva_lookup_table;
  22. VS_FIXEDFILEINFO* m_vs_fixed_file_info;
  23. image_interpreter();
  24. static std::array<BYTE, 8> make_section_name(const BYTE (&name)[8]) {
  25. std::array<BYTE, 8> retval;
  26. std::copy(std::begin(name), std::end(name), retval.begin());
  27. return retval;
  28. }
  29. public:
  30. class parse_error : public ::nkg::exception {
  31. public:
  32. parse_error(std::string_view file, int line, std::string_view message) noexcept :
  33. ::nkg::exception(file, line, message) {}
  34. };
  35. [[nodiscard]]
  36. static image_interpreter parse(void* image_base, bool parse_relocation);
  37. template<typename ptr_t = void*>
  38. [[nodiscard]]
  39. ptr_t image_base() const noexcept {
  40. static_assert(std::is_pointer_v<ptr_t>);
  41. return reinterpret_cast<ptr_t>(m_dos_header);
  42. }
  43. [[nodiscard]]
  44. PIMAGE_DOS_HEADER image_dos_header() const noexcept;
  45. [[nodiscard]]
  46. PIMAGE_NT_HEADERS image_nt_headers() const noexcept;
  47. [[nodiscard]]
  48. PIMAGE_SECTION_HEADER image_section_header_table() const noexcept;
  49. [[nodiscard]]
  50. PIMAGE_SECTION_HEADER image_section_header(size_t n) const;
  51. [[nodiscard]]
  52. PIMAGE_SECTION_HEADER image_section_header(std::string_view name) const;
  53. [[nodiscard]]
  54. PIMAGE_SECTION_HEADER image_section_header_from_rva(rva_t rva) const;
  55. [[nodiscard]]
  56. PIMAGE_SECTION_HEADER image_section_header_from_va(va_t va) const;
  57. [[nodiscard]]
  58. PIMAGE_SECTION_HEADER image_section_header_from_fo(fo_t file_offset) const;
  59. [[nodiscard]]
  60. va_t convert_rva_to_va(rva_t rva) const noexcept;
  61. [[nodiscard]]
  62. fo_t convert_rva_to_fo(rva_t rva) const;
  63. template<typename ptr_t = void*>
  64. [[nodiscard]]
  65. ptr_t convert_rva_to_ptr(rva_t rva) const {
  66. static_assert(std::is_pointer_v<ptr_t>);
  67. return convert_fo_to_ptr<ptr_t>(convert_rva_to_fo(rva));
  68. }
  69. [[nodiscard]]
  70. rva_t convert_fo_to_rva(fo_t file_offset) const;
  71. [[nodiscard]]
  72. va_t convert_fo_to_va(fo_t file_offset) const;
  73. template<typename ptr_t>
  74. [[nodiscard]]
  75. ptr_t convert_fo_to_ptr(fo_t file_offset) const noexcept {
  76. static_assert(std::is_pointer_v<ptr_t>);
  77. return reinterpret_cast<ptr_t>(image_base<char*>() + file_offset);
  78. }
  79. [[nodiscard]]
  80. rva_t convert_va_to_rva(va_t va) const noexcept;
  81. [[nodiscard]]
  82. fo_t convert_va_to_fo(va_t va) const;
  83. template<typename ptr_t>
  84. [[nodiscard]]
  85. ptr_t convert_va_to_ptr(va_t va) const noexcept {
  86. return convert_rva_to_ptr<ptr_t>(convert_va_to_rva(va));
  87. }
  88. template<typename ptr_t>
  89. [[nodiscard]]
  90. fo_t convert_ptr_to_fo(ptr_t ptr) const noexcept {
  91. static_assert(std::is_pointer_v<ptr_t>);
  92. return reinterpret_cast<const volatile char*>(ptr) - image_base<const volatile char*>();
  93. }
  94. template<typename ptr_t>
  95. [[nodiscard]]
  96. rva_t convert_ptr_to_rva(ptr_t ptr) const {
  97. return convert_fo_to_rva(convert_ptr_to_fo(ptr));
  98. }
  99. template<typename ptr_t>
  100. [[nodiscard]]
  101. va_t convert_ptr_to_va(ptr_t ptr) const {
  102. return convert_fo_to_va(convert_ptr_to_fo(ptr));
  103. }
  104. [[nodiscard]]
  105. size_t number_of_sections() const noexcept;
  106. template<typename ptr_t = void*>
  107. [[nodiscard]]
  108. ptr_t image_section_view(size_t n, size_t offset = 0) const {
  109. static_assert(std::is_pointer_v<ptr_t>);
  110. return reinterpret_cast<ptr_t>(image_base<char*>() + image_section_header(n)->PointerToRawData + offset);
  111. }
  112. template<typename ptr_t = void*>
  113. [[nodiscard]]
  114. ptr_t image_section_view(std::string_view section_name, size_t offset = 0) const {
  115. static_assert(std::is_pointer_v<ptr_t>);
  116. return reinterpret_cast<ptr_t>(image_base<char*>() + image_section_header(section_name)->PointerToRawData + offset);
  117. }
  118. template<typename ptr_t, typename pred_func_t>
  119. [[nodiscard]]
  120. ptr_t search_section(size_t n, pred_func_t&& pred_func) const {
  121. static_assert(std::is_pointer_v<ptr_t>);
  122. auto section_header = image_section_header(n);
  123. auto begin = image_base<const uint8_t*>() + section_header->PointerToRawData;
  124. auto end = begin + section_header->Misc.VirtualSize;
  125. for (; begin < end; ++begin) {
  126. if (pred_func(begin, end - begin)) {
  127. return reinterpret_cast<ptr_t>(const_cast<uint8_t*>(begin));
  128. }
  129. }
  130. return nullptr;
  131. }
  132. template<typename ptr_t, typename pred_func_t>
  133. [[nodiscard]]
  134. ptr_t search_section(std::string_view section_name, pred_func_t&& pred_func) const {
  135. static_assert(std::is_pointer_v<ptr_t>);
  136. auto section_header = image_section_header(section_name);
  137. auto begin = image_base<const uint8_t*>() + section_header->PointerToRawData;
  138. auto end = begin + section_header->Misc.VirtualSize;
  139. for (; begin < end; ++begin) {
  140. if (pred_func(begin, end - begin)) {
  141. return reinterpret_cast<ptr_t>(const_cast<uint8_t*>(begin));
  142. }
  143. }
  144. return nullptr;
  145. }
  146. PIMAGE_IMPORT_DESCRIPTOR import_descriptor_from_rva(rva_t rva);
  147. PIMAGE_THUNK_DATA import_lookup_entry_from_rva(rva_t rva);
  148. auto& relocation_distribute() {
  149. return m_relocation_rva_lookup_table;
  150. }
  151. };
  152. }