mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-04-19 04:32:55 +00:00
Process file info resources; cleanup; refactors
This commit is contained in:
@@ -35,7 +35,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return eate;
|
||||
}
|
||||
|
||||
public static ExportAddressTableEntry Deserialize(byte[] content, int offset)
|
||||
public static ExportAddressTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var eate = new ExportAddressTableEntry();
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return hnte;
|
||||
}
|
||||
|
||||
public static HintNameTableEntry Deserialize(byte[] content, int offset)
|
||||
public static HintNameTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var hnte = new HintNameTableEntry();
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return iate;
|
||||
}
|
||||
|
||||
public static ImportAddressTableEntry Deserialize(byte[] content, int offset)
|
||||
public static ImportAddressTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var iate = new ImportAddressTableEntry();
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return idte;
|
||||
}
|
||||
|
||||
public static ImportDirectoryTableEntry Deserialize(byte[] content, int offset)
|
||||
public static ImportDirectoryTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var idte = new ImportDirectoryTableEntry();
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
@@ -8,7 +7,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
/// <summary>
|
||||
/// Resource type and name strings
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class NEResourceNameString
|
||||
{
|
||||
/// <summary>
|
||||
@@ -33,12 +31,12 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return rds;
|
||||
}
|
||||
|
||||
public static NEResourceNameString Deserialize(byte[] contents, int offset)
|
||||
public static NEResourceNameString Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var rds = new NEResourceNameString();
|
||||
|
||||
rds.Length = contents[offset++];
|
||||
rds.Value = Encoding.ASCII.GetChars(contents, offset, rds.Length);
|
||||
rds.Length = content[offset++];
|
||||
rds.Value = Encoding.ASCII.GetChars(content, offset, rds.Length); offset += rds.Length;
|
||||
|
||||
return rds;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
@@ -8,7 +7,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
/// <summary>
|
||||
/// A table of resources for this type
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class NEResourceTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
@@ -61,16 +59,16 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return ni;
|
||||
}
|
||||
|
||||
public static NEResourceTableEntry Deserialize(byte[] contents, int offset)
|
||||
public static NEResourceTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var ni = new NEResourceTableEntry();
|
||||
|
||||
ni.Offset = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
ni.Length = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
ni.Flags = (ResourceTableEntryFlags)BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
ni.ResourceID = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
ni.Handle = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
ni.Usage = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
ni.Offset = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
ni.Length = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
ni.Flags = (ResourceTableEntryFlags)BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
ni.ResourceID = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
ni.Handle = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
ni.Usage = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
|
||||
return ni;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
@@ -11,7 +10,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
/// EXE header. The first entry in the segment table is segment number 1.
|
||||
/// The following is the structure of a segment table entry.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class NESegmentTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
@@ -49,7 +47,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return nste;
|
||||
}
|
||||
|
||||
public static NESegmentTableEntry Deserialize(byte[] content, int offset)
|
||||
public static NESegmentTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var nste = new NESegmentTableEntry();
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.Tools;
|
||||
@@ -11,7 +10,6 @@ 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>
|
||||
@@ -27,7 +25,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
/// <summary>
|
||||
/// A unit of resource data in the Resource Data area.
|
||||
/// </summary>
|
||||
public string EncodedData
|
||||
public string DataAsUTF8String
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -38,7 +36,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
try
|
||||
{
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
return Encoding.GetEncoding(codePage).GetString(Data);
|
||||
var originalEncoding = Encoding.GetEncoding(codePage);
|
||||
byte[] convertedData = Encoding.Convert(originalEncoding, Encoding.UTF8, Data);
|
||||
return Encoding.UTF8.GetString(convertedData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -85,7 +85,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return rde;
|
||||
}
|
||||
|
||||
public static ResourceDataEntry Deserialize(byte[] content, int offset, SectionHeader[] sections)
|
||||
public static ResourceDataEntry Deserialize(byte[] content, ref int offset, SectionHeader[] sections)
|
||||
{
|
||||
var rde = new ResourceDataEntry();
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
@@ -11,7 +10,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
/// 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>
|
||||
@@ -34,12 +32,12 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return rds;
|
||||
}
|
||||
|
||||
public static ResourceDirectoryString Deserialize(byte[] content, int offset)
|
||||
public static ResourceDirectoryString Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var rds = new ResourceDirectoryString();
|
||||
|
||||
rds.Length = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
rds.UnicodeString = Encoding.Unicode.GetString(content, offset, rds.Length);
|
||||
rds.UnicodeString = Encoding.Unicode.GetString(content, offset, rds.Length); offset += rds.Length;
|
||||
|
||||
return rds;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return rdte;
|
||||
}
|
||||
|
||||
public static ResourceDirectoryTableEntry Deserialize(byte[] content, int offset, long sectionStart, SectionHeader[] sections)
|
||||
public static ResourceDirectoryTableEntry Deserialize(byte[] content, ref int offset, long sectionStart, SectionHeader[] sections)
|
||||
{
|
||||
var rdte = new ResourceDirectoryTableEntry();
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
{
|
||||
int nameAddress = (int)(rdte.NameOffset + sectionStart);
|
||||
if (nameAddress >= 0 && nameAddress < content.Length)
|
||||
rdte.Name = ResourceDirectoryString.Deserialize(content, nameAddress);
|
||||
rdte.Name = ResourceDirectoryString.Deserialize(content, ref nameAddress);
|
||||
}
|
||||
|
||||
rdte.DataEntryOffset = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
@@ -128,13 +128,13 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
{
|
||||
int dataEntryAddress = (int)(rdte.DataEntryOffset + sectionStart);
|
||||
if (dataEntryAddress > 0 && dataEntryAddress < content.Length)
|
||||
rdte.DataEntry = ResourceDataEntry.Deserialize(content, dataEntryAddress, sections);
|
||||
rdte.DataEntry = ResourceDataEntry.Deserialize(content, ref dataEntryAddress, sections);
|
||||
}
|
||||
else
|
||||
{
|
||||
int subdirectoryAddress = (int)(rdte.SubdirectoryOffset + sectionStart);
|
||||
if (subdirectoryAddress > 0 && subdirectoryAddress < content.Length)
|
||||
rdte.Subdirectory = ResourceDirectoryTable.Deserialize(content, subdirectoryAddress, sectionStart, sections);
|
||||
rdte.Subdirectory = ResourceDirectoryTable.Deserialize(content, ref subdirectoryAddress, sectionStart, sections);
|
||||
}
|
||||
|
||||
// TODO: Add parsing for further directory table entries in the tree
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
@@ -8,7 +7,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
/// <summary>
|
||||
/// Resource type information block
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class ResourceTypeInformationBlock
|
||||
{
|
||||
/// <summary>
|
||||
@@ -52,18 +50,18 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return rtib;
|
||||
}
|
||||
|
||||
public static ResourceTypeInformationBlock Deserialize(byte[] contents, int offset)
|
||||
public static ResourceTypeInformationBlock Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var rtib = new ResourceTypeInformationBlock();
|
||||
|
||||
rtib.TypeID = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
rtib.ResourceCount = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
rtib.Reserved = BitConverter.ToUInt32(contents, offset); offset += 4;
|
||||
rtib.TypeID = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
rtib.ResourceCount = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
rtib.Reserved = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
|
||||
rtib.ResourceTable = new NEResourceTableEntry[rtib.ResourceCount];
|
||||
for (int i = 0; i < rtib.ResourceCount; i++)
|
||||
{
|
||||
rtib.ResourceTable[i] = NEResourceTableEntry.Deserialize(contents, offset); offset += 12;
|
||||
rtib.ResourceTable[i] = NEResourceTableEntry.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
return rtib;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class CommonObjectFileFormatHeader
|
||||
{
|
||||
/// <summary>
|
||||
@@ -71,7 +69,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
return ifh;
|
||||
}
|
||||
|
||||
public static CommonObjectFileFormatHeader Deserialize(byte[] content, int offset)
|
||||
public static CommonObjectFileFormatHeader Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var ifh = new CommonObjectFileFormatHeader();
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class DataDirectoryHeader
|
||||
{
|
||||
/// <summary>
|
||||
@@ -29,7 +27,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
return ddh;
|
||||
}
|
||||
|
||||
public static DataDirectoryHeader Deserialize(byte[] content, int offset)
|
||||
public static DataDirectoryHeader Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var ddh = new DataDirectoryHeader();
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
@@ -14,7 +13,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
/// 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
|
||||
@@ -102,7 +100,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
/// <summary>
|
||||
/// Reserved words [1C]
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.ERES1WDS)]
|
||||
public ushort[] Reserved1;
|
||||
|
||||
/// <summary>
|
||||
@@ -118,7 +115,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
/// <summary>
|
||||
/// Reserved words [28]
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.ERES2WDS)]
|
||||
public ushort[] Reserved2;
|
||||
|
||||
/// <summary>
|
||||
@@ -168,7 +164,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
return idh;
|
||||
}
|
||||
|
||||
public static MSDOSExecutableHeader Deserialize(byte[] content, int offset, bool asStub = true)
|
||||
public static MSDOSExecutableHeader Deserialize(byte[] content, ref int offset, bool asStub = true)
|
||||
{
|
||||
MSDOSExecutableHeader idh = new MSDOSExecutableHeader();
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
@@ -10,7 +9,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
/// Because of the age of the format some items are unclear in meaning.
|
||||
/// </summary>
|
||||
/// <remarks>http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm</remarks>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class NewExecutableHeader
|
||||
{
|
||||
/// <summary>
|
||||
@@ -216,42 +214,42 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
return neh;
|
||||
}
|
||||
|
||||
public static NewExecutableHeader Deserialize(byte[] contents, int offset)
|
||||
public static NewExecutableHeader Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var neh = new NewExecutableHeader();
|
||||
|
||||
neh.Magic = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.LinkerVersion = contents[offset++];
|
||||
neh.LinkerRevision = contents[offset++];
|
||||
neh.EntryTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.EntryTableSize = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.CrcChecksum = BitConverter.ToUInt32(contents, offset); offset += 4;
|
||||
neh.ProgramFlags = contents[offset++];
|
||||
neh.ApplicationFlags = contents[offset++];
|
||||
neh.Autodata = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.InitialHeapAlloc = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.InitialStackAlloc = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.InitialCSIPSetting = BitConverter.ToUInt32(contents, offset); offset += 4;
|
||||
neh.InitialSSSPSetting = BitConverter.ToUInt32(contents, offset); offset += 4;
|
||||
neh.FileSegmentCount = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.ModuleReferenceTableSize = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.NonResidentNameTableSize = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.SegmentTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.ResourceTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.ResidentNameTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.ModuleReferenceTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.ImportedNamesTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.NonResidentNamesTableOffset = BitConverter.ToUInt32(contents, offset); offset += 4;
|
||||
neh.MovableEntriesCount = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.SegmentAlignmentShiftCount = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.ResourceEntriesCount = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.TargetOperatingSystem = contents[offset++];
|
||||
neh.AdditionalFlags = contents[offset++];
|
||||
neh.ReturnThunkOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.SegmentReferenceThunkOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.MinCodeSwapAreaSize = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
neh.WindowsSDKRevision = contents[offset++];
|
||||
neh.WindowsSDKVersion = contents[offset++];
|
||||
neh.Magic = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.LinkerVersion = content[offset++];
|
||||
neh.LinkerRevision = content[offset++];
|
||||
neh.EntryTableOffset = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.EntryTableSize = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.CrcChecksum = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
neh.ProgramFlags = content[offset++];
|
||||
neh.ApplicationFlags = content[offset++];
|
||||
neh.Autodata = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.InitialHeapAlloc = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.InitialStackAlloc = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.InitialCSIPSetting = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
neh.InitialSSSPSetting = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
neh.FileSegmentCount = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.ModuleReferenceTableSize = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.NonResidentNameTableSize = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.SegmentTableOffset = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.ResourceTableOffset = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.ResidentNameTableOffset = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.ModuleReferenceTableOffset = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.ImportedNamesTableOffset = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.NonResidentNamesTableOffset = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
neh.MovableEntriesCount = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.SegmentAlignmentShiftCount = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.ResourceEntriesCount = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.TargetOperatingSystem = content[offset++];
|
||||
neh.AdditionalFlags = content[offset++];
|
||||
neh.ReturnThunkOffset = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.SegmentReferenceThunkOffset = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.MinCodeSwapAreaSize = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
neh.WindowsSDKRevision = content[offset++];
|
||||
neh.WindowsSDKVersion = content[offset++];
|
||||
|
||||
return neh;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
@@ -19,7 +18,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
/// 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 OptionalHeader
|
||||
{
|
||||
#region Standard Fields
|
||||
@@ -231,7 +229,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
/// <summary>
|
||||
/// Data-directory entries following the optional header
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES)]
|
||||
public DataDirectoryHeader[] DataDirectories;
|
||||
|
||||
#endregion
|
||||
@@ -301,7 +298,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
return ioh;
|
||||
}
|
||||
|
||||
public static OptionalHeader Deserialize(byte[] content, int offset)
|
||||
public static OptionalHeader Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var ioh = new OptionalHeader();
|
||||
|
||||
@@ -364,7 +361,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
ioh.DataDirectories = new DataDirectoryHeader[Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
for (int i = 0; i < Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
|
||||
{
|
||||
ioh.DataDirectories[i] = DataDirectoryHeader.Deserialize(content, offset); offset += 8;
|
||||
ioh.DataDirectories[i] = DataDirectoryHeader.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
return ioh;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
@@ -12,7 +11,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
/// 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>
|
||||
@@ -23,7 +21,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
/// 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>
|
||||
@@ -110,7 +107,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
return ish;
|
||||
}
|
||||
|
||||
public static SectionHeader Deserialize(byte[] content, int offset)
|
||||
public static SectionHeader Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var ish = new SectionHeader();
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
@@ -41,7 +40,8 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
try
|
||||
{
|
||||
// Attempt to read the DOS header first
|
||||
nex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(stream); stream.Seek(nex.DOSStubHeader.NewExeHeaderAddr, SeekOrigin.Begin);
|
||||
nex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(stream);
|
||||
stream.Seek(nex.DOSStubHeader.NewExeHeaderAddr, SeekOrigin.Begin);
|
||||
if (nex.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
|
||||
return null;
|
||||
|
||||
@@ -70,22 +70,20 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
|
||||
try
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
// Attempt to read the DOS header first
|
||||
nex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(content, offset); offset = nex.DOSStubHeader.NewExeHeaderAddr;
|
||||
if (nex.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
|
||||
return null;
|
||||
// Attempt to read the DOS header first
|
||||
nex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(content, ref offset);
|
||||
offset = nex.DOSStubHeader.NewExeHeaderAddr;
|
||||
if (nex.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
|
||||
return null;
|
||||
|
||||
// If the new header address is invalid for the file, it's not a PE
|
||||
if (nex.DOSStubHeader.NewExeHeaderAddr >= content.Length)
|
||||
return null;
|
||||
// If the new header address is invalid for the file, it's not a PE
|
||||
if (nex.DOSStubHeader.NewExeHeaderAddr >= content.Length)
|
||||
return null;
|
||||
|
||||
// Then attempt to read the NE header
|
||||
nex.NewExecutableHeader = NewExecutableHeader.Deserialize(content, offset); offset += Marshal.SizeOf(nex.NewExecutableHeader);
|
||||
if (nex.NewExecutableHeader.Magic != Constants.IMAGE_OS2_SIGNATURE)
|
||||
return null;
|
||||
}
|
||||
// Then attempt to read the NE header
|
||||
nex.NewExecutableHeader = NewExecutableHeader.Deserialize(content, ref offset);
|
||||
if (nex.NewExecutableHeader.Magic != Constants.IMAGE_OS2_SIGNATURE)
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Sections;
|
||||
@@ -234,59 +233,54 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
|
||||
try
|
||||
{
|
||||
unsafe
|
||||
// Attempt to read the DOS header first
|
||||
pex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(content, ref offset);
|
||||
offset = pex.DOSStubHeader.NewExeHeaderAddr;
|
||||
if (pex.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
|
||||
return null;
|
||||
|
||||
// If the new header address is invalid for the file, it's not a PE
|
||||
if (pex.DOSStubHeader.NewExeHeaderAddr >= content.Length)
|
||||
return null;
|
||||
|
||||
// Then attempt to read the PE header
|
||||
pex.ImageFileHeader = CommonObjectFileFormatHeader.Deserialize(content, ref offset);
|
||||
if (pex.ImageFileHeader.Signature != Constants.IMAGE_NT_SIGNATURE)
|
||||
return null;
|
||||
|
||||
// If the optional header is supposed to exist, read that as well
|
||||
if (pex.ImageFileHeader.SizeOfOptionalHeader > 0)
|
||||
pex.OptionalHeader = OptionalHeader.Deserialize(content, ref offset);
|
||||
|
||||
// Then read in the section table
|
||||
pex.SectionTable = new SectionHeader[pex.ImageFileHeader.NumberOfSections];
|
||||
for (int i = 0; i < pex.ImageFileHeader.NumberOfSections; i++)
|
||||
{
|
||||
// Attempt to read the DOS header first
|
||||
pex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(content, offset); offset = pex.DOSStubHeader.NewExeHeaderAddr;
|
||||
if (pex.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
|
||||
return null;
|
||||
pex.SectionTable[i] = SectionHeader.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
// If the new header address is invalid for the file, it's not a PE
|
||||
if (pex.DOSStubHeader.NewExeHeaderAddr >= content.Length)
|
||||
return null;
|
||||
// // Export Table
|
||||
// var table = pex.GetSection(".edata", true);
|
||||
// if (table != null && table.VirtualSize > 0)
|
||||
// {
|
||||
// int tableAddress = (int)ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
|
||||
// pex.ExportTable = ExportDataSection.Deserialize(content, tableAddress);
|
||||
// }
|
||||
|
||||
// Then attempt to read the PE header
|
||||
pex.ImageFileHeader = CommonObjectFileFormatHeader.Deserialize(content, offset); offset += Marshal.SizeOf(pex.ImageFileHeader);
|
||||
if (pex.ImageFileHeader.Signature != Constants.IMAGE_NT_SIGNATURE)
|
||||
return null;
|
||||
// // Import Table
|
||||
// table = pex.GetSection(".idata", true);
|
||||
// if (table != null && table.VirtualSize > 0)
|
||||
// {
|
||||
// int tableAddress = (int)ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
|
||||
// pex.ImportTable = ImportDataSection.Deserialize(content, tableAddress, pex.OptionalHeader.Magic == OptionalHeaderType.PE32Plus, hintCount: 0);
|
||||
// }
|
||||
|
||||
// If the optional header is supposed to exist, read that as well
|
||||
if (pex.ImageFileHeader.SizeOfOptionalHeader > 0)
|
||||
{
|
||||
pex.OptionalHeader = OptionalHeader.Deserialize(content, offset);
|
||||
offset += pex.ImageFileHeader.SizeOfOptionalHeader;
|
||||
}
|
||||
|
||||
// Then read in the section table
|
||||
pex.SectionTable = new SectionHeader[pex.ImageFileHeader.NumberOfSections];
|
||||
for (int i = 0; i < pex.ImageFileHeader.NumberOfSections; i++)
|
||||
{
|
||||
pex.SectionTable[i] = SectionHeader.Deserialize(content, offset); offset += 40;
|
||||
}
|
||||
|
||||
// // Export Table
|
||||
// var table = pex.GetSection(".edata", true);
|
||||
// if (table != null && table.VirtualSize > 0)
|
||||
// {
|
||||
// int tableAddress = (int)ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
|
||||
// pex.ExportTable = ExportDataSection.Deserialize(content, tableAddress);
|
||||
// }
|
||||
|
||||
// // Import Table
|
||||
// table = pex.GetSection(".idata", true);
|
||||
// if (table != null && table.VirtualSize > 0)
|
||||
// {
|
||||
// int tableAddress = (int)ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
|
||||
// pex.ImportTable = ImportDataSection.Deserialize(content, tableAddress, pex.OptionalHeader.Magic == OptionalHeaderType.PE32Plus, hintCount: 0);
|
||||
// }
|
||||
|
||||
// Resource Table
|
||||
var table = pex.GetSection(".rsrc", true);
|
||||
if (table != null && table.VirtualSize > 0)
|
||||
{
|
||||
int tableAddress = (int)ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
|
||||
pex.ResourceSection = ResourceSection.Deserialize(content, tableAddress, pex.SectionTable);
|
||||
}
|
||||
// Resource Table
|
||||
var table = pex.GetSection(".rsrc", true);
|
||||
if (table != null && table.VirtualSize > 0)
|
||||
{
|
||||
int tableAddress = (int)ConvertVirtualAddress(table.VirtualAddress, pex.SectionTable);
|
||||
pex.ResourceSection = ResourceSection.Deserialize(content, ref tableAddress, pex.SectionTable);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
202
BurnOutSharp/ExecutableType/Microsoft/Resources/FixedFileInfo.cs
Normal file
202
BurnOutSharp/ExecutableType/Microsoft/Resources/FixedFileInfo.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
internal class FixedFileInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the value 0xFEEF04BD.
|
||||
/// This is used with the szKey member of the VS_VERSIONINFO structure when searching a file for the VS_FIXEDFILEINFO structure.
|
||||
/// </summary>
|
||||
public uint Signature;
|
||||
|
||||
/// <summary>
|
||||
/// The binary version number of this structure.
|
||||
/// The high-order word of this member contains the major version number, and the low-order word contains the minor version number.
|
||||
/// </summary>
|
||||
public uint StrucVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The most significant 32 bits of the file's binary version number.
|
||||
/// This member is used with dwFileVersionLS to form a 64-bit value used for numeric comparisons.
|
||||
/// </summary>
|
||||
public uint FileVersionMS;
|
||||
|
||||
/// <summary>
|
||||
/// The least significant 32 bits of the file's binary version number.
|
||||
/// This member is used with dwFileVersionMS to form a 64-bit value used for numeric comparisons.
|
||||
/// </summary>
|
||||
public uint FileVersionLS;
|
||||
|
||||
/// <summary>
|
||||
/// The most significant 32 bits of the binary version number of the product with which this file was distributed.
|
||||
/// This member is used with dwProductVersionLS to form a 64-bit value used for numeric comparisons.
|
||||
/// </summary>
|
||||
public uint ProductVersionMS;
|
||||
|
||||
/// <summary>
|
||||
/// The least significant 32 bits of the binary version number of the product with which this file was distributed.
|
||||
/// This member is used with dwProductVersionMS to form a 64-bit value used for numeric comparisons.
|
||||
/// </summary>
|
||||
public uint ProductVersionLS;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a bitmask that specifies the valid bits in dwFileFlags.
|
||||
/// A bit is valid only if it was defined when the file was created.
|
||||
/// </summary>
|
||||
public uint FileFlagsMask;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a bitmask that specifies the Boolean attributes of the file. This member can include one or more of the following values.
|
||||
///
|
||||
/// VS_FF_DEBUG (0x00000001L) The file contains debugging information or is compiled with debugging features enabled.
|
||||
/// VS_FF_INFOINFERRED (0x00000010L) The file's version structure was created dynamically; therefore, some of the members in this structure may be empty or incorrect. This flag should never be set in a file's VS_VERSIONINFO data.
|
||||
/// VS_FF_PATCHED (0x00000004L) The file has been modified and is not identical to the original shipping file of the same version number.
|
||||
/// VS_FF_PRERELEASE (0x00000002L) The file is a development version, not a commercially released product.
|
||||
/// VS_FF_PRIVATEBUILD (0x00000008L) The file was not built using standard release procedures. If this flag is set, the StringFileInfo structure should contain a PrivateBuild entry.
|
||||
/// VS_FF_SPECIALBUILD (0x00000020L) The file was built by the original company using standard release procedures but is a variation of the normal file of the same version number. If this flag is set, the StringFileInfo structure should contain a SpecialBuild entry.
|
||||
/// </summary>
|
||||
/// <remarks>TODO: Make an enum out of this</remarks>
|
||||
public uint FileFlags;
|
||||
|
||||
/// <summary>
|
||||
/// The operating system for which this file was designed. This member can be one of the following values.
|
||||
///
|
||||
/// VOS_DOS (0x00010000L) The file was designed for MS-DOS.
|
||||
/// VOS_NT (0x00040000L) The file was designed for Windows NT.
|
||||
/// VOS__WINDOWS16 (0x00000001L) The file was designed for 16-bit Windows.
|
||||
/// VOS__WINDOWS32 (0x00000004L) The file was designed for 32-bit Windows.
|
||||
/// VOS_OS216 (0x00020000L) The file was designed for 16-bit OS/2.
|
||||
/// VOS_OS232 (0x00030000L) The file was designed for 32-bit OS/2.
|
||||
/// VOS__PM16 (0x00000002L) The file was designed for 16-bit Presentation Manager.
|
||||
/// VOS__PM32 (0x00000003L) The file was designed for 32-bit Presentation Manager.
|
||||
/// VOS_UNKNOWN (0x00000000L) The operating system for which the file was designed is unknown to the system.
|
||||
///
|
||||
/// An application can combine these values to indicate that the file was designed for one operating system running on another.
|
||||
/// The following dwFileOS values are examples of this, but are not a complete list.
|
||||
///
|
||||
/// VOS_DOS_WINDOWS16 (0x00010001L) The file was designed for 16-bit Windows running on MS-DOS.
|
||||
/// VOS_DOS_WINDOWS32 (0x00010004L) The file was designed for 32-bit Windows running on MS-DOS.
|
||||
/// VOS_NT_WINDOWS32 (0x00040004L) The file was designed for Windows NT.
|
||||
/// VOS_OS216_PM16 (0x00020002L) The file was designed for 16-bit Presentation Manager running on 16-bit OS/2.
|
||||
/// VOS_OS232_PM32 (0x00030003L) The file was designed for 32-bit Presentation Manager running on 32-bit OS/2.
|
||||
/// </summary>
|
||||
/// <remarks>TODO: Make an enum out of this</remarks>
|
||||
public uint FileOS;
|
||||
|
||||
/// <summary>
|
||||
/// The general type of file. This member can be one of the following values. All other values are reserved.
|
||||
///
|
||||
/// VFT_APP (0x00000001L) The file contains an application.
|
||||
/// VFT_DLL (0x00000002L) The file contains a DLL.
|
||||
/// VFT_DRV (0x00000003L) The file contains a device driver. If dwFileType is VFT_DRV, dwFileSubtype contains a more specific description of the driver.
|
||||
/// VFT_FONT (0x00000004L) The file contains a font. If dwFileType is VFT_FONT, dwFileSubtype contains a more specific description of the font file.
|
||||
/// VFT_STATIC_LIB (0x00000007L) The file contains a static-link library.
|
||||
/// VFT_UNKNOWN (0x00000000L) The file type is unknown to the system.
|
||||
/// VFT_VXD (0x00000005L) The file contains a virtual device.
|
||||
/// </summary>
|
||||
/// <remarks>TODO: Make an enum out of this</remarks>
|
||||
public uint FileType;
|
||||
|
||||
/// <summary>
|
||||
/// The function of the file. The possible values depend on the value of dwFileType.
|
||||
/// For all values of dwFileType not described in the following list, dwFileSubtype is zero.
|
||||
///
|
||||
/// If dwFileType is VFT_DRV, dwFileSubtype can be one of the following values.
|
||||
///
|
||||
/// VFT2_DRV_COMM (0x0000000AL) The file contains a communications driver.
|
||||
/// VFT2_DRV_DISPLAY (0x00000004L) The file contains a display driver.
|
||||
/// VFT2_DRV_INSTALLABLE (0x00000008L) The file contains an installable driver.
|
||||
/// VFT2_DRV_KEYBOARD (0x00000002L) The file contains a keyboard driver.
|
||||
/// VFT2_DRV_LANGUAGE (0x00000003L) The file contains a language driver.
|
||||
/// VFT2_DRV_MOUSE (0x00000005L) The file contains a mouse driver.
|
||||
/// VFT2_DRV_NETWORK (0x00000006L) The file contains a network driver.
|
||||
/// VFT2_DRV_PRINTER (0x00000001L) The file contains a printer driver.
|
||||
/// VFT2_DRV_SOUND (0x00000009L) The file contains a sound driver.
|
||||
/// VFT2_DRV_SYSTEM (0x00000007L) The file contains a system driver.
|
||||
/// VFT2_DRV_VERSIONED_PRINTER (0x0000000CL) The file contains a versioned printer driver.
|
||||
/// VFT2_UNKNOWN (0x00000000L) The driver type is unknown by the system.
|
||||
///
|
||||
/// If dwFileType is VFT_FONT, dwFileSubtype can be one of the following values.
|
||||
///
|
||||
/// VFT2_FONT_RASTER (0x00000001L) The file contains a raster font.
|
||||
/// VFT2_FONT_TRUETYPE (0x00000003L) The file contains a TrueType font.
|
||||
/// VFT2_FONT_VECTOR (0x00000002L) The file contains a vector font.
|
||||
/// VFT2_UNKNOWN (0x00000000L) The font type is unknown by the system.
|
||||
///
|
||||
/// If dwFileType is VFT_VXD, dwFileSubtype contains the virtual device identifier included in the virtual device control block.
|
||||
/// All dwFileSubtype values not listed here are reserved.
|
||||
/// </summary>
|
||||
/// <remarks>TODO: Make an enum out of this</remarks>
|
||||
public uint FileSubtype;
|
||||
|
||||
/// <summary>
|
||||
/// The most significant 32 bits of the file's 64-bit binary creation date and time stamp.
|
||||
/// </summary>
|
||||
public uint FileDateMS;
|
||||
|
||||
/// <summary>
|
||||
/// The least significant 32 bits of the file's 64-bit binary creation date and time stamp.
|
||||
/// </summary>
|
||||
public uint FileDateLS;
|
||||
|
||||
public static FixedFileInfo Deserialize(Stream stream)
|
||||
{
|
||||
FixedFileInfo ffi = new FixedFileInfo();
|
||||
|
||||
ushort temp;
|
||||
while ((temp = stream.ReadUInt16()) == 0x0000);
|
||||
stream.Seek(-2, SeekOrigin.Current);
|
||||
|
||||
ffi.Signature = stream.ReadUInt32();
|
||||
ffi.StrucVersion = stream.ReadUInt32();
|
||||
ffi.FileVersionMS = stream.ReadUInt32();
|
||||
ffi.FileVersionLS = stream.ReadUInt32();
|
||||
ffi.ProductVersionMS = stream.ReadUInt32();
|
||||
ffi.ProductVersionLS = stream.ReadUInt32();
|
||||
ffi.FileFlagsMask = stream.ReadUInt32();
|
||||
ffi.FileFlags = stream.ReadUInt32();
|
||||
ffi.FileOS = stream.ReadUInt32();
|
||||
ffi.FileType = stream.ReadUInt32();
|
||||
ffi.FileSubtype = stream.ReadUInt32();
|
||||
ffi.FileDateMS = stream.ReadUInt32();
|
||||
ffi.FileDateLS = stream.ReadUInt32();
|
||||
|
||||
return ffi;
|
||||
}
|
||||
|
||||
public static FixedFileInfo Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
FixedFileInfo ffi = new FixedFileInfo();
|
||||
|
||||
ushort temp;
|
||||
bool padded = false;
|
||||
while ((temp = BitConverter.ToUInt16(content, offset)) == 0x0000)
|
||||
{
|
||||
offset += 2;
|
||||
padded = true;
|
||||
}
|
||||
|
||||
if (padded)
|
||||
offset -= 2;
|
||||
|
||||
ffi.Signature = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.StrucVersion = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.FileVersionMS = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.FileVersionLS = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.ProductVersionMS = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.ProductVersionLS = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.FileFlagsMask = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.FileFlags = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.FileOS = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.FileType = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.FileSubtype = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.FileDateMS = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
ffi.FileDateLS = BitConverter.ToUInt32(content, offset); offset += 4;
|
||||
|
||||
return ffi;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
/// <summary>
|
||||
/// If you use the Var structure to list the languages your application or DLL supports instead of using multiple version resources,
|
||||
/// use the Value member to contain an array of DWORD values indicating the language and code page combinations supported by this file.
|
||||
/// The low-order word of each DWORD must contain a Microsoft language identifier, and the high-order word must contain the IBM code page number.
|
||||
/// Either high-order or low-order word can be zero, indicating that the file is language or code page independent.
|
||||
/// If the Var structure is omitted, the file will be interpreted as both language and code page independent.
|
||||
/// </summary>
|
||||
internal class LanguageCodePage
|
||||
{
|
||||
/// <summary>
|
||||
/// The low-order word of each DWORD must contain a Microsoft language identifier
|
||||
/// </summary>
|
||||
public ushort MicrosoftLanguageIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// The high-order word must contain the IBM code page number
|
||||
/// </summary>
|
||||
public ushort IBMCodePageNumber;
|
||||
|
||||
public static LanguageCodePage Deserialize(Stream stream)
|
||||
{
|
||||
LanguageCodePage lcp = new LanguageCodePage();
|
||||
|
||||
lcp.MicrosoftLanguageIdentifier = stream.ReadUInt16();
|
||||
lcp.IBMCodePageNumber = stream.ReadUInt16();
|
||||
|
||||
return lcp;
|
||||
}
|
||||
|
||||
public static LanguageCodePage Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
LanguageCodePage lcp = new LanguageCodePage();
|
||||
|
||||
lcp.MicrosoftLanguageIdentifier = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
lcp.IBMCodePageNumber = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
|
||||
return lcp;
|
||||
}
|
||||
}
|
||||
}
|
||||
73
BurnOutSharp/ExecutableType/Microsoft/Resources/Resource.cs
Normal file
73
BurnOutSharp/ExecutableType/Microsoft/Resources/Resource.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
internal class Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// The length, in bytes, of the resource structure.
|
||||
/// This length does not include any padding that aligns any subsequent version resource data on a 32-bit boundary.
|
||||
/// </summary>
|
||||
public ushort Length;
|
||||
|
||||
/// <summary>
|
||||
/// The length, in bytes, of the Value member.
|
||||
/// This value is zero if there is no Value member associated with the current version structure.
|
||||
/// </summary>
|
||||
public ushort ValueLength;
|
||||
|
||||
/// <summary>
|
||||
/// The type of data in the version resource.
|
||||
/// This member is 1 if the version resource contains text data and 0 if the version resource contains binary data.
|
||||
/// </summary>
|
||||
public ushort Type;
|
||||
|
||||
/// <summary>
|
||||
/// A Unicode string representing the key
|
||||
/// </summary>
|
||||
public string Key;
|
||||
|
||||
public static Resource Deserialize(Stream stream)
|
||||
{
|
||||
Resource r = new Resource();
|
||||
|
||||
while ((r.Length = stream.ReadUInt16()) == 0x0000);
|
||||
|
||||
r.Length = stream.ReadUInt16();
|
||||
r.ValueLength = stream.ReadUInt16();
|
||||
r.Type = stream.ReadUInt16();
|
||||
r.Key = stream.ReadString(Encoding.Unicode);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
public static Resource Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
Resource r = new Resource();
|
||||
|
||||
while ((r.Length = BitConverter.ToUInt16(content, offset)) == 0x0000)
|
||||
{
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
offset += 2;
|
||||
r.ValueLength = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
r.Type = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
|
||||
List<char> keyChars = new List<char>();
|
||||
while (BitConverter.ToUInt16(content, offset) != 0x0000)
|
||||
{
|
||||
keyChars.Add(Encoding.Unicode.GetChars(content, offset, 2)[0]); offset += 2;
|
||||
}
|
||||
offset += 2;
|
||||
|
||||
r.Key = new string(keyChars.ToArray());
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
internal class StringFileInfo : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// An array of one or more StringTable structures.
|
||||
/// Each StringTable structure's szKey member indicates the appropriate language and code page for displaying the text in that StringTable structure.
|
||||
/// </summary>
|
||||
public StringTable Children;
|
||||
|
||||
public static new StringFileInfo Deserialize(Stream stream)
|
||||
{
|
||||
StringFileInfo sfi = new StringFileInfo();
|
||||
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
if (resource.Key != "StringFileInfo")
|
||||
return null;
|
||||
|
||||
sfi.Length = resource.Length;
|
||||
sfi.ValueLength = resource.ValueLength;
|
||||
sfi.Type = resource.Type;
|
||||
sfi.Key = resource.Key;
|
||||
sfi.Children = StringTable.Deserialize(stream);
|
||||
|
||||
return sfi;
|
||||
}
|
||||
|
||||
public static new StringFileInfo Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
StringFileInfo sfi = new StringFileInfo();
|
||||
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
if (resource.Key != "StringFileInfo")
|
||||
return null;
|
||||
|
||||
sfi.Length = resource.Length;
|
||||
sfi.ValueLength = resource.ValueLength;
|
||||
sfi.Type = resource.Type;
|
||||
sfi.Key = resource.Key;
|
||||
sfi.Children = StringTable.Deserialize(content, ref offset);
|
||||
|
||||
return sfi;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
internal class StringStruct : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// Typically contains a list of languages that the application or DLL supports.
|
||||
/// </summary>
|
||||
public string Value;
|
||||
|
||||
public static new StringStruct Deserialize(Stream stream)
|
||||
{
|
||||
StringStruct s = new StringStruct();
|
||||
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
|
||||
s.Length = resource.Length;
|
||||
s.ValueLength = resource.ValueLength;
|
||||
s.Type = resource.Type;
|
||||
s.Key = resource.Key;
|
||||
stream.Seek(stream.Position % 4 == 0 ? 0 : 4 - (stream.Position % 4), SeekOrigin.Current);
|
||||
s.Value = new string(stream.ReadChars(s.ValueLength));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public static new StringStruct Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
StringStruct s = new StringStruct();
|
||||
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
|
||||
s.Length = resource.Length;
|
||||
s.ValueLength = resource.ValueLength;
|
||||
s.Type = resource.Type;
|
||||
s.Key = resource.Key;
|
||||
offset += offset % 4 == 0 ? 0 : 4 - (offset % 4);
|
||||
s.Value = Encoding.Unicode.GetString(content, offset, s.ValueLength * 2); offset += s.ValueLength * 2;
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
internal class StringTable : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// An array of one or more String structures.
|
||||
/// </summary>
|
||||
public StringStruct[] Children;
|
||||
|
||||
public static new StringTable Deserialize(Stream stream)
|
||||
{
|
||||
StringTable st = new StringTable();
|
||||
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
if (resource.Key.Length != 8)
|
||||
return null;
|
||||
|
||||
st.Length = resource.Length;
|
||||
st.ValueLength = resource.ValueLength;
|
||||
st.Type = resource.Type;
|
||||
st.Key = resource.Key;
|
||||
|
||||
// TODO: Deserialize the Value array
|
||||
stream.Seek(st.Length - 6 - (st.Key.Length * 2), SeekOrigin.Begin);
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
public static new StringTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
int originalPosition = offset;
|
||||
StringTable st = new StringTable();
|
||||
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
if (resource.Key.Length != 8)
|
||||
return null;
|
||||
|
||||
st.Length = resource.Length;
|
||||
st.ValueLength = resource.ValueLength;
|
||||
st.Type = resource.Type;
|
||||
st.Key = resource.Key;
|
||||
|
||||
var tempValue = new List<StringStruct>();
|
||||
while (offset - originalPosition < st.Length)
|
||||
{
|
||||
tempValue.Add(StringStruct.Deserialize(content, ref offset));
|
||||
}
|
||||
|
||||
st.Children = tempValue.ToArray();
|
||||
|
||||
return st;
|
||||
}
|
||||
}
|
||||
}
|
||||
56
BurnOutSharp/ExecutableType/Microsoft/Resources/Var.cs
Normal file
56
BurnOutSharp/ExecutableType/Microsoft/Resources/Var.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
internal class Var : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// An array of one or more values that are language and code page identifier pairs.
|
||||
///
|
||||
/// If you use the Var structure to list the languages your application or DLL supports instead of using multiple version resources,
|
||||
/// use the Value member to contain an array of DWORD values indicating the language and code page combinations supported by this file.
|
||||
/// The low-order word of each DWORD must contain a Microsoft language identifier, and the high-order word must contain the IBM code page number.
|
||||
/// Either high-order or low-order word can be zero, indicating that the file is language or code page independent.
|
||||
/// If the Var structure is omitted, the file will be interpreted as both language and code page independent.
|
||||
/// </summary>
|
||||
public LanguageCodePage[] Value;
|
||||
|
||||
public static new Var Deserialize(Stream stream)
|
||||
{
|
||||
Var v = new Var();
|
||||
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
if (resource.Key != "Translation")
|
||||
return null;
|
||||
|
||||
v.Length = resource.Length;
|
||||
v.ValueLength = resource.ValueLength;
|
||||
v.Type = resource.Type;
|
||||
v.Key = resource.Key;
|
||||
|
||||
// TODO: Deserialize the Value array
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public static new Var Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
Var v = new Var();
|
||||
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
if (resource.Key != "Translation")
|
||||
return null;
|
||||
|
||||
v.Length = resource.Length;
|
||||
v.ValueLength = resource.ValueLength;
|
||||
v.Type = resource.Type;
|
||||
v.Key = resource.Key;
|
||||
|
||||
// TODO: Deserialize the Value array
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
internal class VarFileInfo : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// Typically contains a list of languages that the application or DLL supports.
|
||||
/// </summary>
|
||||
public Var Children;
|
||||
|
||||
public static new VarFileInfo Deserialize(Stream stream)
|
||||
{
|
||||
VarFileInfo vfi = new VarFileInfo();
|
||||
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
if (resource.Key != "VarFileInfo")
|
||||
return null;
|
||||
|
||||
vfi.Length = resource.Length;
|
||||
vfi.ValueLength = resource.ValueLength;
|
||||
vfi.Type = resource.Type;
|
||||
vfi.Key = resource.Key;
|
||||
vfi.Children = Var.Deserialize(stream);
|
||||
|
||||
return vfi;
|
||||
}
|
||||
|
||||
public static new VarFileInfo Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
VarFileInfo vfi = new VarFileInfo();
|
||||
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
if (resource.Key != "VarFileInfo")
|
||||
return null;
|
||||
|
||||
vfi.Length = resource.Length;
|
||||
vfi.ValueLength = resource.ValueLength;
|
||||
vfi.Type = resource.Type;
|
||||
vfi.Key = resource.Key;
|
||||
vfi.Children = Var.Deserialize(content, ref offset);
|
||||
|
||||
return vfi;
|
||||
}
|
||||
}
|
||||
}
|
||||
131
BurnOutSharp/ExecutableType/Microsoft/Resources/VersionInfo.cs
Normal file
131
BurnOutSharp/ExecutableType/Microsoft/Resources/VersionInfo.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using System.IO;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
internal class VersionInfo : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// Arbitrary data associated with this VS_VERSIONINFO structure.
|
||||
/// The wValueLength member specifies the length of this member;
|
||||
/// if wValueLength is zero, this member does not exist.
|
||||
/// </summary>
|
||||
public FixedFileInfo Value;
|
||||
|
||||
/// <summary>
|
||||
/// An array of zero or one StringFileInfo structures, and zero or one VarFileInfo structures
|
||||
/// that are children of the current VS_VERSIONINFO structure.
|
||||
/// </summary>
|
||||
public StringFileInfo ChildrenStringFileInfo;
|
||||
|
||||
/// <summary>
|
||||
/// An array of zero or one StringFileInfo structures, and zero or one VarFileInfo structures
|
||||
/// that are children of the current VS_VERSIONINFO structure.
|
||||
/// </summary>
|
||||
public VarFileInfo ChildrenVarFileInfo;
|
||||
|
||||
public static new VersionInfo Deserialize(Stream stream)
|
||||
{
|
||||
long originalPosition = stream.Position;
|
||||
|
||||
VersionInfo vi = new VersionInfo();
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
if (resource.Key != "VS_VERSION_INFO")
|
||||
return null;
|
||||
|
||||
vi.Length = resource.Length;
|
||||
vi.ValueLength = resource.ValueLength;
|
||||
vi.Type = resource.Type;
|
||||
vi.Key = resource.Key;
|
||||
|
||||
if (vi.ValueLength > 0)
|
||||
vi.Value = FixedFileInfo.Deserialize(stream);
|
||||
|
||||
if (stream.Position - originalPosition > vi.Length)
|
||||
return vi;
|
||||
|
||||
long preChildOffset = stream.Position;
|
||||
Resource firstChild = Resource.Deserialize(stream);
|
||||
if (firstChild.Key == "StringFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(stream);
|
||||
}
|
||||
else if (firstChild.Key == "VarFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(stream);
|
||||
}
|
||||
|
||||
if (stream.Position - originalPosition > vi.Length)
|
||||
return vi;
|
||||
|
||||
preChildOffset = stream.Position;
|
||||
Resource secondChild = Resource.Deserialize(stream);
|
||||
if (secondChild.Key == "StringFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(stream);
|
||||
}
|
||||
else if (secondChild.Key == "VarFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(stream);
|
||||
}
|
||||
|
||||
return vi;
|
||||
}
|
||||
|
||||
public static new VersionInfo Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
int originalOffset = offset;
|
||||
|
||||
VersionInfo vi = new VersionInfo();
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
if (resource.Key != "VS_VERSION_INFO")
|
||||
return null;
|
||||
|
||||
vi.Length = resource.Length;
|
||||
vi.ValueLength = resource.ValueLength;
|
||||
vi.Type = resource.Type;
|
||||
vi.Key = resource.Key;
|
||||
|
||||
if (vi.ValueLength > 0)
|
||||
vi.Value = FixedFileInfo.Deserialize(content, ref offset);
|
||||
|
||||
if (offset - originalOffset > vi.Length)
|
||||
return vi;
|
||||
|
||||
int preChildOffset = offset;
|
||||
Resource firstChild = Resource.Deserialize(content, ref offset);
|
||||
if (firstChild.Key == "StringFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(content, ref offset);
|
||||
}
|
||||
else if (firstChild.Key == "VarFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
if (offset - originalOffset > vi.Length)
|
||||
return vi;
|
||||
|
||||
|
||||
preChildOffset = offset;
|
||||
Resource secondChild = Resource.Deserialize(content, ref offset);
|
||||
if (secondChild.Key == "StringFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(content, ref offset);
|
||||
}
|
||||
else if (secondChild.Key == "VarFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
return vi;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Tables;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Sections
|
||||
@@ -56,18 +55,15 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Sections
|
||||
return eds;
|
||||
}
|
||||
|
||||
public static ExportDataSection Deserialize(byte[] content, int offset)
|
||||
public static ExportDataSection Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var eds = new ExportDataSection();
|
||||
|
||||
unsafe
|
||||
{
|
||||
eds.ExportDirectoryTable = ExportDirectoryTable.Deserialize(content, offset); offset += Marshal.SizeOf(eds.ExportDirectoryTable);
|
||||
// eds.ExportAddressTable = ExportAddressTable.Deserialize(content, offset, count: 0); offset += Marshal.SizeOf(eds.ExportAddressTable); // TODO: Figure out where this count comes from
|
||||
// eds.NamePointerTable = ExportNamePointerTable.Deserialize(content, offset, count: 0); offset += Marshal.SizeOf(eds.NamePointerTable); // TODO: Figure out where this count comes from
|
||||
// eds.OrdinalTable = ExportOrdinalTable.Deserialize(content, offset, count: 0); offset += Marshal.SizeOf(eds.OrdinalTable); // TODO: Figure out where this count comes from
|
||||
// eds.ExportNameTable = ExportNameTable.Deserialize(stream); offset += Marshal.SizeOf(eds.ExportAddressTable); // TODO: set this table based on the NamePointerTable value
|
||||
}
|
||||
eds.ExportDirectoryTable = ExportDirectoryTable.Deserialize(content, ref offset);
|
||||
// eds.ExportAddressTable = ExportAddressTable.Deserialize(content, ref offset, count: 0); // TODO: Figure out where this count comes from
|
||||
// eds.NamePointerTable = ExportNamePointerTable.Deserialize(content, ref offset, count: 0); // TODO: Figure out where this count comes from
|
||||
// eds.OrdinalTable = ExportOrdinalTable.Deserialize(content, ref offset, count: 0); // TODO: Figure out where this count comes from
|
||||
// eds.ExportNameTable = ExportNameTable.Deserialize(content, ref offset); // TODO: set this table based on the NamePointerTable value
|
||||
|
||||
return eds;
|
||||
}
|
||||
|
||||
@@ -57,28 +57,24 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Sections
|
||||
return ids;
|
||||
}
|
||||
|
||||
public static ImportDataSection Deserialize(byte[] content, int offset, bool pe32plus, int hintCount)
|
||||
public static ImportDataSection Deserialize(byte[] content, ref int offset, bool pe32plus, int hintCount)
|
||||
{
|
||||
var ids = new ImportDataSection();
|
||||
|
||||
ids.ImportDirectoryTable = ImportDirectoryTable.Deserialize(content, offset); offset += 20 * ids.ImportDirectoryTable.Entries.Length;
|
||||
ids.ImportDirectoryTable = ImportDirectoryTable.Deserialize(content, ref offset);
|
||||
|
||||
List<ImportLookupTable> tempLookupTables = new List<ImportLookupTable>();
|
||||
while (true)
|
||||
{
|
||||
var tempLookupTable = ImportLookupTable.Deserialize(content, offset, pe32plus);
|
||||
if (tempLookupTable.EntriesPE32 != null)
|
||||
offset += 4 * tempLookupTable.EntriesPE32.Length;
|
||||
else if (tempLookupTable.EntriesPE32Plus != null)
|
||||
offset += 8 * tempLookupTable.EntriesPE32Plus.Length;
|
||||
else
|
||||
var tempLookupTable = ImportLookupTable.Deserialize(content, ref offset, pe32plus);
|
||||
if (tempLookupTable.EntriesPE32 == null && tempLookupTable.EntriesPE32Plus == null)
|
||||
break;
|
||||
|
||||
tempLookupTables.Add(tempLookupTable);
|
||||
}
|
||||
|
||||
// TODO: Update the offset, if possible
|
||||
ids.HintNameTable = HintNameTable.Deserialize(content, offset, hintCount);
|
||||
ids.HintNameTable = HintNameTable.Deserialize(content, ref offset, hintCount);
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Tables;
|
||||
|
||||
@@ -32,15 +31,12 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Sections
|
||||
return rs;
|
||||
}
|
||||
|
||||
public static ResourceSection Deserialize(byte[] content, int offset, SectionHeader[] sections)
|
||||
public static ResourceSection Deserialize(byte[] content, ref int offset, SectionHeader[] sections)
|
||||
{
|
||||
var rs = new ResourceSection();
|
||||
|
||||
unsafe
|
||||
{
|
||||
long sectionStart = offset;
|
||||
rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(content, offset, sectionStart, sections); offset += Marshal.SizeOf(rs.ResourceDirectoryTable);
|
||||
}
|
||||
long sectionStart = offset;
|
||||
rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(content, ref offset, sectionStart, sections);
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
@@ -26,14 +26,14 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
return eat;
|
||||
}
|
||||
|
||||
public static ExportAddressTable Deserialize(byte[] content, int offset, int count)
|
||||
public static ExportAddressTable Deserialize(byte[] content, ref int offset, int count)
|
||||
{
|
||||
var eat = new ExportAddressTable();
|
||||
|
||||
eat.Entries = new ExportAddressTableEntry[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
eat.Entries[i] = ExportAddressTableEntry.Deserialize(content, offset); offset += 4;
|
||||
eat.Entries[i] = ExportAddressTableEntry.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
return eat;
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
return edt;
|
||||
}
|
||||
|
||||
public static ExportDirectoryTable Deserialize(byte[] content, int offset)
|
||||
public static ExportDirectoryTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var edt = new ExportDirectoryTable();
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
return enpt;
|
||||
}
|
||||
|
||||
public static ExportNamePointerTable Deserialize(byte[] content, int offset, int count)
|
||||
public static ExportNamePointerTable Deserialize(byte[] content, ref int offset, int count)
|
||||
{
|
||||
var enpt = new ExportNamePointerTable();
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
return edt;
|
||||
}
|
||||
|
||||
public static ExportOrdinalTable Deserialize(byte[] content, int offset, int count)
|
||||
public static ExportOrdinalTable Deserialize(byte[] content, ref int offset, int count)
|
||||
{
|
||||
var edt = new ExportOrdinalTable();
|
||||
|
||||
|
||||
@@ -25,14 +25,14 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
return hnt;
|
||||
}
|
||||
|
||||
public static HintNameTable Deserialize(byte[] content, int offset, int count)
|
||||
public static HintNameTable Deserialize(byte[] content, ref int offset, int count)
|
||||
{
|
||||
var hnt = new HintNameTable();
|
||||
|
||||
hnt.Entries = new HintNameTableEntry[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
hnt.Entries[i] = HintNameTableEntry.Deserialize(content, offset);
|
||||
hnt.Entries[i] = HintNameTableEntry.Deserialize(content, ref offset);
|
||||
offset += 2 + hnt.Entries[i].Name.Length + hnt.Entries[i].Pad;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,14 +33,14 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
return iat;
|
||||
}
|
||||
|
||||
public static ImportAddressTable Deserialize(byte[] content, int offset)
|
||||
public static ImportAddressTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var iat = new ImportAddressTable();
|
||||
|
||||
List<ImportAddressTableEntry> tempEntries = new List<ImportAddressTableEntry>();
|
||||
while (true)
|
||||
{
|
||||
var entry = ImportAddressTableEntry.Deserialize(content, offset); offset += 20;
|
||||
var entry = ImportAddressTableEntry.Deserialize(content, ref offset);
|
||||
tempEntries.Add(entry);
|
||||
if (entry.IsNull())
|
||||
break;
|
||||
|
||||
@@ -33,14 +33,14 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
return idt;
|
||||
}
|
||||
|
||||
public static ImportDirectoryTable Deserialize(byte[] content, int offset)
|
||||
public static ImportDirectoryTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var idt = new ImportDirectoryTable();
|
||||
|
||||
List<ImportDirectoryTableEntry> tempEntries = new List<ImportDirectoryTableEntry>();
|
||||
while (true)
|
||||
{
|
||||
var entry = ImportDirectoryTableEntry.Deserialize(content, offset); offset += 20;
|
||||
var entry = ImportDirectoryTableEntry.Deserialize(content, ref offset);
|
||||
tempEntries.Add(entry);
|
||||
if (entry.IsNull())
|
||||
break;
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
return ilt;
|
||||
}
|
||||
|
||||
public static ImportLookupTable Deserialize(byte[] content, int offset, bool pe32plus)
|
||||
public static ImportLookupTable Deserialize(byte[] content, ref int offset, bool pe32plus)
|
||||
{
|
||||
var ilt = new ImportLookupTable();
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
@@ -17,7 +16,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
/// resource. It also defines the location and size of the resource.
|
||||
/// </summary>
|
||||
/// <remarks>http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm</remarks>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class NEResourceTable
|
||||
{
|
||||
/// <summary>
|
||||
@@ -69,22 +67,19 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
return nrt;
|
||||
}
|
||||
|
||||
public static NEResourceTable Deserialize(byte[] contents, int offset)
|
||||
public static NEResourceTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var nrt = new NEResourceTable();
|
||||
|
||||
nrt.AlignmentShiftCount = BitConverter.ToUInt16(contents, offset); offset += 2;
|
||||
nrt.AlignmentShiftCount = BitConverter.ToUInt16(content, offset); offset += 2;
|
||||
var typeInformationBlocks = new List<ResourceTypeInformationBlock>();
|
||||
while (true)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var block = ResourceTypeInformationBlock.Deserialize(contents, offset); offset += Marshal.SizeOf(block);
|
||||
if (block.TypeID == 0)
|
||||
break;
|
||||
|
||||
typeInformationBlocks.Add(block);
|
||||
}
|
||||
var block = ResourceTypeInformationBlock.Deserialize(content, ref offset);
|
||||
if (block.TypeID == 0)
|
||||
break;
|
||||
|
||||
typeInformationBlocks.Add(block);
|
||||
}
|
||||
|
||||
nrt.TypeInformationBlocks = typeInformationBlocks.ToArray();
|
||||
@@ -92,14 +87,11 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
var typeAndNameStrings = new List<NEResourceNameString>();
|
||||
while (true)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var str = NEResourceNameString.Deserialize(contents, offset); offset += Marshal.SizeOf(str);
|
||||
if (str.Length == 0)
|
||||
break;
|
||||
var str = NEResourceNameString.Deserialize(content, ref offset);
|
||||
if (str.Length == 0)
|
||||
break;
|
||||
|
||||
typeAndNameStrings.Add(str);
|
||||
}
|
||||
typeAndNameStrings.Add(str);
|
||||
}
|
||||
|
||||
nrt.TypeAndNameStrings = typeAndNameStrings.ToArray();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.Tools;
|
||||
@@ -12,7 +11,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
/// 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>
|
||||
@@ -94,7 +92,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
return rdt;
|
||||
}
|
||||
|
||||
public static ResourceDirectoryTable Deserialize(byte[] content, int offset, long sectionStart, SectionHeader[] sections)
|
||||
public static ResourceDirectoryTable Deserialize(byte[] content, ref int offset, long sectionStart, SectionHeader[] sections)
|
||||
{
|
||||
var rdt = new ResourceDirectoryTable();
|
||||
|
||||
@@ -108,13 +106,13 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
rdt.NamedEntries = new ResourceDirectoryTableEntry[rdt.NumberOfNamedEntries];
|
||||
for (int i = 0; i < rdt.NumberOfNamedEntries; i++)
|
||||
{
|
||||
rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, offset, sectionStart, sections); offset += 8;
|
||||
rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, ref offset, sectionStart, sections);
|
||||
}
|
||||
|
||||
rdt.IdEntries = new ResourceDirectoryTableEntry[rdt.NumberOfIdEntries];
|
||||
for (int i = 0; i < rdt.NumberOfIdEntries; i++)
|
||||
{
|
||||
rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, offset, sectionStart, sections); offset += 8;
|
||||
rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, ref offset, sectionStart, sections);
|
||||
}
|
||||
|
||||
return rdt;
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace BurnOutSharp.PackerType
|
||||
&& (name.Equals("Intel(R) Installation Framework", StringComparison.OrdinalIgnoreCase)
|
||||
|| name.Equals("Intel Installation Framework", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return $"Intel Installation Framework {Utilities.GetFileVersion(file)}";
|
||||
return $"Intel Installation Framework {Utilities.GetFileVersion(fileContent)}";
|
||||
}
|
||||
|
||||
name = fvinfo?.ProductName?.Trim();
|
||||
@@ -39,7 +39,7 @@ namespace BurnOutSharp.PackerType
|
||||
&& (name.Equals("Intel(R) Installation Framework", StringComparison.OrdinalIgnoreCase)
|
||||
|| name.Equals("Intel Installation Framework", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return $"Intel Installation Framework {Utilities.GetFileVersion(file)}";
|
||||
return $"Intel Installation Framework {Utilities.GetFileVersion(fileContent)}";
|
||||
}
|
||||
|
||||
// Get the sections from the executable, if possible
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace BurnOutSharp.PackerType
|
||||
{
|
||||
string version = GetVersion(file, fileContent, null);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
return $"Microsoft CAB SFX v{Utilities.GetFileVersion(file)}";
|
||||
return $"Microsoft CAB SFX v{Utilities.GetFileVersion(fileContent)}";
|
||||
|
||||
return "Microsoft CAB SFX";
|
||||
}
|
||||
@@ -46,7 +46,7 @@ namespace BurnOutSharp.PackerType
|
||||
{
|
||||
string version = GetVersion(file, fileContent, null);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
return $"Microsoft CAB SFX v{Utilities.GetFileVersion(file)}";
|
||||
return $"Microsoft CAB SFX v{Utilities.GetFileVersion(fileContent)}";
|
||||
|
||||
return "Microsoft CAB SFX";
|
||||
}
|
||||
@@ -158,7 +158,7 @@ namespace BurnOutSharp.PackerType
|
||||
// This method of version detection is suboptimal because the version is sometimes the version of the included software, not the SFX itself.
|
||||
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
|
||||
{
|
||||
string version = Utilities.GetFileVersion(file);
|
||||
string version = Utilities.GetFileVersion(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
return $"v{version}";
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace BurnOutSharp.PackerType
|
||||
return version;
|
||||
|
||||
// Then check the file version
|
||||
version = Utilities.GetFileVersion(file);
|
||||
version = Utilities.GetFileVersion(fileContent);
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
|
||||
|
||||
@@ -47,13 +47,13 @@ namespace BurnOutSharp.ProtectionType
|
||||
|
||||
string name = fvinfo?.FileDescription?.Trim();
|
||||
if (!string.IsNullOrWhiteSpace(name) && name.Contains("Registration code installer program"))
|
||||
return $"EA CdKey Registration Module {Utilities.GetFileVersion(file)}";
|
||||
return $"EA CdKey Registration Module {Utilities.GetFileVersion(fileContent)}";
|
||||
else if (!string.IsNullOrWhiteSpace(name) && name.Equals("EA DRM Helper", StringComparison.OrdinalIgnoreCase))
|
||||
return $"EA DRM Protection {Utilities.GetFileVersion(file)}";
|
||||
return $"EA DRM Protection {Utilities.GetFileVersion(fileContent)}";
|
||||
|
||||
name = fvinfo?.InternalName?.Trim();
|
||||
if (!string.IsNullOrWhiteSpace(name) && name.Equals("CDCode", StringComparison.Ordinal))
|
||||
return $"EA CdKey Registration Module {Utilities.GetFileVersion(file)}";
|
||||
return $"EA CdKey Registration Module {Utilities.GetFileVersion(fileContent)}";
|
||||
|
||||
// Get the sections from the executable, if possible
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
|
||||
@@ -28,9 +28,9 @@ namespace BurnOutSharp.ProtectionType
|
||||
|
||||
string name = fvinfo?.FileDescription?.Trim();
|
||||
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Games for Windows - LIVE Zero Day Piracy Protection", StringComparison.OrdinalIgnoreCase))
|
||||
return $"Games for Windows LIVE - Zero Day Piracy Protection Module {Utilities.GetFileVersion(file)}";
|
||||
return $"Games for Windows LIVE - Zero Day Piracy Protection Module {Utilities.GetFileVersion(fileContent)}";
|
||||
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Games for Windows", StringComparison.OrdinalIgnoreCase))
|
||||
return $"Games for Windows LIVE {Utilities.GetFileVersion(file)}";
|
||||
return $"Games for Windows LIVE {Utilities.GetFileVersion(fileContent)}";
|
||||
|
||||
// Get the sections from the executable, if possible
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
|
||||
@@ -57,17 +57,17 @@ namespace BurnOutSharp.ProtectionType
|
||||
|
||||
string name = fvinfo?.FileDescription?.Trim();
|
||||
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("DVM Library", StringComparison.OrdinalIgnoreCase))
|
||||
return $"SolidShield {Utilities.GetFileVersion(file)}";
|
||||
return $"SolidShield {Utilities.GetFileVersion(fileContent)}";
|
||||
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Solidshield Activation Library", StringComparison.OrdinalIgnoreCase))
|
||||
return $"SolidShield Core.dll {Utilities.GetFileVersion(file)}";
|
||||
return $"SolidShield Core.dll {Utilities.GetFileVersion(fileContent)}";
|
||||
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Activation Manager", StringComparison.OrdinalIgnoreCase))
|
||||
return $"SolidShield Activation Manager Module {GetFileVersion(file, fileContent, null)}";
|
||||
|
||||
name = fvinfo?.ProductName?.Trim();
|
||||
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Solidshield Activation Library", StringComparison.OrdinalIgnoreCase))
|
||||
return $"SolidShield Core.dll {Utilities.GetFileVersion(file)}";
|
||||
return $"SolidShield Core.dll {Utilities.GetFileVersion(fileContent)}";
|
||||
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Solidshield Library", StringComparison.OrdinalIgnoreCase))
|
||||
return $"SolidShield Core.dll {Utilities.GetFileVersion(file)}";
|
||||
return $"SolidShield Core.dll {Utilities.GetFileVersion(fileContent)}";
|
||||
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Activation Manager", StringComparison.OrdinalIgnoreCase))
|
||||
return $"SolidShield Activation Manager Module {GetFileVersion(file, fileContent, null)}";
|
||||
|
||||
@@ -224,7 +224,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
string companyName = Utilities.GetFileVersionInfo(file)?.CompanyName.ToLowerInvariant();
|
||||
if (!string.IsNullOrWhiteSpace(companyName) && (companyName.Contains("solidshield") || companyName.Contains("tages")))
|
||||
return Utilities.GetFileVersion(file);
|
||||
return Utilities.GetFileVersion(fileContent);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
|
||||
string name = fvinfo?.LegalCopyright?.Trim();
|
||||
if (!string.IsNullOrWhiteSpace(name) && name.Contains("Protection Technology"))
|
||||
return $"StarForce {Utilities.GetFileVersion(file)}";
|
||||
return $"StarForce {Utilities.GetFileVersion(fileContent)}";
|
||||
|
||||
// TODO: Find what fvinfo field actually maps to this
|
||||
name = fvinfo?.FileDescription?.Trim();
|
||||
@@ -155,7 +155,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
|
||||
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
|
||||
{
|
||||
return $"{Utilities.GetFileVersion(file)} ({fileContent.Skip(positions[1] + 22).TakeWhile(c => c != 0x00)})";
|
||||
return $"{Utilities.GetFileVersion(fileContent)} ({fileContent.Skip(positions[1] + 22).TakeWhile(c => c != 0x00)})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.Tools
|
||||
{
|
||||
internal static class BufferExtensions
|
||||
internal static class Extensions
|
||||
{
|
||||
// TODO: Add extensions for BitConverter.ToX(); offset += x;
|
||||
#region Byte Arrays
|
||||
|
||||
/// <summary>
|
||||
/// Find all positions of one array in another, if possible, if possible
|
||||
/// </summary>
|
||||
public static List<int> FindAllPositions(this byte[] stack, byte?[] needle, int start = 0, int end = -1)
|
||||
{
|
||||
// Get the outgoing list
|
||||
List<int> positions = new List<int>();
|
||||
|
||||
// Initialize the loop variables
|
||||
bool found = true;
|
||||
int lastPosition = start;
|
||||
var matcher = new ContentMatch(needle, end: end);
|
||||
|
||||
// Loop over and get all positions
|
||||
while (found)
|
||||
{
|
||||
matcher.Start = lastPosition;
|
||||
(found, lastPosition) = matcher.Match(stack, false);
|
||||
if (found)
|
||||
positions.Add(lastPosition);
|
||||
}
|
||||
|
||||
return positions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the first position of one array in another, if possible
|
||||
/// </summary>
|
||||
public static bool FirstPosition(this byte[] stack, byte?[] needle, out int position, int start = 0, int end = -1)
|
||||
{
|
||||
var matcher = new ContentMatch(needle, start, end);
|
||||
(bool found, int foundPosition) = matcher.Match(stack, false);
|
||||
position = foundPosition;
|
||||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the last position of one array in another, if possible
|
||||
/// </summary>
|
||||
public static bool LastPosition(this byte[] stack, byte?[] needle, out int position, int start = 0, int end = -1)
|
||||
{
|
||||
var matcher = new ContentMatch(needle, start, end);
|
||||
(bool found, int foundPosition) = matcher.Match(stack, true);
|
||||
position = foundPosition;
|
||||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See if a byte array starts with another
|
||||
/// </summary>
|
||||
public static bool StartsWith(this byte[] stack, byte?[] needle)
|
||||
{
|
||||
return stack.FirstPosition(needle, out int _, start: 0, end: 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See if a byte array ends with another
|
||||
/// </summary>
|
||||
public static bool EndsWith(this byte[] stack, byte?[] needle)
|
||||
{
|
||||
return stack.FirstPosition(needle, out int _, start: stack.Length - needle.Length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Streams
|
||||
|
||||
/// <summary>
|
||||
/// Read a byte from the stream
|
||||
/// </summary>
|
||||
@@ -109,6 +182,32 @@ namespace BurnOutSharp.Tools
|
||||
byte[] buffer = new byte[8];
|
||||
stream.Read(buffer, 0, 8);
|
||||
return BitConverter.ToUInt64(buffer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a null-terminated string from the stream
|
||||
/// </summary>
|
||||
public static string ReadString(this Stream stream) => stream.ReadString(Encoding.Default);
|
||||
|
||||
/// <summary>
|
||||
/// Read a null-terminated string from the stream
|
||||
/// </summary>
|
||||
public static string ReadString(this Stream stream, Encoding encoding)
|
||||
{
|
||||
byte[] nullTerminator = encoding.GetBytes(new char[] { '\0' });
|
||||
int charWidth = nullTerminator.Length;
|
||||
|
||||
List<byte> tempBuffer = new List<byte>();
|
||||
|
||||
byte[] buffer = new byte[charWidth];
|
||||
while (stream.Read(buffer, 0, charWidth) != 0 && buffer.SequenceEqual(nullTerminator))
|
||||
{
|
||||
tempBuffer.AddRange(buffer);
|
||||
}
|
||||
|
||||
return encoding.GetString(tempBuffer.ToArray());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Resources;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Sections;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Tables;
|
||||
using BurnOutSharp.Matching;
|
||||
@@ -180,73 +182,6 @@ namespace BurnOutSharp.Tools
|
||||
|
||||
#endregion
|
||||
|
||||
#region Byte Arrays
|
||||
|
||||
/// <summary>
|
||||
/// Find all positions of one array in another, if possible, if possible
|
||||
/// </summary>
|
||||
public static List<int> FindAllPositions(this byte[] stack, byte?[] needle, int start = 0, int end = -1)
|
||||
{
|
||||
// Get the outgoing list
|
||||
List<int> positions = new List<int>();
|
||||
|
||||
// Initialize the loop variables
|
||||
bool found = true;
|
||||
int lastPosition = start;
|
||||
var matcher = new ContentMatch(needle, end: end);
|
||||
|
||||
// Loop over and get all positions
|
||||
while (found)
|
||||
{
|
||||
matcher.Start = lastPosition;
|
||||
(found, lastPosition) = matcher.Match(stack, false);
|
||||
if (found)
|
||||
positions.Add(lastPosition);
|
||||
}
|
||||
|
||||
return positions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the first position of one array in another, if possible
|
||||
/// </summary>
|
||||
public static bool FirstPosition(this byte[] stack, byte?[] needle, out int position, int start = 0, int end = -1)
|
||||
{
|
||||
var matcher = new ContentMatch(needle, start, end);
|
||||
(bool found, int foundPosition) = matcher.Match(stack, false);
|
||||
position = foundPosition;
|
||||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the last position of one array in another, if possible
|
||||
/// </summary>
|
||||
public static bool LastPosition(this byte[] stack, byte?[] needle, out int position, int start = 0, int end = -1)
|
||||
{
|
||||
var matcher = new ContentMatch(needle, start, end);
|
||||
(bool found, int foundPosition) = matcher.Match(stack, true);
|
||||
position = foundPosition;
|
||||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See if a byte array starts with another
|
||||
/// </summary>
|
||||
public static bool StartsWith(this byte[] stack, byte?[] needle)
|
||||
{
|
||||
return stack.FirstPosition(needle, out int _, start: 0, end: 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See if a byte array ends with another
|
||||
/// </summary>
|
||||
public static bool EndsWith(this byte[] stack, byte?[] needle)
|
||||
{
|
||||
return stack.FirstPosition(needle, out int _, start: stack.Length - needle.Length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protection
|
||||
|
||||
/// <summary>
|
||||
@@ -269,6 +204,36 @@ namespace BurnOutSharp.Tools
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the file version info object related to file contents, if possible
|
||||
/// </summary>
|
||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||
/// <returns>FileVersionInfo object on success, null on error</returns>
|
||||
public static VersionInfo GetVersionInfo(byte[] fileContent)
|
||||
{
|
||||
if (fileContent == null || !fileContent.Any())
|
||||
return null;
|
||||
|
||||
// If we don't have a PE executable, just return null
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
var resourceSection = pex?.ResourceSection;
|
||||
if (resourceSection == null)
|
||||
return null;
|
||||
|
||||
var resource = FindResourceInSection(resourceSection, dataContains: "V\0S\0_\0V\0E\0R\0S\0I\0O\0N\0_\0I\0N\0F\0O\0");
|
||||
|
||||
try
|
||||
{
|
||||
int index = 0;
|
||||
return VersionInfo.Deserialize(resource.Data, ref index);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the file version as reported by the filesystem
|
||||
/// </summary>
|
||||
@@ -284,6 +249,29 @@ namespace BurnOutSharp.Tools
|
||||
else
|
||||
return fvinfo.ProductVersion.Replace(", ", ".");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the file version as reported by the filesystem
|
||||
/// </summary>
|
||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||
/// <returns>Version string, null on error</returns>
|
||||
/// TODO: Add override that takes an existing PE
|
||||
public static string GetFileVersion(byte[] fileContent)
|
||||
{
|
||||
var resourceStrings = GetVersionInfo(fileContent)?.ChildrenStringFileInfo?.Children?.Children;
|
||||
if (resourceStrings == null)
|
||||
return null;
|
||||
|
||||
var fileVersion = resourceStrings.FirstOrDefault(s => s.Key == "FileVersion");
|
||||
if (!string.IsNullOrWhiteSpace(fileVersion?.Value))
|
||||
return fileVersion.Value.Replace(", ", ".");
|
||||
|
||||
var productVersion = resourceStrings.FirstOrDefault(s => s.Key == "ProductVersion");
|
||||
if (!string.IsNullOrWhiteSpace(productVersion?.Value))
|
||||
return productVersion.Value.Replace(", ", ".");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper for GetFileVersion for use in content matching
|
||||
@@ -292,7 +280,7 @@ namespace BurnOutSharp.Tools
|
||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||
/// <param name="positions">Last matched positions in the contents</param>
|
||||
/// <returns>Version string, null on error</returns>
|
||||
public static string GetFileVersion(string file, byte[] fileContent, List<int> positions) => GetFileVersion(file);
|
||||
public static string GetFileVersion(string file, byte[] fileContent, List<int> positions) => GetFileVersion(fileContent);
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper for GetFileVersion for use in path matching
|
||||
@@ -388,7 +376,7 @@ namespace BurnOutSharp.Tools
|
||||
/// <param name="dataStart">String to use if checking for data starting with a string</param>
|
||||
/// <param name="dataContains">String to use if checking for data contains a string</param>
|
||||
/// <returns>Full encoded resource data, null on error</returns>
|
||||
private static string FindResourceInSection(ResourceSection rs, string dataStart = null, string dataContains = null)
|
||||
private static ResourceDataEntry FindResourceInSection(ResourceSection rs, string dataStart = null, string dataContains = null)
|
||||
{
|
||||
if (rs == null)
|
||||
return null;
|
||||
@@ -403,7 +391,7 @@ namespace BurnOutSharp.Tools
|
||||
/// <param name="dataStart">String to use if checking for data starting with a string</param>
|
||||
/// <param name="dataContains">String to use if checking for data contains a string</param>
|
||||
/// <returns>Full encoded resource data, null on error</returns>
|
||||
private static string FindResourceInTable(ResourceDirectoryTable rdt, string dataStart, string dataContains)
|
||||
private static ResourceDataEntry FindResourceInTable(ResourceDirectoryTable rdt, string dataStart, string dataContains)
|
||||
{
|
||||
if (rdt == null)
|
||||
return null;
|
||||
@@ -412,15 +400,15 @@ namespace BurnOutSharp.Tools
|
||||
{
|
||||
if (rdte.IsResourceDataEntry() && rdte.DataEntry != null)
|
||||
{
|
||||
if (dataStart != null && rdte.DataEntry.EncodedData.StartsWith(dataStart))
|
||||
return rdte.DataEntry.EncodedData;
|
||||
else if (dataContains != null && rdte.DataEntry.EncodedData.Contains(dataContains))
|
||||
return rdte.DataEntry.EncodedData;
|
||||
if (dataStart != null && rdte.DataEntry.DataAsUTF8String.StartsWith(dataStart))
|
||||
return rdte.DataEntry;
|
||||
else if (dataContains != null && rdte.DataEntry.DataAsUTF8String.Contains(dataContains))
|
||||
return rdte.DataEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
string manifest = FindResourceInTable(rdte.Subdirectory, dataStart, dataContains);
|
||||
if (!string.IsNullOrWhiteSpace(manifest))
|
||||
var manifest = FindResourceInTable(rdte.Subdirectory, dataStart, dataContains);
|
||||
if (manifest != null)
|
||||
return manifest;
|
||||
}
|
||||
}
|
||||
@@ -429,15 +417,15 @@ namespace BurnOutSharp.Tools
|
||||
{
|
||||
if (rdte.IsResourceDataEntry() && rdte.DataEntry != null)
|
||||
{
|
||||
if (dataStart != null && rdte.DataEntry.EncodedData.StartsWith(dataStart))
|
||||
return rdte.DataEntry.EncodedData;
|
||||
else if (dataContains != null && rdte.DataEntry.EncodedData.Contains(dataContains))
|
||||
return rdte.DataEntry.EncodedData;
|
||||
if (dataStart != null && rdte.DataEntry.DataAsUTF8String.StartsWith(dataStart))
|
||||
return rdte.DataEntry;
|
||||
else if (dataContains != null && rdte.DataEntry.DataAsUTF8String.Contains(dataContains))
|
||||
return rdte.DataEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
string manifest = FindResourceInTable(rdte.Subdirectory, dataStart, dataContains);
|
||||
if (!string.IsNullOrWhiteSpace(manifest))
|
||||
var manifest = FindResourceInTable(rdte.Subdirectory, dataStart, dataContains);
|
||||
if (manifest != null)
|
||||
return manifest;
|
||||
}
|
||||
}
|
||||
@@ -450,7 +438,7 @@ namespace BurnOutSharp.Tools
|
||||
/// </summary>
|
||||
/// <param name="rs">ResourceSection from the executable</param>
|
||||
/// <returns>Full assembly manifest, null on error</returns>
|
||||
private static string FindAssemblyManifest(ResourceSection rs) => FindResourceInSection(rs, dataStart: "<assembly");
|
||||
private static string FindAssemblyManifest(ResourceSection rs) => FindResourceInSection(rs, dataStart: "<assembly").DataAsUTF8String;
|
||||
|
||||
/// <summary>
|
||||
/// Get the assembly identity node from an embedded manifest
|
||||
|
||||
Reference in New Issue
Block a user