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
|
||||
{
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
};
|
||||
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue