Added support for PE and COFF.

This commit is contained in:
2017-10-17 17:33:46 +01:00
parent e305f78f5f
commit 952b61d1f8
16 changed files with 2228 additions and 3 deletions

View File

@@ -9,7 +9,9 @@ It is also accompanied by a command line application as an example of usage.
Supported executable formats Supported executable formats
============================ ============================
* Atari ST executable * Atari ST executable
* MZ (aka DOS relocatable executable) * Common Object File Format (COFF)
* NE (Microsoft New Executable)
* LE (Microsoft Linear Executable) * LE (Microsoft Linear Executable)
* LX (IBM Linear eXecutable) * LX (IBM Linear eXecutable)
* MZ (aka DOS relocatable executable)
* NE (Microsoft New Executable)
* PE (Microsoft Portable Executable)

View File

@@ -53,8 +53,10 @@ namespace exeinfo
NE neExe = new NE(exeFs); NE neExe = new NE(exeFs);
AtariST stExe = new AtariST(exeFs); AtariST stExe = new AtariST(exeFs);
LX lxExe = new LX(exeFs); LX lxExe = new LX(exeFs);
COFF coffExe = new COFF(exeFs);
PE peExe = new PE(exeFs);
if (mzExe.IsMZ) if (mzExe.IsMZ)
{ {
recognized = true; recognized = true;
Console.Write(mzExe.GetInfo()); Console.Write(mzExe.GetInfo());
@@ -124,6 +126,18 @@ namespace exeinfo
Console.Write(lxExe.GetInfo()); Console.Write(lxExe.GetInfo());
} }
if (coffExe.IsCOFF)
{
recognized = true;
Console.Write(coffExe.GetInfo());
}
if (peExe.IsPE)
{
recognized = true;
Console.Write(peExe.GetInfo());
}
if (!recognized) if (!recognized)
Console.WriteLine("Executable format not recognized"); Console.WriteLine("Executable format not recognized");
} }

152
libexeinfo/COFF/COFF.cs Normal file
View File

@@ -0,0 +1,152 @@
//
// COFF.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace libexeinfo
{
/// <summary>
/// Represents a Common Object File Format
/// </summary>
public partial class COFF
{
/// <summary>
/// The <see cref="FileStream"/> that contains the executable represented by this instance
/// </summary>
public readonly FileStream BaseStream;
/// <summary>
/// Header for this executable
/// </summary>
public readonly COFFHeader Header;
/// <summary>
/// If true this instance correctly represents a Common Object File Format
/// </summary>
public readonly bool IsCOFF;
public readonly bool IsBigEndian;
/// <summary>
/// Initializes a new instance of the <see cref="T:libexeinfo.COFF"/> class.
/// </summary>
/// <param name="path">Executable path.</param>
public COFF(string path)
{
byte[] buffer = new byte[Marshal.SizeOf(typeof(COFFHeader))];
BaseStream = File.Open(path, FileMode.Open, FileAccess.Read);
BaseStream.Position = 0;
BaseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
Header = (COFFHeader)Marshal.PtrToStructure(hdrPtr, typeof(COFFHeader));
Marshal.FreeHGlobal(hdrPtr);
IsCOFF = Header.optionalHeader.magic == STMAGIC || Header.optionalHeader.magic == OMAGIC || Header.optionalHeader.magic == JMAGIC ||
Header.optionalHeader.magic == DMAGIC || Header.optionalHeader.magic == ZMAGIC || Header.optionalHeader.magic == SHMAGIC;
IsBigEndian = false;
if(!IsCOFF)
{
Header = SwapHeader(Header);
IsCOFF = Header.optionalHeader.magic == STMAGIC || Header.optionalHeader.magic == OMAGIC || Header.optionalHeader.magic == JMAGIC ||
Header.optionalHeader.magic == DMAGIC || Header.optionalHeader.magic == ZMAGIC || Header.optionalHeader.magic == SHMAGIC;
IsBigEndian = !IsCOFF;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="T:libexeinfo.COFF"/> class.
/// </summary>
/// <param name="stream">Stream containing the executable.</param>
public COFF(FileStream stream)
{
byte[] buffer = new byte[Marshal.SizeOf(typeof(COFFHeader))];
BaseStream = stream;
BaseStream.Position = 0;
BaseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
Header = (COFFHeader)Marshal.PtrToStructure(hdrPtr, typeof(COFFHeader));
Marshal.FreeHGlobal(hdrPtr);
IsCOFF = Header.optionalHeader.magic == STMAGIC || Header.optionalHeader.magic == OMAGIC || Header.optionalHeader.magic == JMAGIC ||
Header.optionalHeader.magic == DMAGIC || Header.optionalHeader.magic == ZMAGIC || Header.optionalHeader.magic == SHMAGIC;
IsBigEndian = false;
if (!IsCOFF)
{
Header = SwapHeader(Header);
IsCOFF = Header.optionalHeader.magic == STMAGIC || Header.optionalHeader.magic == OMAGIC || Header.optionalHeader.magic == JMAGIC ||
Header.optionalHeader.magic == DMAGIC || Header.optionalHeader.magic == ZMAGIC || Header.optionalHeader.magic == SHMAGIC;
IsBigEndian = !IsCOFF;
}
}
/// <summary>
/// Identifies if the specified executable is a Common Object File Format
/// </summary>
/// <returns><c>true</c> if the specified executable is a Common Object File Format, <c>false</c> otherwise.</returns>
/// <param name="path">Executable path.</param>
public static bool Identify(string path)
{
FileStream exeFs = File.Open(path, FileMode.Open, FileAccess.Read);
return Identify(exeFs);
}
/// <summary>
/// Identifies if the specified executable is a Common Object File Format
/// </summary>
/// <returns><c>true</c> if the specified executable is a Common Object File Format, <c>false</c> otherwise.</returns>
/// <param name="stream">Stream containing the executable.</param>
public static bool Identify(FileStream stream)
{
byte[] buffer = new byte[Marshal.SizeOf(typeof(COFFHeader))];
stream.Position = 0;
stream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
COFFHeader COFFHdr = (COFFHeader)Marshal.PtrToStructure(hdrPtr, typeof(COFFHeader));
Marshal.FreeHGlobal(hdrPtr);
if (COFFHdr.optionalHeader.magic == STMAGIC || COFFHdr.optionalHeader.magic == OMAGIC || COFFHdr.optionalHeader.magic == JMAGIC ||
COFFHdr.optionalHeader.magic == DMAGIC || COFFHdr.optionalHeader.magic == ZMAGIC || COFFHdr.optionalHeader.magic == SHMAGIC)
return true;
COFFHdr = SwapHeader(COFFHdr);
return COFFHdr.optionalHeader.magic == STMAGIC || COFFHdr.optionalHeader.magic == OMAGIC || COFFHdr.optionalHeader.magic == JMAGIC ||
COFFHdr.optionalHeader.magic == DMAGIC || COFFHdr.optionalHeader.magic == ZMAGIC || COFFHdr.optionalHeader.magic == SHMAGIC;
}
static COFFHeader SwapHeader(COFFHeader header)
{
COFFHeader swapped = BigEndianMarshal.SwapStructureMembersEndian(header);
swapped.characteristics = (Characteristics)Swapping.Swap((ushort)header.characteristics);
swapped.machine = (MachineTypes)Swapping.Swap((ushort)header.machine);
swapped.optionalHeader = BigEndianMarshal.SwapStructureMembersEndian(header.optionalHeader);
return swapped;
}
}
}

113
libexeinfo/COFF/Consts.cs Normal file
View File

@@ -0,0 +1,113 @@
//
// Consts.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace libexeinfo
{
public partial class COFF
{
public const ushort STMAGIC = 0x101;
public const ushort OMAGIC = 0x104;
/// <summary>
/// dirty text and data image, can't share
/// </summary>
public const ushort JMAGIC = 0x107;
/// <summary>
/// dirty text segment, data aligned
/// </summary>
public const ushort DMAGIC = 0x108;
/// <summary>
/// The proper magic number for executables
/// </summary>
public const ushort ZMAGIC = 0x10b;
/// <summary>
/// shared library header
/// </summary>
public const ushort SHMAGIC = 0x123;
/// <summary>
/// Alpha architecture information
/// </summary>
public readonly string SectionAlpha = ".arch";
/// <summary>
/// Uninitialized data
/// </summary>
public readonly string SectionBss = ".bss";
/// <summary>
/// Initialized data
/// </summary>
public readonly string SectionData = ".data";
/// <summary>
/// The export data section, named .edata, contains information about
/// symbols that other images can access through dynamic linking.
/// Exports are generally found in DLLs, but DLLs can import symbols as
/// well.
/// </summary>
public readonly string SectionExport = ".edata";
/// <summary>
/// Import tables
/// </summary>
public readonly string SectionImport = ".idata";
/// <summary>
/// Exception information
/// </summary>
public readonly string SectionException = ".pdata";
/// <summary>
/// Read-only initialized data
/// </summary>
public readonly string SectionReadOnly = ".rdata";
/// <summary>
/// Image relocations
/// </summary>
public readonly string SectionRelocations = ".reloc";
/// <summary>
/// Resource directory
/// </summary>
public readonly string SectionResource = ".rsrc";
/// <summary>
/// Executable code
/// </summary>
public readonly string SectionExecutable = ".text";
/// <summary>
/// Thread-local storage
/// </summary>
public readonly string SectionTls = ".tls";
/// <summary>
/// Exception information
/// </summary>
public readonly string SectioneXception = ".xdata";
/// <summary>
/// Debug information
/// </summary>
public readonly string SectionDebug = ".debug";
/// <summary>
/// A .drectve section consists of a string of ASCII text. This string is
/// a series of linker options (each option containing hyphen, option
/// name, and any appropriate attribute) separated by spaces.The
/// .drectve section must not have relocations or line numbers.
/// </summary>
public readonly string SectionDirectives = ".drectve";
}
}

415
libexeinfo/COFF/Enums.cs Normal file
View File

@@ -0,0 +1,415 @@
//
// Enums.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace libexeinfo
{
public partial class COFF
{
/// <summary>
/// The Machine field has one of the following values that specifies its CPU type. An image file can be run only on the specified machine or on a system that emulates the specified machine.
/// </summary>
public enum MachineTypes : ushort
{
/// <summary>
/// The contents of this field are assumed to be applicable to any machine type
/// </summary>
IMAGE_FILE_MACHINE_UNKNOWN = 0x0,
/// <summary>
/// Alpha AXP
/// </summary>
IMAGE_FILE_MACHINE_ALPHA = 0x184,
/// <summary>
/// Alpha AXP 64-bit.
/// </summary>
IMAGE_FILE_MACHINE_ALPHA64 = 0x284,
/// <summary>
/// Matsushita AM33
/// </summary>
IMAGE_FILE_MACHINE_AM33 = 0x1d3,
/// <summary>
/// x64
/// </summary>
IMAGE_FILE_MACHINE_AMD64 = 0x8664,
/// <summary>
/// ARM little endian
/// </summary>
IMAGE_FILE_MACHINE_ARM = 0x1c0,
/// <summary>
/// ARM64 little endian
/// </summary>
IMAGE_FILE_MACHINE_ARM64 = 0xaa64,
/// <summary>
/// ARM Thumb-2 little endian
/// </summary>
IMAGE_FILE_MACHINE_ARMNT = 0x1c4,
/// <summary>
/// Clipper
/// </summary>
IMAGE_FILE_MACHINE_CLIPPER = 0x17f,
/// <summary>
/// EFI byte code
/// </summary>
IMAGE_FILE_MACHINE_EBC = 0xebc,
/// <summary>
/// Intel 386 or later processors and compatible processors
/// </summary>
IMAGE_FILE_MACHINE_I386 = 0x14c,
/// <summary>
/// Intel 386 or later processors and compatible processors, used by AIX
/// </summary>
IMAGE_FILE_MACHINE_I386_AIX = 0x175,
/// <summary>
/// Intel Itanium processor family
/// </summary>
IMAGE_FILE_MACHINE_IA64 = 0x200,
/// <summary>
/// Mitsubishi M32R little endian
/// </summary>
IMAGE_FILE_MACHINE_M32R = 0x9041,
/// <summary>
/// Motorola 68000 series
/// </summary>
IMAGE_FILE_MACHINE_M68K = 0x268,
/// <summary>
/// Motorola 68000 series
/// </summary>
IMAGE_FILE_MACHINE_M68K_OTHER = 0x150,
/// <summary>
/// MIPS16
/// </summary>
IMAGE_FILE_MACHINE_MIPS16 = 0x266,
/// <summary>
/// MIPS with FPU
/// </summary>
IMAGE_FILE_MACHINE_MIPSFPU = 0x366,
/// <summary>
/// MIPS16 with FPU
/// </summary>
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466,
/// <summary>
/// PowerPC little endian
/// </summary>
IMAGE_FILE_MACHINE_POWERPC = 0x1f0,
/// <summary>
/// Power PC with floating point support
/// </summary>
IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1,
/// <summary>
/// MIPS big endian
/// </summary>
IMAGE_FILE_MACHINE_MIPSEB = 0x160,
/// <summary>
/// MIPS little endian
/// </summary>
IMAGE_FILE_MACHINE_R3000 = 0x162,
/// <summary>
/// MIPS little endian
/// </summary>
IMAGE_FILE_MACHINE_R4000 = 0x166,
/// <summary>
/// MIPS little endian
/// </summary>
IMAGE_FILE_MACHINE_R10000 = 0x168,
/// <summary>
/// RISC-V 32-bit address space
/// </summary>
IMAGE_FILE_MACHINE_RISCV32 = 0x5032,
/// <summary>
/// RISC-V 64-bit address space
/// </summary>
IMAGE_FILE_MACHINE_RISCV64 = 0x5064,
/// <summary>
/// RISC-V 128-bit address space
/// </summary>
IMAGE_FILE_MACHINE_RISCV128 = 0x5128,
/// <summary>
/// Hitachi SH3
/// </summary>
IMAGE_FILE_MACHINE_SH3 = 0x1a2,
/// <summary>
/// Hitachi SH3 DSP
/// </summary>
IMAGE_FILE_MACHINE_SH3DSP = 0x1a3,
/// <summary>
/// Hitachi SH4
/// </summary>
IMAGE_FILE_MACHINE_SH4 = 0x1a6,
/// <summary>
/// Hitachi SH5
/// </summary>
IMAGE_FILE_MACHINE_SH5 = 0x1a8,
/// <summary>
/// Thumb
/// </summary>
IMAGE_FILE_MACHINE_THUMB = 0x1c2,
/// <summary>
/// MIPS little-endian WCE v2
/// </summary>
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169,
/// <summary>
/// WE32000
/// </summary>
IMAGE_FILE_MACHINE_WE32000 = 0x170
}
/// <summary>
/// The Characteristics field contains flags that indicate attributes of the object or image file.
/// </summary>
[Flags]
public enum Characteristics : ushort
{
/// <summary>
/// Image only, Windows CE, and Microsoft Windows NT and later. This indicates that the file does not contain base relocations and must therefore be loaded at its preferred base address. If the base address is not available, the loader reports an error. The default behavior of the linker is to strip base relocations from executable (EXE) files.
/// </summary>
IMAGE_FILE_RELOCS_STRIPPED = 0x0001,
/// <summary>
/// Image only. This indicates that the image file is valid and can be run. If this flag is not set, it indicates a linker error.
/// </summary>
IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002,
/// <summary>
/// COFF line numbers have been removed. This flag is deprecated and should be zero.
/// </summary>
IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004,
/// <summary>
/// COFF symbol table entries for local symbols have been removed. This flag is deprecated and should be zero.
/// </summary>
IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008,
/// <summary>
/// Obsolete. Aggressively trim working set. This flag is deprecated for Windows 2000 and later and must be zero.
/// </summary>
IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010,
/// <summary>
/// Application can handle > 2-GB addresses.
/// </summary>
IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020,
/// <summary>
/// Machine is based on a 16-bit-word architecture.
/// </summary>
IMAGE_FILE_16BIT_MACHINE = 0x0040,
/// <summary>
/// Little endian: the least significant bit (LSB) precedes the most significant bit (MSB) in memory. This flag is deprecated and should be zero.
/// </summary>
IMAGE_FILE_BYTES_REVERSED_LO = 0x0080,
/// <summary>
/// Machine is based on a 32-bit-word architecture.
/// </summary>
IMAGE_FILE_32BIT_MACHINE = 0x0100,
/// <summary>
/// Debugging information is removed from the image file.
/// </summary>
IMAGE_FILE_DEBUG_STRIPPED = 0x0200,
/// <summary>
/// If the image is on removable media, fully load it and copy it to the swap file.
/// </summary>
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400,
/// <summary>
/// If the image is on network media, fully load it and copy it to the swap file.
/// </summary>
IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800,
/// <summary>
/// The image file is a system file, not a user program.
/// </summary>
IMAGE_FILE_SYSTEM = 0x1000,
/// <summary>
/// The image file is a dynamic-link library (DLL). Such files are considered executable files for almost all purposes, although they cannot be directly run.
/// </summary>
IMAGE_FILE_DLL = 0x2000,
/// <summary>
/// The file should be run only on a uniprocessor machine.
/// </summary>
IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000,
/// <summary>
/// Big endian: the MSB precedes the LSB in memory. This flag is deprecated and should be zero.
/// </summary>
IMAGE_FILE_BYTES_REVERSED_HI = 0x8000
}
public const uint IMAGE_SCN_ALIGN_MASK = 0x00F00000;
[Flags]
public enum SectionFlags : uint
{
/// <summary>
/// Reserved for future use.
/// </summary>
IMAGE_SCN_TYPE_DSECT=0x00000001,
/// <summary>
/// Reserved for future use.
/// </summary>
IMAGE_SCN_TYPE_NOLOAD=0x00000002,
/// <summary>
/// Reserved for future use.
/// </summary>
IMAGE_SCN_TYPE_GROUP=0x00000004,
/// <summary>
/// Section should not be padded to next boundary.
/// This is obsolete and replaced by <see cref="IMAGE_SCN_ALIGN_1BYTES"/>.
/// This is valid for object files only.
/// </summary>
IMAGE_SCN_TYPE_NO_PAD=0x00000008,
/// <summary>
/// Reserved for future use.
/// </summary>
IMAGE_SCN_TYPE_COPY=0x00000010,
/// <summary>
/// Section contains executable code.
/// </summary>
IMAGE_SCN_CNT_CODE=0x00000020,
/// <summary>
/// Section contains initialized data.
/// </summary>
IMAGE_SCN_CNT_INITIALIZED_DATA=0x00000040,
/// <summary>
/// Section contains uninitialized data.
/// </summary>
IMAGE_SCN_CNT_UNINITIALIZED_DATA=0x00000080,
/// <summary>
/// Reserved for future use.
/// </summary>
IMAGE_SCN_LNK_OTHER=0x00000100,
/// <summary>
/// Section contains comments or other information. The .drectve section has this type. This is valid for object files only.
/// </summary>
IMAGE_SCN_LNK_INFO=0x00000200,
/// <summary>
/// Reserved for future use.
/// </summary>
IMAGE_SCN_TYPE_OVER=0x00000400,
/// <summary>
/// Section will not become part of the image. This is valid for object files only.
/// </summary>
IMAGE_SCN_LNK_REMOVE=0x00000800,
/// <summary>
/// Section contains COMDAT data. This is valid for object files only.
/// </summary>
IMAGE_SCN_LNK_COMDAT=0x00001000,
/// <summary>
/// Reserved for future use.
/// </summary>
IMAGE_SCN_MEM_FARDATA=0x00008000,
/// <summary>
/// Reserved for future use.
/// </summary>
IMAGE_SCN_MEM_16BIT =0x00020000,
/// <summary>
/// Reserved for future use.
/// </summary>
IMAGE_SCN_MEM_LOCKED=0x00040000,
/// <summary>
/// Reserved for future use.
/// </summary>
IMAGE_SCN_MEM_PRELOAD=0x00080000,
/// <summary>
/// Align data on a 1-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_1BYTES=0x00100000,
/// <summary>
/// Align data on a 2-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_2BYTES=0x00200000,
/// <summary>
/// Align data on a 4-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_4BYTES=0x00300000,
/// <summary>
/// Align data on a 8-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_8BYTES=0x00400000,
/// <summary>
/// Align data on a 16-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_16BYTES=0x00500000,
/// <summary>
/// Align data on a 32-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_32BYTES=0x00600000,
/// <summary>
/// Align data on a 64-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_64BYTES=0x00700000,
/// <summary>
/// Align data on a 128-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_128BYTES=0x00800000,
/// <summary>
/// Align data on a 256-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_256BYTES=0x00900000,
/// <summary>
/// Align data on a 512-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_512BYTES=0x00A00000,
/// <summary>
/// Align data on a 1024-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_1024BYTES=0x00B00000,
/// <summary>
/// Align data on a 2048-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_2048BYTES=0x00C00000,
/// <summary>
/// Align data on a 4096-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_4096BYTES=0x00D00000,
/// <summary>
/// Align data on a 8192-byte boundary. This is valid for object files only.
/// </summary>
IMAGE_SCN_ALIGN_8192BYTES=0x00E00000,
/// <summary>
/// Section contains extended relocations.
/// </summary>
IMAGE_SCN_LNK_NRELOC_OVFL=0x01000000,
/// <summary>
/// Section can be discarded as needed.
/// </summary>
IMAGE_SCN_MEM_DISCARDABLE=0x02000000,
/// <summary>
/// Section cannot be cached.
/// </summary>
IMAGE_SCN_MEM_NOT_CACHED=0x04000000,
/// <summary>
/// Section is not pageable.
/// </summary>
IMAGE_SCN_MEM_NOT_PAGED=0x08000000,
/// <summary>
/// Section can be shared in memory.
/// </summary>
IMAGE_SCN_MEM_SHARED=0x10000000,
/// <summary>
/// Section can be executed as code.
/// </summary>
IMAGE_SCN_MEM_EXECUTE=0x20000000,
/// <summary>
/// Section can be read.
/// </summary>
IMAGE_SCN_MEM_READ=0x40000000,
/// <summary>
/// Section can be written to.
/// </summary>
IMAGE_SCN_MEM_WRITE=0x80000000
}
}
}

121
libexeinfo/COFF/Info.cs Normal file
View File

@@ -0,0 +1,121 @@
//
// Info.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace libexeinfo
{
public partial class COFF
{
public static string GetInfo(COFFHeader header)
{
DateTime epoch = new DateTime(1970, 1, 1);
StringBuilder sb = new StringBuilder();
sb.AppendLine("Common Object File Format (COFF):");
switch (header.optionalHeader.magic)
{
case JMAGIC:
sb.AppendLine("\tExecutable is dirty and unshareable");
break;
case DMAGIC:
sb.AppendLine("\tExecutable is dirty, data is aligned");
break;
case ZMAGIC:
sb.AppendLine("\tNormal executable");
break;
case SHMAGIC:
sb.AppendLine("\tShared library");
break;
case PE.PE32Plus:
sb.AppendLine("\tPE32+ executable");
break;
default:
sb.AppendFormat("\tUnknown executable type with magic {0}", header.optionalHeader.magic).AppendLine();
break;
}
sb.AppendFormat("\tMachine: {0}", MachineTypeToString(header.machine)).AppendLine();
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_RELOCS_STRIPPED))
sb.AppendLine("\tExecutable contains no relocations.");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_EXECUTABLE_IMAGE))
sb.AppendLine("\tExecutable is valid.");
else
sb.AppendLine("\tExecutable is invalid, contains errors or has not been linked correctly.");
if (!header.characteristics.HasFlag(Characteristics.IMAGE_FILE_LINE_NUMS_STRIPPED))
sb.AppendLine("\tExecutable contains line numbers.");
if (!header.characteristics.HasFlag(Characteristics.IMAGE_FILE_LOCAL_SYMS_STRIPPED))
sb.AppendLine("\tExecutable contains debug symbols.");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_AGGRESSIVE_WS_TRIM))
sb.AppendLine("\tWorking set should be aggressively trimmed");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_LARGE_ADDRESS_AWARE))
sb.AppendLine("\tExecutable can handle addresses bigger than 2GiB");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_16BIT_MACHINE))
sb.AppendLine("\tExecutable is for a 16-bit per word machine");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_BYTES_REVERSED_LO))
sb.AppendLine("\tExecutable is little-endian");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_32BIT_MACHINE))
sb.AppendLine("\tExecutable is for a 32-bit per word machine");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_DEBUG_STRIPPED))
sb.AppendLine("\tDebug information has been removed");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP))
sb.AppendLine("\tWhen executable is run from removable media, it should be copied to swap and run from there");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_NET_RUN_FROM_SWAP))
sb.AppendLine("\tWhen executable is run from a network share, it should be copied to swap and run from there");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_SYSTEM))
sb.AppendLine("\tExecutable is a system file");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_DLL))
sb.AppendLine("\tExecutable is a dynamically linkable library");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_UP_SYSTEM_ONLY))
sb.AppendLine("\tExecutable can only run on uniprocessor machines");
if (header.characteristics.HasFlag(Characteristics.IMAGE_FILE_BYTES_REVERSED_HI))
sb.AppendLine("\tExecutable is big-endian");
sb.AppendFormat("\tExecutable has {0} sections", header.numberOfSections).AppendLine();
sb.AppendFormat("\tExecutable was linked on {0}", epoch.AddSeconds(header.timeDateStamp)).AppendLine();
sb.AppendFormat("\tSymbol table starts at {0} and contains {1} symbols", header.pointerToSymbolTable, header.numberOfSymbols).AppendLine();
sb.AppendFormat("\tOptional header has {0} bytes", header.sizeOfOptionalHeader).AppendLine();
if(header.optionalHeader.majorLinkerVersion > 0 || header.optionalHeader.minorLinkerVersion > 0)
sb.AppendFormat("\tLinker version: {0}.{1}", header.optionalHeader.majorLinkerVersion, header.optionalHeader.minorLinkerVersion).AppendLine();
sb.AppendFormat("\tCode has {0} bytes", header.optionalHeader.sizeOfCode).AppendLine();
sb.AppendFormat("\tInitialized data has {0} bytes", header.optionalHeader.sizeOfInitializedData).AppendLine();
sb.AppendFormat("\tUninitialized data has {0} bytes", header.optionalHeader.sizeOfUninitializedData).AppendLine();
sb.AppendFormat("\tAddress point starts at {0}", header.optionalHeader.addressOfEntryPoint).AppendLine();
sb.AppendFormat("\tCode starts at {0}", header.optionalHeader.baseOfCode).AppendLine();
if (header.optionalHeader.magic != PE.PE32Plus)
sb.AppendFormat("\tData starts at {0}", header.optionalHeader.baseOfData).AppendLine();
return sb.ToString();
}
public string GetInfo()
{
return GetInfo(Header);
}
}
}

View File

@@ -0,0 +1,108 @@
//
// MachineTypes.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace libexeinfo
{
public partial class COFF
{
public static string MachineTypeToString(MachineTypes machine)
{
switch (machine)
{
case MachineTypes.IMAGE_FILE_MACHINE_UNKNOWN:
return "Any machine";
case MachineTypes.IMAGE_FILE_MACHINE_ALPHA:
return "Alpha AXP";
case MachineTypes.IMAGE_FILE_MACHINE_ALPHA64:
return "Alpha AXP 64-bit.";
case MachineTypes.IMAGE_FILE_MACHINE_AM33:
return "Matsushita AM33";
case MachineTypes.IMAGE_FILE_MACHINE_AMD64:
return "AMD64 / EM64T";
case MachineTypes.IMAGE_FILE_MACHINE_ARM:
return "ARM little endian";
case MachineTypes.IMAGE_FILE_MACHINE_ARM64:
return "ARM64 little endian";
case MachineTypes.IMAGE_FILE_MACHINE_ARMNT:
return "ARM Thumb-2 little endian";
case MachineTypes.IMAGE_FILE_MACHINE_EBC:
return "EFI byte code";
case MachineTypes.IMAGE_FILE_MACHINE_I386:
case MachineTypes.IMAGE_FILE_MACHINE_I386_AIX:
return "Intel 386 or later processors and compatible processors";
case MachineTypes.IMAGE_FILE_MACHINE_IA64:
return "Intel Itanium processor family";
case MachineTypes.IMAGE_FILE_MACHINE_M32R:
return "Mitsubishi M32R little endian";
case MachineTypes.IMAGE_FILE_MACHINE_M68K:
case MachineTypes.IMAGE_FILE_MACHINE_M68K_OTHER:
return "Motorola 68000 series";
case MachineTypes.IMAGE_FILE_MACHINE_MIPS16:
return "MIPS16";
case MachineTypes.IMAGE_FILE_MACHINE_MIPSFPU:
return "MIPS with FPU";
case MachineTypes.IMAGE_FILE_MACHINE_MIPSFPU16:
return "MIPS16 with FPU";
case MachineTypes.IMAGE_FILE_MACHINE_POWERPC:
return "PowerPC little endian";
case MachineTypes.IMAGE_FILE_MACHINE_POWERPCFP:
return "PowerPC with floating point support";
case MachineTypes.IMAGE_FILE_MACHINE_MIPSEB:
return "MIPS R3000 or later (big endian)";
case MachineTypes.IMAGE_FILE_MACHINE_R3000:
return "MIPS R3000 or later (little endian)";
case MachineTypes.IMAGE_FILE_MACHINE_R4000:
return "MIPS R4000 or later (little endian)";
case MachineTypes.IMAGE_FILE_MACHINE_R10000:
return "MIPS R10000 or later (little endian)";
case MachineTypes.IMAGE_FILE_MACHINE_RISCV32:
return "RISC-V 32-bit address space";
case MachineTypes.IMAGE_FILE_MACHINE_RISCV64:
return "RISC-V 64-bit address space";
case MachineTypes.IMAGE_FILE_MACHINE_RISCV128:
return "RISC-V 128-bit address space";
case MachineTypes.IMAGE_FILE_MACHINE_SH3:
return "Hitachi SH3";
case MachineTypes.IMAGE_FILE_MACHINE_SH3DSP:
return "Hitachi SH3 DSP";
case MachineTypes.IMAGE_FILE_MACHINE_SH4:
return "Hitachi SH4";
case MachineTypes.IMAGE_FILE_MACHINE_SH5:
return "Hitachi SH5";
case MachineTypes.IMAGE_FILE_MACHINE_THUMB:
return "ARM Thumb";
case MachineTypes.IMAGE_FILE_MACHINE_WCEMIPSV2:
return "MIPS little-endian WCE v2";
case MachineTypes.IMAGE_FILE_MACHINE_CLIPPER:
return "Clipper";
case MachineTypes.IMAGE_FILE_MACHINE_WE32000:
return "WE32000 series";
default:
return string.Format("Unknown machine type with code {0}", (ushort)machine);
}
}
}
}

182
libexeinfo/COFF/Structs.cs Normal file
View File

@@ -0,0 +1,182 @@
//
// Structs.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
namespace libexeinfo
{
// TODO: Tru64 COFF is slightly different
public partial class COFF
{
/// <summary>
/// At the beginning of an object file, or immediately after the signature of an image file, is a standard COFF file header in the following format. Note that the Windows loader limits the number of sections to 96.
/// </summary>
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct COFFHeader
{
/// <summary>
/// The number that identifies the type of target machine. For more information, <see cref="MachineTypes"/>.
/// </summary>
public MachineTypes machine;
/// <summary>
/// The number of sections. This indicates the size of the section table, which immediately follows the headers.
/// </summary>
public ushort numberOfSections;
/// <summary>
/// The low 32 bits of the number of seconds since 00:00 January 1, 1970 (a C run-time time_t value), that indicates when the file was created.
/// </summary>
public uint timeDateStamp;
/// <summary>
/// The file offset of the COFF symbol table, or zero if no COFF symbol table is present. This value should be zero for an image because COFF debugging information is deprecated.
/// </summary>
public uint pointerToSymbolTable;
/// <summary>
/// The number of entries in the symbol table. This data can be used to locate the string table, which immediately follows the symbol table. This value should be zero for an image because COFF debugging information is deprecated.
/// </summary>
public uint numberOfSymbols;
public ushort sizeOfOptionalHeader;
/// <summary>
/// The flags that indicate the attributes of the file. For specific flag values, <see cref="Characteristics"/>
/// </summary>
public Characteristics characteristics;
public OptionalHeader optionalHeader;
}
/// <summary>
/// The first eight fields of the optional header are standard fields that are defined for every implementation of COFF. These fields contain general information that is useful for loading and running an executable file. They are unchanged for the PE32+ format.
/// </summary>
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct OptionalHeader
{
/// <summary>
/// The unsigned integer that identifies the state of the image file. The most common number is 0x10B, which identifies it as a normal executable file. 0x107 identifies it as a ROM image, and 0x20B identifies it as a PE32+ executable.
/// </summary>
public ushort magic;
/// <summary>
/// The linker major version number.
/// </summary>
public byte majorLinkerVersion;
/// <summary>
/// The linker minor version number.
/// </summary>
public byte minorLinkerVersion;
/// <summary>
/// The size of the code (text) section, or the sum of all code sections if there are multiple sections.
/// </summary>
public uint sizeOfCode;
/// <summary>
/// The size of the initialized data section, or the sum of all such sections if there are multiple data sections.
/// </summary>
public uint sizeOfInitializedData;
/// <summary>
/// The size of the uninitialized data section (BSS), or the sum of all such sections if there are multiple BSS sections.
/// </summary>
public uint sizeOfUninitializedData;
/// <summary>
/// The address of the entry point relative to the image base when the executable file is loaded into memory. For program images, this is the starting address. For device drivers, this is the address of the initialization function. An entry point is optional for DLLs. When no entry point is present, this field must be zero.
/// </summary>
public uint addressOfEntryPoint;
/// <summary>
/// The address that is relative to the image base of the beginning-of-code section when it is loaded into memory.
/// </summary>
public uint baseOfCode;
/// <summary>
/// PE32 contains this additional field, which is absent in PE32+, following BaseOfCode.<br/>
/// The address that is relative to the image base of the beginning-of-data section when it is loaded into memory.
/// </summary>
public uint baseOfData;
}
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct SectionHeader
{
/// <summary>
/// An 8-byte, null-padded ASCII string. There is no terminating null if the string is
/// exactly eight characters long. For longer names, this field contains a slash(/)
/// followed by ASCII representation of a decimal number: this number is an offset into
/// the string table.Executable images do not use a string table and do not support
/// section names longer than eight characters. Long names in object files will be
/// truncated if emitted to an executable file.
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string name;
/// <summary>
/// Total size of the section when loaded into memory. If this value is greater than
/// <see cref="sizeOfRawData"/>, the section is zero-padded.This field is valid only
/// for executable images and should be set to 0 for object files.
/// </summary>
public uint virtualSize;
/// <summary>
/// For executable images this is the address of the first byte of the section, when
/// loaded into memory, relative to the image base. For object files, this field is
/// the address of the first byte before relocation is applied; for simplicity,
/// compilers should set this to zero. Otherwise, it is an arbitrary value that is
/// subtracted from offsets during relocation.
/// </summary>
public uint virtualAddress;
/// <summary>
/// Size of the section (object file) or size of the initialized data on disk(image
/// files). For executable image, this must be a multiple of FileAlignment from the
/// optional header.If this is less than <see cref="virtualSize"/> the remainder of
/// the section is zero filled. Because this field is rounded while the
/// <see cref="virtualSize"/> field is not it is possible for this to be greater
/// than <see cref="virtualSize"/> as well.When a section contains only
/// uninitialized data, this field should be 0.
/// </summary>
public uint sizeOfRawData;
/// <summary>
/// File pointer to sectionís first page within the COFF file. For executable images,
/// this must be a multiple of FileAlignment from the optional header. For object
/// files, the value should be aligned on a four-byte boundary for best performance.
/// When a section contains only uninitialized data, this field should be 0.
/// </summary>
public uint pointerToRawData;
/// <summary>
/// File pointer to beginning of relocation entries for the section. Set to 0 for
/// executable images or if there are no relocations.
/// </summary>
public uint pointerToRelocations;
/// <summary>
/// File pointer to beginning of line-number entries for the section.Set to 0 if
/// there are no COFF line numbers.
/// </summary>
public uint pointerToLineNumbers;
/// <summary>
/// Number of relocation entries for the section. Set to 0 for executable images.
/// </summary>
public ushort numberOfRelocations;
/// <summary>
/// Number of line-number entries for the section.
/// </summary>
public ushort numberOfLineNumbers;
/// <summary>
/// Flags describing sectionís characteristics. <see cref="SectionFlags"/>
/// </summary>
public SectionFlags characteristics;
}
}
}

