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:
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
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 ············ ··`
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 ············ ··`
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