Skip to content

Last review: Sept 15,2025

MUI

Multilingual User Interface (MUI) resources allow Windows to translate other resources from one language to another. To open an MUI resource, a program can call Windows functions. Quite surprisingly, these functions will reopen the file and read the resource section. This means that such Windows functions will search in the resource section of our PE loader, not the executable we want to load.

To circumvent this issue, we need to replace the resource section of our PE loader with the one from the PE file we want to load. One way to do this is by creating a new section in the PE file representing our PE loader, copying the content of the resource section from the PE file we want to load into this new section, and finally updating all pointers that refer to the resource section to point to the new section.

The following diagram illustrates the creation of this new section and the update of the corresponding pointers:

An executable can have multiple resources that are organized in directories, which can be viewed as folders. A directory is represented by the structure IMAGE_RESOURCE_DIRECTORY.

CPP
typedef struct _IMAGE_RESOURCE_DIRECTORY {
	DWORD	Characteristics;
	DWORD	TimeDateStamp;
	WORD	MajorVersion;
	WORD	MinorVersion;
	WORD	NumberOfNamedEntries;
	WORD	NumberOfIdEntries;
	/*  IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; */
} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY;

This structure is immediately followed by a table of entries. The fields NumberOfNamedEntries and NumberOfIdEntries indicate the number of entries. Each entry is represented by the following structure:

CPP
typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
	...
	union {
		DWORD   OffsetToData;
		struct {
#ifdef BITFIELDS_BIGENDIAN
			unsigned DataIsDirectory:1;
			unsigned OffsetToDirectory:31;
#else
			unsigned OffsetToDirectory:31;
			unsigned DataIsDirectory:1;
#endif
		} DUMMYSTRUCTNAME2;
	} DUMMYUNIONNAME2;
} IMAGE_RESOURCE_DIRECTORY_ENTRY,*PIMAGE_RESOURCE_DIRECTORY_ENTRY;

The field DataIsDirectory indicates whether the entry is a directory or a resource. The fields OffsetToDirectory and OffsetToData provide the offset, relative to the beginning of the resource section, to locate either the directory or the resource.

A resource is represented by:

CPP
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
	DWORD	OffsetToData;
	DWORD	Size;
	DWORD	CodePage;
	DWORD	Reserved;
} IMAGE_RESOURCE_DATA_ENTRY,*PIMAGE_RESOURCE_DATA_ENTRY;

Finally, OffsetToData provides the offset from @BASE where the raw data can be found. This is the field that needs to be corrected.