|
|
|
|
@@ -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
|
|
|
|
|
}
|
|
|
|
|
|