Tuesday, January 10, 2017

Dissecting C# Executables: Part 7

To begin, let me share the full hex dumps of the Xamarin, Visual Studio, and Command Line compiled programs that I am using.  That will make it easier to play along at home.

Now, let's get started with the Section Table as defined in Microsoft Portable Executable and Common ObjectFile Format Specification: Revision 10:

Offset
Size
Field
Description
  0
8
Name
An 8-byte, null-padded UTF-8 encoded string. If the string is exactly 8 characters long, there is no terminating null. For longer names, this field contains a slash (/) that is followed by an ASCII representation of a decimal number that is an offset into the string table. Executable images do not use a string table and do not support section names longer than 8 characters. Long names in object files are truncated if they are emitted to an executable file.
  8
4
VirtualSize
The total size of the section when loaded into memory. If this value is greater than SizeOfRawData, the section is zero-padded. This field is valid only for executable images and should be set to zero for object files.
12
4
VirtualAddress
For executable images, the address of the first byte of the section relative to the image base when the section is loaded into memory. 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.
16
4
SizeOfRawData
The size of the section (for object files) or the size of the initialized data on disk (for image files). For executable images, this must be a multiple of FileAlignment from the optional header. If this is less than VirtualSize, the remainder of the section is zero-filled. Because the SizeOfRawData field is rounded but the VirtualSize field is not, it is possible for SizeOfRawData to be greater than VirtualSize as well. When a section contains only uninitialized data, this field should be zero.
20
4
PointerToRawData
The file pointer to the first page of the section 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 4‑byte boundary for best performance. When a section contains only uninitialized data, this field should be zero.
24
4
PointerToRelocations
The file pointer to the beginning of relocation entries for the section. This is set to zero for executable images or if there are no relocations.
28
4
PointerToLinenumbers
The file pointer to the beginning of line-number entries for the section. This is set to zero if there are no COFF line numbers. This value should be zero for an image because COFF debugging information is deprecated.
32
2
NumberOfRelocations
The number of relocation entries for the section. This is set to zero for executable images.
34
2
NumberOfLinenumbers
The number of line-number entries for the section. This value should be zero for an image because COFF debugging information is deprecated.
36
4
Characteristics
The flags that describe the characteristics of the section. For more information, see section 4.1, “Section Flags.”

Each Section Header shares the same format, so we will be seeing 16 Sections since the NumberOfRvaAndSizes was 0x00000010 from way back in Part 5.  Actually, I cheated and looked ahead and found out that we don't have that many sections.  We will discuss the difference between what the earlier number says and what is actually in the file when we get to it.  Let's go ahead and tackle the first one and see what is inside it.

Let's start with the Visual Studio version this time:

