Visual Studio 2010!

Read now >

View Now
DevSource RSS FEEDS
XML Want an easy way to keep up with breaking tech news? And the Get DevSource headlines delivered to your desktop with RSS.
ADVERTISEMENT
ADVERTISEMENT

 

DevSource.com: Your Source for Visual Studio on Facebook
ADVERTISEMENT
Retrieve Resources From PE Files (Part I)
By Jeff Friesen

Rate This Article: Add This Article To:

Retrieve Resources From PE Files (Part I)
( Page 4 of 4 )

Tour a PE file's resource section

Let's reinforce our understanding of the resource section's organization by touring an example PE file, such as Windows XP's notepad.exe. To prepare for the tour, I dumped the contents of this file's resource section to another file and used the old MS-DOS DEBUG program to present that file's content, beginning with the root directory:

0C53:0100  00 00 00 00 00 00 00 00-00 00 00 00 00 00 08 00   ................
0C53:0110 03 00 00 00 50 00 00 80-04 00 00 00 A8 00 00 80 ....P...........
0C53:0120 05 00 00 00 C0 00 00 80-06 00 00 00 F0 00 00 80 ................
0C53:0130 09 00 00 00 20 01 00 80-0E 00 00 00 40 01 00 80 .... .......@...
0C53:0140 10 00 00 00 58 01 00 80-18 00 00 00 70 01 00 80 ....X.......p...
Note
DEBUG presents content in a sequence of rows, where each row begins with an address presented in a 16-bit segment:16-bit offset format. Furthermore, each row presents 16 byte-values followed by the ASCII values corresponding to those bytes. (The ASCII values are handy for observing string data.) Addresses and byte values are shown in hexadecimal.

The root directory begins at 0C53:0100 with its four-byte Characteristics field. This field is followed by a four-byte TimeDateStamp field, a two-byte MajorVersion field, and a two-byte MinorVersion field. All of these fields contain 0s and aren't relevant to retrieving resources.

The two-byte NumberOfNamedEntries field comes next (beginning at 0C53:010C). This field contains 0, which means that there are no named resource type directories. Immediately following NumberOfNamedEntries is the two-byte NumberOfIdEntries field, which contains 8 -- there are eight type directories identified by integer IDs.

Note
PE files store multi-byte values such that the least-significant byte is stored first.

The eight type directories are described by eight IMAGE_RESOURCE_DIRECTORY structures that begin at 0C53:0110. The first four bytes of each structure store the contents of the Name field; the next four structure bytes store the OffsetToData field's value. Table 2 presents and interprets the contents of all eight structures.

Structure Address Name Field Value OffsetToData Field Value Interpretation
0C53:0110 00000003 80000050 Name's value identifies the RT_ICON resource type. OffsetToData's value identifies an offset to the icon type directory's IMAGE_RESOURCE_DIRECTORY structure, which is located at 0C53:0100+50=0C53:0150.
0C53:0118 00000004 800000A8 Name's value identifies the RT_MENU resource type. OffsetToData's value identifies an offset to the menu type directory's IMAGE_RESOURCE_DIRECTORY structure, which is located at 0C53:0100+A8=0C53:01A8.
0C53:0120 00000005 800000C0 Name's value identifies the RT_DIALOG resource type. OffsetToData's value identifies an offset to the dialog type directory's IMAGE_RESOURCE_DIRECTORY structure, which is located at 0C53:0100+C0=0C53:01C0.
0C53:0128 00000006 800000F0 Name's value identifies the RT_STRING resource type. OffsetToData's value identifies an offset to the string type directory's IMAGE_RESOURCE_DIRECTORY structure, which is located at 0C53:0100+F0=0C53:01F0.
0C53:0130 00000009 80000120 Name's value identifies the RT_ACCELERATOR resource type. OffsetToData's value identifies an offset to the accelerator type directory's IMAGE_RESOURCE_DIRECTORY structure, which is located at 0C53:0100+120=0C53:0220.
0C53:0138 0000000E 80000140 Name's value identifies the RT_GROUP_ICON resource type. OffsetToData's value identifies an offset to the group icon type directory's IMAGE_RESOURCE_DIRECTORY structure, which is located at 0C53:0100+140=0C53:0240.
0C53:0140 00000010 80000158 Name's value identifies the RT_VERSION resource type. OffsetToData's value identifies an offset to the version type directory's IMAGE_RESOURCE_DIRECTORY structure, which is located at 0C53:0100+158=0C53:0258.
0C53:0148 00000018 80000170 Name's value identifies the RT_MANIFEST resource type. OffsetToData's value identifies an offset to the manifest type directory's IMAGE_RESOURCE_DIRECTORY structure, which is located at 0C53:0100+170=0C53:0270.

Table 2: Root directory resource type directory entries

For brevity, we'll tour only the RT_GROUP_ICON and RT_ICON type directories, the group icon and icon instance directories pointed to by these type directories, and the resource data areas pointed to by these instance directories. Furthermore, because notepad.exe contains several RT_ICON resources, we'll look at only one icon instance directory and its associated data area.

The group icon type directory begins at 0C53:0240. According to the following DEBUG output, NumberOfNamedEntries (at 0C53:024C) is 0; NumberOfIdEntries (at 0C53:024E) identifies one type directory entry. This entry's Name field (at 0C53:0250) specifies integer ID 2 as the identity of a group icon instance directory:

0C53:0240  00 00 00 00 00 00 00 00-00 00 00 00 00 00 01 00   ................
0C53:0250 02 00 00 00 68 03 00 80 ....h...

Additionally, the entry's OffsetToData field (at 0C53:0254) identifies an offset to the group icon instance directory's IMAGE_RESOURCE_DIRECTORY structure. After removing the most-significant bit from 80000368, adding 368 to 0C53:0100 yields the address of this structure -- 0C53:0468:

0C53:0460                          00 00 00 00 00 00 00 00           ........
0C53:0470 00 00 00 00 00 00 01 00-09 04 00 00 F0 04 00 00 ................

Unlike a resource type directory, which can access multiple resource instance directories via the type directory's entries, a resource instance directory will only access a single data area via its single directory entry. This is verified above by the contents of the group icon instance directory's NumberOfIdEntries field, which is located at 0C53:476.

The group icon instance directory's single entry begins at 0C53:0478. Its Name field contains 00000409, which provides the 409 integer ID for this group icon. Its OffsetToData field contains 000004F0, which (because the most-significant bit isn't set) locates the group icon's IMAGE_RESOURCE_DATA_ENTRY structure.

The IMAGE_RESOURCE_DATA_ENTRY structure's address is 0C53:0100+4F0, or 0C53:05F0. As indicated by the following DEBUG output, the structure's four-byte OffsetToData field contains 000119F8, and the structure's four-byte Size field contains 00000084 -- the other two fields don't matter:

0C53:05F0  F8 19 01 00 84 00 00 00-00 00 00 00 00 00 00 00   ................

Unlike previous offsets, 000119F8 is an RVA. You cannot add this value to 0C53:0100 as is. Instead, you first need to subtract the resource section's starting RVA, which happens to be B000, from this value. You then add the difference to 0C53:0100. This calculation results in 0C53:6AF8 as the address of the group icon's resource data:

0C53:6AF0                          00 00 01 00 09 00 30 30           ......00
0C53:6B00 10 00 01 00 04 00 68 06-00 00 01 00 20 20 10 00 ......h..... ..
0C53:6B10 01 00 04 00 E8 02 00 00-02 00 10 10 10 00 01 00 ................
0C53:6B20 04 00 28 01 00 00 03 00-30 30 00 00 01 00 08 00 ..(.....00......
0C53:6B30 A8 0E 00 00 04 00 20 20-00 00 01 00 08 00 A8 08 ...... ........
0C53:6B40 00 00 05 00 10 10 00 00-01 00 08 00 68 05 00 00 ............h...
0C53:6B50 06 00 30 30 00 00 01 00-20 00 A8 25 00 00 07 00 ..00.... ..%....
0C53:6B60 20 20 00 00 01 00 20 00-A8 10 00 00 08 00 10 10 .... .........
0C53:6B70 00 00 01 00 20 00 68 04-00 00 09 00 .... .h.....

If you recall the previous section on resource data formats, an RT_GROUP_ICON resource's data is formatted into an ICOHEADER structure followed by an array of ICODIRENTRY structures. The header's two-byte wNumImages field (located above at 0C53:6AFC) identifies the number of array entries, which happens to be nine.

Each ICODIRENTRY structure contains a two-byte wID field that stores the integer ID of the associated RT_ICON resource. Each RT_ICON describes one of the related images that are stored in an .ico file -- multiple images are stored to account for different screen resolutions. Table 3 lists the addresses and values of the group icon's wID fields.

Address Value
0C53:6B0A 1
0C53:6B18 2
0C53:6B26 3
0C53:6B34 4
0C53:6B42 5
0C53:6B50 6
0C53:6B5E 7
0C53:6B6C 8
0C53:6B7A 9

Table 3: ICODIRENTRY wID field addresses and their ID values

The icon type directory begins at 0C53:0150. According to the following DEBUG output, NumberOfIdEntries (at 0C53:015E) identifies nine type directory entries, whose Name fields store integer IDs -- there are no named entries. All nine entries ultimately reference resource data that's associated with the previous group icon resource:

0C53:0150  00 00 00 00 00 00 00 00-00 00 00 00 00 00 09 00   ................
0C53:0160 01 00 00 00 88 01 00 80-02 00 00 00 A0 01 00 80 ................
0C53:0170 03 00 00 00 B8 01 00 80-04 00 00 00 D0 01 00 80 ................
0C53:0180 05 00 00 00 E8 01 00 80-06 00 00 00 00 02 00 80 ................
0C53:0190 07 00 00 00 18 02 00 80-08 00 00 00 30 02 00 80 ............0...
0C53:01A0 09 00 00 00 48 02 00 80 ....H...

The first directory entry (at 0C53:0160) identifies an icon resource whose integer ID is 1. This entry corresponds to the ICODIRENTRY structure whose wID field also contains 1. The directory entry's OffsetToData field contains 80000188, which locates the icon instance directory's IMAGE_RESOURCE_DIRECTORY structure at 0C53:0288:

0C53:0280                          00 00 00 00 00 00 00 00           ........
0C53:0290 00 00 00 00 00 00 01 00-09 04 00 00 B0 03 00 00 ................

The NumberOfIdEntries field (at 0C53:0296) identifies a single resource instance directory entry (as it should be). The entry's Name field (at 0C53:0298) specifies 409 as the icon's ID. Also, the entry's OffsetToData field specifies 000003B0, which is added to 0C53:0100 to determine the IMAGE_RESOURCE_DATA_ENTRY structure's address:

0C53:04B0  10 B8 00 00 68 06 00 00-00 00 00 00 00 00 00 00   ....h...........

To determine the resource data's address, you need to subtract B000 from the 0000B810 RVA, and add the result to 0C53:0100. The resulting address is 0C53:0910. The 16 bytes beginning at this address specify part of a BITMAPINFOHEADER structure, which is identified by the initial 28 byte value (indicating the structure's size):

0C53:0910  28 00 00 00 30 00 00 00-60 00 00 00 01 00 04 00   (...0...`.......


 
 
>>> More Microsoft Architecture Articles          >>> More By Jeff Friesen