mirror of https://github.com/x64dbg/GleeBug
added rva <-> offset conversion functions
This commit is contained in:
parent
ba69fd1509
commit
0dc118cd75
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue