This essay gives an introduction to the .rsrc section of PE files. I'll show
how to parse it in order to locate the different resources and replacing icons
in this section will serve as an useful example.
The .rsrc section of PE files is the section where all kinds of resources are
stored. There are 15 predefined resource-types: RT_ACCELERATOR (Accelerator
table), RT_BITMAP (Bitmap resource), RT_DIALOG (Dialog box), RT_FONT (Font resource),
RT_FONTDIR (Font directory resource), RT_MENU (Menu resource), RT_RCDATA (Application-defined
resource (raw data)), RT_STRING (String-table entry), RT_MESSAGETABLE (Message-table
entry), RT_CURSOR (Hardware-dependent cursor resource), RT_GROUP_CURSOR (Hardware-independent
cursor resource), RT_ICON (Hardware-dependent icon resource), RT_GROUP_ICON
(Hardware-independent icon resource), RT_VERSION (Version resource). Additionaly
you can define your own resource types. Since I concentrate on the icons, only
RT_ICON and RT_GROUP_ICON will be important. The definition from the win32.hlp
(Hardware-dependent icon resource/ Hardware-independent icon resource) may sound
a little complicated. In fact, it is nothing more but a ICO file which is seperated
into two parts: The header (RT_GROUP_ICON) and the data of the icon (RT_ICON).
On http://www.wotsit.org you can find a
great documentation about icon resources in PE files.
The rsrc section is a table which contains all data about the different resources
in different definition-level. I will present the information that is needed
here, if you want a deeper look at the structure of the .rsrc section please
visit http://carpathia.cjb.net/pe_format.
Since an example is more useful than 1000 definitions I coded a small example
which contains several types of resources and I'll explain every byte of the
.rsrc section.
At first we have to locate the .rsrc section. The name of the section does
not matter in any way, so we can't use the section definition of the PE header
to locate the bytes where the resources are saved. To find the start of the
PE header we look at the bytes 3Ch and 3Dh of the file. This word value tells
where the the PE header starts. Take care that it is little-endian and you have
to reverse the byte order. In our example.exe we find 0C00. This means that
the PE header starts at 00C0h and not at 0C00h. 88h bytes after the PE
header starts (in example.exe C0h+88h=148h) we find a DWORD value which indicates
the start of the resource definition. 4 bytes ahead (at C0h+8Ch=14Ch) we find
the length of the resource section. In example.exe the start is 4000h and the
length is 820h. You'll quickly find out that example.exe is only 13FFh bytes
long and there's no offset 4000h. The problem here is that the 4000h is the
virtual offset (the one in memory) and not the one you will use for API functions
likeWriteFile/ReadFile (those use the so called "Raw Offset"). If
you don't know how to convert from virtual offset to raw offset and vice versa,
please read here. If you already know
that I can tell you that the raw offset to virtual offset 4000h is A00h.
The complete .rsrc section of example.exe
00000A00 0000 0000 0000 0000 0000 0000 0000 0300 ................
00000A10 0300 0000 2800 0080 0500 0000 4800 0080 ....(.......H...
00000A20 0E00 0000 6000 0080 0000 0000 0000 0000 ....`...........
00000A30 0000 0000 0000 0200 0100 0000 8000 0080 ................
00000A40 0200 0000 9800 0080 0000 0000 0000 0000 ................
00000A50 0000 0000 0100 0000 4801 0080 B000 0080 ........H.......
00000A60 0000 0000 0000 0000 0000 0000 0100 0100 ................
00000A70 5601 0080 C800 0080 6400 0000 E000 0080 V.......d.......
00000A80 0000 0000 0000 0000 0000 0000 0000 0100 ................
00000A90 0000 0000 F800 0000 0000 0000 0000 0000 ................
00000AA0 0000 0000 0000 0100 0000 0000 0801 0000 ................
00000AB0 0000 0000 0000 0000 0000 0000 0000 0100 ................
00000AC0 0000 0000 1801 0000 0000 0000 0000 0000 ................
00000AD0 0000 0000 0000 0100 0000 0000 2801 0000 ............(...
00000AE0 0000 0000 0000 0000 0000 0000 0000 0100 ................
00000AF0 0000 0000 3801 0000 3842 0000 E802 0000 ....8...8B......
00000B00 0000 0000 0000 0000 3845 0000 E802 0000 ........8E......
00000B10 0000 0000 0000 0000 6041 0000 BC00 0000 ........`A......
00000B20 0000 0000 0000 0000 2045 0000 1400 0000 ........ E......
00000B30 0000 0000 0000 0000 2042 0000 1400 0000 ........ B......
00000B40 0000 0000 0000 0000 0600 4400 4900 4100 ..........D.I.A.
00000B50 4C00 4F00 4700 0400 4900 4300 4F00 4E00 L.O.G...I.C.O.N.
00000B60 0100 FFFF 0000 0000 0000 0000 C400 C890 ................
00000B70 0100 0A00 0A00 AD00 4300 0000 0000 4500 ........C.....E.
00000B80 7800 6100 6D00 7000 6C00 6500 0000 0800 x.a.m.p.l.e.....
00000B90 BC02 0000 4D00 5300 2000 5300 6100 6E00 ....M.S. .S.a.n.
00000BA0 7300 2000 5300 6500 7200 6900 6600 0000 s. .S.e.r.i.f...
00000BB0 0000 0000 0000 0000 0000 0250 1700 1800 ...........P....
00000BC0 9900 0A00 FFFF 0000 FFFF 8200 4500 7800 ............E.x.
00000BD0 6100 6D00 7000 6C00 6500 2000 5000 4500 a.m.p.l.e. .P.E.
00000BE0 2000 6600 6900 6C00 6500 2000 7700 6900 .f.i.l.e. .w.i.
00000BF0 7400 6800 2000 7300 6500 7600 6500 7200 t.h. .s.e.v.e.r.
00000C00 6100 6C00 2000 7200 6500 7300 6F00 7500 a.l. .r.e.s.o.u.
00000C10 7200 6300 6500 7300 0000 0000 0000 0000 r.c.e.s.........
00000C20 0000 0100 0100 2020 1000 0100 0400 E802 ...... ........
00000C30 0000 0100 0000 0000 2800 0000 2000 0000 ........(... ...
00000C40 4000 0000 0100 0400 0000 0000 8002 0000 @...............
00000C50 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000C60 0000 0000 0000 8000 0080 0000 0080 8000 ................
00000C70 8000 0000 8000 8000 8080 0000 C0C0 C000 ................
00000C80 8080 8000 0000 FF00 00FF 0000 00FF FF00 ................
00000C90 FF00 0000 FF00 FF00 FFFF 0000 FFFF FF00 ................
00000CA0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000CB0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000CC0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000CD0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000CE0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000CF0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000D00 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000D10 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000D20 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000D30 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000D40 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000D50 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000D60 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000D70 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000D80 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000D90 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000DA0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000DB0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000DC0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000DD0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000DE0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000DF0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000E00 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000E10 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000E20 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000E30 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000E40 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000E50 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000E60 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000E70 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000E80 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000E90 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000EA0 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF ................
00000EB0 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF ................
00000EC0 FFFC 1FFF FF83 E7FF FE7F F9FF FDFF FEFF ................
00000ED0 F3FF FEFF F7FF FF7F EF00 017F EFFF FF7F ................
00000EE0 EFFF FF7F EFFF FF7F EFFD FF7F EFFF FF7F ................
00000EF0 EFFF FF7F F7FF FF7F F7DF BEFF F7FF FEFF ................
00000F00 FBFF 7EFF FC00 FDFF FFC0 01FF FFFF FFFF ..~.............
00000F10 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF ................
00000F20 0000 0100 0100 2020 1000 0100 0400 E802 ...... ........
00000F30 0000 0200 0000 0000 2800 0000 2000 0000 ........(... ...
00000F40 4000 0000 0100 0400 0000 0000 8002 0000 @...............
00000F50 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000F60 0000 0000 0000 8000 0080 0000 0080 8000 ................
00000F70 8000 0000 8000 8000 8080 0000 C0C0 C000 ................
00000F80 8080 8000 0000 FF00 00FF 0000 00FF FF00 ................
00000F90 FF00 0000 FF00 FF00 FFFF 0000 FFFF FF00 ................
00000FA0 9999 9999 9999 9999 9999 9999 9999 9999 ................
00000FB0 9999 9999 9999 9999 9999 9999 9999 9999 ................
00000FC0 9999 9999 9999 9999 9999 9999 9999 9999 ................
00000FD0 9999 9999 9999 9999 9999 9999 9999 9999 ................
00000FE0 9999 9999 9999 9999 9999 9999 9999 9999 ................
00000FF0 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001000 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001010 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001020 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001030 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001040 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001050 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001060 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001070 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001080 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001090 9999 9999 9999 9999 9999 9999 9999 9999 ................
000010A0 9999 9999 9999 9999 9999 9999 9999 9999 ................
000010B0 9999 9999 9999 9999 9999 9999 9999 9999 ................
000010C0 9999 9999 9999 9999 9999 9999 9999 9999 ................
000010D0 9999 9999 9999 9999 9999 9999 9999 9999 ................
000010E0 9999 9999 9999 9999 9999 9999 9999 9999 ................
000010F0 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001100 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001110 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001120 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001130 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001140 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001150 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001160 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001170 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001180 9999 9999 9999 9999 9999 9999 9999 9999 ................
00001190 9999 9999 9999 9999 9999 9999 9999 9999 ................
000011A0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000011B0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000011C0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000011D0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000011E0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000011F0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001200 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001210 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001220 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001230 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001240 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001250 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001260 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001270 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001280 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001290 0000 0000 0000 0000 0000 0000 0000 0000 ................
000012A0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000012B0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000012C0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000012D0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000012E0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000012F0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001300 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001310 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001320 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001330 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001340 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001350 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001360 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001370 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001380 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001390 0000 0000 0000 0000 0000 0000 0000 0000 ................
000013A0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000013B0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000013C0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000013D0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000013E0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000013F0 0000 0000 0000 0000 0000 0000 0000 0000 ................
Although all of those hex-numbers might look difficult at the first glance
the .rsrc section is quite well-strucured and getting the idea of the different
tables of the definitions is quickly understood.
The bytes 0A00-0A17 represent
typedef struct _IMAGE_RESOURCE_DIRECTORY {
ULONG Characteristics;
ULONG TimeDateStamp;
USHORT MajorVersion;
USHORT MinorVersion;
USHORT NumberOfNamedEntries;
USHORT NumberOfIdEntries;
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
(Taken from "The Portable Executable File Format from Top to Bottom "
by Randy Kath)
This means the following for the single bytes:
0A00-0A03: Characteristics set to 0
0A04-0A07: TimeDateStamp set to 0
0A08-0A09: MajorVersion set to 0
0A0A-0A0B: MinorVersion set to 0
0A0C-0A0D: NumberOfNamedEntries: 0
0A0E-0A0F: NumberOfIdEntries: 3
There are two ways to define resource types. Either you can define them through
a name (ASCIIZ-String like "MyRes") or through an Id (Number like
1234). In the example all resource types (3) are defined through an Id. Right
after this first definition of the resources this follows:
typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
ULONG Name;
ULONG OffsetToData;
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
(Taken from "The Portable Executable File Format from Top to Bottom "
by Randy Kath)
Here are the pointers to the different resource types stored. In our example
this there are 3 resource types and the definitions for those are stored at
the offsets A10-A28.
00000A10 0300 0000 2800 0080 0500 0000 4800 0080 ....(.......H...
00000A20 0E00 0000 6000 0080 ....`...
We see the resource types 03 (RT_ICON), 05 (RT_DIALOG) and 0E (RT_GROUP_ICON).
Their offet-pointers point to 28h, 48h and 60h. This means a closer definition
of RT_ICON starts 28h bytes after the .rsrc section started and a closer definition
of RT_GROUP_ICON starts 60h bytes after the .rsrc section started. I don't follow
the RT_DIALOG anymore because it is not used for replacing icons. I just put
it into the example file, so that the icon related resources are not the only
ones in the .rsrc section.
At 28h we find this:
00000A28 0000 0000 0000 0000 0000 0000 0000 0200 ................
00000A38 0100 0000 8000 0080 0200 0000 9800 0080 ................
It's another IMAGE_RESOURCE_DIRECTORY that tells us that we have 2 icons which
are identified through their Ids. You could complain now and tell me that one
icon is defined through the name "ICON" but you'll see the reason,
later. Attached to this IMAGE_RESOURCE_DIRECTORY we find two IMAGE_RESOURCE_DIRECTORY_ENTRY
structures for further definition of the two icons (at offset 80h and 98h after
the .rsrc section start).
Here you find one more IMAGE_RESOURCE_DIRECTORY which tells us that the two
icon resources contain one icon each and their definition starts at F8h and
108h after the .rsrc section starts:
00000A80 0000 0000 0000 0000 0000 0000 0000 0100 ................
00000A90 0000 0000 F800 0000 0000 0000 0000 0000 ................
00000AA0 0000 0000 0000 0100 0000 0000 0801 0000 ................
This is right here and we finally reached the end: The first icon starts at
the virtual offset (the one in memory) 42E8 (+ImageBase) and is 2E8 bytes long.
The second icon starts at virtual offset 45E8 and is 2E8 bytes long. To convert
virtual offset to raw offset please read the essay
about this conversion in this issue of the Programming Journal.
00000AF8 3842 0000 E802 0000 0000 0000 0000 0000 8B..............
00000B08 3845 0000 E802 0000 0000 0000 0000 0000 8E..............
Now we only have one problem left. The icon resources are 2E8 bytes long. That
is 744 in decimal. The icons I created and added were 766 bytes, though. There
are 22 bytes missing. Furthermore we don't know how to find the identifiers
of the icons as they are displayed in a resource editor (100 and "ICON").
The answer to those questions is given in the RT_GROUP_ICON resource type. It
contains the header - which gets separated from the icon data - of all icon
files that are added to a PE file. To find this information the way is completely
the same as for finding the RT_ICON data. This time we start at A60h. This was
the offset we found in the first step as offset where RT_GROUP_ICON definition
starts (60h bytes after the .rsrc section starts).
00000A60 0000 0000 0000 0000 0000 0000 0100 0100 ................
00000A70 5601 0080 C800 0080 6400 0000 E000 0080 V.......d.......
The IMAGE_RESOURCE_DIRECTORY says: "One icon identified through a name
and another one through an Id". The first icon's name can be found 156h
bytes after the .rsrc section starts, it's further definition can be found C8h
bytes after the start. The second icon's Id is 64h = 100 and further definition
can be found E0h bytes after the start of the .rsrc section. Here you can see
why all offset-pointers have 80h as highest bytes: If the highest byte is 80h,
it is a pointer to the offset where the icon's name is stored (56010080), if
the highest byte is 00h you have the ID (64000000). I guess it is not so important
that the highest byte is 80h but that the highest bit is set. But I never saw
an EXE file with such a huge .rsrc section to fill out the 3 lower bytes of
the dword which serves as offset pointer.
At C8 and E0 you find two more pointers to 128h and 138h and you learn that
both icon resources only include one icon:
00000AC8 0000 0000 0000 0000 0000 0000 0000 0100 ................
00000AD8 0000 0000 2801 0000 0000 0000 0000 0000 ....(...........
00000AE8 0000 0000 0000 0100 0000 0000 3801 0000 ............8...
At the very end of the definition you can see that the first header is located
at 4520h and is 14h bytes long. The 2nd header is at 4220 and is 14h bytes long.
00000B28 2045 0000 1400 0000 0000 0000 0000 0000 E..............
00000B38 2042 0000 1400 0000 0000 0000 0000 0000 B..............
Only one question left. We missed 22 bytes but we only found 14h = 20 bytes.
The reason is simple. The header of an .ICO file is 2 bytes longer than the
one that gets saved to the PE file. In the .ICO file there is a DWORD value
which says where the icon data starts. This is not needed in a PE file because
the pointer to the icon data is stored somewhere else as you saw above. In a
PE file this DWORD value gets a WORD value which holds the ID of the icon.
|