added rva <-> offset conversion functions

This commit is contained in:
mrexodia 2016-02-09 13:30:36 +01:00
parent ba69fd1509
commit 0dc118cd75
4 changed files with 123 additions and 28 deletions

View File

@ -8,8 +8,9 @@ namespace GleeBug
class Section class Section
{ {
public: public:
explicit Section(uint16 index, Region<IMAGE_SECTION_HEADER> & headers, Region<uint8> beforeData, Region<uint8> data) explicit Section(uint16 index, uint32 alignment, Region<IMAGE_SECTION_HEADER> & headers, Region<uint8> beforeData, Region<uint8> data)
: mIndex(index), : mIndex(index),
mAlignment(alignment),
mHeaders(headers), mHeaders(headers),
mBeforeData(beforeData), mBeforeData(beforeData),
mData(data) mData(data)
@ -17,6 +18,7 @@ namespace GleeBug
} }
uint16 GetIndex() const { return mIndex; } uint16 GetIndex() const { return mIndex; }
uint32 GetAlignment() const { return mAlignment; }
IMAGE_SECTION_HEADER & GetHeader() { return mHeaders[mIndex]; } IMAGE_SECTION_HEADER & GetHeader() { return mHeaders[mIndex]; }
const IMAGE_SECTION_HEADER & GetHeader() const { return mHeaders[mIndex]; } const IMAGE_SECTION_HEADER & GetHeader() const { return mHeaders[mIndex]; }
const Region<uint8> & GetBeforeData() const { return mBeforeData; } const Region<uint8> & GetBeforeData() const { return mBeforeData; }
@ -24,6 +26,7 @@ namespace GleeBug
private: private:
uint16 mIndex; uint16 mIndex;
uint32 mAlignment;
Region<IMAGE_SECTION_HEADER> mHeaders; Region<IMAGE_SECTION_HEADER> mHeaders;
Region<uint8> mBeforeData; Region<uint8> mBeforeData;
Region<uint8> mData; Region<uint8> mData;

View File

