$ cnpm install resedit
resedit-js is a library that manipulates resouces contained by Windows Executable files. All implementations are written in JavaScript (TypeScript), without using any native binaries. resedit-js works in both Node.js environment and Web environment.
This library is not tested well for modifying and/or signing executables yet. Please be careful with the emitted binaries.
To use from command line, resedit-js-cli is suitable.
The demo page: resedit demo
npm install resedit
ResEdit namespace, see Examples.dist directory of the package. And, some test codes may help you for usages.For ESM (ES Modules):
//import * as PELibrary from 'pe-library';
import * as ResEdit from 'resedit';
For CJS (CommonJS modules including classic Node.js scripts):
//const PELibrary = require('pe-library');
const ResEdit = require('resedit');
If your Node.js version is prior to v20.19.5,
requirecannot be used for'resedit'package and you must use'resedit/cjs'package as described in Migrate from v1.x to v2.x (collapsed inMigration from prior resedit versionsarea).
This major version up includes 'Change requirements of Node.js version (v20.19.5 or later is required)' and 'Remove TypeScript enum usage' only. If your code base (project) meets following conditions, you can safely upgrade to v3.x (without no more actions):
VersionFileFlags, VersionFileOS, VersionFileDriverSubtype, VersionFileFontSubtype, and VersionFileType
let x: VersionFileFlags.Debug), rewrite with using typeof (e.g, let x: typeof VersionFileFlags.Debug).import, no need for migration.require (Node.js: via createRequire), replace with import statement: import * as ResEdit from 'resedit'.require, choose followings:
require synchronous ES module. resedit does not use top-level await, so you can write require('resedit') from CommonJS module.require call with import statementresedit/cjs module and call load function (see below)"module": "ES2015" or higher, no need for migration."module": "CommonJS", import resedit/cjs and call load functionThe sample of using resedit/cjs in CommonJS module is:
const { load } = require('resedit/cjs');
load().then((ResEdit) => {
// ResEdit will be the namespace object of resedit library
// (for example ResEdit.Data.IconFile is available)
});
Similarly, the sample of using resedit/cjs in TypeScript CommonJS module is:
// You can use `ResEdit` for type references (cannot be used for value references)
import { type ResEdit, load } from 'resedit/cjs';
load().then((RE: typeof ResEdit) => {
// RE will be the namespace object of resedit library
// (for example RE.Data.IconFile is available)
});
.exe and .dll), both 32-bit and 64-bit, are supported.
.res file is not supported now.require('resedit').Resource.IconGroupEntry class.NtExecutable.from receives a signed binary.{ ignoreCert: true } object must be passed to the second argument of NtExecutable.from.NtExecutable.generate will generate unsigned executable binary. If you want to re-sign it, you must use generate-function with signing (see below) or any other signing tool such as Microsoft signtool.resedit-js provides basic signing process generateExecutableWithSign function, which is based on Authenticode specification and related RFCs.
To keep resedit-js generic library, the followings are required to use signing process.
crypto module)
*.cer file data or *.p7b file data with DER-format), which is paired with the private key used by encryption process.These requirements are represented as SignerObject. The caller of generateExecutableWithSign function must implement this object to sign executables.
An example code is here: signTest.mjs
Note that resedit-js only provides basic signing process, and provides as beta version. For example adding more attributes/informations to certificates are not supported now.
Some digest algorithms, such as SHA3 algorithms, might not be supported by current Windows.
import * as PELibrary from 'pe-library';
import * as ResEdit from 'resedit';
import * as fs from 'fs';
// load and parse data
const data = fs.readFileSync('MyApp.exe');
// (the Node.js Buffer instance can be specified directly to NtExecutable.from)
const exe = PELibrary.NtExecutable.from(data);
const res = PELibrary.NtExecutableResource.from(exe);
// rewrite resources
// - You can use helper classes as followings:
// - ResEdit.Resource.IconGroupEntry: access icon resource data
// - ResEdit.Resource.StringTable: access string resource data
// - ResEdit.Resource.VersionInfo: access version info data
// -- replace icons
// load icon data from file
// (you can use ResEdit.Data.IconFile to parse icon data)
const iconFile = ResEdit.Data.IconFile.from(fs.readFileSync('MyIcon.ico'));
ResEdit.Resource.IconGroupEntry.replaceIconsForResource(
// destEntries
res.entries,
// iconGroupID
// - This ID is originally defined in base executable file
// (the ID list can be retrieved by `ResEdit.Resource.IconGroupEntry.fromEntries(res.entries).map((entry) => entry.id)`)
101,
// lang ('lang: 1033' means 'en-US')
1033,
// icons (map IconFileItem to IconItem/RawIconItem)
iconFile.icons.map((item) => item.data)
);
// -- replace version
const viList = ResEdit.Resource.VersionInfo.fromEntries(res.entries);
const vi = viList[0];
// setFileVersion will set `vi.fixedInfo.fileVersionMS`/`fileVersionLS` and 'FileVersion' string value
// ('1033' means 'en-US')
vi.setFileVersion(1, 0, 0, 0, 1033);
// ('lang: 1033' means 'en-US', 'codepage: 1200' is the default codepage)
vi.setStringValues(
{ lang: 1033, codepage: 1200 },
{
FileDescription: 'My application',
ProductName: 'My product',
}
);
vi.outputToResourceEntries(res.entries);
// write to another binary
res.outputResource(exe);
const newBinary = exe.generate();
fs.writeFileSync('MyApp_modified.exe', Buffer.from(newBinary));
Copyright 2013 - present © cnpmjs.org | Home |