main funcions fixes

This commit is contained in:
2025-09-29 22:06:11 +09:00
parent 40e016e128
commit c8c3274527
7995 changed files with 1517998 additions and 1057 deletions

38
desktop-operator/node_modules/pe-library/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,38 @@
# Changelog
## v0.4.1
- Cherry-pick [v.1.0.1](https://github.com/jet2jet/pe-library-js/releases/tag/v1.0.1) bugfix
## v0.4.0
- Add support for ES module loading in Node.js environment
## v0.3.0
- Add support for 'unparsable' resource data
- Use `ignoreUnparsableData` parameter on `from` method of `NtExecutableResource`.
## v0.2.1
- Fix version information (no classes/types are changed)
## v0.2.0
- Add `NtExecutableResource` class and related types
## v0.1.3
- Export `calculateCheckSumForPE` function
## v0.1.2
- Remove `@internal` specifier for some methods
## v0.1.1
- Export `NtExecutableSection` and `NtExecutableFromOptions` types
## v0.1.0
Initial version (almost cloned from [resedit-js](https://github.com/jet2jet/resedit-js))

21
desktop-operator/node_modules/pe-library/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 jet
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

34
desktop-operator/node_modules/pe-library/README.md generated vendored Normal file
View File

@@ -0,0 +1,34 @@
[![NPM version](https://badge.fury.io/js/pe-library.svg)](https://www.npmjs.com/package/pe-library)
[![Build Status](https://github.com/jet2jet/pe-library-js/actions/workflows/main-ci.yml/badge.svg)](https://github.com/jet2jet/pe-library-js)
# pe-library
pe-library provides parsing and generating Portable Executable (known as Windows Executables) binaries.
## Usage
```js
import * as PE from 'pe-library';
import * as fs from 'fs';
// load and parse data
let data = fs.readFileSync('MyApp.exe');
// (the Node.js Buffer instance can be specified directly to NtExecutable.from)
let exe = PE.NtExecutable.from(data);
// get section data
let exportSection = exe.getSectionByEntry(PE.Format.ImageDirectoryEntry.Export);
// read binary data stored in exportSection.data ...
// to write binary: use exe.setSectionByEntry
// write to buffer
let newBin = exe.generate();
fs.writeFileSync('MyApp_modified.exe', new Buffer(newBin));
```
## License
- All programs / source codes / binaries in this package, EXCEPT FOLLOWINGS, are licensed with [MIT License](./LICENSE).
- The followings are licensed with 0-BSD license:
- [tools/dos-stub/dos-stub.asm](./tools/dos-stub/dos-stub.asm)
- The bit code, generated from tools/dos-stub/dos-stub.asm, written in [src/main/util/generate.ts](./src/main/util/generate.ts) as `DOS_STUB_PROGRAM`

View File

@@ -0,0 +1,90 @@
import ImageDirectoryEntry from './format/ImageDirectoryEntry.js';
import ImageDosHeader from './format/ImageDosHeader.js';
import ImageNtHeaders from './format/ImageNtHeaders.js';
import { ImageSectionHeader } from './format/ImageSectionHeaderArray.js';
export interface NtExecutableFromOptions {
/** true to parse binary even if the binary contains Certificate data (i.e. 'signed') */
ignoreCert?: boolean;
}
export interface NtExecutableSection {
info: ImageSectionHeader;
data: ArrayBuffer | null;
}
export default class NtExecutable {
private readonly _headers;
private readonly _sections;
private _ex;
private readonly _dh;
private readonly _nh;
private readonly _dda;
private constructor();
/**
* Creates an NtExecutable instance with an 'empty' executable binary.
* @param is32Bit set true if the binary is for 32-bit (default: false)
* @param isDLL set true if the binary is DLL (default: true)
* @return NtExecutable instance
*/
static createEmpty(is32Bit?: boolean, isDLL?: boolean): NtExecutable;
/**
* Parse the binary and create NtExecutable instance.
* An error will be thrown if the binary data is invalid
* @param bin binary data
* @param options additional option for parsing
* @return NtExecutable instance
*/
static from(bin: ArrayBuffer | ArrayBufferView, options?: NtExecutableFromOptions): NtExecutable;
/**
* Returns whether the executable is for 32-bit architecture
*/
is32bit(): boolean;
getTotalHeaderSize(): number;
get dosHeader(): ImageDosHeader;
get newHeader(): ImageNtHeaders;
getRawHeader(): ArrayBuffer;
getImageBase(): number;
getFileAlignment(): number;
getSectionAlignment(): number;
/**
* Return all sections. The returned array is sorted by raw address.
*/
getAllSections(): readonly NtExecutableSection[];
/**
* Return the section data from ImageDirectoryEntry enum value.
* @note
* The returned instance is equal to the value in {@link getAllSections}'s return value.
*/
getSectionByEntry(entry: ImageDirectoryEntry): Readonly<NtExecutableSection> | null;
/**
* Set the section data from ImageDirectoryEntry enum value.
* If entry is found, then replaces the secion data. If not found, then adds the section data.
*
* NOTE: 'virtualAddress' and 'pointerToRawData' of section object is ignored
* and calculated automatically. 'virtualSize' and 'sizeOfRawData' are used, but
* if the 'section.data.byteLength' is larger than 'sizeOfRawData', then
* these members are replaced.
*
* @param entry ImageDirectoryEntry enum value for the section
* @param section the section data, or null to remove the section
*/
setSectionByEntry(entry: ImageDirectoryEntry, section: Readonly<NtExecutableSection> | null): void;
/**
* Returns the extra data in the executable, or `null` if nothing.
* You can rewrite the returned buffer without using `setExtraData` if
* the size of the new data is equal to the old data.
*/
getExtraData(): ArrayBuffer | null;
/**
* Specifies the new extra data in the executable.
* The specified buffer will be cloned and you can release it after calling this method.
* @param bin buffer containing the new data
* @note
* The extra data will not be aligned by `NtExecutable`.
*/
setExtraData(bin: ArrayBuffer | ArrayBufferView | null): void;
/**
* Generates the executable binary data.
*/
generate(paddingSize?: number): ArrayBuffer;
private rearrangeSections;
private replaceSectionImpl;
}

View File

@@ -0,0 +1,420 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ImageDataDirectoryArray_js_1 = require("./format/ImageDataDirectoryArray.js");
var ImageDirectoryEntry_js_1 = require("./format/ImageDirectoryEntry.js");
var ImageDosHeader_js_1 = require("./format/ImageDosHeader.js");
var ImageNtHeaders_js_1 = require("./format/ImageNtHeaders.js");
var ImageSectionHeaderArray_js_1 = require("./format/ImageSectionHeaderArray.js");
var functions_js_1 = require("./util/functions.js");
var generate_js_1 = require("./util/generate.js");
var NtExecutable = /** @class */ (function () {
function NtExecutable(_headers, _sections, _ex) {
this._headers = _headers;
this._sections = _sections;
this._ex = _ex;
var dh = ImageDosHeader_js_1.default.from(_headers);
var nh = ImageNtHeaders_js_1.default.from(_headers, dh.newHeaderAddress);
this._dh = dh;
this._nh = nh;
this._dda = nh.optionalHeaderDataDirectory;
_sections.sort(function (a, b) {
var ra = a.info.pointerToRawData;
var rb = a.info.pointerToRawData;
if (ra !== rb) {
return ra - rb;
}
var va = a.info.virtualAddress;
var vb = b.info.virtualAddress;
if (va === vb) {
return a.info.virtualSize - b.info.virtualSize;
}
return va - vb;
});
}
/**
* Creates an NtExecutable instance with an 'empty' executable binary.
* @param is32Bit set true if the binary is for 32-bit (default: false)
* @param isDLL set true if the binary is DLL (default: true)
* @return NtExecutable instance
*/
NtExecutable.createEmpty = function (is32Bit, isDLL) {
if (is32Bit === void 0) { is32Bit = false; }
if (isDLL === void 0) { isDLL = true; }
return this.from(generate_js_1.makeEmptyNtExecutableBinary(is32Bit, isDLL));
};
/**
* Parse the binary and create NtExecutable instance.
* An error will be thrown if the binary data is invalid
* @param bin binary data
* @param options additional option for parsing
* @return NtExecutable instance
*/
NtExecutable.from = function (bin, options) {
var dh = ImageDosHeader_js_1.default.from(bin);
var nh = ImageNtHeaders_js_1.default.from(bin, dh.newHeaderAddress);
if (!dh.isValid() || !nh.isValid()) {
throw new TypeError('Invalid binary format');
}
if (nh.fileHeader.numberOfSymbols > 0) {
throw new Error('Binary with symbols is not supported now');
}
var fileAlignment = nh.optionalHeader.fileAlignment;
var securityEntry = nh.optionalHeaderDataDirectory.get(ImageDirectoryEntry_js_1.default.Certificate);
if (securityEntry.size > 0) {
// Signed executables should be parsed only when `ignoreCert` is true
if (!(options === null || options === void 0 ? void 0 : options.ignoreCert)) {
throw new Error('Parsing signed executable binary is not allowed by default.');
}
}
var secOff = dh.newHeaderAddress + nh.getSectionHeaderOffset();
var secCount = nh.fileHeader.numberOfSections;
var sections = [];
var tempSectionHeaderBinary = functions_js_1.allocatePartialBinary(bin, secOff, secCount * ImageSectionHeaderArray_js_1.default.itemSize);
var secArray = ImageSectionHeaderArray_js_1.default.from(tempSectionHeaderBinary, secCount, 0);
var lastOffset = functions_js_1.roundUp(secOff + secCount * ImageSectionHeaderArray_js_1.default.itemSize, fileAlignment);
// console.log(`from data size 0x${bin.byteLength.toString(16)}:`);
secArray.forEach(function (info) {
if (!info.pointerToRawData || !info.sizeOfRawData) {
info.pointerToRawData = 0;
info.sizeOfRawData = 0;
sections.push({
info: info,
data: null,
});
}
else {
// console.log(` section ${info.name}: 0x${info.pointerToRawData.toString(16)}, size = 0x${info.sizeOfRawData.toString(16)}`);
var secBin = functions_js_1.allocatePartialBinary(bin, info.pointerToRawData, info.sizeOfRawData);
sections.push({
info: info,
data: secBin,
});
var secEndOffset = functions_js_1.roundUp(info.pointerToRawData + info.sizeOfRawData, fileAlignment);
if (secEndOffset > lastOffset) {
lastOffset = secEndOffset;
}
}
});
// the size of DOS and NT headers is equal to section offset
var headers = functions_js_1.allocatePartialBinary(bin, 0, secOff);
// extra data
var exData = null;
var lastExDataOffset = bin.byteLength;
// It may contain that both extra data and certificate data are available.
// In this case the extra data is followed by the certificate data.
if (securityEntry.size > 0) {
lastExDataOffset = securityEntry.virtualAddress;
}
if (lastOffset < lastExDataOffset) {
exData = functions_js_1.allocatePartialBinary(bin, lastOffset, lastExDataOffset - lastOffset);
}
return new NtExecutable(headers, sections, exData);
};
/**
* Returns whether the executable is for 32-bit architecture
*/
NtExecutable.prototype.is32bit = function () {
return this._nh.is32bit();
};
NtExecutable.prototype.getTotalHeaderSize = function () {
return this._headers.byteLength;
};
Object.defineProperty(NtExecutable.prototype, "dosHeader", {
get: function () {
return this._dh;
},
enumerable: false,
configurable: true
});
Object.defineProperty(NtExecutable.prototype, "newHeader", {
get: function () {
return this._nh;
},
enumerable: false,
configurable: true
});
NtExecutable.prototype.getRawHeader = function () {
return this._headers;
};
NtExecutable.prototype.getImageBase = function () {
return this._nh.optionalHeader.imageBase;
};
NtExecutable.prototype.getFileAlignment = function () {
return this._nh.optionalHeader.fileAlignment;
};
NtExecutable.prototype.getSectionAlignment = function () {
return this._nh.optionalHeader.sectionAlignment;
};
/**
* Return all sections. The returned array is sorted by raw address.
*/
NtExecutable.prototype.getAllSections = function () {
return this._sections;
};
/**
* Return the section data from ImageDirectoryEntry enum value.
* @note
* The returned instance is equal to the value in {@link getAllSections}'s return value.
*/
NtExecutable.prototype.getSectionByEntry = function (entry) {
var dd = this._dda.get(entry);
var r = this._sections
.filter(function (sec) {
var vaEnd = sec.info.virtualAddress + sec.info.virtualSize;
return (dd.virtualAddress >= sec.info.virtualAddress &&
dd.virtualAddress < vaEnd);
})
.shift();
return r !== undefined ? r : null;
};
/**
* Set the section data from ImageDirectoryEntry enum value.
* If entry is found, then replaces the secion data. If not found, then adds the section data.
*
* NOTE: 'virtualAddress' and 'pointerToRawData' of section object is ignored
* and calculated automatically. 'virtualSize' and 'sizeOfRawData' are used, but
* if the 'section.data.byteLength' is larger than 'sizeOfRawData', then
* these members are replaced.
*
* @param entry ImageDirectoryEntry enum value for the section
* @param section the section data, or null to remove the section
*/
NtExecutable.prototype.setSectionByEntry = function (entry, section) {
var sec = section
? { data: section.data, info: section.info }
: null;
var dd = this._dda.get(entry);
var hasEntry = dd.size > 0;
if (!sec) {
if (!hasEntry) {
// no need to replace
}
else {
// clear entry
this._dda.set(entry, { size: 0, virtualAddress: 0 });
var len = this._sections.length;
for (var i = 0; i < len; ++i) {
var sec_1 = this._sections[i];
var vaStart = sec_1.info.virtualAddress;
var vaLast = vaStart + sec_1.info.virtualSize;
if (dd.virtualAddress >= vaStart &&
dd.virtualAddress < vaLast) {
this._sections.splice(i, 1);
// section count changed
this._nh.fileHeader.numberOfSections =
this._sections.length;
break;
}
}
}
}
else {
var rawSize = !sec.data ? 0 : sec.data.byteLength;
var fileAlign = this._nh.optionalHeader.fileAlignment;
var secAlign = this._nh.optionalHeader.sectionAlignment;
var alignedFileSize = !sec.data ? 0 : functions_js_1.roundUp(rawSize, fileAlign);
var alignedSecSize = !sec.data
? 0
: functions_js_1.roundUp(sec.info.virtualSize, secAlign);
if (sec.info.sizeOfRawData < alignedFileSize) {
sec.info.sizeOfRawData = alignedFileSize;
}
else {
alignedFileSize = sec.info.sizeOfRawData;
}
if (!hasEntry) {
var virtAddr_1 = 0;
var rawAddr_1 = functions_js_1.roundUp(this._headers.byteLength, fileAlign);
// get largest addresses
this._sections.forEach(function (secExist) {
if (secExist.info.pointerToRawData) {
if (rawAddr_1 <= secExist.info.pointerToRawData) {
rawAddr_1 =
secExist.info.pointerToRawData +
secExist.info.sizeOfRawData;
}
}
if (virtAddr_1 <= secExist.info.virtualAddress) {
virtAddr_1 =
secExist.info.virtualAddress +
secExist.info.virtualSize;
}
});
if (!alignedFileSize) {
rawAddr_1 = 0;
}
if (!virtAddr_1) {
virtAddr_1 = this.newHeader.optionalHeader.baseOfCode;
}
virtAddr_1 = functions_js_1.roundUp(virtAddr_1, secAlign);
sec.info.pointerToRawData = rawAddr_1;
sec.info.virtualAddress = virtAddr_1;
// add entry
this._dda.set(entry, {
size: rawSize,
virtualAddress: virtAddr_1,
});
this._sections.push(sec);
// section count changed
this._nh.fileHeader.numberOfSections = this._sections.length;
// change image size
this._nh.optionalHeader.sizeOfImage = functions_js_1.roundUp(virtAddr_1 + alignedSecSize, this._nh.optionalHeader.sectionAlignment);
}
else {
// replace entry
this.replaceSectionImpl(dd.virtualAddress, sec.info, sec.data);
}
}
};
/**
* Returns the extra data in the executable, or `null` if nothing.
* You can rewrite the returned buffer without using `setExtraData` if
* the size of the new data is equal to the old data.
*/
NtExecutable.prototype.getExtraData = function () {
return this._ex;
};
/**
* Specifies the new extra data in the executable.
* The specified buffer will be cloned and you can release it after calling this method.
* @param bin buffer containing the new data
* @note
* The extra data will not be aligned by `NtExecutable`.
*/
NtExecutable.prototype.setExtraData = function (bin) {
if (bin === null) {
this._ex = null;
}
else {
this._ex = functions_js_1.cloneToArrayBuffer(bin);
}
};
/**
* Generates the executable binary data.
*/
NtExecutable.prototype.generate = function (paddingSize) {
// calculate binary size
var dh = this._dh;
var nh = this._nh;
var secOff = dh.newHeaderAddress + nh.getSectionHeaderOffset();
var size = secOff;
size += this._sections.length * ImageSectionHeaderArray_js_1.default.itemSize;
var align = nh.optionalHeader.fileAlignment;
size = functions_js_1.roundUp(size, align);
this._sections.forEach(function (sec) {
if (!sec.info.pointerToRawData) {
return;
}
var lastOff = sec.info.pointerToRawData + sec.info.sizeOfRawData;
if (size < lastOff) {
size = lastOff;
size = functions_js_1.roundUp(size, align);
}
});
var lastPosition = size;
if (this._ex !== null) {
size += this._ex.byteLength;
}
if (typeof paddingSize === 'number') {
size += paddingSize;
}
// make buffer
var bin = new ArrayBuffer(size);
var u8bin = new Uint8Array(bin);
u8bin.set(new Uint8Array(this._headers, 0, secOff));
// reset Security section offset (eliminate it)
ImageDataDirectoryArray_js_1.default.from(bin, dh.newHeaderAddress + nh.getDataDirectoryOffset()).set(ImageDirectoryEntry_js_1.default.Certificate, {
size: 0,
virtualAddress: 0,
});
var secArray = ImageSectionHeaderArray_js_1.default.from(bin, this._sections.length, secOff);
this._sections.forEach(function (sec, i) {
if (!sec.data) {
sec.info.pointerToRawData = 0;
sec.info.sizeOfRawData = 0;
}
secArray.set(i, sec.info);
if (!sec.data || !sec.info.pointerToRawData) {
return;
}
u8bin.set(new Uint8Array(sec.data), sec.info.pointerToRawData);
});
if (this._ex !== null) {
u8bin.set(new Uint8Array(this._ex), lastPosition);
}
// re-calc checksum
if (nh.optionalHeader.checkSum !== 0) {
functions_js_1.calculateCheckSumForPE(bin, true);
}
return bin;
};
NtExecutable.prototype.rearrangeSections = function (rawAddressStart, rawDiff, virtualAddressStart, virtualDiff) {
if (!rawDiff && !virtualDiff) {
return;
}
var nh = this._nh;
var secAlign = nh.optionalHeader.sectionAlignment;
var dirs = this._dda;
var len = this._sections.length;
var lastVirtAddress = 0;
for (var i = 0; i < len; ++i) {
var sec = this._sections[i];
var virtAddr = sec.info.virtualAddress;
if (virtualDiff && virtAddr >= virtualAddressStart) {
var iDir = dirs.findIndexByVirtualAddress(virtAddr);
virtAddr += virtualDiff;
if (iDir !== null) {
dirs.set(iDir, {
virtualAddress: virtAddr,
size: sec.info.virtualSize,
});
}
sec.info.virtualAddress = virtAddr;
}
var fileAddr = sec.info.pointerToRawData;
if (rawDiff && fileAddr >= rawAddressStart) {
sec.info.pointerToRawData = fileAddr + rawDiff;
}
lastVirtAddress = functions_js_1.roundUp(sec.info.virtualAddress + sec.info.virtualSize, secAlign);
}
// fix image size from last virtual address
nh.optionalHeader.sizeOfImage = lastVirtAddress;
};
// NOTE: info.virtualSize must be valid
NtExecutable.prototype.replaceSectionImpl = function (virtualAddress, info, data) {
var len = this._sections.length;
for (var i = 0; i < len; ++i) {
var s = this._sections[i];
// console.log(`replaceSectionImpl: ${virtualAddress} <--> ${s.info.virtualAddress}`);
if (s.info.virtualAddress === virtualAddress) {
// console.log(` found`);
var secAlign = this._nh.optionalHeader.sectionAlignment;
var fileAddr = s.info.pointerToRawData;
var oldFileAddr = fileAddr + s.info.sizeOfRawData;
var oldVirtAddr = virtualAddress + functions_js_1.roundUp(s.info.virtualSize, secAlign);
s.info = functions_js_1.cloneObject(info);
s.info.virtualAddress = virtualAddress;
s.info.pointerToRawData = fileAddr;
s.data = data;
// shift addresses
var newFileAddr = fileAddr + info.sizeOfRawData;
var newVirtAddr = virtualAddress + functions_js_1.roundUp(info.virtualSize, secAlign);
this.rearrangeSections(oldFileAddr, newFileAddr - oldFileAddr, oldVirtAddr, newVirtAddr - oldVirtAddr);
// BLOCK: rewrite DataDirectory entry for specified virtualAddress
{
var dirs = this._dda;
var iDir = dirs.findIndexByVirtualAddress(virtualAddress);
if (iDir !== null) {
dirs.set(iDir, {
virtualAddress: virtualAddress,
size: info.virtualSize,
});
}
}
break;
}
}
};
return NtExecutable;
}());
exports.default = NtExecutable;

View File

@@ -0,0 +1,75 @@
import NtExecutable from './NtExecutable.js';
import { ImageSectionHeader } from './format/ImageSectionHeaderArray.js';
import ResourceEntry from './type/ResourceEntry.js';
/** Manages resource data for NtExecutable */
export default class NtExecutableResource {
/** The timestamp for resource */
dateTime: number;
/** The major version data for resource */
majorVersion: number;
/** The minor version data for resource */
minorVersion: number;
/** Resource entries */
entries: ResourceEntry[];
/**
* The section data header of resource data (used by outputResource method).
* This instance will be null if the base executable does not contain resource data.
* You can override this field before calling outputResource method.
* (Note that the addresses and sizes are ignored for output)
*/
sectionDataHeader: ImageSectionHeader | null;
private originalSize;
private constructor();
private parse;
/**
* Parses resource data for `NtExecutable`.
* This function returns valid instance even if
* the executable does not have resource data.
* @param exe `NtExecutable` instance
* @param ignoreUnparsableData (default: false) specify true if skipping 'unparsable' (e.g. unusual format) data.
* When true, the resource data may break on write operation.
*/
static from(exe: NtExecutable, ignoreUnparsableData?: boolean): NtExecutableResource;
/**
* Add or replace the resource entry.
* This method replaces the entry only if there is an entry with `type`, `id` and `lang` equal.
*/
replaceResourceEntry(entry: ResourceEntry): void;
/**
* Returns all resource entries, which has specified type and id, as UTF-8 string data.
* @param type Resource type
* @param id Resource id
* @returns an array of lang and value pair (tuple)
*/
getResourceEntriesAsString(type: string | number, id: string | number): Array<[lang: string | number, value: string]>;
/**
* Add or replace the resource entry with UTF-8 string data.
* This method is a wrapper of {@link NtExecutableResource.replaceResourceEntry}.
*/
replaceResourceEntryFromString(type: string | number, id: string | number, lang: string | number, value: string): void;
/**
* Removes resource entries which has specified type and id.
*/
removeResourceEntry(type: string | number, id: string | number, lang?: string | number): void;
/**
* Generates resource data binary for NtExecutable (not for .res file)
* @param virtualAddress The virtual address for the section
* @param alignment File alignment value of executable
* @param noGrow Set true to disallow growing resource section (throw errors if data exceeds)
* @param allowShrink Set true to allow shrinking resource section (if the data size is less than original)
*/
generateResourceData(virtualAddress: number, alignment: number, noGrow?: boolean, allowShrink?: boolean): {
bin: ArrayBuffer;
rawSize: number;
dataOffset: number;
descEntryOffset: number;
descEntryCount: number;
};
/**
* Writes holding resource data to specified NtExecutable instance.
* @param exeDest An NtExecutable instance to write resource section to
* @param noGrow Set true to disallow growing resource section (throw errors if data exceeds)
* @param allowShrink Set true to allow shrinking resource section (if the data size is less than original)
*/
outputResource(exeDest: NtExecutable, noGrow?: boolean, allowShrink?: boolean): void;
}

View File

@@ -0,0 +1,664 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ImageDirectoryEntry_js_1 = require("./format/ImageDirectoryEntry.js");
var functions_js_1 = require("./util/functions.js");
function removeDuplicates(a) {
return a.reduce(function (p, c) {
return p.indexOf(c) >= 0 ? p : p.concat(c);
}, []);
}
function readString(view, offset) {
var length = view.getUint16(offset, true);
var r = '';
offset += 2;
for (var i = 0; i < length; ++i) {
r += String.fromCharCode(view.getUint16(offset, true));
offset += 2;
}
return r;
}
function readLanguageTable(view, typeEntry, name, languageTable, cb) {
var off = languageTable;
var nameEntry = {
name: name,
languageTable: languageTable,
characteristics: view.getUint32(off, true),
dateTime: view.getUint32(off + 4, true),
majorVersion: view.getUint16(off + 8, true),
minorVersion: view.getUint16(off + 10, true),
};
var nameCount = view.getUint16(off + 12, true);
var idCount = view.getUint16(off + 14, true);
off += 16;
for (var i = 0; i < nameCount; ++i) {
var nameOffset = view.getUint32(off, true) & 0x7fffffff;
var dataOffset = view.getUint32(off + 4, true);
// ignore if the offset refers to the next table
if ((dataOffset & 0x80000000) !== 0) {
off += 8;
continue;
}
var name_1 = readString(view, nameOffset);
cb(typeEntry, nameEntry, { lang: name_1, dataOffset: dataOffset });
off += 8;
}
for (var i = 0; i < idCount; ++i) {
var id = view.getUint32(off, true) & 0x7fffffff;
var dataOffset = view.getUint32(off + 4, true);
// ignore if the offset refers to the next table
if ((dataOffset & 0x80000000) !== 0) {
off += 8;
continue;
}
cb(typeEntry, nameEntry, { lang: id, dataOffset: dataOffset });
off += 8;
}
}
function readNameTable(view, type, nameTable, cb) {
var off = nameTable;
var typeEntry = {
type: type,
nameTable: nameTable,
characteristics: view.getUint32(off, true),
dateTime: view.getUint32(off + 4, true),
majorVersion: view.getUint16(off + 8, true),
minorVersion: view.getUint16(off + 10, true),
};
var nameCount = view.getUint16(off + 12, true);
var idCount = view.getUint16(off + 14, true);
off += 16;
for (var i = 0; i < nameCount; ++i) {
var nameOffset = view.getUint32(off, true) & 0x7fffffff;
var nextTable = view.getUint32(off + 4, true);
// ignore if no next table is available
if (!(nextTable & 0x80000000)) {
off += 8;
continue;
}
nextTable &= 0x7fffffff;
var name_2 = readString(view, nameOffset);
readLanguageTable(view, typeEntry, name_2, nextTable, cb);
off += 8;
}
for (var i = 0; i < idCount; ++i) {
var id = view.getUint32(off, true) & 0x7fffffff;
var nextTable = view.getUint32(off + 4, true);
// ignore if no next table is available
if (!(nextTable & 0x80000000)) {
off += 8;
continue;
}
nextTable &= 0x7fffffff;
readLanguageTable(view, typeEntry, id, nextTable, cb);
off += 8;
}
}
function divideEntriesImplByID(r, names, entries) {
var entriesByString = {};
var entriesByNumber = {};
entries.forEach(function (e) {
if (typeof e.lang === 'string') {
entriesByString[e.lang] = e;
names.push(e.lang);
}
else {
entriesByNumber[e.lang] = e;
}
});
var strKeys = Object.keys(entriesByString);
strKeys.sort().forEach(function (type) {
r.s.push(entriesByString[type]);
});
var numKeys = Object.keys(entriesByNumber);
numKeys
.map(function (k) { return Number(k); })
.sort(function (a, b) { return a - b; })
.forEach(function (type) {
r.n.push(entriesByNumber[type]);
});
return 16 + 8 * (strKeys.length + numKeys.length);
}
function divideEntriesImplByName(r, names, entries) {
var entriesByString = {};
var entriesByNumber = {};
entries.forEach(function (e) {
var _a, _b;
if (typeof e.id === 'string') {
var a = (_a = entriesByString[e.id]) !== null && _a !== void 0 ? _a : (entriesByString[e.id] = []);
names.push(e.id);
a.push(e);
}
else {
var a = (_b = entriesByNumber[e.id]) !== null && _b !== void 0 ? _b : (entriesByNumber[e.id] = []);
a.push(e);
}
});
var sSum = Object.keys(entriesByString)
.sort()
.map(function (id) {
var o = {
id: id,
s: [],
n: [],
};
r.s.push(o);
return divideEntriesImplByID(o, names, entriesByString[id]);
})
.reduce(function (p, c) { return p + 8 + c; }, 0);
var nSum = Object.keys(entriesByNumber)
.map(function (k) { return Number(k); })
.sort(function (a, b) { return a - b; })
.map(function (id) {
var o = {
id: id,
s: [],
n: [],
};
r.n.push(o);
return divideEntriesImplByID(o, names, entriesByNumber[id]);
})
.reduce(function (p, c) { return p + 8 + c; }, 0);
return 16 + sSum + nSum;
}
function divideEntriesImplByType(r, names, entries) {
var entriesByString = {};
var entriesByNumber = {};
entries.forEach(function (e) {
var _a, _b;
if (typeof e.type === 'string') {
var a = (_a = entriesByString[e.type]) !== null && _a !== void 0 ? _a : (entriesByString[e.type] = []);
names.push(e.type);
a.push(e);
}
else {
var a = (_b = entriesByNumber[e.type]) !== null && _b !== void 0 ? _b : (entriesByNumber[e.type] = []);
a.push(e);
}
});
var sSum = Object.keys(entriesByString)
.sort()
.map(function (type) {
var o = { type: type, s: [], n: [] };
r.s.push(o);
return divideEntriesImplByName(o, names, entriesByString[type]);
})
.reduce(function (p, c) { return p + 8 + c; }, 0);
var nSum = Object.keys(entriesByNumber)
.map(function (k) { return Number(k); })
.sort(function (a, b) { return a - b; })
.map(function (type) {
var o = { type: type, s: [], n: [] };
r.n.push(o);
return divideEntriesImplByName(o, names, entriesByNumber[type]);
})
.reduce(function (p, c) { return p + 8 + c; }, 0);
return 16 + sSum + nSum;
}
function calculateStringLengthForWrite(text) {
var length = text.length;
// limit to 65535 because the 'length' field is uint16
return length > 65535 ? 65535 : length;
}
function getStringOffset(target, strings) {
var l = strings.length;
for (var i = 0; i < l; ++i) {
var s = strings[i];
if (s.text === target) {
return s.offset;
}
}
throw new Error('Unexpected');
}
/** (returns offset just after the written text) */
function writeString(view, offset, text) {
var length = calculateStringLengthForWrite(text);
view.setUint16(offset, length, true);
offset += 2;
for (var i = 0; i < length; ++i) {
view.setUint16(offset, text.charCodeAt(i), true);
offset += 2;
}
return offset;
}
function writeLanguageTable(view, offset, strings, data) {
// characteristics
view.setUint32(offset, 0, true);
// timestamp
view.setUint32(offset + 4, 0, true);
// major version / minor version
view.setUint32(offset + 8, 0, true);
// name entries
view.setUint16(offset + 12, data.s.length, true);
// id entries
view.setUint16(offset + 14, data.n.length, true);
offset += 16;
// name entries (not in specification)
data.s.forEach(function (e) {
var strOff = getStringOffset(e.lang, strings);
view.setUint32(offset, strOff, true);
view.setUint32(offset + 4, e.offset, true);
offset += 8;
});
// id entries
data.n.forEach(function (e) {
view.setUint32(offset, e.lang, true);
view.setUint32(offset + 4, e.offset, true);
offset += 8;
});
return offset;
}
function writeNameTable(view, offset, leafOffset, strings, data) {
// characteristics
view.setUint32(offset, 0, true);
// timestamp
view.setUint32(offset + 4, 0, true);
// major version / minor version
view.setUint32(offset + 8, 0, true);
// name entries
view.setUint16(offset + 12, data.s.length, true);
// id entries
view.setUint16(offset + 14, data.n.length, true);
offset += 16;
data.s.forEach(function (e) {
e.offset = leafOffset;
leafOffset = writeLanguageTable(view, leafOffset, strings, e);
});
data.n.forEach(function (e) {
e.offset = leafOffset;
leafOffset = writeLanguageTable(view, leafOffset, strings, e);
});
data.s.forEach(function (e) {
var strOff = getStringOffset(e.id, strings);
view.setUint32(offset, strOff + 0x80000000, true);
view.setUint32(offset + 4, e.offset + 0x80000000, true);
offset += 8;
});
data.n.forEach(function (e) {
view.setUint32(offset, e.id, true);
view.setUint32(offset + 4, e.offset + 0x80000000, true);
offset += 8;
});
return leafOffset;
}
function writeTypeTable(view, offset, strings, data) {
// characteristics
view.setUint32(offset, 0, true);
// timestamp
view.setUint32(offset + 4, 0, true);
// major version / minor version
view.setUint32(offset + 8, 0, true);
// name entries
view.setUint16(offset + 12, data.s.length, true);
// id entries
view.setUint16(offset + 14, data.n.length, true);
offset += 16;
var nextTableOffset = offset + 8 * (data.s.length + data.n.length);
data.s.forEach(function (e) {
e.offset = nextTableOffset;
nextTableOffset += 16 + 8 * (e.s.length + e.n.length);
});
data.n.forEach(function (e) {
e.offset = nextTableOffset;
nextTableOffset += 16 + 8 * (e.s.length + e.n.length);
});
data.s.forEach(function (e) {
var strOff = getStringOffset(e.type, strings);
view.setUint32(offset, strOff + 0x80000000, true);
view.setUint32(offset + 4, e.offset + 0x80000000, true);
offset += 8;
nextTableOffset = writeNameTable(view, e.offset, nextTableOffset, strings, e);
});
data.n.forEach(function (e) {
view.setUint32(offset, e.type, true);
view.setUint32(offset + 4, e.offset + 0x80000000, true);
offset += 8;
nextTableOffset = writeNameTable(view, e.offset, nextTableOffset, strings, e);
});
return nextTableOffset;
}
////////////////////////////////////////////////////////////////////////////////
/** Manages resource data for NtExecutable */
var NtExecutableResource = /** @class */ (function () {
function NtExecutableResource() {
/** The timestamp for resource */
this.dateTime = 0;
/** The major version data for resource */
this.majorVersion = 0;
/** The minor version data for resource */
this.minorVersion = 0;
/** Resource entries */
this.entries = [];
/**
* The section data header of resource data (used by outputResource method).
* This instance will be null if the base executable does not contain resource data.
* You can override this field before calling outputResource method.
* (Note that the addresses and sizes are ignored for output)
*/
this.sectionDataHeader = null;
this.originalSize = 0;
}
NtExecutableResource.prototype.parse = function (section, ignoreUnparsableData) {
if (!section.data) {
return;
}
var view = new DataView(section.data);
// --- First: Resource Directory Table ---
// (off: 0 -- Characteristics (uint32))
this.dateTime = view.getUint32(4, true);
this.majorVersion = view.getUint16(8, true);
this.minorVersion = view.getUint16(10, true);
var nameCount = view.getUint16(12, true);
var idCount = view.getUint16(14, true);
var off = 16;
var res = [];
var cb = function (t, n, l) {
var off = view.getUint32(l.dataOffset, true) -
section.info.virtualAddress;
var size = view.getUint32(l.dataOffset + 4, true);
var cp = view.getUint32(l.dataOffset + 8, true);
if (off >= 0) {
var bin = new Uint8Array(size);
bin.set(new Uint8Array(section.data, off, size));
res.push({
type: t.type,
id: n.name,
lang: l.lang,
codepage: cp,
bin: bin.buffer,
});
}
else {
if (!ignoreUnparsableData) {
throw new Error('Cannot parse resource directory entry; RVA seems to be invalid.');
}
res.push({
type: t.type,
id: n.name,
lang: l.lang,
codepage: cp,
bin: new ArrayBuffer(0),
rva: l.dataOffset,
});
}
};
for (var i = 0; i < nameCount; ++i) {
var nameOffset = view.getUint32(off, true) & 0x7fffffff;
var nextTable = view.getUint32(off + 4, true);
// ignore if no next table is available
if (!(nextTable & 0x80000000)) {
off += 8;
continue;
}
nextTable &= 0x7fffffff;
var name_3 = readString(view, nameOffset);
readNameTable(view, name_3, nextTable, cb);
off += 8;
}
for (var i = 0; i < idCount; ++i) {
var typeId = view.getUint32(off, true) & 0x7fffffff;
var nextTable = view.getUint32(off + 4, true);
// ignore if no next table is available
if (!(nextTable & 0x80000000)) {
off += 8;
continue;
}
nextTable &= 0x7fffffff;
readNameTable(view, typeId, nextTable, cb);
off += 8;
}
this.entries = res;
this.originalSize = section.data.byteLength;
};
/**
* Parses resource data for `NtExecutable`.
* This function returns valid instance even if
* the executable does not have resource data.
* @param exe `NtExecutable` instance
* @param ignoreUnparsableData (default: false) specify true if skipping 'unparsable' (e.g. unusual format) data.
* When true, the resource data may break on write operation.
*/
NtExecutableResource.from = function (exe, ignoreUnparsableData) {
if (ignoreUnparsableData === void 0) { ignoreUnparsableData = false; }
var secs = []
.concat(exe.getAllSections())
.sort(function (a, b) { return a.info.virtualAddress - b.info.virtualAddress; });
var entry = exe.getSectionByEntry(ImageDirectoryEntry_js_1.default.Resource);
// check if the section order is supported
// (not supported if any other sections except 'relocation' is available,
// because the recalculation of virtual address is not simple)
if (entry) {
var reloc = exe.getSectionByEntry(ImageDirectoryEntry_js_1.default.BaseRelocation);
for (var i = 0; i < secs.length; ++i) {
var s = secs[i];
if (s === entry) {
for (var j = i + 1; j < secs.length; ++j) {
if (!reloc || secs[j] !== reloc) {
throw new Error('After Resource section, sections except for relocation are not supported');
}
}
break;
}
}
}
var r = new NtExecutableResource();
r.sectionDataHeader = entry ? functions_js_1.cloneObject(entry.info) : null;
if (entry) {
r.parse(entry, ignoreUnparsableData);
}
return r;
};
/**
* Add or replace the resource entry.
* This method replaces the entry only if there is an entry with `type`, `id` and `lang` equal.
*/
NtExecutableResource.prototype.replaceResourceEntry = function (entry) {
for (var len = this.entries.length, i = 0; i < len; ++i) {
var e = this.entries[i];
if (e.type === entry.type &&
e.id === entry.id &&
e.lang === entry.lang) {
this.entries[i] = entry;
return;
}
}
this.entries.push(entry);
};
/**
* Returns all resource entries, which has specified type and id, as UTF-8 string data.
* @param type Resource type
* @param id Resource id
* @returns an array of lang and value pair (tuple)
*/
NtExecutableResource.prototype.getResourceEntriesAsString = function (type, id) {
return this.entries
.filter(function (entry) { return entry.type === type && entry.id === id; })
.map(function (entry) { return [entry.lang, functions_js_1.binaryToString(entry.bin)]; });
};
/**
* Add or replace the resource entry with UTF-8 string data.
* This method is a wrapper of {@link NtExecutableResource.replaceResourceEntry}.
*/
NtExecutableResource.prototype.replaceResourceEntryFromString = function (type, id, lang, value) {
var entry = {
type: type,
id: id,
lang: lang,
codepage: 1200,
bin: functions_js_1.stringToBinary(value),
};
this.replaceResourceEntry(entry);
};
/**
* Removes resource entries which has specified type and id.
*/
NtExecutableResource.prototype.removeResourceEntry = function (type, id, lang) {
this.entries = this.entries.filter(function (entry) {
return !(entry.type === type &&
entry.id === id &&
(typeof lang === 'undefined' || entry.lang === lang));
});
};
/**
* Generates resource data binary for NtExecutable (not for .res file)
* @param virtualAddress The virtual address for the section
* @param alignment File alignment value of executable
* @param noGrow Set true to disallow growing resource section (throw errors if data exceeds)
* @param allowShrink Set true to allow shrinking resource section (if the data size is less than original)
*/
NtExecutableResource.prototype.generateResourceData = function (virtualAddress, alignment, noGrow, allowShrink) {
if (noGrow === void 0) { noGrow = false; }
if (allowShrink === void 0) { allowShrink = false; }
// estimate data size and divide to output table
var r = {
s: [],
n: [],
};
var strings = [];
var size = divideEntriesImplByType(r, strings, this.entries);
strings = removeDuplicates(strings);
var stringsOffset = size;
size += strings.reduce(function (prev, cur) {
return prev + 2 + calculateStringLengthForWrite(cur) * 2;
}, 0);
size = functions_js_1.roundUp(size, 8);
var descOffset = size;
size = this.entries.reduce(function (p, e) {
e.offset = p;
return p + 16;
}, descOffset);
var dataOffset = size;
size = this.entries.reduce(function (p, e) {
return functions_js_1.roundUp(p, 8) + e.bin.byteLength;
}, dataOffset);
var alignedSize = functions_js_1.roundUp(size, alignment);
var originalAlignedSize = functions_js_1.roundUp(this.originalSize, alignment);
if (noGrow) {
if (alignedSize > originalAlignedSize) {
throw new Error('New resource data is larger than original');
}
}
if (!allowShrink) {
if (alignedSize < originalAlignedSize) {
alignedSize = originalAlignedSize;
}
}
// generate binary
var bin = new ArrayBuffer(alignedSize);
var view = new DataView(bin);
var o = descOffset;
var va = virtualAddress + dataOffset;
this.entries.forEach(function (e) {
var len = e.bin.byteLength;
if (typeof e.rva !== 'undefined') {
// RVA
view.setUint32(o, e.rva, true);
}
else {
va = functions_js_1.roundUp(va, 8);
// RVA
view.setUint32(o, va, true);
va += len;
}
// size
view.setUint32(o + 4, len, true);
// codepage
view.setUint32(o + 8, e.codepage, true);
// (zero)
view.setUint32(o + 12, 0, true);
o += 16;
});
o = dataOffset;
this.entries.forEach(function (e) {
var len = e.bin.byteLength;
functions_js_1.copyBuffer(bin, o, e.bin, 0, len);
o += functions_js_1.roundUp(len, 8);
});
var stringsData = [];
o = stringsOffset;
strings.forEach(function (s) {
stringsData.push({
offset: o,
text: s,
});
o = writeString(view, o, s);
});
writeTypeTable(view, 0, stringsData, r);
// fill with 'PADDINGX'
if (alignedSize > size) {
var pad = 'PADDINGX';
for (var i = size, j = 0; i < alignedSize; ++i, ++j) {
if (j === 8) {
j = 0;
}
view.setUint8(i, pad.charCodeAt(j));
}
}
return {
bin: bin,
rawSize: size,
dataOffset: dataOffset,
descEntryOffset: descOffset,
descEntryCount: this.entries.length,
};
};
/**
* Writes holding resource data to specified NtExecutable instance.
* @param exeDest An NtExecutable instance to write resource section to
* @param noGrow Set true to disallow growing resource section (throw errors if data exceeds)
* @param allowShrink Set true to allow shrinking resource section (if the data size is less than original)
*/
NtExecutableResource.prototype.outputResource = function (exeDest, noGrow, allowShrink) {
if (noGrow === void 0) { noGrow = false; }
if (allowShrink === void 0) { allowShrink = false; }
// make section data
var fileAlign = exeDest.getFileAlignment();
var sectionData;
if (this.sectionDataHeader) {
sectionData = {
data: null,
info: functions_js_1.cloneObject(this.sectionDataHeader),
};
}
else {
sectionData = {
data: null,
info: {
name: '.rsrc',
virtualSize: 0,
virtualAddress: 0,
sizeOfRawData: 0,
pointerToRawData: 0,
pointerToRelocations: 0,
pointerToLineNumbers: 0,
numberOfRelocations: 0,
numberOfLineNumbers: 0,
characteristics: 0x40000040, // read access and initialized data
},
};
}
// first, set virtualAddress to 0 because
// the virtual address is not determined now
var data = this.generateResourceData(0, fileAlign, noGrow, allowShrink);
sectionData.data = data.bin;
sectionData.info.sizeOfRawData = data.bin.byteLength;
sectionData.info.virtualSize = data.rawSize;
// write as section
exeDest.setSectionByEntry(ImageDirectoryEntry_js_1.default.Resource, sectionData);
// rewrite section raw-data
var generatedSection = exeDest.getSectionByEntry(ImageDirectoryEntry_js_1.default.Resource);
var view = new DataView(generatedSection.data);
// set RVA
var o = data.descEntryOffset;
var va = generatedSection.info.virtualAddress + data.dataOffset;
for (var i = 0; i < data.descEntryCount; ++i) {
var len = view.getUint32(o + 4, true);
va = functions_js_1.roundUp(va, 8);
// RVA
view.setUint32(o, va, true);
va += len;
o += 16;
}
};
return NtExecutableResource;
}());
exports.default = NtExecutableResource;

View File

@@ -0,0 +1,90 @@
import ImageDirectoryEntry from './format/ImageDirectoryEntry.js';
import ImageDosHeader from './format/ImageDosHeader.js';
import ImageNtHeaders from './format/ImageNtHeaders.js';
import { ImageSectionHeader } from './format/ImageSectionHeaderArray.js';
export interface NtExecutableFromOptions {
/** true to parse binary even if the binary contains Certificate data (i.e. 'signed') */
ignoreCert?: boolean;
}
export interface NtExecutableSection {
info: ImageSectionHeader;
data: ArrayBuffer | null;
}
export default class NtExecutable {
private readonly _headers;
private readonly _sections;
private _ex;
private readonly _dh;
private readonly _nh;
private readonly _dda;
private constructor();
/**
* Creates an NtExecutable instance with an 'empty' executable binary.
* @param is32Bit set true if the binary is for 32-bit (default: false)
* @param isDLL set true if the binary is DLL (default: true)
* @return NtExecutable instance
*/
static createEmpty(is32Bit?: boolean, isDLL?: boolean): NtExecutable;
/**
* Parse the binary and create NtExecutable instance.
* An error will be thrown if the binary data is invalid
* @param bin binary data
* @param options additional option for parsing
* @return NtExecutable instance
*/
static from(bin: ArrayBuffer | ArrayBufferView, options?: NtExecutableFromOptions): NtExecutable;
/**
* Returns whether the executable is for 32-bit architecture
*/
is32bit(): boolean;
getTotalHeaderSize(): number;
get dosHeader(): ImageDosHeader;
get newHeader(): ImageNtHeaders;
getRawHeader(): ArrayBuffer;
getImageBase(): number;
getFileAlignment(): number;
getSectionAlignment(): number;
/**
* Return all sections. The returned array is sorted by raw address.
*/
getAllSections(): readonly NtExecutableSection[];
/**
* Return the section data from ImageDirectoryEntry enum value.
* @note
* The returned instance is equal to the value in {@link getAllSections}'s return value.
*/
getSectionByEntry(entry: ImageDirectoryEntry): Readonly<NtExecutableSection> | null;
/**
* Set the section data from ImageDirectoryEntry enum value.
* If entry is found, then replaces the secion data. If not found, then adds the section data.
*
* NOTE: 'virtualAddress' and 'pointerToRawData' of section object is ignored
* and calculated automatically. 'virtualSize' and 'sizeOfRawData' are used, but
* if the 'section.data.byteLength' is larger than 'sizeOfRawData', then
* these members are replaced.
*
* @param entry ImageDirectoryEntry enum value for the section
* @param section the section data, or null to remove the section
*/
setSectionByEntry(entry: ImageDirectoryEntry, section: Readonly<NtExecutableSection> | null): void;
/**
* Returns the extra data in the executable, or `null` if nothing.
* You can rewrite the returned buffer without using `setExtraData` if
* the size of the new data is equal to the old data.
*/
getExtraData(): ArrayBuffer | null;
/**
* Specifies the new extra data in the executable.
* The specified buffer will be cloned and you can release it after calling this method.
* @param bin buffer containing the new data
* @note
* The extra data will not be aligned by `NtExecutable`.
*/
setExtraData(bin: ArrayBuffer | ArrayBufferView | null): void;
/**
* Generates the executable binary data.
*/
generate(paddingSize?: number): ArrayBuffer;
private rearrangeSections;
private replaceSectionImpl;
}

View File

@@ -0,0 +1,418 @@
import ImageDataDirectoryArray from './format/ImageDataDirectoryArray.js';
import ImageDirectoryEntry from './format/ImageDirectoryEntry.js';
import ImageDosHeader from './format/ImageDosHeader.js';
import ImageNtHeaders from './format/ImageNtHeaders.js';
import ImageSectionHeaderArray from './format/ImageSectionHeaderArray.js';
import { allocatePartialBinary, calculateCheckSumForPE, cloneObject, cloneToArrayBuffer, roundUp, } from './util/functions.js';
import { makeEmptyNtExecutableBinary } from './util/generate.js';
var NtExecutable = /** @class */ (function () {
function NtExecutable(_headers, _sections, _ex) {
this._headers = _headers;
this._sections = _sections;
this._ex = _ex;
var dh = ImageDosHeader.from(_headers);
var nh = ImageNtHeaders.from(_headers, dh.newHeaderAddress);
this._dh = dh;
this._nh = nh;
this._dda = nh.optionalHeaderDataDirectory;
_sections.sort(function (a, b) {
var ra = a.info.pointerToRawData;
var rb = a.info.pointerToRawData;
if (ra !== rb) {
return ra - rb;
}
var va = a.info.virtualAddress;
var vb = b.info.virtualAddress;
if (va === vb) {
return a.info.virtualSize - b.info.virtualSize;
}
return va - vb;
});
}
/**
* Creates an NtExecutable instance with an 'empty' executable binary.
* @param is32Bit set true if the binary is for 32-bit (default: false)
* @param isDLL set true if the binary is DLL (default: true)
* @return NtExecutable instance
*/
NtExecutable.createEmpty = function (is32Bit, isDLL) {
if (is32Bit === void 0) { is32Bit = false; }
if (isDLL === void 0) { isDLL = true; }
return this.from(makeEmptyNtExecutableBinary(is32Bit, isDLL));
};
/**
* Parse the binary and create NtExecutable instance.
* An error will be thrown if the binary data is invalid
* @param bin binary data
* @param options additional option for parsing
* @return NtExecutable instance
*/
NtExecutable.from = function (bin, options) {
var dh = ImageDosHeader.from(bin);
var nh = ImageNtHeaders.from(bin, dh.newHeaderAddress);
if (!dh.isValid() || !nh.isValid()) {
throw new TypeError('Invalid binary format');
}
if (nh.fileHeader.numberOfSymbols > 0) {
throw new Error('Binary with symbols is not supported now');
}
var fileAlignment = nh.optionalHeader.fileAlignment;
var securityEntry = nh.optionalHeaderDataDirectory.get(ImageDirectoryEntry.Certificate);
if (securityEntry.size > 0) {
// Signed executables should be parsed only when `ignoreCert` is true
if (!(options === null || options === void 0 ? void 0 : options.ignoreCert)) {
throw new Error('Parsing signed executable binary is not allowed by default.');
}
}
var secOff = dh.newHeaderAddress + nh.getSectionHeaderOffset();
var secCount = nh.fileHeader.numberOfSections;
var sections = [];
var tempSectionHeaderBinary = allocatePartialBinary(bin, secOff, secCount * ImageSectionHeaderArray.itemSize);
var secArray = ImageSectionHeaderArray.from(tempSectionHeaderBinary, secCount, 0);
var lastOffset = roundUp(secOff + secCount * ImageSectionHeaderArray.itemSize, fileAlignment);
// console.log(`from data size 0x${bin.byteLength.toString(16)}:`);
secArray.forEach(function (info) {
if (!info.pointerToRawData || !info.sizeOfRawData) {
info.pointerToRawData = 0;
info.sizeOfRawData = 0;
sections.push({
info: info,
data: null,
});
}
else {
// console.log(` section ${info.name}: 0x${info.pointerToRawData.toString(16)}, size = 0x${info.sizeOfRawData.toString(16)}`);
var secBin = allocatePartialBinary(bin, info.pointerToRawData, info.sizeOfRawData);
sections.push({
info: info,
data: secBin,
});
var secEndOffset = roundUp(info.pointerToRawData + info.sizeOfRawData, fileAlignment);
if (secEndOffset > lastOffset) {
lastOffset = secEndOffset;
}
}
});
// the size of DOS and NT headers is equal to section offset
var headers = allocatePartialBinary(bin, 0, secOff);
// extra data
var exData = null;
var lastExDataOffset = bin.byteLength;
// It may contain that both extra data and certificate data are available.
// In this case the extra data is followed by the certificate data.
if (securityEntry.size > 0) {
lastExDataOffset = securityEntry.virtualAddress;
}
if (lastOffset < lastExDataOffset) {
exData = allocatePartialBinary(bin, lastOffset, lastExDataOffset - lastOffset);
}
return new NtExecutable(headers, sections, exData);
};
/**
* Returns whether the executable is for 32-bit architecture
*/
NtExecutable.prototype.is32bit = function () {
return this._nh.is32bit();
};
NtExecutable.prototype.getTotalHeaderSize = function () {
return this._headers.byteLength;
};
Object.defineProperty(NtExecutable.prototype, "dosHeader", {
get: function () {
return this._dh;
},
enumerable: false,
configurable: true
});
Object.defineProperty(NtExecutable.prototype, "newHeader", {
get: function () {
return this._nh;
},
enumerable: false,
configurable: true
});
NtExecutable.prototype.getRawHeader = function () {
return this._headers;
};
NtExecutable.prototype.getImageBase = function () {
return this._nh.optionalHeader.imageBase;
};
NtExecutable.prototype.getFileAlignment = function () {
return this._nh.optionalHeader.fileAlignment;
};
NtExecutable.prototype.getSectionAlignment = function () {
return this._nh.optionalHeader.sectionAlignment;
};
/**
* Return all sections. The returned array is sorted by raw address.
*/
NtExecutable.prototype.getAllSections = function () {
return this._sections;
};
/**
* Return the section data from ImageDirectoryEntry enum value.
* @note
* The returned instance is equal to the value in {@link getAllSections}'s return value.
*/
NtExecutable.prototype.getSectionByEntry = function (entry) {
var dd = this._dda.get(entry);
var r = this._sections
.filter(function (sec) {
var vaEnd = sec.info.virtualAddress + sec.info.virtualSize;
return (dd.virtualAddress >= sec.info.virtualAddress &&
dd.virtualAddress < vaEnd);
})
.shift();
return r !== undefined ? r : null;
};
/**
* Set the section data from ImageDirectoryEntry enum value.
* If entry is found, then replaces the secion data. If not found, then adds the section data.
*
* NOTE: 'virtualAddress' and 'pointerToRawData' of section object is ignored
* and calculated automatically. 'virtualSize' and 'sizeOfRawData' are used, but
* if the 'section.data.byteLength' is larger than 'sizeOfRawData', then
* these members are replaced.
*
* @param entry ImageDirectoryEntry enum value for the section
* @param section the section data, or null to remove the section
*/
NtExecutable.prototype.setSectionByEntry = function (entry, section) {
var sec = section
? { data: section.data, info: section.info }
: null;
var dd = this._dda.get(entry);
var hasEntry = dd.size > 0;
if (!sec) {
if (!hasEntry) {
// no need to replace
}
else {
// clear entry
this._dda.set(entry, { size: 0, virtualAddress: 0 });
var len = this._sections.length;
for (var i = 0; i < len; ++i) {
var sec_1 = this._sections[i];
var vaStart = sec_1.info.virtualAddress;
var vaLast = vaStart + sec_1.info.virtualSize;
if (dd.virtualAddress >= vaStart &&
dd.virtualAddress < vaLast) {
this._sections.splice(i, 1);
// section count changed
this._nh.fileHeader.numberOfSections =
this._sections.length;
break;
}
}
}
}
else {
var rawSize = !sec.data ? 0 : sec.data.byteLength;
var fileAlign = this._nh.optionalHeader.fileAlignment;
var secAlign = this._nh.optionalHeader.sectionAlignment;
var alignedFileSize = !sec.data ? 0 : roundUp(rawSize, fileAlign);
var alignedSecSize = !sec.data
? 0
: roundUp(sec.info.virtualSize, secAlign);
if (sec.info.sizeOfRawData < alignedFileSize) {
sec.info.sizeOfRawData = alignedFileSize;
}
else {
alignedFileSize = sec.info.sizeOfRawData;
}
if (!hasEntry) {
var virtAddr_1 = 0;
var rawAddr_1 = roundUp(this._headers.byteLength, fileAlign);
// get largest addresses
this._sections.forEach(function (secExist) {
if (secExist.info.pointerToRawData) {
if (rawAddr_1 <= secExist.info.pointerToRawData) {
rawAddr_1 =
secExist.info.pointerToRawData +
secExist.info.sizeOfRawData;
}
}
if (virtAddr_1 <= secExist.info.virtualAddress) {
virtAddr_1 =
secExist.info.virtualAddress +
secExist.info.virtualSize;
}
});
if (!alignedFileSize) {
rawAddr_1 = 0;
}
if (!virtAddr_1) {
virtAddr_1 = this.newHeader.optionalHeader.baseOfCode;
}
virtAddr_1 = roundUp(virtAddr_1, secAlign);
sec.info.pointerToRawData = rawAddr_1;
sec.info.virtualAddress = virtAddr_1;
// add entry
this._dda.set(entry, {
size: rawSize,
virtualAddress: virtAddr_1,
});
this._sections.push(sec);
// section count changed
this._nh.fileHeader.numberOfSections = this._sections.length;
// change image size
this._nh.optionalHeader.sizeOfImage = roundUp(virtAddr_1 + alignedSecSize, this._nh.optionalHeader.sectionAlignment);
}
else {
// replace entry
this.replaceSectionImpl(dd.virtualAddress, sec.info, sec.data);
}
}
};
/**
* Returns the extra data in the executable, or `null` if nothing.
* You can rewrite the returned buffer without using `setExtraData` if
* the size of the new data is equal to the old data.
*/
NtExecutable.prototype.getExtraData = function () {
return this._ex;
};
/**
* Specifies the new extra data in the executable.
* The specified buffer will be cloned and you can release it after calling this method.
* @param bin buffer containing the new data
* @note
* The extra data will not be aligned by `NtExecutable`.
*/
NtExecutable.prototype.setExtraData = function (bin) {
if (bin === null) {
this._ex = null;
}
else {
this._ex = cloneToArrayBuffer(bin);
}
};
/**
* Generates the executable binary data.
*/
NtExecutable.prototype.generate = function (paddingSize) {
// calculate binary size
var dh = this._dh;
var nh = this._nh;
var secOff = dh.newHeaderAddress + nh.getSectionHeaderOffset();
var size = secOff;
size += this._sections.length * ImageSectionHeaderArray.itemSize;
var align = nh.optionalHeader.fileAlignment;
size = roundUp(size, align);
this._sections.forEach(function (sec) {
if (!sec.info.pointerToRawData) {
return;
}
var lastOff = sec.info.pointerToRawData + sec.info.sizeOfRawData;
if (size < lastOff) {
size = lastOff;
size = roundUp(size, align);
}
});
var lastPosition = size;
if (this._ex !== null) {
size += this._ex.byteLength;
}
if (typeof paddingSize === 'number') {
size += paddingSize;
}
// make buffer
var bin = new ArrayBuffer(size);
var u8bin = new Uint8Array(bin);
u8bin.set(new Uint8Array(this._headers, 0, secOff));
// reset Security section offset (eliminate it)
ImageDataDirectoryArray.from(bin, dh.newHeaderAddress + nh.getDataDirectoryOffset()).set(ImageDirectoryEntry.Certificate, {
size: 0,
virtualAddress: 0,
});
var secArray = ImageSectionHeaderArray.from(bin, this._sections.length, secOff);
this._sections.forEach(function (sec, i) {
if (!sec.data) {
sec.info.pointerToRawData = 0;
sec.info.sizeOfRawData = 0;
}
secArray.set(i, sec.info);
if (!sec.data || !sec.info.pointerToRawData) {
return;
}
u8bin.set(new Uint8Array(sec.data), sec.info.pointerToRawData);
});
if (this._ex !== null) {
u8bin.set(new Uint8Array(this._ex), lastPosition);
}
// re-calc checksum
if (nh.optionalHeader.checkSum !== 0) {
calculateCheckSumForPE(bin, true);
}
return bin;
};
NtExecutable.prototype.rearrangeSections = function (rawAddressStart, rawDiff, virtualAddressStart, virtualDiff) {
if (!rawDiff && !virtualDiff) {
return;
}
var nh = this._nh;
var secAlign = nh.optionalHeader.sectionAlignment;
var dirs = this._dda;
var len = this._sections.length;
var lastVirtAddress = 0;
for (var i = 0; i < len; ++i) {
var sec = this._sections[i];
var virtAddr = sec.info.virtualAddress;
if (virtualDiff && virtAddr >= virtualAddressStart) {
var iDir = dirs.findIndexByVirtualAddress(virtAddr);
virtAddr += virtualDiff;
if (iDir !== null) {
dirs.set(iDir, {
virtualAddress: virtAddr,
size: sec.info.virtualSize,
});
}
sec.info.virtualAddress = virtAddr;
}
var fileAddr = sec.info.pointerToRawData;
if (rawDiff && fileAddr >= rawAddressStart) {
sec.info.pointerToRawData = fileAddr + rawDiff;
}
lastVirtAddress = roundUp(sec.info.virtualAddress + sec.info.virtualSize, secAlign);
}
// fix image size from last virtual address
nh.optionalHeader.sizeOfImage = lastVirtAddress;
};
// NOTE: info.virtualSize must be valid
NtExecutable.prototype.replaceSectionImpl = function (virtualAddress, info, data) {
var len = this._sections.length;
for (var i = 0; i < len; ++i) {
var s = this._sections[i];
// console.log(`replaceSectionImpl: ${virtualAddress} <--> ${s.info.virtualAddress}`);
if (s.info.virtualAddress === virtualAddress) {
// console.log(` found`);
var secAlign = this._nh.optionalHeader.sectionAlignment;
var fileAddr = s.info.pointerToRawData;
var oldFileAddr = fileAddr + s.info.sizeOfRawData;
var oldVirtAddr = virtualAddress + roundUp(s.info.virtualSize, secAlign);
s.info = cloneObject(info);
s.info.virtualAddress = virtualAddress;
s.info.pointerToRawData = fileAddr;
s.data = data;
// shift addresses
var newFileAddr = fileAddr + info.sizeOfRawData;
var newVirtAddr = virtualAddress + roundUp(info.virtualSize, secAlign);
this.rearrangeSections(oldFileAddr, newFileAddr - oldFileAddr, oldVirtAddr, newVirtAddr - oldVirtAddr);
// BLOCK: rewrite DataDirectory entry for specified virtualAddress
{
var dirs = this._dda;
var iDir = dirs.findIndexByVirtualAddress(virtualAddress);
if (iDir !== null) {
dirs.set(iDir, {
virtualAddress: virtualAddress,
size: info.virtualSize,
});
}
}
break;
}
}
};
return NtExecutable;
}());
export default NtExecutable;

View File

@@ -0,0 +1,75 @@
import NtExecutable from './NtExecutable.js';
import { ImageSectionHeader } from './format/ImageSectionHeaderArray.js';
import ResourceEntry from './type/ResourceEntry.js';
/** Manages resource data for NtExecutable */
export default class NtExecutableResource {
/** The timestamp for resource */
dateTime: number;
/** The major version data for resource */
majorVersion: number;
/** The minor version data for resource */
minorVersion: number;
/** Resource entries */
entries: ResourceEntry[];
/**
* The section data header of resource data (used by outputResource method).
* This instance will be null if the base executable does not contain resource data.
* You can override this field before calling outputResource method.
* (Note that the addresses and sizes are ignored for output)
*/
sectionDataHeader: ImageSectionHeader | null;
private originalSize;
private constructor();
private parse;
/**
* Parses resource data for `NtExecutable`.
* This function returns valid instance even if
* the executable does not have resource data.
* @param exe `NtExecutable` instance
* @param ignoreUnparsableData (default: false) specify true if skipping 'unparsable' (e.g. unusual format) data.
* When true, the resource data may break on write operation.
*/
static from(exe: NtExecutable, ignoreUnparsableData?: boolean): NtExecutableResource;
/**
* Add or replace the resource entry.
* This method replaces the entry only if there is an entry with `type`, `id` and `lang` equal.
*/
replaceResourceEntry(entry: ResourceEntry): void;
/**
* Returns all resource entries, which has specified type and id, as UTF-8 string data.
* @param type Resource type
* @param id Resource id
* @returns an array of lang and value pair (tuple)
*/
getResourceEntriesAsString(type: string | number, id: string | number): Array<[lang: string | number, value: string]>;
/**
* Add or replace the resource entry with UTF-8 string data.
* This method is a wrapper of {@link NtExecutableResource.replaceResourceEntry}.
*/
replaceResourceEntryFromString(type: string | number, id: string | number, lang: string | number, value: string): void;
/**
* Removes resource entries which has specified type and id.
*/
removeResourceEntry(type: string | number, id: string | number, lang?: string | number): void;
/**
* Generates resource data binary for NtExecutable (not for .res file)
* @param virtualAddress The virtual address for the section
* @param alignment File alignment value of executable
* @param noGrow Set true to disallow growing resource section (throw errors if data exceeds)
* @param allowShrink Set true to allow shrinking resource section (if the data size is less than original)
*/
generateResourceData(virtualAddress: number, alignment: number, noGrow?: boolean, allowShrink?: boolean): {
bin: ArrayBuffer;
rawSize: number;
dataOffset: number;
descEntryOffset: number;
descEntryCount: number;
};
/**
* Writes holding resource data to specified NtExecutable instance.
* @param exeDest An NtExecutable instance to write resource section to
* @param noGrow Set true to disallow growing resource section (throw errors if data exceeds)
* @param allowShrink Set true to allow shrinking resource section (if the data size is less than original)
*/
outputResource(exeDest: NtExecutable, noGrow?: boolean, allowShrink?: boolean): void;
}

View File

@@ -0,0 +1,662 @@
import ImageDirectoryEntry from './format/ImageDirectoryEntry.js';
import { binaryToString, cloneObject, copyBuffer, roundUp, stringToBinary, } from './util/functions.js';
function removeDuplicates(a) {
return a.reduce(function (p, c) {
return p.indexOf(c) >= 0 ? p : p.concat(c);
}, []);
}
function readString(view, offset) {
var length = view.getUint16(offset, true);
var r = '';
offset += 2;
for (var i = 0; i < length; ++i) {
r += String.fromCharCode(view.getUint16(offset, true));
offset += 2;
}
return r;
}
function readLanguageTable(view, typeEntry, name, languageTable, cb) {
var off = languageTable;
var nameEntry = {
name: name,
languageTable: languageTable,
characteristics: view.getUint32(off, true),
dateTime: view.getUint32(off + 4, true),
majorVersion: view.getUint16(off + 8, true),
minorVersion: view.getUint16(off + 10, true),
};
var nameCount = view.getUint16(off + 12, true);
var idCount = view.getUint16(off + 14, true);
off += 16;
for (var i = 0; i < nameCount; ++i) {
var nameOffset = view.getUint32(off, true) & 0x7fffffff;
var dataOffset = view.getUint32(off + 4, true);
// ignore if the offset refers to the next table
if ((dataOffset & 0x80000000) !== 0) {
off += 8;
continue;
}
var name_1 = readString(view, nameOffset);
cb(typeEntry, nameEntry, { lang: name_1, dataOffset: dataOffset });
off += 8;
}
for (var i = 0; i < idCount; ++i) {
var id = view.getUint32(off, true) & 0x7fffffff;
var dataOffset = view.getUint32(off + 4, true);
// ignore if the offset refers to the next table
if ((dataOffset & 0x80000000) !== 0) {
off += 8;
continue;
}
cb(typeEntry, nameEntry, { lang: id, dataOffset: dataOffset });
off += 8;
}
}
function readNameTable(view, type, nameTable, cb) {
var off = nameTable;
var typeEntry = {
type: type,
nameTable: nameTable,
characteristics: view.getUint32(off, true),
dateTime: view.getUint32(off + 4, true),
majorVersion: view.getUint16(off + 8, true),
minorVersion: view.getUint16(off + 10, true),
};
var nameCount = view.getUint16(off + 12, true);
var idCount = view.getUint16(off + 14, true);
off += 16;
for (var i = 0; i < nameCount; ++i) {
var nameOffset = view.getUint32(off, true) & 0x7fffffff;
var nextTable = view.getUint32(off + 4, true);
// ignore if no next table is available
if (!(nextTable & 0x80000000)) {
off += 8;
continue;
}
nextTable &= 0x7fffffff;
var name_2 = readString(view, nameOffset);
readLanguageTable(view, typeEntry, name_2, nextTable, cb);
off += 8;
}
for (var i = 0; i < idCount; ++i) {
var id = view.getUint32(off, true) & 0x7fffffff;
var nextTable = view.getUint32(off + 4, true);
// ignore if no next table is available
if (!(nextTable & 0x80000000)) {
off += 8;
continue;
}
nextTable &= 0x7fffffff;
readLanguageTable(view, typeEntry, id, nextTable, cb);
off += 8;
}
}
function divideEntriesImplByID(r, names, entries) {
var entriesByString = {};
var entriesByNumber = {};
entries.forEach(function (e) {
if (typeof e.lang === 'string') {
entriesByString[e.lang] = e;
names.push(e.lang);
}
else {
entriesByNumber[e.lang] = e;
}
});
var strKeys = Object.keys(entriesByString);
strKeys.sort().forEach(function (type) {
r.s.push(entriesByString[type]);
});
var numKeys = Object.keys(entriesByNumber);
numKeys
.map(function (k) { return Number(k); })
.sort(function (a, b) { return a - b; })
.forEach(function (type) {
r.n.push(entriesByNumber[type]);
});
return 16 + 8 * (strKeys.length + numKeys.length);
}
function divideEntriesImplByName(r, names, entries) {
var entriesByString = {};
var entriesByNumber = {};
entries.forEach(function (e) {
var _a, _b;
if (typeof e.id === 'string') {
var a = (_a = entriesByString[e.id]) !== null && _a !== void 0 ? _a : (entriesByString[e.id] = []);
names.push(e.id);
a.push(e);
}
else {
var a = (_b = entriesByNumber[e.id]) !== null && _b !== void 0 ? _b : (entriesByNumber[e.id] = []);
a.push(e);
}
});
var sSum = Object.keys(entriesByString)
.sort()
.map(function (id) {
var o = {
id: id,
s: [],
n: [],
};
r.s.push(o);
return divideEntriesImplByID(o, names, entriesByString[id]);
})
.reduce(function (p, c) { return p + 8 + c; }, 0);
var nSum = Object.keys(entriesByNumber)
.map(function (k) { return Number(k); })
.sort(function (a, b) { return a - b; })
.map(function (id) {
var o = {
id: id,
s: [],
n: [],
};
r.n.push(o);
return divideEntriesImplByID(o, names, entriesByNumber[id]);
})
.reduce(function (p, c) { return p + 8 + c; }, 0);
return 16 + sSum + nSum;
}
function divideEntriesImplByType(r, names, entries) {
var entriesByString = {};
var entriesByNumber = {};
entries.forEach(function (e) {
var _a, _b;
if (typeof e.type === 'string') {
var a = (_a = entriesByString[e.type]) !== null && _a !== void 0 ? _a : (entriesByString[e.type] = []);
names.push(e.type);
a.push(e);
}
else {
var a = (_b = entriesByNumber[e.type]) !== null && _b !== void 0 ? _b : (entriesByNumber[e.type] = []);
a.push(e);
}
});
var sSum = Object.keys(entriesByString)
.sort()
.map(function (type) {
var o = { type: type, s: [], n: [] };
r.s.push(o);
return divideEntriesImplByName(o, names, entriesByString[type]);
})
.reduce(function (p, c) { return p + 8 + c; }, 0);
var nSum = Object.keys(entriesByNumber)
.map(function (k) { return Number(k); })
.sort(function (a, b) { return a - b; })
.map(function (type) {
var o = { type: type, s: [], n: [] };
r.n.push(o);
return divideEntriesImplByName(o, names, entriesByNumber[type]);
})
.reduce(function (p, c) { return p + 8 + c; }, 0);
return 16 + sSum + nSum;
}
function calculateStringLengthForWrite(text) {
var length = text.length;
// limit to 65535 because the 'length' field is uint16
return length > 65535 ? 65535 : length;
}
function getStringOffset(target, strings) {
var l = strings.length;
for (var i = 0; i < l; ++i) {
var s = strings[i];
if (s.text === target) {
return s.offset;
}
}
throw new Error('Unexpected');
}
/** (returns offset just after the written text) */
function writeString(view, offset, text) {
var length = calculateStringLengthForWrite(text);
view.setUint16(offset, length, true);
offset += 2;
for (var i = 0; i < length; ++i) {
view.setUint16(offset, text.charCodeAt(i), true);
offset += 2;
}
return offset;
}
function writeLanguageTable(view, offset, strings, data) {
// characteristics
view.setUint32(offset, 0, true);
// timestamp
view.setUint32(offset + 4, 0, true);
// major version / minor version
view.setUint32(offset + 8, 0, true);
// name entries
view.setUint16(offset + 12, data.s.length, true);
// id entries
view.setUint16(offset + 14, data.n.length, true);
offset += 16;
// name entries (not in specification)
data.s.forEach(function (e) {
var strOff = getStringOffset(e.lang, strings);
view.setUint32(offset, strOff, true);
view.setUint32(offset + 4, e.offset, true);
offset += 8;
});
// id entries
data.n.forEach(function (e) {
view.setUint32(offset, e.lang, true);
view.setUint32(offset + 4, e.offset, true);
offset += 8;
});
return offset;
}
function writeNameTable(view, offset, leafOffset, strings, data) {
// characteristics
view.setUint32(offset, 0, true);
// timestamp
view.setUint32(offset + 4, 0, true);
// major version / minor version
view.setUint32(offset + 8, 0, true);
// name entries
view.setUint16(offset + 12, data.s.length, true);
// id entries
view.setUint16(offset + 14, data.n.length, true);
offset += 16;
data.s.forEach(function (e) {
e.offset = leafOffset;
leafOffset = writeLanguageTable(view, leafOffset, strings, e);
});
data.n.forEach(function (e) {
e.offset = leafOffset;
leafOffset = writeLanguageTable(view, leafOffset, strings, e);
});
data.s.forEach(function (e) {
var strOff = getStringOffset(e.id, strings);
view.setUint32(offset, strOff + 0x80000000, true);
view.setUint32(offset + 4, e.offset + 0x80000000, true);
offset += 8;
});
data.n.forEach(function (e) {
view.setUint32(offset, e.id, true);
view.setUint32(offset + 4, e.offset + 0x80000000, true);
offset += 8;
});
return leafOffset;
}
function writeTypeTable(view, offset, strings, data) {
// characteristics
view.setUint32(offset, 0, true);
// timestamp
view.setUint32(offset + 4, 0, true);
// major version / minor version
view.setUint32(offset + 8, 0, true);
// name entries
view.setUint16(offset + 12, data.s.length, true);
// id entries
view.setUint16(offset + 14, data.n.length, true);
offset += 16;
var nextTableOffset = offset + 8 * (data.s.length + data.n.length);
data.s.forEach(function (e) {
e.offset = nextTableOffset;
nextTableOffset += 16 + 8 * (e.s.length + e.n.length);
});
data.n.forEach(function (e) {
e.offset = nextTableOffset;
nextTableOffset += 16 + 8 * (e.s.length + e.n.length);
});
data.s.forEach(function (e) {
var strOff = getStringOffset(e.type, strings);
view.setUint32(offset, strOff + 0x80000000, true);
view.setUint32(offset + 4, e.offset + 0x80000000, true);
offset += 8;
nextTableOffset = writeNameTable(view, e.offset, nextTableOffset, strings, e);
});
data.n.forEach(function (e) {
view.setUint32(offset, e.type, true);
view.setUint32(offset + 4, e.offset + 0x80000000, true);
offset += 8;
nextTableOffset = writeNameTable(view, e.offset, nextTableOffset, strings, e);
});
return nextTableOffset;
}
////////////////////////////////////////////////////////////////////////////////
/** Manages resource data for NtExecutable */
var NtExecutableResource = /** @class */ (function () {
function NtExecutableResource() {
/** The timestamp for resource */
this.dateTime = 0;
/** The major version data for resource */
this.majorVersion = 0;
/** The minor version data for resource */
this.minorVersion = 0;
/** Resource entries */
this.entries = [];
/**
* The section data header of resource data (used by outputResource method).
* This instance will be null if the base executable does not contain resource data.
* You can override this field before calling outputResource method.
* (Note that the addresses and sizes are ignored for output)
*/
this.sectionDataHeader = null;
this.originalSize = 0;
}
NtExecutableResource.prototype.parse = function (section, ignoreUnparsableData) {
if (!section.data) {
return;
}
var view = new DataView(section.data);
// --- First: Resource Directory Table ---
// (off: 0 -- Characteristics (uint32))
this.dateTime = view.getUint32(4, true);
this.majorVersion = view.getUint16(8, true);
this.minorVersion = view.getUint16(10, true);
var nameCount = view.getUint16(12, true);
var idCount = view.getUint16(14, true);
var off = 16;
var res = [];
var cb = function (t, n, l) {
var off = view.getUint32(l.dataOffset, true) -
section.info.virtualAddress;
var size = view.getUint32(l.dataOffset + 4, true);
var cp = view.getUint32(l.dataOffset + 8, true);
if (off >= 0) {
var bin = new Uint8Array(size);
bin.set(new Uint8Array(section.data, off, size));
res.push({
type: t.type,
id: n.name,
lang: l.lang,
codepage: cp,
bin: bin.buffer,
});
}
else {
if (!ignoreUnparsableData) {
throw new Error('Cannot parse resource directory entry; RVA seems to be invalid.');
}
res.push({
type: t.type,
id: n.name,
lang: l.lang,
codepage: cp,
bin: new ArrayBuffer(0),
rva: l.dataOffset,
});
}
};
for (var i = 0; i < nameCount; ++i) {
var nameOffset = view.getUint32(off, true) & 0x7fffffff;
var nextTable = view.getUint32(off + 4, true);
// ignore if no next table is available
if (!(nextTable & 0x80000000)) {
off += 8;
continue;
}
nextTable &= 0x7fffffff;
var name_3 = readString(view, nameOffset);
readNameTable(view, name_3, nextTable, cb);
off += 8;
}
for (var i = 0; i < idCount; ++i) {
var typeId = view.getUint32(off, true) & 0x7fffffff;
var nextTable = view.getUint32(off + 4, true);
// ignore if no next table is available
if (!(nextTable & 0x80000000)) {
off += 8;
continue;
}
nextTable &= 0x7fffffff;
readNameTable(view, typeId, nextTable, cb);
off += 8;
}
this.entries = res;
this.originalSize = section.data.byteLength;
};
/**
* Parses resource data for `NtExecutable`.
* This function returns valid instance even if
* the executable does not have resource data.
* @param exe `NtExecutable` instance
* @param ignoreUnparsableData (default: false) specify true if skipping 'unparsable' (e.g. unusual format) data.
* When true, the resource data may break on write operation.
*/
NtExecutableResource.from = function (exe, ignoreUnparsableData) {
if (ignoreUnparsableData === void 0) { ignoreUnparsableData = false; }
var secs = []
.concat(exe.getAllSections())
.sort(function (a, b) { return a.info.virtualAddress - b.info.virtualAddress; });
var entry = exe.getSectionByEntry(ImageDirectoryEntry.Resource);
// check if the section order is supported
// (not supported if any other sections except 'relocation' is available,
// because the recalculation of virtual address is not simple)
if (entry) {
var reloc = exe.getSectionByEntry(ImageDirectoryEntry.BaseRelocation);
for (var i = 0; i < secs.length; ++i) {
var s = secs[i];
if (s === entry) {
for (var j = i + 1; j < secs.length; ++j) {
if (!reloc || secs[j] !== reloc) {
throw new Error('After Resource section, sections except for relocation are not supported');
}
}
break;
}
}
}
var r = new NtExecutableResource();
r.sectionDataHeader = entry ? cloneObject(entry.info) : null;
if (entry) {
r.parse(entry, ignoreUnparsableData);
}
return r;
};
/**
* Add or replace the resource entry.
* This method replaces the entry only if there is an entry with `type`, `id` and `lang` equal.
*/
NtExecutableResource.prototype.replaceResourceEntry = function (entry) {
for (var len = this.entries.length, i = 0; i < len; ++i) {
var e = this.entries[i];
if (e.type === entry.type &&
e.id === entry.id &&
e.lang === entry.lang) {
this.entries[i] = entry;
return;
}
}
this.entries.push(entry);
};
/**
* Returns all resource entries, which has specified type and id, as UTF-8 string data.
* @param type Resource type
* @param id Resource id
* @returns an array of lang and value pair (tuple)
*/
NtExecutableResource.prototype.getResourceEntriesAsString = function (type, id) {
return this.entries
.filter(function (entry) { return entry.type === type && entry.id === id; })
.map(function (entry) { return [entry.lang, binaryToString(entry.bin)]; });
};
/**
* Add or replace the resource entry with UTF-8 string data.
* This method is a wrapper of {@link NtExecutableResource.replaceResourceEntry}.
*/
NtExecutableResource.prototype.replaceResourceEntryFromString = function (type, id, lang, value) {
var entry = {
type: type,
id: id,
lang: lang,
codepage: 1200,
bin: stringToBinary(value),
};
this.replaceResourceEntry(entry);
};
/**
* Removes resource entries which has specified type and id.
*/
NtExecutableResource.prototype.removeResourceEntry = function (type, id, lang) {
this.entries = this.entries.filter(function (entry) {
return !(entry.type === type &&
entry.id === id &&
(typeof lang === 'undefined' || entry.lang === lang));
});
};
/**
* Generates resource data binary for NtExecutable (not for .res file)
* @param virtualAddress The virtual address for the section
* @param alignment File alignment value of executable
* @param noGrow Set true to disallow growing resource section (throw errors if data exceeds)
* @param allowShrink Set true to allow shrinking resource section (if the data size is less than original)
*/
NtExecutableResource.prototype.generateResourceData = function (virtualAddress, alignment, noGrow, allowShrink) {
if (noGrow === void 0) { noGrow = false; }
if (allowShrink === void 0) { allowShrink = false; }
// estimate data size and divide to output table
var r = {
s: [],
n: [],
};
var strings = [];
var size = divideEntriesImplByType(r, strings, this.entries);
strings = removeDuplicates(strings);
var stringsOffset = size;
size += strings.reduce(function (prev, cur) {
return prev + 2 + calculateStringLengthForWrite(cur) * 2;
}, 0);
size = roundUp(size, 8);
var descOffset = size;
size = this.entries.reduce(function (p, e) {
e.offset = p;
return p + 16;
}, descOffset);
var dataOffset = size;
size = this.entries.reduce(function (p, e) {
return roundUp(p, 8) + e.bin.byteLength;
}, dataOffset);
var alignedSize = roundUp(size, alignment);
var originalAlignedSize = roundUp(this.originalSize, alignment);
if (noGrow) {
if (alignedSize > originalAlignedSize) {
throw new Error('New resource data is larger than original');
}
}
if (!allowShrink) {
if (alignedSize < originalAlignedSize) {
alignedSize = originalAlignedSize;
}
}
// generate binary
var bin = new ArrayBuffer(alignedSize);
var view = new DataView(bin);
var o = descOffset;
var va = virtualAddress + dataOffset;
this.entries.forEach(function (e) {
var len = e.bin.byteLength;
if (typeof e.rva !== 'undefined') {
// RVA
view.setUint32(o, e.rva, true);
}
else {
va = roundUp(va, 8);
// RVA
view.setUint32(o, va, true);
va += len;
}
// size
view.setUint32(o + 4, len, true);
// codepage
view.setUint32(o + 8, e.codepage, true);
// (zero)
view.setUint32(o + 12, 0, true);
o += 16;
});
o = dataOffset;
this.entries.forEach(function (e) {
var len = e.bin.byteLength;
copyBuffer(bin, o, e.bin, 0, len);
o += roundUp(len, 8);
});
var stringsData = [];
o = stringsOffset;
strings.forEach(function (s) {
stringsData.push({
offset: o,
text: s,
});
o = writeString(view, o, s);
});
writeTypeTable(view, 0, stringsData, r);
// fill with 'PADDINGX'
if (alignedSize > size) {
var pad = 'PADDINGX';
for (var i = size, j = 0; i < alignedSize; ++i, ++j) {
if (j === 8) {
j = 0;
}
view.setUint8(i, pad.charCodeAt(j));
}
}
return {
bin: bin,
rawSize: size,
dataOffset: dataOffset,
descEntryOffset: descOffset,
descEntryCount: this.entries.length,
};
};
/**
* Writes holding resource data to specified NtExecutable instance.
* @param exeDest An NtExecutable instance to write resource section to
* @param noGrow Set true to disallow growing resource section (throw errors if data exceeds)
* @param allowShrink Set true to allow shrinking resource section (if the data size is less than original)
*/
NtExecutableResource.prototype.outputResource = function (exeDest, noGrow, allowShrink) {
if (noGrow === void 0) { noGrow = false; }
if (allowShrink === void 0) { allowShrink = false; }
// make section data
var fileAlign = exeDest.getFileAlignment();
var sectionData;
if (this.sectionDataHeader) {
sectionData = {
data: null,
info: cloneObject(this.sectionDataHeader),
};
}
else {
sectionData = {
data: null,
info: {
name: '.rsrc',
virtualSize: 0,
virtualAddress: 0,
sizeOfRawData: 0,
pointerToRawData: 0,
pointerToRelocations: 0,
pointerToLineNumbers: 0,
numberOfRelocations: 0,
numberOfLineNumbers: 0,
characteristics: 0x40000040, // read access and initialized data
},
};
}
// first, set virtualAddress to 0 because
// the virtual address is not determined now
var data = this.generateResourceData(0, fileAlign, noGrow, allowShrink);
sectionData.data = data.bin;
sectionData.info.sizeOfRawData = data.bin.byteLength;
sectionData.info.virtualSize = data.rawSize;
// write as section
exeDest.setSectionByEntry(ImageDirectoryEntry.Resource, sectionData);
// rewrite section raw-data
var generatedSection = exeDest.getSectionByEntry(ImageDirectoryEntry.Resource);
var view = new DataView(generatedSection.data);
// set RVA
var o = data.descEntryOffset;
var va = generatedSection.info.virtualAddress + data.dataOffset;
for (var i = 0; i < data.descEntryCount; ++i) {
var len = view.getUint32(o + 4, true);
va = roundUp(va, 8);
// RVA
view.setUint32(o, va, true);
va += len;
o += 16;
}
};
return NtExecutableResource;
}());
export default NtExecutableResource;

View File

@@ -0,0 +1,14 @@
import FormatBase from './FormatBase.js';
/** abstract class that support array-like methods and 'for...of' operation */
declare abstract class ArrayFormatBase<T> extends FormatBase {
protected constructor(view: DataView);
abstract readonly length: number;
abstract get(index: number): Readonly<T>;
abstract set(index: number, data: T): void;
forEach(callback: (value: T, index: number, base: this) => void): void;
_iterator(): Iterator<Readonly<T>>;
}
interface ArrayFormatBase<T> {
[Symbol.iterator]: () => Iterator<Readonly<T>>;
}
export default ArrayFormatBase;

View File

@@ -0,0 +1,64 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import FormatBase from './FormatBase.js';
/** abstract class that support array-like methods and 'for...of' operation */
var ArrayFormatBase = /** @class */ (function (_super) {
__extends(ArrayFormatBase, _super);
function ArrayFormatBase(view) {
return _super.call(this, view) || this;
}
ArrayFormatBase.prototype.forEach = function (callback) {
var len = this.length;
var a = [];
a.length = len;
for (var i = 0; i < len; ++i) {
a[i] = this.get(i);
}
for (var i = 0; i < len; ++i) {
callback(a[i], i, this);
}
};
ArrayFormatBase.prototype._iterator = function () {
return new (/** @class */ (function () {
function class_1(base) {
this.base = base;
this.i = 0;
}
class_1.prototype.next = function () {
if (this.i === this.base.length) {
return {
value: undefined,
done: true,
};
}
else {
return {
value: this.base.get(this.i++),
done: false,
};
}
};
return class_1;
}()))(this);
};
return ArrayFormatBase;
}(FormatBase));
/* istanbul ignore else */
if (typeof Symbol !== 'undefined') {
ArrayFormatBase.prototype[Symbol.iterator] =
ArrayFormatBase.prototype._iterator;
}
export default ArrayFormatBase;

View File

@@ -0,0 +1,6 @@
export default abstract class FormatBase {
protected readonly view: DataView;
protected constructor(view: DataView);
copyTo(bin: ArrayBuffer, offset: number): void;
get byteLength(): number;
}

View File

@@ -0,0 +1,17 @@
var FormatBase = /** @class */ (function () {
function FormatBase(view) {
this.view = view;
}
FormatBase.prototype.copyTo = function (bin, offset) {
new Uint8Array(bin, offset, this.view.byteLength).set(new Uint8Array(this.view.buffer, this.view.byteOffset, this.view.byteLength));
};
Object.defineProperty(FormatBase.prototype, "byteLength", {
get: function () {
return this.view.byteLength;
},
enumerable: false,
configurable: true
});
return FormatBase;
}());
export default FormatBase;

View File

@@ -0,0 +1,16 @@
import ArrayFormatBase from './ArrayFormatBase.js';
export interface ImageDataDirectory {
virtualAddress: number;
size: number;
}
export default class ImageDataDirectoryArray extends ArrayFormatBase<ImageDataDirectory> {
static readonly size = 128;
static readonly itemSize = 8;
readonly length = 16;
private constructor();
/** @note This does not clone binary data; the changes to the array will modify the specified buffer `bin` */
static from(bin: ArrayBuffer, offset?: number): ImageDataDirectoryArray;
get(index: number): Readonly<ImageDataDirectory>;
set(index: number, data: ImageDataDirectory): void;
findIndexByVirtualAddress(virtualAddress: number): number | null;
}

View File

@@ -0,0 +1,53 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import ArrayFormatBase from './ArrayFormatBase.js';
var ImageDataDirectoryArray = /** @class */ (function (_super) {
__extends(ImageDataDirectoryArray, _super);
function ImageDataDirectoryArray(view) {
var _this = _super.call(this, view) || this;
_this.length = 16;
return _this;
}
/** @note This does not clone binary data; the changes to the array will modify the specified buffer `bin` */
ImageDataDirectoryArray.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
return new ImageDataDirectoryArray(new DataView(bin, offset, 128));
};
ImageDataDirectoryArray.prototype.get = function (index) {
return {
virtualAddress: this.view.getUint32(index * 8, true),
size: this.view.getUint32(4 + index * 8, true),
};
};
ImageDataDirectoryArray.prototype.set = function (index, data) {
this.view.setUint32(index * 8, data.virtualAddress, true);
this.view.setUint32(4 + index * 8, data.size, true);
};
ImageDataDirectoryArray.prototype.findIndexByVirtualAddress = function (virtualAddress) {
for (var i = 0; i < 16; ++i) {
var va = this.view.getUint32(i * 8, true);
var vs = this.view.getUint32(4 + i * 8, true);
if (virtualAddress >= va && virtualAddress < va + vs) {
return i;
}
}
return null;
};
ImageDataDirectoryArray.size = 128; // 16 * 8
ImageDataDirectoryArray.itemSize = 8;
return ImageDataDirectoryArray;
}(ArrayFormatBase));
export default ImageDataDirectoryArray;

View File

@@ -0,0 +1,22 @@
declare enum ImageDirectoryEntry {
Export = 0,
Import = 1,
Resource = 2,
Exception = 3,
Certificate = 4,
Security = 4,
BaseRelocation = 5,
Debug = 6,
Architecture = 7,
GlobalPointer = 8,
Tls = 9,
TLS = 9,
LoadConfig = 10,
BoundImport = 11,
Iat = 12,
IAT = 12,
DelayImport = 13,
ComDescriptor = 14,
COMDescriptor = 14
}
export default ImageDirectoryEntry;

View File

@@ -0,0 +1,24 @@
var ImageDirectoryEntry;
(function (ImageDirectoryEntry) {
ImageDirectoryEntry[ImageDirectoryEntry["Export"] = 0] = "Export";
ImageDirectoryEntry[ImageDirectoryEntry["Import"] = 1] = "Import";
ImageDirectoryEntry[ImageDirectoryEntry["Resource"] = 2] = "Resource";
ImageDirectoryEntry[ImageDirectoryEntry["Exception"] = 3] = "Exception";
ImageDirectoryEntry[ImageDirectoryEntry["Certificate"] = 4] = "Certificate";
// alias
ImageDirectoryEntry[ImageDirectoryEntry["Security"] = 4] = "Security";
ImageDirectoryEntry[ImageDirectoryEntry["BaseRelocation"] = 5] = "BaseRelocation";
ImageDirectoryEntry[ImageDirectoryEntry["Debug"] = 6] = "Debug";
ImageDirectoryEntry[ImageDirectoryEntry["Architecture"] = 7] = "Architecture";
ImageDirectoryEntry[ImageDirectoryEntry["GlobalPointer"] = 8] = "GlobalPointer";
ImageDirectoryEntry[ImageDirectoryEntry["Tls"] = 9] = "Tls";
ImageDirectoryEntry[ImageDirectoryEntry["TLS"] = 9] = "TLS";
ImageDirectoryEntry[ImageDirectoryEntry["LoadConfig"] = 10] = "LoadConfig";
ImageDirectoryEntry[ImageDirectoryEntry["BoundImport"] = 11] = "BoundImport";
ImageDirectoryEntry[ImageDirectoryEntry["Iat"] = 12] = "Iat";
ImageDirectoryEntry[ImageDirectoryEntry["IAT"] = 12] = "IAT";
ImageDirectoryEntry[ImageDirectoryEntry["DelayImport"] = 13] = "DelayImport";
ImageDirectoryEntry[ImageDirectoryEntry["ComDescriptor"] = 14] = "ComDescriptor";
ImageDirectoryEntry[ImageDirectoryEntry["COMDescriptor"] = 14] = "COMDescriptor";
})(ImageDirectoryEntry || (ImageDirectoryEntry = {}));
export default ImageDirectoryEntry;

View File

@@ -0,0 +1,42 @@
import FormatBase from './FormatBase.js';
export default class ImageDosHeader extends FormatBase {
static readonly size = 64;
static readonly DEFAULT_MAGIC = 23117;
private constructor();
static from(bin: ArrayBuffer | ArrayBufferView, offset?: number): ImageDosHeader;
isValid(): boolean;
get magic(): number;
set magic(val: number);
get lastPageSize(): number;
set lastPageSize(val: number);
get pages(): number;
set pages(val: number);
get relocations(): number;
set relocations(val: number);
get headerSizeInParagraph(): number;
set headerSizeInParagraph(val: number);
get minAllocParagraphs(): number;
set minAllocParagraphs(val: number);
get maxAllocParagraphs(): number;
set maxAllocParagraphs(val: number);
get initialSS(): number;
set initialSS(val: number);
get initialSP(): number;
set initialSP(val: number);
get checkSum(): number;
set checkSum(val: number);
get initialIP(): number;
set initialIP(val: number);
get initialCS(): number;
set initialCS(val: number);
get relocationTableAddress(): number;
set relocationTableAddress(val: number);
get overlayNum(): number;
set overlayNum(val: number);
get oemId(): number;
set oemId(val: number);
get oemInfo(): number;
set oemInfo(val: number);
get newHeaderAddress(): number;
set newHeaderAddress(val: number);
}

View File

@@ -0,0 +1,206 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import FormatBase from './FormatBase.js';
import { createDataView } from '../util/functions.js';
var ImageDosHeader = /** @class */ (function (_super) {
__extends(ImageDosHeader, _super);
function ImageDosHeader(view) {
return _super.call(this, view) || this;
}
ImageDosHeader.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
return new ImageDosHeader(createDataView(bin, offset, 64));
};
ImageDosHeader.prototype.isValid = function () {
return this.magic === ImageDosHeader.DEFAULT_MAGIC;
};
Object.defineProperty(ImageDosHeader.prototype, "magic", {
get: function () {
return this.view.getUint16(0, true);
},
set: function (val) {
this.view.setUint16(0, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "lastPageSize", {
get: function () {
return this.view.getUint16(2, true);
},
set: function (val) {
this.view.setUint16(2, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "pages", {
get: function () {
return this.view.getUint16(4, true);
},
set: function (val) {
this.view.setUint16(4, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "relocations", {
get: function () {
return this.view.getUint16(6, true);
},
set: function (val) {
this.view.setUint16(6, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "headerSizeInParagraph", {
get: function () {
return this.view.getUint16(8, true);
},
set: function (val) {
this.view.setUint16(8, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "minAllocParagraphs", {
get: function () {
return this.view.getUint16(10, true);
},
set: function (val) {
this.view.setUint16(10, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "maxAllocParagraphs", {
get: function () {
return this.view.getUint16(12, true);
},
set: function (val) {
this.view.setUint16(12, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "initialSS", {
get: function () {
return this.view.getUint16(14, true);
},
set: function (val) {
this.view.setUint16(14, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "initialSP", {
get: function () {
return this.view.getUint16(16, true);
},
set: function (val) {
this.view.setUint16(16, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "checkSum", {
get: function () {
return this.view.getUint16(18, true);
},
set: function (val) {
this.view.setUint16(18, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "initialIP", {
get: function () {
return this.view.getUint16(20, true);
},
set: function (val) {
this.view.setUint16(20, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "initialCS", {
get: function () {
return this.view.getUint16(22, true);
},
set: function (val) {
this.view.setUint16(22, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "relocationTableAddress", {
get: function () {
return this.view.getUint16(24, true);
},
set: function (val) {
this.view.setUint16(24, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "overlayNum", {
get: function () {
return this.view.getUint16(26, true);
},
set: function (val) {
this.view.setUint16(26, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "oemId", {
// WORD e_res[4] (28,30,32,34)
get: function () {
return this.view.getUint16(36, true);
},
set: function (val) {
this.view.setUint16(36, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "oemInfo", {
get: function () {
return this.view.getUint16(38, true);
},
set: function (val) {
this.view.setUint16(38, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "newHeaderAddress", {
// WORD e_res2[10] (40,42,44,46,48,50,52,54,56,58)
get: function () {
return this.view.getUint32(60, true);
},
set: function (val) {
this.view.setUint32(60, val, true);
},
enumerable: false,
configurable: true
});
ImageDosHeader.size = 64;
ImageDosHeader.DEFAULT_MAGIC = 0x5a4d; // 'MZ'
return ImageDosHeader;
}(FormatBase));
export default ImageDosHeader;

View File

@@ -0,0 +1,20 @@
import FormatBase from './FormatBase.js';
export default class ImageFileHeader extends FormatBase {
static readonly size = 20;
private constructor();
static from(bin: ArrayBuffer, offset?: number): ImageFileHeader;
get machine(): number;
set machine(val: number);
get numberOfSections(): number;
set numberOfSections(val: number);
get timeDateStamp(): number;
set timeDateStamp(val: number);
get pointerToSymbolTable(): number;
set pointerToSymbolTable(val: number);
get numberOfSymbols(): number;
set numberOfSymbols(val: number);
get sizeOfOptionalHeader(): number;
set sizeOfOptionalHeader(val: number);
get characteristics(): number;
set characteristics(val: number);
}

View File

@@ -0,0 +1,99 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import FormatBase from './FormatBase.js';
var ImageFileHeader = /** @class */ (function (_super) {
__extends(ImageFileHeader, _super);
function ImageFileHeader(view) {
return _super.call(this, view) || this;
}
ImageFileHeader.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
return new ImageFileHeader(new DataView(bin, offset, 20));
};
Object.defineProperty(ImageFileHeader.prototype, "machine", {
get: function () {
return this.view.getUint16(0, true);
},
set: function (val) {
this.view.setUint16(0, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "numberOfSections", {
get: function () {
return this.view.getUint16(2, true);
},
set: function (val) {
this.view.setUint16(2, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "timeDateStamp", {
get: function () {
return this.view.getUint32(4, true);
},
set: function (val) {
this.view.setUint32(4, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "pointerToSymbolTable", {
get: function () {
return this.view.getUint32(8, true);
},
set: function (val) {
this.view.setUint32(8, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "numberOfSymbols", {
get: function () {
return this.view.getUint32(12, true);
},
set: function (val) {
this.view.setUint32(12, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "sizeOfOptionalHeader", {
get: function () {
return this.view.getUint16(16, true);
},
set: function (val) {
this.view.setUint16(16, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "characteristics", {
get: function () {
return this.view.getUint16(18, true);
},
set: function (val) {
this.view.setUint16(18, val, true);
},
enumerable: false,
configurable: true
});
ImageFileHeader.size = 20;
return ImageFileHeader;
}(FormatBase));
export default ImageFileHeader;

View File

@@ -0,0 +1,19 @@
import FormatBase from './FormatBase.js';
import ImageFileHeader from './ImageFileHeader.js';
import ImageOptionalHeader from './ImageOptionalHeader.js';
import ImageOptionalHeader64 from './ImageOptionalHeader64.js';
import ImageDataDirectoryArray from './ImageDataDirectoryArray.js';
export default class ImageNtHeaders extends FormatBase {
static readonly DEFAULT_SIGNATURE = 17744;
private constructor();
static from(bin: ArrayBuffer | ArrayBufferView, offset?: number): ImageNtHeaders;
isValid(): boolean;
is32bit(): boolean;
get signature(): number;
set signature(val: number);
get fileHeader(): ImageFileHeader;
get optionalHeader(): ImageOptionalHeader | ImageOptionalHeader64;
get optionalHeaderDataDirectory(): ImageDataDirectoryArray;
getDataDirectoryOffset(): number;
getSectionHeaderOffset(): number;
}

View File

@@ -0,0 +1,101 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import FormatBase from './FormatBase.js';
import ImageFileHeader from './ImageFileHeader.js';
import ImageOptionalHeader from './ImageOptionalHeader.js';
import ImageOptionalHeader64 from './ImageOptionalHeader64.js';
import ImageDataDirectoryArray from './ImageDataDirectoryArray.js';
import { createDataView } from '../util/functions.js';
var ImageNtHeaders = /** @class */ (function (_super) {
__extends(ImageNtHeaders, _super);
function ImageNtHeaders(view) {
return _super.call(this, view) || this;
}
ImageNtHeaders.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
var magic = createDataView(bin, offset + ImageFileHeader.size, 6).getUint16(4, true);
var len = 4 + ImageFileHeader.size + ImageDataDirectoryArray.size;
if (magic === ImageOptionalHeader64.DEFAULT_MAGIC) {
len += ImageOptionalHeader64.size;
}
else {
len += ImageOptionalHeader.size;
}
return new ImageNtHeaders(createDataView(bin, offset, len));
};
ImageNtHeaders.prototype.isValid = function () {
return this.signature === ImageNtHeaders.DEFAULT_SIGNATURE;
};
ImageNtHeaders.prototype.is32bit = function () {
return (this.view.getUint16(ImageFileHeader.size + 4, true) ===
ImageOptionalHeader.DEFAULT_MAGIC);
};
Object.defineProperty(ImageNtHeaders.prototype, "signature", {
get: function () {
return this.view.getUint32(0, true);
},
set: function (val) {
this.view.setUint32(0, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageNtHeaders.prototype, "fileHeader", {
get: function () {
return ImageFileHeader.from(this.view.buffer, this.view.byteOffset + 4);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageNtHeaders.prototype, "optionalHeader", {
get: function () {
var off = ImageFileHeader.size + 4;
var magic = this.view.getUint16(off, true);
if (magic === ImageOptionalHeader64.DEFAULT_MAGIC) {
return ImageOptionalHeader64.from(this.view.buffer, this.view.byteOffset + off);
}
else {
return ImageOptionalHeader.from(this.view.buffer, this.view.byteOffset + off);
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageNtHeaders.prototype, "optionalHeaderDataDirectory", {
get: function () {
return ImageDataDirectoryArray.from(this.view.buffer, this.view.byteOffset + this.getDataDirectoryOffset());
},
enumerable: false,
configurable: true
});
ImageNtHeaders.prototype.getDataDirectoryOffset = function () {
var off = ImageFileHeader.size + 4;
var magic = this.view.getUint16(off, true);
if (magic === ImageOptionalHeader64.DEFAULT_MAGIC) {
off += ImageOptionalHeader64.size;
}
else {
off += ImageOptionalHeader.size;
}
return off;
};
ImageNtHeaders.prototype.getSectionHeaderOffset = function () {
return this.getDataDirectoryOffset() + ImageDataDirectoryArray.size;
};
ImageNtHeaders.DEFAULT_SIGNATURE = 0x4550; // 'PE\x00\x00'
return ImageNtHeaders;
}(FormatBase));
export default ImageNtHeaders;

View File

@@ -0,0 +1,67 @@
import FormatBase from './FormatBase.js';
export default class ImageOptionalHeader extends FormatBase {
static readonly size = 96;
static readonly DEFAULT_MAGIC = 267;
private constructor();
static from(bin: ArrayBuffer, offset?: number): ImageOptionalHeader;
get magic(): number;
set magic(val: number);
get majorLinkerVersion(): number;
set majorLinkerVersion(val: number);
get minorLinkerVersion(): number;
set minorLinkerVersion(val: number);
get sizeOfCode(): number;
set sizeOfCode(val: number);
get sizeOfInitializedData(): number;
set sizeOfInitializedData(val: number);
get sizeOfUninitializedData(): number;
set sizeOfUninitializedData(val: number);
get addressOfEntryPoint(): number;
set addressOfEntryPoint(val: number);
get baseOfCode(): number;
set baseOfCode(val: number);
get baseOfData(): number;
set baseOfData(val: number);
get imageBase(): number;
set imageBase(val: number);
get sectionAlignment(): number;
set sectionAlignment(val: number);
get fileAlignment(): number;
set fileAlignment(val: number);
get majorOperatingSystemVersion(): number;
set majorOperatingSystemVersion(val: number);
get minorOperatingSystemVersion(): number;
set minorOperatingSystemVersion(val: number);
get majorImageVersion(): number;
set majorImageVersion(val: number);
get minorImageVersion(): number;
set minorImageVersion(val: number);
get majorSubsystemVersion(): number;
set majorSubsystemVersion(val: number);
get minorSubsystemVersion(): number;
set minorSubsystemVersion(val: number);
get win32VersionValue(): number;
set win32VersionValue(val: number);
get sizeOfImage(): number;
set sizeOfImage(val: number);
get sizeOfHeaders(): number;
set sizeOfHeaders(val: number);
get checkSum(): number;
set checkSum(val: number);
get subsystem(): number;
set subsystem(val: number);
get dllCharacteristics(): number;
set dllCharacteristics(val: number);
get sizeOfStackReserve(): number;
set sizeOfStackReserve(val: number);
get sizeOfStackCommit(): number;
set sizeOfStackCommit(val: number);
get sizeOfHeapReserve(): number;
set sizeOfHeapReserve(val: number);
get sizeOfHeapCommit(): number;
set sizeOfHeapCommit(val: number);
get loaderFlags(): number;
set loaderFlags(val: number);
get numberOfRvaAndSizes(): number;
set numberOfRvaAndSizes(val: number);
}

View File

@@ -0,0 +1,330 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import FormatBase from './FormatBase.js';
var ImageOptionalHeader = /** @class */ (function (_super) {
__extends(ImageOptionalHeader, _super);
function ImageOptionalHeader(view) {
return _super.call(this, view) || this;
}
ImageOptionalHeader.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
return new ImageOptionalHeader(new DataView(bin, offset, 96));
};
Object.defineProperty(ImageOptionalHeader.prototype, "magic", {
get: function () {
return this.view.getUint16(0, true);
},
set: function (val) {
this.view.setUint16(0, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "majorLinkerVersion", {
get: function () {
return this.view.getUint8(2);
},
set: function (val) {
this.view.setUint8(2, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "minorLinkerVersion", {
get: function () {
return this.view.getUint8(3);
},
set: function (val) {
this.view.setUint8(3, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfCode", {
get: function () {
return this.view.getUint32(4, true);
},
set: function (val) {
this.view.setUint32(4, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfInitializedData", {
get: function () {
return this.view.getUint32(8, true);
},
set: function (val) {
this.view.setUint32(8, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfUninitializedData", {
get: function () {
return this.view.getUint32(12, true);
},
set: function (val) {
this.view.setUint32(12, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "addressOfEntryPoint", {
get: function () {
return this.view.getUint32(16, true);
},
set: function (val) {
this.view.setUint32(16, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "baseOfCode", {
get: function () {
return this.view.getUint32(20, true);
},
set: function (val) {
this.view.setUint32(20, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "baseOfData", {
get: function () {
return this.view.getUint32(24, true);
},
set: function (val) {
this.view.setUint32(24, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "imageBase", {
get: function () {
return this.view.getUint32(28, true);
},
set: function (val) {
this.view.setUint32(28, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sectionAlignment", {
get: function () {
return this.view.getUint32(32, true);
},
set: function (val) {
this.view.setUint32(32, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "fileAlignment", {
get: function () {
return this.view.getUint32(36, true);
},
set: function (val) {
this.view.setUint32(36, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "majorOperatingSystemVersion", {
get: function () {
return this.view.getUint16(40, true);
},
set: function (val) {
this.view.setUint16(40, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "minorOperatingSystemVersion", {
get: function () {
return this.view.getUint16(42, true);
},
set: function (val) {
this.view.setUint16(42, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "majorImageVersion", {
get: function () {
return this.view.getUint16(44, true);
},
set: function (val) {
this.view.setUint16(44, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "minorImageVersion", {
get: function () {
return this.view.getUint16(46, true);
},
set: function (val) {
this.view.setUint16(46, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "majorSubsystemVersion", {
get: function () {
return this.view.getUint16(48, true);
},
set: function (val) {
this.view.setUint16(48, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "minorSubsystemVersion", {
get: function () {
return this.view.getUint16(50, true);
},
set: function (val) {
this.view.setUint16(50, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "win32VersionValue", {
get: function () {
return this.view.getUint32(52, true);
},
set: function (val) {
this.view.setUint32(52, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfImage", {
get: function () {
return this.view.getUint32(56, true);
},
set: function (val) {
this.view.setUint32(56, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfHeaders", {
get: function () {
return this.view.getUint32(60, true);
},
set: function (val) {
this.view.setUint32(60, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "checkSum", {
get: function () {
return this.view.getUint32(64, true);
},
set: function (val) {
this.view.setUint32(64, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "subsystem", {
get: function () {
return this.view.getUint16(68, true);
},
set: function (val) {
this.view.setUint16(68, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "dllCharacteristics", {
get: function () {
return this.view.getUint16(70, true);
},
set: function (val) {
this.view.setUint16(70, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfStackReserve", {
get: function () {
return this.view.getUint32(72, true);
},
set: function (val) {
this.view.setUint32(72, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfStackCommit", {
get: function () {
return this.view.getUint32(76, true);
},
set: function (val) {
this.view.setUint32(76, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfHeapReserve", {
get: function () {
return this.view.getUint32(80, true);
},
set: function (val) {
this.view.setUint32(80, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfHeapCommit", {
get: function () {
return this.view.getUint32(84, true);
},
set: function (val) {
this.view.setUint32(84, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "loaderFlags", {
get: function () {
return this.view.getUint32(88, true);
},
set: function (val) {
this.view.setUint32(88, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "numberOfRvaAndSizes", {
get: function () {
return this.view.getUint32(92, true);
},
set: function (val) {
this.view.setUint32(92, val, true);
},
enumerable: false,
configurable: true
});
ImageOptionalHeader.size = 96;
ImageOptionalHeader.DEFAULT_MAGIC = 0x10b;
return ImageOptionalHeader;
}(FormatBase));
export default ImageOptionalHeader;

View File

@@ -0,0 +1,75 @@
import FormatBase from './FormatBase.js';
export default class ImageOptionalHeader64 extends FormatBase {
static readonly size = 112;
static readonly DEFAULT_MAGIC = 523;
private constructor();
static from(bin: ArrayBuffer, offset?: number): ImageOptionalHeader64;
get magic(): number;
set magic(val: number);
get majorLinkerVersion(): number;
set majorLinkerVersion(val: number);
get minorLinkerVersion(): number;
set minorLinkerVersion(val: number);
get sizeOfCode(): number;
set sizeOfCode(val: number);
get sizeOfInitializedData(): number;
set sizeOfInitializedData(val: number);
get sizeOfUninitializedData(): number;
set sizeOfUninitializedData(val: number);
get addressOfEntryPoint(): number;
set addressOfEntryPoint(val: number);
get baseOfCode(): number;
set baseOfCode(val: number);
get imageBase(): number;
set imageBase(val: number);
get imageBaseBigInt(): bigint;
set imageBaseBigInt(val: bigint);
get sectionAlignment(): number;
set sectionAlignment(val: number);
get fileAlignment(): number;
set fileAlignment(val: number);
get majorOperatingSystemVersion(): number;
set majorOperatingSystemVersion(val: number);
get minorOperatingSystemVersion(): number;
set minorOperatingSystemVersion(val: number);
get majorImageVersion(): number;
set majorImageVersion(val: number);
get minorImageVersion(): number;
set minorImageVersion(val: number);
get majorSubsystemVersion(): number;
set majorSubsystemVersion(val: number);
get minorSubsystemVersion(): number;
set minorSubsystemVersion(val: number);
get win32VersionValue(): number;
set win32VersionValue(val: number);
get sizeOfImage(): number;
set sizeOfImage(val: number);
get sizeOfHeaders(): number;
set sizeOfHeaders(val: number);
get checkSum(): number;
set checkSum(val: number);
get subsystem(): number;
set subsystem(val: number);
get dllCharacteristics(): number;
set dllCharacteristics(val: number);
get sizeOfStackReserve(): number;
set sizeOfStackReserve(val: number);
get sizeOfStackReserveBigInt(): bigint;
set sizeOfStackReserveBigInt(val: bigint);
get sizeOfStackCommit(): number;
set sizeOfStackCommit(val: number);
get sizeOfStackCommitBigInt(): bigint;
set sizeOfStackCommitBigInt(val: bigint);
get sizeOfHeapReserve(): number;
set sizeOfHeapReserve(val: number);
get sizeOfHeapReserveBigInt(): bigint;
set sizeOfHeapReserveBigInt(val: bigint);
get sizeOfHeapCommit(): number;
set sizeOfHeapCommit(val: number);
get sizeOfHeapCommitBigInt(): bigint;
set sizeOfHeapCommitBigInt(val: bigint);
get loaderFlags(): number;
set loaderFlags(val: number);
get numberOfRvaAndSizes(): number;
set numberOfRvaAndSizes(val: number);
}

View File

@@ -0,0 +1,394 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import FormatBase from './FormatBase.js';
function getUint64LE(view, offset) {
return (view.getUint32(offset + 4, true) * 0x100000000 +
view.getUint32(offset, true));
}
function setUint64LE(view, offset, val) {
view.setUint32(offset, val & 0xffffffff, true);
view.setUint32(offset + 4, Math.floor(val / 0x100000000), true);
}
function getUint64LEBigInt(view, offset) {
/* istanbul ignore if */
if (typeof BigInt === 'undefined') {
throw new Error('BigInt not supported');
}
return (BigInt(0x100000000) * BigInt(view.getUint32(offset + 4, true)) +
BigInt(view.getUint32(offset, true)));
}
function setUint64LEBigInt(view, offset, val) {
/* istanbul ignore if */
if (typeof BigInt === 'undefined') {
throw new Error('BigInt not supported');
}
view.setUint32(offset, Number(val & BigInt(0xffffffff)), true);
view.setUint32(offset + 4, Math.floor(Number((val / BigInt(0x100000000)) & BigInt(0xffffffff))), true);
}
var ImageOptionalHeader64 = /** @class */ (function (_super) {
__extends(ImageOptionalHeader64, _super);
function ImageOptionalHeader64(view) {
return _super.call(this, view) || this;
}
ImageOptionalHeader64.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
return new ImageOptionalHeader64(new DataView(bin, offset, 112));
};
Object.defineProperty(ImageOptionalHeader64.prototype, "magic", {
get: function () {
return this.view.getUint16(0, true);
},
set: function (val) {
this.view.setUint16(0, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "majorLinkerVersion", {
get: function () {
return this.view.getUint8(2);
},
set: function (val) {
this.view.setUint8(2, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "minorLinkerVersion", {
get: function () {
return this.view.getUint8(3);
},
set: function (val) {
this.view.setUint8(3, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfCode", {
get: function () {
return this.view.getUint32(4, true);
},
set: function (val) {
this.view.setUint32(4, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfInitializedData", {
get: function () {
return this.view.getUint32(8, true);
},
set: function (val) {
this.view.setUint32(8, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfUninitializedData", {
get: function () {
return this.view.getUint32(12, true);
},
set: function (val) {
this.view.setUint32(12, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "addressOfEntryPoint", {
get: function () {
return this.view.getUint32(16, true);
},
set: function (val) {
this.view.setUint32(16, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "baseOfCode", {
get: function () {
return this.view.getUint32(20, true);
},
set: function (val) {
this.view.setUint32(20, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "imageBase", {
get: function () {
return getUint64LE(this.view, 24);
},
set: function (val) {
setUint64LE(this.view, 24, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "imageBaseBigInt", {
get: function () {
return getUint64LEBigInt(this.view, 24);
},
set: function (val) {
setUint64LEBigInt(this.view, 24, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sectionAlignment", {
get: function () {
return this.view.getUint32(32, true);
},
set: function (val) {
this.view.setUint32(32, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "fileAlignment", {
get: function () {
return this.view.getUint32(36, true);
},
set: function (val) {
this.view.setUint32(36, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "majorOperatingSystemVersion", {
get: function () {
return this.view.getUint16(40, true);
},
set: function (val) {
this.view.setUint16(40, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "minorOperatingSystemVersion", {
get: function () {
return this.view.getUint16(42, true);
},
set: function (val) {
this.view.setUint16(42, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "majorImageVersion", {
get: function () {
return this.view.getUint16(44, true);
},
set: function (val) {
this.view.setUint16(44, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "minorImageVersion", {
get: function () {
return this.view.getUint16(46, true);
},
set: function (val) {
this.view.setUint16(46, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "majorSubsystemVersion", {
get: function () {
return this.view.getUint16(48, true);
},
set: function (val) {
this.view.setUint16(48, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "minorSubsystemVersion", {
get: function () {
return this.view.getUint16(50, true);
},
set: function (val) {
this.view.setUint16(50, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "win32VersionValue", {
get: function () {
return this.view.getUint32(52, true);
},
set: function (val) {
this.view.setUint32(52, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfImage", {
get: function () {
return this.view.getUint32(56, true);
},
set: function (val) {
this.view.setUint32(56, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfHeaders", {
get: function () {
return this.view.getUint32(60, true);
},
set: function (val) {
this.view.setUint32(60, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "checkSum", {
get: function () {
return this.view.getUint32(64, true);
},
set: function (val) {
this.view.setUint32(64, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "subsystem", {
get: function () {
return this.view.getUint16(68, true);
},
set: function (val) {
this.view.setUint16(68, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "dllCharacteristics", {
get: function () {
return this.view.getUint16(70, true);
},
set: function (val) {
this.view.setUint16(70, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfStackReserve", {
get: function () {
return getUint64LE(this.view, 72);
},
set: function (val) {
setUint64LE(this.view, 72, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfStackReserveBigInt", {
get: function () {
return getUint64LEBigInt(this.view, 72);
},
set: function (val) {
setUint64LEBigInt(this.view, 72, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfStackCommit", {
get: function () {
return getUint64LE(this.view, 80);
},
set: function (val) {
setUint64LE(this.view, 80, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfStackCommitBigInt", {
get: function () {
return getUint64LEBigInt(this.view, 80);
},
set: function (val) {
setUint64LEBigInt(this.view, 80, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfHeapReserve", {
get: function () {
return getUint64LE(this.view, 88);
},
set: function (val) {
setUint64LE(this.view, 88, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfHeapReserveBigInt", {
get: function () {
return getUint64LEBigInt(this.view, 88);
},
set: function (val) {
setUint64LEBigInt(this.view, 88, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfHeapCommit", {
get: function () {
return getUint64LE(this.view, 96);
},
set: function (val) {
setUint64LE(this.view, 96, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfHeapCommitBigInt", {
get: function () {
return getUint64LEBigInt(this.view, 96);
},
set: function (val) {
setUint64LEBigInt(this.view, 96, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "loaderFlags", {
get: function () {
return this.view.getUint32(104, true);
},
set: function (val) {
this.view.setUint32(104, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "numberOfRvaAndSizes", {
get: function () {
return this.view.getUint32(108, true);
},
set: function (val) {
this.view.setUint32(108, val, true);
},
enumerable: false,
configurable: true
});
ImageOptionalHeader64.size = 112;
ImageOptionalHeader64.DEFAULT_MAGIC = 0x20b;
return ImageOptionalHeader64;
}(FormatBase));
export default ImageOptionalHeader64;

View File

@@ -0,0 +1,21 @@
import ArrayFormatBase from './ArrayFormatBase.js';
export interface ImageSectionHeader {
name: string;
virtualSize: number;
virtualAddress: number;
sizeOfRawData: number;
pointerToRawData: number;
pointerToRelocations: number;
pointerToLineNumbers: number;
numberOfRelocations: number;
numberOfLineNumbers: number;
characteristics: number;
}
export default class ImageSectionHeaderArray extends ArrayFormatBase<ImageSectionHeader> {
readonly length: number;
static readonly itemSize = 40;
private constructor();
static from(bin: ArrayBuffer, length: number, offset?: number): ImageSectionHeaderArray;
get(index: number): Readonly<ImageSectionHeader>;
set(index: number, data: ImageSectionHeader): void;
}

View File

@@ -0,0 +1,59 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import ArrayFormatBase from './ArrayFormatBase.js';
import { getFixedString, setFixedString } from '../util/functions.js';
var ImageSectionHeaderArray = /** @class */ (function (_super) {
__extends(ImageSectionHeaderArray, _super);
function ImageSectionHeaderArray(view, length) {
var _this = _super.call(this, view) || this;
_this.length = length;
return _this;
}
ImageSectionHeaderArray.from = function (bin, length, offset) {
if (offset === void 0) { offset = 0; }
var size = length * 40;
return new ImageSectionHeaderArray(new DataView(bin, offset, size), length);
};
ImageSectionHeaderArray.prototype.get = function (index) {
return {
name: getFixedString(this.view, index * 40, 8),
virtualSize: this.view.getUint32(8 + index * 40, true),
virtualAddress: this.view.getUint32(12 + index * 40, true),
sizeOfRawData: this.view.getUint32(16 + index * 40, true),
pointerToRawData: this.view.getUint32(20 + index * 40, true),
pointerToRelocations: this.view.getUint32(24 + index * 40, true),
pointerToLineNumbers: this.view.getUint32(28 + index * 40, true),
numberOfRelocations: this.view.getUint16(32 + index * 40, true),
numberOfLineNumbers: this.view.getUint16(34 + index * 40, true),
characteristics: this.view.getUint32(36 + index * 40, true),
};
};
ImageSectionHeaderArray.prototype.set = function (index, data) {
setFixedString(this.view, index * 40, 8, data.name);
this.view.setUint32(8 + index * 40, data.virtualSize, true);
this.view.setUint32(12 + index * 40, data.virtualAddress, true);
this.view.setUint32(16 + index * 40, data.sizeOfRawData, true);
this.view.setUint32(20 + index * 40, data.pointerToRawData, true);
this.view.setUint32(24 + index * 40, data.pointerToRelocations, true);
this.view.setUint32(28 + index * 40, data.pointerToLineNumbers, true);
this.view.setUint16(32 + index * 40, data.numberOfRelocations, true);
this.view.setUint16(34 + index * 40, data.numberOfLineNumbers, true);
this.view.setUint32(36 + index * 40, data.characteristics, true);
};
ImageSectionHeaderArray.itemSize = 40;
return ImageSectionHeaderArray;
}(ArrayFormatBase));
export default ImageSectionHeaderArray;

View File

@@ -0,0 +1,15 @@
import ArrayFormatBase from './ArrayFormatBase.js';
import FormatBase from './FormatBase.js';
import ImageDataDirectoryArray, { ImageDataDirectory } from './ImageDataDirectoryArray.js';
import ImageDirectoryEntry from './ImageDirectoryEntry.js';
import ImageDosHeader from './ImageDosHeader.js';
import ImageFileHeader from './ImageFileHeader.js';
import ImageNtHeaders from './ImageNtHeaders.js';
import ImageOptionalHeader from './ImageOptionalHeader.js';
import ImageOptionalHeader64 from './ImageOptionalHeader64.js';
import ImageSectionHeaderArray, { ImageSectionHeader } from './ImageSectionHeaderArray.js';
export { ArrayFormatBase, FormatBase, ImageDataDirectory, ImageDataDirectoryArray, ImageDirectoryEntry, ImageDosHeader, ImageFileHeader, ImageNtHeaders, ImageOptionalHeader, ImageOptionalHeader64, ImageSectionHeader, ImageSectionHeaderArray, };
export declare function getImageDosHeader(bin: ArrayBuffer): ImageDosHeader;
export declare function getImageNtHeadersByDosHeader(bin: ArrayBuffer, dosHeader: ImageDosHeader): ImageNtHeaders;
export declare function getImageSectionHeadersByNtHeaders(bin: ArrayBuffer, dosHeader: ImageDosHeader, ntHeaders: ImageNtHeaders): ImageSectionHeaderArray;
export declare function findImageSectionBlockByDirectoryEntry(bin: ArrayBuffer, dosHeader: ImageDosHeader, ntHeaders: ImageNtHeaders, entryType: ImageDirectoryEntry): ArrayBuffer | null;

View File

@@ -0,0 +1,40 @@
import ArrayFormatBase from './ArrayFormatBase.js';
import FormatBase from './FormatBase.js';
import ImageDataDirectoryArray from './ImageDataDirectoryArray.js';
import ImageDirectoryEntry from './ImageDirectoryEntry.js';
import ImageDosHeader from './ImageDosHeader.js';
import ImageFileHeader from './ImageFileHeader.js';
import ImageNtHeaders from './ImageNtHeaders.js';
import ImageOptionalHeader from './ImageOptionalHeader.js';
import ImageOptionalHeader64 from './ImageOptionalHeader64.js';
import ImageSectionHeaderArray from './ImageSectionHeaderArray.js';
export { ArrayFormatBase, FormatBase, ImageDataDirectoryArray, ImageDirectoryEntry, ImageDosHeader, ImageFileHeader, ImageNtHeaders, ImageOptionalHeader, ImageOptionalHeader64, ImageSectionHeaderArray, };
export function getImageDosHeader(bin) {
return ImageDosHeader.from(bin);
}
export function getImageNtHeadersByDosHeader(bin, dosHeader) {
return ImageNtHeaders.from(bin, dosHeader.newHeaderAddress);
}
export function getImageSectionHeadersByNtHeaders(bin, dosHeader, ntHeaders) {
return ImageSectionHeaderArray.from(bin, ntHeaders.fileHeader.numberOfSections, dosHeader.newHeaderAddress + ntHeaders.byteLength);
}
export function findImageSectionBlockByDirectoryEntry(bin, dosHeader, ntHeaders, entryType) {
var arr = ImageSectionHeaderArray.from(bin, ntHeaders.fileHeader.numberOfSections, dosHeader.newHeaderAddress + ntHeaders.byteLength);
var len = arr.length;
var rva = ntHeaders.optionalHeaderDataDirectory.get(entryType).virtualAddress;
for (var i = 0; i < len; ++i) {
var sec = arr.get(i);
var vaEnd = sec.virtualAddress + sec.virtualSize;
if (rva >= sec.virtualAddress && rva < vaEnd) {
var ptr = sec.pointerToRawData;
if (!ptr) {
return null;
}
return bin.slice(ptr, ptr + sec.sizeOfRawData);
}
if (rva < sec.virtualAddress) {
return null;
}
}
return null;
}

View File

@@ -0,0 +1,7 @@
import NtExecutable, { NtExecutableFromOptions, NtExecutableSection } from './NtExecutable.js';
import NtExecutableResource from './NtExecutableResource.js';
import { calculateCheckSumForPE } from './util/functions.js';
import version from './version.js';
import * as Format from './format/index.js';
import * as Type from './type/index.js';
export { NtExecutable, NtExecutableFromOptions, NtExecutableResource, NtExecutableSection, calculateCheckSumForPE, version, Format, Type, };

View File

@@ -0,0 +1,7 @@
import NtExecutable from './NtExecutable.js';
import NtExecutableResource from './NtExecutableResource.js';
import { calculateCheckSumForPE } from './util/functions.js';
import version from './version.js';
import * as Format from './format/index.js';
import * as Type from './type/index.js';
export { NtExecutable, NtExecutableResource, calculateCheckSumForPE, version, Format, Type, };

View File

@@ -0,0 +1,31 @@
export interface ResourceEntryBaseType<TType extends string | number, TID extends string | number, TLang extends string | number> {
/**
* The resource type name or numeric value.
* For well-known type (such as `RT_ICON`), this value must be the predefined numeric value.
*/
type: TType;
/** The ID of resource data. */
id: TID;
/**
* The language value of resource data.
* According to specification, this value can be string, but
* typically this value would be LANGID (numeric) value.
*/
lang: TLang;
/**
* The code page value for strings within the resource data.
* Typically this value would be the Unicode code page '1200'.
*/
codepage: number;
/** The actual resource data. If the data cannot be read, this field will be an empty binary. */
bin: ArrayBuffer;
/** RVA data for resource data. This field is available only when actual data (`bin` field) cannot be read. */
rva?: number;
/** (used by output) */
offset?: number;
}
export declare type ResourceEntryT<TType extends string | number> = ResourceEntryBaseType<TType, string | number, string | number>;
export declare type ResourceEntryTT<TType extends string | number, TID extends string | number> = ResourceEntryBaseType<TType, TID, string | number>;
/** Raw resource entry data */
declare type ResourceEntry = ResourceEntryBaseType<string | number, string | number, string | number>;
export default ResourceEntry;

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,2 @@
import ResourceEntry, { ResourceEntryBaseType, ResourceEntryT, ResourceEntryTT } from './ResourceEntry.js';
export { ResourceEntry, ResourceEntryBaseType, ResourceEntryT, ResourceEntryTT, };

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,13 @@
/// <reference lib="dom" />
export declare function cloneObject<T extends object>(object: Readonly<T>): T;
export declare function cloneObject<T extends object>(object: T): T;
export declare function createDataView(bin: ArrayBuffer | ArrayBufferView, byteOffset?: number, byteLength?: number): DataView;
export declare function calculateCheckSumForPE(bin: ArrayBuffer, storeToBinary?: boolean): number;
export declare function roundUp(val: number, align: number): number;
export declare function copyBuffer(dest: ArrayBuffer | ArrayBufferView, destOffset: number, src: ArrayBuffer | ArrayBufferView, srcOffset: number, length: number): void;
export declare function allocatePartialBinary(binBase: ArrayBuffer | ArrayBufferView, offset: number, length: number): ArrayBuffer;
export declare function cloneToArrayBuffer(binBase: ArrayBuffer | ArrayBufferView): ArrayBuffer;
export declare function getFixedString(view: DataView, offset: number, length: number): string;
export declare function setFixedString(view: DataView, offset: number, length: number, text: string): void;
export declare function binaryToString(bin: ArrayBuffer | ArrayBufferView): string;
export declare function stringToBinary(string: string): ArrayBuffer;

View File

@@ -0,0 +1,259 @@
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference lib='dom' />
import ImageDosHeader from '../format/ImageDosHeader.js';
export function cloneObject(object) {
var r = {};
Object.keys(object).forEach(function (key) {
r[key] = object[key];
});
return r;
}
/* eslint-enable @typescript-eslint/ban-types */
export function createDataView(bin, byteOffset, byteLength) {
if ('buffer' in bin) {
var newOffset = bin.byteOffset;
var newLength = bin.byteLength;
if (typeof byteOffset !== 'undefined') {
newOffset += byteOffset;
newLength -= byteOffset;
}
if (typeof byteLength !== 'undefined') {
newLength = byteLength;
}
return new DataView(bin.buffer, newOffset, newLength);
}
else {
return new DataView(bin, byteOffset, byteLength);
}
}
export function calculateCheckSumForPE(bin, storeToBinary) {
var dosHeader = ImageDosHeader.from(bin);
var view = new DataView(bin);
var checkSumOffset = dosHeader.newHeaderAddress + 88;
var result = 0;
var limit = 0x100000000; // 2^32
var update = function (dword) {
result += dword;
if (result >= limit) {
result = (result % limit) + ((result / limit) | 0);
}
};
var len = view.byteLength;
var lenExtra = len % 4;
var lenAlign = len - lenExtra;
for (var i = 0; i < lenAlign; i += 4) {
if (i !== checkSumOffset) {
update(view.getUint32(i, true));
}
}
if (lenExtra !== 0) {
var extra = 0;
for (var i = 0; i < lenExtra; i++) {
extra |= view.getUint8(lenAlign + i) << ((3 - i) * 8);
}
update(extra);
}
result = (result & 0xffff) + (result >>> 16);
result += result >>> 16;
result = (result & 0xffff) + len;
if (storeToBinary) {
view.setUint32(checkSumOffset, result, true);
}
return result;
}
export function roundUp(val, align) {
return Math.floor((val + align - 1) / align) * align;
}
export function copyBuffer(dest, destOffset, src, srcOffset, length) {
var ua8Dest = 'buffer' in dest
? new Uint8Array(dest.buffer, dest.byteOffset + (destOffset || 0), length)
: new Uint8Array(dest, destOffset, length);
var ua8Src = 'buffer' in src
? new Uint8Array(src.buffer, src.byteOffset + (srcOffset || 0), length)
: new Uint8Array(src, srcOffset, length);
ua8Dest.set(ua8Src);
}
export function allocatePartialBinary(binBase, offset, length) {
var b = new ArrayBuffer(length);
copyBuffer(b, 0, binBase, offset, length);
return b;
}
export function cloneToArrayBuffer(binBase) {
if ('buffer' in binBase) {
var b = new ArrayBuffer(binBase.byteLength);
new Uint8Array(b).set(new Uint8Array(binBase.buffer, binBase.byteOffset, binBase.byteLength));
return b;
}
else {
var b = new ArrayBuffer(binBase.byteLength);
new Uint8Array(b).set(new Uint8Array(binBase));
return b;
}
}
export function getFixedString(view, offset, length) {
var actualLen = 0;
for (var i = 0; i < length; ++i) {
if (view.getUint8(offset + i) === 0) {
break;
}
++actualLen;
}
if (typeof Buffer !== 'undefined') {
return Buffer.from(view.buffer, view.byteOffset + offset, actualLen).toString('utf8');
}
else if (typeof decodeURIComponent !== 'undefined') {
var s = '';
for (var i = 0; i < actualLen; ++i) {
var c = view.getUint8(offset + i);
if (c < 16) {
s += '%0' + c.toString(16);
}
else {
s += '%' + c.toString(16);
}
}
return decodeURIComponent(s);
}
else {
var s = '';
for (var i = 0; i < actualLen; ++i) {
var c = view.getUint8(offset + i);
s += String.fromCharCode(c);
}
return s;
}
}
export function setFixedString(view, offset, length, text) {
if (typeof Buffer !== 'undefined') {
var u = new Uint8Array(view.buffer, view.byteOffset + offset, length);
// fill by zero
u.set(new Uint8Array(length));
u.set(Buffer.from(text, 'utf8').subarray(0, length));
}
else if (typeof encodeURIComponent !== 'undefined') {
var s = encodeURIComponent(text);
for (var i = 0, j = 0; i < length; ++i) {
if (j >= s.length) {
view.setUint8(i + offset, 0);
}
else {
var c = s.charCodeAt(j);
if (c === 37) {
// '%'
var n = parseInt(s.substr(j + 1, 2), 16);
if (typeof n === 'number' && !isNaN(n)) {
view.setUint8(i + offset, n);
}
else {
view.setUint8(i + offset, 0);
}
j += 3;
}
else {
view.setUint8(i + offset, c);
}
}
}
}
else {
for (var i = 0, j = 0; i < length; ++i) {
if (j >= text.length) {
view.setUint8(i + offset, 0);
}
else {
var c = text.charCodeAt(j);
view.setUint8(i + offset, c & 0xff);
}
}
}
}
export function binaryToString(bin) {
if (typeof TextDecoder !== 'undefined') {
var dec = new TextDecoder();
return dec.decode(bin);
}
else if (typeof Buffer !== 'undefined') {
var b = void 0;
if ('buffer' in bin) {
b = Buffer.from(bin.buffer, bin.byteOffset, bin.byteLength);
}
else {
b = Buffer.from(bin);
}
return b.toString('utf8');
}
else {
var view = void 0;
if ('buffer' in bin) {
view = new Uint8Array(bin.buffer, bin.byteOffset, bin.byteLength);
}
else {
view = new Uint8Array(bin);
}
if (typeof decodeURIComponent !== 'undefined') {
var s = '';
for (var i = 0; i < view.length; ++i) {
var c = view[i];
if (c < 16) {
s += '%0' + c.toString(16);
}
else {
s += '%' + c.toString(16);
}
}
return decodeURIComponent(s);
}
else {
var s = '';
for (var i = 0; i < view.length; ++i) {
var c = view[i];
s += String.fromCharCode(c);
}
return s;
}
}
}
export function stringToBinary(string) {
if (typeof TextEncoder !== 'undefined') {
var enc = new TextEncoder();
return cloneToArrayBuffer(enc.encode(string));
}
else if (typeof Buffer !== 'undefined') {
return cloneToArrayBuffer(Buffer.from(string, 'utf8'));
}
else if (typeof encodeURIComponent !== 'undefined') {
var data = encodeURIComponent(string);
var len = 0;
for (var i = 0; i < data.length; ++len) {
var c = data.charCodeAt(i);
if (c === 37) {
i += 3;
}
else {
++i;
}
}
var bin = new ArrayBuffer(len);
var view = new Uint8Array(bin);
for (var i = 0, j = 0; i < data.length; ++j) {
var c = data.charCodeAt(i);
if (c === 37) {
var n = parseInt(data.substring(i + 1, i + 3), 16);
view[j] = n;
i += 3;
}
else {
view[j] = c;
++i;
}
}
return bin;
}
else {
var bin = new ArrayBuffer(string.length);
new Uint8Array(bin).set([].map.call(string, function (c) {
return c.charCodeAt(0);
}));
return bin;
}
}

View File

@@ -0,0 +1,5 @@
export declare function getDosStubDataSize(): number;
export declare function fillDosStubData(bin: ArrayBuffer | ArrayBufferView): void;
export declare function estimateNewHeaderSize(is32Bit: boolean): number;
export declare function fillPeHeaderEmptyData(bin: ArrayBuffer | ArrayBufferView, offset: number, totalBinSize: number, is32Bit: boolean, isDLL: boolean): void;
export declare function makeEmptyNtExecutableBinary(is32Bit: boolean, isDLL: boolean): ArrayBuffer;

View File

@@ -0,0 +1,119 @@
// To make the binary (DOS_STUB_PROGRAM):
// $ cd tools/dos-stub
// $ nasm -f bin -o dos-stub.bin dos-stub.asm
// $ node -e "console.log([].map.call(fs.readFileSync('tools/dos-stub/dos-stub.bin'), (v)=>`0x${Buffer.from([v]).toString('hex')}`).join(','))"
//
// NOTE: the original dos-stub.asm program and the bit code in DOS_STUB_PROGRAM are under the 0-BSD license.
import ImageDataDirectoryArray from '../format/ImageDataDirectoryArray.js';
import ImageDosHeader from '../format/ImageDosHeader.js';
import ImageFileHeader from '../format/ImageFileHeader.js';
import ImageNtHeaders from '../format/ImageNtHeaders.js';
import ImageOptionalHeader from '../format/ImageOptionalHeader.js';
import ImageOptionalHeader64 from '../format/ImageOptionalHeader64.js';
import { copyBuffer, roundUp } from './functions.js';
// fill with '0x00' to make 8-bytes alignment
// prettier-ignore
var DOS_STUB_PROGRAM = new Uint8Array([
0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x44, 0x4f,
0x53, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f,
0x72, 0x74, 0x65, 0x64, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]);
var DOS_STUB_SIZE = roundUp(ImageDosHeader.size + DOS_STUB_PROGRAM.length, 0x80);
var DEFAULT_FILE_ALIGNMENT = 512;
export function getDosStubDataSize() {
return DOS_STUB_SIZE;
}
export function fillDosStubData(bin) {
var dos = ImageDosHeader.from(bin);
dos.magic = ImageDosHeader.DEFAULT_MAGIC;
// last page size
dos.lastPageSize = DOS_STUB_SIZE % 512;
// total page count
dos.pages = Math.ceil(DOS_STUB_SIZE / 512);
// no relocations
dos.relocations = 0;
// header size as paragraph count (1 paragraph = 16 bytes)
dos.headerSizeInParagraph = Math.ceil(ImageDosHeader.size / 16);
dos.minAllocParagraphs = 0;
dos.maxAllocParagraphs = 0xffff;
dos.initialSS = 0;
dos.initialSP = 0x80;
// (no relocations, but set offset after the header)
dos.relocationTableAddress = ImageDosHeader.size;
dos.newHeaderAddress = DOS_STUB_SIZE;
copyBuffer(bin, ImageDosHeader.size, DOS_STUB_PROGRAM, 0, DOS_STUB_PROGRAM.length);
}
export function estimateNewHeaderSize(is32Bit) {
return (
// magic
4 +
ImageFileHeader.size +
(is32Bit ? ImageOptionalHeader.size : ImageOptionalHeader64.size) +
ImageDataDirectoryArray.size);
}
export function fillPeHeaderEmptyData(bin, offset, totalBinSize, is32Bit, isDLL) {
var _bin;
var _offset;
if ('buffer' in bin) {
_bin = bin.buffer;
_offset = bin.byteOffset + offset;
}
else {
_bin = bin;
_offset = offset;
}
new DataView(_bin, _offset).setUint32(0, ImageNtHeaders.DEFAULT_SIGNATURE, true);
var fh = ImageFileHeader.from(_bin, _offset + 4);
fh.machine = is32Bit ? 0x14c : 0x8664;
fh.numberOfSections = 0; // no sections
fh.timeDateStamp = 0;
fh.pointerToSymbolTable = 0;
fh.numberOfSymbols = 0;
fh.sizeOfOptionalHeader =
(is32Bit ? ImageOptionalHeader.size : ImageOptionalHeader64.size) +
ImageDataDirectoryArray.size;
fh.characteristics = isDLL ? 0x2102 : 0x102;
var oh = (is32Bit ? ImageOptionalHeader : ImageOptionalHeader64).from(_bin, _offset + 4 + ImageFileHeader.size);
oh.magic = is32Bit
? ImageOptionalHeader.DEFAULT_MAGIC
: ImageOptionalHeader64.DEFAULT_MAGIC;
// oh.majorLinkerVersion = 0;
// oh.minorLinkerVersion = 0;
oh.sizeOfCode = 0;
oh.sizeOfInitializedData = 0;
oh.sizeOfUninitializedData = 0;
oh.addressOfEntryPoint = 0;
oh.baseOfCode = 0x1000;
// oh.baseOfData = 0; // for 32bit only
oh.imageBase = is32Bit ? 0x1000000 : 0x180000000;
oh.sectionAlignment = 4096;
oh.fileAlignment = DEFAULT_FILE_ALIGNMENT;
oh.majorOperatingSystemVersion = 6;
oh.minorOperatingSystemVersion = 0;
// oh.majorImageVersion = 0;
// oh.minorImageVersion = 0;
oh.majorSubsystemVersion = 6;
oh.minorSubsystemVersion = 0;
// oh.win32VersionValue = 0;
oh.sizeOfHeaders = roundUp(totalBinSize, oh.fileAlignment);
// oh.checkSum = 0;
oh.subsystem = 2; // IMAGE_SUBSYSTEM_WINDOWS_GUI
oh.dllCharacteristics =
(is32Bit ? 0 : 0x20) + // IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
0x40 + // IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
0x100; // IMAGE_DLLCHARACTERISTICS_NX_COMPAT
oh.sizeOfStackReserve = 0x100000;
oh.sizeOfStackCommit = 0x1000;
oh.sizeOfHeapReserve = 0x100000;
oh.sizeOfHeapCommit = 0x1000;
// oh.loaderFlags = 0;
oh.numberOfRvaAndSizes =
ImageDataDirectoryArray.size / ImageDataDirectoryArray.itemSize;
}
export function makeEmptyNtExecutableBinary(is32Bit, isDLL) {
var bufferSize = roundUp(DOS_STUB_SIZE + estimateNewHeaderSize(is32Bit), DEFAULT_FILE_ALIGNMENT);
var bin = new ArrayBuffer(bufferSize);
fillDosStubData(bin);
fillPeHeaderEmptyData(bin, DOS_STUB_SIZE, bufferSize, is32Bit, isDLL);
return bin;
}

View File

@@ -0,0 +1,2 @@
declare const _default: "0.4.1";
export default _default;

View File

@@ -0,0 +1 @@
export default '0.4.1';

View File

@@ -0,0 +1,14 @@
import FormatBase from './FormatBase.js';
/** abstract class that support array-like methods and 'for...of' operation */
declare abstract class ArrayFormatBase<T> extends FormatBase {
protected constructor(view: DataView);
abstract readonly length: number;
abstract get(index: number): Readonly<T>;
abstract set(index: number, data: T): void;
forEach(callback: (value: T, index: number, base: this) => void): void;
_iterator(): Iterator<Readonly<T>>;
}
interface ArrayFormatBase<T> {
[Symbol.iterator]: () => Iterator<Readonly<T>>;
}
export default ArrayFormatBase;

View File

@@ -0,0 +1,66 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var FormatBase_js_1 = require("./FormatBase.js");
/** abstract class that support array-like methods and 'for...of' operation */
var ArrayFormatBase = /** @class */ (function (_super) {
__extends(ArrayFormatBase, _super);
function ArrayFormatBase(view) {
return _super.call(this, view) || this;
}
ArrayFormatBase.prototype.forEach = function (callback) {
var len = this.length;
var a = [];
a.length = len;
for (var i = 0; i < len; ++i) {
a[i] = this.get(i);
}
for (var i = 0; i < len; ++i) {
callback(a[i], i, this);
}
};
ArrayFormatBase.prototype._iterator = function () {
return new (/** @class */ (function () {
function class_1(base) {
this.base = base;
this.i = 0;
}
class_1.prototype.next = function () {
if (this.i === this.base.length) {
return {
value: undefined,
done: true,
};
}
else {
return {
value: this.base.get(this.i++),
done: false,
};
}
};
return class_1;
}()))(this);
};
return ArrayFormatBase;
}(FormatBase_js_1.default));
/* istanbul ignore else */
if (typeof Symbol !== 'undefined') {
ArrayFormatBase.prototype[Symbol.iterator] =
ArrayFormatBase.prototype._iterator;
}
exports.default = ArrayFormatBase;

View File

@@ -0,0 +1,6 @@
export default abstract class FormatBase {
protected readonly view: DataView;
protected constructor(view: DataView);
copyTo(bin: ArrayBuffer, offset: number): void;
get byteLength(): number;
}

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var FormatBase = /** @class */ (function () {
function FormatBase(view) {
this.view = view;
}
FormatBase.prototype.copyTo = function (bin, offset) {
new Uint8Array(bin, offset, this.view.byteLength).set(new Uint8Array(this.view.buffer, this.view.byteOffset, this.view.byteLength));
};
Object.defineProperty(FormatBase.prototype, "byteLength", {
get: function () {
return this.view.byteLength;
},
enumerable: false,
configurable: true
});
return FormatBase;
}());
exports.default = FormatBase;

View File

@@ -0,0 +1,16 @@
import ArrayFormatBase from './ArrayFormatBase.js';
export interface ImageDataDirectory {
virtualAddress: number;
size: number;
}
export default class ImageDataDirectoryArray extends ArrayFormatBase<ImageDataDirectory> {
static readonly size = 128;
static readonly itemSize = 8;
readonly length = 16;
private constructor();
/** @note This does not clone binary data; the changes to the array will modify the specified buffer `bin` */
static from(bin: ArrayBuffer, offset?: number): ImageDataDirectoryArray;
get(index: number): Readonly<ImageDataDirectory>;
set(index: number, data: ImageDataDirectory): void;
findIndexByVirtualAddress(virtualAddress: number): number | null;
}

View File

@@ -0,0 +1,55 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var ArrayFormatBase_js_1 = require("./ArrayFormatBase.js");
var ImageDataDirectoryArray = /** @class */ (function (_super) {
__extends(ImageDataDirectoryArray, _super);
function ImageDataDirectoryArray(view) {
var _this = _super.call(this, view) || this;
_this.length = 16;
return _this;
}
/** @note This does not clone binary data; the changes to the array will modify the specified buffer `bin` */
ImageDataDirectoryArray.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
return new ImageDataDirectoryArray(new DataView(bin, offset, 128));
};
ImageDataDirectoryArray.prototype.get = function (index) {
return {
virtualAddress: this.view.getUint32(index * 8, true),
size: this.view.getUint32(4 + index * 8, true),
};
};
ImageDataDirectoryArray.prototype.set = function (index, data) {
this.view.setUint32(index * 8, data.virtualAddress, true);
this.view.setUint32(4 + index * 8, data.size, true);
};
ImageDataDirectoryArray.prototype.findIndexByVirtualAddress = function (virtualAddress) {
for (var i = 0; i < 16; ++i) {
var va = this.view.getUint32(i * 8, true);
var vs = this.view.getUint32(4 + i * 8, true);
if (virtualAddress >= va && virtualAddress < va + vs) {
return i;
}
}
return null;
};
ImageDataDirectoryArray.size = 128; // 16 * 8
ImageDataDirectoryArray.itemSize = 8;
return ImageDataDirectoryArray;
}(ArrayFormatBase_js_1.default));
exports.default = ImageDataDirectoryArray;

View File

@@ -0,0 +1,22 @@
declare enum ImageDirectoryEntry {
Export = 0,
Import = 1,
Resource = 2,
Exception = 3,
Certificate = 4,
Security = 4,
BaseRelocation = 5,
Debug = 6,
Architecture = 7,
GlobalPointer = 8,
Tls = 9,
TLS = 9,
LoadConfig = 10,
BoundImport = 11,
Iat = 12,
IAT = 12,
DelayImport = 13,
ComDescriptor = 14,
COMDescriptor = 14
}
export default ImageDirectoryEntry;

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ImageDirectoryEntry;
(function (ImageDirectoryEntry) {
ImageDirectoryEntry[ImageDirectoryEntry["Export"] = 0] = "Export";
ImageDirectoryEntry[ImageDirectoryEntry["Import"] = 1] = "Import";
ImageDirectoryEntry[ImageDirectoryEntry["Resource"] = 2] = "Resource";
ImageDirectoryEntry[ImageDirectoryEntry["Exception"] = 3] = "Exception";
ImageDirectoryEntry[ImageDirectoryEntry["Certificate"] = 4] = "Certificate";
// alias
ImageDirectoryEntry[ImageDirectoryEntry["Security"] = 4] = "Security";
ImageDirectoryEntry[ImageDirectoryEntry["BaseRelocation"] = 5] = "BaseRelocation";
ImageDirectoryEntry[ImageDirectoryEntry["Debug"] = 6] = "Debug";
ImageDirectoryEntry[ImageDirectoryEntry["Architecture"] = 7] = "Architecture";
ImageDirectoryEntry[ImageDirectoryEntry["GlobalPointer"] = 8] = "GlobalPointer";
ImageDirectoryEntry[ImageDirectoryEntry["Tls"] = 9] = "Tls";
ImageDirectoryEntry[ImageDirectoryEntry["TLS"] = 9] = "TLS";
ImageDirectoryEntry[ImageDirectoryEntry["LoadConfig"] = 10] = "LoadConfig";
ImageDirectoryEntry[ImageDirectoryEntry["BoundImport"] = 11] = "BoundImport";
ImageDirectoryEntry[ImageDirectoryEntry["Iat"] = 12] = "Iat";
ImageDirectoryEntry[ImageDirectoryEntry["IAT"] = 12] = "IAT";
ImageDirectoryEntry[ImageDirectoryEntry["DelayImport"] = 13] = "DelayImport";
ImageDirectoryEntry[ImageDirectoryEntry["ComDescriptor"] = 14] = "ComDescriptor";
ImageDirectoryEntry[ImageDirectoryEntry["COMDescriptor"] = 14] = "COMDescriptor";
})(ImageDirectoryEntry || (ImageDirectoryEntry = {}));
exports.default = ImageDirectoryEntry;

View File

@@ -0,0 +1,42 @@
import FormatBase from './FormatBase.js';
export default class ImageDosHeader extends FormatBase {
static readonly size = 64;
static readonly DEFAULT_MAGIC = 23117;
private constructor();
static from(bin: ArrayBuffer | ArrayBufferView, offset?: number): ImageDosHeader;
isValid(): boolean;
get magic(): number;
set magic(val: number);
get lastPageSize(): number;
set lastPageSize(val: number);
get pages(): number;
set pages(val: number);
get relocations(): number;
set relocations(val: number);
get headerSizeInParagraph(): number;
set headerSizeInParagraph(val: number);
get minAllocParagraphs(): number;
set minAllocParagraphs(val: number);
get maxAllocParagraphs(): number;
set maxAllocParagraphs(val: number);
get initialSS(): number;
set initialSS(val: number);
get initialSP(): number;
set initialSP(val: number);
get checkSum(): number;
set checkSum(val: number);
get initialIP(): number;
set initialIP(val: number);
get initialCS(): number;
set initialCS(val: number);
get relocationTableAddress(): number;
set relocationTableAddress(val: number);
get overlayNum(): number;
set overlayNum(val: number);
get oemId(): number;
set oemId(val: number);
get oemInfo(): number;
set oemInfo(val: number);
get newHeaderAddress(): number;
set newHeaderAddress(val: number);
}

View File

@@ -0,0 +1,208 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var FormatBase_js_1 = require("./FormatBase.js");
var functions_js_1 = require("../util/functions.js");
var ImageDosHeader = /** @class */ (function (_super) {
__extends(ImageDosHeader, _super);
function ImageDosHeader(view) {
return _super.call(this, view) || this;
}
ImageDosHeader.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
return new ImageDosHeader(functions_js_1.createDataView(bin, offset, 64));
};
ImageDosHeader.prototype.isValid = function () {
return this.magic === ImageDosHeader.DEFAULT_MAGIC;
};
Object.defineProperty(ImageDosHeader.prototype, "magic", {
get: function () {
return this.view.getUint16(0, true);
},
set: function (val) {
this.view.setUint16(0, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "lastPageSize", {
get: function () {
return this.view.getUint16(2, true);
},
set: function (val) {
this.view.setUint16(2, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "pages", {
get: function () {
return this.view.getUint16(4, true);
},
set: function (val) {
this.view.setUint16(4, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "relocations", {
get: function () {
return this.view.getUint16(6, true);
},
set: function (val) {
this.view.setUint16(6, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "headerSizeInParagraph", {
get: function () {
return this.view.getUint16(8, true);
},
set: function (val) {
this.view.setUint16(8, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "minAllocParagraphs", {
get: function () {
return this.view.getUint16(10, true);
},
set: function (val) {
this.view.setUint16(10, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "maxAllocParagraphs", {
get: function () {
return this.view.getUint16(12, true);
},
set: function (val) {
this.view.setUint16(12, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "initialSS", {
get: function () {
return this.view.getUint16(14, true);
},
set: function (val) {
this.view.setUint16(14, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "initialSP", {
get: function () {
return this.view.getUint16(16, true);
},
set: function (val) {
this.view.setUint16(16, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "checkSum", {
get: function () {
return this.view.getUint16(18, true);
},
set: function (val) {
this.view.setUint16(18, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "initialIP", {
get: function () {
return this.view.getUint16(20, true);
},
set: function (val) {
this.view.setUint16(20, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "initialCS", {
get: function () {
return this.view.getUint16(22, true);
},
set: function (val) {
this.view.setUint16(22, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "relocationTableAddress", {
get: function () {
return this.view.getUint16(24, true);
},
set: function (val) {
this.view.setUint16(24, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "overlayNum", {
get: function () {
return this.view.getUint16(26, true);
},
set: function (val) {
this.view.setUint16(26, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "oemId", {
// WORD e_res[4] (28,30,32,34)
get: function () {
return this.view.getUint16(36, true);
},
set: function (val) {
this.view.setUint16(36, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "oemInfo", {
get: function () {
return this.view.getUint16(38, true);
},
set: function (val) {
this.view.setUint16(38, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageDosHeader.prototype, "newHeaderAddress", {
// WORD e_res2[10] (40,42,44,46,48,50,52,54,56,58)
get: function () {
return this.view.getUint32(60, true);
},
set: function (val) {
this.view.setUint32(60, val, true);
},
enumerable: false,
configurable: true
});
ImageDosHeader.size = 64;
ImageDosHeader.DEFAULT_MAGIC = 0x5a4d; // 'MZ'
return ImageDosHeader;
}(FormatBase_js_1.default));
exports.default = ImageDosHeader;

View File

@@ -0,0 +1,20 @@
import FormatBase from './FormatBase.js';
export default class ImageFileHeader extends FormatBase {
static readonly size = 20;
private constructor();
static from(bin: ArrayBuffer, offset?: number): ImageFileHeader;
get machine(): number;
set machine(val: number);
get numberOfSections(): number;
set numberOfSections(val: number);
get timeDateStamp(): number;
set timeDateStamp(val: number);
get pointerToSymbolTable(): number;
set pointerToSymbolTable(val: number);
get numberOfSymbols(): number;
set numberOfSymbols(val: number);
get sizeOfOptionalHeader(): number;
set sizeOfOptionalHeader(val: number);
get characteristics(): number;
set characteristics(val: number);
}

View File

@@ -0,0 +1,101 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var FormatBase_js_1 = require("./FormatBase.js");
var ImageFileHeader = /** @class */ (function (_super) {
__extends(ImageFileHeader, _super);
function ImageFileHeader(view) {
return _super.call(this, view) || this;
}
ImageFileHeader.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
return new ImageFileHeader(new DataView(bin, offset, 20));
};
Object.defineProperty(ImageFileHeader.prototype, "machine", {
get: function () {
return this.view.getUint16(0, true);
},
set: function (val) {
this.view.setUint16(0, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "numberOfSections", {
get: function () {
return this.view.getUint16(2, true);
},
set: function (val) {
this.view.setUint16(2, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "timeDateStamp", {
get: function () {
return this.view.getUint32(4, true);
},
set: function (val) {
this.view.setUint32(4, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "pointerToSymbolTable", {
get: function () {
return this.view.getUint32(8, true);
},
set: function (val) {
this.view.setUint32(8, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "numberOfSymbols", {
get: function () {
return this.view.getUint32(12, true);
},
set: function (val) {
this.view.setUint32(12, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "sizeOfOptionalHeader", {
get: function () {
return this.view.getUint16(16, true);
},
set: function (val) {
this.view.setUint16(16, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageFileHeader.prototype, "characteristics", {
get: function () {
return this.view.getUint16(18, true);
},
set: function (val) {
this.view.setUint16(18, val, true);
},
enumerable: false,
configurable: true
});
ImageFileHeader.size = 20;
return ImageFileHeader;
}(FormatBase_js_1.default));
exports.default = ImageFileHeader;

View File

@@ -0,0 +1,19 @@
import FormatBase from './FormatBase.js';
import ImageFileHeader from './ImageFileHeader.js';
import ImageOptionalHeader from './ImageOptionalHeader.js';
import ImageOptionalHeader64 from './ImageOptionalHeader64.js';
import ImageDataDirectoryArray from './ImageDataDirectoryArray.js';
export default class ImageNtHeaders extends FormatBase {
static readonly DEFAULT_SIGNATURE = 17744;
private constructor();
static from(bin: ArrayBuffer | ArrayBufferView, offset?: number): ImageNtHeaders;
isValid(): boolean;
is32bit(): boolean;
get signature(): number;
set signature(val: number);
get fileHeader(): ImageFileHeader;
get optionalHeader(): ImageOptionalHeader | ImageOptionalHeader64;
get optionalHeaderDataDirectory(): ImageDataDirectoryArray;
getDataDirectoryOffset(): number;
getSectionHeaderOffset(): number;
}

View File

@@ -0,0 +1,103 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var FormatBase_js_1 = require("./FormatBase.js");
var ImageFileHeader_js_1 = require("./ImageFileHeader.js");
var ImageOptionalHeader_js_1 = require("./ImageOptionalHeader.js");
var ImageOptionalHeader64_js_1 = require("./ImageOptionalHeader64.js");
var ImageDataDirectoryArray_js_1 = require("./ImageDataDirectoryArray.js");
var functions_js_1 = require("../util/functions.js");
var ImageNtHeaders = /** @class */ (function (_super) {
__extends(ImageNtHeaders, _super);
function ImageNtHeaders(view) {
return _super.call(this, view) || this;
}
ImageNtHeaders.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
var magic = functions_js_1.createDataView(bin, offset + ImageFileHeader_js_1.default.size, 6).getUint16(4, true);
var len = 4 + ImageFileHeader_js_1.default.size + ImageDataDirectoryArray_js_1.default.size;
if (magic === ImageOptionalHeader64_js_1.default.DEFAULT_MAGIC) {
len += ImageOptionalHeader64_js_1.default.size;
}
else {
len += ImageOptionalHeader_js_1.default.size;
}
return new ImageNtHeaders(functions_js_1.createDataView(bin, offset, len));
};
ImageNtHeaders.prototype.isValid = function () {
return this.signature === ImageNtHeaders.DEFAULT_SIGNATURE;
};
ImageNtHeaders.prototype.is32bit = function () {
return (this.view.getUint16(ImageFileHeader_js_1.default.size + 4, true) ===
ImageOptionalHeader_js_1.default.DEFAULT_MAGIC);
};
Object.defineProperty(ImageNtHeaders.prototype, "signature", {
get: function () {
return this.view.getUint32(0, true);
},
set: function (val) {
this.view.setUint32(0, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageNtHeaders.prototype, "fileHeader", {
get: function () {
return ImageFileHeader_js_1.default.from(this.view.buffer, this.view.byteOffset + 4);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageNtHeaders.prototype, "optionalHeader", {
get: function () {
var off = ImageFileHeader_js_1.default.size + 4;
var magic = this.view.getUint16(off, true);
if (magic === ImageOptionalHeader64_js_1.default.DEFAULT_MAGIC) {
return ImageOptionalHeader64_js_1.default.from(this.view.buffer, this.view.byteOffset + off);
}
else {
return ImageOptionalHeader_js_1.default.from(this.view.buffer, this.view.byteOffset + off);
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageNtHeaders.prototype, "optionalHeaderDataDirectory", {
get: function () {
return ImageDataDirectoryArray_js_1.default.from(this.view.buffer, this.view.byteOffset + this.getDataDirectoryOffset());
},
enumerable: false,
configurable: true
});
ImageNtHeaders.prototype.getDataDirectoryOffset = function () {
var off = ImageFileHeader_js_1.default.size + 4;
var magic = this.view.getUint16(off, true);
if (magic === ImageOptionalHeader64_js_1.default.DEFAULT_MAGIC) {
off += ImageOptionalHeader64_js_1.default.size;
}
else {
off += ImageOptionalHeader_js_1.default.size;
}
return off;
};
ImageNtHeaders.prototype.getSectionHeaderOffset = function () {
return this.getDataDirectoryOffset() + ImageDataDirectoryArray_js_1.default.size;
};
ImageNtHeaders.DEFAULT_SIGNATURE = 0x4550; // 'PE\x00\x00'
return ImageNtHeaders;
}(FormatBase_js_1.default));
exports.default = ImageNtHeaders;

View File

@@ -0,0 +1,67 @@
import FormatBase from './FormatBase.js';
export default class ImageOptionalHeader extends FormatBase {
static readonly size = 96;
static readonly DEFAULT_MAGIC = 267;
private constructor();
static from(bin: ArrayBuffer, offset?: number): ImageOptionalHeader;
get magic(): number;
set magic(val: number);
get majorLinkerVersion(): number;
set majorLinkerVersion(val: number);
get minorLinkerVersion(): number;
set minorLinkerVersion(val: number);
get sizeOfCode(): number;
set sizeOfCode(val: number);
get sizeOfInitializedData(): number;
set sizeOfInitializedData(val: number);
get sizeOfUninitializedData(): number;
set sizeOfUninitializedData(val: number);
get addressOfEntryPoint(): number;
set addressOfEntryPoint(val: number);
get baseOfCode(): number;
set baseOfCode(val: number);
get baseOfData(): number;
set baseOfData(val: number);
get imageBase(): number;
set imageBase(val: number);
get sectionAlignment(): number;
set sectionAlignment(val: number);
get fileAlignment(): number;
set fileAlignment(val: number);
get majorOperatingSystemVersion(): number;
set majorOperatingSystemVersion(val: number);
get minorOperatingSystemVersion(): number;
set minorOperatingSystemVersion(val: number);
get majorImageVersion(): number;
set majorImageVersion(val: number);
get minorImageVersion(): number;
set minorImageVersion(val: number);
get majorSubsystemVersion(): number;
set majorSubsystemVersion(val: number);
get minorSubsystemVersion(): number;
set minorSubsystemVersion(val: number);
get win32VersionValue(): number;
set win32VersionValue(val: number);
get sizeOfImage(): number;
set sizeOfImage(val: number);
get sizeOfHeaders(): number;
set sizeOfHeaders(val: number);
get checkSum(): number;
set checkSum(val: number);
get subsystem(): number;
set subsystem(val: number);
get dllCharacteristics(): number;
set dllCharacteristics(val: number);
get sizeOfStackReserve(): number;
set sizeOfStackReserve(val: number);
get sizeOfStackCommit(): number;
set sizeOfStackCommit(val: number);
get sizeOfHeapReserve(): number;
set sizeOfHeapReserve(val: number);
get sizeOfHeapCommit(): number;
set sizeOfHeapCommit(val: number);
get loaderFlags(): number;
set loaderFlags(val: number);
get numberOfRvaAndSizes(): number;
set numberOfRvaAndSizes(val: number);
}

View File

@@ -0,0 +1,332 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var FormatBase_js_1 = require("./FormatBase.js");
var ImageOptionalHeader = /** @class */ (function (_super) {
__extends(ImageOptionalHeader, _super);
function ImageOptionalHeader(view) {
return _super.call(this, view) || this;
}
ImageOptionalHeader.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
return new ImageOptionalHeader(new DataView(bin, offset, 96));
};
Object.defineProperty(ImageOptionalHeader.prototype, "magic", {
get: function () {
return this.view.getUint16(0, true);
},
set: function (val) {
this.view.setUint16(0, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "majorLinkerVersion", {
get: function () {
return this.view.getUint8(2);
},
set: function (val) {
this.view.setUint8(2, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "minorLinkerVersion", {
get: function () {
return this.view.getUint8(3);
},
set: function (val) {
this.view.setUint8(3, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfCode", {
get: function () {
return this.view.getUint32(4, true);
},
set: function (val) {
this.view.setUint32(4, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfInitializedData", {
get: function () {
return this.view.getUint32(8, true);
},
set: function (val) {
this.view.setUint32(8, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfUninitializedData", {
get: function () {
return this.view.getUint32(12, true);
},
set: function (val) {
this.view.setUint32(12, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "addressOfEntryPoint", {
get: function () {
return this.view.getUint32(16, true);
},
set: function (val) {
this.view.setUint32(16, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "baseOfCode", {
get: function () {
return this.view.getUint32(20, true);
},
set: function (val) {
this.view.setUint32(20, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "baseOfData", {
get: function () {
return this.view.getUint32(24, true);
},
set: function (val) {
this.view.setUint32(24, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "imageBase", {
get: function () {
return this.view.getUint32(28, true);
},
set: function (val) {
this.view.setUint32(28, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sectionAlignment", {
get: function () {
return this.view.getUint32(32, true);
},
set: function (val) {
this.view.setUint32(32, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "fileAlignment", {
get: function () {
return this.view.getUint32(36, true);
},
set: function (val) {
this.view.setUint32(36, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "majorOperatingSystemVersion", {
get: function () {
return this.view.getUint16(40, true);
},
set: function (val) {
this.view.setUint16(40, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "minorOperatingSystemVersion", {
get: function () {
return this.view.getUint16(42, true);
},
set: function (val) {
this.view.setUint16(42, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "majorImageVersion", {
get: function () {
return this.view.getUint16(44, true);
},
set: function (val) {
this.view.setUint16(44, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "minorImageVersion", {
get: function () {
return this.view.getUint16(46, true);
},
set: function (val) {
this.view.setUint16(46, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "majorSubsystemVersion", {
get: function () {
return this.view.getUint16(48, true);
},
set: function (val) {
this.view.setUint16(48, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "minorSubsystemVersion", {
get: function () {
return this.view.getUint16(50, true);
},
set: function (val) {
this.view.setUint16(50, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "win32VersionValue", {
get: function () {
return this.view.getUint32(52, true);
},
set: function (val) {
this.view.setUint32(52, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfImage", {
get: function () {
return this.view.getUint32(56, true);
},
set: function (val) {
this.view.setUint32(56, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfHeaders", {
get: function () {
return this.view.getUint32(60, true);
},
set: function (val) {
this.view.setUint32(60, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "checkSum", {
get: function () {
return this.view.getUint32(64, true);
},
set: function (val) {
this.view.setUint32(64, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "subsystem", {
get: function () {
return this.view.getUint16(68, true);
},
set: function (val) {
this.view.setUint16(68, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "dllCharacteristics", {
get: function () {
return this.view.getUint16(70, true);
},
set: function (val) {
this.view.setUint16(70, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfStackReserve", {
get: function () {
return this.view.getUint32(72, true);
},
set: function (val) {
this.view.setUint32(72, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfStackCommit", {
get: function () {
return this.view.getUint32(76, true);
},
set: function (val) {
this.view.setUint32(76, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfHeapReserve", {
get: function () {
return this.view.getUint32(80, true);
},
set: function (val) {
this.view.setUint32(80, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "sizeOfHeapCommit", {
get: function () {
return this.view.getUint32(84, true);
},
set: function (val) {
this.view.setUint32(84, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "loaderFlags", {
get: function () {
return this.view.getUint32(88, true);
},
set: function (val) {
this.view.setUint32(88, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader.prototype, "numberOfRvaAndSizes", {
get: function () {
return this.view.getUint32(92, true);
},
set: function (val) {
this.view.setUint32(92, val, true);
},
enumerable: false,
configurable: true
});
ImageOptionalHeader.size = 96;
ImageOptionalHeader.DEFAULT_MAGIC = 0x10b;
return ImageOptionalHeader;
}(FormatBase_js_1.default));
exports.default = ImageOptionalHeader;

View File

@@ -0,0 +1,75 @@
import FormatBase from './FormatBase.js';
export default class ImageOptionalHeader64 extends FormatBase {
static readonly size = 112;
static readonly DEFAULT_MAGIC = 523;
private constructor();
static from(bin: ArrayBuffer, offset?: number): ImageOptionalHeader64;
get magic(): number;
set magic(val: number);
get majorLinkerVersion(): number;
set majorLinkerVersion(val: number);
get minorLinkerVersion(): number;
set minorLinkerVersion(val: number);
get sizeOfCode(): number;
set sizeOfCode(val: number);
get sizeOfInitializedData(): number;
set sizeOfInitializedData(val: number);
get sizeOfUninitializedData(): number;
set sizeOfUninitializedData(val: number);
get addressOfEntryPoint(): number;
set addressOfEntryPoint(val: number);
get baseOfCode(): number;
set baseOfCode(val: number);
get imageBase(): number;
set imageBase(val: number);
get imageBaseBigInt(): bigint;
set imageBaseBigInt(val: bigint);
get sectionAlignment(): number;
set sectionAlignment(val: number);
get fileAlignment(): number;
set fileAlignment(val: number);
get majorOperatingSystemVersion(): number;
set majorOperatingSystemVersion(val: number);
get minorOperatingSystemVersion(): number;
set minorOperatingSystemVersion(val: number);
get majorImageVersion(): number;
set majorImageVersion(val: number);
get minorImageVersion(): number;
set minorImageVersion(val: number);
get majorSubsystemVersion(): number;
set majorSubsystemVersion(val: number);
get minorSubsystemVersion(): number;
set minorSubsystemVersion(val: number);
get win32VersionValue(): number;
set win32VersionValue(val: number);
get sizeOfImage(): number;
set sizeOfImage(val: number);
get sizeOfHeaders(): number;
set sizeOfHeaders(val: number);
get checkSum(): number;
set checkSum(val: number);
get subsystem(): number;
set subsystem(val: number);
get dllCharacteristics(): number;
set dllCharacteristics(val: number);
get sizeOfStackReserve(): number;
set sizeOfStackReserve(val: number);
get sizeOfStackReserveBigInt(): bigint;
set sizeOfStackReserveBigInt(val: bigint);
get sizeOfStackCommit(): number;
set sizeOfStackCommit(val: number);
get sizeOfStackCommitBigInt(): bigint;
set sizeOfStackCommitBigInt(val: bigint);
get sizeOfHeapReserve(): number;
set sizeOfHeapReserve(val: number);
get sizeOfHeapReserveBigInt(): bigint;
set sizeOfHeapReserveBigInt(val: bigint);
get sizeOfHeapCommit(): number;
set sizeOfHeapCommit(val: number);
get sizeOfHeapCommitBigInt(): bigint;
set sizeOfHeapCommitBigInt(val: bigint);
get loaderFlags(): number;
set loaderFlags(val: number);
get numberOfRvaAndSizes(): number;
set numberOfRvaAndSizes(val: number);
}

View File

@@ -0,0 +1,396 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var FormatBase_js_1 = require("./FormatBase.js");
function getUint64LE(view, offset) {
return (view.getUint32(offset + 4, true) * 0x100000000 +
view.getUint32(offset, true));
}
function setUint64LE(view, offset, val) {
view.setUint32(offset, val & 0xffffffff, true);
view.setUint32(offset + 4, Math.floor(val / 0x100000000), true);
}
function getUint64LEBigInt(view, offset) {
/* istanbul ignore if */
if (typeof BigInt === 'undefined') {
throw new Error('BigInt not supported');
}
return (BigInt(0x100000000) * BigInt(view.getUint32(offset + 4, true)) +
BigInt(view.getUint32(offset, true)));
}
function setUint64LEBigInt(view, offset, val) {
/* istanbul ignore if */
if (typeof BigInt === 'undefined') {
throw new Error('BigInt not supported');
}
view.setUint32(offset, Number(val & BigInt(0xffffffff)), true);
view.setUint32(offset + 4, Math.floor(Number((val / BigInt(0x100000000)) & BigInt(0xffffffff))), true);
}
var ImageOptionalHeader64 = /** @class */ (function (_super) {
__extends(ImageOptionalHeader64, _super);
function ImageOptionalHeader64(view) {
return _super.call(this, view) || this;
}
ImageOptionalHeader64.from = function (bin, offset) {
if (offset === void 0) { offset = 0; }
return new ImageOptionalHeader64(new DataView(bin, offset, 112));
};
Object.defineProperty(ImageOptionalHeader64.prototype, "magic", {
get: function () {
return this.view.getUint16(0, true);
},
set: function (val) {
this.view.setUint16(0, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "majorLinkerVersion", {
get: function () {
return this.view.getUint8(2);
},
set: function (val) {
this.view.setUint8(2, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "minorLinkerVersion", {
get: function () {
return this.view.getUint8(3);
},
set: function (val) {
this.view.setUint8(3, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfCode", {
get: function () {
return this.view.getUint32(4, true);
},
set: function (val) {
this.view.setUint32(4, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfInitializedData", {
get: function () {
return this.view.getUint32(8, true);
},
set: function (val) {
this.view.setUint32(8, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfUninitializedData", {
get: function () {
return this.view.getUint32(12, true);
},
set: function (val) {
this.view.setUint32(12, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "addressOfEntryPoint", {
get: function () {
return this.view.getUint32(16, true);
},
set: function (val) {
this.view.setUint32(16, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "baseOfCode", {
get: function () {
return this.view.getUint32(20, true);
},
set: function (val) {
this.view.setUint32(20, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "imageBase", {
get: function () {
return getUint64LE(this.view, 24);
},
set: function (val) {
setUint64LE(this.view, 24, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "imageBaseBigInt", {
get: function () {
return getUint64LEBigInt(this.view, 24);
},
set: function (val) {
setUint64LEBigInt(this.view, 24, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sectionAlignment", {
get: function () {
return this.view.getUint32(32, true);
},
set: function (val) {
this.view.setUint32(32, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "fileAlignment", {
get: function () {
return this.view.getUint32(36, true);
},
set: function (val) {
this.view.setUint32(36, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "majorOperatingSystemVersion", {
get: function () {
return this.view.getUint16(40, true);
},
set: function (val) {
this.view.setUint16(40, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "minorOperatingSystemVersion", {
get: function () {
return this.view.getUint16(42, true);
},
set: function (val) {
this.view.setUint16(42, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "majorImageVersion", {
get: function () {
return this.view.getUint16(44, true);
},
set: function (val) {
this.view.setUint16(44, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "minorImageVersion", {
get: function () {
return this.view.getUint16(46, true);
},
set: function (val) {
this.view.setUint16(46, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "majorSubsystemVersion", {
get: function () {
return this.view.getUint16(48, true);
},
set: function (val) {
this.view.setUint16(48, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "minorSubsystemVersion", {
get: function () {
return this.view.getUint16(50, true);
},
set: function (val) {
this.view.setUint16(50, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "win32VersionValue", {
get: function () {
return this.view.getUint32(52, true);
},
set: function (val) {
this.view.setUint32(52, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfImage", {
get: function () {
return this.view.getUint32(56, true);
},
set: function (val) {
this.view.setUint32(56, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfHeaders", {
get: function () {
return this.view.getUint32(60, true);
},
set: function (val) {
this.view.setUint32(60, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "checkSum", {
get: function () {
return this.view.getUint32(64, true);
},
set: function (val) {
this.view.setUint32(64, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "subsystem", {
get: function () {
return this.view.getUint16(68, true);
},
set: function (val) {
this.view.setUint16(68, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "dllCharacteristics", {
get: function () {
return this.view.getUint16(70, true);
},
set: function (val) {
this.view.setUint16(70, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfStackReserve", {
get: function () {
return getUint64LE(this.view, 72);
},
set: function (val) {
setUint64LE(this.view, 72, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfStackReserveBigInt", {
get: function () {
return getUint64LEBigInt(this.view, 72);
},
set: function (val) {
setUint64LEBigInt(this.view, 72, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfStackCommit", {
get: function () {
return getUint64LE(this.view, 80);
},
set: function (val) {
setUint64LE(this.view, 80, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfStackCommitBigInt", {
get: function () {
return getUint64LEBigInt(this.view, 80);
},
set: function (val) {
setUint64LEBigInt(this.view, 80, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfHeapReserve", {
get: function () {
return getUint64LE(this.view, 88);
},
set: function (val) {
setUint64LE(this.view, 88, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfHeapReserveBigInt", {
get: function () {
return getUint64LEBigInt(this.view, 88);
},
set: function (val) {
setUint64LEBigInt(this.view, 88, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfHeapCommit", {
get: function () {
return getUint64LE(this.view, 96);
},
set: function (val) {
setUint64LE(this.view, 96, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "sizeOfHeapCommitBigInt", {
get: function () {
return getUint64LEBigInt(this.view, 96);
},
set: function (val) {
setUint64LEBigInt(this.view, 96, val);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "loaderFlags", {
get: function () {
return this.view.getUint32(104, true);
},
set: function (val) {
this.view.setUint32(104, val, true);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ImageOptionalHeader64.prototype, "numberOfRvaAndSizes", {
get: function () {
return this.view.getUint32(108, true);
},
set: function (val) {
this.view.setUint32(108, val, true);
},
enumerable: false,
configurable: true
});
ImageOptionalHeader64.size = 112;
ImageOptionalHeader64.DEFAULT_MAGIC = 0x20b;
return ImageOptionalHeader64;
}(FormatBase_js_1.default));
exports.default = ImageOptionalHeader64;

View File

@@ -0,0 +1,21 @@
import ArrayFormatBase from './ArrayFormatBase.js';
export interface ImageSectionHeader {
name: string;
virtualSize: number;
virtualAddress: number;
sizeOfRawData: number;
pointerToRawData: number;
pointerToRelocations: number;
pointerToLineNumbers: number;
numberOfRelocations: number;
numberOfLineNumbers: number;
characteristics: number;
}
export default class ImageSectionHeaderArray extends ArrayFormatBase<ImageSectionHeader> {
readonly length: number;
static readonly itemSize = 40;
private constructor();
static from(bin: ArrayBuffer, length: number, offset?: number): ImageSectionHeaderArray;
get(index: number): Readonly<ImageSectionHeader>;
set(index: number, data: ImageSectionHeader): void;
}

View File

@@ -0,0 +1,61 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var ArrayFormatBase_js_1 = require("./ArrayFormatBase.js");
var functions_js_1 = require("../util/functions.js");
var ImageSectionHeaderArray = /** @class */ (function (_super) {
__extends(ImageSectionHeaderArray, _super);
function ImageSectionHeaderArray(view, length) {
var _this = _super.call(this, view) || this;
_this.length = length;
return _this;
}
ImageSectionHeaderArray.from = function (bin, length, offset) {
if (offset === void 0) { offset = 0; }
var size = length * 40;
return new ImageSectionHeaderArray(new DataView(bin, offset, size), length);
};
ImageSectionHeaderArray.prototype.get = function (index) {
return {
name: functions_js_1.getFixedString(this.view, index * 40, 8),
virtualSize: this.view.getUint32(8 + index * 40, true),
virtualAddress: this.view.getUint32(12 + index * 40, true),
sizeOfRawData: this.view.getUint32(16 + index * 40, true),
pointerToRawData: this.view.getUint32(20 + index * 40, true),
pointerToRelocations: this.view.getUint32(24 + index * 40, true),
pointerToLineNumbers: this.view.getUint32(28 + index * 40, true),
numberOfRelocations: this.view.getUint16(32 + index * 40, true),
numberOfLineNumbers: this.view.getUint16(34 + index * 40, true),
characteristics: this.view.getUint32(36 + index * 40, true),
};
};
ImageSectionHeaderArray.prototype.set = function (index, data) {
functions_js_1.setFixedString(this.view, index * 40, 8, data.name);
this.view.setUint32(8 + index * 40, data.virtualSize, true);
this.view.setUint32(12 + index * 40, data.virtualAddress, true);
this.view.setUint32(16 + index * 40, data.sizeOfRawData, true);
this.view.setUint32(20 + index * 40, data.pointerToRawData, true);
this.view.setUint32(24 + index * 40, data.pointerToRelocations, true);
this.view.setUint32(28 + index * 40, data.pointerToLineNumbers, true);
this.view.setUint16(32 + index * 40, data.numberOfRelocations, true);
this.view.setUint16(34 + index * 40, data.numberOfLineNumbers, true);
this.view.setUint32(36 + index * 40, data.characteristics, true);
};
ImageSectionHeaderArray.itemSize = 40;
return ImageSectionHeaderArray;
}(ArrayFormatBase_js_1.default));
exports.default = ImageSectionHeaderArray;

View File

@@ -0,0 +1,15 @@
import ArrayFormatBase from './ArrayFormatBase.js';
import FormatBase from './FormatBase.js';
import ImageDataDirectoryArray, { ImageDataDirectory } from './ImageDataDirectoryArray.js';
import ImageDirectoryEntry from './ImageDirectoryEntry.js';
import ImageDosHeader from './ImageDosHeader.js';
import ImageFileHeader from './ImageFileHeader.js';
import ImageNtHeaders from './ImageNtHeaders.js';
import ImageOptionalHeader from './ImageOptionalHeader.js';
import ImageOptionalHeader64 from './ImageOptionalHeader64.js';
import ImageSectionHeaderArray, { ImageSectionHeader } from './ImageSectionHeaderArray.js';
export { ArrayFormatBase, FormatBase, ImageDataDirectory, ImageDataDirectoryArray, ImageDirectoryEntry, ImageDosHeader, ImageFileHeader, ImageNtHeaders, ImageOptionalHeader, ImageOptionalHeader64, ImageSectionHeader, ImageSectionHeaderArray, };
export declare function getImageDosHeader(bin: ArrayBuffer): ImageDosHeader;
export declare function getImageNtHeadersByDosHeader(bin: ArrayBuffer, dosHeader: ImageDosHeader): ImageNtHeaders;
export declare function getImageSectionHeadersByNtHeaders(bin: ArrayBuffer, dosHeader: ImageDosHeader, ntHeaders: ImageNtHeaders): ImageSectionHeaderArray;
export declare function findImageSectionBlockByDirectoryEntry(bin: ArrayBuffer, dosHeader: ImageDosHeader, ntHeaders: ImageNtHeaders, entryType: ImageDirectoryEntry): ArrayBuffer | null;

View File

@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.findImageSectionBlockByDirectoryEntry = exports.getImageSectionHeadersByNtHeaders = exports.getImageNtHeadersByDosHeader = exports.getImageDosHeader = exports.ImageSectionHeaderArray = exports.ImageOptionalHeader64 = exports.ImageOptionalHeader = exports.ImageNtHeaders = exports.ImageFileHeader = exports.ImageDosHeader = exports.ImageDirectoryEntry = exports.ImageDataDirectoryArray = exports.FormatBase = exports.ArrayFormatBase = void 0;
var ArrayFormatBase_js_1 = require("./ArrayFormatBase.js");
exports.ArrayFormatBase = ArrayFormatBase_js_1.default;
var FormatBase_js_1 = require("./FormatBase.js");
exports.FormatBase = FormatBase_js_1.default;
var ImageDataDirectoryArray_js_1 = require("./ImageDataDirectoryArray.js");
exports.ImageDataDirectoryArray = ImageDataDirectoryArray_js_1.default;
var ImageDirectoryEntry_js_1 = require("./ImageDirectoryEntry.js");
exports.ImageDirectoryEntry = ImageDirectoryEntry_js_1.default;
var ImageDosHeader_js_1 = require("./ImageDosHeader.js");
exports.ImageDosHeader = ImageDosHeader_js_1.default;
var ImageFileHeader_js_1 = require("./ImageFileHeader.js");
exports.ImageFileHeader = ImageFileHeader_js_1.default;
var ImageNtHeaders_js_1 = require("./ImageNtHeaders.js");
exports.ImageNtHeaders = ImageNtHeaders_js_1.default;
var ImageOptionalHeader_js_1 = require("./ImageOptionalHeader.js");
exports.ImageOptionalHeader = ImageOptionalHeader_js_1.default;
var ImageOptionalHeader64_js_1 = require("./ImageOptionalHeader64.js");
exports.ImageOptionalHeader64 = ImageOptionalHeader64_js_1.default;
var ImageSectionHeaderArray_js_1 = require("./ImageSectionHeaderArray.js");
exports.ImageSectionHeaderArray = ImageSectionHeaderArray_js_1.default;
function getImageDosHeader(bin) {
return ImageDosHeader_js_1.default.from(bin);
}
exports.getImageDosHeader = getImageDosHeader;
function getImageNtHeadersByDosHeader(bin, dosHeader) {
return ImageNtHeaders_js_1.default.from(bin, dosHeader.newHeaderAddress);
}
exports.getImageNtHeadersByDosHeader = getImageNtHeadersByDosHeader;
function getImageSectionHeadersByNtHeaders(bin, dosHeader, ntHeaders) {
return ImageSectionHeaderArray_js_1.default.from(bin, ntHeaders.fileHeader.numberOfSections, dosHeader.newHeaderAddress + ntHeaders.byteLength);
}
exports.getImageSectionHeadersByNtHeaders = getImageSectionHeadersByNtHeaders;
function findImageSectionBlockByDirectoryEntry(bin, dosHeader, ntHeaders, entryType) {
var arr = ImageSectionHeaderArray_js_1.default.from(bin, ntHeaders.fileHeader.numberOfSections, dosHeader.newHeaderAddress + ntHeaders.byteLength);
var len = arr.length;
var rva = ntHeaders.optionalHeaderDataDirectory.get(entryType).virtualAddress;
for (var i = 0; i < len; ++i) {
var sec = arr.get(i);
var vaEnd = sec.virtualAddress + sec.virtualSize;
if (rva >= sec.virtualAddress && rva < vaEnd) {
var ptr = sec.pointerToRawData;
if (!ptr) {
return null;
}
return bin.slice(ptr, ptr + sec.sizeOfRawData);
}
if (rva < sec.virtualAddress) {
return null;
}
}
return null;
}
exports.findImageSectionBlockByDirectoryEntry = findImageSectionBlockByDirectoryEntry;

View File

@@ -0,0 +1,7 @@
import NtExecutable, { NtExecutableFromOptions, NtExecutableSection } from './NtExecutable.js';
import NtExecutableResource from './NtExecutableResource.js';
import { calculateCheckSumForPE } from './util/functions.js';
import version from './version.js';
import * as Format from './format/index.js';
import * as Type from './type/index.js';
export { NtExecutable, NtExecutableFromOptions, NtExecutableResource, NtExecutableSection, calculateCheckSumForPE, version, Format, Type, };

15
desktop-operator/node_modules/pe-library/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Type = exports.Format = exports.version = exports.calculateCheckSumForPE = exports.NtExecutableResource = exports.NtExecutable = void 0;
var NtExecutable_js_1 = require("./NtExecutable.js");
exports.NtExecutable = NtExecutable_js_1.default;
var NtExecutableResource_js_1 = require("./NtExecutableResource.js");
exports.NtExecutableResource = NtExecutableResource_js_1.default;
var functions_js_1 = require("./util/functions.js");
Object.defineProperty(exports, "calculateCheckSumForPE", { enumerable: true, get: function () { return functions_js_1.calculateCheckSumForPE; } });
var version_js_1 = require("./version.js");
exports.version = version_js_1.default;
var Format = require("./format/index.js");
exports.Format = Format;
var Type = require("./type/index.js");
exports.Type = Type;

View File

@@ -0,0 +1,17 @@
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const {
NtExecutable,
NtExecutableResource,
calculateCheckSumForPE,
version,
Format,
} = require('./index.js');
export {
NtExecutable,
NtExecutableResource,
calculateCheckSumForPE,
version,
Format,
};

View File

@@ -0,0 +1,31 @@
export interface ResourceEntryBaseType<TType extends string | number, TID extends string | number, TLang extends string | number> {
/**
* The resource type name or numeric value.
* For well-known type (such as `RT_ICON`), this value must be the predefined numeric value.
*/
type: TType;
/** The ID of resource data. */
id: TID;
/**
* The language value of resource data.
* According to specification, this value can be string, but
* typically this value would be LANGID (numeric) value.
*/
lang: TLang;
/**
* The code page value for strings within the resource data.
* Typically this value would be the Unicode code page '1200'.
*/
codepage: number;
/** The actual resource data. If the data cannot be read, this field will be an empty binary. */
bin: ArrayBuffer;
/** RVA data for resource data. This field is available only when actual data (`bin` field) cannot be read. */
rva?: number;
/** (used by output) */
offset?: number;
}
export declare type ResourceEntryT<TType extends string | number> = ResourceEntryBaseType<TType, string | number, string | number>;
export declare type ResourceEntryTT<TType extends string | number, TID extends string | number> = ResourceEntryBaseType<TType, TID, string | number>;
/** Raw resource entry data */
declare type ResourceEntry = ResourceEntryBaseType<string | number, string | number, string | number>;
export default ResourceEntry;

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,2 @@
import ResourceEntry, { ResourceEntryBaseType, ResourceEntryT, ResourceEntryTT } from './ResourceEntry.js';
export { ResourceEntry, ResourceEntryBaseType, ResourceEntryT, ResourceEntryTT, };

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,13 @@
/// <reference lib="dom" />
export declare function cloneObject<T extends object>(object: Readonly<T>): T;
export declare function cloneObject<T extends object>(object: T): T;
export declare function createDataView(bin: ArrayBuffer | ArrayBufferView, byteOffset?: number, byteLength?: number): DataView;
export declare function calculateCheckSumForPE(bin: ArrayBuffer, storeToBinary?: boolean): number;
export declare function roundUp(val: number, align: number): number;
export declare function copyBuffer(dest: ArrayBuffer | ArrayBufferView, destOffset: number, src: ArrayBuffer | ArrayBufferView, srcOffset: number, length: number): void;
export declare function allocatePartialBinary(binBase: ArrayBuffer | ArrayBufferView, offset: number, length: number): ArrayBuffer;
export declare function cloneToArrayBuffer(binBase: ArrayBuffer | ArrayBufferView): ArrayBuffer;
export declare function getFixedString(view: DataView, offset: number, length: number): string;
export declare function setFixedString(view: DataView, offset: number, length: number, text: string): void;
export declare function binaryToString(bin: ArrayBuffer | ArrayBufferView): string;
export declare function stringToBinary(string: string): ArrayBuffer;

View File

@@ -0,0 +1,273 @@
"use strict";
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference lib='dom' />
Object.defineProperty(exports, "__esModule", { value: true });
exports.stringToBinary = exports.binaryToString = exports.setFixedString = exports.getFixedString = exports.cloneToArrayBuffer = exports.allocatePartialBinary = exports.copyBuffer = exports.roundUp = exports.calculateCheckSumForPE = exports.createDataView = exports.cloneObject = void 0;
var ImageDosHeader_js_1 = require("../format/ImageDosHeader.js");
function cloneObject(object) {
var r = {};
Object.keys(object).forEach(function (key) {
r[key] = object[key];
});
return r;
}
exports.cloneObject = cloneObject;
/* eslint-enable @typescript-eslint/ban-types */
function createDataView(bin, byteOffset, byteLength) {
if ('buffer' in bin) {
var newOffset = bin.byteOffset;
var newLength = bin.byteLength;
if (typeof byteOffset !== 'undefined') {
newOffset += byteOffset;
newLength -= byteOffset;
}
if (typeof byteLength !== 'undefined') {
newLength = byteLength;
}
return new DataView(bin.buffer, newOffset, newLength);
}
else {
return new DataView(bin, byteOffset, byteLength);
}
}
exports.createDataView = createDataView;
function calculateCheckSumForPE(bin, storeToBinary) {
var dosHeader = ImageDosHeader_js_1.default.from(bin);
var view = new DataView(bin);
var checkSumOffset = dosHeader.newHeaderAddress + 88;
var result = 0;
var limit = 0x100000000; // 2^32
var update = function (dword) {
result += dword;
if (result >= limit) {
result = (result % limit) + ((result / limit) | 0);
}
};
var len = view.byteLength;
var lenExtra = len % 4;
var lenAlign = len - lenExtra;
for (var i = 0; i < lenAlign; i += 4) {
if (i !== checkSumOffset) {
update(view.getUint32(i, true));
}
}
if (lenExtra !== 0) {
var extra = 0;
for (var i = 0; i < lenExtra; i++) {
extra |= view.getUint8(lenAlign + i) << ((3 - i) * 8);
}
update(extra);
}
result = (result & 0xffff) + (result >>> 16);
result += result >>> 16;
result = (result & 0xffff) + len;
if (storeToBinary) {
view.setUint32(checkSumOffset, result, true);
}
return result;
}
exports.calculateCheckSumForPE = calculateCheckSumForPE;
function roundUp(val, align) {
return Math.floor((val + align - 1) / align) * align;
}
exports.roundUp = roundUp;
function copyBuffer(dest, destOffset, src, srcOffset, length) {
var ua8Dest = 'buffer' in dest
? new Uint8Array(dest.buffer, dest.byteOffset + (destOffset || 0), length)
: new Uint8Array(dest, destOffset, length);
var ua8Src = 'buffer' in src
? new Uint8Array(src.buffer, src.byteOffset + (srcOffset || 0), length)
: new Uint8Array(src, srcOffset, length);
ua8Dest.set(ua8Src);
}
exports.copyBuffer = copyBuffer;
function allocatePartialBinary(binBase, offset, length) {
var b = new ArrayBuffer(length);
copyBuffer(b, 0, binBase, offset, length);
return b;
}
exports.allocatePartialBinary = allocatePartialBinary;
function cloneToArrayBuffer(binBase) {
if ('buffer' in binBase) {
var b = new ArrayBuffer(binBase.byteLength);
new Uint8Array(b).set(new Uint8Array(binBase.buffer, binBase.byteOffset, binBase.byteLength));
return b;
}
else {
var b = new ArrayBuffer(binBase.byteLength);
new Uint8Array(b).set(new Uint8Array(binBase));
return b;
}
}
exports.cloneToArrayBuffer = cloneToArrayBuffer;
function getFixedString(view, offset, length) {
var actualLen = 0;
for (var i = 0; i < length; ++i) {
if (view.getUint8(offset + i) === 0) {
break;
}
++actualLen;
}
if (typeof Buffer !== 'undefined') {
return Buffer.from(view.buffer, view.byteOffset + offset, actualLen).toString('utf8');
}
else if (typeof decodeURIComponent !== 'undefined') {
var s = '';
for (var i = 0; i < actualLen; ++i) {
var c = view.getUint8(offset + i);
if (c < 16) {
s += '%0' + c.toString(16);
}
else {
s += '%' + c.toString(16);
}
}
return decodeURIComponent(s);
}
else {
var s = '';
for (var i = 0; i < actualLen; ++i) {
var c = view.getUint8(offset + i);
s += String.fromCharCode(c);
}
return s;
}
}
exports.getFixedString = getFixedString;
function setFixedString(view, offset, length, text) {
if (typeof Buffer !== 'undefined') {
var u = new Uint8Array(view.buffer, view.byteOffset + offset, length);
// fill by zero
u.set(new Uint8Array(length));
u.set(Buffer.from(text, 'utf8').subarray(0, length));
}
else if (typeof encodeURIComponent !== 'undefined') {
var s = encodeURIComponent(text);
for (var i = 0, j = 0; i < length; ++i) {
if (j >= s.length) {
view.setUint8(i + offset, 0);
}
else {
var c = s.charCodeAt(j);
if (c === 37) {
// '%'
var n = parseInt(s.substr(j + 1, 2), 16);
if (typeof n === 'number' && !isNaN(n)) {
view.setUint8(i + offset, n);
}
else {
view.setUint8(i + offset, 0);
}
j += 3;
}
else {
view.setUint8(i + offset, c);
}
}
}
}
else {
for (var i = 0, j = 0; i < length; ++i) {
if (j >= text.length) {
view.setUint8(i + offset, 0);
}
else {
var c = text.charCodeAt(j);
view.setUint8(i + offset, c & 0xff);
}
}
}
}
exports.setFixedString = setFixedString;
function binaryToString(bin) {
if (typeof TextDecoder !== 'undefined') {
var dec = new TextDecoder();
return dec.decode(bin);
}
else if (typeof Buffer !== 'undefined') {
var b = void 0;
if ('buffer' in bin) {
b = Buffer.from(bin.buffer, bin.byteOffset, bin.byteLength);
}
else {
b = Buffer.from(bin);
}
return b.toString('utf8');
}
else {
var view = void 0;
if ('buffer' in bin) {
view = new Uint8Array(bin.buffer, bin.byteOffset, bin.byteLength);
}
else {
view = new Uint8Array(bin);
}
if (typeof decodeURIComponent !== 'undefined') {
var s = '';
for (var i = 0; i < view.length; ++i) {
var c = view[i];
if (c < 16) {
s += '%0' + c.toString(16);
}
else {
s += '%' + c.toString(16);
}
}
return decodeURIComponent(s);
}
else {
var s = '';
for (var i = 0; i < view.length; ++i) {
var c = view[i];
s += String.fromCharCode(c);
}
return s;
}
}
}
exports.binaryToString = binaryToString;
function stringToBinary(string) {
if (typeof TextEncoder !== 'undefined') {
var enc = new TextEncoder();
return cloneToArrayBuffer(enc.encode(string));
}
else if (typeof Buffer !== 'undefined') {
return cloneToArrayBuffer(Buffer.from(string, 'utf8'));
}
else if (typeof encodeURIComponent !== 'undefined') {
var data = encodeURIComponent(string);
var len = 0;
for (var i = 0; i < data.length; ++len) {
var c = data.charCodeAt(i);
if (c === 37) {
i += 3;
}
else {
++i;
}
}
var bin = new ArrayBuffer(len);
var view = new Uint8Array(bin);
for (var i = 0, j = 0; i < data.length; ++j) {
var c = data.charCodeAt(i);
if (c === 37) {
var n = parseInt(data.substring(i + 1, i + 3), 16);
view[j] = n;
i += 3;
}
else {
view[j] = c;
++i;
}
}
return bin;
}
else {
var bin = new ArrayBuffer(string.length);
new Uint8Array(bin).set([].map.call(string, function (c) {
return c.charCodeAt(0);
}));
return bin;
}
}
exports.stringToBinary = stringToBinary;

View File

@@ -0,0 +1,5 @@
export declare function getDosStubDataSize(): number;
export declare function fillDosStubData(bin: ArrayBuffer | ArrayBufferView): void;
export declare function estimateNewHeaderSize(is32Bit: boolean): number;
export declare function fillPeHeaderEmptyData(bin: ArrayBuffer | ArrayBufferView, offset: number, totalBinSize: number, is32Bit: boolean, isDLL: boolean): void;
export declare function makeEmptyNtExecutableBinary(is32Bit: boolean, isDLL: boolean): ArrayBuffer;

View File

@@ -0,0 +1,127 @@
"use strict";
// To make the binary (DOS_STUB_PROGRAM):
// $ cd tools/dos-stub
// $ nasm -f bin -o dos-stub.bin dos-stub.asm
// $ node -e "console.log([].map.call(fs.readFileSync('tools/dos-stub/dos-stub.bin'), (v)=>`0x${Buffer.from([v]).toString('hex')}`).join(','))"
//
// NOTE: the original dos-stub.asm program and the bit code in DOS_STUB_PROGRAM are under the 0-BSD license.
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeEmptyNtExecutableBinary = exports.fillPeHeaderEmptyData = exports.estimateNewHeaderSize = exports.fillDosStubData = exports.getDosStubDataSize = void 0;
var ImageDataDirectoryArray_js_1 = require("../format/ImageDataDirectoryArray.js");
var ImageDosHeader_js_1 = require("../format/ImageDosHeader.js");
var ImageFileHeader_js_1 = require("../format/ImageFileHeader.js");
var ImageNtHeaders_js_1 = require("../format/ImageNtHeaders.js");
var ImageOptionalHeader_js_1 = require("../format/ImageOptionalHeader.js");
var ImageOptionalHeader64_js_1 = require("../format/ImageOptionalHeader64.js");
var functions_js_1 = require("./functions.js");
// fill with '0x00' to make 8-bytes alignment
// prettier-ignore
var DOS_STUB_PROGRAM = new Uint8Array([
0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x44, 0x4f,
0x53, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f,
0x72, 0x74, 0x65, 0x64, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]);
var DOS_STUB_SIZE = functions_js_1.roundUp(ImageDosHeader_js_1.default.size + DOS_STUB_PROGRAM.length, 0x80);
var DEFAULT_FILE_ALIGNMENT = 512;
function getDosStubDataSize() {
return DOS_STUB_SIZE;
}
exports.getDosStubDataSize = getDosStubDataSize;
function fillDosStubData(bin) {
var dos = ImageDosHeader_js_1.default.from(bin);
dos.magic = ImageDosHeader_js_1.default.DEFAULT_MAGIC;
// last page size
dos.lastPageSize = DOS_STUB_SIZE % 512;
// total page count
dos.pages = Math.ceil(DOS_STUB_SIZE / 512);
// no relocations
dos.relocations = 0;
// header size as paragraph count (1 paragraph = 16 bytes)
dos.headerSizeInParagraph = Math.ceil(ImageDosHeader_js_1.default.size / 16);
dos.minAllocParagraphs = 0;
dos.maxAllocParagraphs = 0xffff;
dos.initialSS = 0;
dos.initialSP = 0x80;
// (no relocations, but set offset after the header)
dos.relocationTableAddress = ImageDosHeader_js_1.default.size;
dos.newHeaderAddress = DOS_STUB_SIZE;
functions_js_1.copyBuffer(bin, ImageDosHeader_js_1.default.size, DOS_STUB_PROGRAM, 0, DOS_STUB_PROGRAM.length);
}
exports.fillDosStubData = fillDosStubData;
function estimateNewHeaderSize(is32Bit) {
return (
// magic
4 +
ImageFileHeader_js_1.default.size +
(is32Bit ? ImageOptionalHeader_js_1.default.size : ImageOptionalHeader64_js_1.default.size) +
ImageDataDirectoryArray_js_1.default.size);
}
exports.estimateNewHeaderSize = estimateNewHeaderSize;
function fillPeHeaderEmptyData(bin, offset, totalBinSize, is32Bit, isDLL) {
var _bin;
var _offset;
if ('buffer' in bin) {
_bin = bin.buffer;
_offset = bin.byteOffset + offset;
}
else {
_bin = bin;
_offset = offset;
}
new DataView(_bin, _offset).setUint32(0, ImageNtHeaders_js_1.default.DEFAULT_SIGNATURE, true);
var fh = ImageFileHeader_js_1.default.from(_bin, _offset + 4);
fh.machine = is32Bit ? 0x14c : 0x8664;
fh.numberOfSections = 0; // no sections
fh.timeDateStamp = 0;
fh.pointerToSymbolTable = 0;
fh.numberOfSymbols = 0;
fh.sizeOfOptionalHeader =
(is32Bit ? ImageOptionalHeader_js_1.default.size : ImageOptionalHeader64_js_1.default.size) +
ImageDataDirectoryArray_js_1.default.size;
fh.characteristics = isDLL ? 0x2102 : 0x102;
var oh = (is32Bit ? ImageOptionalHeader_js_1.default : ImageOptionalHeader64_js_1.default).from(_bin, _offset + 4 + ImageFileHeader_js_1.default.size);
oh.magic = is32Bit
? ImageOptionalHeader_js_1.default.DEFAULT_MAGIC
: ImageOptionalHeader64_js_1.default.DEFAULT_MAGIC;
// oh.majorLinkerVersion = 0;
// oh.minorLinkerVersion = 0;
oh.sizeOfCode = 0;
oh.sizeOfInitializedData = 0;
oh.sizeOfUninitializedData = 0;
oh.addressOfEntryPoint = 0;
oh.baseOfCode = 0x1000;
// oh.baseOfData = 0; // for 32bit only
oh.imageBase = is32Bit ? 0x1000000 : 0x180000000;
oh.sectionAlignment = 4096;
oh.fileAlignment = DEFAULT_FILE_ALIGNMENT;
oh.majorOperatingSystemVersion = 6;
oh.minorOperatingSystemVersion = 0;
// oh.majorImageVersion = 0;
// oh.minorImageVersion = 0;
oh.majorSubsystemVersion = 6;
oh.minorSubsystemVersion = 0;
// oh.win32VersionValue = 0;
oh.sizeOfHeaders = functions_js_1.roundUp(totalBinSize, oh.fileAlignment);
// oh.checkSum = 0;
oh.subsystem = 2; // IMAGE_SUBSYSTEM_WINDOWS_GUI
oh.dllCharacteristics =
(is32Bit ? 0 : 0x20) + // IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
0x40 + // IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
0x100; // IMAGE_DLLCHARACTERISTICS_NX_COMPAT
oh.sizeOfStackReserve = 0x100000;
oh.sizeOfStackCommit = 0x1000;
oh.sizeOfHeapReserve = 0x100000;
oh.sizeOfHeapCommit = 0x1000;
// oh.loaderFlags = 0;
oh.numberOfRvaAndSizes =
ImageDataDirectoryArray_js_1.default.size / ImageDataDirectoryArray_js_1.default.itemSize;
}
exports.fillPeHeaderEmptyData = fillPeHeaderEmptyData;
function makeEmptyNtExecutableBinary(is32Bit, isDLL) {
var bufferSize = functions_js_1.roundUp(DOS_STUB_SIZE + estimateNewHeaderSize(is32Bit), DEFAULT_FILE_ALIGNMENT);
var bin = new ArrayBuffer(bufferSize);
fillDosStubData(bin);
fillPeHeaderEmptyData(bin, DOS_STUB_SIZE, bufferSize, is32Bit, isDLL);
return bin;
}
exports.makeEmptyNtExecutableBinary = makeEmptyNtExecutableBinary;

View File

@@ -0,0 +1,2 @@
declare const _default: "0.4.1";
export default _default;

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = '0.4.1';

71
desktop-operator/node_modules/pe-library/package.json generated vendored Normal file
View File

@@ -0,0 +1,71 @@
{
"name": "pe-library",
"version": "0.4.1",
"engines": {
"node": ">=12",
"npm": ">=6"
},
"engineStrict": true,
"description": "Node.js library for Portable Executable format",
"main": "./dist/index.js",
"module": "./dist/_esm/index.js",
"exports": {
"node": {
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"import": "./dist/_esm/index.js",
"require": "./dist/index.js"
},
"types": "./dist/index.d.ts",
"author": "jet",
"license": "MIT",
"homepage": "https://github.com/jet2jet/pe-library-js",
"keywords": [
"javascript",
"library",
"pe",
"pe-executable",
"portable-executable",
"exe"
],
"repository": {
"type": "git",
"url": "https://github.com/jet2jet/pe-library-js.git"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/jet2jet"
},
"scripts": {
"build": "npm run build:cjs && npm run build:esm",
"build:cjs": "tsc -p ./tsconfig.app.json",
"build:esm": "tsc -p ./tsconfig.app.esm.json && node ./tools/copyEsmFile.js",
"lint": "npm run lint:prettier && npm run lint:eslint",
"lint:eslint": "eslint -c .eslintrc.yml --ext .js,.jsx,.ts,.tsx .",
"lint:eslint:fix": "eslint -c .eslintrc.yml --fix --ext .js,.jsx,.ts,.tsx .",
"lint:fix": "npm run lint:prettier:fix && npm run lint:eslint:fix",
"lint:prettier": "prettier --config ./.prettierrc.yml --check \"**/*.{js,jsx,ts,tsx,yml,json,md}\"",
"lint:prettier:fix": "prettier --config ./.prettierrc.yml --write \"**/*.{js,jsx,ts,tsx,yml,json,md}\"",
"test": "jest --config ./jest.config.basic.js",
"version": "node ./tools/updateVersion.js ./src/main/version.ts && git add -A ./src/main/version.ts"
},
"dependencies": {},
"devDependencies": {
"@types/jest": "^28.1.8",
"@types/node": "^12.20.37",
"@typescript-eslint/eslint-plugin": "^5.48.0",
"@typescript-eslint/parser": "^5.48.0",
"eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.0",
"eslint-config-standard": "^17.0.0",
"eslint-config-standard-with-typescript": "^26.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.6.0",
"eslint-plugin-promise": "^6.1.1",
"jest": "^28.1.3",
"prettier": "^2.8.2",
"ts-jest": "^28.0.8",
"typescript": "~4.2.4"
}
}