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
{
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),
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<uint8> & GetBeforeData() const { return mBeforeData; }
@ -24,6 +26,7 @@ namespace GleeBug
private:
uint16 mIndex;
uint32 mAlignment;
Region<IMAGE_SECTION_HEADER> mHeaders;
Region<uint8> mBeforeData;
Region<uint8> mData;

View File

@ -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");
}
};

View File

@ -35,6 +35,10 @@ namespace GleeBug
ErrorSectionDataRead
};
const int HeaderSection = -1;
typedef std::map<Range, int, RangeCompare> 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<IMAGE_DOS_HEADER> & GetDosHeader() const { return mDosHeader; }
bool GetDosNtOverlap() const { return mDosNtOverlap; }
@ -52,12 +58,26 @@ namespace GleeBug
const Region<IMAGE_SECTION_HEADER> & GetSectionHeaders() const { return mSectionHeaders; }
const Region<uint8> & GetAfterSectionHeadersData() const { return mAfterSectionHeadersData; }
const std::vector<Section> & 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<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>
Region<T> readRegion(uint32 count = 1)
{
@ -65,7 +85,7 @@ namespace GleeBug
}
std::unordered_map<Error, const char*> mErrorMap;
File & mFile;
std::vector<uint8> mData;
uint32 mOffset;
@ -80,6 +100,8 @@ namespace GleeBug
Region<IMAGE_SECTION_HEADER> mSectionHeaders;
Region<uint8> mAfterSectionHeadersData;
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(" 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;