Lock section names, scan for hidden resources

This commit is contained in:
Matt Nadareski
2022-12-30 09:09:42 -08:00
parent a46d52ddbb
commit 1027956892
2 changed files with 50 additions and 17 deletions

View File

@@ -300,7 +300,7 @@ namespace BurnOutSharp.Builders
// Try to parse the resource directory table
data.Seek(resourceTableAddress, SeekOrigin.Begin);
var resourceDirectoryTable = ParseResourceDirectoryTable(data, data.Position, executable.SectionTable);
var resourceDirectoryTable = ParseResourceDirectoryTable(data, data.Position, executable.SectionTable, optionalHeader.ResourceTable.Size, true);
if (resourceDirectoryTable == null)
return null;
@@ -1195,8 +1195,10 @@ namespace BurnOutSharp.Builders
/// <param name="data">Stream to parse</param>
/// <param name="initialOffset">Initial offset to use in address comparisons</param>
/// <param name="sections">Section table to use for virtual address translation</param>
/// <param name="size">Indicates the size of the section, only used for top-level</param>
/// <param name="topLevel">Indicates if this is the top level or not</param>
/// <returns>Filled resource directory table on success, null on error</returns>
private static ResourceDirectoryTable ParseResourceDirectoryTable(Stream data, long initialOffset, SectionHeader[] sections)
private static ResourceDirectoryTable ParseResourceDirectoryTable(Stream data, long initialOffset, SectionHeader[] sections, uint size = 0, bool topLevel = false)
{
// TODO: Use marshalling here instead of building
var resourceDirectoryTable = new ResourceDirectoryTable();
@@ -1287,6 +1289,34 @@ namespace BurnOutSharp.Builders
}
}
// If we are not at the top level
if (!topLevel)
return resourceDirectoryTable;
// Align to the 1024-byte boundary
while (data.Position - initialOffset < size && data.Position % 1024 != 0)
_ = data.ReadByteValue();
// If we have not used up the full size, parse the remaining chunk as a single resource
if (data.Position - initialOffset < size)
{
Array.Resize(ref resourceDirectoryTable.Entries, totalEntryCount + 1);
int length = (int)(data.Position - initialOffset);
resourceDirectoryTable.Entries[totalEntryCount] = new ResourceDirectoryEntry
{
Name = new ResourceDirectoryString { UnicodeString = Encoding.ASCII.GetBytes("HIDDEN RESOURCE") },
IntegerID = uint.MaxValue,
DataEntryOffset = (uint)data.Position,
DataEntry = new ResourceDataEntry
{
Size = (uint)length,
Data = data.ReadBytes(length),
Codepage = (uint)Encoding.Unicode.CodePage,
},
};
}
return resourceDirectoryTable;
}

View File

@@ -563,23 +563,26 @@ namespace BurnOutSharp.Wrappers
{
get
{
// Use the cached data if possible
if (_sectionNames != null)
return _sectionNames;
// Otherwise, build and return the cached array
_sectionNames = new string[_executable.SectionTable.Length];
for (int i = 0; i < _sectionNames.Length; i++)
lock (_sourceDataLock)
{
var section = _executable.SectionTable[i];
// Use the cached data if possible
if (_sectionNames != null)
return _sectionNames;
// TODO: Handle long section names with leading `/`
byte[] sectionNameBytes = section.Name;
string sectionNameString = Encoding.UTF8.GetString(sectionNameBytes).TrimEnd('\0');
_sectionNames[i] = sectionNameString;
// Otherwise, build and return the cached array
_sectionNames = new string[_executable.SectionTable.Length];
for (int i = 0; i < _sectionNames.Length; i++)
{
var section = _executable.SectionTable[i];
// TODO: Handle long section names with leading `/`
byte[] sectionNameBytes = section.Name;
string sectionNameString = Encoding.UTF8.GetString(sectionNameBytes).TrimEnd('\0');
_sectionNames[i] = sectionNameString;
}
return _sectionNames;
}
return _sectionNames;
}
}
@@ -3117,7 +3120,7 @@ namespace BurnOutSharp.Wrappers
/// </summary>
private void ParseResourceDirectoryTable(Models.PortableExecutable.ResourceDirectoryTable table, List<object> types)
{
int totalEntries = table.NumberOfNameEntries + table.NumberOfIDEntries;
int totalEntries = table?.Entries?.Length ?? 0;
for (int i = 0; i < totalEntries; i++)
{
var entry = table.Entries[i];