This page hosts a formal specification of Microsoft PE (Portable Executable) file format using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
All parsing code for JavaScript generated by Kaitai Struct depends on the JavaScript runtime library. You have to install it before you can parse data.
The JavaScript runtime library is available at npm:
npm install kaitai-struct
See the usage examples in the JavaScript notes.
Parse structure from an ArrayBuffer:
var arrayBuffer = ...;
var data = new MicrosoftPe(new KaitaiStream(arrayBuffer));
After that, one can get various attributes from the structure by accessing fields or properties like:
data.mz // => get mz
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['exports', 'kaitai-struct/KaitaiStream'], factory);
} else if (typeof exports === 'object' && exports !== null && typeof exports.nodeType !== 'number') {
factory(exports, require('kaitai-struct/KaitaiStream'));
} else {
factory(root.MicrosoftPe || (root.MicrosoftPe = {}), root.KaitaiStream);
}
})(typeof self !== 'undefined' ? self : this, function (MicrosoftPe_, KaitaiStream) {
/**
* @see {@link https://learn.microsoft.com/en-us/windows/win32/debug/pe-format|Source}
*/
var MicrosoftPe = (function() {
MicrosoftPe.PeFormat = Object.freeze({
ROM_IMAGE: 263,
PE32: 267,
PE32_PLUS: 523,
263: "ROM_IMAGE",
267: "PE32",
523: "PE32_PLUS",
});
function MicrosoftPe(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root || this;
this._read();
}
MicrosoftPe.prototype._read = function() {
this.mz = new MzPlaceholder(this._io, this, this._root);
}
var Annoyingstring = MicrosoftPe.Annoyingstring = (function() {
function Annoyingstring(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
Annoyingstring.prototype._read = function() {
}
Object.defineProperty(Annoyingstring.prototype, 'name', {
get: function() {
if (this._m_name !== undefined)
return this._m_name;
this._m_name = (this.nameZeroes == 0 ? this.nameFromOffset : this.nameFromShort);
return this._m_name;
}
});
Object.defineProperty(Annoyingstring.prototype, 'nameFromOffset', {
get: function() {
if (this._m_nameFromOffset !== undefined)
return this._m_nameFromOffset;
if (this.nameZeroes == 0) {
var io = this._root._io;
var _pos = io.pos;
io.seek((this.nameZeroes == 0 ? this._parent._parent.symbolNameTableOffset + this.nameOffset : 0));
this._m_nameFromOffset = KaitaiStream.bytesToStr(io.readBytesTerm(0, false, true, false), "ASCII");
io.seek(_pos);
}
return this._m_nameFromOffset;
}
});
Object.defineProperty(Annoyingstring.prototype, 'nameFromShort', {
get: function() {
if (this._m_nameFromShort !== undefined)
return this._m_nameFromShort;
if (this.nameZeroes != 0) {
var _pos = this._io.pos;
this._io.seek(0);
this._m_nameFromShort = KaitaiStream.bytesToStr(this._io.readBytesTerm(0, false, true, false), "ASCII");
this._io.seek(_pos);
}
return this._m_nameFromShort;
}
});
Object.defineProperty(Annoyingstring.prototype, 'nameOffset', {
get: function() {
if (this._m_nameOffset !== undefined)
return this._m_nameOffset;
var _pos = this._io.pos;
this._io.seek(4);
this._m_nameOffset = this._io.readU4le();
this._io.seek(_pos);
return this._m_nameOffset;
}
});
Object.defineProperty(Annoyingstring.prototype, 'nameZeroes', {
get: function() {
if (this._m_nameZeroes !== undefined)
return this._m_nameZeroes;
var _pos = this._io.pos;
this._io.seek(0);
this._m_nameZeroes = this._io.readU4le();
this._io.seek(_pos);
return this._m_nameZeroes;
}
});
return Annoyingstring;
})();
/**
* @see {@link https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#the-attribute-certificate-table-image-only|Source}
*/
var CertificateEntry = MicrosoftPe.CertificateEntry = (function() {
CertificateEntry.CertificateRevision = Object.freeze({
REVISION_1_0: 256,
REVISION_2_0: 512,
256: "REVISION_1_0",
512: "REVISION_2_0",
});
CertificateEntry.CertificateTypeEnum = Object.freeze({
X509: 1,
PKCS_SIGNED_DATA: 2,
RESERVED_1: 3,
TS_STACK_SIGNED: 4,
1: "X509",
2: "PKCS_SIGNED_DATA",
3: "RESERVED_1",
4: "TS_STACK_SIGNED",
});
function CertificateEntry(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
CertificateEntry.prototype._read = function() {
this.length = this._io.readU4le();
this.revision = this._io.readU2le();
this.certificateType = this._io.readU2le();
this.certificateBytes = this._io.readBytes(this.length - 8);
}
/**
* Specifies the length of the attribute certificate entry.
*/
/**
* Contains the certificate version number.
*/
/**
* Specifies the type of content in bCertificate
*/
/**
* Contains a certificate, such as an Authenticode signature.
*/
return CertificateEntry;
})();
var CertificateTable = MicrosoftPe.CertificateTable = (function() {
function CertificateTable(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
CertificateTable.prototype._read = function() {
this.items = [];
var i = 0;
while (!this._io.isEof()) {
this.items.push(new CertificateEntry(this._io, this, this._root));
i++;
}
}
return CertificateTable;
})();
/**
* @see 3.3. COFF File Header (Object and Image)
*/
var CoffHeader = MicrosoftPe.CoffHeader = (function() {
CoffHeader.MachineType = Object.freeze({
UNKNOWN: 0,
I386: 332,
R4000: 358,
WCE_MIPS_V2: 361,
ALPHA: 388,
SH3: 418,
SH3_DSP: 419,
SH4: 422,
SH5: 424,
ARM: 448,
THUMB: 450,
ARM_NT: 452,
AM33: 467,
POWERPC: 496,
POWERPC_FP: 497,
IA64: 512,
MIPS16: 614,
ALPHA64_OR_AXP64: 644,
MIPS_FPU: 870,
MIPS16_FPU: 1126,
EBC: 3772,
RISCV32: 20530,
RISCV64: 20580,
RISCV128: 20776,
LOONGARCH32: 25138,
LOONGARCH64: 25188,
AMD64: 34404,
M32R: 36929,
ARM64: 43620,
0: "UNKNOWN",
332: "I386",
358: "R4000",
361: "WCE_MIPS_V2",
388: "ALPHA",
418: "SH3",
419: "SH3_DSP",
422: "SH4",
424: "SH5",
448: "ARM",
450: "THUMB",
452: "ARM_NT",
467: "AM33",
496: "POWERPC",
497: "POWERPC_FP",
512: "IA64",
614: "MIPS16",
644: "ALPHA64_OR_AXP64",
870: "MIPS_FPU",
1126: "MIPS16_FPU",
3772: "EBC",
20530: "RISCV32",
20580: "RISCV64",
20776: "RISCV128",
25138: "LOONGARCH32",
25188: "LOONGARCH64",
34404: "AMD64",
36929: "M32R",
43620: "ARM64",
});
function CoffHeader(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
CoffHeader.prototype._read = function() {
this.machine = this._io.readU2le();
this.numberOfSections = this._io.readU2le();
this.timeDateStamp = this._io.readU4le();
this.pointerToSymbolTable = this._io.readU4le();
this.numberOfSymbols = this._io.readU4le();
this.sizeOfOptionalHeader = this._io.readU2le();
this.characteristics = this._io.readU2le();
}
Object.defineProperty(CoffHeader.prototype, 'symbolNameTableOffset', {
get: function() {
if (this._m_symbolNameTableOffset !== undefined)
return this._m_symbolNameTableOffset;
this._m_symbolNameTableOffset = this.pointerToSymbolTable + this.symbolTableSize;
return this._m_symbolNameTableOffset;
}
});
Object.defineProperty(CoffHeader.prototype, 'symbolNameTableSize', {
get: function() {
if (this._m_symbolNameTableSize !== undefined)
return this._m_symbolNameTableSize;
var _pos = this._io.pos;
this._io.seek(this.symbolNameTableOffset);
this._m_symbolNameTableSize = this._io.readU4le();
this._io.seek(_pos);
return this._m_symbolNameTableSize;
}
});
Object.defineProperty(CoffHeader.prototype, 'symbolTable', {
get: function() {
if (this._m_symbolTable !== undefined)
return this._m_symbolTable;
var _pos = this._io.pos;
this._io.seek(this.pointerToSymbolTable);
this._m_symbolTable = [];
for (var i = 0; i < this.numberOfSymbols; i++) {
this._m_symbolTable.push(new CoffSymbol(this._io, this, this._root));
}
this._io.seek(_pos);
return this._m_symbolTable;
}
});
Object.defineProperty(CoffHeader.prototype, 'symbolTableSize', {
get: function() {
if (this._m_symbolTableSize !== undefined)
return this._m_symbolTableSize;
this._m_symbolTableSize = this.numberOfSymbols * 18;
return this._m_symbolTableSize;
}
});
return CoffHeader;
})();
var CoffSymbol = MicrosoftPe.CoffSymbol = (function() {
function CoffSymbol(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
CoffSymbol.prototype._read = function() {
this._raw_nameAnnoying = this._io.readBytes(8);
var _io__raw_nameAnnoying = new KaitaiStream(this._raw_nameAnnoying);
this.nameAnnoying = new Annoyingstring(_io__raw_nameAnnoying, this, this._root);
this.value = this._io.readU4le();
this.sectionNumber = this._io.readU2le();
this.type = this._io.readU2le();
this.storageClass = this._io.readU1();
this.numberOfAuxSymbols = this._io.readU1();
}
Object.defineProperty(CoffSymbol.prototype, 'data', {
get: function() {
if (this._m_data !== undefined)
return this._m_data;
var _pos = this._io.pos;
this._io.seek(this.section.pointerToRawData + this.value);
this._m_data = this._io.readBytes(1);
this._io.seek(_pos);
return this._m_data;
}
});
Object.defineProperty(CoffSymbol.prototype, 'section', {
get: function() {
if (this._m_section !== undefined)
return this._m_section;
this._m_section = this._root.pe.sections[this.sectionNumber - 1];
return this._m_section;
}
});
return CoffSymbol;
})();
var DataDir = MicrosoftPe.DataDir = (function() {
function DataDir(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
DataDir.prototype._read = function() {
this.virtualAddress = this._io.readU4le();
this.size = this._io.readU4le();
}
return DataDir;
})();
var MzPlaceholder = MicrosoftPe.MzPlaceholder = (function() {
function MzPlaceholder(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
MzPlaceholder.prototype._read = function() {
this.magic = this._io.readBytes(2);
if (!((KaitaiStream.byteArrayCompare(this.magic, new Uint8Array([77, 90])) == 0))) {
throw new KaitaiStream.ValidationNotEqualError(new Uint8Array([77, 90]), this.magic, this._io, "/types/mz_placeholder/seq/0");
}
this.data1 = this._io.readBytes(58);
this.ofsPe = this._io.readU4le();
}
/**
* In PE file, an offset to PE header
*/
return MzPlaceholder;
})();
var OptionalHeader = MicrosoftPe.OptionalHeader = (function() {
function OptionalHeader(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
OptionalHeader.prototype._read = function() {
this.std = new OptionalHeaderStd(this._io, this, this._root);
this.windows = new OptionalHeaderWindows(this._io, this, this._root);
this.dataDirs = new OptionalHeaderDataDirs(this._io, this, this._root);
}
return OptionalHeader;
})();
var OptionalHeaderDataDirs = MicrosoftPe.OptionalHeaderDataDirs = (function() {
function OptionalHeaderDataDirs(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
OptionalHeaderDataDirs.prototype._read = function() {
this.exportTable = new DataDir(this._io, this, this._root);
this.importTable = new DataDir(this._io, this, this._root);
this.resourceTable = new DataDir(this._io, this, this._root);
this.exceptionTable = new DataDir(this._io, this, this._root);
this.certificateTable = new DataDir(this._io, this, this._root);
this.baseRelocationTable = new DataDir(this._io, this, this._root);
this.debug = new DataDir(this._io, this, this._root);
this.architecture = new DataDir(this._io, this, this._root);
this.globalPtr = new DataDir(this._io, this, this._root);
this.tlsTable = new DataDir(this._io, this, this._root);
this.loadConfigTable = new DataDir(this._io, this, this._root);
this.boundImport = new DataDir(this._io, this, this._root);
this.iat = new DataDir(this._io, this, this._root);
this.delayImportDescriptor = new DataDir(this._io, this, this._root);
this.clrRuntimeHeader = new DataDir(this._io, this, this._root);
}
return OptionalHeaderDataDirs;
})();
var OptionalHeaderStd = MicrosoftPe.OptionalHeaderStd = (function() {
function OptionalHeaderStd(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
OptionalHeaderStd.prototype._read = function() {
this.format = this._io.readU2le();
this.majorLinkerVersion = this._io.readU1();
this.minorLinkerVersion = this._io.readU1();
this.sizeOfCode = this._io.readU4le();
this.sizeOfInitializedData = this._io.readU4le();
this.sizeOfUninitializedData = this._io.readU4le();
this.addressOfEntryPoint = this._io.readU4le();
this.baseOfCode = this._io.readU4le();
if (this.format == MicrosoftPe.PeFormat.PE32) {
this.baseOfData = this._io.readU4le();
}
}
return OptionalHeaderStd;
})();
var OptionalHeaderWindows = MicrosoftPe.OptionalHeaderWindows = (function() {
OptionalHeaderWindows.SubsystemEnum = Object.freeze({
UNKNOWN: 0,
NATIVE: 1,
WINDOWS_GUI: 2,
WINDOWS_CUI: 3,
POSIX_CUI: 7,
WINDOWS_CE_GUI: 9,
EFI_APPLICATION: 10,
EFI_BOOT_SERVICE_DRIVER: 11,
EFI_RUNTIME_DRIVER: 12,
EFI_ROM: 13,
XBOX: 14,
WINDOWS_BOOT_APPLICATION: 16,
0: "UNKNOWN",
1: "NATIVE",
2: "WINDOWS_GUI",
3: "WINDOWS_CUI",
7: "POSIX_CUI",
9: "WINDOWS_CE_GUI",
10: "EFI_APPLICATION",
11: "EFI_BOOT_SERVICE_DRIVER",
12: "EFI_RUNTIME_DRIVER",
13: "EFI_ROM",
14: "XBOX",
16: "WINDOWS_BOOT_APPLICATION",
});
function OptionalHeaderWindows(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
OptionalHeaderWindows.prototype._read = function() {
if (this._parent.std.format == MicrosoftPe.PeFormat.PE32) {
this.imageBase32 = this._io.readU4le();
}
if (this._parent.std.format == MicrosoftPe.PeFormat.PE32_PLUS) {
this.imageBase64 = this._io.readU8le();
}
this.sectionAlignment = this._io.readU4le();
this.fileAlignment = this._io.readU4le();
this.majorOperatingSystemVersion = this._io.readU2le();
this.minorOperatingSystemVersion = this._io.readU2le();
this.majorImageVersion = this._io.readU2le();
this.minorImageVersion = this._io.readU2le();
this.majorSubsystemVersion = this._io.readU2le();
this.minorSubsystemVersion = this._io.readU2le();
this.win32VersionValue = this._io.readU4le();
this.sizeOfImage = this._io.readU4le();
this.sizeOfHeaders = this._io.readU4le();
this.checkSum = this._io.readU4le();
this.subsystem = this._io.readU2le();
this.dllCharacteristics = this._io.readU2le();
if (this._parent.std.format == MicrosoftPe.PeFormat.PE32) {
this.sizeOfStackReserve32 = this._io.readU4le();
}
if (this._parent.std.format == MicrosoftPe.PeFormat.PE32_PLUS) {
this.sizeOfStackReserve64 = this._io.readU8le();
}
if (this._parent.std.format == MicrosoftPe.PeFormat.PE32) {
this.sizeOfStackCommit32 = this._io.readU4le();
}
if (this._parent.std.format == MicrosoftPe.PeFormat.PE32_PLUS) {
this.sizeOfStackCommit64 = this._io.readU8le();
}
if (this._parent.std.format == MicrosoftPe.PeFormat.PE32) {
this.sizeOfHeapReserve32 = this._io.readU4le();
}
if (this._parent.std.format == MicrosoftPe.PeFormat.PE32_PLUS) {
this.sizeOfHeapReserve64 = this._io.readU8le();
}
if (this._parent.std.format == MicrosoftPe.PeFormat.PE32) {
this.sizeOfHeapCommit32 = this._io.readU4le();
}
if (this._parent.std.format == MicrosoftPe.PeFormat.PE32_PLUS) {
this.sizeOfHeapCommit64 = this._io.readU8le();
}
this.loaderFlags = this._io.readU4le();
this.numberOfRvaAndSizes = this._io.readU4le();
}
return OptionalHeaderWindows;
})();
var PeHeader = MicrosoftPe.PeHeader = (function() {
function PeHeader(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
PeHeader.prototype._read = function() {
this.peSignature = this._io.readBytes(4);
if (!((KaitaiStream.byteArrayCompare(this.peSignature, new Uint8Array([80, 69, 0, 0])) == 0))) {
throw new KaitaiStream.ValidationNotEqualError(new Uint8Array([80, 69, 0, 0]), this.peSignature, this._io, "/types/pe_header/seq/0");
}
this.coffHdr = new CoffHeader(this._io, this, this._root);
this._raw_optionalHdr = this._io.readBytes(this.coffHdr.sizeOfOptionalHeader);
var _io__raw_optionalHdr = new KaitaiStream(this._raw_optionalHdr);
this.optionalHdr = new OptionalHeader(_io__raw_optionalHdr, this, this._root);
this.sections = [];
for (var i = 0; i < this.coffHdr.numberOfSections; i++) {
this.sections.push(new Section(this._io, this, this._root));
}
}
Object.defineProperty(PeHeader.prototype, 'certificateTable', {
get: function() {
if (this._m_certificateTable !== undefined)
return this._m_certificateTable;
if (this.optionalHdr.dataDirs.certificateTable.virtualAddress != 0) {
var _pos = this._io.pos;
this._io.seek(this.optionalHdr.dataDirs.certificateTable.virtualAddress);
this._raw__m_certificateTable = this._io.readBytes(this.optionalHdr.dataDirs.certificateTable.size);
var _io__raw__m_certificateTable = new KaitaiStream(this._raw__m_certificateTable);
this._m_certificateTable = new CertificateTable(_io__raw__m_certificateTable, this, this._root);
this._io.seek(_pos);
}
return this._m_certificateTable;
}
});
return PeHeader;
})();
var Section = MicrosoftPe.Section = (function() {
function Section(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root;
this._read();
}
Section.prototype._read = function() {
this.name = KaitaiStream.bytesToStr(KaitaiStream.bytesStripRight(this._io.readBytes(8), 0), "UTF-8");
this.virtualSize = this._io.readU4le();
this.virtualAddress = this._io.readU4le();
this.sizeOfRawData = this._io.readU4le();
this.pointerToRawData = this._io.readU4le();
this.pointerToRelocations = this._io.readU4le();
this.pointerToLinenumbers = this._io.readU4le();
this.numberOfRelocations = this._io.readU2le();
this.numberOfLinenumbers = this._io.readU2le();
this.characteristics = this._io.readU4le();
}
Object.defineProperty(Section.prototype, 'body', {
get: function() {
if (this._m_body !== undefined)
return this._m_body;
var _pos = this._io.pos;
this._io.seek(this.pointerToRawData);
this._m_body = this._io.readBytes(this.sizeOfRawData);
this._io.seek(_pos);
return this._m_body;
}
});
return Section;
})();
Object.defineProperty(MicrosoftPe.prototype, 'pe', {
get: function() {
if (this._m_pe !== undefined)
return this._m_pe;
var _pos = this._io.pos;
this._io.seek(this.mz.ofsPe);
this._m_pe = new PeHeader(this._io, this, this._root);
this._io.seek(_pos);
return this._m_pe;
}
});
return MicrosoftPe;
})();
MicrosoftPe_.MicrosoftPe = MicrosoftPe;
});