@ -177,7 +177,37 @@ namespace GleeBug
return ErrorOk; 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) if (!count)
return ErrorOk; return ErrorOk;
@ -234,7 +264,30 @@ namespace GleeBug
for (uint16 i = 0; i < count; i++) for (uint16 i = 0; i < count; i++)
{ {
const auto & section = sortedHeaders[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; return ErrorOk;
@ -257,26 +310,30 @@ namespace GleeBug
void Pe::setupErrorMap() void Pe::setupErrorMap()
{ {
mErrorMap.insert({ ErrorOk, "ErrorOk" }); auto add = [this](Error e, const char* s)
mErrorMap.insert({ ErrorDosHeaderRead, "ErrorDosHeaderRead" }); {
mErrorMap.insert({ ErrorDosHeaderMagic, "ErrorDosHeaderMagic" }); mErrorMap.insert({ e, s });
mErrorMap.insert({ ErrorDosHeaderNtHeaderOffset, "ErrorDosHeaderNtHeaderOffset" }); };
mErrorMap.insert({ ErrorDosHeaderNtHeaderOffsetOverlap, "ErrorDosHeaderNtHeaderOffsetOverlap" }); add(ErrorOk, "ErrorOk");
mErrorMap.insert({ ErrorAfterDosHeaderData, "ErrorAfterDosHeaderData" }); add(ErrorDosHeaderRead, "ErrorDosHeaderRead");
mErrorMap.insert({ ErrorNtSignatureRead, "ErrorNtSignatureRead" }); add(ErrorDosHeaderMagic, "ErrorDosHeaderMagic");
mErrorMap.insert({ ErrorNtSignatureMagic, "ErrorNtSignatureMagic" }); add(ErrorDosHeaderNtHeaderOffset, "ErrorDosHeaderNtHeaderOffset");
mErrorMap.insert({ ErrorNtFileHeaderRead, "ErrorNtFileHeaderRead" }); add(ErrorDosHeaderNtHeaderOffsetOverlap, "ErrorDosHeaderNtHeaderOffsetOverlap");
mErrorMap.insert({ ErrorNtFileHeaderSizeOfOptionalHeaderOverlap, "ErrorNtFileHeaderSizeOfOptionalHeaderOverlap" }); add(ErrorAfterDosHeaderData, "ErrorAfterDosHeaderData");
mErrorMap.insert({ ErrorNtFileHeaderUnsupportedMachine, "ErrorNtFileHeaderUnsupportedMachine" }); add(ErrorNtSignatureRead, "ErrorNtSignatureRead");
mErrorMap.insert({ ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead, "ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead" }); add(ErrorNtSignatureMagic, "ErrorNtSignatureMagic");
mErrorMap.insert({ ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize, "ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize" }); add(ErrorNtFileHeaderRead, "ErrorNtFileHeaderRead");
mErrorMap.insert({ ErrorNtOptionalHeaderRead, "ErrorNtOptionalHeaderRead" }); add(ErrorNtFileHeaderSizeOfOptionalHeaderOverlap, "ErrorNtFileHeaderSizeOfOptionalHeaderOverlap");
mErrorMap.insert({ ErrorNtOptionalHeaderMagic, "ErrorNtOptionalHeaderMagic" }); add(ErrorNtFileHeaderUnsupportedMachine, "ErrorNtFileHeaderUnsupportedMachine");
mErrorMap.insert({ ErrorAfterOptionalHeaderDataRead, "ErrorAfterOptionalHeaderDataRead" }); add(ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead, "ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead");
mErrorMap.insert({ ErrorNtHeadersRegionSize, "ErrorNtHeadersRegionSize" }); add(ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize, "ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize");
mErrorMap.insert({ ErrorSectionHeadersRead, "ErrorSectionHeadersRead" }); add(ErrorNtOptionalHeaderRead, "ErrorNtOptionalHeaderRead");
mErrorMap.insert({ ErrorAfterSectionHeadersDataRead, "ErrorAfterSectionHeadersDataRead" }); add(ErrorNtOptionalHeaderMagic, "ErrorNtOptionalHeaderMagic");
mErrorMap.insert({ ErrorBeforeSectionDataRead, "ErrorBeforeSectionDataRead" }); add(ErrorAfterOptionalHeaderDataRead, "ErrorAfterOptionalHeaderDataRead");
mErrorMap.insert({ ErrorSectionDataRead, "ErrorSectionDataRead" }); add(ErrorNtHeadersRegionSize, "ErrorNtHeadersRegionSize");
add(ErrorSectionHeadersRead, "ErrorSectionHeadersRead");
add(ErrorAfterSectionHeadersDataRead, "ErrorAfterSectionHeadersDataRead");
add(ErrorBeforeSectionDataRead, "ErrorBeforeSectionDataRead");
add(ErrorSectionDataRead, "ErrorSectionDataRead");
} }
}; };

View File

@ -35,6 +35,10 @@ namespace GleeBug
ErrorSectionDataRead ErrorSectionDataRead
}; };
const int HeaderSection = -1;
typedef std::map<Range, int, RangeCompare> RangeSectionMap;
explicit Pe(File & file); explicit Pe(File & file);
void Clear(); void Clear();
@ -42,6 +46,8 @@ namespace GleeBug
bool IsValidPe() const; bool IsValidPe() const;
bool IsPe64() const; bool IsPe64() const;
Error Parse(bool allowOverlap = false); Error Parse(bool allowOverlap = false);
uint32 ConvertOffsetToRva(uint32 offset);
uint32 ConvertRvaToOffset(uint32 rva);
const Region<IMAGE_DOS_HEADER> & GetDosHeader() const { return mDosHeader; } const Region<IMAGE_DOS_HEADER> & GetDosHeader() const { return mDosHeader; }
bool GetDosNtOverlap() const { return mDosNtOverlap; } bool GetDosNtOverlap() const { return mDosNtOverlap; }
@ -52,12 +58,26 @@ namespace GleeBug
const Region<IMAGE_SECTION_HEADER> & GetSectionHeaders() const { return mSectionHeaders; } const Region<IMAGE_SECTION_HEADER> & GetSectionHeaders() const { return mSectionHeaders; }
const Region<uint8> & GetAfterSectionHeadersData() const { return mAfterSectionHeadersData; } const Region<uint8> & GetAfterSectionHeadersData() const { return mAfterSectionHeadersData; }
const std::vector<Section> & GetSections() const { return mSections; } const std::vector<Section> & GetSections() const { return mSections; }
const RangeSectionMap & GetOffsetSectionMap() const { return mOffsetSectionMap; }
const RangeSectionMap & GetRvaSectionMap() const { return mRvaSectionMap; }
private: private:
Error parseSections(uint16 count); Error parseSections(uint16 count, uint32 alignment = 0x1000);
uint32 readData(uint32 size); uint32 readData(uint32 size);
void setupErrorMap(); void setupErrorMap();
template<typename T>
T alignAdjustSize(T size, uint32 alignment) //TODO: check this
{
return size + (alignment - 1) & ~(alignment - 1);
}
template<typename T>
T alignAdjustAddress(T address, uint32 alignment) //TODO: check this
{
return address & ~(alignment - 1);
}
template<typename T> template<typename T>
Region<T> readRegion(uint32 count = 1) Region<T> readRegion(uint32 count = 1)
{ {
@ -65,7 +85,7 @@ namespace GleeBug
} }
std::unordered_map<Error, const char*> mErrorMap; std::unordered_map<Error, const char*> mErrorMap;
File & mFile; File & mFile;
std::vector<uint8> mData; std::vector<uint8> mData;
uint32 mOffset; uint32 mOffset;
@ -80,6 +100,8 @@ namespace GleeBug
Region<IMAGE_SECTION_HEADER> mSectionHeaders; Region<IMAGE_SECTION_HEADER> mSectionHeaders;
Region<uint8> mAfterSectionHeadersData; Region<uint8> mAfterSectionHeadersData;
std::vector<Section> mSections; std::vector<Section> mSections;
RangeSectionMap mOffsetSectionMap;
RangeSectionMap mRvaSectionMap;
}; };
}; };

View File

@ -116,6 +116,18 @@ static bool testPeFile(const wchar_t* szFileName, bool dumpData = true)
printRegion(" Before Data", section.GetBeforeData(), false); printRegion(" Before Data", section.GetBeforeData(), false);
printRegion(" Data", section.GetData()); 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 else
printf("Pe::Parse failed (%s)!\n", pe.ErrorText(parseError)); printf("Pe::Parse failed (%s)!\n", pe.ErrorText(parseError));
@ -149,8 +161,9 @@ static void testCorkami()
int main() int main()
{ {
//testPeFile(L"C:\\test64.exe"); testPeFile(L"C:\\test64.exe");
testCorkami(); //testCorkami();
//testPeFile(L"c:\\!exclude\\pe\\bin\\appendedhdr.exe");
puts(""); puts("");
system("pause"); system("pause");
return 0; return 0;