38
libexeinfo/PE/Consts.cs Normal file
View File

@@ -0,0 +1,38 @@
//
// Consts.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace libexeinfo
{
public partial class PE
{
/// <summary>
/// Portable Executable signature, "PE\0\0"
/// </summary>
public const ushort Signature = 0x00004550;
public const ushort PE32 = COFF.ZMAGIC;
public const ushort PE32Plus = 0x20b;
}
}

177
libexeinfo/PE/Enums.cs Normal file
View File

@@ -0,0 +1,177 @@
//
// Enums.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace libexeinfo
{
public partial class PE
{
/// <summary>
/// The following values defined for the Subsystem field of the optional header determine which Windows subsystem (if any) is required to run the image.
/// </summary>
public enum Subsystems : ushort
{
/// <summary>
/// An unknown subsystem
/// </summary>
IMAGE_SUBSYSTEM_UNKNOWN = 0,
/// <summary>
/// Device drivers and native Windows processes
/// </summary>
IMAGE_SUBSYSTEM_NATIVE = 1,
/// <summary>
/// The Windows graphical user interface (GUI) subsystem
/// </summary>
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2,
/// <summary>
/// The Windows character subsystem
/// </summary>
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3,
/// <summary>
/// The OS/2 character subsystem
/// </summary>
IMAGE_SUBSYSTEM_OS2_CUI = 5,
/// <summary>
/// The Posix character subsystem
/// </summary>
IMAGE_SUBSYSTEM_POSIX_CUI = 7,
/// <summary>
/// Native Win9x driver
/// </summary>
IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8,
/// <summary>
/// Windows CE
/// </summary>
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9,
/// <summary>
/// An Extensible Firmware Interface (EFI) application
/// </summary>
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
/// <summary>
/// An EFI driver with boot services
/// </summary>
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
/// <summary>
/// An EFI driver with run-time services
/// </summary>
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12,
/// <summary>
/// An EFI ROM image
/// </summary>
IMAGE_SUBSYSTEM_EFI_ROM = 13,
/// <summary>
/// XBOX
/// </summary>
IMAGE_SUBSYSTEM_XBOX = 14,
/// <summary>
/// Windows boot application
/// </summary>
IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16
}
/// <summary>
/// The following values are defined for the DllCharacteristics field of the optional header.
/// </summary>
[Flags]
public enum DllCharacteristics : ushort
{
/// <summary>
/// Image can handle a high entropy 64-bit virtual address space.
/// </summary>
IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020,
/// <summary>
/// DLL can be relocated at load time.
/// </summary>
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040,
/// <summary>
/// Code Integrity checks are enforced.
/// </summary>
IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080,
/// <summary>
/// Image is NX compatible.
/// </summary>
IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100,
/// <summary>
/// Isolation aware, but do not isolate the image.
/// </summary>
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200,
/// <summary>
/// Does not use structured exception (SE) handling. No SE handler may be called in this image.
/// </summary>
IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400,
/// <summary>
/// Do not bind the image.
/// </summary>
IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800,
/// <summary>
/// Image must execute in an AppContainer.
/// </summary>
IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 0x1000,
/// <summary>
/// A WDM driver.
/// </summary>
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000,
/// <summary>
/// Image supports Control Flow Guard.
/// </summary>
IMAGE_DLLCHARACTERISTICS_GUARD_CF = 0x4000,
/// <summary>
/// Terminal Server aware.
/// </summary>
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
}
public enum DebugTypes : uint
{
/// <summary>
/// Unknown value, ignored by all tools.
/// </summary>
IMAGE_DEBUG_TYPE_UNKNOWN = 0,
/// <summary>
/// COFF debug information (line numbers, symbol table, and string table).
/// This type of debug information is also pointed to by fields in the file headers.
/// </summary>
IMAGE_DEBUG_TYPE_COFF = 1,
/// <summary>
/// CodeView debug information. The format of the data block is described
/// by the CV4 specification.
/// </summary>
IMAGE_DEBUG_TYPE_CODEVIEW = 2,
/// <summary>
/// Frame Pointer Omission (FPO) information. This information tells the
/// debugger how to interpret non-standard stack frames, which use the
/// EBP register for a purpose other than as a frame pointer.
/// </summary>
IMAGE_DEBUG_TYPE_FPO = 3,
IMAGE_DEBUG_TYPE_MISC = 4,
IMAGE_DEBUG_TYPE_EXCEPTION = 5,
IMAGE_DEBUG_TYPE_FIXUP = 6,
IMAGE_DEBUG_TYPE_OMAP_TO_SRC = 7,
IMAGE_DEBUG_TYPE_OMAP_FROM_SRC = 8,
IMAGE_DEBUG_TYPE_BORLAND = 9
}
}
}

100
libexeinfo/PE/Info.cs Normal file
View File

@@ -0,0 +1,100 @@
//
// Info.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace libexeinfo
{
public partial class PE
{
public static string GetInfo(PEHeader header, WindowsHeader64 winheader)
{
StringBuilder sb = new StringBuilder();
sb.Append(COFF.GetInfo(header.coff));
sb.AppendLine("Portable Executable (PE):");
if(header.coff.optionalHeader.magic == PE32Plus)
sb.AppendFormat("\tExecutable base address: 0x{0:X16}", winheader.imageBase).AppendLine();
else
sb.AppendFormat("\tExecutable base address: 0x{0:X8}", winheader.imageBase).AppendLine();
sb.AppendFormat("\tSections are aligned to {0} bytes", winheader.sectionAlignment).AppendLine();
sb.AppendFormat("\tFile is aligned to {0} bytes", winheader.fileAlignment).AppendLine();
if(winheader.majorOperatingSystemVersion > 0 || winheader.minorOperatingSystemVersion > 0)
sb.AppendFormat("\tExecutable requires at least operating system version {0}.{1} to run", winheader.majorOperatingSystemVersion, winheader.minorOperatingSystemVersion).AppendLine();
if (winheader.majorImageVersion > 0 || winheader.minorImageVersion > 0)
sb.AppendFormat("\tExecutable version: {0}.{1}", winheader.majorImageVersion, winheader.minorImageVersion).AppendLine();
sb.AppendFormat("\tAccording to subsystem, executable is {0}", SubsystemToString(winheader.subsystem)).AppendLine();
if (winheader.majorSubsystemVersion > 0 || winheader.minorSubsystemVersion > 0)
sb.AppendFormat("\tExecutable requires at least subsystem version {0}.{1} to run", winheader.majorSubsystemVersion, winheader.minorSubsystemVersion).AppendLine();
if (winheader.dllCharacteristics.HasFlag(DllCharacteristics.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA))
sb.AppendLine("\tExecutable can handle a high entropy 64-bit virtual address space");
if (winheader.dllCharacteristics.HasFlag(DllCharacteristics.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE))
sb.AppendLine("\tExecutable can be relocated at load time");
if (winheader.dllCharacteristics.HasFlag(DllCharacteristics.IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY))
sb.AppendLine("\tCode Integrity checks are enforced");
if (winheader.dllCharacteristics.HasFlag(DllCharacteristics.IMAGE_DLLCHARACTERISTICS_NX_COMPAT))
sb.AppendLine("\tExecutable is NX compatible");
if (winheader.dllCharacteristics.HasFlag(DllCharacteristics.IMAGE_DLLCHARACTERISTICS_NO_ISOLATION))
sb.AppendLine("\tExecutable is isolation aware, but should not be isolated");
if (winheader.dllCharacteristics.HasFlag(DllCharacteristics.IMAGE_DLLCHARACTERISTICS_NO_SEH))
sb.AppendLine("\tExecutable does not use structured exception handling");
if (winheader.dllCharacteristics.HasFlag(DllCharacteristics.IMAGE_DLLCHARACTERISTICS_NO_BIND))
sb.AppendLine("\tExecutable should not be binded");
if (winheader.dllCharacteristics.HasFlag(DllCharacteristics.IMAGE_DLLCHARACTERISTICS_APPCONTAINER))
sb.AppendLine("\tExecutable must be run inside an AppContainer");
if (winheader.dllCharacteristics.HasFlag(DllCharacteristics.IMAGE_DLLCHARACTERISTICS_WDM_DRIVER))
sb.AppendLine("\tExecutable contains a WDM driver");
if (winheader.dllCharacteristics.HasFlag(DllCharacteristics.IMAGE_DLLCHARACTERISTICS_GUARD_CF))
sb.AppendLine("\tExecutable supports Control Flow Guard");
if (winheader.dllCharacteristics.HasFlag(DllCharacteristics.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE))
sb.AppendLine("\tExecutable is Terminal Server aware");
if (winheader.win32VersionValue > 0)
sb.AppendFormat("\tWin32 version value: {0}", winheader.win32VersionValue).AppendLine();
sb.AppendFormat("\tExecutable is {0} bytes", winheader.sizeOfImage).AppendLine();
sb.AppendFormat("\tHeaders are {0} bytes", winheader.sizeOfHeaders).AppendLine();
sb.AppendFormat("\tChecksum: 0x{0:X8}", winheader.checksum).AppendLine();
sb.AppendFormat("\t{0} bytes of stack should be reserved", winheader.sizeOfStackReserve).AppendLine();
sb.AppendFormat("\t{0} bytes of stack should be committed", winheader.sizeOfStackCommit).AppendLine();
sb.AppendFormat("\t{0} bytes of heap should be reserved", winheader.sizeOfHeapReserve).AppendLine();
sb.AppendFormat("\t{0} bytes of heap should be committed", winheader.sizeOfHeapCommit).AppendLine();
if (winheader.loaderFlags > 0)
sb.AppendFormat("\tLoader flags: {0}", winheader.loaderFlags).AppendLine();
sb.AppendFormat("\t{0} RVA entries follow the header", winheader.numberOfRvaAndSizes).AppendLine();
return sb.ToString();
}
public string GetInfo()
{
return GetInfo(Header, WinHeader);
}
}
}

232
libexeinfo/PE/PE.cs Normal file
View File

@@ -0,0 +1,232 @@
//
// PE.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITPESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONPECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace libexeinfo
{
/// <summary>
/// Represents a Microsoft Portable Executable
/// </summary>
public partial class PE
{
/// <summary>
/// The <see cref="FileStream"/> that contains the executable represented by this instance
/// </summary>
public readonly FileStream BaseStream;
/// <summary>
/// Header for this executable
/// </summary>
public readonly PEHeader Header;
/// <summary>
/// If true this instance correctly represents a Microsoft Portable Executable
/// </summary>
public readonly bool IsPE;
public readonly MZ BaseExecutable;
public readonly WindowsHeader64 WinHeader;
/// <summary>
/// Initializes a new instance of the <see cref="T:libexeinfo.PE"/> class.
/// </summary>
/// <param name="path">Executable path.</param>
public PE(string path)
{
IsPE = false;
BaseStream = File.Open(path, FileMode.Open, FileAccess.Read);
BaseExecutable = new MZ(BaseStream);
if(BaseExecutable.IsMZ)
{
if(BaseExecutable.Header.new_offset < BaseStream.Length)
{
BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin);
byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))];
BaseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
Header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader));
Marshal.FreeHGlobal(hdrPtr);
IsPE = Header.signature == Signature;
if(IsPE)
{
if(Header.coff.optionalHeader.magic == PE32Plus)
{
BaseStream.Position -= 4;
buffer = new byte[Marshal.SizeOf(typeof(WindowsHeader64))];
BaseStream.Read(buffer, 0, buffer.Length);
hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
WinHeader = (WindowsHeader64)Marshal.PtrToStructure(hdrPtr, typeof(WindowsHeader64));
Marshal.FreeHGlobal(hdrPtr);
}
else
{
buffer = new byte[Marshal.SizeOf(typeof(WindowsHeader))];
BaseStream.Read(buffer, 0, buffer.Length);
hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
WindowsHeader hdr32 = (WindowsHeader)Marshal.PtrToStructure(hdrPtr, typeof(WindowsHeader));
Marshal.FreeHGlobal(hdrPtr);
WinHeader = ToPlus(hdr32);
}
}
}
}
}
/// <summary>
/// Initializes a new instance of the <see cref="T:libexeinfo.PE"/> class.
/// </summary>
/// <param name="stream">Stream containing the executable.</param>
public PE(FileStream stream)
{
IsPE = false;
BaseStream = stream;
BaseExecutable = new MZ(BaseStream);
if (BaseExecutable.IsMZ)
{
if (BaseExecutable.Header.new_offset < BaseStream.Length)
{
BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin);
byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))];
BaseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
Header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader));
Marshal.FreeHGlobal(hdrPtr);
IsPE = Header.signature == Signature;
if (IsPE)
{
if (Header.coff.optionalHeader.magic == PE32Plus)
{
BaseStream.Position -= 4;
buffer = new byte[Marshal.SizeOf(typeof(WindowsHeader64))];
BaseStream.Read(buffer, 0, buffer.Length);
hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
WinHeader = (WindowsHeader64)Marshal.PtrToStructure(hdrPtr, typeof(WindowsHeader64));
Marshal.FreeHGlobal(hdrPtr);
}
else
{
buffer = new byte[Marshal.SizeOf(typeof(WindowsHeader))];
BaseStream.Read(buffer, 0, buffer.Length);
hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
WindowsHeader hdr32 = (WindowsHeader)Marshal.PtrToStructure(hdrPtr, typeof(WindowsHeader));
Marshal.FreeHGlobal(hdrPtr);
WinHeader = ToPlus(hdr32);
}
}
}
}
}
/// <summary>
/// Identifies if the specified executable is a Microsoft Portable Executable
/// </summary>
/// <returns><c>true</c> if the specified executable is a Microsoft Portable Executable, <c>false</c> otherwise.</returns>
/// <param name="path">Executable path.</param>
public static bool Identify(string path)
{
FileStream BaseStream = File.Open(path, FileMode.Open, FileAccess.Read);
MZ BaseExecutable = new MZ(BaseStream);
if (BaseExecutable.IsMZ)
{
if (BaseExecutable.Header.new_offset < BaseStream.Length)
{
BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin);
byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))];
BaseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
PEHeader Header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader));
Marshal.FreeHGlobal(hdrPtr);
return Header.signature == Signature;
}
}
return false;
}
/// <summary>
/// Identifies if the specified executable is a Microsoft Portable Executable
/// </summary>
/// <returns><c>true</c> if the specified executable is a Microsoft Portable Executable, <c>false</c> otherwise.</returns>
/// <param name="stream">Stream containing the executable.</param>
public static bool Identify(FileStream stream)
{
FileStream BaseStream = stream;
MZ BaseExecutable = new MZ(BaseStream);
if (BaseExecutable.IsMZ)
{
if (BaseExecutable.Header.new_offset < BaseStream.Length)
{
BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin);
byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))];
BaseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
PEHeader Header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader));
Marshal.FreeHGlobal(hdrPtr);
return Header.signature == Signature;
}
}
return false;
}
static WindowsHeader64 ToPlus(WindowsHeader header)
{
return new WindowsHeader64
{
imageBase = header.imageBase,
sectionAlignment = header.sectionAlignment,
fileAlignment = header.fileAlignment,
majorOperatingSystemVersion = header.majorOperatingSystemVersion,
minorOperatingSystemVersion = header.minorOperatingSystemVersion,
majorImageVersion = header.majorImageVersion,
minorImageVersion = header.minorImageVersion,
majorSubsystemVersion = header.majorSubsystemVersion,
minorSubsystemVersion = header.minorSubsystemVersion,
win32VersionValue = header.win32VersionValue,
sizeOfImage = header.sizeOfImage,
sizeOfHeaders = header.sizeOfHeaders,
checksum = header.checksum,
subsystem = header.subsystem,
dllCharacteristics = header.dllCharacteristics,
sizeOfStackReserve = header.sizeOfStackReserve,
sizeOfStackCommit = header.sizeOfStackCommit,
sizeOfHeapReserve = header.sizeOfHeapReserve,
sizeOfHeapCommit = header.sizeOfHeapCommit,
loaderFlags = header.loaderFlags,
numberOfRvaAndSizes = header.numberOfRvaAndSizes
};
}
}
}

