Reorganize and create Resource-related things

This commit is contained in:
Matt Nadareski
2021-08-27 10:38:42 -07:00
parent 2de4f3f808
commit b4ab969f88
7 changed files with 151 additions and 106 deletions

View File

@@ -0,0 +1,59 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
{
/// <summary>
/// Each Resource Data entry describes an actual unit of raw data in the Resource Data area.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal class ResourceDataEntry
{
/// <summary>
/// The address of a unit of resource data in the Resource Data area.
/// </summary>
public uint OffsetToData;
/// <summary>
/// The size, in bytes, of the resource data that is pointed to by the Data RVA field.
/// </summary>
public uint Size;
/// <summary>
/// The code page that is used to decode code point values within the resource data.
/// Typically, the code page would be the Unicode code page.
/// </summary>
public uint CodePage;
/// <summary>
/// Reserved, must be 0.
/// </summary>
public uint Reserved;
public static ResourceDataEntry Deserialize(Stream stream)
{
var rde = new ResourceDataEntry();
rde.OffsetToData = stream.ReadUInt32();
rde.Size = stream.ReadUInt32();
rde.CodePage = stream.ReadUInt32();
rde.Reserved = stream.ReadUInt32();
return rde;
}
public static ResourceDataEntry Deserialize(byte[] content, int offset)
{
var rde = new ResourceDataEntry();
rde.OffsetToData = BitConverter.ToUInt32(content, offset); offset += 4;
rde.Size = BitConverter.ToUInt32(content, offset); offset += 4;
rde.CodePage = BitConverter.ToUInt32(content, offset); offset += 4;
rde.Reserved = BitConverter.ToUInt32(content, offset); offset += 4;
return rde;
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.IO;
using BurnOutSharp.ExecutableType.Microsoft.Headers;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
@@ -18,8 +19,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#resource-directory-entries</remarks>
internal class ResourceDirectoryTableEntry
{
#region Name Entry
/// <summary>
/// The offset of a string that gives the Type, Name, or Language ID entry, depending on level of table.
/// </summary>
@@ -40,31 +39,70 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
/// </summary>
public uint SubdirectoryOffset => DataEntryOffset;
#endregion
/// <summary>
/// Resource Data entry (a leaf).
/// </summary>
public ResourceDataEntry DataEntry;
/// <summary>
/// Determine if an entry represents a leaf or another directory table
/// </summary>
public bool IsResourceDataEntry() => (DataEntryOffset & (1 << 31)) == 0;
public static ResourceDirectoryTableEntry Deserialize(Stream stream)
public static ResourceDirectoryTableEntry Deserialize(Stream stream, SectionHeader[] sections)
{
var idte = new ResourceDirectoryTableEntry();
var rdte = new ResourceDirectoryTableEntry();
idte.NameOffset = stream.ReadUInt32();
idte.DataEntryOffset = stream.ReadUInt32();
rdte.NameOffset = stream.ReadUInt32();
rdte.DataEntryOffset = stream.ReadUInt32();
return idte;
// Read in the data if we have a leaf
if (rdte.IsResourceDataEntry())
{
long lastPosition = stream.Position;
try
{
int dataEntryAddress = (int)EVORE.ConvertVirtualAddress(rdte.DataEntryOffset, sections);
if (dataEntryAddress > 0)
{
stream.Seek(dataEntryAddress, SeekOrigin.Begin);
rdte.DataEntry = ResourceDataEntry.Deserialize(stream);
}
}
catch { }
finally
{
stream.Seek(lastPosition, SeekOrigin.Begin);
}
}
// TODO: Add parsing for further directory table entries in the tree
return rdte;
}
public static ResourceDirectoryTableEntry Deserialize(byte[] content, int offset)
public static ResourceDirectoryTableEntry Deserialize(byte[] content, int offset, SectionHeader[] sections)
{
var idte = new ResourceDirectoryTableEntry();
var rdte = new ResourceDirectoryTableEntry();
idte.NameOffset = BitConverter.ToUInt32(content, offset); offset += 4;
idte.DataEntryOffset = BitConverter.ToUInt32(content, offset); offset += 4;
rdte.NameOffset = BitConverter.ToUInt32(content, offset); offset += 4;
rdte.DataEntryOffset = BitConverter.ToUInt32(content, offset); offset += 4;
return idte;
// Read in the data if we have a leaf
if (rdte.IsResourceDataEntry())
{
try
{
int dataEntryAddress = (int)EVORE.ConvertVirtualAddress(rdte.DataEntryOffset, sections);
if (dataEntryAddress > 0)
rdte.DataEntry = ResourceDataEntry.Deserialize(content, dataEntryAddress);
}
catch { }
}
// TODO: Add parsing for further directory table entries in the tree
return rdte;
}
}
}

View File

@@ -1,39 +0,0 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_RESOURCE_DATA_ENTRY
{
public uint OffsetToData;
public uint Size;
public uint CodePage;
public uint Reserved;
public static IMAGE_RESOURCE_DATA_ENTRY Deserialize(Stream stream)
{
var irde = new IMAGE_RESOURCE_DATA_ENTRY();
irde.OffsetToData = stream.ReadUInt32();
irde.Size = stream.ReadUInt32();
irde.CodePage = stream.ReadUInt32();
irde.Reserved = stream.ReadUInt32();
return irde;
}
}
}

View File

@@ -1,35 +0,0 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_RESOURCE_DIRECTORY_ENTRY
{
public uint Name;
public uint OffsetToData;
public static IMAGE_RESOURCE_DIRECTORY_ENTRY Deserialize(Stream stream)
{
var irde = new IMAGE_RESOURCE_DIRECTORY_ENTRY();
irde.Name = stream.ReadUInt32();
irde.OffsetToData = stream.ReadUInt32();
return irde;
}
}
}

