mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-04-27 16:50:46 +00:00
Continue exe organization, start IIF migration
This commit is contained in:
@@ -2,7 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each entry in the export address table is a field that uses one of two formats in the following table.
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each entry in the export address table is a field that uses one of two formats in the following table.
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each entry in the hint/name table has the following format
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each import address entry has the following format
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each import directory entry has the following format
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// The resource directory string area consists of Unicode strings, which are word-aligned.
|
||||
/// These strings are stored together after the last Resource Directory entry and before the first Resource Data entry.
|
||||
/// This minimizes the impact of these variable-length strings on the alignment of the fixed-size directory entries.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class ResourceDirectoryString
|
||||
{
|
||||
/// <summary>
|
||||
/// The size of the string, not including length field itself.
|
||||
/// </summary>
|
||||
public ushort Length;
|
||||
|
||||
/// <summary>
|
||||
/// The variable-length Unicode string data, word-aligned.
|
||||
/// </summary>
|
||||
public char[] UnicodeString;
|
||||
|
||||
public static ResourceDirectoryString Deserialize(Stream stream)
|
||||
{
|
||||
var rds = new ResourceDirectoryString();
|
||||
|
||||
rds.Length = stream.ReadUInt16();
|
||||
rds.UnicodeString = stream.ReadChars(rds.Length, Encoding.Unicode);
|
||||
|
||||
return rds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// The directory entries make up the rows of a table.
|
||||
/// Each resource directory entry has the following format.
|
||||
/// Whether the entry is a Name or ID entry is indicated by the
|
||||
/// resource directory table, which indicates how many Name and
|
||||
/// ID entries follow it (remember that all the Name entries
|
||||
/// precede all the ID entries for the table). All entries for
|
||||
/// the table are sorted in ascending order: the Name entries
|
||||
/// by case-sensitive string and the ID entries by numeric value.
|
||||
/// Offsets are relative to the address in the IMAGE_DIRECTORY_ENTRY_RESOURCE DataDirectory.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
public uint NameOffset;
|
||||
|
||||
/// <summary>
|
||||
/// A 32-bit integer that identifies the Type, Name, or Language ID entry.
|
||||
/// </summary>
|
||||
public uint IntegerId => NameOffset;
|
||||
|
||||
/// <summary>
|
||||
/// High bit 0. Address of a Resource Data entry (a leaf).
|
||||
/// </summary>
|
||||
public uint DataEntryOffset;
|
||||
|
||||
/// <summary>
|
||||
/// High bit 1. The lower 31 bits are the address of another resource directory table (the next level down).
|
||||
/// </summary>
|
||||
public uint SubdirectoryOffset => DataEntryOffset;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <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)
|
||||
{
|
||||
var idte = new ResourceDirectoryTableEntry();
|
||||
|
||||
idte.NameOffset = stream.ReadUInt32();
|
||||
idte.DataEntryOffset = stream.ReadUInt32();
|
||||
|
||||
return idte;
|
||||
}
|
||||
|
||||
public static ResourceDirectoryTableEntry Deserialize(byte[] content, int offset)
|
||||
{
|
||||
var idte = new ResourceDirectoryTableEntry();
|
||||
|
||||
idte.NameOffset = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
idte.DataEntryOffset = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
|
||||
return idte;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@ using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_FILE_HEADER
|
||||
internal class CommonObjectFileFormatHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// After the MS-DOS stub, at the file offset specified at offset 0x3c, is a 4-byte signature that identifies the file as a PE format image file.
|
||||
@@ -55,9 +55,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
/// </summary>
|
||||
public ImageObjectCharacteristics Characteristics;
|
||||
|
||||
public static IMAGE_FILE_HEADER Deserialize(Stream stream)
|
||||
public static CommonObjectFileFormatHeader Deserialize(Stream stream)
|
||||
{
|
||||
var ifh = new IMAGE_FILE_HEADER();
|
||||
var ifh = new CommonObjectFileFormatHeader();
|
||||
|
||||
ifh.Signature = stream.ReadUInt32();
|
||||
ifh.Machine = (MachineType)stream.ReadUInt16();
|
||||
@@ -71,9 +71,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
return ifh;
|
||||
}
|
||||
|
||||
public static IMAGE_FILE_HEADER Deserialize(byte[] content, int offset)
|
||||
public static CommonObjectFileFormatHeader Deserialize(byte[] content, int offset)
|
||||
{
|
||||
var ifh = new IMAGE_FILE_HEADER();
|
||||
var ifh = new CommonObjectFileFormatHeader();
|
||||
|
||||
ifh.Signature = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ifh.Machine = (MachineType)BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
@@ -0,0 +1,211 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
{
|
||||
/// <summary>
|
||||
/// The MS-DOS EXE format, also known as MZ after its signature (the initials of Microsoft engineer Mark Zbykowski),
|
||||
/// was introduced with MS-DOS 2.0 (version 1.0 only sported the simple COM format). It is designed as a relocatable
|
||||
/// executable running under real mode. As such, only DOS and Windows 9x can use this format natively, but there are
|
||||
/// several free DOS emulators (e.g., DOSBox) that support it and that run under various operating systems (e.g.,
|
||||
/// Linux, Amiga, Windows NT, etc.). Although they can exist on their own, MZ executables are embedded in all NE, LE,
|
||||
/// and PE executables, usually as stubs so that when they are ran under DOS, they display a warning.
|
||||
/// </summary>
|
||||
/// <remarks>https://wiki.osdev.org/MZ</remarks>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class MSDOSExecutableHeader
|
||||
{
|
||||
#region Standard Fields
|
||||
|
||||
/// <summary>
|
||||
/// 0x5A4D (ASCII for 'M' and 'Z') [00]
|
||||
/// </summary>
|
||||
public ushort Magic;
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes in the last page. [02]
|
||||
/// </summary>
|
||||
public ushort LastPageBytes;
|
||||
|
||||
/// <summary>
|
||||
/// Number of whole/partial pages. [04]
|
||||
/// </summary>
|
||||
public ushort Pages;
|
||||
|
||||
/// <summary>
|
||||
/// Number of entries in the relocation table. [06]
|
||||
/// </summary>
|
||||
public ushort Relocations;
|
||||
|
||||
/// <summary>
|
||||
/// The number of paragraphs taken up by the header.It can be any value, as the loader
|
||||
/// just uses it to find where the actual executable data starts. It may be larger than
|
||||
/// what the "standard" fields take up, and you may use it if you want to include your
|
||||
/// own header metadata, or put the relocation table there, or use it for any other purpose. [08]
|
||||
/// </summary>
|
||||
public ushort HeaderParagraphSize;
|
||||
|
||||
/// <summary>
|
||||
/// The number of paragraphs required by the program, excluding the PSP and program image.
|
||||
/// If no free block is big enough, the loading stops. [0A]
|
||||
/// </summary>
|
||||
public ushort MinimumExtraParagraphs;
|
||||
|
||||
/// <summary>
|
||||
/// The number of paragraphs requested by the program.
|
||||
/// If no free block is big enough, the biggest one possible is allocated. [0C]
|
||||
/// </summary>
|
||||
public ushort MaximumExtraParagraphs;
|
||||
|
||||
/// <summary>
|
||||
/// Relocatable segment address for SS. [0E]
|
||||
/// </summary>
|
||||
public ushort InitialSSValue;
|
||||
|
||||
/// <summary>
|
||||
/// Initial value for SP. [10]
|
||||
/// </summary>
|
||||
public ushort InitialSPValue;
|
||||
|
||||
/// <summary>
|
||||
/// When added to the sum of all other words in the file, the result should be zero. [12]
|
||||
/// </summary>
|
||||
public ushort Checksum;
|
||||
|
||||
/// <summary>
|
||||
/// Initial value for IP. [14]
|
||||
/// </summary>
|
||||
public ushort InitialIPValue;
|
||||
|
||||
/// <summary>
|
||||
/// Relocatable segment address for CS. [16]
|
||||
/// </summary>
|
||||
public ushort InitialCSValue;
|
||||
|
||||
/// <summary>
|
||||
/// The (absolute) offset to the relocation table. [18]
|
||||
/// </summary>
|
||||
public ushort RelocationTableAddr;
|
||||
|
||||
/// <summary>
|
||||
/// Value used for overlay management.
|
||||
/// If zero, this is the main executable. [1A]
|
||||
/// </summary>
|
||||
public ushort OverlayNumber;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PE Extensions
|
||||
|
||||
/// <summary>
|
||||
/// Reserved words [1C]
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.ERES1WDS)]
|
||||
public ushort[] Reserved1;
|
||||
|
||||
/// <summary>
|
||||
/// Defined by name but no other information is given; typically zeroes [24]
|
||||
/// </summary>
|
||||
public ushort OEMIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// Defined by name but no other information is given; typically zeroes [26]
|
||||
/// </summary>
|
||||
public ushort OEMInformation;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved words [28]
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.ERES2WDS)]
|
||||
public ushort[] Reserved2;
|
||||
|
||||
/// <summary>
|
||||
/// Starting address of the PE header [3C]
|
||||
/// </summary>
|
||||
public int NewExeHeaderAddr;
|
||||
|
||||
#endregion
|
||||
|
||||
public static MSDOSExecutableHeader Deserialize(Stream stream, bool asStub = true)
|
||||
{
|
||||
MSDOSExecutableHeader idh = new MSDOSExecutableHeader();
|
||||
|
||||
idh.Magic = stream.ReadUInt16();
|
||||
idh.LastPageBytes = stream.ReadUInt16();
|
||||
idh.Pages = stream.ReadUInt16();
|
||||
idh.Relocations = stream.ReadUInt16();
|
||||
idh.HeaderParagraphSize = stream.ReadUInt16();
|
||||
idh.MinimumExtraParagraphs = stream.ReadUInt16();
|
||||
idh.MaximumExtraParagraphs = stream.ReadUInt16();
|
||||
idh.InitialSSValue = stream.ReadUInt16();
|
||||
idh.InitialSPValue = stream.ReadUInt16();
|
||||
idh.Checksum = stream.ReadUInt16();
|
||||
idh.InitialIPValue = stream.ReadUInt16();
|
||||
idh.InitialCSValue = stream.ReadUInt16();
|
||||
idh.RelocationTableAddr = stream.ReadUInt16();
|
||||
idh.OverlayNumber = stream.ReadUInt16();
|
||||
|
||||
// If we're not reading as a stub, return now
|
||||
if (!asStub)
|
||||
return idh;
|
||||
|
||||
idh.Reserved1 = new ushort[Constants.ERES1WDS];
|
||||
for (int i = 0; i < Constants.ERES1WDS; i++)
|
||||
{
|
||||
idh.Reserved1[i] = stream.ReadUInt16();
|
||||
}
|
||||
idh.OEMIdentifier = stream.ReadUInt16();
|
||||
idh.OEMInformation = stream.ReadUInt16();
|
||||
idh.Reserved2 = new ushort[Constants.ERES2WDS];
|
||||
for (int i = 0; i < Constants.ERES2WDS; i++)
|
||||
{
|
||||
idh.Reserved2[i] = stream.ReadUInt16();
|
||||
}
|
||||
idh.NewExeHeaderAddr = stream.ReadInt32();
|
||||
|
||||
return idh;
|
||||
}
|
||||
|
||||
public static MSDOSExecutableHeader Deserialize(byte[] content, int offset, bool asStub = true)
|
||||
{
|
||||
MSDOSExecutableHeader idh = new MSDOSExecutableHeader();
|
||||
|
||||
idh.Magic = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.LastPageBytes = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.Pages = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.Relocations = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.HeaderParagraphSize = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.MinimumExtraParagraphs = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.MaximumExtraParagraphs = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.InitialSSValue = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.InitialSPValue = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.Checksum = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.InitialIPValue = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.InitialCSValue = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.RelocationTableAddr = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.OverlayNumber = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
|
||||
// If we're not reading as a stub, return now
|
||||
if (!asStub)
|
||||
return idh;
|
||||
|
||||
idh.Reserved1 = new ushort[Constants.ERES1WDS];
|
||||
for (int i = 0; i < Constants.ERES1WDS; i++)
|
||||
{
|
||||
idh.Reserved1[i] = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
}
|
||||
idh.OEMIdentifier = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.OEMInformation = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.Reserved2 = new ushort[Constants.ERES2WDS];
|
||||
for (int i = 0; i < Constants.ERES2WDS; i++)
|
||||
{
|
||||
idh.Reserved2[i] = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
}
|
||||
idh.NewExeHeaderAddr = BitConverter.ToInt32(content, offset); offset += 4;
|
||||
|
||||
return idh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,24 @@ using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
{
|
||||
/// <summary>
|
||||
/// Every image file has an optional header that provides information to the loader.
|
||||
/// This header is optional in the sense that some files (specifically, object files) do not have it.
|
||||
/// For image files, this header is required. An object file can have an optional header, but generally
|
||||
/// this header has no function in an object file except to increase its size.
|
||||
///
|
||||
/// Note that the size of the optional header is not fixed.
|
||||
/// The SizeOfOptionalHeader field in the COFF header must be used to validate that a probe into the file
|
||||
/// for a particular data directory does not go beyond SizeOfOptionalHeader.
|
||||
///
|
||||
/// The NumberOfRvaAndSizes field of the optional header should also be used to ensure that no probe for
|
||||
/// a particular data directory entry goes beyond the optional header.
|
||||
/// In addition, it is important to validate the optional header magic number for format compatibility.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_OPTIONAL_HEADER
|
||||
internal class OptionalHeader
|
||||
{
|
||||
#region Standard Fields
|
||||
|
||||
@@ -222,9 +236,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
|
||||
#endregion
|
||||
|
||||
public static IMAGE_OPTIONAL_HEADER Deserialize(Stream stream)
|
||||
public static OptionalHeader Deserialize(Stream stream)
|
||||
{
|
||||
var ioh = new IMAGE_OPTIONAL_HEADER();
|
||||
var ioh = new OptionalHeader();
|
||||
|
||||
ioh.Magic = (OptionalHeaderType)stream.ReadUInt16();
|
||||
ioh.MajorLinkerVersion = stream.ReadByteValue();
|
||||
@@ -287,9 +301,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
return ioh;
|
||||
}
|
||||
|
||||
public static IMAGE_OPTIONAL_HEADER Deserialize(byte[] content, int offset)
|
||||
public static OptionalHeader Deserialize(byte[] content, int offset)
|
||||
{
|
||||
var ioh = new IMAGE_OPTIONAL_HEADER();
|
||||
var ioh = new OptionalHeader();
|
||||
|
||||
ioh.Magic = (OptionalHeaderType)BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
ioh.MajorLinkerVersion = content[offset]; offset++;
|
||||
132
BurnOutSharp/ExecutableType/Microsoft/Headers/SectionHeader.cs
Normal file
132
BurnOutSharp/ExecutableType/Microsoft/Headers/SectionHeader.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
{
|
||||
/// <summary>
|
||||
/// Each row of the section table is, in effect, a section header.
|
||||
/// This table immediately follows the optional header, if any.
|
||||
/// This positioning is required because the file header does not contain a direct pointer to the section table.
|
||||
/// Instead, the location of the section table is determined by calculating the location of the first byte after the headers.
|
||||
/// Make sure to use the size of the optional header as specified in the file header.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class SectionHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// An 8-byte, null-padded UTF-8 encoded string.
|
||||
/// If the string is exactly 8 characters long, there is no terminating null.
|
||||
/// For longer names, this field contains a slash (/) that is followed by an ASCII representation of a decimal number
|
||||
/// that is an offset into the string table.
|
||||
/// Executable images do not use a string table and do not support section names longer than 8 characters.
|
||||
/// Long names in object files are truncated if they are emitted to an executable file.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.IMAGE_SIZEOF_SHORT_NAME)]
|
||||
public byte[] Name;
|
||||
|
||||
/// <summary>
|
||||
/// The total size of the section when loaded into memory.
|
||||
/// If this value is greater than SizeOfRawData, the section is zero-padded.
|
||||
/// This field is valid only for executable images and should be set to zero for object files.
|
||||
/// </summary>
|
||||
public uint VirtualSize;
|
||||
|
||||
/// <summary>
|
||||
/// For executable images, the address of the first byte of the section relative to the image base when the section
|
||||
/// is loaded into memory.
|
||||
/// For object files, this field is the address of the first byte before relocation is applied; for simplicity,
|
||||
/// compilers should set this to zero.
|
||||
/// Otherwise, it is an arbitrary value that is subtracted from offsets during relocation.
|
||||
/// </summary>
|
||||
public uint VirtualAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the section (for object files) or the size of the initialized data on disk (for image files).
|
||||
/// For executable images, this must be a multiple of FileAlignment from the optional header.
|
||||
/// If this is less than VirtualSize, the remainder of the section is zero-filled.
|
||||
/// Because the SizeOfRawData field is rounded but the VirtualSize field is not, it is possible for SizeOfRawData
|
||||
/// to be greater than VirtualSize as well.
|
||||
/// When a section contains only uninitialized data, this field should be zero.
|
||||
/// </summary>
|
||||
public uint SizeOfRawData;
|
||||
|
||||
/// <summary>
|
||||
/// The file pointer to the first page of the section within the COFF file.
|
||||
/// For executable images, this must be a multiple of FileAlignment from the optional header.
|
||||
/// For object files, the value should be aligned on a 4-byte boundary for best performance.
|
||||
/// When a section contains only uninitialized data, this field should be zero.
|
||||
/// </summary>
|
||||
public uint PointerToRawData;
|
||||
|
||||
/// <summary>
|
||||
/// The file pointer to the beginning of relocation entries for the section.
|
||||
/// This is set to zero for executable images or if there are no relocations.
|
||||
/// </summary>
|
||||
public uint PointerToRelocations;
|
||||
|
||||
/// <summary>
|
||||
/// The file pointer to the beginning of line-number entries for the section.
|
||||
/// This is set to zero if there are no COFF line numbers.
|
||||
/// This value should be zero for an image because COFF debugging information is deprecated.
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public uint PointerToLinenumbers;
|
||||
|
||||
/// <summary>
|
||||
/// The number of relocation entries for the section.
|
||||
/// This is set to zero for executable images.
|
||||
/// </summary>
|
||||
public ushort NumberOfRelocations;
|
||||
|
||||
/// <summary>
|
||||
/// The number of line-number entries for the section.
|
||||
/// This value should be zero for an image because COFF debugging information is deprecated.
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public ushort NumberOfLinenumbers;
|
||||
|
||||
/// <summary>
|
||||
/// The flags that describe the characteristics of the section.
|
||||
/// </summary>
|
||||
public SectionCharacteristics Characteristics;
|
||||
|
||||
public static SectionHeader Deserialize(Stream stream)
|
||||
{
|
||||
var ish = new SectionHeader();
|
||||
|
||||
ish.Name = stream.ReadBytes(Constants.IMAGE_SIZEOF_SHORT_NAME);
|
||||
ish.VirtualSize = stream.ReadUInt32();
|
||||
ish.VirtualAddress = stream.ReadUInt32();
|
||||
ish.SizeOfRawData = stream.ReadUInt32();
|
||||
ish.PointerToRawData = stream.ReadUInt32();
|
||||
ish.PointerToRelocations = stream.ReadUInt32();
|
||||
ish.PointerToLinenumbers = stream.ReadUInt32();
|
||||
ish.NumberOfRelocations = stream.ReadUInt16();
|
||||
ish.NumberOfLinenumbers = stream.ReadUInt16();
|
||||
ish.Characteristics = (SectionCharacteristics)stream.ReadUInt32();
|
||||
|
||||
return ish;
|
||||
}
|
||||
|
||||
public static SectionHeader Deserialize(byte[] content, int offset)
|
||||
{
|
||||
var ish = new SectionHeader();
|
||||
|
||||
ish.Name = new byte[Constants.IMAGE_SIZEOF_SHORT_NAME];
|
||||
Array.Copy(content, offset, ish.Name, 0, Constants.IMAGE_SIZEOF_SHORT_NAME); offset += Constants.IMAGE_SIZEOF_SHORT_NAME;
|
||||
ish.VirtualSize = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.VirtualAddress = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.SizeOfRawData = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.PointerToRawData = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.PointerToRelocations = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.PointerToLinenumbers = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.NumberOfRelocations = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
ish.NumberOfLinenumbers = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
ish.Characteristics = (SectionCharacteristics)BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
|
||||
return ish;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,118 +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;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// DOS 1, 2, 3 .EXE header
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_DOS_HEADER
|
||||
{
|
||||
public ushort Magic; // 00 Magic number
|
||||
public ushort LastPageBytes; // 02 Bytes on last page of file
|
||||
public ushort Pages; // 04 Pages in file
|
||||
public ushort Relocations; // 06 Relocations
|
||||
public ushort HeaderParagraphSize; // 08 Size of header in paragraphs
|
||||
public ushort MinimumExtraParagraphs; // 0A Minimum extra paragraphs needed
|
||||
public ushort MaximumExtraParagraphs; // 0C Maximum extra paragraphs needed
|
||||
public ushort InitialSSValue; // 0E Initial (relative) SS value
|
||||
public ushort InitialSPValue; // 10 Initial SP value
|
||||
public ushort Checksum; // 12 Checksum
|
||||
public ushort InitialIPValue; // 14 Initial IP value
|
||||
public ushort InitialCSValue; // 16 Initial (relative) CS value
|
||||
public ushort RelocationTableAddr; // 18 File address of relocation table
|
||||
public ushort OverlayNumber; // 1A Overlay number
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.ERES1WDS)]
|
||||
public ushort[] Reserved1; // 1C Reserved words
|
||||
public ushort OEMIdentifier; // 24 OEM identifier (for e_oeminfo)
|
||||
public ushort OEMInformation; // 26 OEM information; e_oemid specific
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.ERES2WDS)]
|
||||
public ushort[] Reserved2; // 28 Reserved words
|
||||
public int NewExeHeaderAddr; // 3C File address of new exe header
|
||||
|
||||
public static IMAGE_DOS_HEADER Deserialize(Stream stream)
|
||||
{
|
||||
IMAGE_DOS_HEADER idh = new IMAGE_DOS_HEADER();
|
||||
|
||||
idh.Magic = stream.ReadUInt16();
|
||||
idh.LastPageBytes = stream.ReadUInt16();
|
||||
idh.Pages = stream.ReadUInt16();
|
||||
idh.Relocations = stream.ReadUInt16();
|
||||
idh.HeaderParagraphSize = stream.ReadUInt16();
|
||||
idh.MinimumExtraParagraphs = stream.ReadUInt16();
|
||||
idh.MaximumExtraParagraphs = stream.ReadUInt16();
|
||||
idh.InitialSSValue = stream.ReadUInt16();
|
||||
idh.InitialSPValue = stream.ReadUInt16();
|
||||
idh.Checksum = stream.ReadUInt16();
|
||||
idh.InitialIPValue = stream.ReadUInt16();
|
||||
idh.InitialCSValue = stream.ReadUInt16();
|
||||
idh.RelocationTableAddr = stream.ReadUInt16();
|
||||
idh.OverlayNumber = stream.ReadUInt16();
|
||||
idh.Reserved1 = new ushort[Constants.ERES1WDS];
|
||||
for (int i = 0; i < Constants.ERES1WDS; i++)
|
||||
{
|
||||
idh.Reserved1[i] = stream.ReadUInt16();
|
||||
}
|
||||
idh.OEMIdentifier = stream.ReadUInt16();
|
||||
idh.OEMInformation = stream.ReadUInt16();
|
||||
idh.Reserved2 = new ushort[Constants.ERES2WDS];
|
||||
for (int i = 0; i < Constants.ERES2WDS; i++)
|
||||
{
|
||||
idh.Reserved2[i] = stream.ReadUInt16();
|
||||
}
|
||||
idh.NewExeHeaderAddr = stream.ReadInt32();
|
||||
|
||||
return idh;
|
||||
}
|
||||
|
||||
public static IMAGE_DOS_HEADER Deserialize(byte[] content, int offset)
|
||||
{
|
||||
IMAGE_DOS_HEADER idh = new IMAGE_DOS_HEADER();
|
||||
|
||||
idh.Magic = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.LastPageBytes = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.Pages = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.Relocations = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.HeaderParagraphSize = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.MinimumExtraParagraphs = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.MaximumExtraParagraphs = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.InitialSSValue = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.InitialSPValue = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.Checksum = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.InitialIPValue = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.InitialCSValue = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.RelocationTableAddr = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.OverlayNumber = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.Reserved1 = new ushort[Constants.ERES1WDS];
|
||||
for (int i = 0; i < Constants.ERES1WDS; i++)
|
||||
{
|
||||
idh.Reserved1[i] = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
}
|
||||
idh.OEMIdentifier = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.OEMInformation = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
idh.Reserved2 = new ushort[Constants.ERES2WDS];
|
||||
for (int i = 0; i < Constants.ERES2WDS; i++)
|
||||
{
|
||||
idh.Reserved2[i] = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
}
|
||||
idh.NewExeHeaderAddr = BitConverter.ToInt32(content, offset); offset += 4;
|
||||
|
||||
return idh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +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
|
||||
{
|
||||
public uint Characteristics;
|
||||
public uint TimeDateStamp;
|
||||
public ushort MajorVersion;
|
||||
public ushort MinorVersion;
|
||||
public ushort NumberOfNamedEntries;
|
||||
public ushort NumberOfIdEntries;
|
||||
|
||||
public static IMAGE_RESOURCE_DIRECTORY Deserialize(Stream stream)
|
||||
{
|
||||
var ird = new IMAGE_RESOURCE_DIRECTORY();
|
||||
|
||||
ird.Characteristics = stream.ReadUInt32();
|
||||
ird.TimeDateStamp = stream.ReadUInt32();
|
||||
ird.MajorVersion = stream.ReadUInt16();
|
||||
ird.MinorVersion = stream.ReadUInt16();
|
||||
ird.NumberOfNamedEntries = stream.ReadUInt16();
|
||||
ird.NumberOfIdEntries = stream.ReadUInt16();
|
||||
|
||||
return ird;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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_DIR_STRING_U
|
||||
{
|
||||
public ushort Length;
|
||||
public char[] NameString;
|
||||
|
||||
public static IMAGE_RESOURCE_DIR_STRING_U Deserialize(Stream stream)
|
||||
{
|
||||
var irdsu = new IMAGE_RESOURCE_DIR_STRING_U();
|
||||
|
||||
irdsu.Length = stream.ReadUInt16();
|
||||
irdsu.NameString = stream.ReadChars(irdsu.Length);
|
||||
|
||||
return irdsu;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_SECTION_HEADER
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.IMAGE_SIZEOF_SHORT_NAME)]
|
||||
public byte[] Name;
|
||||
public uint VirtualSize;
|
||||
public uint VirtualAddress;
|
||||
public uint SizeOfRawData;
|
||||
public uint PointerToRawData;
|
||||
public uint PointerToRelocations;
|
||||
public uint PointerToLinenumbers;
|
||||
public ushort NumberOfRelocations;
|
||||
public ushort NumberOfLinenumbers;
|
||||
public SectionCharacteristics Characteristics;
|
||||
|
||||
public static IMAGE_SECTION_HEADER Deserialize(Stream stream)
|
||||
{
|
||||
var ish = new IMAGE_SECTION_HEADER();
|
||||
|
||||
ish.Name = stream.ReadBytes(Constants.IMAGE_SIZEOF_SHORT_NAME);
|
||||
ish.VirtualSize = stream.ReadUInt32();
|
||||
ish.VirtualAddress = stream.ReadUInt32();
|
||||
ish.SizeOfRawData = stream.ReadUInt32();
|
||||
ish.PointerToRawData = stream.ReadUInt32();
|
||||
ish.PointerToRelocations = stream.ReadUInt32();
|
||||
ish.PointerToLinenumbers = stream.ReadUInt32();
|
||||
ish.NumberOfRelocations = stream.ReadUInt16();
|
||||
ish.NumberOfLinenumbers = stream.ReadUInt16();
|
||||
ish.Characteristics = (SectionCharacteristics)stream.ReadUInt32();
|
||||
|
||||
return ish;
|
||||
}
|
||||
|
||||
public static IMAGE_SECTION_HEADER Deserialize(byte[] content, int offset)
|
||||
{
|
||||
var ish = new IMAGE_SECTION_HEADER();
|
||||
|
||||
ish.Name = new byte[Constants.IMAGE_SIZEOF_SHORT_NAME];
|
||||
Array.Copy(content, offset, ish.Name, 0, Constants.IMAGE_SIZEOF_SHORT_NAME); offset += Constants.IMAGE_SIZEOF_SHORT_NAME;
|
||||
ish.VirtualSize = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.VirtualAddress = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.SizeOfRawData = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.PointerToRawData = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.PointerToRelocations = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.PointerToLinenumbers = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ish.NumberOfRelocations = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
ish.NumberOfLinenumbers = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
ish.Characteristics = (SectionCharacteristics)BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
|
||||
return ish;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,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
|
||||
{
|
||||
@@ -10,7 +10,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
/// A COFF object file header consists of a COFF file header and an optional header.
|
||||
/// In both cases, the file headers are followed immediately by section headers.
|
||||
/// </summary>
|
||||
internal class PEExecutable
|
||||
internal class PortableExecutable
|
||||
{
|
||||
#region Headers
|
||||
|
||||
@@ -23,13 +23,13 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
/// This information enables Windows to properly execute the image file, even though it has an MS-DOS stub.
|
||||
/// This file offset is placed at location 0x3c during linking.
|
||||
// </summary>
|
||||
public IMAGE_DOS_HEADER MSDOSStub;
|
||||
public MSDOSExecutableHeader DOSStubHeader;
|
||||
|
||||
/// <summary>
|
||||
/// At the beginning of an object file, or immediately after the signature of an image file, is a standard COFF file header in the following format.
|
||||
/// Note that the Windows loader limits the number of sections to 96.
|
||||
/// </summary>
|
||||
public IMAGE_FILE_HEADER COFFFileHeader;
|
||||
public CommonObjectFileFormatHeader ImageFileHeader;
|
||||
|
||||
/// <summary>
|
||||
/// Every image file has an optional header that provides information to the loader.
|
||||
@@ -37,7 +37,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
/// For image files, this header is required.
|
||||
/// An object file can have an optional header, but generally this header has no function in an object file except to increase its size.
|
||||
/// </summary>
|
||||
public IMAGE_OPTIONAL_HEADER OptionalHeader;
|
||||
public OptionalHeader OptionalHeader;
|
||||
|
||||
/// <summary>
|
||||
/// Each row of the section table is, in effect, a section header.
|
||||
@@ -46,7 +46,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
/// Instead, the location of the section table is determined by calculating the location of the first byte after the headers.
|
||||
/// Make sure to use the size of the optional header as specified in the file header.
|
||||
/// </summary>
|
||||
public IMAGE_SECTION_HEADER[] SectionHeaders;
|
||||
public SectionHeader[] SectionTable;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -63,34 +63,41 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
// </summary>
|
||||
public ImportDataSection ImportTable;
|
||||
|
||||
/// <summary>
|
||||
/// Resources are indexed by a multiple-level binary-sorted tree structure.
|
||||
// The general design can incorporate 2**31 levels.
|
||||
// By convention, however, Windows uses three levels
|
||||
// </summary>
|
||||
public ResourceSection ResourceSection;
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: Add more and more parts of a standard PE executable, not just the header
|
||||
// TODO: Add data directory table information here instead of in IMAGE_OPTIONAL_HEADER
|
||||
|
||||
public static PEExecutable Deserialize(Stream stream)
|
||||
public static PortableExecutable Deserialize(Stream stream)
|
||||
{
|
||||
PEExecutable pex = new PEExecutable();
|
||||
PortableExecutable pex = new PortableExecutable();
|
||||
|
||||
try
|
||||
{
|
||||
pex.MSDOSStub = IMAGE_DOS_HEADER.Deserialize(stream); stream.Seek(pex.MSDOSStub.NewExeHeaderAddr, SeekOrigin.Begin);
|
||||
pex.COFFFileHeader = IMAGE_FILE_HEADER.Deserialize(stream);
|
||||
if (pex.COFFFileHeader.SizeOfOptionalHeader > 0)
|
||||
pex.OptionalHeader = IMAGE_OPTIONAL_HEADER.Deserialize(stream);
|
||||
pex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(stream); stream.Seek(pex.DOSStubHeader.NewExeHeaderAddr, SeekOrigin.Begin);
|
||||
pex.ImageFileHeader = CommonObjectFileFormatHeader.Deserialize(stream);
|
||||
if (pex.ImageFileHeader.SizeOfOptionalHeader > 0)
|
||||
pex.OptionalHeader = OptionalHeader.Deserialize(stream);
|
||||
|
||||
pex.SectionHeaders = new IMAGE_SECTION_HEADER[pex.COFFFileHeader.NumberOfSections];
|
||||
for (int i = 0; i < pex.COFFFileHeader.NumberOfSections; i++)
|
||||
pex.SectionTable = new SectionHeader[pex.ImageFileHeader.NumberOfSections];
|
||||
for (int i = 0; i < pex.ImageFileHeader.NumberOfSections; i++)
|
||||
{
|
||||
pex.SectionHeaders[i] = IMAGE_SECTION_HEADER.Deserialize(stream);
|
||||
pex.SectionTable[i] = SectionHeader.Deserialize(stream);
|
||||
}
|
||||
|
||||
// TODO: Uncomment these when RVA conversion works
|
||||
// TODO: Uncomment these when all directories are understod and implemented
|
||||
// // Export Table
|
||||
// var table = pex.SectionHeaders[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
// var table = pex.SectionTable[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
// 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.ExportTable = ExportDataSection.Deserialize(stream);
|
||||
// }
|
||||
@@ -112,33 +119,33 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
return pex;
|
||||
}
|
||||
|
||||
public static PEExecutable Deserialize(byte[] content, int offset)
|
||||
public static PortableExecutable Deserialize(byte[] content, int offset)
|
||||
{
|
||||
PEExecutable pex = new PEExecutable();
|
||||
PortableExecutable pex = new PortableExecutable();
|
||||
|
||||
try
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
pex.MSDOSStub = IMAGE_DOS_HEADER.Deserialize(content, offset); offset = pex.MSDOSStub.NewExeHeaderAddr;
|
||||
pex.COFFFileHeader = IMAGE_FILE_HEADER.Deserialize(content, offset); offset += Marshal.SizeOf(pex.COFFFileHeader);
|
||||
if (pex.COFFFileHeader.SizeOfOptionalHeader > 0)
|
||||
pex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(content, offset); offset = pex.DOSStubHeader.NewExeHeaderAddr;
|
||||
pex.ImageFileHeader = CommonObjectFileFormatHeader.Deserialize(content, offset); offset += Marshal.SizeOf(pex.ImageFileHeader);
|
||||
if (pex.ImageFileHeader.SizeOfOptionalHeader > 0)
|
||||
{
|
||||
pex.OptionalHeader = IMAGE_OPTIONAL_HEADER.Deserialize(content, offset); offset += pex.COFFFileHeader.SizeOfOptionalHeader;
|
||||
pex.OptionalHeader = OptionalHeader.Deserialize(content, offset); offset += pex.ImageFileHeader.SizeOfOptionalHeader;
|
||||
}
|
||||
|
||||
pex.SectionHeaders = new IMAGE_SECTION_HEADER[pex.COFFFileHeader.NumberOfSections];
|
||||
for (int i = 0; i < pex.COFFFileHeader.NumberOfSections; i++)
|
||||
pex.SectionTable = new SectionHeader[pex.ImageFileHeader.NumberOfSections];
|
||||
for (int i = 0; i < pex.ImageFileHeader.NumberOfSections; i++)
|
||||
{
|
||||
pex.SectionHeaders[i] = IMAGE_SECTION_HEADER.Deserialize(content, offset); offset += 40;
|
||||
pex.SectionTable[i] = SectionHeader.Deserialize(content, offset); offset += 40;
|
||||
}
|
||||
|
||||
// TODO: Uncomment these when RVA conversion works
|
||||
// TODO: Uncomment these when all directories are understod and implemented
|
||||
// // Export Table
|
||||
// var table = pex.SectionHeaders[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
// var table = pex.SectionTable[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
// if (table.VirtualSize > 0)
|
||||
// {
|
||||
// int tableAddress = (int)EVORE.ConvertVirtualAddress(table.VirtualAddress, pex.SectionHeaders);
|
||||
// int tableAddress = (int)EVORE.ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
|
||||
// pex.ExportTable = ExportDataSection.Deserialize(content, tableAddress);
|
||||
// }
|
||||
|
||||
@@ -1,47 +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
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource type or name string
|
||||
/// </summary>
|
||||
/// TODO: Fix this because SizeConst = 0 is not valid
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class RsrcString
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of bytes in string
|
||||
/// </summary>
|
||||
public byte Length;
|
||||
|
||||
/// <summary>
|
||||
/// Next of string
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
|
||||
public char[] Text;
|
||||
|
||||
public static RsrcString Deserialize(Stream stream)
|
||||
{
|
||||
var rs = new RsrcString();
|
||||
|
||||
rs.Length = stream.ReadByteValue();
|
||||
rs.Text = stream.ReadChars(rs.Length);
|
||||
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Tables;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Sections
|
||||
{
|
||||
/// <summary>
|
||||
/// A series of resource directory tables relates all of the levels in the following way:
|
||||
// Each directory table is followed by a series of directory entries that give the name or
|
||||
// identifier (ID) for that level (Type, Name, or Language level) and an address of either
|
||||
// a data description or another directory table. If the address points to a data description,
|
||||
// then the data is a leaf in the tree. If the address points to another directory table,
|
||||
// then that table lists directory entries at the next level down
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-rsrc-section</remarks>
|
||||
internal class ResourceSection
|
||||
{
|
||||
/// <summary>
|
||||
/// A table with just one row (unlike the debug directory).
|
||||
/// This table indicates the locations and sizes of the other export tables.
|
||||
/// </summary>
|
||||
public ResourceDirectoryTable ResourceDirectoryTable;
|
||||
|
||||
public static ResourceSection Deserialize(Stream stream)
|
||||
{
|
||||
var rs = new ResourceSection();
|
||||
|
||||
rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(stream);
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
public static ResourceSection Deserialize(byte[] content, int offset)
|
||||
{
|
||||
var rs = new ResourceSection();
|
||||
|
||||
unsafe
|
||||
{
|
||||
rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(content, offset); offset += Marshal.SizeOf(rs.ResourceDirectoryTable);
|
||||
}
|
||||
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
{
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
{
|
||||
/// <summary>
|
||||
/// Each resource directory table has the following format.
|
||||
/// This data structure should be considered the heading of a table
|
||||
/// because the table actually consists of directory entries and this structure
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class ResourceDirectoryTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource flags.
|
||||
/// This field is reserved for future use.
|
||||
/// It is currently set to zero.
|
||||
/// </summary>
|
||||
public uint Characteristics;
|
||||
|
||||
/// <summary>
|
||||
/// The time that the resource data was created by the resource compiler.
|
||||
/// </summary>
|
||||
public uint TimeDateStamp;
|
||||
|
||||
/// <summary>
|
||||
/// The major version number, set by the user.
|
||||
/// </summary>
|
||||
public ushort MajorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The minor version number, set by the user.
|
||||
/// </summary>
|
||||
public ushort MinorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The number of directory entries immediately following
|
||||
/// the table that use strings to identify Type, Name, or
|
||||
/// Language entries (depending on the level of the table).
|
||||
/// </summary>
|
||||
public ushort NumberOfNamedEntries;
|
||||
|
||||
/// <summary>
|
||||
/// The number of directory entries immediately following
|
||||
/// the Name entries that use numeric IDs for Type, Name,
|
||||
/// or Language entries.
|
||||
/// </summary>
|
||||
public ushort NumberOfIdEntries;
|
||||
|
||||
/// <summary>
|
||||
/// The directory entries immediately following
|
||||
/// the table that use strings to identify Type, Name, or
|
||||
/// Language entries (depending on the level of the table).
|
||||
/// </summary>
|
||||
public ResourceDirectoryTableEntry[] NamedEntries;
|
||||
|
||||
/// <summary>
|
||||
/// The directory entries immediately following
|
||||
/// the Name entries that use numeric IDs for Type, Name,
|
||||
/// or Language entries.
|
||||
/// </summary>
|
||||
public ResourceDirectoryTableEntry[] IdEntries;
|
||||
|
||||
// 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)
|
||||
{
|
||||
var rdt = new ResourceDirectoryTable();
|
||||
|
||||
rdt.Characteristics = stream.ReadUInt32();
|
||||
rdt.TimeDateStamp = stream.ReadUInt32();
|
||||
rdt.MajorVersion = stream.ReadUInt16();
|
||||
rdt.MinorVersion = stream.ReadUInt16();
|
||||
rdt.NumberOfNamedEntries = stream.ReadUInt16();
|
||||
rdt.NumberOfIdEntries = stream.ReadUInt16();
|
||||
|
||||
rdt.NamedEntries = new ResourceDirectoryTableEntry[rdt.NumberOfNamedEntries];
|
||||
for (int i = 0; i < rdt.NumberOfNamedEntries; i++)
|
||||
{
|
||||
rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(stream);
|
||||
}
|
||||
|
||||
rdt.IdEntries = new ResourceDirectoryTableEntry[rdt.NumberOfIdEntries];
|
||||
for (int i = 0; i < rdt.NumberOfIdEntries; i++)
|
||||
{
|
||||
rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(stream);
|
||||
}
|
||||
|
||||
return rdt;
|
||||
}
|
||||
|
||||
public static ResourceDirectoryTable Deserialize(byte[] content, int offset)
|
||||
{
|
||||
var rdt = new ResourceDirectoryTable();
|
||||
|
||||
rdt.Characteristics = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
rdt.TimeDateStamp = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
rdt.MajorVersion = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
rdt.MinorVersion = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
rdt.NumberOfNamedEntries = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
rdt.NumberOfIdEntries = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
|
||||
rdt.NamedEntries = new ResourceDirectoryTableEntry[rdt.NumberOfNamedEntries];
|
||||
for (int i = 0; i < rdt.NumberOfNamedEntries; i++)
|
||||
{
|
||||
rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, offset); 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;
|
||||
}
|
||||
|
||||
return rdt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ namespace BurnOutSharp.PackerType
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug = false)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
PEExecutable pex = PEExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionHeaders;
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace BurnOutSharp.PackerType
|
||||
var rdataSection = sections.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).StartsWith(".rdata"));
|
||||
if (rdataSection != null)
|
||||
{
|
||||
int sectionAddr = (int)EVORE.ConvertVirtualAddress(rdataSection.VirtualAddress, sections);
|
||||
int sectionAddr = (int)rdataSection.PointerToRawData;
|
||||
int sectionEnd = sectionAddr + (int)rdataSection.VirtualSize;
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
|
||||
@@ -25,8 +25,8 @@ namespace BurnOutSharp.PackerType
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug = false)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
PEExecutable pex = PEExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionHeaders;
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace BurnOutSharp.PackerType
|
||||
// Loop through all "extension" sections
|
||||
foreach (var section in sections.Where(s => s != null && Encoding.ASCII.GetString(s.Name).Trim('\0').EndsWith("1")))
|
||||
{
|
||||
int sectionAddr = (int)EVORE.ConvertVirtualAddress(section.VirtualAddress, sections);
|
||||
int sectionAddr = (int)section.PointerToRawData;
|
||||
int sectionEnd = sectionAddr + (int)section.VirtualSize;
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
|
||||
@@ -22,8 +22,8 @@ namespace BurnOutSharp.PackerType
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug = false)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
PEExecutable pex = PEExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionHeaders;
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace BurnOutSharp.PackerType
|
||||
});
|
||||
if (dataSection != null)
|
||||
{
|
||||
int sectionAddr = (int)EVORE.ConvertVirtualAddress(dataSection.VirtualAddress, sections);
|
||||
int sectionAddr = (int)dataSection.PointerToRawData;
|
||||
int sectionEnd = sectionAddr + (int)dataSection.VirtualSize;
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
@@ -56,7 +56,7 @@ namespace BurnOutSharp.PackerType
|
||||
}
|
||||
|
||||
// Get the DOS stub from the executable, if possible
|
||||
var stub = pex?.MSDOSStub;
|
||||
var stub = pex?.DOSStubHeader;
|
||||
if (stub == null)
|
||||
return null;
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ namespace BurnOutSharp.PackerType
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug = false)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
PEExecutable pex = PEExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionHeaders;
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace BurnOutSharp.PackerType
|
||||
});
|
||||
if (dataSection != null)
|
||||
{
|
||||
int sectionAddr = (int)EVORE.ConvertVirtualAddress(dataSection.VirtualAddress, sections);
|
||||
int sectionAddr = (int)dataSection.PointerToRawData;
|
||||
int sectionEnd = sectionAddr + (int)dataSection.VirtualSize;
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using BurnOutSharp.Matching;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
@@ -43,6 +46,18 @@ namespace BurnOutSharp.PackerType
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug = false)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Assembly information lives in the .rsrc section
|
||||
// I need to find out how to navigate the resources in general
|
||||
// as well as figure out the specific resources for both
|
||||
// file info and MUI (XML) info. Once I figure this out,
|
||||
// that also opens the doors to easier assembly XML checks.
|
||||
|
||||
var fvinfo = Utilities.GetFileVersionInfo(file);
|
||||
|
||||
string name = fvinfo?.FileDescription?.Trim();
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.Matching;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
@@ -16,8 +17,8 @@ namespace BurnOutSharp.PackerType
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug = false)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
PEExecutable pex = PEExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionHeaders;
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
@@ -92,7 +93,7 @@ namespace BurnOutSharp.PackerType
|
||||
/// <param name="sections">Array of sections to check against</param>
|
||||
/// <param name="sectionPrefix">Prefix of the sections to check for</param>
|
||||
/// <returns>Real address of the section data, -1 on error</returns>
|
||||
private int FindData(byte[] fileContent, IMAGE_SECTION_HEADER[] sections, string sectionPrefix)
|
||||
private int FindData(byte[] fileContent, SectionHeader[] sections, string sectionPrefix)
|
||||
{
|
||||
// Get the two matching sections, if possible
|
||||
var firstSection = sections.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).StartsWith($"{sectionPrefix}0"));
|
||||
@@ -103,7 +104,7 @@ namespace BurnOutSharp.PackerType
|
||||
return -1;
|
||||
|
||||
// Return the first section address
|
||||
return (int)EVORE.ConvertVirtualAddress(firstSection.VirtualAddress, sections);
|
||||
return (int)firstSection.PointerToRawData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,8 @@ namespace BurnOutSharp.ProtectionType
|
||||
// (char)0x00 + (char)0x00 + BoG_
|
||||
new ContentMatchSet(new byte?[] { 0x00, 0x00, 0x42, 0x6F, 0x47, 0x5F }, Get320to4xVersion, "SafeDisc"),
|
||||
|
||||
// TODO: These two following are section headers. They should be converted to section header checks instead
|
||||
|
||||
// stxt774
|
||||
new ContentMatchSet(new byte?[] { 0x73, 0x74, 0x78, 0x74, 0x37, 0x37, 0x34 }, Get320to4xVersion, "SafeDisc"),
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Sections;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Tables;
|
||||
|
||||
@@ -35,7 +36,7 @@ namespace BurnOutSharp.Tools
|
||||
/// <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>
|
||||
internal static uint ConvertVirtualAddress(uint virtualAddress, IMAGE_SECTION_HEADER[] sections)
|
||||
internal static uint ConvertVirtualAddress(uint virtualAddress, SectionHeader[] sections)
|
||||
{
|
||||
// Loop through all of the sections
|
||||
for (int i = 0; i < sections.Length; i++)
|
||||
@@ -65,8 +66,8 @@ namespace BurnOutSharp.Tools
|
||||
|
||||
try
|
||||
{
|
||||
PEExecutable pex = PEExecutable.Deserialize(fileContent, 0);
|
||||
return pex.COFFFileHeader.Characteristics.HasFlag(ImageObjectCharacteristics.IMAGE_FILE_DLL);
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
return pex.ImageFileHeader.Characteristics.HasFlag(ImageObjectCharacteristics.IMAGE_FILE_DLL);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -125,13 +126,13 @@ namespace BurnOutSharp.Tools
|
||||
unsafe
|
||||
{
|
||||
// Read all of the executable header information
|
||||
PEExecutable pex = PEExecutable.Deserialize(fileContent, 0);
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
|
||||
// Find the import directory entry
|
||||
IMAGE_DATA_DIRECTORY idei = pex.OptionalHeader.DataDirectories[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
|
||||
// Set the table index and size
|
||||
int tableIndex = (int)ConvertVirtualAddress(idei.VirtualAddress, pex.SectionHeaders);
|
||||
int tableIndex = (int)ConvertVirtualAddress(idei.VirtualAddress, pex.SectionTable);
|
||||
int tableSize = (int)idei.Size;
|
||||
if (tableIndex <= 0 || tableSize <= 0)
|
||||
return null;
|
||||
|
||||
@@ -39,11 +39,16 @@ namespace BurnOutSharp.Tools
|
||||
/// <summary>
|
||||
/// Read a character array from the stream
|
||||
/// </summary>
|
||||
public static char[] ReadChars(this Stream stream, int count)
|
||||
public static char[] ReadChars(this Stream stream, int count) => stream.ReadChars(count, Encoding.Default);
|
||||
|
||||
/// <summary>
|
||||
/// Read a character array from the stream
|
||||
/// </summary>
|
||||
public static char[] ReadChars(this Stream stream, int count, Encoding encoding)
|
||||
{
|
||||
byte[] buffer = new byte[count];
|
||||
stream.Read(buffer, 0, count);
|
||||
return Encoding.Default.GetString(buffer).ToCharArray();
|
||||
return encoding.GetString(buffer).ToCharArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user