351
libexeinfo/PE/Structs.cs Normal file
View File

@@ -0,0 +1,351 @@
//
// Structs.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using static libexeinfo.COFF;
namespace libexeinfo
{
public partial class PE
{
/// <summary>
/// Header for a Microsoft New Executable
/// </summary>
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct PEHeader
{
/// <summary>
/// After the MS-DOS stub, at the file offset specified at offset 0x3c, is a 4-byte signature that identifies the file as a PE format image file. This signature is "PE\0\0" (the letters "P" and "E" followed by two null bytes).
/// </summary>
public uint signature;
public COFFHeader coff;
}
/// <summary>
/// The next 21 fields are an extension to the COFF optional header format. They contain additional information that is required by the linker and loader in Windows.
/// </summary>
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct WindowsHeader
{
/// <summary>
/// The preferred address of the first byte of image when loaded into memory; must be a multiple of 64 K. The default for DLLs is 0x10000000. The default for Windows CE EXEs is 0x00010000. The default for Windows NT, Windows 2000, Windows XP, Windows 95, Windows 98, and Windows Me is 0x00400000.
/// </summary>
public uint imageBase;
/// <summary>
/// The alignment (in bytes) of sections when they are loaded into memory. It must be greater than or equal to FileAlignment. The default is the page size for the architecture.
/// </summary>
public uint sectionAlignment;
/// <summary>
/// The alignment factor (in bytes) that is used to align the raw data of sections in the image file. The value should be a power of 2 between 512 and 64 K, inclusive. The default is 512. If the SectionAlignment is less than the architecture's page size, then FileAlignment must match SectionAlignment.
/// </summary>
public uint fileAlignment;
/// <summary>
/// The major version number of the required operating system.
/// </summary>
public ushort majorOperatingSystemVersion;
/// <summary>
/// The minor version number of the required operating system.
/// </summary>
public ushort minorOperatingSystemVersion;
/// <summary>
/// The major version number of the image.
/// </summary>
public ushort majorImageVersion;
/// <summary>
/// The minor version number of the image.
/// </summary>
public ushort minorImageVersion;
/// <summary>
/// The major version number of the subsystem.
/// </summary>
public ushort majorSubsystemVersion;
/// <summary>
/// The minor version number of the subsystem.
/// </summary>
public ushort minorSubsystemVersion;
/// <summary>
/// Reserved, must be zero.
/// </summary>
public uint win32VersionValue;
/// <summary>
/// The size (in bytes) of the image, including all headers, as the image is loaded in memory. It must be a multiple of SectionAlignment.
/// </summary>
public uint sizeOfImage;
/// <summary>
/// The combined size of an MS-DOS stub, PE header, and section headers rounded up to a multiple of FileAlignment.
/// </summary>
public uint sizeOfHeaders;
/// <summary>
/// The image file checksum. The algorithm for computing the checksum is incorporated into IMAGHELP.DLL. The following are checked for validation at load time: all drivers, any DLL loaded at boot time, and any DLL that is loaded into a critical Windows process.
/// </summary>
public uint checksum;
/// <summary>
/// The subsystem that is required to run this image. For more information, <see cref="Subsystems"/>.
/// </summary>
public Subsystems subsystem;
/// <summary>
/// For more information, <see cref="DllCharacteristics"/>.
/// </summary>
public DllCharacteristics dllCharacteristics;
/// <summary>
/// The size of the stack to reserve. Only SizeOfStackCommit is committed; the rest is made available one page at a time until the reserve size is reached.
/// </summary>
public uint sizeOfStackReserve;
/// <summary>
/// The size of the stack to commit.
/// </summary>
public uint sizeOfStackCommit;
/// <summary>
/// The size of the local heap space to reserve. Only SizeOfHeapCommit is committed; the rest is made available one page at a time until the reserve size is reached.
/// </summary>
public uint sizeOfHeapReserve;
/// <summary>
/// The size of the local heap space to commit.
/// </summary>
public uint sizeOfHeapCommit;
/// <summary>
/// Reserved, must be zero.
/// </summary>
public uint loaderFlags;
/// <summary>
/// The number of data-directory entries in the remainder of the optional header. Each describes a location and size.
/// </summary>
public uint numberOfRvaAndSizes;
}
/// <summary>
/// The next 21 fields are an extension to the COFF optional header format. They contain additional information that is required by the linker and loader in Windows.
/// </summary>
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct WindowsHeader64
{
/// <summary>
/// The preferred address of the first byte of image when loaded into memory; must be a multiple of 64 K. The default for DLLs is 0x10000000. The default for Windows CE EXEs is 0x00010000. The default for Windows NT, Windows 2000, Windows XP, Windows 95, Windows 98, and Windows Me is 0x00400000.
/// </summary>
public ulong imageBase;
/// <summary>
/// The alignment (in bytes) of sections when they are loaded into memory. It must be greater than or equal to FileAlignment. The default is the page size for the architecture.
/// </summary>
public uint sectionAlignment;
/// <summary>
/// The alignment factor (in bytes) that is used to align the raw data of sections in the image file. The value should be a power of 2 between 512 and 64 K, inclusive. The default is 512. If the SectionAlignment is less than the architecture's page size, then FileAlignment must match SectionAlignment.
/// </summary>
public uint fileAlignment;
/// <summary>
/// The major version number of the required operating system.
/// </summary>
public ushort majorOperatingSystemVersion;
/// <summary>
/// The minor version number of the required operating system.
/// </summary>
public ushort minorOperatingSystemVersion;
/// <summary>
/// The major version number of the image.
/// </summary>
public ushort majorImageVersion;
/// <summary>
/// The minor version number of the image.
/// </summary>
public ushort minorImageVersion;
/// <summary>
/// The major version number of the subsystem.
/// </summary>
public ushort majorSubsystemVersion;
/// <summary>
/// The minor version number of the subsystem.
/// </summary>
public ushort minorSubsystemVersion;
/// <summary>
/// Reserved, must be zero.
/// </summary>
public uint win32VersionValue;
/// <summary>
/// The size (in bytes) of the image, including all headers, as the image is loaded in memory. It must be a multiple of SectionAlignment.
/// </summary>
public uint sizeOfImage;
/// <summary>
/// The combined size of an MS-DOS stub, PE header, and section headers rounded up to a multiple of FileAlignment.
/// </summary>
public uint sizeOfHeaders;
/// <summary>
/// The image file checksum. The algorithm for computing the checksum is incorporated into IMAGHELP.DLL. The following are checked for validation at load time: all drivers, any DLL loaded at boot time, and any DLL that is loaded into a critical Windows process.
/// </summary>
public uint checksum;
/// <summary>
/// The subsystem that is required to run this image. For more information, <see cref="Subsystems"/>.
/// </summary>
public Subsystems subsystem;
/// <summary>
/// For more information, <see cref="DllCharacteristics"/>.
/// </summary>
public DllCharacteristics dllCharacteristics;
/// <summary>
/// The size of the stack to reserve. Only SizeOfStackCommit is committed; the rest is made available one page at a time until the reserve size is reached.
/// </summary>
public ulong sizeOfStackReserve;
/// <summary>
/// The size of the stack to commit.
/// </summary>
public ulong sizeOfStackCommit;
/// <summary>
/// The size of the local heap space to reserve. Only SizeOfHeapCommit is committed; the rest is made available one page at a time until the reserve size is reached.
/// </summary>
public ulong sizeOfHeapReserve;
/// <summary>
/// The size of the local heap space to commit.
/// </summary>
public ulong sizeOfHeapCommit;
/// <summary>
/// Reserved, must be zero.
/// </summary>
public uint loaderFlags;
/// <summary>
/// The number of data-directory entries in the remainder of the optional header. Each describes a location and size.
/// </summary>
public uint numberOfRvaAndSizes;
}
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct ImageDataDirectory
{
/// <summary>
/// Relative virtual address of the table
/// </summary>
uint rva;
/// <summary>
/// The size in bytes
/// </summary>
uint size;
}
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct DebugDirectory
{
/// <summary>
/// A reserved field intended to be used for flags, set to zero for now.
/// </summary>
public uint characteristics;
/// <summary>
/// Time and date the debug data was created.
/// </summary>
public uint timeDateStamp;
/// <summary>
/// Major version number of the debug data format.
/// </summary>
public ushort majorVersion;
/// <summary>
/// Minor version number of the debug data format.
/// </summary>
public ushort minorVersion;
/// <summary>
/// Format of debugging information: this field enables support of multiple debuggers. <see cref="DebugTypes"/> for more information.
/// </summary>
public DebugTypes type;
/// <summary>
/// Size of the debug data (not including the debug directory itself).
/// </summary>
public uint sizeOfData;
/// <summary>
/// Address of the debug data when loaded, relative to the image base.
/// </summary>
public uint addressOfRawData;
/// <summary>
/// File pointer to the debug data.
/// </summary>
public uint pointerToRawData;
}
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct ResourceDirectoryTable
{
/// <summary>
/// Resource flags, reserved for future use; currently set to zero.
/// </summary>
public uint characteristics;
/// <summary>
/// Time the resource data was created by the resource compiler.
/// </summary>
public uint timeDateStamp;
/// <summary>
/// Major version number, set by the user.
/// </summary>
public ushort majorVersion;
/// <summary>
/// Minor version number.
/// </summary>
public ushort minorVersion;
/// <summary>
/// Number of directory entries, immediately following the table,
/// that use strings to identify Type, Name, or Language
/// (depending on the level of the table).
/// </summary>
public ushort nameEntries;
/// <summary>
/// Number of directory entries, immediately following the Name
/// entries, that use numeric identifiers for Type, Name, or Language.
/// </summary>
public ushort idEntries;
}
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct ResourceDirectoryEntries
{
/// <summary>
/// Address of string that gives the Type, Name, or Language identifier, depending on level of table.
/// or
/// 32-bit integer that identifies Type, Name, or Language.
/// </summary>
public uint nameOrID;
/// <summary>
/// High bit 0: Address of a Resource Data Entry(a leaf).
/// High bit 1: Lower 31 bits are the address of another Resource Directory Table(the next level down).
/// </summary>
public uint rva;
}
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct ResourceDataEntry
{
/// <summary>
/// Address of a unit of resource data in the Resource Data area.
/// </summary>
public uint rva;
/// <summary>
/// Size, in bytes, of the resource data pointed to by the Data RVA field.
/// </summary>
public uint size;
/// <summary>
/// Code page used to decode code point values within the resource data.Typically, the code page would be the Unicode code page.
/// </summary>
public uint codepage;
/// <summary>
/// Reserved (must be set to 0)
/// </summary>
public uint reserved;
}
}
}

