Refactor ImageInterpreter

This commit is contained in:
Double Sine 2019-09-27 16:33:50 +08:00
parent 028c90b794
commit c173b0ff50
No known key found for this signature in database
GPG Key ID: 44460E4F43EA8633
6 changed files with 159 additions and 48 deletions

View File

@ -64,8 +64,8 @@ namespace nkg {
NewImage._SectionNameTable[SectionName] = i;
}
NewImage._SectionAddressTable[NewImage._SectionHeaderTable[i].VirtualAddress] = i;
NewImage._SectionOffsetTable[NewImage._SectionHeaderTable[i].PointerToRawData] = i;
NewImage._SectionRvaTable[NewImage._SectionHeaderTable[i].VirtualAddress] = i;
NewImage._SectionFileOffsetTable[NewImage._SectionHeaderTable[i].PointerToRawData] = i;
}
if (!DisableRelocationParsing && NewImage._NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) {
@ -86,14 +86,14 @@ namespace nkg {
case IMAGE_REL_BASED_HIGH:
case IMAGE_REL_BASED_LOW:
case IMAGE_REL_BASED_HIGHADJ:
NewImage._RelocationAddressTable[Rva + (RelocItems[i] & 0x0fff)] = 2;
NewImage._RelocationRvaTable[Rva + (RelocItems[i] & 0x0fff)] = 2;
break;
case IMAGE_REL_BASED_HIGHLOW:
NewImage._RelocationAddressTable[Rva + (RelocItems[i] & 0x0fff)] = 4;
NewImage._RelocationRvaTable[Rva + (RelocItems[i] & 0x0fff)] = 4;
break;
#if defined(IMAGE_REL_BASED_DIR64)
case IMAGE_REL_BASED_DIR64:
NewImage._RelocationAddressTable[Rva + (RelocItems[i] & 0x0fff)] = 8;
NewImage._RelocationRvaTable[Rva + (RelocItems[i] & 0x0fff)] = 8;
break;
#endif
default:
@ -179,7 +179,16 @@ namespace nkg {
}
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeader(PCSTR lpszSectionName) const {
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeader(size_t Idx) const {
if (Idx < _NtHeaders->FileHeader.NumberOfSections) {
return _SectionHeaderTable + Idx;
} else {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Idx is out of range."));
}
}
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeaderByName(PCSTR lpszSectionName) const {
uint64_t NameValue = 0;
for (int i = 0; i < sizeof(NameValue) && lpszSectionName[i]; ++i)
@ -196,9 +205,9 @@ namespace nkg {
}
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeader(uintptr_t Rva) const {
auto it = _SectionAddressTable.upper_bound(Rva);
if (it != _SectionAddressTable.begin()) {
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeaderByRva(uintptr_t Rva) const {
auto it = _SectionRvaTable.upper_bound(Rva);
if (it != _SectionRvaTable.begin()) {
--it;
}
@ -215,15 +224,14 @@ namespace nkg {
}
[[nodiscard]]
uintptr_t ImageInterpreter::RvaToFileOffset(uintptr_t Rva) const {
auto SectionHeader = ImageSectionHeader(Rva);
return SectionHeader->PointerToRawData + (Rva - static_cast<uintptr_t>(SectionHeader->VirtualAddress));
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeaderByVa(uintptr_t Va) const {
return ImageSectionHeaderByRva(Va - _NtHeaders->OptionalHeader.ImageBase);
}
[[nodiscard]]
uintptr_t ImageInterpreter::FileOffsetToRva(uintptr_t FileOffset) const {
auto it = _SectionOffsetTable.upper_bound(FileOffset);
if (it != _SectionOffsetTable.begin()) {
PIMAGE_SECTION_HEADER ImageInterpreter::ImageSectionHeaderByFileOffset(uintptr_t FileOffset) const {
auto it = _SectionFileOffsetTable.upper_bound(FileOffset);
if (it != _SectionFileOffsetTable.begin()) {
--it;
}
@ -232,23 +240,64 @@ namespace nkg {
uintptr_t SectionFileOffsetEnd = SectionFileOffsetBegin + SectionHeader->SizeOfRawData;
if (SectionFileOffsetBegin <= FileOffset && FileOffset < SectionFileOffsetEnd) {
return SectionHeader->VirtualAddress + (FileOffset - SectionHeader->PointerToRawData);
return SectionHeader;
} else {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Target section header is not found."))
.AddHint(std::xstring::format(TEXT("FileOffset = 0x%zx"), FileOffset));
}
}
[[nodiscard]]
uintptr_t ImageInterpreter::RvaToVa(uintptr_t Rva) const noexcept {
return Rva + _NtHeaders->OptionalHeader.ImageBase;
}
[[nodiscard]]
uintptr_t ImageInterpreter::RvaToFileOffset(uintptr_t Rva) const {
auto SectionHeader = ImageSectionHeaderByRva(Rva);
return SectionHeader->PointerToRawData + (Rva - static_cast<uintptr_t>(SectionHeader->VirtualAddress));
}
[[nodiscard]]
uintptr_t ImageInterpreter::FileOffsetToRva(uintptr_t FileOffset) const {
auto SectionHeader = ImageSectionHeaderByFileOffset(FileOffset);
return SectionHeader->VirtualAddress + (FileOffset - SectionHeader->PointerToRawData);
}
[[nodiscard]]
uintptr_t ImageInterpreter::FileOffsetToVa(uintptr_t FileOffset) const {
return FileOffsetToRva(FileOffset) + _NtHeaders->OptionalHeader.ImageBase;
}
[[nodiscard]]
uintptr_t ImageInterpreter::VaToRva(uintptr_t Va) const noexcept {
return Va - _NtHeaders->OptionalHeader.ImageBase;
}
[[nodiscard]]
uintptr_t ImageInterpreter::VaToFileOffset(uintptr_t Va) const {
return ImageSectionHeaderByVa(Va)->PointerToRawData;
}
[[nodiscard]]
bool ImageInterpreter::IsRvaRangeInRelocTable(uintptr_t Rva, size_t Size) const {
auto it = _RelocationAddressTable.upper_bound(Rva);
if (it != _RelocationAddressTable.begin()) {
auto it = _RelocationRvaTable.upper_bound(Rva);
if (it != _RelocationRvaTable.begin()) {
--it;
}
return it->first <= Rva && Rva < it->first + it->second;
}
[[nodiscard]]
bool ImageInterpreter::IsVaRangeInRelocTable(uintptr_t Va, size_t Size) const {
return IsRvaRangeInRelocTable(VaToRva(Va), Size);
}
[[nodiscard]]
bool ImageInterpreter::IsFileOffsetRangeInRelocTable(uintptr_t FileOffset, size_t Size) const {
return IsRvaRangeInRelocTable(FileOffsetToRva(FileOffset), Size);
}
DWORD ImageInterpreter::ImageFileMajorVersion() const {
if (_VsFixedFileInfo) {
return _VsFixedFileInfo->dwFileVersionMS;

View File

@ -21,9 +21,9 @@ namespace nkg {
PIMAGE_NT_HEADERS _NtHeaders;
PIMAGE_SECTION_HEADER _SectionHeaderTable;
std::map<uint64_t, size_t> _SectionNameTable;
std::map<uintptr_t, size_t> _SectionAddressTable;
std::map<uintptr_t, size_t> _SectionOffsetTable;
std::map<uintptr_t, size_t> _RelocationAddressTable;
std::map<uintptr_t, size_t> _SectionRvaTable;
std::map<uintptr_t, size_t> _SectionFileOffsetTable;
std::map<uintptr_t, size_t> _RelocationRvaTable;
VS_FIXEDFILEINFO* _VsFixedFileInfo;
ImageInterpreter();
@ -57,33 +57,48 @@ namespace nkg {
PIMAGE_SECTION_HEADER ImageSectionTable() const noexcept;
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageSectionHeader(PCSTR lpszSectionName) const;
PIMAGE_SECTION_HEADER ImageSectionHeader(size_t Idx) const;
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageSectionHeader(uintptr_t Rva) const;
PIMAGE_SECTION_HEADER ImageSectionHeaderByName(PCSTR lpszSectionName) const;
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageSectionHeaderByRva(uintptr_t Rva) const;
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageSectionHeaderByVa(uintptr_t Va) const;
[[nodiscard]]
PIMAGE_SECTION_HEADER ImageSectionHeaderByFileOffset(uintptr_t FileOffset) const;
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType ImageSectionView(PCSTR lpszSectionName, size_t Offset = 0) const {
return ImageOffset<__PtrType>(ImageSectionHeader(lpszSectionName)->PointerToRawData + Offset);
}
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType ImageSectionView(PIMAGE_SECTION_HEADER SectionHeader, size_t Offset = 0) const {
__PtrType ImageSectionView(PIMAGE_SECTION_HEADER SectionHeader, size_t Offset = 0) const noexcept {
return ImageOffset<__PtrType>(SectionHeader->PointerToRawData + Offset);
}
template<typename __ReturnType, typename __Hint>
template<typename __PtrType = PVOID>
[[nodiscard]]
__ReturnType SearchSection(PCSTR lpszSectionName, __Hint&& Hint) const {
return SearchSection<__ReturnType>(ImageSectionHeader(lpszSectionName), std::forward<__Hint>(Hint));
__PtrType ImageSectionViewByName(PCSTR lpszSectionName, size_t Offset = 0) const {
return ImageOffset<__PtrType>(ImageSectionHeaderByName(lpszSectionName)->PointerToRawData + Offset);
}
template<typename __ReturnType, typename __Hint>
template<typename __PtrType = PVOID>
[[nodiscard]]
__ReturnType SearchSection(PCSTR lpszSectionName, size_t Offset, __Hint&& Hint) const {
return SearchSection<__ReturnType>(ImageSectionHeader(lpszSectionName), Offset, std::forward<__Hint>(Hint));
__PtrType ImageSectionViewByRva(uintptr_t Rva, size_t Offset = 0) const {
return ImageOffset<__PtrType>(ImageSectionHeaderByRva(Rva)->PointerToRawData + Offset);
}
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType ImageSectionViewByVa(uintptr_t Va, size_t Offset = 0) const {
return ImageOffset<__PtrType>(ImageSectionHeaderByVa(Va)->PointerToRawData + Offset);
}
template<typename __PtrType = PVOID>
[[nodiscard]]
__PtrType ImageSectionViewByFileOffset(uintptr_t FileOffset, size_t Offset = 0) const {
return ImageOffset<__PtrType>(ImageSectionHeaderByFileOffset(FileOffset)->PointerToRawData + Offset);
}
template<typename __ReturnType, typename __Hint>
@ -120,11 +135,23 @@ namespace nkg {
throw Exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), TEXT("Data is not found."));
}
template<typename __ReturnType, typename __Hint>
[[nodiscard]]
uintptr_t RvaToFileOffset(uintptr_t Rva) const;
__ReturnType SearchSection(PCSTR lpszSectionName, __Hint&& Hint) const {
return SearchSection<__ReturnType>(ImageSectionHeaderByName(lpszSectionName), std::forward<__Hint>(Hint));
}
template<typename __ReturnType, typename __Hint>
[[nodiscard]]
__ReturnType SearchSection(PCSTR lpszSectionName, size_t Offset, __Hint&& Hint) const {
return SearchSection<__ReturnType>(ImageSectionHeaderByName(lpszSectionName), Offset, std::forward<__Hint>(Hint));
}
[[nodiscard]]
uintptr_t FileOffsetToRva(uintptr_t FileOffset) const;
uintptr_t RvaToVa(uintptr_t Rva) const noexcept;
[[nodiscard]]
uintptr_t RvaToFileOffset(uintptr_t Rva) const;
template<typename __PtrType = PVOID>
[[nodiscard]]
@ -133,12 +160,11 @@ namespace nkg {
return ImageOffset<__PtrType>(RvaToFileOffset(Rva));
}
template<typename __PtrType>
[[nodiscard]]
uintptr_t PointerToRva(__PtrType Ptr) const {
static_assert(std::is_pointer_v<__PtrType>);
return FileOffsetToRva(reinterpret_cast<const volatile char*>(Ptr) - reinterpret_cast<const volatile char*>(_DosHeader));
}
uintptr_t FileOffsetToRva(uintptr_t FileOffset) const;
[[nodiscard]]
uintptr_t FileOffsetToVa(uintptr_t FileOffset) const;
template<typename __PtrType>
[[nodiscard]]
@ -146,6 +172,18 @@ namespace nkg {
return ImageOffset<__PtrType>(FileOffset);
}
[[nodiscard]]
uintptr_t VaToRva(uintptr_t Va) const noexcept;
[[nodiscard]]
uintptr_t VaToFileOffset(uintptr_t Va) const;
template<typename __PtrType>
[[nodiscard]]
__PtrType VaToPointer(uintptr_t Va) const noexcept {
return RvaToPointer<__PtrType>(VaToRva(Va));
}
template<typename __PtrType>
[[nodiscard]]
uintptr_t PointerToFileOffset(__PtrType Ptr) const noexcept {
@ -153,9 +191,33 @@ namespace nkg {
return reinterpret_cast<const volatile char*>(Ptr) - reinterpret_cast<const volatile char*>(_DosHeader);
}
template<typename __PtrType>
[[nodiscard]]
uintptr_t PointerToRva(__PtrType Ptr) const {
return FileOffsetToRva(PointerToFileOffset(Ptr));
}
template<typename __PtrType>
[[nodiscard]]
uintptr_t PointerToVa(__PtrType Ptr) const {
return FileOffsetToVa(PointerToFileOffset(Ptr));
}
[[nodiscard]]
bool IsRvaRangeInRelocTable(uintptr_t Rva, size_t Size) const;
[[nodiscard]]
bool IsVaRangeInRelocTable(uintptr_t Va, size_t Size) const;
[[nodiscard]]
bool IsFileOffsetRangeInRelocTable(uintptr_t FileOffset, size_t Size) const;
template<typename __PtrType>
[[nodiscard]]
bool IsFileOffsetRangeInRelocTable(__PtrType Ptr, size_t Size) const {
return IsRvaRangeInRelocTable(PointerToRva(Ptr), Size);
}
[[nodiscard]]
DWORD ImageFileMajorVersion() const;

View File

@ -55,8 +55,8 @@ namespace nkg {
[[nodiscard]]
bool PatchSolution1::FindPatchOffset() noexcept {
try {
PIMAGE_SECTION_HEADER SectionHeader_text = _Image.ImageSectionHeader(".text");
PIMAGE_SECTION_HEADER SectionHeader_rdata = _Image.ImageSectionHeader(".rdata");
PIMAGE_SECTION_HEADER SectionHeader_text = _Image.ImageSectionHeaderByName(".text");
PIMAGE_SECTION_HEADER SectionHeader_rdata = _Image.ImageSectionHeaderByName(".rdata");
const uint8_t* pbPatch[_countof(_PatchOffset)] = {};
pbPatch[0] = _Image.SearchSection<const uint8_t*>(SectionHeader_rdata, [](const uint8_t* p) {

View File

@ -429,7 +429,7 @@ print('};')
[[nodiscard]]
bool PatchSolution2::FindPatchOffset() noexcept {
try {
auto SectionHeader_text = _Image.ImageSectionHeader(".text");
auto SectionHeader_text = _Image.ImageSectionHeaderByName(".text");
auto SectionView_text = _Image.ImageSectionView<const uint8_t*>(SectionHeader_text);
const uint8_t* lpPatch[_countof(_PatchOffset)] = {};

View File

@ -437,7 +437,7 @@ print('};')
bool PatchSolution2::FindPatchOffset() noexcept {
try {
auto SectionHeader_text = _Image.ImageSectionHeader(".text");
auto SectionHeader_text = _Image.ImageSectionHeaderByName(".text");
auto SectionView_text = _Image.ImageSectionView<const uint8_t*>(SectionHeader_text);
const uint8_t* lpPatch[_countof(_PatchOffset)] = {};

View File

@ -323,7 +323,7 @@ namespace nkg {
}
size_t PublicKeyReadCursor = 0;
auto SectionHeader_rdata = _Image.ImageSectionHeader(".rdata");
auto SectionHeader_rdata = _Image.ImageSectionHeaderByName(".rdata");
auto SectionView_rdata = _Image.ImageSectionView(SectionHeader_rdata);
for (size_t i = 0; i < _countof(_Patch); PublicKeyReadCursor += Keyword[i].Size, ++i) {