The COFF Optional Header is not a fixed size, so we use the information from the previous section to determine the size. All three images had the same SizeOfOptionalHeader data, 0x00E0 or 244 bytes. We start just where we left off, in the second half of the 00000090 row which are different for each of the binary files under investigation:
MS Command Line, .NET 2.0:
00000090 00 00 00 00 E0 00 02 01 0B 01 08 00 00 04 00 00 ····à···········
VS 2015, .NET 2.0
00000090 00 00 00 00 E0 00 22 00 0B 01 30 00 00 08 00 00 ····à·"···0·····
Xamarin Studio, .NET 2.0
00000090 00 00 00 00 E0 00 02 01 0B 01 08 00 00 06 00 00 ····à···········
The first data halfword (two bytes) is the PE Format, and all three are the same 0x0B 0x01 or 0x010B which we look up in the table given in the super Microsoft Portable Executable and Common ObjectFile Format Specification: Revision 10:
Magic number
|
PE format
|
0x10b
|
PE32
|
0x20b
|
PE32+
|
So we have a PE32 format for all three files. The next part depends on what type of image. Since we are looking at a PE32 image, the offset to the standard fields is 0, so the next halfword is the start of them. Here are the standard fields from the MS COFF doc:
Offset
|
Size
|
Field
|
Description
|
0
|
2
|
Magic
|
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.
|
2
|
1
|
MajorLinkerVersion
|
The
linker major version number.
|
3
|
1
|
MinorLinkerVersion
|
The
linker minor version number.
|
4
|
4
|
SizeOfCode
|
The
size of the code (text) section, or the sum of all code sections if there are
multiple sections.
|
8
|
4
|
SizeOfInitializedData
|
The
size of the initialized data section, or the sum of all such sections if
there are multiple data sections.
|
12
|
4
|
SizeOfUninitializedData
|
The
size of the uninitialized data section (BSS), or the sum of all such sections
if there are multiple BSS sections.
|
16
|
4
|
AddressOfEntryPoint
|
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.
|
20
|
4
|
BaseOfCode
|
The
address that is relative to the image base of the beginning-of-code section
when it is loaded into memory.
|
So, the next byte after the Magic field is the MajorLinkerVersion which is 0x08 for both the MS Command Line and the Xamarin Studio versions and 0x30 for the VS 2015 version. The MinorLinkerVersion is 0x00 for all three. What this means, is that the linker used is definitely different between the VS 2015 file and the other two. We don't know for sure that the two with the same version numbers used the same linker (and they probably didn't), but we know they didn't use the same one as VS 2015. Does it matter? It shouldn't, but linkers are code and code almost always has bugs of some type.
Next, to finish out the line we have the SizeOfCode which differs in all three. Not entirely surprising, I guess, but the Program of all three decompile to the same IL in JustDecompile. The differences must be around the edges. Something to look into in another post. For now, let's finish up the section by moving to the next line from the file:
MS Command Line, .NET 2.0:
000000A0 00 06 00 00 00 00 00 00 AE 23 00 00 00 20 00 00 ········r#··· ··
VS 2015, .NET 2.0
000000A0 00 0A 00 00 00 00 00 00 AA 27 00 00 00 20 00 00 ········ª'··· ··
Xamarin Studio, .NET 2.0
000000A0 00 06 00 00 00 00 00 00 FE 24 00 00 00 20 00 00 ········_$··· ··
As you can see, they all differ. The next word (4 bytes) is the SizeOfInitializedData which is the same for the Command Line and Xamarin. We will need to look back on this when we get to those sections of the files. Next we have the SizeOfUnitializedData which is 0 for all three. Next, we have the AddressOfEntryPoint which is different for all three, not surprising given the previous size differences we found. The last word on this line is the BaseOfCode which is the same for all three.
We need the first word from the next line to finish out the section with the BaseOfData:
which is only found in the PE32 image type. All three are the same, so I will just end by showing the line from the Command line version:
We need the first word from the next line to finish out the section with the BaseOfData:
Offset
|
Size
|
Field
|
Description
|
24
|
4
|
BaseOfData
|
The
address that is relative to the image base of the beginning-of-data section when
it is loaded into memory.
|
which is only found in the PE32 image type. All three are the same, so I will just end by showing the line from the Command line version:
MS Command Line, .NET 2.0:
000000B0 00 40 00 00 00 00 40 00 00 20 00 00 00 02 00 00 ·@····@·· ······
Till next time, happy digging!