D:\Source\HelloWorld\CommandLine>PrintBinaryFile.exe HelloWorld_VS_2.0.exe
00000170   00 00 00 00 00 00 00 00  2E 74 65 78 74 00 00 00   ········.text···
00000180   B0 07 00 00 00 20 00 00  00 08 00 00 00 02 00 00   °···· ··········
00000190   00 00 00 00 00 00 00 00  00 00 00 00 20 00 00 60   ············ ··`

The Name is given as a word storing a UTF-8 encoded string which may or may not have a terminating null.  The size is 8 bytes, and each byte is a character, so our Name value is .text for this Section Header.  The final three bytes of the field are not used because they are null.  Next is the VirtualSize which is a half-word with the value 0x000007B0 or 1968.  Next is the VirtualAddress half-word which is 0x00002000.  That is followed by another half-word holding the SizeOfRawData holding the value of 0x00000800 which must be a multiple of the FileAlignment value from Part 5 which was 0x00000200.  Next is the PointerToRawData half-word which is 0x00000200 and gives us the offset to the data of the section.  The next half-word contains the PointerToRelocations which is 0x00 because this file doesn't contain any relocations.  The next half-word contains 0x00 for the PointerToLinenumbers because COFF debugging (as noted before) is deprecated.  The NumberOfRelocations is a two bytes containing 0x00 because there are no relocations for executable images.  The NumberOfLinenumbers is another two bytes with 0x00 because...deprecated.  The final half-word is the Characteristics which is a flag field containing 0x60000020 which decodes to IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ using the following massive table:

Flag
Value
Description

0x00000000
Reserved for future use.

0x00000001
Reserved for future use.

0x00000002
Reserved for future use.

0x00000004
Reserved for future use.
IMAGE_SCN_TYPE_NO_PAD
0x00000008
The section should not be padded to the next boundary. This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES. This is valid only for object files.

0x00000010
Reserved for future use.
IMAGE_SCN_CNT_CODE
0x00000020
The section contains executable code.
IMAGE_SCN_CNT_INITIALIZED_DATA
0x00000040
The section contains initialized data.
IMAGE_SCN_CNT_UNINITIALIZED_ DATA
0x00000080
The section contains uninitialized data.
IMAGE_SCN_LNK_OTHER
0x00000100
Reserved for future use.
IMAGE_SCN_LNK_INFO
0x00000200
The section contains comments or other information. The .drectve section has this type. This is valid for object files only.

0x00000400
Reserved for future use.
IMAGE_SCN_LNK_REMOVE
0x00000800
The section will not become part of the image. This is valid only for object files.
IMAGE_SCN_LNK_COMDAT
0x00001000
The section contains COMDAT data. For more information, see section 5.5.6, “COMDAT Sections (Object Only).” This is valid only for object files.
IMAGE_SCN_GPREL
0x00008000
The section contains data referenced through the global pointer (GP).
IMAGE_SCN_MEM_PURGEABLE
0x00020000
Reserved for future use.
IMAGE_SCN_MEM_16BIT
0x00020000
Reserved for future use.
IMAGE_SCN_MEM_LOCKED
0x00040000
Reserved for future use.
IMAGE_SCN_MEM_PRELOAD
0x00080000
Reserved for future use.
IMAGE_SCN_ALIGN_1BYTES
0x00100000
Align data on a 1-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_2BYTES
0x00200000
Align data on a 2-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_4BYTES
0x00300000
Align data on a 4-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_8BYTES
0x00400000
Align data on an 8-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_16BYTES
0x00500000
Align data on a 16-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_32BYTES
0x00600000
Align data on a 32-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_64BYTES
0x00700000
Align data on a 64-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_128BYTES
0x00800000
Align data on a 128-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_256BYTES
0x00900000
Align data on a 256-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_512BYTES
0x00A00000
Align data on a 512-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_1024BYTES
0x00B00000
Align data on a 1024-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_2048BYTES
0x00C00000
Align data on a 2048-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_4096BYTES
0x00D00000
Align data on a 4096-byte boundary. Valid only for object files.
IMAGE_SCN_ALIGN_8192BYTES
0x00E00000
Align data on an 8192-byte boundary. Valid only for object files.
IMAGE_SCN_LNK_NRELOC_OVFL
0x01000000
The section contains extended relocations.
IMAGE_SCN_MEM_DISCARDABLE
0x02000000
The section can be discarded as needed.
IMAGE_SCN_MEM_NOT_CACHED
0x04000000
The section cannot be cached.
IMAGE_SCN_MEM_NOT_PAGED
0x08000000
The section is not pageable.
IMAGE_SCN_MEM_SHARED
0x10000000
The section can be shared in memory.
IMAGE_SCN_MEM_EXECUTE
0x20000000
The section can be executed as code.
IMAGE_SCN_MEM_READ
0x40000000
The section can be read.
IMAGE_SCN_MEM_WRITE
0x80000000
The section can be written to.

The Xamarin:

D:\Source\HelloWorld\CommandLine>PrintBinaryFile.exe HelloWorld_Xamarin_2.0.exe
00000170   00 00 00 00 00 00 00 00  2E 74 65 78 74 00 00 00   ········.text···
00000180   04 05 00 00 00 20 00 00  00 06 00 00 00 02 00 00   ····· ··········
00000190   00 00 00 00 00 00 00 00  00 00 00 00 20 00 00 60   ············ ··`

and Command Line:

D:\Source\HelloWorld\CommandLine>PrintBinaryFile.exe HelloWorld_CSC_2.0.exe
00000170   00 00 00 00 00 00 00 00  2E 74 65 78 74 00 00 00   ········.text···
00000180   B4 03 00 00 00 20 00 00  00 04 00 00 00 02 00 00   '···· ··········
00000190   00 00 00 00 00 00 00 00  00 00 00 00 20 00 00 60   ············ ··`

images differ only slightly in this section.  Let me copy the Visual Studio section here as well to make it easier to compare them:

D:\Source\HelloWorld\CommandLine>PrintBinaryFile.exe HelloWorld_VS_2.0.exe
00000170   00 00 00 00 00 00 00 00  2E 74 65 78 74 00 00 00   ········.text···
00000180   B0 07 00 00 00 20 00 00  00 08 00 00 00 02 00 00   °···· ··········
00000190   00 00 00 00 00 00 00 00  00 00 00 00 20 00 00 60   ············ ··`

Note the differences in Italics.  They are, respectively, the VirtualSize and the SizeOfRawData.  It makes perfect sense for these two to be connected, and given the different file sizes we knew that the extra bytes had to be somewhere.  The VS is the largest, with a size of 0x00000800 followed by the Xamarin at 0x00000600 with the Command Line being the smallest at 0x00000400.  What do you think is in there?  Any predictions?

Enough for tonight.  We will tackle another Section Header tomorrow.  Keep reading, and comment with suggestions or thoughts.


Part 1
Part 2
Part 3
Part 4
Part 5
Part 6
Part 7
Part 8
Part 9

No comments:

Post a Comment