From 0dc118cd7534da4ae3bfd5598d9bae5233663c4f Mon Sep 17 00:00:00 2001 From: mrexodia Date: Tue, 9 Feb 2016 13:30:36 +0100 Subject: [PATCH] added rva <-> offset conversion functions --- GleeBug/Static.Pe.Section.h | 5 +- GleeBug/Static.Pe.cpp | 103 ++++++++++++++++++++++++++++-------- GleeBug/Static.Pe.h | 26 ++++++++- MyDebugger/main.cpp | 17 +++++- 4 files changed, 123 insertions(+), 28 deletions(-) diff --git a/GleeBug/Static.Pe.Section.h b/GleeBug/Static.Pe.Section.h index 9fdaa22..cb1ee7e 100644 --- a/GleeBug/Static.Pe.Section.h +++ b/GleeBug/Static.Pe.Section.h @@ -8,8 +8,9 @@ namespace GleeBug class Section { public: - explicit Section(uint16 index, Region & headers, Region beforeData, Region data) + explicit Section(uint16 index, uint32 alignment, Region & headers, Region beforeData, Region data) : mIndex(index), + mAlignment(alignment), mHeaders(headers), mBeforeData(beforeData), mData(data) @@ -17,6 +18,7 @@ namespace GleeBug } uint16 GetIndex() const { return mIndex; } + uint32 GetAlignment() const { return mAlignment; } IMAGE_SECTION_HEADER & GetHeader() { return mHeaders[mIndex]; } const IMAGE_SECTION_HEADER & GetHeader() const { return mHeaders[mIndex]; } const Region & GetBeforeData() const { return mBeforeData; } @@ -24,6 +26,7 @@ namespace GleeBug private: uint16 mIndex; + uint32 mAlignment; Region mHeaders; Region mBeforeData; Region mData; diff --git a/GleeBug/Static.Pe.cpp b/GleeBug/Static.Pe.cpp index 131cb64..d94d69a 100644 --- a/GleeBug/Static.Pe.cpp +++ b/GleeBug/Static.Pe.cpp @@ -177,7 +177,37 @@ namespace GleeBug return ErrorOk; } - Pe::Error Pe::parseSections(uint16 count) + uint32 Pe::ConvertOffsetToRva(uint32 offset) + { + if (!mOffsetSectionMap.size()) //TODO: verify this (no sections means direct mapping) + return offset; + const auto found = mOffsetSectionMap.find(Range(offset, offset)); + if (found == mOffsetSectionMap.end()) + return INVALID_VALUE; + auto index = found->second; + if (index == HeaderSection) + return offset; + const auto & section = mSections[index]; + offset -= uint32(found->first.first); //adjust the offset to be relative to the offset range in the map + return alignAdjustAddress(section.GetHeader().VirtualAddress, section.GetAlignment()) + offset; + } + + uint32 Pe::ConvertRvaToOffset(uint32 rva) + { + if (!mRvaSectionMap.size()) //TODO: verify this (no sections means direct mapping) + return rva; + const auto found = mRvaSectionMap.find(Range(rva, rva)); + if (found == mRvaSectionMap.end()) + return INVALID_VALUE; + auto index = found->second; + if (index == HeaderSection) + return rva; + const auto & section = mSections[index]; + rva -= uint32(found->first.first); //adjust the rva to be relative to the rva range in the map + return section.GetHeader().PointerToRawData + rva; + } + + Pe::Error Pe::parseSections(uint16 count, uint32 alignment) { if (!count) return ErrorOk; @@ -234,7 +264,30 @@ namespace GleeBug for (uint16 i = 0; i < count; i++) { const auto & section = sortedHeaders[i]; - mSections.push_back(Section(i, mSectionHeaders, section.beforeData, section.data)); + mSections.push_back(Section(i, alignment, mSectionHeaders, section.beforeData, section.data)); + } + + //create rva/offset -> section maps + if (count) //insert pe header offset/rva (file start -> first section is the PE header) + { + const auto & section = mSections[0]; + mOffsetSectionMap.insert({ Range(0, section.GetHeader().PointerToRawData - 1), HeaderSection }); + auto rva = alignAdjustSize(section.GetHeader().VirtualAddress, alignment); + mRvaSectionMap.insert({ Range(0, rva - 1), HeaderSection }); + } + else //TODO: handle file without sections + { + } + for (const auto & section : mSections) + { + //offset -> section index + auto offset = section.GetHeader().PointerToRawData; + mOffsetSectionMap.insert({ Range(offset, offset + section.GetHeader().SizeOfRawData - 1), section.GetIndex() }); + + //rva -> section index + auto rva = alignAdjustAddress(section.GetHeader().VirtualAddress, alignment); + auto vsize = alignAdjustSize(section.GetHeader().Misc.VirtualSize, alignment); + mRvaSectionMap.insert({ Range(rva, rva + vsize - 1), section.GetIndex() }); } return ErrorOk; @@ -257,26 +310,30 @@ namespace GleeBug void Pe::setupErrorMap() { - mErrorMap.insert({ ErrorOk, "ErrorOk" }); - mErrorMap.insert({ ErrorDosHeaderRead, "ErrorDosHeaderRead" }); - mErrorMap.insert({ ErrorDosHeaderMagic, "ErrorDosHeaderMagic" }); - mErrorMap.insert({ ErrorDosHeaderNtHeaderOffset, "ErrorDosHeaderNtHeaderOffset" }); - mErrorMap.insert({ ErrorDosHeaderNtHeaderOffsetOverlap, "ErrorDosHeaderNtHeaderOffsetOverlap" }); - mErrorMap.insert({ ErrorAfterDosHeaderData, "ErrorAfterDosHeaderData" }); - mErrorMap.insert({ ErrorNtSignatureRead, "ErrorNtSignatureRead" }); - mErrorMap.insert({ ErrorNtSignatureMagic, "ErrorNtSignatureMagic" }); - mErrorMap.insert({ ErrorNtFileHeaderRead, "ErrorNtFileHeaderRead" }); - mErrorMap.insert({ ErrorNtFileHeaderSizeOfOptionalHeaderOverlap, "ErrorNtFileHeaderSizeOfOptionalHeaderOverlap" }); - mErrorMap.insert({ ErrorNtFileHeaderUnsupportedMachine, "ErrorNtFileHeaderUnsupportedMachine" }); - mErrorMap.insert({ ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead, "ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead" }); - mErrorMap.insert({ ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize, "ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize" }); - mErrorMap.insert({ ErrorNtOptionalHeaderRead, "ErrorNtOptionalHeaderRead" }); - mErrorMap.insert({ ErrorNtOptionalHeaderMagic, "ErrorNtOptionalHeaderMagic" }); - mErrorMap.insert({ ErrorAfterOptionalHeaderDataRead, "ErrorAfterOptionalHeaderDataRead" }); - mErrorMap.insert({ ErrorNtHeadersRegionSize, "ErrorNtHeadersRegionSize" }); - mErrorMap.insert({ ErrorSectionHeadersRead, "ErrorSectionHeadersRead" }); - mErrorMap.insert({ ErrorAfterSectionHeadersDataRead, "ErrorAfterSectionHeadersDataRead" }); - mErrorMap.insert({ ErrorBeforeSectionDataRead, "ErrorBeforeSectionDataRead" }); - mErrorMap.insert({ ErrorSectionDataRead, "ErrorSectionDataRead" }); + auto add = [this](Error e, const char* s) + { + mErrorMap.insert({ e, s }); + }; + add(ErrorOk, "ErrorOk"); + add(ErrorDosHeaderRead, "ErrorDosHeaderRead"); + add(ErrorDosHeaderMagic, "ErrorDosHeaderMagic"); + add(ErrorDosHeaderNtHeaderOffset, "ErrorDosHeaderNtHeaderOffset"); + add(ErrorDosHeaderNtHeaderOffsetOverlap, "ErrorDosHeaderNtHeaderOffsetOverlap"); + add(ErrorAfterDosHeaderData, "ErrorAfterDosHeaderData"); + add(ErrorNtSignatureRead, "ErrorNtSignatureRead"); + add(ErrorNtSignatureMagic, "ErrorNtSignatureMagic"); + add(ErrorNtFileHeaderRead, "ErrorNtFileHeaderRead"); + add(ErrorNtFileHeaderSizeOfOptionalHeaderOverlap, "ErrorNtFileHeaderSizeOfOptionalHeaderOverlap"); + add(ErrorNtFileHeaderUnsupportedMachine, "ErrorNtFileHeaderUnsupportedMachine"); + add(ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead, "ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead"); + add(ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize, "ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize"); + add(ErrorNtOptionalHeaderRead, "ErrorNtOptionalHeaderRead"); + add(ErrorNtOptionalHeaderMagic, "ErrorNtOptionalHeaderMagic"); + add(ErrorAfterOptionalHeaderDataRead, "ErrorAfterOptionalHeaderDataRead"); + add(ErrorNtHeadersRegionSize, "ErrorNtHeadersRegionSize"); + add(ErrorSectionHeadersRead, "ErrorSectionHeadersRead"); + add(ErrorAfterSectionHeadersDataRead, "ErrorAfterSectionHeadersDataRead"); + add(ErrorBeforeSectionDataRead, "ErrorBeforeSectionDataRead"); + add(ErrorSectionDataRead, "ErrorSectionDataRead"); } }; \ No newline at end of file diff --git a/GleeBug/Static.Pe.h b/GleeBug/Static.Pe.h index 2aaad1c..5d8893c 100644 --- a/GleeBug/Static.Pe.h +++ b/GleeBug/Static.Pe.h @@ -35,6 +35,10 @@ namespace GleeBug ErrorSectionDataRead }; + const int HeaderSection = -1; + + typedef std::map RangeSectionMap; + explicit Pe(File & file); void Clear(); @@ -42,6 +46,8 @@ namespace GleeBug bool IsValidPe() const; bool IsPe64() const; Error Parse(bool allowOverlap = false); + uint32 ConvertOffsetToRva(uint32 offset); + uint32 ConvertRvaToOffset(uint32 rva); const Region & GetDosHeader() const { return mDosHeader; } bool GetDosNtOverlap() const { return mDosNtOverlap; } @@ -52,12 +58,26 @@ namespace GleeBug const Region & GetSectionHeaders() const { return mSectionHeaders; } const Region & GetAfterSectionHeadersData() const { return mAfterSectionHeadersData; } const std::vector
& GetSections() const { return mSections; } + const RangeSectionMap & GetOffsetSectionMap() const { return mOffsetSectionMap; } + const RangeSectionMap & GetRvaSectionMap() const { return mRvaSectionMap; } private: - Error parseSections(uint16 count); + Error parseSections(uint16 count, uint32 alignment = 0x1000); uint32 readData(uint32 size); void setupErrorMap(); + template + T alignAdjustSize(T size, uint32 alignment) //TODO: check this + { + return size + (alignment - 1) & ~(alignment - 1); + } + + template + T alignAdjustAddress(T address, uint32 alignment) //TODO: check this + { + return address & ~(alignment - 1); + } + template Region readRegion(uint32 count = 1) { @@ -65,7 +85,7 @@ namespace GleeBug } std::unordered_map mErrorMap; - + File & mFile; std::vector mData; uint32 mOffset; @@ -80,6 +100,8 @@ namespace GleeBug Region mSectionHeaders; Region mAfterSectionHeadersData; std::vector
mSections; + RangeSectionMap mOffsetSectionMap; + RangeSectionMap mRvaSectionMap; }; }; diff --git a/MyDebugger/main.cpp b/MyDebugger/main.cpp index dc58a54..bde57e2 100644 --- a/MyDebugger/main.cpp +++ b/MyDebugger/main.cpp @@ -116,6 +116,18 @@ static bool testPeFile(const wchar_t* szFileName, bool dumpData = true) printRegion(" Before Data", section.GetBeforeData(), false); printRegion(" Data", section.GetData()); } + + printf("\nOffset -> Section:\n"); + for (auto range : pe.GetOffsetSectionMap()) + { + printf(" %08llX:%08llX -> %d\n", range.first.first, range.first.second, range.second); + } + + printf("\nRva -> Section:\n"); + for (auto range : pe.GetRvaSectionMap()) + { + printf(" %08llX:%08llX -> %d\n", range.first.first, range.first.second, range.second); + } } else printf("Pe::Parse failed (%s)!\n", pe.ErrorText(parseError)); @@ -149,8 +161,9 @@ static void testCorkami() int main() { - //testPeFile(L"C:\\test64.exe"); - testCorkami(); + testPeFile(L"C:\\test64.exe"); + //testCorkami(); + //testPeFile(L"c:\\!exclude\\pe\\bin\\appendedhdr.exe"); puts(""); system("pause"); return 0;