· 9 years ago · Oct 05, 2016, 11:52 AM
1$Id: pe.txt,v 1.9 1999/03/20 23:55:09 LUEVELSMEYER Exp $
2
3
4
5The PE file format
6==================
7
8
9
10Preface
11-------
12
13The PE ("portable executable") file format is the format of executable
14binaries (DLLs and programs) for MS windows NT, windows 95 and
15win32s; in windows NT, the drivers are in this format, too.
16It can also be used for object files and libraries.
17
18The format is designed by Microsoft and standardized by the TIS (tool
19interface standard) Committee (Microsoft, Intel, Borland, Watcom, IBM
20and others) in 1993, apparently based on a good knowledge of COFF, the
21"common object file format" used for object files and executables on
22several UNIXes and on VMS.
23
24The win32 SDK includes a header file <winnt.h> containing #defines and
25typedefs for the PE-format. I will mention the struct-member-names and
26#defines as we go.
27
28You may also find the DLL "imagehelp.dll" to be helpful. It is part of
29windows NT, but documentation is scarce. Some of its functions are
30described in the "Developer Network".
31
32
33
34General Layout
35--------------
36
37At the start of a PE file we find an MS-DOS executable ("stub"); this
38makes any PE file a valid MS-DOS executable.
39
40After the DOS-stub there is a 32-bit-signature with the magic number
410x00004550 (IMAGE_NT_SIGNATURE).
42
43Then there is a file header (in the COFF-format) that tells on which
44machine the binary is supposed to run, how many sections are in it, the
45time it was linked, whether it is an executable or a DLL and so on. (The
46difference between executable and DLL in this context is: a DLL can not
47be started but only be used by another binary, and a binary cannot link
48to an executable).
49
50After that, we have an optional header (it is always there but still
51called "optional" - COFF uses an "optional header" for libraries but not
52for objects, that's why it is called "optional"). This tells us more
53about how the binary should be loaded: The starting address, the amount
54of stack to reserve, the size of the data segment etc..
55
56An interesting part of the optional header is the trailing array of
57'data directories'; these directories contain pointers to data in the
58'sections'. If, for example, the binary has an export directory, you
59will find a pointer to that directory in the array member
60IMAGE_DIRECTORY_ENTRY_EXPORT, and it will point into one of the
61sections.
62
63Following the headers we find the 'sections', introduced by the 'section
64headers'. Essentially, the sections' contents is what you really need to
65execute a program, and all the header and directory stuff is just there
66to help you find it.
67Each section has some flags about alignment, what kind of data it
68contains ("initialized data" and so on), whether it can be shared etc.,
69and the data itself. Most, but not all, sections contain one or more
70directories referenced through the entries of the optional header's
71"data directory" array, like the directory of exported functions or the
72directory of base relocations. Directoryless types of contents are, for
73example, "executable code" or "initialized data".
74
75 +-------------------+
76 | DOS-stub |
77 +-------------------+
78 | file-header |
79 +-------------------+
80 | optional header |
81 |- - - - - - - - - -|
82 | |
83 | data directories |
84 | |
85 +-------------------+
86 | |
87 | section headers |
88 | |
89 +-------------------+
90 | |
91 | section 1 |
92 | |
93 +-------------------+
94 | |
95 | section 2 |
96 | |
97 +-------------------+
98 | |
99 | ... |
100 | |
101 +-------------------+
102 | |
103 | section n |
104 | |
105 +-------------------+
106
107
108
109DOS-stub and Signature
110----------------------
111
112The concept of a DOS-stub is well-known from the 16-bit-windows-
113executables (which were in the "NE" format). The stub is used for
114OS/2-executables, self-extracting archives and other applications, too.
115For PE-files, it is a MS-DOS 2.0 compatible executable that almost
116always consists of about 100 bytes that output an error message such as
117"this program needs windows NT".
118You recognize a DOS-stub by validating the DOS-header, being a
119struct IMAGE_DOS_HEADER. The first 2 bytes should be the sequence "MZ"
120(there is a #define IMAGE_DOS_SIGNATURE for this WORD).
121You distinguish a PE binary from other stubbed binaries by the trailing
122signature, which you find at the offset given by the header member
123'e_lfanew' (which is 32 bits long beginning at byte offset 60). For OS/2
124and windows binaries, the signature is a 16-bit-word; for PE files, it
125is a 32-bit-longword aligned at a 8-byte-boundary and having the value
126IMAGE_NT_SIGNATURE #defined to be 0x00004550.
127
128
129
130File Header
131-----------
132
133To get to the IMAGE_FILE_HEADER, validate the "MZ" of the DOS-header
134(1st 2 bytes), then find the 'e_lfanew' member of the DOS-stub's header
135and skip that many bytes from the beginning of the file. Verify the
136signature you will find there. The file header, a struct
137IMAGE_FILE_HEADER, begins immediatly after it; the members are described
138top to bottom.
139
140The first member is the 'Machine', a 16-bit-value indicating the system
141the binary is intended to run on. Known legal values are
142
143 IMAGE_FILE_MACHINE_I386 (0x14c)
144 for Intel 80386 processor or better
145
146 0x014d
147 for Intel 80486 processor or better
148
149 0x014e
150 for Intel Pentium processor or better
151
152 0x0160
153 for R3000 (MIPS) processor, big endian
154
155 IMAGE_FILE_MACHINE_R3000 (0x162)
156 for R3000 (MIPS) processor, little endian
157
158 IMAGE_FILE_MACHINE_R4000 (0x166)
159 for R4000 (MIPS) processor, little endian
160
161 IMAGE_FILE_MACHINE_R10000 (0x168)
162 for R10000 (MIPS) processor, little endian
163
164 IMAGE_FILE_MACHINE_ALPHA (0x184)
165 for DEC Alpha AXP processor
166
167 IMAGE_FILE_MACHINE_POWERPC (0x1F0)
168 for IBM Power PC, little endian
169
170Then we have the 'NumberOfSections', a 16-bit-value. It is the number of
171sections that follow the headers. We will discuss the sections later.
172
173Next is a timestamp 'TimeDateStamp' (32 bit), giving the time the file
174was created. You can distinguish several versions of the same file by
175this value, even if the "official" version number was not altered. (The
176format of the timestamp is not documented except that it should be
177somewhat unique among versions of the same file, but apparently it is
178'seconds since January 1 1970 00:00:00' in UTC - the format used by most
179C compilers for the time_t.)
180This timestamp is used for the binding of import directories, which will
181be discussed later.
182Warning: some linkers tend to set this timestamp to absurd values which
183are not the time of linking in time_t format as described.
184
185The members 'PointerToSymbolTable' and 'NumberOfSymbols' (both 32 bit)
186are used for debugging information. I don't know how to decipher them,
187and I've found the pointer to be always 0.
188
189'SizeOfOptionalHeader' (16 bit) is simply sizeof(IMAGE_OPTIONAL_HEADER).
190You can use it to validate the correctness of the PE file's structure.
191
192'Characteristics' is 16 bits and consists of a collection of flags, most
193of them being valid only for object files and libraries:
194
195 Bit 0 (IMAGE_FILE_RELOCS_STRIPPED) is set if there is no relocation
196 information in the file. This refers to relocation information per
197 section in the sections themselves; it is not used for executables,
198 which have relocation information in the 'base relocation' directory
199 described below.
200
201 Bit 1 (IMAGE_FILE_EXECUTABLE_IMAGE) is set if the file is
202 executable, i.e. it is not an object file or a library. This flag
203 may also be set if the linker attempted to create an executable but
204 failed for some reason, and keeps the image in order to do e.g.
205 incremental linking the next time.
206
207 Bit 2 (IMAGE_FILE_LINE_NUMS_STRIPPED) is set if the line number
208 information is stripped; this is not used for executable files.
209
210 Bit 3 (IMAGE_FILE_LOCAL_SYMS_STRIPPED) is set if there is no
211 information about local symbols in the file (this is not used
212 for executable files).
213
214 Bit 4 (IMAGE_FILE_AGGRESIVE_WS_TRIM) is set if the operating system
215 is supposed to trim the working set of the running process (the
216 amount of RAM the process uses) aggressivly by paging it out. This
217 should be set if it is a demon-like application that waits most of
218 the time and only wakes up once a day, or the like.
219
220 Bits 7 (IMAGE_FILE_BYTES_REVERSED_LO) and 15
221 (IMAGE_FILE_BYTES_REVERSED_HI) are set if the endianess of the file is
222 not what the machine would expect, so it must swap bytes before
223 reading. This is unreliable for executable files (the OS expects
224 executables to be correctly byte-ordered).
225
226 Bit 8 (IMAGE_FILE_32BIT_MACHINE) is set if the machine is expected
227 to be a 32 bit machine. This is always set for current
228 implementations; NT5 may work differently.
229
230 Bit 9 (IMAGE_FILE_DEBUG_STRIPPED) is set if there is no debugging
231 information in the file. This is unused for executable files.
232 According to other information ([6]), this bit is called "fixed" and
233 is set if the image can only run if it is loaded at the preferred
234 load address (i.e. it is not relocatable).
235
236 Bit 10 (IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP) is set if the application
237 may not run from a removable medium such as a floppy or a CD-ROM. In
238 this case, the operating system is advised to copy the file to the
239 swapfile and execute it from there.
240
241 Bit 11 (IMAGE_FILE_NET_RUN_FROM_SWAP) is set if the application may
242 not run from the network. In this case, the operating system is
243 advised to copy the file to the swapfile and execute it from there.
244
245 Bit 12 (IMAGE_FILE_SYSTEM) is set if the file is a system file such
246 as a driver. This is unused for executable files; it is also not
247 used in all the NT drivers I inspected.
248
249 Bit 13 (IMAGE_FILE_DLL) is set if the file is a DLL.
250
251 Bit 14 (IMAGE_FILE_UP_SYSTEM_ONLY) is set if the file is not
252 designed to run on multiprocessor systems (that is, it will crash
253 there because it relies in some way on exactly one processor).
254
255
256
257Relative Virtual Addresses
258--------------------------
259
260The PE format makes heavy use of so-called RVAs. An RVA, aka "relative
261virtual address", is used to describe a memory address if you don't know
262the base address. It is the value you need to add to the base address to
263get the linear address.
264The base address is the address the PE image is loaded to, and may vary
265from one invocation to the next.
266
267Example: suppose an executable file is loaded to address 0x400000 and
268execution starts at RVA 0x1560. The effective execution start will then
269be at the address 0x401560. If the executable were loaded to 0x100000,
270the execution start would be 0x101560.
271
272Things become complicated because the parts of the PE-file (the
273sections) are not necessarily aligned the same way the loaded image is.
274For example, the sections of the file are often aligned to
275512-byte-borders, but the loaded image is perhaps aligned to
2764096-byte-borders. See 'SectionAlignment' and 'FileAlignment' below.
277
278So to find a piece of information in a PE-file for a specific RVA,
279you must calculate the offsets as if the file were loaded, but skip
280according to the file-offsets.
281As an example, suppose you knew the execution starts at RVA 0x1560, and
282want to diassemble the code starting there. To find the address in the
283file, you will have to find out that sections in RAM are aligned to 4096
284bytes and the ".code"-section starts at RVA 0x1000 in RAM and is 16384
285bytes long; then you know that RVA 0x1560 is at offset 0x560 in that
286section. Find out that the sections are aligned to 512-byte-borders in
287the file and that ".code" begins at offset 0x800 in the file, and you
288know that the code execution start is at byte 0x800+0x560=0xd60 in the
289file.
290
291Then you disassemble and find an access to a variable at the linear
292address 0x1051d0. The linear address will be relocated upon loading the
293binary and is given on the assumption that the preferred load address is
294used. You find out that the preferred load address is 0x100000, so we
295are dealing with RVA 0x51d0. This is in the data section which starts at
296RVA 0x5000 and is 2048 bytes long. It begins at file offset 0x4800.
297Hence. the veriable can be found at file offset
2980x4800+0x51d0-0x5000=0x49d0.
299
300
301Optional Header
302---------------
303
304Immediatly following the file header is the IMAGE_OPTIONAL_HEADER
305(which, in spite of the name, is always there). It contains
306information about how to treat the PE-file exactly. We'll also have the
307members from top to bottom.
308
309The first 16-bit-word is 'Magic' and has, as far as I looked into
310PE-files, always the value 0x010b.
311
312The next 2 bytes are the version of the linker ('MajorLinkerVersion' and
313'MinorLinkerVersion') that produced the file. These values, again, are
314unreliable and do not always reflect the linker version properly.
315(Several linkers simply don't set this field.)
316And, coming to think about it, what good is the version if you have got
317no idea *which* linker was used?
318
319The next 3 longwords (32 bit each) are intended to be the size of the
320executable code ('SizeOfCode'), the size of the initialized data
321('SizeOfInitializedData', the so-called "data segment"), and the size of
322the uninitialized data ('SizeOfUninitializedData', the so-called "bss
323segment"). These values are, again, unreliable (e.g. the data segment
324may actually be split into several segments by the compiler or linker),
325and you get better sizes by inspecting the 'sections' that follow the
326optional header.
327
328Next is a 32-bit-value that is a RVA. This RVA is the offset to the
329codes's entry point ('AddressOfEntryPoint').
330Execution starts here; it is e.g. the address of a DLL's LibMain() or a
331program's startup code (which will in turn call main()) or a driver's
332DriverEntry(). If you dare to load the image "by hand", you call this
333address to start the process after you have done all the fixups and the
334relocations.
335
336The next 2 32-bit-values are the offsets to the executable code
337('BaseOfCode') and the initialized data ('BaseOfData'), both of them
338RVAs again, and both of them being of little interest because you get
339more reliable information by inspecting the 'sections' that follow the
340headers.
341There is no offset to the uninitialized data because, being
342uninitialized, there is little point in providing this data in the
343image.
344
345The next entry is a 32-bit-value giving the preferred (linear) load
346address ('ImageBase') of the entire binary, including all headers. This
347is the address (always a multiple of 64 KB) the file has been relocated
348to by the linker; if the binary can in fact be loaded to that address,
349the loader doesn't need to relocate the file again, which is a win in
350loading time.
351The preferred load address can not be used if another image has already
352been loaded to that address (an "address clash", which happens quite
353often if you load several DLLs that are all relocated to the linker's
354default), or the memory in question has been used for other purposes
355(stack, malloc(), uninitialized data, whatever). In these cases, the
356image must be loaded to some other address and it needs to be relocated
357(see 'relocation directory' below). This has further consequences if the
358image is a DLL, because then the "bound imports" are no longer valid,
359and fixups have to be made to the binary that uses the DLL - see 'import
360directory' below.
361
362The next 2 32-bit-values are the alignments of the PE-file's sections in
363RAM ('SectionAlignment', when the image has been loaded) and in the file
364('FileAlignment'). Usually both values are 32, or FileAlignment is 512
365and SectionAlignment is 4096. Sections will be discussed later.
366
367The next 2 16-bit-words are the expected operating system version
368('MajorOperatingSystemVersion' and 'MinorOperatingSystemVersion' [they
369_do_ like self-documenting names at MS]). This version information is
370intended to be the operating system's (e.g. NT or Win95) version, as
371opposed to the subsystem's version (e.g. Win32); it is often not
372supplied, or wrong supplied. The loader doesn't use it, apparently.
373
374The next 2 16-bit-words are the binary's version, ('MajorImageVersion' and
375'MinorImageVersion'). Many linkers don't set this information correctly
376and many programmers don't bother to supply it, so it is better to rely
377on the version-resource if one exists.
378
379The next 2 16-bit-words are the expected subsystem version
380('MajorSubsystemVersion' and 'MinorSubsystemVersion'). This should be
381the Win32 version or the POSIX version, because 16-bit-programs or
382OS/2-programs won't be in PE-format, obviously.
383This subsystem version should be supplied correctly, because it *is*
384checked and used:
385If the application is a Win32-GUI-application and runs on NT4, and the
386subsystem version is *not* 4.0, the dialogs won't be 3D-style and
387certain other features will also work "old-style" because the
388application expects to run on NT 3.51, which had the program manager
389instead of explorer and so on, and NT 4.0 will mimic that behaviour as
390faithfully as possible.
391
392Then we have a 'Win32VersionValue' of 32 bits. I don't know what it is
393good for. It has been 0 in all the PE files that I inspected.
394
395Next is a 32-bits-value giving the amount of memory the image will need,
396in bytes ('SizeOfImage'). It is the sum of all headers' and sections'
397lengths if aligned to 'SectionAlignment'. It is a hint to the loader how
398many pages it will need in order to load the image.
399
400The next thing is a 32-bit-value giving the total length of all headers
401including the data directories and the section headers
402('SizeOfHeaders'). It is at the same time the offset from the beginning
403of the file to the first section's raw data.
404
405Then we have got a 32-bit-checksum ('CheckSum'). This checksum is, for
406current versions of NT, only checked if the image is a NT-driver (the
407driver will fail to load if the checksum isn't correct). For other
408binary types, the checksum need not be supplied and may be 0.
409The algorithm to compute the checksum is property of Microsoft, and they
410won't tell you. However, several tools of the Win32 SDK will compute
411and/or patch a valid checksum, and the function CheckSumMappedFile() in
412the imagehelp.dll will do so too.
413The checksum is supposed to prevent loading of damaged binaries that
414would crash anyway - and a crashing driver would result in a BSOD, so
415it is better not to load it at all.
416
417Then there is a 16-bit-word 'Subsystem' that tells in which of the
418NT-subsystems the image runs:
419
420 IMAGE_SUBSYSTEM_NATIVE (1)
421 The binary doesn't need a subsystem. This is used for drivers.
422
423 IMAGE_SUBSYSTEM_WINDOWS_GUI (2)
424 The image is a Win32 graphical binary. (It can still open a
425 console with AllocConsole() but won't get one automatically at
426 startup.)
427
428 IMAGE_SUBSYSTEM_WINDOWS_CUI (3)
429 The binary is a Win32 console binary. (It will get a console
430 per default at startup, or inherit the parent's console.)
431
432 IMAGE_SUBSYSTEM_OS2_CUI (5)
433 The binary is a OS/2 console binary. (OS/2 binaries will be in
434 OS/2 format, so this value will seldom be used in a PE file.)
435
436 IMAGE_SUBSYSTEM_POSIX_CUI (7)
437 The binary uses the POSIX console subsystem.
438
439Windows 95 binaries will always use the Win32 subsystem, so the only
440legal values for these binaries are 2 and 3; I don't know if "native"
441binaries on windows 95 are possible.
442
443The next thing is a 16-bit-value that tells, if the image is a DLL, when
444to call the DLL's entry point ('DllCharacteristics'). This seems not to
445be used; apparently, the DLL is always notified about everything.
446 If bit 0 is set, the DLL is notified about process attachment (i.e.
447 DLL load).
448 If bit 1 is set, the DLL is notified about thread detachments (i.e.
449 thread terminations).
450 If bit 2 is set, the DLL is notified about thread attachments (i.e.
451 thread creations).
452 If bit 3 is set, the DLL is notified about process detachment (i.e.
453 DLL unload).
454
455The next 4 32-bit-values are the size of reserved stack
456('SizeOfStackReserve'), the size of initially committed stack
457('SizeOfStackCommit'), the size of the reserved heap
458('SizeOfHeapReserve') and the size of the committed heap
459('SizeOfHeapCommit').
460The 'reserved' amounts are address space (not real RAM) that is reserved
461for the specific purpose; at program startup, the 'committed' amount is
462actually allocated in RAM. The 'committed' value is also the amount by
463which the committed stack or heap grows if necessary. (Other sources
464claim that the stack will grow in pages, regardless of the
465'SizeOfStackCommit' value. I didn't check this.)
466So, as an example, if a program has a reserved heap of 1 MB and a
467committed heap of 64 KB, the heap will start out at 64 KB and is
468guaranteed to be enlargeable up to 1 MB. The heap will grow in
46964-KB-chunks.
470The 'heap' in this context is the primary (default) heap. A process can
471create more heaps if so it wishes.
472The stack is the first thread's stack (the one that starts main()). The
473process can create more threads which will have their own stacks.
474DLLs don't have a stack or heap of their own, so the values are ignored
475for their images. I don't know if drivers have a heap or a stack of
476their own, but I don't think so.
477
478After these stack- and heap-descriptions, we find 32 bits of
479'LoaderFlags', which I didn't find a useful description of. I only found
480a vague note about setting bits that automatically invoke a breakpoint
481or a debugger after loading the image; however, this doesn't seem to
482work.
483
484Then we find 32 bits of 'NumberOfRvaAndSizes', which is the number of
485valid entries in the directories that follow immediatly. I've found this
486value to be unreliable; you might wish use the constant
487IMAGE_NUMBEROF_DIRECTORY_ENTRIES instead, or the lesser of both.
488
489After the 'NumberOfRvaAndSizes' there is an array of
490IMAGE_NUMBEROF_DIRECTORY_ENTRIES (16) IMAGE_DATA_DIRECTORYs.
491Each of these directories describes the location (32 bits RVA called
492'VirtualAddress') and size (also 32 bit, called 'Size') of a particular
493piece of information, which is located in one of the sections that
494follow the directory entries.
495For example, the security directory is found at the RVA and has the size
496that are given at index 4.
497The directories that I know the structure of will be discussed later.
498Defined directory indexes are:
499
500 IMAGE_DIRECTORY_ENTRY_EXPORT (0)
501 The directory of exported symbols; mostly used for DLLs.
502 Described below.
503
504 IMAGE_DIRECTORY_ENTRY_IMPORT (1)
505 The directory of imported symbols; see below.
506
507 IMAGE_DIRECTORY_ENTRY_RESOURCE (2)
508 Directory of resources. Described below.
509
510 IMAGE_DIRECTORY_ENTRY_EXCEPTION (3)
511 Exception directory - structure and purpose unknown.
512
513 IMAGE_DIRECTORY_ENTRY_SECURITY (4)
514 Security directory - structure and purpose unknown.
515
516 IMAGE_DIRECTORY_ENTRY_BASERELOC (5)
517 Base relocation table - see below.
518
519 IMAGE_DIRECTORY_ENTRY_DEBUG (6)
520 Debug directory - contents is compiler dependent. Moreover, many
521 compilers stuff the debug information into the code section and
522 don't create a separate section for it.
523
524 IMAGE_DIRECTORY_ENTRY_COPYRIGHT (7)
525 Description string - some arbitrary copyright note or the like.
526
527 IMAGE_DIRECTORY_ENTRY_GLOBALPTR (8)
528 Machine Value (MIPS GP) - structure and purpose unknown.
529
530 IMAGE_DIRECTORY_ENTRY_TLS (9)
531 Thread local storage directory - structure unknown; contains
532 variables that are declared "__declspec(thread)", i.e.
533 per-thread global variables.
534
535 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG (10)
536 Load configuration directory - structure and purpose unknown.
537
538 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (11)
539 Bound import directory - see description of import directory.
540
541 IMAGE_DIRECTORY_ENTRY_IAT (12)
542 Import Address Table - see description of import directory.
543
544As an example, if we find at index 7 the 2 longwords 0x12000 and 33, and
545the load address is 0x10000, we know that the copyright data is at
546address 0x10000+0x12000 (in whatever section there may be), and the
547copyright note is 33 bytes long.
548If a directory of a particular type is not used in a binary, the Size
549and VirtualAddress are both 0.
550
551
552
553Section directories
554-------------------
555
556The sections consist of two major parts: first, a section description
557(of type IMAGE_SECTION_HEADER) and then the raw section data. So after
558the data directories we find an array of 'NumberOfSections' section
559headers, ordered by the sections' RVAs.
560
561A section header contains:
562
563An array of IMAGE_SIZEOF_SHORT_NAME (8) bytes that make up the name
564(ASCII) of the section. If all of the 8 bytes are used there is no 0-
565terminator for the string! The name is typically something like ".data"
566or ".text" or ".bss". There need not be a leading '.', the names may
567also be "CODE" or "IAT" or the like.
568Please note that the names are not at all related to the contents of the
569section. A section named ".code" may or may not contain the executable
570code; it may just as well contain the import address table; it may also
571contain the code *and* the address table *and* the initialized data.
572To find information in the sections, you will have to look it up via the
573data directories of the optional header. Do not rely on the names, and
574do not assume that the section's raw data starts at the beginning of a
575section.
576
577The next member of the IMAGE_SECTION_HEADER is a 32-bit-union of
578'PhysicalAddress' and 'VirtualSize'. In an object file, this is the
579address the contents is relocated to; in an executable, it is the size of
580the contents. In fact, the field seems to be unused; There are linkers
581that enter the size, and there are linkers that enter the address, and
582I've also found a linker that enters a 0, and all the executables run
583like the gentle wind.
584
585The next member is 'VirtualAddress', a 32-bit-value holding the RVA to
586the section's data when it is loaded in RAM.
587
588Then we have got 32 bits of 'SizeOfRawData', which is the size of the
589secion's data rounded up to the next multiple of 'FileAlignment'.
590
591Next is 'PointerToRawData' (32 bits), which is incredibly useful because
592it is the offset from the file's beginning to the section's data. If it
593is 0, the section's data are not contained in the file and will be
594arbitrary at load time.
595
596Then we have got 'PointerToRelocations' (32 bits) and
597'PointerToLinenumbers' (also 32 bits), 'NumberOfRelocations' (16 bits)
598and 'NumberOfLinenumbers' (also 16 bits). All of these are information
599that's only used for object files. Executables have a special base
600relocation directory, and the line number information, if present at
601all, is usually contained in a special purpose debugging segment or
602elsewhere.
603
604The last member of a section header is the 32 bits 'Characteristics',
605which is a bunch of flags describing how the section's memory should be
606treated:
607
608 If bit 5 (IMAGE_SCN_CNT_CODE) is set, the section contains
609 executable code.
610
611 If bit 6 (IMAGE_SCN_CNT_INITIALIZED_DATA) is set, the section
612 contains data that gets a defined value before execution starts. In
613 other words: the section's data in the file is meaningful.
614
615 If bit 7 (IMAGE_SCN_CNT_UNINITIALIZED_DATA) is set, this section
616 contains uninitialized data and will be initialized to all-0-bytes
617 before execution starts. This is normally the BSS.
618
619 If bit 9 (IMAGE_SCN_LNK_INFO) is set, the section doesn't contain
620 image data but comments, description or other documentation. This
621 information is part of an object file and may be information for the
622 linker, such as which libraries are needed.
623
624 If bit 11 (IMAGE_SCN_LNK_REMOVE) is set, the data is part of an
625 object file's section that is supposed to be left out when the
626 executable file is linked. Often combined with bit 9.
627
628 If bit 12 (IMAGE_SCN_LNK_COMDAT) is set, the section contains
629 "common block data", which are packaged functions of some sort.
630
631 If bit 15 (IMAGE_SCN_MEM_FARDATA) is set, we have far data -
632 whatever that means. This bit's meaning is unsure.
633
634 If bit 17 (IMAGE_SCN_MEM_PURGEABLE) is set, the section's data
635 is purgeable - but I don't think that this is the same as
636 "discardable", which has a bit of its own, see below.
637 The same bit is apparently used to indicate 16-bit-information as
638 there is also a define IMAGE_SCN_MEM_16BIT for it.
639 This bit's meaning is unsure.
640
641 If bit 18 (IMAGE_SCN_MEM_LOCKED) is set, the section should not be
642 moved in memory? Perhaps it indicates there is no relocation
643 information? This bit's meaning is unsure.
644
645 If bit 19 (IMAGE_SCN_MEM_PRELOAD) is set, the section should be
646 paged in before execution starts? This bit's meaning is unsure.
647
648 Bits 20 to 23 specify an alignment that I have no information
649 about. There are #defines IMAGE_SCN_ALIGN_16BYTES and the like. The
650 only value I've ever seen used is 0, for the default 16-byte-
651 alignment. I suspect that this is the alignment of objects in a
652 library file or the like.
653
654 If bit 24 (IMAGE_SCN_LNK_NRELOC_OVFL) is set, the section contains
655 some extended relocations that I don't know about.
656
657 If bit 25 (IMAGE_SCN_MEM_DISCARDABLE) is set, the section's data is
658 not needed after the process has started. This is the case,
659 for example, with the relocation information. I've seen it also for
660 startup routines of drivers and services that are only executed
661 once, and for import directories.
662
663 If bit 26 (IMAGE_SCN_MEM_NOT_CACHED) is set, the section's data
664 should not be cached. Don't ask my why not. Does this mean to switch
665 off the 2nd-level-cache?
666
667 If bit 27 (IMAGE_SCN_MEM_NOT_PAGED) is set, the section's data
668 should not be paged out. This is interesting for drivers.
669
670 If bit 28 (IMAGE_SCN_MEM_SHARED) is set, the section's data is
671 shared among all running instances of the image. If it is e.g. the
672 initialized data of a DLL, all running instances of the DLL will at
673 any time have the same variable contents.
674 Note that only the first instance's section is initialized.
675 Sections containing code are always shared copy-on-write (i.e. the
676 sharing doesn't work if relocations are necessary).
677
678 If bit 29 (IMAGE_SCN_MEM_EXECUTE) is set, the process gets
679 'execute'-access to the section's memory.
680
681 If bit 30 (IMAGE_SCN_MEM_READ) is set, the process gets
682 'read'-access to the section's memory.
683
684 If bit 31 (IMAGE_SCN_MEM_WRITE) is set, the process gets
685 'write'-access to the section's memory.
686
687
688
689After the section headers we find the sections themselves. They are, in
690the file, aligned to 'FileAlignment' bytes (that is, after the optional
691header and after each section's data there will be padding bytes) and
692ordered by their RVAs. When loaded (in RAM), the sections are aligned to
693'SectionAlignment' bytes.
694
695As an example, if the optional header ends at file offset 981 and
696'FileAlignment' is 512, the first section will start at byte 1024. Note
697that you can find the sections via the 'PointerToRawData' or the
698'VirtualAddress', so there is hardly any need to actually fuss around
699with the alignments.
700
701
702I will try to make an image of it all:
703
704
705 +-------------------+
706 | DOS-stub |
707 +-------------------+
708 | file-header |
709 +-------------------+
710 | optional header |
711 |- - - - - - - - - -|
712 | |----------------+
713 | data directories | |
714 | | |
715 |(RVAs to direc- |-------------+ |
716 |tories in sections)| | |
717 | |---------+ | |
718 | | | | |
719 +-------------------+ | | |
720 | |-----+ | | |
721 | section headers | | | | |
722 | (RVAs to section |--+ | | | |
723 | borders) | | | | | |
724 +-------------------+<-+ | | | |
725 | | | <-+ | |
726 | section data 1 | | | |
727 | | | <-----+ |
728 +-------------------+<----+ |
729 | | |
730 | section data 2 | |
731 | | <--------------+
732 +-------------------+
733
734There is one section header for each section, and each data directory
735will point to one of the sections (several data directories may point to
736the same section, and there may be sections without data directory
737pointing to them).
738
739
740
741Sections' raw data
742------------------
743
744
745general
746-------
747All sections are aligned to 'SectionAlignment' when loaded in RAM, and
748'FileAlignment' in the file. The sections are described by entries in
749the section headers: You find the sections in the file via
750'PointerToRawData' and in memory via 'VirtualAddress'; the length is in
751'SizeOfRawData'.
752
753There are several kinds of sections, depending on what's contained in
754them. In most cases (but not in all) there will be at least one
755data directory in a section, with a pointer to it in the optional
756header's data directory array.
757
758
759code section
760------------
761First, I will mention the code section. The section will have, at least,
762the bits 'IMAGE_SCN_CNT_CODE', 'IMAGE_SCN_MEM_EXECUTE' and
763'IMAGE_SCN_MEM_READ' set, and 'AddressOfEntryPoint' will point somewhere
764into the section, to the start of the function that the developer wants
765to execute first.
766'BaseOfCode' will normally point to the start of this section, but may
767point to somewhere later in the section if some non-code-bytes are
768placed before the code in the section.
769Normally, there will be nothing but executable code in this section, and
770there will be only one code section, but don't rely on this.
771Typical section names are ".text", ".code", "AUTO" and the like.
772
773
774data section
775------------
776The next thing we'll discuss is the initialized variables; this section
777contains initialized static variables (like "static int i = 5;"). It will
778have, at least, the bits 'IMAGE_SCN_CNT_INITIALIZED_DATA',
779'IMAGE_SCN_MEM_READ' and 'IMAGE_SCN_MEM_WRITE' set. Some linkers may
780place constant data into a section of their own that doesn't have the
781writeable-bit. If part of the data is shareable, or there are other
782peculiarities, there may be more sections with the apropriate section-
783bits set.
784The section, or sections, will be in the range 'BaseOfData' up to
785'BaseOfData'+'SizeOfInitializedData'.
786Typical section names are '.data', '.idata', 'DATA' and so on.
787
788
789bss section
790-----------
791Then there is the uninitialized data (for static variables like "static
792int k;"); this section is quite like the initialized data, but will have
793a file offset ('PointerToRawData') of 0 indicating its contents is not
794stored in the file, and 'IMAGE_SCN_CNT_UNINITIALIZED_DATA' is set
795instead of 'IMAGE_SCN_CNT_INITIALIZED_DATA' to indicate that the
796contents should be set to 0-bytes at load-time. This means, there is a
797section header but no section in the file; the section will be created
798by the loader and consist entirely of 0-bytes.
799The length will be 'SizeOfUninitializedData'.
800Typical names are '.bss', 'BSS' and the like.
801
802These were the section data that are *not* pointed to by data
803directories. Their contents and structure is supplied by the compiler,
804not by the linker.
805(The stack-segment and heap-segment are not sections in the binary but
806created by the loader from the stacksize- and heapsize-entries in the
807optional header.)
808
809
810copyright
811---------
812To begin with a simple directory-section, let's look at the data
813directory 'IMAGE_DIRECTORY_ENTRY_COPYRIGHT'. The contents is a
814copyright- or description string in ASCII (not 0-terminated), like
815"Gonkulator control application, copyright (c) 1848 Hugendubel & Cie".
816This string is, normally, supplied to the linker with the command line
817or a description file.
818This string is not needed at runtime and may be discarded. It is not
819writeable; in fact, the application doesn't need access at all.
820So the linker will find out if there is a discardable non-writeable
821section already and if not, create one (named '.descr' or the like). It
822will then stuff the string into the section and let the
823copyright-directory-pointer point to the string. The
824'IMAGE_SCN_CNT_INITIALIZED_DATA' bit should be set.
825
826
827exported symbols
828----------------
829(Note that the description of the export directory was faulty in versions
830of this text before 1999-03-12. It didn't describe forwarders, exports
831by ordinal only, or exports with several names.)
832
833The next-simplest thing is the export directory,
834'IMAGE_DIRECTORY_ENTRY_EXPORT'. This is a directory typically found
835in DLLs; it contains the entry points of exported functions (and the
836addresses of exported objects etc.). Executables may of course also have
837exported symbols but usually they don't.
838The containing section should be "initialized data" and "readable". It
839should not be "discardable" because the process might call
840"GetProcAddress()" to find a function's entry point at runtime.
841The section is normally called '.edata' if it is a separate thing; often
842enough, it is merged into some other section like "initialized data".
843
844The structure of the export table ('IMAGE_EXPORT_DIRECTORY') comprises a
845header and the export data, that is: the symbol names, their ordinals
846and the offsets to their entry points.
847
848First, we have 32 bits of 'Characteristics' that are unused and normally
8490. Then there is a 32-bit-'TimeDateStamp', which presumably should give
850the time the table was created in the time_t-format; alas, it is not
851always valid (some linkers set it to 0). Then we have 2 16-bit-words of
852version-info ('MajorVersion' and 'MinorVersion'), and these, too, are
853often enough set to 0.
854
855The next thing is 32 bits of 'Name'; this is an RVA to the DLL name as a
8560-terminated ASCII string. (The name is necessary in case the DLL file is
857renamed - see "binding" at the import directory.)
858Then, we have got a 32-bit-'Base'. We'll come to that in a moment.
859
860The next 32-bit-value is the total number of exported items
861('NumberOfFunctions'). In addition to their ordinal number, items may be
862exported by one or several names. and the next 32-bit-number is the
863total number of exported names ('NumberOfNames').
864In most cases, each exported item will have exactly one corresponding
865name and it will be used by that name, but an item may have several
866associated names (it is then accessible by each of them), or it may have
867no name, in which case it is only accessible by its ordinal number. The
868use of unnamed exports (purely by ordinal) is discouraged, because all
869versions of the exporting DLL would have to use the same ordinal
870numbering, which is a maintainance problem.
871
872The next 32-bit-value 'AddressOfFunctions' is a RVA to the list of
873exported items. It points to an array of 'NumberOfFunctions'
87432-bit-values, each being a RVA to the exported function or variable.
875
876There are 2 quirks about this list: First, such an exported RVA may be 0,
877in which case it is unused. Second, if the RVA points into the section
878containing the export directory, this is a forwarded export. A forwarded
879export is a pointer to an export in another binary; if it is used, the
880pointed-to export in the other binary is used instead. The RVA in this
881case points, as mentioned, into the export directory's section, to a
882zero-terminated string comprising the name of the pointed-to DLL and
883the export name separated by a dot, like "otherdll.exportname", or the
884DLL's name and the export ordinal, like "otherdll.#19".
885
886Now is the time to explain the export ordinal. An export's ordinal is
887the index into the AddressOfFunctions-Array (the 0-based position in
888this array) plus the 'Base' mentioned above.
889In most cases, the 'Base' is 1, which means the first export has an
890ordinal of 1, the second has an ordinal of 2 and so on.
891
892After the 'AddressOfFunctions'-RVA we find a RVA to the array of
89332-bit-RVAs to symbol names 'AddressOfNames', and a RVA to the array of
89416-bit-ordinals 'AddressOfNameOrdinals'. Both arrays have
895'NumberOfNames' elements.
896The symbol names may be missing entirely, in which case the
897'AddressOfNames' is 0. Otherwise, the pointed-to arrays are running
898parallel, which means their elements at each index belong together. The
899'AddressOfNames'-array consists of RVAs to 0-terminated export names;
900the names are held in a sorted list (i.e. the first array member is the
901RVA to the alphabetically smallest name; this allows efficient searching
902when looking up an exported symbol by name).
903According to the PE specification, the 'AddressOfNameOrdinals'-array has
904the ordinal corresponding to each name; however, I've found this array
905to contain the actual index into the 'AddressOfFunctions-Array instead.
906
907I'll draw a picture about the three tables:
908
909
910 AddressOfFunctions
911 |
912 |
913 |
914 v
915 exported RVA with ordinal 'Base'
916 exported RVA with ordinal 'Base'+1
917 ...
918 exported RVA with ordinal 'Base'+'NumberOfFunctions'-1
919
920
921
922 AddressOfNames AddressOfNameOrdinals
923 | |
924 | |
925 | |
926 v v
927 RVA to first name <-> Index of export for first name
928 RVA to second name <-> Index of export for second name
929 ... ...
930 RVA to name 'NumberOfNames' <-> Index of export for name 'NumberOfNames'
931
932
933Some examples are in order.
934
935To find an exported symbol by ordinal, subtract the 'Base' to get the
936index, follow the 'AddressOfFunctions'-RVA to find the exports-array and
937use the index to find the exported RVA in the array. If it does not
938point into the export section, you are done. Otherwise, it points to a
939string describing the exporting DLL and the name or ordinal therein, and
940you have to look up the forwarded export there.
941
942To find an exported symbol by name, follow the 'AddressOfNames'-RVA (if
943it is 0 there are no names) to find the array of RVAs to the export
944names. Search your name in the list. Use the name's index in the
945'AddressOfNameOrdinals'-Array and get the 16-bit-number corresponding to
946the found name. According to the PE spec, it is an ordinal and you need
947to subtract the 'Base' to get the export index; according to my
948experiences it is the export index and you don't subtract. Using the
949export index, you find the export RVA in the 'AddressOfFunctions'-Array,
950being either the exported RVA itself or a RVA to a string describing a
951forwarded export.
952
953
954imported symbols
955----------------
956When the compiler finds a call to a function that is in a different
957executable (mostly in a DLL), it will, in the most simplistic case, not
958know anything about the circumstances and simply output a normal
959call-instruction to that symbol, the address of which the linker will
960have to fix, like it does for any external symbol.
961The linker uses an import library to look up from which DLL which symnol
962is imported, and produces stubs for all the imported symbols, each of
963which consists of a jump-instruction; the stubs are the actual
964call-targets. These jump-instructions will actually jump to an address
965that's fetched from the so-called import address table. In more
966sophisticated applications (when "__declspec(dllimport)" is used), the
967compiler knows the function is imported, and outputs a call to the
968address that's in the import address table, bypassing the jump.
969
970Anyway, the address of the function in the DLL is always necessary and
971will be supplied by the loader from the exporting DLL's export directory
972when the application is loaded. The loader knows which symbols in what
973libraries have to be looked up and their addresses fixed by searching
974the import directory.
975
976I will better give you an example. The calls with or without
977__declspec(dllimport) look like this:
978
979 source:
980 int symbol(char *);
981 __declspec(dllimport) int symbol2(char*);
982 void foo(void)
983 {
984 int i=symbol("bar");
985 int j=symbol2("baz");
986 }
987
988 assembly:
989 ...
990 call _symbol ; without declspec(dllimport)
991 ...
992 call [__imp__symbol2] ; with declspec(dllimport)
993 ...
994
995In the first case (without __declspec(dllimport)), the compiler didn't
996know that '_symbol' was in a DLL, so the linker has to provide the
997function '_symbol'. Since the function isn't there, it will supply a
998stub function for the imported symbol, being an indirect jump. The
999collection of all import-stubs is called the "transfer area" (also
1000sometimes called a "trampoline", because you jump there in order to jump
1001to somewhere else).
1002Typically this transfer area is located in the code section (it is not
1003part of the import directory). Each of the function stubs is a jump to
1004the actual function in the target DLLs. The transfer area looks like
1005this:
1006
1007 _symbol: jmp [__imp__symbol]
1008 _other_symbol: jmp [__imp__other__symbol]
1009 ...
1010
1011
1012This means: if you use imported symbols without specifying
1013"__declspec(dllimport)" then the linker will generate a transfer area
1014for them, consisting of indirect jumps. If you do specify
1015"__declspec(dllimport)", the compiler will do the indirection itself and
1016a transfer area is not necessary. (It also means: if you import
1017variables or other stuff you must specify "__declspec(dllimport)",
1018because a stub with a jmp instruction is appropriate for functions
1019only.)
1020
1021In any case the adress of symbol 'x' is stored at a location '__imp_x'.
1022All these locations together comprise the so-called "import address
1023table", which is provided to the linker by the import libraries of the
1024various DLLs that are used. The import address table is a list of
1025addresses like this:
1026
1027 __imp__symbol: 0xdeadbeef
1028 __imp__symbol2: 0x40100
1029 __imp__symbol3: 0x300100
1030 ...
1031
1032This import address table is a part of the import directory, and it is
1033pointed to by the IMAGE_DIRECTORY_ENTRY_IAT directory pointer (although
1034some linkers don't set this directory entry and it works nevertheless;
1035apparently, the loader can resolve imports without using the directory
1036IMAGE_DIRECTORY_ENTRY_IAT).
1037The addresses in this table are unknown to the linker; the linker
1038inserts dummies (RVAs to the function names; see below for more
1039information) that are patched by the loader at load time using the
1040export directory of the exporting DLL. The import address table, and how
1041it is found by the loader, will be described in more detail later in
1042this chapter.
1043
1044Note that this description is C-specific; there are other application
1045building environments that don't use import libraries. They all need to
1046generate an import address table, though, which they use to let their
1047programs access the imported objects and functions. C compilers tend to
1048use import libraries because it is convenient for them - their linkers
1049use libraries anyway. Other environments use e.g. a description file
1050that lists the necessary DLL names and function names (like the "module
1051definition file"), or a declaration-style list in the source.
1052
1053
1054This is how imports are used by the program's code; now we'll look how
1055an import directory is made up so the loader can use it.
1056
1057
1058The import directory should reside in a section that's "initialized
1059data" and "readable".
1060The import directory is an array of IMAGE_IMPORT_DESCRIPTORs, one for
1061each used DLL. The list is terminated by a IMAGE_IMPORT_DESCRIPTOR
1062that's entirely filled with 0-bytes.
1063An IMAGE_IMPORT_DESCRIPTOR is a struct with these members:
1064
1065 OriginalFirstThunk
1066 An RVA (32 bit) pointing to a 0-terminated array of RVAs to
1067 IMAGE_THUNK_DATAs, each describing one imported function. The
1068 array will never change.
1069
1070 TimeDateStamp
1071 A 32-bit-timestamp that has several purposes. Let's pretend that
1072 the timestamp is 0, and handle the advanced cases later.
1073
1074 ForwarderChain
1075 The 32-bit-index of the first forwarder in the list of imported
1076 functions. Forwarders are also advanced stuff; set to all-bits-1
1077 for beginners.
1078
1079 Name
1080 A 32-bit-RVA to the name (a 0-terminated ASCII string) of the
1081 DLL.
1082
1083 FirstThunk
1084 An RVA (32 bit) to a 0-terminated array of RVAs to
1085 IMAGE_THUNK_DATAs, each describing one imported function. The
1086 array is part of the import address table and will change.
1087
1088So each IMAGE_IMPORT_DESCRIPTOR in the array gives you the name of the
1089exporting DLL and, apart from the forwarder and timestamp, it gives you
10902 RVAs to arrays of IMAGE_THUNK_DATAs, using 32 bits. (The last member
1091of each array is entirely filled with 0-bytes to mark the end.)
1092Each IMAGE_THUNK_DATA is, for now, an RVA to a IMAGE_IMPORT_BY_NAME
1093which describes the imported function.
1094The interesting point is now, the arrays run parallel, i.e.: they point
1095to the same IMAGE_IMPORT_BY_NAMEs.
1096
1097No need to be desparate, I will draw another picture. This is the
1098essential contents of one IMAGE_IMPORT_DESCRIPTOR:
1099
1100 OriginalFirstThunk FirstThunk
1101 | |
1102 | |
1103 | |
1104 V V
1105
1106 0--> func1 <--0
1107 1--> func2 <--1
1108 2--> func3 <--2
1109 3--> foo <--3
1110 4--> mumpitz <--4
1111 5--> knuff <--5
1112 6-->0 0<--6 /* the last RVA is 0! */
1113
1114where the names in the center are the yet to discuss
1115IMAGE_IMPORT_BY_NAMEs. Each of them is a 16-bit-number (a hint) followed
1116by an unspecified amount of bytes, being the 0-terminated ASCII name of
1117the imported symbol.
1118The hint is an index into the exporting DLL's name table (see export
1119directory above). The name at that index is tried, and if it doesn't
1120match then a binary search is done to find the name.
1121(Some linkers don't bother to look up correct hints and simply specify
11221 all the time, or some other arbitrary number. This doesn't harm, it
1123just makes the first attempt to resolve the name always fail, enforcing
1124a binary search for each name.)
1125
1126To summarize, if you want to look up information about the imported
1127function "foo" from DLL "knurr", you first find the entry
1128IMAGE_DIRECTORY_ENTRY_IMPORT in the data directories, get an RVA, find
1129that address in the raw section data and now have an array of
1130IMAGE_IMPORT_DESCRIPTORs. Get the member of this array that relates to
1131the DLL "knurr" by inspecting the strings pointed to by the 'Name's.
1132When you have found the right IMAGE_IMPORT_DESCRIPTOR, follow its
1133'OriginalFirstThunk' and get hold of the pointed-to array of
1134IMAGE_THUNK_DATAs; inspect the RVAs and find the function "foo".
1135
1136Ok, now, why do we have *two* lists of pointers to the
1137IMAGE_IMPORT_BY_NAMEs? Because at runtime the application doesn't need
1138the imported functions' names but the addresses. This is where the
1139import address table comes in again. The loader will look up each
1140imported symbol in the export-directory of the DLL in question and
1141replace the IMAGE_THUNK_DATA-element in the 'FirstThunk'-list (which
1142until now also points to the IMAGE_IMPORT_BY_NAME) with the linear
1143address of the DLL's entry point.
1144Remember the list of addresses with labels like "__imp__symbol"; the
1145import address table, pointed to by the data directory
1146IMAGE_DIRECTORY_ENTRY_IAT, is exactly the list pointed to by
1147'FirstThunk'. (In case of imports from several DLLs, the import address
1148table comprises the 'FirstThunk'-Arrays of all the DLLs. The directory
1149entry IMAGE_DIRECTORY_ENTRY_IAT may be missing, the imports will still
1150work fine.)
1151The 'OriginalFirstThunk'-array remains untouched, so you can always look
1152up the original list of imported names via the
1153'OriginalFirstThunk'-list.
1154
1155The import is now patched with the correct linear addresses and looks
1156like this:
1157
1158 OriginalFirstThunk FirstThunk
1159 | |
1160 | |
1161 | |
1162 V V
1163
1164 0--> func1 0--> exported func1
1165 1--> func2 1--> exported func2
1166 2--> func3 2--> exported func3
1167 3--> foo 3--> exported foo
1168 4--> mumpitz 4--> exported mumpitz
1169 5--> knuff 5--> exported knuff
1170 6-->0 0<--6
1171
1172
1173This was the basic structure, for simple cases. Now we'll learn about
1174tweaks in the import directories.
1175
1176First, the bit IMAGE_ORDINAL_FLAG (that is: the MSB) of the
1177IMAGE_THUNK_DATA in the arrays can be set, in which case there is no
1178symbol-name-information in the list and the symbol is imported purely by
1179ordinal. You get the ordinal by inspecting the lower word of the
1180IMAGE_THUNK_DATA.
1181The import by ordinals is discouraged; it is much safer to import by
1182name, because the export ordinals might change if the exporting DLL is
1183not in the expected version.
1184
1185Second, there are the so-called "bound imports".
1186
1187Think about the loader's task: when a binary that it wants to execute
1188needs a function from a DLL, the loader loads the DLL, finds its export
1189directory, looks up the function's RVA and calculates the function's
1190entry point. Then it patches the so-found address into the 'FirstThunk'-
1191list.
1192Given that the programmer was clever and supplied unique preferred load
1193addresses for the DLLs that don't clash, we can assume that the
1194functions' entry points will always be the same. They can be computed
1195and patched into the 'FirstThunk'-list at link-time, and that's what
1196happens with the "bound imports". (The utility "bind" does this; it is
1197part of the Win32 SDK.)
1198
1199Of course, one must be cautious: The user's DLL may have a different
1200version, or it may be necessary to relocate the DLL, thus invalidating
1201the pre-patched 'FirstThunk'-list; in this case, the loader will still
1202be able to walk the 'OriginalFirstThunk'-list, find the imported symbols
1203and re-patch the 'FirstThunk'-list. The loader knows that this is
1204necessary if a) the versions of the exporting DLL don't match or b) the
1205exporting DLL had to be relocated.
1206
1207To decide whether there were relocations is no problem for the loader,
1208but how to find out if the versions differ? This is where the
1209'TimeDateStamp' of the IMAGE_IMPORT_DESCRIPTOR comes in. If it is 0, the
1210import-list has not been bound, and the loader must fix the entry points
1211always. Otherwise, the imports are bound, and 'TimeDateStamp' must match
1212the 'TimeDateStamp' of the exporting DLL's 'FileHeader'; if it doesn't
1213match, the loader assumes that the binary is bound to a "wrong" DLL and
1214will re-patch the import list.
1215
1216There is an additional quirk about "forwarders" in the import-list. A DLL
1217can export a symbol that's not defined in the DLL but imported from
1218another DLL; such a symbol is said to be forwarded (see the export
1219directory description above).
1220Now, obviously you can't tell if the symbol's entry point is valid by
1221looking into the timestamp of a DLL that doesn't actually contain the
1222entry point. So the forwarded symbols' entry points must always be fixed
1223up, for safety reasons. In the import list of a binary, imports of
1224forwarded symbols need to be found so the loader can patch them.
1225
1226This is done via the 'ForwarderChain'. It is an index into the thunk-
1227lists; the import at the indexed position is a forwarded export, and the
1228contents of the 'FirstThunk'-list at this position is the index of the
1229*next* forwarded import, and so on, until the index is "-1" which
1230indicates there are no more forwards. If there are no forwarders at all,
1231'ForwarderChain' is -1 itself.
1232
1233This was the so-called "old-style" binding.
1234
1235At this point, we should sum up what we have had so far :-)
1236
1237Ok, I will assume you have found the IMAGE_DIRECTORY_ENTRY_IMPORT and you have
1238followed it to find the import-directory, which will be in one of the
1239sections. Now you're at the beginning of an array of
1240IMAGE_IMPORT_DESCRIPTORs the last of which will be entirely 0-bytes-
1241filled.
1242To decipher one of the IMAGE_IMPORT_DESCRIPTORs, you first look into the
1243'Name'-field, follow the RVA and thusly find the name of the exporting
1244DLL. Next you decide whether the imports are bound or not;
1245'TimeDateStamp' will be non-zero if the imports are bound. If they are
1246bound, now is a good time to check if the DLL version matches yours by
1247comparing the 'TimeDateStamp's.
1248Now you follow the 'OriginalFirstThunk'-RVA to go to the
1249IMAGE_THUNK_DATA-array; walk down this array (it is be 0-terminated),
1250and each member will be the RVA of a IMAGE_IMPORT_BY_NAME (unless the
1251hi-bit is set in which case you don't have a name but are left with a
1252mere ordinal). Follow the RVA, and skip 2 bytes (the hint), and now
1253you have got a 0-terminated ASCII-string that's the name of the imported
1254function.
1255To find the supplied entry point addresses in case it is a bound import,
1256follow the 'FirstThunk' and walk it parallel to the
1257'OriginalFirstThunk'-array; the array-members are the linear addresses
1258of the entry points (leaving aside the forwarders-topic for a moment).
1259
1260There is one thing I didn't mention until now: Apparently there are
1261linkers that exhibit a bug when they build the import directory (I've
1262found this bug being in use by a Borland C linker). These linkers set
1263the 'OriginalFirstThunk' in the IMAGE_IMPORT_DESCRIPTOR to 0 and create
1264only the 'FirstThunk'-array. Obviously, such import directories cannot
1265be bound (else the necessary information to re-fix the imports were
1266lost - you couldn't find the function names). In this case, you will
1267have to follow the 'FirstThunk'-array to get the imported symbol names,
1268and you will never have pre-patched entry point addresses. I have found
1269a TIS document ([6]) describing the import directory in a way that is
1270compatible to this bug, so that paper may be the origin of the bug.
1271The TIS document specifies:
1272 IMPORT FLAGS
1273 TIME/DATE STAMP
1274 MAJOR VERSION - MINOR VERSION
1275 NAME RVA
1276 IMPORT LOOKUP TABLE RVA
1277 IMPORT ADDRESS TABLE RVA
1278as opposed to the structure used elsewhere:
1279 OriginalFirstThunk
1280 TimeDateStamp
1281 ForwarderChain
1282 Name
1283 FirstThunk
1284
1285The last tweak about the import directories is the so-called "new style"
1286binding (it is described in [3]), which can also be done with the
1287"bind"-utility. When this is used, the 'TimeDateStamp' is set to
1288all-bits-1 and there is no forwarderchain; all imported symbols get their
1289address patched, whether they are forwarded or not. Still, you need to
1290know the DLLs' version, and you need to distinguish forwarded symbols
1291from ordinary ones. For this purpose, the
1292IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT directory is created. This will, as
1293far as I could find out, *not* be in a section but in the header, after
1294the section headers and before the first section. (Hey, I didn't invent
1295this, I'm only describing it!)
1296This directory tells you, for each used DLL, from which other DLLs there
1297are forwarded exports.
1298The structure is an IMAGE_BOUND_IMPORT_DESCRIPTOR, comprising (in this
1299order):
1300A 32-bit number, giving you the 'TimeDateStamp' of the DLL;
1301a 16-bit-number 'OffsetModuleName', being the offset from the beginning
1302of the directory to the 0-terminated name of the DLL;
1303a 16-bit-number 'NumberOfModuleForwarderRefs' giving you the number of
1304DLLs that this DLL uses for its forwarders.
1305
1306Immediatly following this struct you find 'NumberOfModuleForwarderRefs'
1307structs that tell you the names and versions of the DLLs that this DLL
1308forwards from. These structs are 'IMAGE_BOUND_FORWARDER_REF's:
1309A 32-bit-number 'TimeDateStamp';
1310a 16-bit-number 'OffsetModuleName', being the offset from the beginning
1311of the directory to the 0-terminated name of the forwarded-from DLL;
131216 unused bits.
1313
1314Following the 'IMAGE_BOUND_FORWARDER_REF's is the next
1315'IMAGE_BOUND_IMPORT_DESCRIPTOR' and so on; the list is terminated by an
1316all-0-bits-IMAGE_BOUND_IMPORT_DESCRIPTOR.
1317
1318
1319Sorry for the inconvenience, but that's what it looks like :-)
1320
1321
1322Now, if you have a new-bound import directory, you load all the DLLs,
1323use the directory pointer IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT to find the
1324IMAGE_BOUND_IMPORT_DESCRIPTOR, scan through it and check if the
1325'TimeDateStamp's of the loaded DLLs match the ones given in this
1326directory. If not, fix them in the 'FirstThunk'-array of the import
1327directory.
1328
1329
1330
1331resources
1332---------
1333The resources, such as dialog boxes, menus, icons and so on, are stored
1334in the data directory pointed to by IMAGE_DIRECTORY_ENTRY_RESOURCE. It
1335is in a section that has, at least, the bits
1336'IMAGE_SCN_CNT_INITIALIZED_DATA' and 'IMAGE_SCN_MEM_READ' set.
1337
1338A resource base is a 'IMAGE_RESOURCE_DIRECTORY'; it contains several
1339'IMAGE_RESOURCE_DIRECTORY_ENTRY's each of which in turn may point to a
1340'IMAGE_RESOURCE_DIRECTORY'. This way, you get a tree of
1341'IMAGE_RESOURCE_DIRECTORY's with 'IMAGE_RESOURCE_DIRECTORY_ENTRY's as
1342leafs; these leafs point to the actual resource data.
1343
1344In real life, the situation is somewhat relaxed. Normally you won't find
1345convoluted trees you can't possibly sort out.
1346The hierarchy is, normally, like this: one directory is the root. It
1347points to directories, one for each resource type. These directories
1348point to subdirectories, each of which will have a name or an ID and
1349point to a directory of the languages provided for this resource; for
1350each language you will find one resource entry, which will finally point
1351to the data. (Note that multi-language-resources don't work on
1352Win95, which always uses the same resource if it is available in several
1353languages - I didn't check which one, but I guess it's the first it
1354encounters. They do work on NT.)
1355
1356The tree, without the pointer to the data, may look like this:
1357
1358 (root)
1359 |
1360 +----------------+------------------+
1361 | | |
1362 menu dialog icon
1363 | | |
1364 +-----+-----+ +-+----+ +-+----+----+
1365 | | | | | | |
1366 "main" "popup" 0x10 "maindlg" 0x100 0x110 0x120
1367 | | | | | | |
1368 +---+-+ | | | | | |
1369 | | default english default def. def. def.
1370german english
1371
1372
1373A IMAGE_RESOURCE_DIRECTORY comprises:
137432 bits of unused flags called 'Characteristics';
137532 bits 'TimeDateStamp' (again in the common time_t representation),
1376giving you the time the resource was created (if the entry is set);
137716 bits 'MajorVersion' and 16 bits 'MinorVersion', thusly allowing you
1378to maintain several versions of the resource;
137916 bits 'NumberOfNamedEntries' and another 16 bits 'NumberOfIdEntries'.
1380
1381Immediatly following such a structure are
1382'NumberOfNamedEntries'+'NumberOfIdEntries' structs which are of the
1383format 'IMAGE_RESOURCE_DIRECTORY_ENTRY', those with the names coming first.
1384They may point to further 'IMAGE_RESOURCE_DIRECTORY's or they point to
1385the actual resource data.
1386A IMAGE_RESOURCE_DIRECTORY_ENTRY consists of:
138732 bits giving you the id of the resource or the directory it describes;
138832 bits offset to the data or offset to the next sub-directory.
1389
1390The meaning of the id depends on the level in the tree; the id may be a
1391number (if the hi-bit is clear) or a name (if the hi-bit is set). If it
1392is a name, the lower 31 bits are the offset from the beginning of the
1393resource section's raw data to the name (the name consists of 16 bits
1394length and trailing wide characters, in unicode, not 0-terminated).
1395
1396If you are in the root-directory, the id, if it is a number, is the
1397resource-type:
1398 1: cursor
1399 2: bitmap
1400 3: icon
1401 4: menu
1402 5: dialog
1403 6: string table
1404 7: font directory
1405 8: font
1406 9: accelerators
1407 10: unformatted resource data
1408 11: message table
1409 12: group cursor
1410 14: group icon
1411 16: version information
1412Any other number is user-defined. Any resource-type with a type-name is
1413always user-defined.
1414
1415If you are one level deeper, the id is the resource-id (or resource-
1416name).
1417
1418If you are another level deeper, the id must be a number, and it is the
1419language-id of the specific instance of the resource; for example, you
1420can have the same dialog in australian english, canadian french and
1421swiss german localized forms, and they all share the same resource-id.
1422The system will choose the dialog to load based on the thread's locale,
1423which in turn will usually reflect the user's "regional setting".
1424(If the resource cannot be found for the thread locale, the system will
1425first try to find a resource for the locale using a neutral sublanguage,
1426e.g. it will look for standard french instead of the user's canadian
1427french; if it still can't be found, the instance with the smallest
1428language id will be used. As noted, all this works only on NT.)
1429To decipher the language id, split it into the primary language id and
1430the sublanguage id using the macros PRIMARYLANGID() and SUBLANGID(),
1431giving you the bits 0 to 9 or 10 to 15, respectivly. The values are
1432defined in the file "winresrc.h".
1433Language-resources are only supported for accelerators, dialogs, menus,
1434rcdata or stringtables; other resource-types should be
1435LANG_NEUTRAL/SUBLANG_NEUTRAL.
1436
1437To find out whether the next level below a resource directory is another
1438directory, you inspect the hi-bit of the offset. If it is set, the
1439remaining 31 bits are the offset from the beginning of the resource
1440section's raw data to the next directory, again in the format
1441IMAGE_RESOURCE_DIRECTORY with trailing IMAGE_RESOURCE_DIRECTORY_ENTRYs.
1442
1443If the bit is clear, the offset is the distance from the beginning of
1444the resource section's raw data to the resource's raw data description,
1445a IMAGE_RESOURCE_DATA_ENTRY. It consists of 32 bits 'OffsetToData' (the
1446offset to the raw data, counting from the beginning of the resource
1447section's raw data), 32 bits of 'Size' of the data, 32 bits 'CodePage'
1448and 32 unused bits.
1449(The use of codepages is discouraged, you should use the 'language'-
1450feature to support multiple locales.)
1451
1452
1453The raw data format depends on the resource type; descriptions can be
1454found in the MS SDK documentation. Note that any string in resources is
1455always in UNICODE except for user defined resources, which are in the
1456format the developer chooses, obviously.
1457
1458
1459relocations
1460-----------
1461The last data directory I will describe is the base relocation
1462directory. It is pointed to by the IMAGE_DIRECTORY_ENTRY_BASERELOC entry
1463in the data directories of the optional header. It is typically
1464contained in a section if its own, with a name like ".reloc" and the
1465bits IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE and
1466IMAGE_SCN_MEM_READ set.
1467
1468The relocation data is needed by the loader if the image cannot be
1469loaded to the preferred load address 'ImageBase' mentioned in the
1470optional header. In this case, the fixed addresses supplied by the
1471linker are no longer valid, and the loader has to apply fixups for
1472absolute addresses used for locations of static variables, string
1473literals and so on.
1474
1475The relocation directory is a sequence of chunks. Each chunk contains
1476the relocation information for 4 KB of the image. A chunk starts with a
1477'IMAGE_BASE_RELOCATION' struct. It consists of 32 bits 'VirtualAddress'
1478and 32 bits 'SizeOfBlock'. It is followed by the chunk's actual
1479relocation data, being 16 bits each.
1480The 'VirtualAddress' is the base RVA that the relocations of this chunk
1481need to be applied to; the 'SizeOfBlock' is the size of the entire chunk
1482in bytes.
1483The number of trailing relocations is
1484('SizeOfBlock'-sizeof(IMAGE_BASE_RELOCATION))/2
1485The relocation information ends when you encounter a
1486IMAGE_BASE_RELOCATION struct with a 'VirtualAddress' of 0.
1487
1488Each 16-bit-relocation information consists of the relocation position
1489in the lower 12 bits and a relocation type in the high 4 bits. To get
1490the relocation RVA, you need to add the IMAGE_BASE_RELOCATION's
1491'VirtualAddress' to the 12-bit-position. The type is one of:
1492 IMAGE_REL_BASED_ABSOLUTE (0)
1493 This is a no-op; it is used to align the chunk to a 32-bits-
1494 border. The position should be 0.
1495 IMAGE_REL_BASED_HIGH (1)
1496 The high 16 bits of the relocation must be applied to the 16
1497 bits of the WORD pointed to by the offset, which is the high
1498 word of a 32-bit-DWORD.
1499 IMAGE_REL_BASED_LOW (2)
1500 The low 16 bits of the relocation must be applied to the 16
1501 bits of the WORD pointed to by the offset, which is the low
1502 word of a 32-bit-DWORD.
1503 IMAGE_REL_BASED_HIGHLOW (3)
1504 The entire 32-bit-relocation must be applied to the entire 32
1505 bits in question. This (and the no-op '0') is the only
1506 relocation type I've actually found in binaries.
1507 IMAGE_REL_BASED_HIGHADJ (4)
1508 This is one for the tough. Read yourself (from [6]) and make
1509 sense out of it if you can:
1510 "Highadjust. This fixup requires a full 32-bit value. The high
1511 16-bits is located at Offset, and the low 16-bits is located in
1512 the next Offset array element (this array element is included in
1513 the Size field). The two need to be combined into a signed
1514 variable. Add the 32-bit delta. Then add 0x8000 and store the
1515 high 16-bits of the signed variable to the 16-bit field at
1516 Offset."
1517 IMAGE_REL_BASED_MIPS_JMPADDR (5)
1518 Unknown
1519 IMAGE_REL_BASED_SECTION (6)
1520 Unknown
1521 IMAGE_REL_BASED_REL32 (7)
1522 Unknown
1523
1524As an example, if you find the relocation information to be
1525 0x00004000 (32 bits, starting RVA)
1526 0x00000010 (32 bits, size of chunk)
1527 0x3012 (16 bits reloc data)
1528 0x3080 (16 bits reloc data)
1529 0x30f6 (16 bits reloc data)
1530 0x0000 (16 bits reloc data)
1531 0x00000000 (next chunk's RVA)
1532 0xff341234
1533you know the first chunk describes relocations starting at RVA 0x4000 and
1534is 16 bytes long. Because the header uses 8 bytes and one relocation
1535uses 2 bytes, there are (16-8)/2=4 relocations in the chunk.
1536The first relocation is to be applied to the DWORD at 0x4012, the next
1537to the DWORD at 0x4080, and the third to the DWORD at 0x40f6. The last
1538relocation is a no-op.
1539The next chunk has a RVA of 0 and finishes the list.
1540
1541Now, how do you do a relocation?
1542You know that the image *is* relocated to the preferred load address
1543'ImageBase' in the optional header; you also know the address you did
1544load the image to. If they match, you don't need to do anything.
1545If they don't match, you calculate the difference
1546actual_base-preferred_base
1547and add that value (signed, it may be negative) to the relocation
1548positions, which you will find with the method described above.
1549
1550
1551Acknowledgments
1552---------------
1553Thanks go to David Binette for his debugging and proof-reading.
1554(The remaining errors are entirely mine.)
1555Also thanks to wotsit.org for letting me put the file on their site.
1556
1557
1558Copyright
1559---------
1560This text is copyright 1999 by B. Luevelsmeyer. It is freeware, and you
1561may use it for any purpose but on your own risk. It contains errors and
1562it is incomplete. You have been warned.
1563
1564
1565Bug reports
1566-----------
1567Send any bug reports (or other comments) to
1568bernd.luevelsmeyer@iplan.heitec.net
1569
1570
1571Versions
1572--------
1573You find the date of the current release at the top of the file.
1574
15751998-04-06
1576 First public release
1577
15781998-07-29
1579 Changed wrong "byte" to "word" for image version and subsystem version
1580 Corrected error "stack is limited to 1 MB" (in fact it is not limited)
1581 Corrected some typos
1582
15831999-03-15
1584 Corrected export directory description, which was very incomplete
1585 Reworded import directory description, which had been unclear
1586 Corrected typos and did some rewording in other sections
1587
1588
1589Literature
1590----------
1591
1592[1]
1593"Peering Inside the PE: A Tour of the Win32 Portable Executable File
1594Format" (M. Pietrek), in: Microsoft Systems Journal 3/1994
1595
1596[2]
1597"Why to Use _declspec(dllimport) & _declspec(dllexport) In Code", MS
1598Knowledge Base Q132044
1599
1600[3]
1601"Windows Q&A" (M. Pietrek), in: Microsoft Systems Journal 8/1995
1602
1603[4]
1604"Writing Multiple-Language Resources", MS Knowledge Base Q89866
1605
1606[5]
1607"The Portable Executable File Format from Top to Bottom" (Randy Kath),
1608in: Microsoft Developer Network
1609
1610[6]
1611Tool Interface Standard (TIS) Formats Specification for Windows Version
16121.0 (Intel Order Number 241597, Intel Corporation 1993)
1613
1614
1615Appendix: hello world
1616---------------------
1617In this appendix I will show how to make programs by hand. The example
1618will use Intel-assembly, because I don't speak DEC Alpha.
1619
1620The program will be the equivalent of
1621
1622 #include <stdio.h>
1623 int main(void)
1624 {
1625 puts(hello,world);
1626 return 0;
1627 }
1628
1629First, I translate it to use Win32 functions instead of the C runtime:
1630
1631 #define STD_OUTPUT_HANDLE -11UL
1632 #define hello "hello, world\n"
1633
1634 __declspec(dllimport) unsigned long __stdcall
1635 GetStdHandle(unsigned long hdl);
1636
1637 __declspec(dllimport) unsigned long __stdcall
1638 WriteConsoleA(unsigned long hConsoleOutput,
1639 const void *buffer,
1640 unsigned long chrs,
1641 unsigned long *written,
1642 unsigned long unused
1643 );
1644
1645 static unsigned long written;
1646
1647 void startup(void)
1648 {
1649 WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE),hello,sizeof(hello)-1,&written,0);
1650 return;
1651 }
1652
1653Now I will fumble out the assembly:
1654 startup:
1655 ; parameters for WriteConsole(), backwards
1656 6A 00 push 0x00000000
1657 68 ?? ?? ?? ?? push offset _written
1658 6A 0D push 0x0000000d
1659 68 ?? ?? ?? ?? push offset hello
1660 ; parameter for GetStdHandle()
1661 6A F5 push 0xfffffff5
1662 2E FF 15 ?? ?? ?? ?? call dword ptr cs:__imp__GetStdHandle@4
1663 ; result is last parameter for WriteConsole()
1664 50 push eax
1665 2E FF 15 ?? ?? ?? ?? call dword ptr cs:__imp__WriteConsoleA@20
1666 C3 ret
1667
1668 hello:
1669 68 65 6C 6C 6F 2C 20 77 6F 72 6C 64 0A "hello, world\n"
1670 _written:
1671 00 00 00 00
1672
1673That was the compiler part. Anyone can do that. From now on we play
1674linker, which is much more interesting :-)
1675
1676I need to find the functions WriteConsoleA() and GetStdHandle(). They
1677happen to be in "kernel32.dll". (That was the 'import library' part.)
1678
1679Now I can start to make the executable. Question marks will take the
1680place of yet-to-find-out values; they will be patched afterwards.
1681
1682First the DOS-stub, starting at 0x0 and being 0x40 bytes long:
1683 00 | 4d 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1684 10 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1685 20 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1686 30 | 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00
1687As you can see, this isn't really a MS-DOS program. It's just the header
1688with the signature "MZ" at the beginning and the e_lfanew pointing
1689immediatly after the header, without any code. That's because it isn't
1690intended to run on MS-DOS; it's just here because the specification
1691requires it.
1692
1693Then the PE signature, starting at 0x40 and being 0x4 bytes long:
1694 50 45 00 00
1695
1696Now the file-header, which will start at byte 0x44 and is 0x14 bytes long:
1697 Machine 4c 01 ; i386
1698 NumberOfSections 02 00 ; code and data
1699 TimeDateStamp 00 00 00 00 ; who cares?
1700 PointerToSymbolTable 00 00 00 00 ; unused
1701 NumberOfSymbols 00 00 00 00 ; unused
1702 SizeOfOptionalHeader e0 00 ; constant
1703 Characteristics 02 01 ; executable on 32-bit-machine
1704
1705And the optional header, which will start at byte 0x58 and is 0x60 bytes long:
1706 Magic 0b 01 ; constant
1707 MajorLinkerVersion 00 ; I'm version 0.0 :-)
1708 MinorLinkerVersion 00 ;
1709 SizeOfCode 20 00 00 00 ; 32 bytes of code
1710 SizeOfInitializedData ?? ?? ?? ?? ; yet to find out
1711 SizeOfUninitializedData 00 00 00 00 ; we don't have a BSS
1712 AddressOfEntryPoint ?? ?? ?? ?? ; yet to find out
1713 BaseOfCode ?? ?? ?? ?? ; yet to find out
1714 BaseOfData ?? ?? ?? ?? ; yet to find out
1715 ImageBase 00 00 10 00 ; 1 MB, chosen arbitrarily
1716 SectionAlignment 20 00 00 00 ; 32-bytes-alignment
1717 FileAlignment 20 00 00 00 ; 32-bytes-alignment
1718 MajorOperatingSystemVersion 04 00 ; NT 4.0
1719 MinorOperatingSystemVersion 00 00 ;
1720 MajorImageVersion 00 00 ; version 0.0
1721 MinorImageVersion 00 00 ;
1722 MajorSubsystemVersion 04 00 ; Win32 4.0
1723 MinorSubsystemVersion 00 00 ;
1724 Win32VersionValue 00 00 00 00 ; unused?
1725 SizeOfImage ?? ?? ?? ?? ; yet to find out
1726 SizeOfHeaders ?? ?? ?? ?? ; yet to find out
1727 CheckSum 00 00 00 00 ; not used for non-drivers
1728 Subsystem 03 00 ; Win32 console
1729 DllCharacteristics 00 00 ; unused (not a DLL)
1730 SizeOfStackReserve 00 00 10 00 ; 1 MB stack
1731 SizeOfStackCommit 00 10 00 00 ; 4 KB to start with
1732 SizeOfHeapReserve 00 00 10 00 ; 1 MB heap
1733 SizeOfHeapCommit 00 10 00 00 ; 4 KB to start with
1734 LoaderFlags 00 00 00 00 ; unknown
1735 NumberOfRvaAndSizes 10 00 00 00 ; constant
1736
1737As you can see, I plan to have only 2 sections, one for code and one for
1738all the rest (data, constants and import directory). There will be no
1739relocations and no other stuff like resources. Also I won't have a BSS
1740segment and stuff the variable 'written' into the initialized data.
1741The section alignment is the same in the file and in RAM (32 bytes);
1742this helps to keep the task easy, otherwise I'd have to calculate RVAs
1743back and forth too much.
1744
1745Now we set up the data directories, beginning at byte 0xb8 and being 0x80 bytes long:
1746 Address Size
1747 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_EXPORT (0)
1748 ?? ?? ?? ?? ?? ?? ?? ?? ; IMAGE_DIRECTORY_ENTRY_IMPORT (1)
1749 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_RESOURCE (2)
1750 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_EXCEPTION (3)
1751 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_SECURITY (4)
1752 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_BASERELOC (5)
1753 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_DEBUG (6)
1754 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_COPYRIGHT (7)
1755 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_GLOBALPTR (8)
1756 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_TLS (9)
1757 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG (10)
1758 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (11)
1759 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_IAT (12)
1760 00 00 00 00 00 00 00 00 ; 13
1761 00 00 00 00 00 00 00 00 ; 14
1762 00 00 00 00 00 00 00 00 ; 15
1763Only the import directory is in use.
1764
1765Next are the section headers. First we make the code section, which will
1766contain the above mentioned assembly. It is 32 bytes long, and so will
1767be the code section. The header begins at 0x138 and is 0x28 bytes long:
1768
1769 Name 2e 63 6f 64 65 00 00 00 ; ".code"
1770 VirtualSize 00 00 00 00 ; unused
1771 VirtualAddress ?? ?? ?? ?? ; yet to find out
1772 SizeOfRawData 20 00 00 00 ; size of code
1773 PointerToRawData ?? ?? ?? ?? ; yet to find out
1774 PointerToRelocations 00 00 00 00 ; unused
1775 PointerToLinenumbers 00 00 00 00 ; unused
1776 NumberOfRelocations 00 00 ; unused
1777 NumberOfLinenumbers 00 00 ; unused
1778 Characteristics 20 00 00 60 ; code, executable, readable
1779
1780The second section will contain the data. The header begins at 0x160 and
1781is 0x28 bytes long:
1782
1783 Name 2e 64 61 74 61 00 00 00 ; ".data"
1784 VirtualSize 00 00 00 00 ; unused
1785 VirtualAddress ?? ?? ?? ?? ; yet to find out
1786 SizeOfRawData ?? ?? ?? ?? ; yet to find out
1787 PointerToRawData ?? ?? ?? ?? ; yet to find out
1788 PointerToRelocations 00 00 00 00 ; unused
1789 PointerToLinenumbers 00 00 00 00 ; unused
1790 NumberOfRelocations 00 00 ; unused
1791 NumberOfLinenumbers 00 00 ; unused
1792 Characteristics 40 00 00 c0 ; initialized, readable, writeable
1793
1794The next byte is 0x188, but the sections need to be aligned to 32 bytes
1795(because I chose so), so we need padding bytes up to 0x1a0:
1796
1797 00 00 00 00 00 00 ; padding
1798 00 00 00 00 00 00
1799 00 00 00 00 00 00
1800 00 00 00 00 00 00
1801
1802
1803Now the first section, being the code section with the above mentioned
1804assembly, *does* come. It begins at byte 0x1a0 and is 0x20 bytes long:
1805 6A 00 ; push 0x00000000
1806 68 ?? ?? ?? ?? ; push offset _written
1807 6A 0D ; push 0x0000000d
1808 68 ?? ?? ?? ?? ; push offset hello_string
1809 6A F5 ; push 0xfffffff5
1810 2E FF 15 ?? ?? ?? ?? ; call dword ptr cs:__imp__GetStdHandle@4
1811 50 ; push eax
1812 2E FF 15 ?? ?? ?? ?? ; call dword ptr cs:__imp__WriteConsoleA@20
1813 C3 ; ret
1814
1815Because of the previous section's length we don't need any padding
1816before the next section (data), and here it comes, beginning at 0x1c0:
1817
1818 68 65 6C 6C 6F 2C 20 77 6F 72 6C 64 0A ; "hello, world\n"
1819 00 00 00 ; padding to align _written
1820 00 00 00 00 ; _written
1821
1822Now all that's left is the import directory. It will import 2 functions
1823from "kernel32.dll", and it's immediatly following the variables in the
1824same section. First we will align it to 32 bytes:
1825
1826 00 00 00 00 00 00 00 00 00 00 00 00 ; padding
1827
1828It begins at 0x1e0 with the IMAGE_IMPORT_DESCRIPTOR:
1829 OriginalFirstThunk ?? ?? ?? ?? ; yet to find out
1830 TimeDateStamp 00 00 00 00 ; unbound
1831 ForwarderChain ff ff ff ff ; no forwarders
1832 Name ?? ?? ?? ?? ; yet to find out
1833 FirstThunk ?? ?? ?? ?? ; yet to find out
1834
1835We need to terminate the import-directory with a 0-bytes-entry (we are at 0x1f4):
1836 OriginalFirstThunk 00 00 00 00 ; terminator
1837 TimeDateStamp 00 00 00 00 ;
1838 ForwarderChain 00 00 00 00 ;
1839 Name 00 00 00 00 ;
1840 FirstThunk 00 00 00 00 ;
1841
1842Now there's the DLL name left, and the 2 thunks, and the thunk-data, and
1843the function names. But we will be finished real soon now!
1844
1845The DLL name, 0-terminated, beginning at 0x208:
1846 6b 65 72 6e 65 6c 33 32 2e 64 6c 6c 00 ; "kernel32.dll"
1847 00 00 00 ; padding to 32-bit-boundary
1848
1849The original first thunk, starting at 0x218:
1850 AddressOfData ?? ?? ?? ?? ; RVA to function name "WriteConsoleA"
1851 AddressOfData ?? ?? ?? ?? ; RVA to function name "GetStdHandle"
1852 00 00 00 00 ; terminator
1853
1854The first thunk is exactly the same list and starts at 0x224:
1855(__imp__WriteConsoleA@20, at 0x224)
1856 AddressOfData ?? ?? ?? ?? ; RVA to function name "WriteConsoleA"
1857(__imp__GetStdHandle@4, at 0x228)
1858 AddressOfData ?? ?? ?? ?? ; RVA to function name "GetStdHandle"
1859 00 00 00 00 ; terminator
1860
1861Now what's left is the two function names in the shape of an
1862IMAGE_IMPORT_BY_NAME. We are at byte 0x230.
1863 01 00 ; ordinal, need not be correct
1864 57 72 69 74 65 43 6f 6e 73 6f 6c 65 41 00 ; "WriteConsoleA"
1865 02 00 ; ordinal, need not be correct
1866 47 65 74 53 74 64 48 61 6e 64 6c 65 00 ; "GetStdHandle"
1867
1868Ok, that's about all. The next byte, which we don't really need, is
18690x24f. We need to fill the section with padding up to 0x260:
1870 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; padding
1871 00
1872
1873------------
1874
1875We are done. Now that we know all the byte-offsets, we can apply fixups
1876to all those addresses and sizes that were indicated as "unknown" with
1877'??'-marks.
1878I won't force you to read that step-by-step (it's quite
1879straightforward), and simply present the result:
1880
1881------------
1882
1883DOS-header, starting at 0x0:
1884 00 | 4d 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1885 10 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1886 20 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1887 30 | 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00
1888
1889signature, starting at 0x40:
1890 50 45 00 00
1891
1892file-header, starting at 0x44:
1893 Machine 4c 01 ; i386
1894 NumberOfSections 02 00 ; code and data
1895 TimeDateStamp 00 00 00 00 ; who cares?
1896 PointerToSymbolTable 00 00 00 00 ; unused
1897 NumberOfSymbols 00 00 00 00 ; unused
1898 SizeOfOptionalHeader e0 00 ; constant
1899 Characteristics 02 01 ; executable on 32-bit-machine
1900
1901optional header, starting at 0x58:
1902 Magic 0b 01 ; constant
1903 MajorLinkerVersion 00 ; I'm version 0.0 :-)
1904 MinorLinkerVersion 00 ;
1905 SizeOfCode 20 00 00 00 ; 32 bytes of code
1906 SizeOfInitializedData a0 00 00 00 ; data section size
1907 SizeOfUninitializedData 00 00 00 00 ; we don't have a BSS
1908 AddressOfEntryPoint a0 01 00 00 ; beginning of code section
1909 BaseOfCode a0 01 00 00 ; RVA to code section
1910 BaseOfData c0 01 00 00 ; RVA to data section
1911 ImageBase 00 00 10 00 ; 1 MB, chosen arbitrarily
1912 SectionAlignment 20 00 00 00 ; 32-bytes-alignment
1913 FileAlignment 20 00 00 00 ; 32-bytes-alignment
1914 MajorOperatingSystemVersion 04 00 ; NT 4.0
1915 MinorOperatingSystemVersion 00 00 ;
1916 MajorImageVersion 00 00 ; version 0.0
1917 MinorImageVersion 00 00 ;
1918 MajorSubsystemVersion 04 00 ; Win32 4.0
1919 MinorSubsystemVersion 00 00 ;
1920 Win32VersionValue 00 00 00 00 ; unused?
1921 SizeOfImage c0 00 00 00 ; sum of all section sizes
1922 SizeOfHeaders a0 01 00 00 ; offset to 1st section
1923 CheckSum 00 00 00 00 ; not used for non-drivers
1924 Subsystem 03 00 ; Win32 console
1925 DllCharacteristics 00 00 ; unused (not a DLL)
1926 SizeOfStackReserve 00 00 10 00 ; 1 MB stack
1927 SizeOfStackCommit 00 10 00 00 ; 4 KB to start with
1928 SizeOfHeapReserve 00 00 10 00 ; 1 MB heap
1929 SizeOfHeapCommit 00 10 00 00 ; 4 KB to start with
1930 LoaderFlags 00 00 00 00 ; unknown
1931 NumberOfRvaAndSizes 10 00 00 00 ; constant
1932
1933data directories, starting at 0xb8:
1934 Address Size
1935 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_EXPORT (0)
1936 e0 01 00 00 6f 00 00 00 ; IMAGE_DIRECTORY_ENTRY_IMPORT (1)
1937 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_RESOURCE (2)
1938 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_EXCEPTION (3)
1939 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_SECURITY (4)
1940 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_BASERELOC (5)
1941 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_DEBUG (6)
1942 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_COPYRIGHT (7)
1943 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_GLOBALPTR (8)
1944 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_TLS (9)
1945 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG (10)
1946 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (11)
1947 00 00 00 00 00 00 00 00 ; IMAGE_DIRECTORY_ENTRY_IAT (12)
1948 00 00 00 00 00 00 00 00 ; 13
1949 00 00 00 00 00 00 00 00 ; 14
1950 00 00 00 00 00 00 00 00 ; 15
1951
1952section header (code), starting at 0x138:
1953 Name 2e 63 6f 64 65 00 00 00 ; ".code"
1954 VirtualSize 00 00 00 00 ; unused
1955 VirtualAddress a0 01 00 00 ; RVA to code section
1956 SizeOfRawData 20 00 00 00 ; size of code
1957 PointerToRawData a0 01 00 00 ; file offset to code section
1958 PointerToRelocations 00 00 00 00 ; unused
1959 PointerToLinenumbers 00 00 00 00 ; unused
1960 NumberOfRelocations 00 00 ; unused
1961 NumberOfLinenumbers 00 00 ; unused
1962 Characteristics 20 00 00 60 ; code, executable, readable
1963
1964section header (data), starting at 0x160:
1965 Name 2e 64 61 74 61 00 00 00 ; ".data"
1966 VirtualSize 00 00 00 00 ; unused
1967 VirtualAddress c0 01 00 00 ; RVA to data section
1968 SizeOfRawData a0 00 00 00 ; size of data section
1969 PointerToRawData c0 01 00 00 ; file offset to data section
1970 PointerToRelocations 00 00 00 00 ; unused
1971 PointerToLinenumbers 00 00 00 00 ; unused
1972 NumberOfRelocations 00 00 ; unused
1973 NumberOfLinenumbers 00 00 ; unused
1974 Characteristics 40 00 00 c0 ; initialized, readable, writeable
1975
1976(padding)
1977 00 00 00 00 00 00 ; padding
1978 00 00 00 00 00 00
1979 00 00 00 00 00 00
1980 00 00 00 00 00 00
1981
1982code section, starting at 0x1a0:
1983 6A 00 ; push 0x00000000
1984 68 d0 01 10 00 ; push offset _written
1985 6A 0D ; push 0x0000000d
1986 68 c0 01 10 00 ; push offset hello_string
1987 6A F5 ; push 0xfffffff5
1988 2E FF 15 28 02 10 00 ; call dword ptr cs:__imp__GetStdHandle@4
1989 50 ; push eax
1990 2E FF 15 24 02 10 00 ; call dword ptr cs:__imp__WriteConsoleA@20
1991 C3 ; ret
1992
1993data section, beginning at 0x1c0:
1994 68 65 6C 6C 6F 2C 20 77 6F 72 6C 64 0A ; "hello, world\n"
1995 00 00 00 ; padding to align _written
1996 00 00 00 00 ; _written
1997padding:
1998 00 00 00 00 00 00 00 00 00 00 00 00 ; padding
1999IMAGE_IMPORT_DESCRIPTOR, starting at 0x1e0:
2000 OriginalFirstThunk 18 02 00 00 ; RVA to orig. 1st thunk
2001 TimeDateStamp 00 00 00 00 ; unbound
2002 ForwarderChain ff ff ff ff ; no forwarders
2003 Name 08 02 00 00 ; RVA to DLL name
2004 FirstThunk 24 02 00 00 ; RVA to 1st thunk
2005terminator (0x1f4):
2006 OriginalFirstThunk 00 00 00 00 ; terminator
2007 TimeDateStamp 00 00 00 00 ;
2008 ForwarderChain 00 00 00 00 ;
2009 Name 00 00 00 00 ;
2010 FirstThunk 00 00 00 00 ;
2011The DLL name, at 0x208:
2012 6b 65 72 6e 65 6c 33 32 2e 64 6c 6c 00 ; "kernel32.dll"
2013 00 00 00 ; padding to 32-bit-boundary
2014original first thunk, starting at 0x218:
2015 AddressOfData 30 02 00 00 ; RVA to function name "WriteConsoleA"
2016 AddressOfData 40 02 00 00 ; RVA to function name "GetStdHandle"
2017 00 00 00 00 ; terminator
2018first thunk, starting at 0x224:
2019 AddressOfData 30 02 00 00 ; RVA to function name "WriteConsoleA"
2020 AddressOfData 40 02 00 00 ; RVA to function name "GetStdHandle"
2021 00 00 00 00 ; terminator
2022IMAGE_IMPORT_BY_NAME, at byte 0x230:
2023 01 00 ; ordinal, need not be correct
2024 57 72 69 74 65 43 6f 6e 73 6f 6c 65 41 00 ; "WriteConsoleA"
2025IMAGE_IMPORT_BY_NAME, at byte 0x240:
2026 02 00 ; ordinal, need not be correct
2027 47 65 74 53 74 64 48 61 6e 64 6c 65 00 ; "GetStdHandle"
2028(padding)
2029 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; padding
2030 00
2031First unused byte: 0x260
2032
2033--------------
2034
2035Alas, this works on NT but didn't on windows 95. windows95 can't run
2036applications with a section alignment of 32 bytes, it needs an
2037alignment of 4 KB and, apparently, a file alignment of 512 bytes. So for
2038windows95 you'll have to insert a large number of 0-bytes (for padding)
2039and adjust the RVAs. Thanks go to D. Binette for testing on windows95.
2040
2041
2042 -- end of text --