mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-04-25 15:50:18 +00:00
Reorganize and create Resource-related things
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user