# encoding: ascii
# api: powershell
# title: JScript: read PE headers
# description: See original post at https://gist.github.com/gregzakharov/9877156 for examples.
# version: 0.1
# type: function
# author: greg zakharov
# license: CC0
# x-poshcode-id: 5030
# x-archived: 2014-04-03T07:48:43
# x-published: 2014-03-30T18:26:00
#
#
var pe = pe || {
getRawData : function(fileName) {
try {
var xml = new ActiveXObject('Microsoft.XMLDOM').createElement('Binary'),
raw, e_magic, e_lfanew;
xml.dataType = 'bin.hex';
with (new ActiveXObject('ADODB.Stream')) {
Type = 1;
Open();
LoadFromFile(fileName);
xml.nodeTypedValue = Read(1024);
Close();
}
raw = xml.text.match(/.{2}/g);
e_magic = parseInt('0x' + raw.slice(0, 2).reverse().join(''));
e_lfanew = 256 * parseInt('0x' + raw[0x3D]) + parseInt('0x' + raw[0x3C]);
if (e_magic != 23117 || raw.slice(e_lfanew, (e_lfanew + 4)).join('') != 50450000) {
WScript.echo('Invalid file format.');
WScript.Quit(1);
}
}
catch (e) {
WScript.echo(e.message);
WScript.Quit(1);
}
return [raw, e_lfanew];
},
getDosHeader : function(fileName) {
Array.prototype.getBytes = function(b) {
return parseInt('0x' + this.slice(b, b + 2).reverse().join(''));
}
var raw = this.getRawData(fileName)[0],
IMAGE_DOS_HEADER = {
'e_magic' : raw.getBytes(0x00),
'e_cblp' : raw.getBytes(0x02),
'e_cp' : raw.getBytes(0x04),
'e_crlc' : raw.getBytes(0x06),
'e_cparhdr' : raw.getBytes(0x08),
'e_minalloc' : raw.getBytes(0x0A),
'e_maxalloc' : 256 * parseInt('0x' + raw[0x0D]) + parseInt('0x' + raw[0x0C]),
'e_ss' : raw.getBytes(0x0E),
'e_sp' : raw.getBytes(0x10),
'e_csum' : raw.getBytes(0x12),
'e_ip' : raw.getBytes(0x14),
'e_cs' : raw.getBytes(0x16),
'e_lfarlc' : raw.getBytes(0x18),
'e_ovno' : raw.getBytes(0x1A),
'e_res' : raw.slice(0x1C, 0x23),
'e_oemid' : raw.getBytes(0x24),
'e_oeminfo' : raw.getBytes(0x26),
'e_res2' : raw.slice(0x28, 0x3B),
'e_lfanew' : this.getRawData(fileName)[1]
}
this.print(IMAGE_DOS_HEADER, 11);
},
getFileHeader : function(fileName) {
var raw = this.getRawData(fileName),
i, mac = {
'I386' : 0x014c,
'IA64' : 0x0200,
'AMD64' : 0x8664
},
ifc = {
'RelocationsStripped' : 0x0001,
'Executable' : 0x0002,
'LineNumbersStripped' : 0x0004,
'SymbolsStripped' : 0x0008,
'AggressiveTrimWorkingSet' : 0x0010,
'LargeAddressAware' : 0x0020,
'Supports16Bit' : 0x0040,
'ReservedBytesWo' : 0x0080,
'Supports32Bit' : 0x0100,
'DebugInfoStripped' : 0x0200,
'RunFromSwapIfInRmvbl' : 0x0400,
'RunFromSwapIfInNetwrk' : 0x0800,
'SystemFile' : 0x1000,
'Dll' : 0x2000,
'OnlyFroSingleCoreProc' : 0x4000,
'BytesOfWordReserved' : 0x8000
},
IMAGE_FILE_HEADER = {};
Array.prototype.getBytes = function(b, e) {
return parseInt('0x' + this.slice(raw[1] + b, raw[1] + b + e).reverse().join(''));
}
for (i in mac)
if (raw[0].getBytes(0x04, 2) == mac[i]) IMAGE_FILE_HEADER['Machine'] = i;
with (new Date(1970, 0, 1)) {
IMAGE_FILE_HEADER['TimeDateStamp'] = new Date(
setSeconds(getSeconds() + raw[0].getBytes(0x08, 4))
);
}
IMAGE_FILE_HEADER['PointerToSymbolTable'] = raw[0].getBytes(0x0C, 2);
IMAGE_FILE_HEADER['NumberOfSymbols'] = raw[0].getBytes(0x10, 2);
IMAGE_FILE_HEADER['SizeOfOptionalHeader'] = raw[0].getBytes(0x14, 2).toString(16);
IMAGE_FILE_HEADER['Characteristics'] = '';
for (i in ifc) {
if ((raw[0].getBytes(0x16, 4) & ifc[i]) == ifc[i])
IMAGE_FILE_HEADER['Characteristics'] += i + '; ';
}
this.print(IMAGE_FILE_HEADER, 21);
},
getOptionalHeader : function(fileName) {
var raw = this.getRawData(fileName),
i, iss = {
'Unknown' : 0x00,
'Native' : 0x01,
'WindowsGUI' : 0x02,
'WindowsCUI' : 0x03,
'OS2_CUI' : 0x04,
'POSIX_CUI' : 0x05,
'NativeWindows' : 0x06,
'WindowsCE_CUI' : 0x07,
'EFIApplication' : 0x08,
'EFIBootServiceDrv' : 0x09,
'EFIRuntimeDrv' : 0x0A,
'EFIRom' : 0x0B,
'XBox' : 0x0C,
'WinBootApp' : 0x10
},
idc = {
'Res0' : 0x0001,
'Res1' : 0x0002,
'Res2' : 0x0004,
'Res3' : 0x0008,
'DynamicBase' : 0x0040,
'ForceItegrity' : 0x0080,
'NxCompatible' : 0x0100,
'NoIsolation' : 0x0200,
'NoSEH' : 0x0400,
'NoBind' : 0x0800,
'Res4' : 0x1000,
'WDMDriver' : 0x2000,
'TerminalSrvAware' : 0x8000
};
Array.prototype.getBytes = function(b, e) {
return '0x' + this.slice(raw[1] + b, raw[1] + b + e).reverse().join('');
}
var bit = (parseInt(raw[0].getBytes(0x16, 4)) & 0x0100) == 0x0100 ? 0 : 1;
var IMAGE_OPTIONAL_HEADER = {
'Magic' : raw[0].getBytes(0x18, 2) == 0x10B ? 'PE32' : 'PE32+',
'Linker' : [parseInt(raw[0].getBytes(0x1A, 1)), parseInt(raw[0].getBytes(0x1B, 2))],
'SizeOfCode' : raw[0].getBytes(0x1C, 4),
'SizeOfInitData' : raw[0].getBytes(0x20, 4),
'SizeOfUnInitData' : raw[0].getBytes(0x24, 4),
'AddressOfEntryPoint' : raw[0].getBytes(0x28, 4),
'BaseOfCode' : raw[0].getBytes(0x2C, 4),
'BaseOfData' : bit == 0 ? raw[0].getBytes(0x30, 4) : 'n/a',
'ImageBase' : bit == 0 ? raw[0].getBytes(0x34, 4) : raw[0].getBytes(0x30, 8),
'SectionAlignment' : raw[0].getBytes(0x38, 4),
'FileAlignment' : raw[0].getBytes(0x3C, 4),
'OSVersion' : [parseInt(raw[0].getBytes(0x40, 2)), parseInt(raw[0].getBytes(0x42, 2))],
'ImageVersion' : [parseInt(raw[0].getBytes(0x44, 2)), parseInt(raw[0].getBytes(0x46, 2))],
'SubsystemVersion' : [parseInt(raw[0].getBytes(0x48, 2)), parseInt(raw[0].getBytes(0x4A, 2))],
'Win32VersionValue' : raw[0].getBytes(0x4C, 4),
'SizeOfImage' : raw[0].getBytes(0x50, 4),
'SizeOfHeaders' : raw[0].getBytes(0x54, 4),
'Checksum' : raw[0].getBytes(0x58, 4)
};
for (i in iss) {
if (raw[0].getBytes(0x5C, 2) == iss[i])
IMAGE_OPTIONAL_HEADER['Subsystem'] = i;
}
IMAGE_OPTIONAL_HEADER['DllCharacteristics'] = '';
for (i in idc) {
if ((raw[0].getBytes(0x5E, 4) & idc[i]) == idc[i])
IMAGE_OPTIONAL_HEADER['DllCharacteristics'] += i + '; ';
}
IMAGE_OPTIONAL_HEADER['SizeOfStackreserve'] =
bit == 0 ? raw[0].getBytes(0x60, 4) : raw[0].getBytes(0x60, 8);
IMAGE_OPTIONAL_HEADER['SizeOfStackCommit'] =
bit == 0 ? raw[0].getBytes(0x64, 4) : raw[0].getBytes(0x68, 8);
IMAGE_OPTIONAL_HEADER['SizeOfHeapReserve'] =
bit == 0 ? raw[0].getBytes(0x68, 4) : raw[0].getBytes(0x70, 8);
IMAGE_OPTIONAL_HEADER['SizeOfHeapCommit'] =
bit == 0 ? raw[0].getBytes(0x6C, 4) : raw[0].getBytes(0x78, 8);
IMAGE_OPTIONAL_HEADER['LoaderFlags'] =
bit == 0 ? raw[0].getBytes(0x70, 4) : raw[0].getBytes(0x80, 4);
IMAGE_OPTIONAL_HEADER['NumberOfRvaAndSizes'] =
bit == 0 ? raw[0].getBytes(0x74, 4) : raw[0].getBytes(0x84, 4);
this.print(IMAGE_OPTIONAL_HEADER, 20);
},
getSectionHeaders : function(fileName) {
var raw = this.getRawData(fileName),
ptr = raw[1] + parseInt('0x' + raw[0].slice(raw[1] + 0x14, raw[1] + 0x16)) + 0x18,
sec, i, isc = {
'TypeDsect' : 0x00000001,
'TypeNoLoad' : 0x00000002,
'TypeGroup' : 0x00000004,
'TypeNoPadded' : 0x00000008,
'TypeCopy' : 0x00000010,
'Code' : 0x00000020,
'InitializedData' : 0x00000040,
'UninitializedData' : 0x00000080,
'LinkOther' : 0x00000100,
'LinkInfo' : 0x00000200,
'TypeOver' : 0x00000400,
'LinkRemove' : 0x00000800,
'LinkComDat' : 0x00001000,
'Reserved' : 0x00002000,
'NoDeferSpecExceptions' : 0x00004000,
'RelativeGP' : 0x00008000,
'MemPurgeable' : 0x00020000,
'Memory16Bit' : 0x00020000,
'MemoryLocked' : 0x00040000,
'MemoryPreload' : 0x00080000,
'Align1Bytes' : 0x00100000,
'Align2Bytes' : 0x00200000,
'Align4Bytes' : 0x00300000,
'Align8Bytes' : 0x00400000,
'Align16Bytes' : 0x00500000,
'Align32Bytes' : 0x00600000,
'Align64Bytes' : 0x00700000,
'Align128Bytes' : 0x00800000,
'Align256Bytes' : 0x00900000,
'Align512Bytes' : 0x00A00000,
'Align1024Bytes' : 0x00B00000,
'Align2048Bytes' : 0x00C00000,
'Align4096Bytes' : 0x00D00000,
'Align8192Bytes' : 0x00E00000,
'AlignMask' : 0x00F00000,
'LinkExRelocOverflow' : 0x01000000,
'MemoryDiscardable' : 0x02000000,
'MemoryNotCached' : 0x04000000,
'MemoryNotPaged' : 0x08000000,
'MemoryShared' : 0x10000000,
'MemoryExecute' : 0x20000000,
'MemoryRead' : 0x40000000,
'MemoryWrite' : 0x80000000
};
Array.prototype.getDetail = function(b) {
return '0x' + this.slice(ptr + b, ptr + b + 4).reverse().join('');
}
WScript.echo('Name VirtSize VirtAddr SzRawData PtrRawData Characteristics');
WScript.echo('----- ---------- ---------- ---------- ---------- ----------------');
for (i = 0; i < parseInt('0x' + raw[0].slice(raw[1] + 0x6, raw[1] + 0x8)); ++i) {
sec = raw[0].slice(ptr, ptr + 0x07);
for (var j = 0, cap = '', chr =''; j < sec.length; ++j) {
cap += String.fromCharCode(parseInt('0x' + sec[j]));
}
WScript.StdOut.Write(cap);
WScript.StdOut.Write(raw[0].getDetail(0x08) + ' ');
WScript.StdOut.Write(raw[0].getDetail(0x0C) + ' ');
WScript.StdOut.Write(raw[0].getDetail(0x10) + ' ');
WScript.StdOut.Write(raw[0].getDetail(0x14) + ' ');
for (var k in isc) {
if (parseInt('0x' + raw[0].slice(
ptr + 0x24, ptr + 0x28).reverse().join('')) & isc[k]) {
chr += k + '; ';
}
}
WScript.echo(chr);
ptr += 0x28;
}
},
print : function(o, v) {
var i, j;
for (i in o) {
j = i;
while (j.length != v) j += ' ';
WScript.echo(j + ': ' + o[i]);
}
}
}