View File

@@ -0,0 +1,71 @@
//
// Subsystems.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace libexeinfo
{
public partial class PE
{
public static string SubsystemToString(Subsystems subsystem)
{
switch(subsystem)
{
/// <summary>
/// An unknown subsystem
/// </summary>
case Subsystems.IMAGE_SUBSYSTEM_UNKNOWN:
return "for an unknown subsystem with no code";
case Subsystems.IMAGE_SUBSYSTEM_NATIVE:
return "an application for native Windows API";
case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_GUI:
return "an application for Windows GUI";
case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_CUI:
return "an application for Windows command-line";
case Subsystems.IMAGE_SUBSYSTEM_OS2_CUI:
return "an application for OS/2 command-line";
case Subsystems.IMAGE_SUBSYSTEM_POSIX_CUI:
return "an application for POSIX command-line";
case Subsystems.IMAGE_SUBSYSTEM_NATIVE_WINDOWS:
return "a driver for Windows 9x";
case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
return "an application for Windows CE";
case Subsystems.IMAGE_SUBSYSTEM_EFI_APPLICATION:
return "an EFI application";
case Subsystems.IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
return "an EFI boot services driver";
case Subsystems.IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
return "an EFI run-time services driver";
case Subsystems.IMAGE_SUBSYSTEM_EFI_ROM:
return "an EFI ROM image";
case Subsystems.IMAGE_SUBSYSTEM_XBOX:
return "a Xbox executable";
case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION:
return "an application for Windows Boot environment";
default:
return string.Format("for an unknown subsystem with code {0}", (ushort)subsystem);
}
}
}
}

134
libexeinfo/Swapping.cs Normal file
View File

@@ -0,0 +1,134 @@
//
// Swapping.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// Copyright (c) 2017 Copyright © Claunia.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
namespace libexeinfo
{
public static class Swapping
{
public static byte[] SwapTenBytes(byte[] source)
{
byte[] destination = new byte[8];
destination[0] = source[9];
destination[1] = source[8];
destination[2] = source[7];
destination[3] = source[6];
destination[4] = source[5];
destination[5] = source[4];
destination[6] = source[3];
destination[7] = source[2];
destination[8] = source[1];
destination[9] = source[0];
return destination;
}
public static byte[] SwapEightBytes(byte[] source)
{
byte[] destination = new byte[8];
destination[0] = source[7];
destination[1] = source[6];
destination[2] = source[5];
destination[3] = source[4];
destination[4] = source[3];
destination[5] = source[2];
destination[6] = source[1];
destination[7] = source[0];
return destination;
}
public static byte[] SwapFourBytes(byte[] source)
{
byte[] destination = new byte[4];
destination[0] = source[3];
destination[1] = source[2];
destination[2] = source[1];
destination[3] = source[0];
return destination;
}
public static byte[] SwapTwoBytes(byte[] source)
{
byte[] destination = new byte[2];
destination[0] = source[1];
destination[1] = source[0];
return destination;
}
public static uint PDPFromLittleEndian(uint x)
{
return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
}
public static uint PDPFromBigEndian(uint x)
{
return ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8);
}
public static ulong Swap(ulong x)
{
x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8;
return x;
}
public static long Swap(long x)
{
return BitConverter.ToInt64(BitConverter.GetBytes(x).Reverse().ToArray(), 0);
}
public static ushort Swap(ushort x)
{
return (ushort)((x << 8) | (x >> 8));
}
public static short Swap(short x)
{
return (short)((x << 8) | ((x >> 8) & 0xFF));
}
public static uint Swap(uint x)
{
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF);
return (x << 16) | (x >> 16);
}
public static int Swap(int x)
{
x = (int)(((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF));
return (x << 16) | ((x >> 16) & 0xFFFF);
}
}
}

View File

@@ -64,6 +64,19 @@
<Compile Include="LX\Consts.cs" /> <Compile Include="LX\Consts.cs" />
<Compile Include="LX\Info.cs" /> <Compile Include="LX\Info.cs" />
<Compile Include="LX\LX.cs" /> <Compile Include="LX\LX.cs" />
<Compile Include="PE\Info.cs" />
<Compile Include="PE\Consts.cs" />
<Compile Include="PE\Enums.cs" />
<Compile Include="PE\PE.cs" />
<Compile Include="PE\Structs.cs" />
<Compile Include="COFF\Consts.cs" />
<Compile Include="COFF\Enums.cs" />
<Compile Include="COFF\Structs.cs" />
<Compile Include="COFF\Info.cs" />
<Compile Include="COFF\COFF.cs" />
<Compile Include="COFF\MachineTypes.cs" />
<Compile Include="Swapping.cs" />
<Compile Include="PE\Subsystems.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
@@ -79,6 +92,8 @@
<Folder Include="NE\" /> <Folder Include="NE\" />
<Folder Include="AtariST\" /> <Folder Include="AtariST\" />
<Folder Include="LX\" /> <Folder Include="LX\" />
<Folder Include="PE\" />
<Folder Include="COFF\" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\NuGet.Build.Packaging.0.1.276\build\NuGet.Build.Packaging.targets" Condition="Exists('..\packages\NuGet.Build.Packaging.0.1.276\build\NuGet.Build.Packaging.targets')" /> <Import Project="..\packages\NuGet.Build.Packaging.0.1.276\build\NuGet.Build.Packaging.targets" Condition="Exists('..\packages\NuGet.Build.Packaging.0.1.276\build\NuGet.Build.Packaging.targets')" />