Buy Me a Coffee

Buy Me a Coffee!

Monday, February 6, 2017

Reading Structured Binary files in C#: Part 2

So, the first thing we need to read in is the MS-DOS 2.0 section.  The Back in Part 3 of the Dissection series we sort of skipped over the first part, but the program will need to read it fully.  The interesting part that didn't come into play is that the size of the section is fluid.  You can pack in a larger Stub program if you want by using a /stub option on the linker, but most people just don't.   I am going to cheat by pretending that they are all going to be the same so that I don't have to mess with anything of a variable size yet, but I am going to acknowledge that it is just that, a cheat.  So even though I acknowledge and read the Pointer to the PE Header, I am going to pretend it is always going to be 0x80.
Our first struct will be:

    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
    public struct MSDOS20Section
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x4)]
        public string Signature;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x37)]
        byte[] MSDOSEXEHeader;

        public Int32 OffsetToPEHeader;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x40)]
        byte[] MSDOSStub;

Notice the attributes on the struct and fields?  The attribute on the struct sets the type of layout which will be used when marshaling, character set, and the pack size.  Because we have set the LayoutKind to be Explicit, we must get to provide a FieldOffset along with the type and size.  For the initial pass, I am going to build out the structures in direct alignment with the PECOFF document.  As we move through the file, I believe we will start to consolidate or encapsulate some of the smaller sections into larger ones to keep our code clean.
Speaking of clean, we should override ToString on each of our structs to make dumping them to the console window as we build them out.  Eventually we will want a better/sexy output that included colors and such, but for now we just need the information out to match the dissection results.  Our initial output is an underwhelming:

Signature: MZ?
OffsetToPEHeader: 80

Press return to exit

That is good for now, we will conquer the COFF header next.