using System.IO; using BurnOutSharp.Models.PortableExecutable; namespace BurnOutSharp.Builder { // TODO: Make Stream Data rely on Byte Data public static class PortableExecutable { #region Byte Data /// /// Parse a byte array into a Portable Executable /// /// Byte array to parse /// Offset into the byte array /// Filled executable on success, null on error public static Executable ParseExecutable(byte[] data, int offset) { // If the data is invalid if (data == null) return null; // If the offset is out of bounds if (offset < 0 || offset >= data.Length) return null; // Cache the current offset int initialOffset = offset; // Create a new executable to fill var executable = new Executable(); #region MS-DOS Stub // Parse the MS-DOS stub var stub = MSDOS.ParseExecutable(data, offset); if (stub?.Header == null || stub.Header.NewExeHeaderAddr == 0) return null; // Set the MS-DOS stub executable.Stub = stub; #endregion #region Signature offset = (int)(initialOffset + stub.Header.NewExeHeaderAddr); executable.Signature = new byte[4]; for (int i = 0; i < executable.Signature.Length; i++) { executable.Signature[i] = data.ReadByte(ref offset); } if (executable.Signature[0] != 'P' || executable.Signature[1] != 'E' || executable.Signature[2] != '\0' || executable.Signature[3] != '\0') return null; #endregion // TODO: Implement PE parsing return null; } /// /// Parse a byte array into a Portable Executable COFF file header /// /// Byte array to parse /// Offset into the byte array /// Filled COFF file header on success, null on error private static COFFFileHeader ParseCOFFFileHeader(byte[] data, int offset) { // TODO: Implement PE COFF file header parsing return null; } #endregion #region Stream Data /// /// Parse a Stream into a Portable Executable /// /// Stream to parse /// Filled executable on success, null on error public static Executable ParseExecutable(Stream data) { // If the data is invalid if (data == null) return null; // If the offset is out of bounds if (data.Position < 0 || data.Position >= data.Length) return null; // Cache the current offset int initialOffset = (int)data.Position; // Create a new executable to fill var executable = new Executable(); #region MS-DOS Stub // Parse the MS-DOS stub var stub = MSDOS.ParseExecutable(data); if (stub?.Header == null || stub.Header.NewExeHeaderAddr == 0) return null; // Set the MS-DOS stub executable.Stub = stub; #endregion #region Signature data.Seek(initialOffset + stub.Header.NewExeHeaderAddr, SeekOrigin.Begin); executable.Signature = new byte[4]; for (int i = 0; i < executable.Signature.Length; i++) { executable.Signature[i] = data.ReadByteValue(); } if (executable.Signature[0] != 'P' || executable.Signature[1] != 'E' || executable.Signature[2] != '\0' || executable.Signature[3] != '\0') return null; #endregion // TODO: Implement PE parsing return null; } /// /// Parse a Stream into a Portable Executable COFF file header /// /// Stream to parse /// Filled executable header on success, null on error private static COFFFileHeader ParseCOFFFileHeader(Stream data) { // TODO: Implement PE COFF file header parsing return null; } #endregion } }