Fix reading generic sections

This commit is contained in:
Matt Nadareski
2021-09-15 11:47:12 -07:00
parent ba97abed44
commit a579bfea1f
5 changed files with 62 additions and 48 deletions

View File

@@ -176,6 +176,34 @@ namespace BurnOutSharp.ExecutableType.Microsoft
return sectionNames.Any(n => n.Trim('\0').StartsWith(sectionName));
}
/// <summary>
/// Convert a virtual address to a physical one
/// </summary>
/// <param name="virtualAddress">Virtual address to convert</param>
/// <param name="sections">Array of sections to check against</param>
/// <returns>Physical address, 0 on error</returns>
public static uint ConvertVirtualAddress(uint virtualAddress, SectionHeader[] sections)
{
// Loop through all of the sections
for (int i = 0; i < sections.Length; i++)
{
// If the section is invalid, just skip it
if (sections[i] == null)
continue;
// If the section "starts" at 0, just skip it
if (sections[i].PointerToRawData == 0)
continue;
// Attempt to derive the physical address from the current section
var section = sections[i];
if (virtualAddress >= section.VirtualAddress && virtualAddress <= section.VirtualAddress + section.VirtualSize)
return section.PointerToRawData + virtualAddress - section.VirtualAddress;
}
return 0;
}
/// <summary>
/// Get the first section based on name, if possible
/// </summary>
@@ -230,13 +258,27 @@ namespace BurnOutSharp.ExecutableType.Microsoft
return SectionTable.Select(s => Encoding.ASCII.GetString(s.Name)).ToArray();
}
/// <summary>
/// Print all sections, including their start and end addresses
/// </summary>
public void PrintAllSections()
{
foreach (var section in SectionTable)
{
string sectionName = Encoding.ASCII.GetString(section.Name).Trim('\0');
int sectionAddr = (int)section.PointerToRawData;
int sectionEnd = sectionAddr + (int)section.VirtualSize;
Console.WriteLine($"{sectionName}: {sectionAddr} -> {sectionEnd}");
}
}
/// <summary>
/// Get the raw bytes from a section, if possible
/// </summary>
public byte[] ReadRawSection(Stream stream, string sectionName, bool first = true, int offset = 0)
public byte[] ReadRawSection(Stream stream, string sectionName, bool force = false, bool first = true, int offset = 0)
{
// Special cases for non-offset data
if (offset == 0)
// Special cases for non-forced, non-offset data
if (!force && offset == 0)
{
switch (sectionName)
{
@@ -274,10 +316,10 @@ namespace BurnOutSharp.ExecutableType.Microsoft
/// <summary>
/// Get the raw bytes from a section, if possible
/// </summary>
public byte[] ReadRawSection(byte[] content, string sectionName, bool first = true, int offset = 0)
public byte[] ReadRawSection(byte[] content, string sectionName, bool force = false, bool first = true, int offset = 0)
{
// Special cases for non-offset data
if (offset == 0)
// Special cases for non-forced, non-offset data
if (!force && offset == 0)
{
switch (sectionName)
{
@@ -304,34 +346,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft
return content.ReadBytes(ref startingIndex, readLength);
}
/// <summary>
/// Convert a virtual address to a physical one
/// </summary>
/// <param name="virtualAddress">Virtual address to convert</param>
/// <param name="sections">Array of sections to check against</param>
/// <returns>Physical address, 0 on error</returns>
public static uint ConvertVirtualAddress(uint virtualAddress, SectionHeader[] sections)
{
// Loop through all of the sections
for (int i = 0; i < sections.Length; i++)
{
// If the section is invalid, just skip it
if (sections[i] == null)
continue;
// If the section "starts" at 0, just skip it
if (sections[i].PointerToRawData == 0)
continue;
// Attempt to derive the physical address from the current section
var section = sections[i];
if (virtualAddress >= section.VirtualAddress && virtualAddress <= section.VirtualAddress + section.VirtualSize)
return section.PointerToRawData + virtualAddress - section.VirtualAddress;
}
return 0;
}
#endregion
public static PortableExecutable Deserialize(Stream stream)
@@ -396,19 +410,19 @@ namespace BurnOutSharp.ExecutableType.Microsoft
#region Freeform Sections
// Data Section
pex.DataSectionRaw = pex.ReadRawSection(stream, ".data", false) ?? pex.ReadRawSection(stream, "DATA", false);
pex.DataSectionRaw = pex.ReadRawSection(stream, ".data", force: true, first: false) ?? pex.ReadRawSection(stream, "DATA", force: true, first: false);
// Export Table
pex.ExportDataSectionRaw = pex.ReadRawSection(stream, ".edata", false);
pex.ExportDataSectionRaw = pex.ReadRawSection(stream, ".edata", force: true, first: false);
// Import Table
pex.ImportDataSectionRaw = pex.ReadRawSection(stream, ".idata", false);
pex.ImportDataSectionRaw = pex.ReadRawSection(stream, ".idata", force: true, first: false);
// Resource Data Section
pex.ResourceDataSectionRaw = pex.ReadRawSection(stream, ".rdata", false);
pex.ResourceDataSectionRaw = pex.ReadRawSection(stream, ".rdata", force: true, first: false);
// Text Section
pex.TextSectionRaw = pex.ReadRawSection(stream, ".text", false);
pex.TextSectionRaw = pex.ReadRawSection(stream, ".text", force: true, first: false);
#endregion
}
@@ -484,19 +498,19 @@ namespace BurnOutSharp.ExecutableType.Microsoft
#region Freeform Sections
// Data Section
pex.DataSectionRaw = pex.ReadRawSection(content, ".data", false) ?? pex.ReadRawSection(content, "DATA", false);
pex.DataSectionRaw = pex.ReadRawSection(content, ".data", force: true, first: false) ?? pex.ReadRawSection(content, "DATA", force: true, first: false);
// Export Table
pex.ExportDataSectionRaw = pex.ReadRawSection(content, ".edata", false);
pex.ExportDataSectionRaw = pex.ReadRawSection(content, ".edata", force: true, first: false);
// Import Table
pex.ImportDataSectionRaw = pex.ReadRawSection(content, ".idata", false);
pex.ImportDataSectionRaw = pex.ReadRawSection(content, ".idata", force: true, first: false);
// Resource Data Section
pex.ResourceDataSectionRaw = pex.ReadRawSection(content, ".rdata", false);
pex.ResourceDataSectionRaw = pex.ReadRawSection(content, ".rdata", force: true, first: false);
// Text Section
pex.TextSectionRaw = pex.ReadRawSection(content, ".text", false);
pex.TextSectionRaw = pex.ReadRawSection(content, ".text", force: true, first: false);
#endregion
}