diff --git a/Steamless.API/PE64/NativeApi64.cs b/Steamless.API/PE64/NativeApi64.cs
new file mode 100644
index 0000000..e5dfdc8
--- /dev/null
+++ b/Steamless.API/PE64/NativeApi64.cs
@@ -0,0 +1,599 @@
+/**
+ * Steamless - Copyright (c) 2015 - 2017 atom0s [atom0s@live.com]
+ *
+ * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
+ * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/ or send a letter to
+ * Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
+ *
+ * By using Steamless, you agree to the above license and its terms.
+ *
+ * Attribution - You must give appropriate credit, provide a link to the license and indicate if changes were
+ * made. You must do so in any reasonable manner, but not in any way that suggests the licensor
+ * endorses you or your use.
+ *
+ * Non-Commercial - You may not use the material (Steamless) for commercial purposes.
+ *
+ * No-Derivatives - If you remix, transform, or build upon the material (Steamless), you may not distribute the
+ * modified material. You are, however, allowed to submit the modified works back to the original
+ * Steamless project in attempt to have it added to the original project.
+ *
+ * You may not apply legal terms or technological measures that legally restrict others
+ * from doing anything the license permits.
+ *
+ * No warranties are given.
+ */
+
+namespace Steamless.API.PE64
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ public class NativeApi64
+ {
+ ///
+ /// IMAGE_DOS_HEADER Structure
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ImageDosHeader64
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
+ public char[] e_magic;
+
+ public ushort e_cblp;
+ public ushort e_cp;
+ public ushort e_crlc;
+ public ushort e_cparhdr;
+ public ushort e_minalloc;
+ public ushort e_maxalloc;
+ public ushort e_ss;
+ public ushort e_sp;
+ public ushort e_csum;
+ public ushort e_ip;
+ public ushort e_cs;
+ public ushort e_lfarlc;
+ public ushort e_ovno;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
+ public ushort[] e_res1;
+
+ public ushort e_oemid;
+ public ushort e_oeminfo;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
+ public ushort[] e_res2;
+
+ public int e_lfanew;
+
+ ///
+ /// Gets if this structure is valid for a PE file.
+ ///
+ public bool IsValid => new string(this.e_magic) == "MZ";
+ }
+
+ ///
+ /// IMAGE_NT_HEADERS Structure
+ ///
+ [StructLayout(LayoutKind.Explicit)]
+ public struct ImageNtHeaders64
+ {
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
+ public char[] Signature;
+
+ [FieldOffset(4)]
+ public ImageFileHeader64 FileHeader;
+
+ [FieldOffset(24)]
+ public ImageOptionalHeader64 OptionalHeader;
+
+ ///
+ /// Gets if this structure is valid for a PE file.
+ ///
+ public bool IsValid => new string(this.Signature).Trim('\0') == "PE";
+ }
+
+ ///
+ /// IMAGE_FILE_HEADER Structure
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ImageFileHeader64
+ {
+ public ushort Machine;
+ public ushort NumberOfSections;
+ public uint TimeDateStamp;
+ public uint PointerToSymbolTable;
+ public uint NumberOfSymbols;
+ public ushort SizeOfOptionalHeader;
+ public ushort Characteristics;
+ }
+
+ ///
+ /// Machine Type Enumeration
+ ///
+ public enum MachineType : ushort
+ {
+ Native = 0,
+ I386 = 0x014C,
+ Itanium = 0x0200,
+ X64 = 0x8664
+ }
+
+ ///
+ /// Magic Type Enumeration
+ ///
+ public enum MagicType : ushort
+ {
+ ImageNtOptionalHdr32Magic = 0x10B,
+ ImageNtOptionalHdr64Magic = 0x20B
+ }
+
+ ///
+ /// Sub System Type Enumeration
+ ///
+ public enum SubSystemType : ushort
+ {
+ ImageSubsystemUnknown = 0,
+ ImageSubsystemNative = 1,
+ ImageSubsystemWindowsGui = 2,
+ ImageSubsystemWindowsCui = 3,
+ ImageSubsystemPosixCui = 7,
+ ImageSubsystemWindowsCeGui = 9,
+ ImageSubsystemEfiApplication = 10,
+ ImageSubsystemEfiBootServiceDriver = 11,
+ ImageSubsystemEfiRuntimeDriver = 12,
+ ImageSubsystemEfiRom = 13,
+ ImageSubsystemXbox = 14
+ }
+
+ ///
+ /// Dll Characteristics Type Enumeration
+ ///
+ public enum DllCharacteristicsType : ushort
+ {
+ Reserved0 = 0x0001,
+ Reserved1 = 0x0002,
+ Reserved2 = 0x0004,
+ Reserved3 = 0x0008,
+ ImageDllCharacteristicsDynamicBase = 0x0040,
+ ImageDllCharacteristicsForceIntegrity = 0x0080,
+ ImageDllCharacteristicsNxCompat = 0x0100,
+ ImageDllcharacteristicsNoIsolation = 0x0200,
+ ImageDllcharacteristicsNoSeh = 0x0400,
+ ImageDllcharacteristicsNoBind = 0x0800,
+ Reserved4 = 0x1000,
+ ImageDllcharacteristicsWdmDriver = 0x2000,
+ ImageDllcharacteristicsTerminalServerAware = 0x8000
+ }
+
+ ///
+ /// IMAGE_OPTIONAL_HEADER Structure
+ ///
+ [StructLayout(LayoutKind.Explicit)]
+ public struct ImageOptionalHeader64
+ {
+ [FieldOffset(0)]
+ public MagicType Magic;
+
+ [FieldOffset(2)]
+ public byte MajorLinkerVersion;
+
+ [FieldOffset(3)]
+ public byte MinorLinkerVersion;
+
+ [FieldOffset(4)]
+ public uint SizeOfCode;
+
+ [FieldOffset(8)]
+ public uint SizeOfInitializedData;
+
+ [FieldOffset(12)]
+ public uint SizeOfUninitializedData;
+
+ [FieldOffset(16)]
+ public uint AddressOfEntryPoint;
+
+ [FieldOffset(20)]
+ public uint BaseOfCode;
+
+ [FieldOffset(24)]
+ public ulong ImageBase;
+
+ [FieldOffset(32)]
+ public uint SectionAlignment;
+
+ [FieldOffset(36)]
+ public uint FileAlignment;
+
+ [FieldOffset(40)]
+ public ushort MajorOperatingSystemVersion;
+
+ [FieldOffset(42)]
+ public ushort MinorOperatingSystemVersion;
+
+ [FieldOffset(44)]
+ public ushort MajorImageVersion;
+
+ [FieldOffset(46)]
+ public ushort MinorImageVersion;
+
+ [FieldOffset(48)]
+ public ushort MajorSubsystemVersion;
+
+ [FieldOffset(50)]
+ public ushort MinorSubsystemVersion;
+
+ [FieldOffset(52)]
+ public uint Win32VersionValue;
+
+ [FieldOffset(56)]
+ public uint SizeOfImage;
+
+ [FieldOffset(60)]
+ public uint SizeOfHeaders;
+
+ [FieldOffset(64)]
+ public uint CheckSum;
+
+ [FieldOffset(68)]
+ public SubSystemType Subsystem;
+
+ [FieldOffset(70)]
+ public DllCharacteristicsType DllCharacteristics;
+
+ [FieldOffset(72)]
+ public ulong SizeOfStackReserve;
+
+ [FieldOffset(80)]
+ public ulong SizeOfStackCommit;
+
+ [FieldOffset(88)]
+ public ulong SizeOfHeapReserve;
+
+ [FieldOffset(96)]
+ public ulong SizeOfHeapCommit;
+
+ [FieldOffset(104)]
+ public uint LoaderFlags;
+
+ [FieldOffset(108)]
+ public uint NumberOfRvaAndSizes;
+
+ [FieldOffset(112)]
+ public ImageDataDirectory64 ExportTable;
+
+ [FieldOffset(120)]
+ public ImageDataDirectory64 ImportTable;
+
+ [FieldOffset(128)]
+ public ImageDataDirectory64 ResourceTable;
+
+ [FieldOffset(136)]
+ public ImageDataDirectory64 ExceptionTable;
+
+ [FieldOffset(144)]
+ public ImageDataDirectory64 CertificateTable;
+
+ [FieldOffset(152)]
+ public ImageDataDirectory64 BaseRelocationTable;
+
+ [FieldOffset(160)]
+ public ImageDataDirectory64 Debug;
+
+ [FieldOffset(168)]
+ public ImageDataDirectory64 Architecture;
+
+ [FieldOffset(176)]
+ public ImageDataDirectory64 GlobalPtr;
+
+ [FieldOffset(184)]
+ public ImageDataDirectory64 TLSTable;
+
+ [FieldOffset(192)]
+ public ImageDataDirectory64 LoadConfigTable;
+
+ [FieldOffset(200)]
+ public ImageDataDirectory64 BoundImport;
+
+ [FieldOffset(208)]
+ public ImageDataDirectory64 IAT;
+
+ [FieldOffset(216)]
+ public ImageDataDirectory64 DelayImportDescriptor;
+
+ [FieldOffset(224)]
+ public ImageDataDirectory64 CLRRuntimeHeader;
+
+ [FieldOffset(232)]
+ public ImageDataDirectory64 Reserved;
+ }
+
+ ///
+ /// IMAGE_DATA_DIRECTORY Structure
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ImageDataDirectory64
+ {
+ public uint VirtualAddress;
+ public uint Size;
+ }
+
+ ///
+ /// IMAGE_SECTION_HEADER Structure
+ ///
+ [StructLayout(LayoutKind.Explicit)]
+ public struct ImageSectionHeader64
+ {
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public char[] Name;
+
+ [FieldOffset(8)]
+ public uint VirtualSize;
+
+ [FieldOffset(12)]
+ public uint VirtualAddress;
+
+ [FieldOffset(16)]
+ public uint SizeOfRawData;
+
+ [FieldOffset(20)]
+ public uint PointerToRawData;
+
+ [FieldOffset(24)]
+ public uint PointerToRelocations;
+
+ [FieldOffset(28)]
+ public uint PointerToLinenumbers;
+
+ [FieldOffset(32)]
+ public ushort NumberOfRelocations;
+
+ [FieldOffset(34)]
+ public ushort NumberOfLinenumbers;
+
+ [FieldOffset(36)]
+ public DataSectionFlags Characteristics;
+
+ ///
+ /// Gets the section name of this current section object.
+ ///
+ public string SectionName => new string(this.Name).Trim('\0');
+
+ ///
+ /// Gets if this structure is valid for a PE file.
+ ///
+ public bool IsValid => this.SizeOfRawData != 0 && this.PointerToRawData != 0;
+ }
+
+ ///
+ /// Data Section Flags Enumeration
+ ///
+ [Flags]
+ public enum DataSectionFlags : uint
+ {
+ ///
+ /// Reserved for future use.
+ ///
+ TypeReg = 0x00000000,
+
+ ///
+ /// Reserved for future use.
+ ///
+ TypeDsect = 0x00000001,
+
+ ///
+ /// Reserved for future use.
+ ///
+ TypeNoLoad = 0x00000002,
+
+ ///
+ /// Reserved for future use.
+ ///
+ TypeGroup = 0x00000004,
+
+ ///
+ /// The section should not be padded to the next boundary. This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES. This is valid only for object files.
+ ///
+ TypeNoPadded = 0x00000008,
+
+ ///
+ /// Reserved for future use.
+ ///
+ TypeCopy = 0x00000010,
+
+ ///
+ /// The section contains executable code.
+ ///
+ ContentCode = 0x00000020,
+
+ ///
+ /// The section contains initialized data.
+ ///
+ ContentInitializedData = 0x00000040,
+
+ ///
+ /// The section contains uninitialized data.
+ ///
+ ContentUninitializedData = 0x00000080,
+
+ ///
+ /// Reserved for future use.
+ ///
+ LinkOther = 0x00000100,
+
+ ///
+ /// The section contains comments or other information. The .drectve section has this type. This is valid for object files only.
+ ///
+ LinkInfo = 0x00000200,
+
+ ///
+ /// Reserved for future use.
+ ///
+ TypeOver = 0x00000400,
+
+ ///
+ /// The section will not become part of the image. This is valid only for object files.
+ ///
+ LinkRemove = 0x00000800,
+
+ ///
+ /// The section contains COMDAT data. For more information, see section 5.5.6, COMDAT Sections (Object Only). This is valid only for object files.
+ ///
+ LinkComDat = 0x00001000,
+
+ ///
+ /// Reset speculative exceptions handling bits in the TLB entries for this section.
+ ///
+ NoDeferSpecExceptions = 0x00004000,
+
+ ///
+ /// The section contains data referenced through the global pointer (GP).
+ ///
+ RelativeGp = 0x00008000,
+
+ ///
+ /// Reserved for future use.
+ ///
+ MemPurgeable = 0x00020000,
+
+ ///
+ /// Reserved for future use.
+ ///
+ Memory16Bit = 0x00020000,
+
+ ///
+ /// Reserved for future use.
+ ///
+ MemoryLocked = 0x00040000,
+
+ ///
+ /// Reserved for future use.
+ ///
+ MemoryPreload = 0x00080000,
+
+ ///
+ /// Align data on a 1-byte boundary. Valid only for object files.
+ ///
+ Align1Bytes = 0x00100000,
+
+ ///
+ /// Align data on a 2-byte boundary. Valid only for object files.
+ ///
+ Align2Bytes = 0x00200000,
+
+ ///
+ /// Align data on a 4-byte boundary. Valid only for object files.
+ ///
+ Align4Bytes = 0x00300000,
+
+ ///
+ /// Align data on an 8-byte boundary. Valid only for object files.
+ ///
+ Align8Bytes = 0x00400000,
+
+ ///
+ /// Align data on a 16-byte boundary. Valid only for object files.
+ ///
+ Align16Bytes = 0x00500000,
+
+ ///
+ /// Align data on a 32-byte boundary. Valid only for object files.
+ ///
+ Align32Bytes = 0x00600000,
+
+ ///
+ /// Align data on a 64-byte boundary. Valid only for object files.
+ ///
+ Align64Bytes = 0x00700000,
+
+ ///
+ /// Align data on a 128-byte boundary. Valid only for object files.
+ ///
+ Align128Bytes = 0x00800000,
+
+ ///
+ /// Align data on a 256-byte boundary. Valid only for object files.
+ ///
+ Align256Bytes = 0x00900000,
+
+ ///
+ /// Align data on a 512-byte boundary. Valid only for object files.
+ ///
+ Align512Bytes = 0x00A00000,
+
+ ///
+ /// Align data on a 1024-byte boundary. Valid only for object files.
+ ///
+ Align1024Bytes = 0x00B00000,
+
+ ///
+ /// Align data on a 2048-byte boundary. Valid only for object files.
+ ///
+ Align2048Bytes = 0x00C00000,
+
+ ///
+ /// Align data on a 4096-byte boundary. Valid only for object files.
+ ///
+ Align4096Bytes = 0x00D00000,
+
+ ///
+ /// Align data on an 8192-byte boundary. Valid only for object files.
+ ///
+ Align8192Bytes = 0x00E00000,
+
+ ///
+ /// The section contains extended relocations.
+ ///
+ LinkExtendedRelocationOverflow = 0x01000000,
+
+ ///
+ /// The section can be discarded as needed.
+ ///
+ MemoryDiscardable = 0x02000000,
+
+ ///
+ /// The section cannot be cached.
+ ///
+ MemoryNotCached = 0x04000000,
+
+ ///
+ /// The section is not pageable.
+ ///
+ MemoryNotPaged = 0x08000000,
+
+ ///
+ /// The section can be shared in memory.
+ ///
+ MemoryShared = 0x10000000,
+
+ ///
+ /// The section can be executed as code.
+ ///
+ MemoryExecute = 0x20000000,
+
+ ///
+ /// The section can be read.
+ ///
+ MemoryRead = 0x40000000,
+
+ ///
+ /// The section can be written to.
+ ///
+ MemoryWrite = 0x80000000
+ }
+
+ ///
+ /// IMAGE_TLS_DIRECTORY Structure
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ImageTlsDirectory64
+ {
+ public ulong StartAddressOfRawData;
+ public ulong EndAddressOfRawData;
+ public ulong AddressOfIndex;
+ public ulong AddressOfCallBacks;
+ public uint SizeOfZeroFill;
+ public uint Characteristics;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Steamless.API/PE64/Pe64File.cs b/Steamless.API/PE64/Pe64File.cs
new file mode 100644
index 0000000..f2a096d
--- /dev/null
+++ b/Steamless.API/PE64/Pe64File.cs
@@ -0,0 +1,421 @@
+/**
+ * Steamless - Copyright (c) 2015 - 2017 atom0s [atom0s@live.com]
+ *
+ * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
+ * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/ or send a letter to
+ * Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
+ *
+ * By using Steamless, you agree to the above license and its terms.
+ *
+ * Attribution - You must give appropriate credit, provide a link to the license and indicate if changes were
+ * made. You must do so in any reasonable manner, but not in any way that suggests the licensor
+ * endorses you or your use.
+ *
+ * Non-Commercial - You may not use the material (Steamless) for commercial purposes.
+ *
+ * No-Derivatives - If you remix, transform, or build upon the material (Steamless), you may not distribute the
+ * modified material. You are, however, allowed to submit the modified works back to the original
+ * Steamless project in attempt to have it added to the original project.
+ *
+ * You may not apply legal terms or technological measures that legally restrict others
+ * from doing anything the license permits.
+ *
+ * No warranties are given.
+ */
+
+namespace Steamless.API.PE64
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// Portable Executable (64bit) Class
+ ///
+ public class Pe64File
+ {
+ ///
+ /// Default Constructor
+ ///
+ public Pe64File()
+ {
+ }
+
+ ///
+ /// Overloaded Constructor
+ ///
+ ///
+ public Pe64File(string file)
+ {
+ this.FilePath = file;
+ }
+
+ ///
+ /// Parses a Win64 PE file.
+ ///
+ ///
+ ///
+ public bool Parse(string file = null)
+ {
+ // Prepare the class variables..
+ if (file != null)
+ this.FilePath = file;
+
+ this.FileData = null;
+ this.DosHeader = new NativeApi64.ImageDosHeader64();
+ this.NtHeaders = new NativeApi64.ImageNtHeaders64();
+ this.DosStubSize = 0;
+ this.DosStubOffset = 0;
+ this.DosStubData = null;
+ this.Sections = new List();
+ this.SectionData = new List();
+ this.TlsDirectory = new NativeApi64.ImageTlsDirectory64();
+ this.TlsCallbacks = new List();
+
+ // Ensure a file path has been set..
+ if (string.IsNullOrEmpty(this.FilePath) || !File.Exists(this.FilePath))
+ return false;
+
+ // Read the file data..
+ this.FileData = File.ReadAllBytes(this.FilePath);
+
+ // Ensure we have valid data by the overall length..
+ if (this.FileData.Length < (Marshal.SizeOf(typeof(NativeApi64.ImageDosHeader64)) + Marshal.SizeOf(typeof(NativeApi64.ImageNtHeaders64))))
+ return false;
+
+ // Read the file headers..
+ this.DosHeader = Pe64Helpers.GetStructure(this.FileData);
+ this.NtHeaders = Pe64Helpers.GetStructure(this.FileData, this.DosHeader.e_lfanew);
+
+ // Validate the headers..
+ if (!this.DosHeader.IsValid || !this.NtHeaders.IsValid)
+ return false;
+
+ // Read and store the dos header if it exists..
+ this.DosStubSize = (uint)(this.DosHeader.e_lfanew - Marshal.SizeOf(typeof(NativeApi64.ImageDosHeader64)));
+ if (this.DosStubSize > 0)
+ {
+ this.DosStubOffset = (uint)Marshal.SizeOf(typeof(NativeApi64.ImageDosHeader64));
+ this.DosStubData = new byte[this.DosStubSize];
+ Array.Copy(this.FileData, (int)this.DosStubOffset, this.DosStubData, 0, (int)this.DosStubSize);
+ }
+
+ // Read the file sections..
+ for (var x = 0; x < this.NtHeaders.FileHeader.NumberOfSections; x++)
+ {
+ var section = Pe64Helpers.GetSection(this.FileData, x, this.DosHeader, this.NtHeaders);
+ this.Sections.Add(section);
+
+ // Get the sections data..
+ var sectionData = new byte[this.GetAlignment(section.SizeOfRawData, this.NtHeaders.OptionalHeader.FileAlignment)];
+ Array.Copy(this.FileData, section.PointerToRawData, sectionData, 0, section.SizeOfRawData);
+ this.SectionData.Add(sectionData);
+ }
+
+ try
+ {
+ // Obtain the file overlay if one exists..
+ var lastSection = this.Sections.Last();
+ var fileSize = lastSection.SizeOfRawData + lastSection.PointerToRawData;
+ if (fileSize < this.FileData.Length)
+ {
+ this.OverlayData = new byte[this.FileData.Length - fileSize];
+ Array.Copy(this.FileData, fileSize, this.OverlayData, 0, this.FileData.Length - fileSize);
+ }
+ }
+ catch
+ {
+ return false;
+ }
+
+ // Read the files Tls information if available..
+ if (this.NtHeaders.OptionalHeader.TLSTable.VirtualAddress != 0)
+ {
+ // Get the file offset to the Tls data..
+ var tls = this.NtHeaders.OptionalHeader.TLSTable;
+ var addr = this.GetFileOffsetFromRva(tls.VirtualAddress);
+
+ // Read the Tls directory..
+ this.TlsDirectory = Pe64Helpers.GetStructure(this.FileData, (int)addr);
+
+ // Read the Tls callbacks..
+ addr = this.GetRvaFromVa(this.TlsDirectory.AddressOfCallBacks);
+ addr = this.GetFileOffsetFromRva(addr);
+
+ // Loop until we hit a null pointer..
+ var count = 0;
+ while (true)
+ {
+ var callback = BitConverter.ToUInt64(this.FileData, (int)addr + (count * 4));
+ if (callback == 0)
+ break;
+
+ this.TlsCallbacks.Add(callback);
+ count++;
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// Determines if the current file is 64bit.
+ ///
+ ///
+ public bool IsFile64Bit()
+ {
+ return (this.NtHeaders.FileHeader.Machine & (uint)NativeApi64.MachineType.X64) == (uint)NativeApi64.MachineType.X64;
+ }
+
+ ///
+ /// Determines if the file has a section containing the given name.
+ ///
+ ///
+ ///
+ public bool HasSection(string name)
+ {
+ return this.Sections.Any(s => string.Compare(s.SectionName, name, StringComparison.InvariantCultureIgnoreCase) == 0);
+ }
+
+ ///
+ /// Obtains a section by its name.
+ ///
+ ///
+ ///
+ public NativeApi64.ImageSectionHeader64 GetSection(string name)
+ {
+ return this.Sections.FirstOrDefault(s => string.Compare(s.SectionName, name, StringComparison.InvariantCultureIgnoreCase) == 0);
+ }
+
+ ///
+ /// Obtains the owner section of the given rva.
+ ///
+ ///
+ ///
+ public NativeApi64.ImageSectionHeader64 GetOwnerSection(uint rva)
+ {
+ foreach (var s in this.Sections)
+ {
+ var size = s.VirtualSize;
+ if (size == 0)
+ size = s.SizeOfRawData;
+
+ if ((rva >= s.VirtualAddress) && (rva < s.VirtualAddress + size))
+ return s;
+ }
+
+ return default(NativeApi64.ImageSectionHeader64);
+ }
+
+ ///
+ /// Obtains the owner section of the given rva.
+ ///
+ ///
+ ///
+ public NativeApi64.ImageSectionHeader64 GetOwnerSection(ulong rva)
+ {
+ foreach (var s in this.Sections)
+ {
+ var size = s.VirtualSize;
+ if (size == 0)
+ size = s.SizeOfRawData;
+
+ if ((rva >= s.VirtualAddress) && (rva < s.VirtualAddress + size))
+ return s;
+ }
+
+ return default(NativeApi64.ImageSectionHeader64);
+ }
+
+ ///
+ /// Obtains a sections data by its index.
+ ///
+ ///
+ ///
+ public byte[] GetSectionData(int index)
+ {
+ if (index < 0 || index > this.Sections.Count)
+ return null;
+
+ return this.SectionData[index];
+ }
+
+ ///
+ /// Obtains a sections data by its name.
+ ///
+ ///
+ ///
+ public byte[] GetSectionData(string name)
+ {
+ for (var x = 0; x < this.Sections.Count; x++)
+ {
+ if (string.Compare(this.Sections[x].SectionName, name, StringComparison.InvariantCultureIgnoreCase) == 0)
+ return this.SectionData[x];
+ }
+
+ return null;
+ }
+
+ ///
+ /// Gets a sections index by its name.
+ ///
+ ///
+ ///
+ public int GetSectionIndex(string name)
+ {
+ for (var x = 0; x < this.Sections.Count; x++)
+ {
+ if (string.Compare(this.Sections[x].SectionName, name, StringComparison.InvariantCultureIgnoreCase) == 0)
+ return x;
+ }
+
+ return -1;
+ }
+
+ ///
+ /// Gets a sections index by its name.
+ ///
+ ///
+ ///
+ public int GetSectionIndex(NativeApi64.ImageSectionHeader64 section)
+ {
+ return this.Sections.IndexOf(section);
+ }
+
+ ///
+ /// Removes a section from the files section list.
+ ///
+ ///
+ ///
+ public bool RemoveSection(NativeApi64.ImageSectionHeader64 section)
+ {
+ var index = this.Sections.IndexOf(section);
+ if (index == -1)
+ return false;
+
+ this.Sections.RemoveAt(index);
+ this.SectionData.RemoveAt(index);
+
+ return true;
+ }
+
+ ///
+ /// Rebuilds the sections by aligning them as needed. Updates the Nt headers to
+ /// correct the new SizeOfImage after alignment is completed.
+ ///
+ public void RebuildSections()
+ {
+ for (var x = 0; x < this.Sections.Count; x++)
+ {
+ // Obtain the current section and realign the data..
+ var section = this.Sections[x];
+ section.VirtualAddress = (uint)this.GetAlignment(section.VirtualAddress, this.NtHeaders.OptionalHeader.SectionAlignment);
+ section.VirtualSize = (uint)this.GetAlignment(section.VirtualSize, this.NtHeaders.OptionalHeader.SectionAlignment);
+ section.PointerToRawData = (uint)this.GetAlignment(section.PointerToRawData, this.NtHeaders.OptionalHeader.FileAlignment);
+ section.SizeOfRawData = (uint)this.GetAlignment(section.SizeOfRawData, this.NtHeaders.OptionalHeader.FileAlignment);
+
+ // Store the sections updates..
+ this.Sections[x] = section;
+ }
+
+ // Update the size of the image..
+ var ntHeaders = this.NtHeaders;
+ ntHeaders.OptionalHeader.SizeOfImage = this.Sections.Last().VirtualAddress + this.Sections.Last().VirtualSize;
+ this.NtHeaders = ntHeaders;
+ }
+
+ ///
+ /// Obtains the relative virtual address from the given virtual address.
+ ///
+ ///
+ ///
+ public ulong GetRvaFromVa(ulong va)
+ {
+ return va - this.NtHeaders.OptionalHeader.ImageBase;
+ }
+
+ ///
+ /// Obtains the file offset from the given relative virtual address.
+ ///
+ ///
+ ///
+ public ulong GetFileOffsetFromRva(ulong rva)
+ {
+ var section = this.GetOwnerSection(rva);
+ return (rva - (section.VirtualAddress - section.PointerToRawData));
+ }
+
+ ///
+ /// Aligns the value based on the given alignment.
+ ///
+ ///
+ ///
+ ///
+ public ulong GetAlignment(ulong val, ulong align)
+ {
+ return (((val + align - 1) / align) * align);
+ }
+
+ ///
+ /// Gets or sets the path to the file being processed.
+ ///
+ public string FilePath { get; set; }
+
+ ///
+ /// Gets or sets the raw file data read from disk.
+ ///
+ public byte[] FileData { get; set; }
+
+ ///
+ /// Gets or sets the dos header of the file.
+ ///
+ public NativeApi64.ImageDosHeader64 DosHeader { get; set; }
+
+ ///
+ /// Gets or sets the NT headers of the file.
+ ///
+ public NativeApi64.ImageNtHeaders64 NtHeaders { get; set; }
+
+ ///
+ /// Gets or sets the optional dos stub size.
+ ///
+ public ulong DosStubSize { get; set; }
+
+ ///
+ /// Gets or sets the optional dos stub offset.
+ ///
+ public ulong DosStubOffset { get; set; }
+
+ ///
+ /// Gets or sets the optional dos stub data.
+ ///
+ public byte[] DosStubData { get; set; }
+
+ ///
+ /// Gets or sets the sections of the file.
+ ///
+ public List Sections;
+
+ ///
+ /// Gets or sets the section data of the file.
+ ///
+ public List SectionData;
+
+ ///
+ /// Gets or sets the overlay data of the file.
+ ///
+ public byte[] OverlayData;
+
+ ///
+ /// Gets or sets the Tls directory of the file.
+ ///
+ public NativeApi64.ImageTlsDirectory64 TlsDirectory { get; set; }
+
+ ///
+ /// Gets or sets a list of Tls callbacks of the file.
+ ///
+ public List TlsCallbacks { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Steamless.API/PE64/Pe64Helpers.cs b/Steamless.API/PE64/Pe64Helpers.cs
new file mode 100644
index 0000000..317aa1a
--- /dev/null
+++ b/Steamless.API/PE64/Pe64Helpers.cs
@@ -0,0 +1,128 @@
+/**
+ * Steamless - Copyright (c) 2015 - 2017 atom0s [atom0s@live.com]
+ *
+ * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
+ * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/ or send a letter to
+ * Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
+ *
+ * By using Steamless, you agree to the above license and its terms.
+ *
+ * Attribution - You must give appropriate credit, provide a link to the license and indicate if changes were
+ * made. You must do so in any reasonable manner, but not in any way that suggests the licensor
+ * endorses you or your use.
+ *
+ * Non-Commercial - You may not use the material (Steamless) for commercial purposes.
+ *
+ * No-Derivatives - If you remix, transform, or build upon the material (Steamless), you may not distribute the
+ * modified material. You are, however, allowed to submit the modified works back to the original
+ * Steamless project in attempt to have it added to the original project.
+ *
+ * You may not apply legal terms or technological measures that legally restrict others
+ * from doing anything the license permits.
+ *
+ * No warranties are given.
+ */
+
+namespace Steamless.API.PE64
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Runtime.InteropServices;
+
+ public class Pe64Helpers
+ {
+ ///
+ /// Converts a byte array to the given structure type.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static T GetStructure(byte[] data, int offset = 0)
+ {
+ var ptr = Marshal.AllocHGlobal(data.Length);
+ Marshal.Copy(data, offset, ptr, data.Length - offset);
+ var obj = (T)Marshal.PtrToStructure(ptr, typeof(T));
+ Marshal.FreeHGlobal(ptr);
+
+ return obj;
+ }
+
+ ///
+ /// Converts the given object back to a byte array.
+ ///
+ ///
+ ///
+ ///
+ public static byte[] GetStructureBytes(T obj)
+ {
+ var size = Marshal.SizeOf(obj);
+ var data = new byte[size];
+ var ptr = Marshal.AllocHGlobal(size);
+ Marshal.StructureToPtr(obj, ptr, true);
+ Marshal.Copy(ptr, data, 0, size);
+ Marshal.FreeHGlobal(ptr);
+ return data;
+ }
+
+ ///
+ /// Obtains a section from the given file information.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static NativeApi64.ImageSectionHeader64 GetSection(byte[] rawData, int index, NativeApi64.ImageDosHeader64 dosHeader, NativeApi64.ImageNtHeaders64 ntHeaders)
+ {
+ var sectionSize = Marshal.SizeOf(typeof(NativeApi64.ImageSectionHeader64));
+ var optionalHeaderOffset = Marshal.OffsetOf(typeof(NativeApi64.ImageNtHeaders64), "OptionalHeader").ToInt64();
+ var dataOffset = dosHeader.e_lfanew + optionalHeaderOffset + ntHeaders.FileHeader.SizeOfOptionalHeader;
+
+ return GetStructure(rawData, (int)dataOffset + (index * sectionSize));
+ }
+
+ ///
+ /// Scans the given data for the given pattern.
+ ///
+ /// Notes:
+ /// Patterns are assumed to be 2 byte hex values with spaces.
+ /// Wildcards are represented by ??.
+ ///
+ ///
+ ///
+ ///
+ public static uint FindPattern(byte[] data, string pattern)
+ {
+ try
+ {
+ // Trim the pattern from extra whitespace..
+ var trimPattern = pattern.Replace(" ", "").Trim();
+
+ // Convert the pattern to a byte array..
+ var patternMask = new List();
+ var patternData = Enumerable.Range(0, trimPattern.Length).Where(x => x % 2 == 0)
+ .Select(x =>
+ {
+ var bt = trimPattern.Substring(x, 2);
+ patternMask.Add(!bt.Contains('?'));
+ return bt.Contains('?') ? (byte)0 : Convert.ToByte(bt, 16);
+ }).ToArray();
+
+ // Scan the given data for our pattern..
+ for (var x = 0; x < data.Length; x++)
+ {
+ if (!patternData.Where((t, y) => patternMask[y] && t != data[x + y]).Any())
+ return (uint)x;
+ }
+
+ return 0;
+ }
+ catch
+ {
+ return 0;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Steamless.API/Properties/AssemblyInfo.cs b/Steamless.API/Properties/AssemblyInfo.cs
index d9a4d96..d32b314 100644
--- a/Steamless.API/Properties/AssemblyInfo.cs
+++ b/Steamless.API/Properties/AssemblyInfo.cs
@@ -36,5 +36,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("56c95629-3b34-47fe-b988-04274409294f")]
-[assembly: AssemblyVersion("1.0.0.1")]
-[assembly: AssemblyFileVersion("1.0.0.1")]
\ No newline at end of file
+[assembly: AssemblyVersion("1.0.0.2")]
+[assembly: AssemblyFileVersion("1.0.0.2")]
\ No newline at end of file
diff --git a/Steamless.API/Steamless.API.csproj b/Steamless.API/Steamless.API.csproj
index 3f8fe1a..9da2089 100644
--- a/Steamless.API/Steamless.API.csproj
+++ b/Steamless.API/Steamless.API.csproj
@@ -45,6 +45,9 @@
+
+
+
@@ -54,9 +57,7 @@
-
-
-
+