View File

@@ -2,6 +2,7 @@ using System.IO;
using System.Runtime.InteropServices;
using BurnOutSharp.ExecutableType.Microsoft.Headers;
using BurnOutSharp.ExecutableType.Microsoft.Sections;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ExecutableType.Microsoft
{
@@ -92,7 +93,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft
pex.SectionTable[i] = SectionHeader.Deserialize(stream);
}
// TODO: Uncomment these when all directories are understod and implemented
// TODO: Uncomment these as the directories are understod and implemented
// // Export Table
// var table = pex.SectionTable[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_EXPORT];
// if (table.VirtualSize > 0)
@@ -103,16 +104,26 @@ namespace BurnOutSharp.ExecutableType.Microsoft
// }
// // Import Table
// table = pex.SectionHeaders[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_IMPORT];
// table = pex.SectionTable[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_IMPORT];
// if (table.VirtualSize > 0)
// {
// int tableAddress = (int)EVORE.ConvertVirtualAddress(table.VirtualAddress, pex.SectionHeaders);
// int tableAddress = (int)EVORE.ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
// stream.Seek(tableAddress, SeekOrigin.Begin);
// pex.ImportTable = ImportDataSection.Deserialize(stream, pex.OptionalHeader.Magic == OptionalHeaderType.PE32Plus, hintCount: 0); // TODO: Figure out where this count comes from
// }
// // Resource Table
// var table = pex.SectionTable[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_RESOURCE];
// if (table.VirtualSize > 0)
// {
// int tableAddress = (int)EVORE.ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
// stream.Seek(tableAddress, SeekOrigin.Begin);
// pex.ResourceSection = ResourceSection.Deserialize(stream, pex.SectionTable);
// }
}
catch
catch (System.Exception ex)
{
System.Console.WriteLine($"Errored out on a file: {ex}");
return null;
}
@@ -140,7 +151,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft
pex.SectionTable[i] = SectionHeader.Deserialize(content, offset); offset += 40;
}
// TODO: Uncomment these when all directories are understod and implemented
// TODO: Uncomment these as the directories are understod and implemented
// // Export Table
// var table = pex.SectionTable[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_EXPORT];
// if (table.VirtualSize > 0)
@@ -150,16 +161,25 @@ namespace BurnOutSharp.ExecutableType.Microsoft
// }
// // Import Table
// table = pex.SectionHeaders[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_IMPORT];
// table = pex.SectionTable[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_IMPORT];
// if (table.VirtualSize > 0)
// {
// int tableAddress = (int)EVORE.ConvertVirtualAddress(table.VirtualAddress, pex.SectionHeaders);
// pex.ImportTable = ImportDataSection.Deserialize(content, tableAddress, pex.OptionalHeader.Magic == OptionalHeaderType.PE32Plus, hintCount: 0); offset += Marshal.SizeOf(pex.ImportTable); // TODO: Figure out where this count comes from
// int tableAddress = (int)EVORE.ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
// pex.ImportTable = ImportDataSection.Deserialize(content, tableAddress, pex.OptionalHeader.Magic == OptionalHeaderType.PE32Plus, hintCount: 0);
// }
// // Resource Table
// var table = pex.SectionTable[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_RESOURCE];
// if (table.VirtualSize > 0)
// {
// int tableAddress = (int)EVORE.ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
// pex.ResourceSection = ResourceSection.Deserialize(content, tableAddress, pex.SectionTable);
// }
}
}
catch
catch (System.Exception ex)
{
System.Console.WriteLine($"Errored out on a file: {ex}");
return null;
}

View File

@@ -1,5 +1,6 @@
using System.IO;
using System.Runtime.InteropServices;
using BurnOutSharp.ExecutableType.Microsoft.Headers;
using BurnOutSharp.ExecutableType.Microsoft.Tables;
namespace BurnOutSharp.ExecutableType.Microsoft.Sections
@@ -21,22 +22,22 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Sections
/// </summary>
public ResourceDirectoryTable ResourceDirectoryTable;
public static ResourceSection Deserialize(Stream stream)
public static ResourceSection Deserialize(Stream stream, SectionHeader[] sections)
{
var rs = new ResourceSection();
rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(stream);
rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(stream, 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
{
rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(content, offset); offset += Marshal.SizeOf(rs.ResourceDirectoryTable);
rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(content, offset, sections); offset += Marshal.SizeOf(rs.ResourceDirectoryTable);
}
return rs;

View File

@@ -2,6 +2,7 @@ using System;
using System.IO;
using System.Runtime.InteropServices;
using BurnOutSharp.ExecutableType.Microsoft.Entries;
using BurnOutSharp.ExecutableType.Microsoft.Headers;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
@@ -67,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)
public static ResourceDirectoryTable Deserialize(Stream stream, SectionHeader[] sections)
{
var rdt = new ResourceDirectoryTable();
@@ -81,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);
rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(stream, sections);
}
rdt.IdEntries = new ResourceDirectoryTableEntry[rdt.NumberOfIdEntries];
for (int i = 0; i < rdt.NumberOfIdEntries; i++)
{
rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(stream);
rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(stream, sections);
}
return rdt;
}
public static ResourceDirectoryTable Deserialize(byte[] content, int offset)
public static ResourceDirectoryTable Deserialize(byte[] content, int offset, SectionHeader[] sections)
{
var rdt = new ResourceDirectoryTable();
@@ -107,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); offset += 8;
rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, offset, sections); offset += 8;
}
rdt.IdEntries = new ResourceDirectoryTableEntry[rdt.NumberOfIdEntries];
for (int i = 0; i < rdt.NumberOfIdEntries; i++)
{
rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, offset); offset += 8;
rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, offset, sections); offset += 8;
}
return rdt;