ベタ書きですが、C++で64ビットPEファイルの各種ヘッダーとデータディレクトリの物理アドレスを取得するサンプルです。
IMAGE_OPTIONAL_HEADERのDataDirectory[]に含まれるIMAGE_DATA_DIRECTORYの実体はIMAGE_SECTION_HEADERの指す各セクションに含まれており、その物理アドレスはそれぞれの仮想アドレスの差と所属するIMAGE_SECTION_HEADERのPointerToRawDataの和で取得できます。詳しくはコードで。
// 64ビットPE形式ファイルに含まれるセクションとセクションに含まれるデータディレクトリを列挙します。 #include <iostream> #include <iomanip> #include <fstream> #include <memory> #define STRICT #include <Windows.h> const wchar_t* const ImageDataDirectoryNames[] = { L"Export", L"Import", L"Resource", L"Exception", L"Security", L"Base Relocation", L"Debug", L"Architecture", L"Global Pointer", L"TLS", L"Load Config", L"Bound Import", L"IAT", L"Delay Import", L"COM DEscriptor" }; inline std::wstring convert_ansi_string_to_wstring( const char* const s, size_t len) noexcept(false); bool parse_pefile64( const std::byte* base, const IMAGE_DOS_HEADER** imgDosHdr, const IMAGE_NT_HEADERS64** imgNtHdrs) noexcept(false); bool ImageSectionHeaderContainsImageDataDirectory( const IMAGE_SECTION_HEADER& sectionHeader, const IMAGE_DATA_DIRECTORY& dataDirectory) noexcept; using unique_HANDLE = std::unique_ptr<std::remove_pointer_t<HANDLE>, decltype(&CloseHandle)>; template <typename T> using unique_MapViewOfFile_HANDLE = std::unique_ptr<T, decltype(&UnmapViewOfFile)>; inline auto to_unique_HANDLE(HANDLE handle) { return unique_HANDLE(handle, &CloseHandle); } template <typename T> inline auto to_unique_MapViewOfFile_HANDLE(void* p) { return unique_MapViewOfFile_HANDLE<std::byte>( reinterpret_cast<std::byte*>(p, &UnmapViewOfFile); } int wmain() { unique_HANDLE fileHandle = to_unique_HANDLE( CreateFileW(L"C:\\Windows\\System32\\User32.dll", GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr)); unique_HANDLE fileMapHandle = to_unique_HANDLE( CreateFileMappingW(fileHandle.get(), nullptr, PAGE_READONLY, 0, 0, nullptr)); auto data = to_unique_MapViewOfFile_HANDLE<std::byte>( MapViewOfFile(fileMapHandle.get(), FILE_MAP_READ, 0, 0, 0)); const IMAGE_DOS_HEADER* dosHeader; const IMAGE_NT_HEADERS64* ntHeaders; if (!parse_pefile64(data.get(), &dosHeader, &ntHeaders)) { std::wcout << L"ファイルは64ビットのPE形式ではありません。" << std::endl; return -1; } auto firstSectionHeader = reinterpret_cast<const PIMAGE_SECTION_HEADER>IMAGE_FIRST_SECTION(ntHeaders); for (unsigned i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) { auto psectionHeader = firstSectionHeader + i; auto sectionName = convert_ansi_string_to_wstring( reinterpret_cast<const char*>(psectionHeader->Name), IMAGE_SIZEOF_SHORT_NAME); std::wcout << sectionName.c_str() << std::endl; std::wcout << L"Raw Address: 0x" << std::hex << std::setfill(L'0') << std::setw(8) << psectionHeader->PointerToRawData << std::endl; std::wcout << L"Raw Size: " << std::dec << psectionHeader->SizeOfRawData << L" byte" << std::endl; // セクションに含まれるデータディレクトリを列挙する for (unsigned int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) { const auto& dataDir = ntHeaders->OptionalHeader.DataDirectory[i]; if (ImageSectionHeaderContainsImageDataDirectory(*psectionHeader, dataDir)) { // ディレクトリはセクションの内部に含まれる。 auto offset = static_cast<ptrdiff_t>(dataDir.VirtualAddress) - psectionHeader->VirtualAddress; std::wcout << L" 0x" << std::hex << std::setw(8) << std::setfill(L'0') << offset << L" " << ImageDataDirectoryNames[i] << std::endl; } } std::wcout << std::endl; } return 0; } inline std::wstring convert_ansi_string_to_wstring( const char* const s, size_t len) noexcept(false) { if (s == nullptr) throw new std::invalid_argument(""); return std::wstring(s, s + len); } bool parse_pefile64( const std::byte* base, const IMAGE_DOS_HEADER** imgDosHdr, const IMAGE_NT_HEADERS64** imgNtHdrs) noexcept(false) { if (base == nullptr || imgDosHdr == nullptr || imgNtHdrs == nullptr) throw new std::invalid_argument(""); auto dosHeader = reinterpret_cast<const IMAGE_DOS_HEADER*>(base); if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) return false; auto signature = reinterpret_cast<const DWORD*>(base + dosHeader->e_lfanew); if (*signature != IMAGE_NT_SIGNATURE) return false; auto fileHeader = reinterpret_cast<const IMAGE_FILE_HEADER*>(signature + 1); if (fileHeader->SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER64)) return false; auto optionalHeader = reinterpret_cast<const IMAGE_OPTIONAL_HEADER64*>(fileHeader + 1); if (optionalHeader->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) return false; *imgDosHdr = dosHeader; *imgNtHdrs = reinterpret_cast<const IMAGE_NT_HEADERS64*>(signature); return true; } bool ImageSectionHeaderContainsImageDataDirectory( const IMAGE_SECTION_HEADER& sectionHeader, const IMAGE_DATA_DIRECTORY& dataDirectory) noexcept { auto sec_lo = sectionHeader.VirtualAddress; auto sec_hi = sectionHeader.VirtualAddress + sectionHeader.SizeOfRawData; auto dir_lo = dataDirectory.VirtualAddress; auto dir_hi = dataDirectory.VirtualAddress + dataDirectory.Size; return sec_lo <= dir_lo && dir_hi <= sec_hi; }