diff --git a/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDataEntry.cs b/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDataEntry.cs
index 6f48d750..67d395db 100644
--- a/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDataEntry.cs
+++ b/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDataEntry.cs
@@ -1,6 +1,9 @@
using System;
using System.IO;
+using System.Linq;
using System.Runtime.InteropServices;
+using System.Text;
+using BurnOutSharp.ExecutableType.Microsoft.Headers;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
@@ -16,6 +19,35 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
///
public uint OffsetToData;
+ ///
+ /// A unit of resource data in the Resource Data area.
+ ///
+ public byte[] Data;
+
+ ///
+ /// A unit of resource data in the Resource Data area.
+ ///
+ public string EncodedData
+ {
+ get
+ {
+ int codePage = (int)CodePage;
+ if (Data == null || codePage < 0)
+ return string.Empty;
+
+ try
+ {
+ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+ return Encoding.GetEncoding(codePage).GetString(Data);
+ }
+ catch (Exception ex)
+ {
+ return Encoding.ASCII.GetString(Data);
+ }
+
+ }
+ }
+
///
/// The size, in bytes, of the resource data that is pointed to by the Data RVA field.
///
@@ -32,7 +64,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
///
public uint Reserved;
- public static ResourceDataEntry Deserialize(Stream stream)
+ public static ResourceDataEntry Deserialize(Stream stream, SectionHeader[] sections)
{
var rde = new ResourceDataEntry();
@@ -41,10 +73,19 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
rde.CodePage = stream.ReadUInt32();
rde.Reserved = stream.ReadUInt32();
+ int realOffsetToData = (int)PortableExecutable.ConvertVirtualAddress(rde.OffsetToData, sections);
+ if (realOffsetToData > -1 && realOffsetToData < stream.Length)
+ {
+ long lastPosition = stream.Position;
+ stream.Seek(realOffsetToData, SeekOrigin.Begin);
+ rde.Data = stream.ReadBytes((int)rde.Size);
+ stream.Seek(lastPosition, SeekOrigin.Begin);
+ }
+
return rde;
}
- public static ResourceDataEntry Deserialize(byte[] content, int offset)
+ public static ResourceDataEntry Deserialize(byte[] content, int offset, SectionHeader[] sections)
{
var rde = new ResourceDataEntry();
@@ -53,6 +94,10 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
rde.CodePage = BitConverter.ToUInt32(content, offset); offset += 4;
rde.Reserved = BitConverter.ToUInt32(content, offset); offset += 4;
+ int realOffsetToData = (int)PortableExecutable.ConvertVirtualAddress(rde.OffsetToData, sections);
+ if (realOffsetToData > -1 && realOffsetToData < content.Length)
+ rde.Data = new ArraySegment(content, realOffsetToData, (int)rde.Size).ToArray();
+
return rde;
}
}
diff --git a/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDirectoryTableEntry.cs b/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDirectoryTableEntry.cs
index e7c80eef..af450330 100644
--- a/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDirectoryTableEntry.cs
+++ b/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDirectoryTableEntry.cs
@@ -1,5 +1,7 @@
using System;
using System.IO;
+using BurnOutSharp.ExecutableType.Microsoft.Headers;
+using BurnOutSharp.ExecutableType.Microsoft.Tables;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
@@ -48,7 +50,10 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
///
public ResourceDataEntry DataEntry;
- private bool NameFieldIsIntegerId = false;
+ ///
+ /// Another resource directory table (the next level down).
+ ///
+ public ResourceDirectoryTable Subdirectory;
///
/// Determine if an entry has a name or integer identifier
@@ -60,47 +65,44 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
///
public bool IsResourceDataEntry() => (DataEntryOffset & (1 << 31)) == 0;
- public static ResourceDirectoryTableEntry Deserialize(Stream stream, long sectionStart)
+ public static ResourceDirectoryTableEntry Deserialize(Stream stream, long sectionStart, SectionHeader[] sections)
{
var rdte = new ResourceDirectoryTableEntry();
rdte.IntegerId = stream.ReadUInt32();
if (!rdte.IsIntegerIDEntry())
{
- long lastPosition = stream.Position;
int nameAddress = (int)(rdte.NameOffset + sectionStart);
if (nameAddress >= 0 && nameAddress < stream.Length)
{
- try
- {
- stream.Seek(nameAddress, SeekOrigin.Begin);
- rdte.Name = ResourceDirectoryString.Deserialize(stream);
- }
- catch { }
- finally
- {
- stream.Seek(lastPosition, SeekOrigin.Begin);
- }
+ long lastPosition = stream.Position;
+ stream.Seek(nameAddress, SeekOrigin.Begin);
+ rdte.Name = ResourceDirectoryString.Deserialize(stream);
+ stream.Seek(lastPosition, SeekOrigin.Begin);
}
}
rdte.DataEntryOffset = stream.ReadUInt32();
if (rdte.IsResourceDataEntry())
{
- long lastPosition = stream.Position;
int dataEntryAddress = (int)(rdte.DataEntryOffset + sectionStart);
if (dataEntryAddress > 0 && dataEntryAddress < stream.Length)
{
- try
- {
- stream.Seek(dataEntryAddress, SeekOrigin.Begin);
- rdte.DataEntry = ResourceDataEntry.Deserialize(stream);
- }
- catch { }
- finally
- {
- stream.Seek(lastPosition, SeekOrigin.Begin);
- }
+ long lastPosition = stream.Position;
+ stream.Seek(dataEntryAddress, SeekOrigin.Begin);
+ rdte.DataEntry = ResourceDataEntry.Deserialize(stream, sections);
+ stream.Seek(lastPosition, SeekOrigin.Begin);
+ }
+ }
+ else
+ {
+ int subdirectoryAddress = (int)(rdte.SubdirectoryOffset + sectionStart);
+ if (subdirectoryAddress > 0 && subdirectoryAddress < stream.Length)
+ {
+ long lastPosition = stream.Position;
+ stream.Seek(subdirectoryAddress, SeekOrigin.Begin);
+ rdte.Subdirectory = ResourceDirectoryTable.Deserialize(stream, sectionStart, sections);
+ stream.Seek(lastPosition, SeekOrigin.Begin);
}
}
@@ -109,7 +111,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
return rdte;
}
- public static ResourceDirectoryTableEntry Deserialize(byte[] content, int offset, long sectionStart)
+ public static ResourceDirectoryTableEntry Deserialize(byte[] content, int offset, long sectionStart, SectionHeader[] sections)
{
var rdte = new ResourceDirectoryTableEntry();
@@ -118,13 +120,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
{
int nameAddress = (int)(rdte.NameOffset + sectionStart);
if (nameAddress >= 0 && nameAddress < content.Length)
- {
- try
- {
- rdte.Name = ResourceDirectoryString.Deserialize(content, nameAddress);
- }
- catch { }
- }
+ rdte.Name = ResourceDirectoryString.Deserialize(content, nameAddress);
}
rdte.DataEntryOffset = BitConverter.ToUInt32(content, offset); offset += 4;
@@ -132,13 +128,13 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
{
int dataEntryAddress = (int)(rdte.DataEntryOffset + sectionStart);
if (dataEntryAddress > 0 && dataEntryAddress < content.Length)
- {
- try
- {
- rdte.DataEntry = ResourceDataEntry.Deserialize(content, dataEntryAddress);
- }
- catch { }
- }
+ rdte.DataEntry = ResourceDataEntry.Deserialize(content, dataEntryAddress, sections);
+ }
+ else
+ {
+ int subdirectoryAddress = (int)(rdte.SubdirectoryOffset + sectionStart);
+ if (subdirectoryAddress > 0 && subdirectoryAddress < content.Length)
+ rdte.Subdirectory = ResourceDirectoryTable.Deserialize(content, subdirectoryAddress, sectionStart, sections);
}
// TODO: Add parsing for further directory table entries in the tree
diff --git a/BurnOutSharp/ExecutableType/Microsoft/PortableExecutable.cs b/BurnOutSharp/ExecutableType/Microsoft/PortableExecutable.cs
index 7a63a5a5..d6cee7da 100644
--- a/BurnOutSharp/ExecutableType/Microsoft/PortableExecutable.cs
+++ b/BurnOutSharp/ExecutableType/Microsoft/PortableExecutable.cs
@@ -216,7 +216,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft
{
int tableAddress = (int)ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
stream.Seek(tableAddress, SeekOrigin.Begin);
- pex.ResourceSection = ResourceSection.Deserialize(stream);
+ pex.ResourceSection = ResourceSection.Deserialize(stream, pex.SectionTable);
}
}
catch (Exception ex)
@@ -285,7 +285,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft
if (table != null && table.VirtualSize > 0)
{
int tableAddress = (int)ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
- pex.ResourceSection = ResourceSection.Deserialize(content, tableAddress);
+ pex.ResourceSection = ResourceSection.Deserialize(content, tableAddress, pex.SectionTable);
}
}
}
diff --git a/BurnOutSharp/ExecutableType/Microsoft/Sections/ResourceSection.cs b/BurnOutSharp/ExecutableType/Microsoft/Sections/ResourceSection.cs
index cfea6738..eee13b54 100644
--- a/BurnOutSharp/ExecutableType/Microsoft/Sections/ResourceSection.cs
+++ b/BurnOutSharp/ExecutableType/Microsoft/Sections/ResourceSection.cs
@@ -22,24 +22,24 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Sections
///
public ResourceDirectoryTable ResourceDirectoryTable;
- public static ResourceSection Deserialize(Stream stream)
+ public static ResourceSection Deserialize(Stream stream, SectionHeader[] sections)
{
var rs = new ResourceSection();
long sectionStart = stream.Position;
- rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(stream, sectionStart);
+ rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(stream, sectionStart, sections);
return rs;
}
- public static ResourceSection Deserialize(byte[] content, int offset)
+ public static ResourceSection Deserialize(byte[] content, int offset, SectionHeader[] sections)
{
var rs = new ResourceSection();
unsafe
{
long sectionStart = offset;
- rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(content, offset, sectionStart); offset += Marshal.SizeOf(rs.ResourceDirectoryTable);
+ rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(content, offset, sectionStart, sections); offset += Marshal.SizeOf(rs.ResourceDirectoryTable);
}
return rs;
diff --git a/BurnOutSharp/ExecutableType/Microsoft/Tables/ResourceDirectoryTable.cs b/BurnOutSharp/ExecutableType/Microsoft/Tables/ResourceDirectoryTable.cs
index 3110ff61..aa82fd0c 100644
--- a/BurnOutSharp/ExecutableType/Microsoft/Tables/ResourceDirectoryTable.cs
+++ b/BurnOutSharp/ExecutableType/Microsoft/Tables/ResourceDirectoryTable.cs
@@ -68,7 +68,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
// TODO: Determine how to store or reference the resource directory strings
// that immediately follow the last directory entry but before the data
- public static ResourceDirectoryTable Deserialize(Stream stream, long sectionStart)
+ public static ResourceDirectoryTable Deserialize(Stream stream, long sectionStart, SectionHeader[] sections)
{
var rdt = new ResourceDirectoryTable();
@@ -82,19 +82,19 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
rdt.NamedEntries = new ResourceDirectoryTableEntry[rdt.NumberOfNamedEntries];
for (int i = 0; i < rdt.NumberOfNamedEntries; i++)
{
- rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(stream, sectionStart);
+ rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(stream, sectionStart, sections);
}
rdt.IdEntries = new ResourceDirectoryTableEntry[rdt.NumberOfIdEntries];
for (int i = 0; i < rdt.NumberOfIdEntries; i++)
{
- rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(stream, sectionStart);
+ rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(stream, sectionStart, sections);
}
return rdt;
}
- public static ResourceDirectoryTable Deserialize(byte[] content, int offset, long sectionStart)
+ public static ResourceDirectoryTable Deserialize(byte[] content, int offset, long sectionStart, SectionHeader[] sections)
{
var rdt = new ResourceDirectoryTable();
@@ -108,13 +108,13 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
rdt.NamedEntries = new ResourceDirectoryTableEntry[rdt.NumberOfNamedEntries];
for (int i = 0; i < rdt.NumberOfNamedEntries; i++)
{
- rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, offset, sectionStart); offset += 8;
+ rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, offset, sectionStart, sections); offset += 8;
}
rdt.IdEntries = new ResourceDirectoryTableEntry[rdt.NumberOfIdEntries];
for (int i = 0; i < rdt.NumberOfIdEntries; i++)
{
- rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, offset, sectionStart); offset += 8;
+ rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, offset, sectionStart, sections); offset += 8;
}
return rdt;