0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

cscの作法 その250

Posted at

概要

cscの作法、調べてみた。
exeファイルをパースしてみた。
clrヘッダーもパースしてみた。

サンプルコード


using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

public class PEReader {
	[StructLayout(LayoutKind.Sequential)]
	public struct IMAGE_DOS_HEADER {
		public UInt16 e_magic;
		public UInt16 e_cblp;
		public UInt16 e_cp;
		public UInt16 e_crlc;
		public UInt16 e_cparhdr;
		public UInt16 e_minalloc;
		public UInt16 e_maxalloc;
		public UInt16 e_ss;
		public UInt16 e_sp;
		public UInt16 e_csum;
		public UInt16 e_ip;
		public UInt16 e_cs;
		public UInt16 e_lfarlc;
		public UInt16 e_ovno;
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
		public UInt16[] e_res1;
		public UInt16 e_oemid;
		public UInt16 e_oeminfo;
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
		public UInt16[] e_res2;
		public UInt32 e_lfanew;
	}
	[StructLayout(LayoutKind.Sequential)]
	public struct IMAGE_NT_HEADERS {
		public UInt32 Signature;
		public IMAGE_FILE_HEADER FileHeader;
		public IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
		public IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
	}
	[StructLayout(LayoutKind.Sequential)]
	public struct IMAGE_FILE_HEADER {
		public UInt16 Machine;
		public UInt16 NumberOfSections;
		public UInt32 TimeDateStamp;
		public UInt32 PointerToSymbolTable;
		public UInt32 NumberOfSymbols;
		public UInt16 SizeOfOptionalHeader;
		public UInt16 Characteristics;
	}
	[StructLayout(LayoutKind.Sequential)]
	public struct IMAGE_OPTIONAL_HEADER32 {
		public UInt16 Magic;
		public Byte MajorLinkerVersion;
		public Byte MinorLinkerVersion;
		public UInt32 SizeOfCode;
		public UInt32 SizeOfInitializedData;
		public UInt32 SizeOfUninitializedData;
		public UInt32 AddressOfEntryPoint;
		public UInt32 BaseOfCode;
		public UInt32 BaseOfData;
		public UInt32 ImageBase;
		public UInt32 SectionAlignment;
		public UInt32 FileAlignment;
		public UInt16 MajorOperatingSystemVersion;
		public UInt16 MinorOperatingSystemVersion;
		public UInt16 MajorImageVersion;
		public UInt16 MinorImageVersion;
		public UInt16 MajorSubsystemVersion;
		public UInt16 MinorSubsystemVersion;
		public UInt32 Win32VersionValue;
		public UInt32 SizeOfImage;
		public UInt32 SizeOfHeaders;
		public UInt32 CheckSum;
		public UInt16 Subsystem;
		public UInt16 DllCharacteristics;
		public UInt32 SizeOfStackReserve;
		public UInt32 SizeOfStackCommit;
		public UInt32 SizeOfHeapReserve;
		public UInt32 SizeOfHeapCommit;
		public UInt32 LoaderFlags;
		public UInt32 NumberOfRvaAndSizes;
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
		public IMAGE_DATA_DIRECTORY[] DataDirectory;
	}
	[StructLayout(LayoutKind.Sequential)]
	public struct IMAGE_OPTIONAL_HEADER64 {
		public UInt16 Magic;
		public Byte MajorLinkerVersion;
		public Byte MinorLinkerVersion;
		public UInt32 SizeOfCode;
		public UInt32 SizeOfInitializedData;
		public UInt32 SizeOfUninitializedData;
		public UInt32 AddressOfEntryPoint;
		public UInt32 BaseOfCode;
		public UInt64 ImageBase;
		public UInt32 SectionAlignment;
		public UInt32 FileAlignment;
		public UInt16 MajorOperatingSystemVersion;
		public UInt16 MinorOperatingSystemVersion;
		public UInt16 MajorImageVersion;
		public UInt16 MinorImageVersion;
		public UInt16 MajorSubsystemVersion;
		public UInt16 MinorSubsystemVersion;
		public UInt32 Win32VersionValue;
		public UInt32 SizeOfImage;
		public UInt32 SizeOfHeaders;
		public UInt32 CheckSum;
		public UInt16 Subsystem;
		public UInt16 DllCharacteristics;
		public UInt64 SizeOfStackReserve;
		public UInt64 SizeOfStackCommit;
		public UInt64 SizeOfHeapReserve;
		public UInt64 SizeOfHeapCommit;
		public UInt32 LoaderFlags;
		public UInt32 NumberOfRvaAndSizes;
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
		public IMAGE_DATA_DIRECTORY[] DataDirectory;
	}
	[StructLayout(LayoutKind.Sequential)]
	public struct IMAGE_DATA_DIRECTORY {
		public UInt32 VirtualAddress;
		public UInt32 Size;
	}
	[StructLayout(LayoutKind.Sequential)]
	public struct IMAGE_SECTION_HEADER {
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
		public string Name;
		public Misc Misc;
		public UInt32 VirtualAddress;
		public UInt32 SizeOfRawData;
		public UInt32 PointerToRawData;
		public UInt32 PointerToRelocations;
		public UInt32 PointerToLinenumbers;
		public UInt16 NumberOfRelocations;
		public UInt16 NumberOfLinenumbers;
		public UInt32 Characteristics;
	}
	[StructLayout(LayoutKind.Explicit)]
	public struct Misc {
		[FieldOffset(0)]
		public UInt32 PhysicalAddress;
		[FieldOffset(0)]
		public UInt32 VirtualSize;
	}
	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	public struct IMAGE_COR20_HEADER {
		public uint cb;
		public ushort MajorRuntimeVersion;
		public ushort MinorRuntimeVersion;
		public IMAGE_DATA_DIRECTORY MetaData;
		public uint Flags;
		public uint EntryPointToken;
		public IMAGE_DATA_DIRECTORY Resources;
		public IMAGE_DATA_DIRECTORY StrongNameSignature;
		public IMAGE_DATA_DIRECTORY CodeManagerTable;
		public IMAGE_DATA_DIRECTORY VTableFixups;
		public IMAGE_DATA_DIRECTORY ExportAddressTableJumps;
		public IMAGE_DATA_DIRECTORY ManagedNativeHeader;
	}
	private readonly IMAGE_DOS_HEADER _dosHeader;
	private IMAGE_NT_HEADERS _ntHeaders;
	private readonly IList<IMAGE_SECTION_HEADER> _sectionHeaders = new List<IMAGE_SECTION_HEADER>();
	public PEReader(BinaryReader reader) {
		reader.BaseStream.Seek(0, SeekOrigin.Begin);
		_dosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(reader);
		if (_dosHeader.e_magic != 0x5a4d)
		{
			throw new InvalidOperationException("File is not a portable executable.");
		}
		reader.BaseStream.Seek(_dosHeader.e_lfanew, SeekOrigin.Begin);
		_ntHeaders.Signature = MarshalBytesTo<UInt32>(reader);
		if (_ntHeaders.Signature != 0x4550)
		{
			throw new InvalidOperationException("Invalid portable executable signature in NT header.");
		}
		_ntHeaders.FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader);
		if (Is32bitAssembly())
		{
			Load32bitOptionalHeaders(reader);
		}
		else
		{
			Load64bitOptionalHeaders(reader);
		}
		foreach (IMAGE_SECTION_HEADER header in _sectionHeaders)
		{
			reader.BaseStream.Seek(header.PointerToRawData, SeekOrigin.Begin);
			byte[] sectiondata = reader.ReadBytes((int) header.SizeOfRawData);
		}
	}
	public IMAGE_DOS_HEADER GetDOSHeader() {
		return _dosHeader;
	}
	public UInt32 GetPESignature() {
		return _ntHeaders.Signature;
	}
	public IMAGE_FILE_HEADER GetFileHeader() {
		return _ntHeaders.FileHeader;
	}
	public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32() {
		return _ntHeaders.OptionalHeader32;
	}
	public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64() {
		return _ntHeaders.OptionalHeader64;
	}
	public IList<IMAGE_SECTION_HEADER> GetSectionHeaders() {
		return _sectionHeaders;
	}
	public bool Is32bitAssembly() {
		return ((_ntHeaders.FileHeader.Characteristics & 0x0100) == 0x0100);
	}
	private void Load64bitOptionalHeaders(BinaryReader reader) {
		_ntHeaders.OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader);
		if (_ntHeaders.OptionalHeader64.NumberOfRvaAndSizes != 0x10)
		{
			throw new InvalidOperationException("Invalid number of data directories in NT header");
		}
		for (int i = 0; i < _ntHeaders.OptionalHeader64.NumberOfRvaAndSizes; i++)
		{
			if (_ntHeaders.OptionalHeader64.DataDirectory[i].Size > 0)
			{
				_sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
			}
		}
	}
	private void Load32bitOptionalHeaders(BinaryReader reader) {
		_ntHeaders.OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader);
		if (_ntHeaders.OptionalHeader32.NumberOfRvaAndSizes != 0x10)
		{
			throw new InvalidOperationException("Invalid number of data directories in NT header");
		}
		for (int i = 0; i < _ntHeaders.OptionalHeader32.NumberOfRvaAndSizes; i++)
		{
			if (_ntHeaders.OptionalHeader32.DataDirectory[i].Size > 0)
			{
				_sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
			}
		}
	}
	private static T MarshalBytesTo<T>(BinaryReader reader) {
		byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
		GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
		T theStructure = (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
		handle.Free();
		return theStructure;
	}
	static void Main(string[] args) {
		Stream stream = new FileStream(args[0], FileMode.Open);
		PEReader pe = new PEReader(new BinaryReader(stream));
		IMAGE_DOS_HEADER dosh = pe.GetDOSHeader();
		Console.WriteLine("IMAGE_DOS_HEADER.e_magic: 0x" + dosh.e_magic.ToString("X"));
		Console.WriteLine("IMAGE_DOS_HEADER.e_lfanew: 0x" + dosh.e_lfanew.ToString("X"));
		Console.WriteLine("IMAGE_NT_HEADERS.Signature: 0x" + pe.GetPESignature().ToString("X"));
		IMAGE_FILE_HEADER flh = pe.GetFileHeader();
		Console.WriteLine("IMAGE_FILE_HEADER.Machine: 0x" + flh.Machine.ToString("X"));
		Console.WriteLine("IMAGE_FILE_HEADER.NumberOfSections: 0x" + flh.NumberOfSections.ToString("X"));
		Console.WriteLine("IMAGE_FILE_HEADER.Characteristics: 0x" + flh.Characteristics.ToString("X"));
		if ((flh.Characteristics & 0x0100) == 0x0100)
		{
			IMAGE_OPTIONAL_HEADER32 oph = pe.GetOptionalHeaders32();
			Console.WriteLine("IMAGE_OPTION_HEADER.Magic: 0x" + oph.Magic.ToString("X"));
			Console.WriteLine("IMAGE_OPTION_HEADER.MajorLinkerVersion: 0x" + oph.MajorLinkerVersion.ToString("X"));
			Console.WriteLine("IMAGE_OPTION_HEADER.MinorLinkerVersion: 0x" + oph.MinorLinkerVersion.ToString("X"));
			Console.WriteLine("IMAGE_OPTION_HEADER.SizeOfCode: 0x" + oph.SizeOfCode.ToString("X"));
			Console.WriteLine("IMAGE_OPTION_HEADER.FileAlignment: 0x" + oph.FileAlignment.ToString("X"));
			Console.WriteLine("IMAGE_OPTION_HEADER.NumberOfRvaAndSizes: 0x" + oph.NumberOfRvaAndSizes.ToString("X"));
		}
		else
		{
			IMAGE_OPTIONAL_HEADER64 oph = pe.GetOptionalHeaders64();
			Console.WriteLine("IMAGE_OPTION_HEADER.Magic: 0x" + oph.Magic.ToString("X"));
			Console.WriteLine("IMAGE_OPTION_HEADER.MajorLinkerVersion: 0x" + oph.MajorLinkerVersion.ToString("X"));
			Console.WriteLine("IMAGE_OPTION_HEADER.MinorLinkerVersion: 0x" + oph.MinorLinkerVersion.ToString("X"));
			Console.WriteLine("IMAGE_OPTION_HEADER.SizeOfCode: 0x" + oph.SizeOfCode.ToString("X"));
			Console.WriteLine("IMAGE_OPTION_HEADER.FileAlignment: 0x" + oph.FileAlignment.ToString("X"));
			Console.WriteLine("IMAGE_OPTION_HEADER.NumberOfRvaAndSizes: 0x" + oph.NumberOfRvaAndSizes.ToString("X"));
		}
		IList<IMAGE_SECTION_HEADER> sels = pe.GetSectionHeaders();
		foreach (IMAGE_SECTION_HEADER header in sels)
		{
			Console.WriteLine("IMAGE_SECTION_HEADER.Name: " + header.Name);
			Console.WriteLine("IMAGE_SECTION_HEADER.Misc.PhysicalAddress: " + header.Misc.PhysicalAddress);
			Console.WriteLine("IMAGE_SECTION_HEADER.PointerToRawData: " + header.PointerToRawData);
		}
		BinaryReader reader = new BinaryReader(stream);
		reader.BaseStream.Seek(520, SeekOrigin.Begin);
		IMAGE_COR20_HEADER cor20 = MarshalBytesTo<IMAGE_COR20_HEADER>(reader);
		Console.WriteLine("IMAGE_COR20_HEADER.MajorRuntimeVersion: " + cor20.MajorRuntimeVersion);
		Console.WriteLine("IMAGE_COR20_HEADER.MinorRuntimeVersion: " + cor20.MinorRuntimeVersion);
	}
}





実行結果

>pe4 dr0.exe
IMAGE_DOS_HEADER.e_magic: 0x5A4D
IMAGE_DOS_HEADER.e_lfanew: 0x80
IMAGE_NT_HEADERS.Signature: 0x4550
IMAGE_FILE_HEADER.Machine: 0x14C
IMAGE_FILE_HEADER.NumberOfSections: 0x3
IMAGE_FILE_HEADER.Characteristics: 0x102
IMAGE_OPTION_HEADER.Magic: 0x10B
IMAGE_OPTION_HEADER.MajorLinkerVersion: 0xB
IMAGE_OPTION_HEADER.MinorLinkerVersion: 0x0
IMAGE_OPTION_HEADER.SizeOfCode: 0x800
IMAGE_OPTION_HEADER.FileAlignment: 0x200
IMAGE_OPTION_HEADER.NumberOfRvaAndSizes: 0x10
IMAGE_SECTION_HEADER.Name: .text
IMAGE_SECTION_HEADER.Misc.PhysicalAddress: 1892
IMAGE_SECTION_HEADER.PointerToRawData: 512
IMAGE_SECTION_HEADER.Name: .rsrc
IMAGE_SECTION_HEADER.Misc.PhysicalAddress: 1224
IMAGE_SECTION_HEADER.PointerToRawData: 2560
IMAGE_SECTION_HEADER.Name: .reloc
IMAGE_SECTION_HEADER.Misc.PhysicalAddress: 12
IMAGE_SECTION_HEADER.PointerToRawData: 4096
IMAGE_SECTION_HEADER.Name:
IMAGE_SECTION_HEADER.Misc.PhysicalAddress: 0
IMAGE_SECTION_HEADER.PointerToRawData: 0
IMAGE_SECTION_HEADER.Name: 
IMAGE_SECTION_HEADER.Misc.PhysicalAddress: 0
IMAGE_SECTION_HEADER.PointerToRawData: 0
IMAGE_COR20_HEADER.MajorRuntimeVersion: 2
IMAGE_COR20_HEADER.MinorRuntimeVersion: 5

>

以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?