Icons and Cursors (RT_GROUP_CURSOR, RT_GROUP_ICON, RT_CURSOR, RT_ICON)
Icons and cursors follow a near-identical structure in the PE file format, and closely resemble the ICO file format. Each icon is actually a set of individual icon files containing the same image in various resolutions, pixel formats and color palettes.
The relevant code for reading and writing icon resources can be found in the following namespace:
using AsmResolver.PE.Win32Resources.Icon;
Icon resources are represented using the IconResource
class.
In the following, basic usage of this class is described.
Creating Icon Resources
To create a new icon resource, simply use the constructor of the IconResource
class, specifying the type of icons to store.
var icons = new IconResource(IconType.Icon);
var cursors = new IconResource(IconType.Cursor);
Reading Icon Resources
To extract existing icons from a Portable Executable file, you will need to access the root resource directory of a PEImage
.
Then, all icon groups can be obtained using the FromDirectory
factory method:
PEImage image = ...;
var icons = IconResource.FromDirectory(image.Resources, IconType.Icon);
Icon Groups
Icon groups are exposed using the Groups
property, and can be iterated and modified:
foreach (var iconGroup in icons.Groups)
{
Console.WriteLine($"ID: {iconGroup.Id}, LCID: {iconGroup.Lcid}");
}
Each icon group consists of a set of Icons
, each containing pixel data for a specific icon of a particular resolution and format:
IconGroup iconGroup = ...;
foreach (var icon in iconGroup.Icons)
{
Console.WriteLine($"- {icon.Id}, {icon.Width}x{icon.Height}, {icon.PixelData.GetPhysicalSize()} bytes");
}
A single IconEntry
contains both fields for the ICO or CUR header such as Width
and Height
, as well as the raw pixel data in the PixelData
property.
AsmResolver does not provide a way to interpret or reconstruct pixel data stored in an icon entry.
It only exposes a raw ISegment
which can be read using a BinaryStreamReader
or turned into a byte array (see Reading Segment Contents).
byte[] rawData = icon.PixelData.WriteIntoArray();
Note
The PixelData
property contains the icon's raw data excluding the ICO or CUR header.
When modifying icon entries, make sure the header fields in the IconEntry
object itself are therefore updated accordingly.
All collections and properties are mutable, and as such can be used to modify icons stored in a PE file.
Writing Icon Resources
To serialize the (modified) icon resource back to the resources of a PE image, use the InsertIntoDirectory
method:
PEImage image = ...;
IconResource icons = ...;
icons.InsertIntoDirectory(image.Resources);
The PE image can then be saved as normal.
Either rebuild the PE image (see Writing a PE Image), or simply add a new section to the PE file with the contents of image.Resources
(see Adding a new Section).