@isopodlabs/binary_libs 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CompoundDocument.d.ts +129 -0
- package/dist/CompoundDocument.js +300 -0
- package/dist/arch.d.ts +26 -0
- package/dist/arch.js +96 -0
- package/dist/clr.d.ts +286 -0
- package/dist/clr.js +658 -0
- package/dist/elf.d.ts +112 -0
- package/dist/elf.js +778 -0
- package/dist/mach.d.ts +394 -0
- package/dist/mach.js +1027 -0
- package/dist/pe.d.ts +151 -0
- package/dist/pe.js +484 -0
- package/package.json +6 -3
- package/.gitmodules +0 -3
- package/.vscode/launch.json +0 -16
- package/.vscode/settings.json +0 -3
- package/.vscode/tasks.json +0 -39
- package/eslint.config.mjs +0 -32
- package/src/CompoundDocument.ts +0 -314
- package/src/arch.ts +0 -79
- package/src/clr.ts +0 -646
- package/src/elf.ts +0 -802
- package/src/mach.ts +0 -1140
- package/src/pe.ts +0 -506
- package/transform.ts +0 -369
- package/tsconfig.json +0 -27
- package/tsconfig.tsbuildinfo +0 -1
package/dist/pe.d.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import * as binary from '@isopodlabs/binary';
|
|
2
|
+
export declare class pe_stream extends binary.stream {
|
|
3
|
+
pe: PE;
|
|
4
|
+
constructor(pe: PE, data: Uint8Array);
|
|
5
|
+
get_rva(): Uint8Array | undefined;
|
|
6
|
+
}
|
|
7
|
+
declare const Section_base: (new (s: binary._stream) => {
|
|
8
|
+
Name: string;
|
|
9
|
+
VirtualSize: number;
|
|
10
|
+
VirtualAddress: binary.hex<number | bigint>;
|
|
11
|
+
SizeOfRawData: number;
|
|
12
|
+
PointerToRawData: binary.hex<number | bigint>;
|
|
13
|
+
PointerToRelocations: binary.hex<number | bigint>;
|
|
14
|
+
PointerToLinenumbers: binary.hex<number | bigint>;
|
|
15
|
+
NumberOfRelocations: number;
|
|
16
|
+
NumberOfLinenumbers: number;
|
|
17
|
+
Characteristics: Record<string, bigint | boolean> | Record<string, number | boolean>;
|
|
18
|
+
}) & {
|
|
19
|
+
get: (s: binary._stream) => {
|
|
20
|
+
Name: string;
|
|
21
|
+
VirtualSize: number;
|
|
22
|
+
VirtualAddress: binary.hex<number | bigint>;
|
|
23
|
+
SizeOfRawData: number;
|
|
24
|
+
PointerToRawData: binary.hex<number | bigint>;
|
|
25
|
+
PointerToRelocations: binary.hex<number | bigint>;
|
|
26
|
+
PointerToLinenumbers: binary.hex<number | bigint>;
|
|
27
|
+
NumberOfRelocations: number;
|
|
28
|
+
NumberOfLinenumbers: number;
|
|
29
|
+
Characteristics: Record<string, bigint | boolean> | Record<string, number | boolean>;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
declare class Section extends Section_base {
|
|
33
|
+
data?: binary.MappedMemory;
|
|
34
|
+
constructor(r: binary.stream);
|
|
35
|
+
get flags(): number;
|
|
36
|
+
}
|
|
37
|
+
interface DirectoryInfo {
|
|
38
|
+
read?: (pe: PE, data: binary.MappedMemory) => any;
|
|
39
|
+
}
|
|
40
|
+
type Directory = {
|
|
41
|
+
VirtualAddress: number;
|
|
42
|
+
Size: number;
|
|
43
|
+
};
|
|
44
|
+
export declare class PE {
|
|
45
|
+
private data;
|
|
46
|
+
header: {
|
|
47
|
+
magic: number;
|
|
48
|
+
cblp: number;
|
|
49
|
+
cp: number;
|
|
50
|
+
crlc: number;
|
|
51
|
+
cparhdr: number;
|
|
52
|
+
minalloc: number;
|
|
53
|
+
maxalloc: binary.hex<number | bigint>;
|
|
54
|
+
ss: number;
|
|
55
|
+
sp: number;
|
|
56
|
+
csum: number;
|
|
57
|
+
ip: number;
|
|
58
|
+
cs: number;
|
|
59
|
+
lfarlc: number;
|
|
60
|
+
ovno: number;
|
|
61
|
+
} & {
|
|
62
|
+
res: number[];
|
|
63
|
+
oemid: number;
|
|
64
|
+
oeminfo: number;
|
|
65
|
+
res2: number[];
|
|
66
|
+
lfanew: number;
|
|
67
|
+
};
|
|
68
|
+
opt?: {
|
|
69
|
+
Magic: string;
|
|
70
|
+
MajorLinkerVersion: number;
|
|
71
|
+
MinorLinkerVersion: number;
|
|
72
|
+
SizeOfCode: number;
|
|
73
|
+
SizeOfInitializedData: number;
|
|
74
|
+
SizeOfUninitializedData: number;
|
|
75
|
+
AddressOfEntryPoint: binary.hex<number | bigint>;
|
|
76
|
+
BaseOfCode: binary.hex<number | bigint>;
|
|
77
|
+
} & ({
|
|
78
|
+
BaseOfData: binary.hex<number | bigint>;
|
|
79
|
+
ImageBase: binary.hex<number | bigint>;
|
|
80
|
+
SectionAlignment: number;
|
|
81
|
+
FileAlignment: number;
|
|
82
|
+
MajorOperatingSystemVersion: number;
|
|
83
|
+
MinorOperatingSystemVersion: number;
|
|
84
|
+
MajorImageVersion: number;
|
|
85
|
+
MinorImageVersion: number;
|
|
86
|
+
MajorSubsystemVersion: number;
|
|
87
|
+
MinorSubsystemVersion: number;
|
|
88
|
+
Win32VersionValue: number;
|
|
89
|
+
SizeOfImage: number;
|
|
90
|
+
SizeOfHeaders: number;
|
|
91
|
+
CheckSum: number;
|
|
92
|
+
Subsystem: number;
|
|
93
|
+
DllCharacteristics: Record<string, bigint | boolean> | Record<string, number | boolean>;
|
|
94
|
+
SizeOfStackReserve: number;
|
|
95
|
+
SizeOfStackCommit: number;
|
|
96
|
+
SizeOfHeapReserve: number;
|
|
97
|
+
SizeOfHeapCommit: number;
|
|
98
|
+
LoaderFlags: number;
|
|
99
|
+
DataDirectory: Record<string, {
|
|
100
|
+
VirtualAddress: number;
|
|
101
|
+
Size: number;
|
|
102
|
+
}>;
|
|
103
|
+
} | {
|
|
104
|
+
ImageBase: binary.hex<number | bigint>;
|
|
105
|
+
SectionAlignment: number;
|
|
106
|
+
FileAlignment: number;
|
|
107
|
+
MajorOperatingSystemVersion: number;
|
|
108
|
+
MinorOperatingSystemVersion: number;
|
|
109
|
+
MajorImageVersion: number;
|
|
110
|
+
MinorImageVersion: number;
|
|
111
|
+
MajorSubsystemVersion: number;
|
|
112
|
+
MinorSubsystemVersion: number;
|
|
113
|
+
Win32VersionValue: number;
|
|
114
|
+
SizeOfImage: number;
|
|
115
|
+
SizeOfHeaders: number;
|
|
116
|
+
CheckSum: number;
|
|
117
|
+
Subsystem: number;
|
|
118
|
+
DllCharacteristics: Record<string, bigint | boolean> | Record<string, number | boolean>;
|
|
119
|
+
SizeOfStackReserve: bigint;
|
|
120
|
+
SizeOfStackCommit: bigint;
|
|
121
|
+
SizeOfHeapReserve: bigint;
|
|
122
|
+
SizeOfHeapCommit: bigint;
|
|
123
|
+
LoaderFlags: number;
|
|
124
|
+
DataDirectory: Record<string, {
|
|
125
|
+
VirtualAddress: number;
|
|
126
|
+
Size: number;
|
|
127
|
+
}>;
|
|
128
|
+
});
|
|
129
|
+
sections: Section[];
|
|
130
|
+
static check(data: Uint8Array): boolean;
|
|
131
|
+
constructor(data: Uint8Array);
|
|
132
|
+
get directories(): Record<string, {
|
|
133
|
+
VirtualAddress: number;
|
|
134
|
+
Size: number;
|
|
135
|
+
} & {}> | undefined;
|
|
136
|
+
FindSectionRVA(rva: number): Section | undefined;
|
|
137
|
+
FindSectionRaw(addr: number): Section | undefined;
|
|
138
|
+
GetDataRVA(rva: number, size?: number): binary.MappedMemory | undefined;
|
|
139
|
+
GetDataRaw(addr: number, size: number): Uint8Array | undefined;
|
|
140
|
+
GetDataDir(dir: {
|
|
141
|
+
VirtualAddress: number;
|
|
142
|
+
Size: number;
|
|
143
|
+
}): binary.MappedMemory | undefined;
|
|
144
|
+
ReadDirectory(name: string): any;
|
|
145
|
+
}
|
|
146
|
+
export declare function ReadExports(file: pe_stream): (string | number | binary.MappedMemory | undefined)[][];
|
|
147
|
+
export declare class DLLImports extends Array {
|
|
148
|
+
}
|
|
149
|
+
export declare function ReadImports(file: pe_stream): [string, any][];
|
|
150
|
+
export declare function ReadResourceDirectory(file: binary.stream, data: binary.MappedMemory, type?: number): Record<string, any>;
|
|
151
|
+
export {};
|
package/dist/pe.js
ADDED
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.DLLImports = exports.PE = exports.DATA_DIRECTORY = exports.DIRECTORIES = exports.pe_stream = void 0;
|
|
27
|
+
exports.ReadExports = ReadExports;
|
|
28
|
+
exports.ReadImports = ReadImports;
|
|
29
|
+
exports.ReadResourceDirectory = ReadResourceDirectory;
|
|
30
|
+
const binary = __importStar(require("@isopodlabs/binary"));
|
|
31
|
+
class MyDate extends Date {
|
|
32
|
+
constructor(x) { super(x * 1000); }
|
|
33
|
+
valueOf() { return this.getTime() / 1000; }
|
|
34
|
+
toString() { return super.toString(); }
|
|
35
|
+
}
|
|
36
|
+
const uint16 = binary.UINT16_LE;
|
|
37
|
+
const uint32 = binary.UINT32_LE;
|
|
38
|
+
const uint64 = binary.UINT64_LE;
|
|
39
|
+
const TIMEDATE = binary.as(uint32, MyDate);
|
|
40
|
+
//-----------------------------------------------------------------------------
|
|
41
|
+
// COFF
|
|
42
|
+
//-----------------------------------------------------------------------------
|
|
43
|
+
const DOS_HEADER = {
|
|
44
|
+
magic: uint16,
|
|
45
|
+
cblp: uint16,
|
|
46
|
+
cp: uint16,
|
|
47
|
+
crlc: uint16,
|
|
48
|
+
cparhdr: uint16,
|
|
49
|
+
minalloc: uint16,
|
|
50
|
+
maxalloc: binary.asHex(uint16),
|
|
51
|
+
ss: uint16,
|
|
52
|
+
sp: uint16,
|
|
53
|
+
csum: uint16,
|
|
54
|
+
ip: uint16,
|
|
55
|
+
cs: uint16,
|
|
56
|
+
lfarlc: uint16,
|
|
57
|
+
ovno: uint16,
|
|
58
|
+
};
|
|
59
|
+
const EXE_HEADER = {
|
|
60
|
+
res: binary.ArrayType(4, uint16),
|
|
61
|
+
oemid: uint16,
|
|
62
|
+
oeminfo: uint16,
|
|
63
|
+
res2: binary.ArrayType(10, uint16),
|
|
64
|
+
lfanew: binary.INT32_LE,
|
|
65
|
+
};
|
|
66
|
+
//-----------------------------------------------------------------------------
|
|
67
|
+
// PE
|
|
68
|
+
//-----------------------------------------------------------------------------
|
|
69
|
+
class pe_stream extends binary.stream {
|
|
70
|
+
pe;
|
|
71
|
+
constructor(pe, data) {
|
|
72
|
+
super(data);
|
|
73
|
+
this.pe = pe;
|
|
74
|
+
}
|
|
75
|
+
get_rva() { return this.pe.GetDataRVA(uint32.get(this))?.data; }
|
|
76
|
+
}
|
|
77
|
+
exports.pe_stream = pe_stream;
|
|
78
|
+
const RVA_STRING = {
|
|
79
|
+
get(s) { return binary.utils.decodeTextTo0(s.get_rva(), 'utf8'); },
|
|
80
|
+
put(_s) { }
|
|
81
|
+
};
|
|
82
|
+
const RVA_ARRAY16 = {
|
|
83
|
+
get(s) { return binary.utils.to16(s.get_rva()); },
|
|
84
|
+
put(_s) { }
|
|
85
|
+
};
|
|
86
|
+
const RVA_ARRAY32 = {
|
|
87
|
+
get(s) { return binary.utils.to32(s.get_rva()); },
|
|
88
|
+
put(_s) { }
|
|
89
|
+
};
|
|
90
|
+
const RVA_ARRAY64 = {
|
|
91
|
+
get(s) { return binary.utils.to64(s.get_rva()); },
|
|
92
|
+
put(_s) { }
|
|
93
|
+
};
|
|
94
|
+
const FILE_HEADER = {
|
|
95
|
+
Machine: uint16,
|
|
96
|
+
NumberOfSections: uint16,
|
|
97
|
+
TimeDateStamp: uint32,
|
|
98
|
+
PointerToSymbolTable: uint32,
|
|
99
|
+
NumberOfSymbols: uint32,
|
|
100
|
+
SizeOfOptionalHeader: uint16,
|
|
101
|
+
Characteristics: uint16,
|
|
102
|
+
};
|
|
103
|
+
const SECTION_CHARACTERISTICS = {
|
|
104
|
+
// 0x00000000,
|
|
105
|
+
// 0x00000001,
|
|
106
|
+
// 0x00000002,
|
|
107
|
+
// 0x00000004,
|
|
108
|
+
TYPE_NO_PAD: 0x00000008,
|
|
109
|
+
// 0x00000010,
|
|
110
|
+
CNT_CODE: 0x00000020,
|
|
111
|
+
CNT_INITIALIZED_DATA: 0x00000040,
|
|
112
|
+
CNT_UNINITIALIZED_DATA: 0x00000080,
|
|
113
|
+
LNK_OTHER: 0x00000100,
|
|
114
|
+
LNK_INFO: 0x00000200,
|
|
115
|
+
// 0x00000400,
|
|
116
|
+
LNK_REMOVE: 0x00000800,
|
|
117
|
+
LNK_COMDAT: 0x00001000,
|
|
118
|
+
GPREL: 0x00008000,
|
|
119
|
+
// MEM_PURGEABLE 0x00020000,
|
|
120
|
+
MEM_16BIT: 0x00020000,
|
|
121
|
+
MEM_LOCKED: 0x00040000,
|
|
122
|
+
MEM_PRELOAD: 0x00080000,
|
|
123
|
+
ALIGN: 0x00f00000,
|
|
124
|
+
//ALIGN_1BYTES 0x00100000,
|
|
125
|
+
//ALIGN_2BYTES 0x00200000,
|
|
126
|
+
//ALIGN_4BYTES 0x00300000,
|
|
127
|
+
//ALIGN_8BYTES 0x00400000,
|
|
128
|
+
//ALIGN_16BYTES 0x00500000,
|
|
129
|
+
//ALIGN_32BYTES 0x00600000,
|
|
130
|
+
//ALIGN_64BYTES 0x00700000,
|
|
131
|
+
//ALIGN_128BYTES 0x00800000,
|
|
132
|
+
//ALIGN_256BYTES 0x00900000,
|
|
133
|
+
//ALIGN_512BYTES 0x00A00000,
|
|
134
|
+
//ALIGN_1024BYTES 0x00B00000,
|
|
135
|
+
//ALIGN_2048BYTES 0x00C00000,
|
|
136
|
+
//ALIGN_4096BYTES 0x00D00000,
|
|
137
|
+
//ALIGN_8192BYTES 0x00E00000,
|
|
138
|
+
LNK_NRELOC_OVFL: 0x01000000,
|
|
139
|
+
MEM_DISCARDABLE: 0x02000000,
|
|
140
|
+
MEM_NOT_CACHED: 0x04000000,
|
|
141
|
+
MEM_NOT_PAGED: 0x08000000,
|
|
142
|
+
MEM_SHARED: 0x10000000,
|
|
143
|
+
MEM_EXECUTE: 0x20000000,
|
|
144
|
+
MEM_READ: 0x40000000,
|
|
145
|
+
MEM_WRITE: 0x80000000,
|
|
146
|
+
};
|
|
147
|
+
class Section extends binary.ReadClass({
|
|
148
|
+
Name: binary.StringType(8),
|
|
149
|
+
VirtualSize: uint32,
|
|
150
|
+
VirtualAddress: binary.asHex(uint32),
|
|
151
|
+
SizeOfRawData: uint32,
|
|
152
|
+
PointerToRawData: binary.asHex(uint32),
|
|
153
|
+
PointerToRelocations: binary.asHex(uint32),
|
|
154
|
+
PointerToLinenumbers: binary.asHex(uint32),
|
|
155
|
+
NumberOfRelocations: binary.INT16_LE,
|
|
156
|
+
NumberOfLinenumbers: binary.INT16_LE,
|
|
157
|
+
Characteristics: binary.asFlags(uint32, SECTION_CHARACTERISTICS)
|
|
158
|
+
}) {
|
|
159
|
+
data;
|
|
160
|
+
constructor(r) {
|
|
161
|
+
super(r);
|
|
162
|
+
try {
|
|
163
|
+
this.data = new binary.MappedMemory(r.buffer_at(+this.PointerToRawData, this.SizeOfRawData), +this.VirtualAddress, this.flags);
|
|
164
|
+
}
|
|
165
|
+
catch (e) {
|
|
166
|
+
console.log(e);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
get flags() {
|
|
170
|
+
return 8 /* binary.MEM.RELATIVE */
|
|
171
|
+
| (this.Characteristics.MEM_READ ? 1 /* binary.MEM.READ */ : 0)
|
|
172
|
+
| (this.Characteristics.MEM_WRITE ? 2 /* binary.MEM.WRITE */ : 0)
|
|
173
|
+
| (this.Characteristics.MEM_EXECUTE ? 4 /* binary.MEM.EXECUTE */ : 0);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
exports.DIRECTORIES = {
|
|
177
|
+
EXPORT: { read: (pe, data) => ReadExports(new pe_stream(pe, data.data)) },
|
|
178
|
+
IMPORT: { read: (pe, data) => ReadImports(new pe_stream(pe, data.data)) },
|
|
179
|
+
RESOURCE: { read: (pe, data) => ReadResourceDirectory(new binary.stream(data.data), data) },
|
|
180
|
+
EXCEPTION: {}, // Exception Directory
|
|
181
|
+
SECURITY: {}, // Security Directory
|
|
182
|
+
BASERELOC: {}, // Base Relocation Table
|
|
183
|
+
DEBUG_DIR: {}, // Debug Directory
|
|
184
|
+
ARCHITECTURE: {}, // Architecture Specific Data
|
|
185
|
+
GLOBALPTR: {}, // RVA of GP
|
|
186
|
+
TLS: {},
|
|
187
|
+
LOAD_CONFIG: {}, // Load Configuration Directory
|
|
188
|
+
BOUND_IMPORT: {}, // Bound Import Directory in headers
|
|
189
|
+
IAT: {}, // Import Address Table
|
|
190
|
+
DELAY_IMPORT: {},
|
|
191
|
+
CLR_DESCRIPTOR: {},
|
|
192
|
+
};
|
|
193
|
+
exports.DATA_DIRECTORY = {
|
|
194
|
+
VirtualAddress: uint32,
|
|
195
|
+
Size: uint32,
|
|
196
|
+
};
|
|
197
|
+
const MAGIC = {
|
|
198
|
+
NT32: 0x10b,
|
|
199
|
+
NT64: 0x20b,
|
|
200
|
+
ROM: 0x107,
|
|
201
|
+
OBJ: 0x104, // object files, eg as output
|
|
202
|
+
// DEMAND: 0x10b, // demand load format, eg normal ld output
|
|
203
|
+
TARGET: 0x101, // target shlib
|
|
204
|
+
HOST: 0x123, // host shlib
|
|
205
|
+
};
|
|
206
|
+
const DLLCHARACTERISTICS = {
|
|
207
|
+
DYNAMIC_BASE: 0x0040, // DLL can be relocated at load time (ASLR)
|
|
208
|
+
FORCE_INTEGRITY: 0x0080, // Code integrity checks are enforced
|
|
209
|
+
NX_COMPAT: 0x0100, // Image is NX compatible (DEP)
|
|
210
|
+
NO_ISOLATION: 0x0200, // Isolation aware, but do not isolate the image
|
|
211
|
+
NO_SEH: 0x0400, // Does not use structured exception handling
|
|
212
|
+
NO_BIND: 0x0800, // Do not bind the image
|
|
213
|
+
WDM_DRIVER: 0x2000, // Driver uses WDM model
|
|
214
|
+
TERMINAL_SERVER_AWARE: 0x8000, // Terminal Server aware
|
|
215
|
+
};
|
|
216
|
+
const OPTIONAL_HEADER = {
|
|
217
|
+
Magic: binary.asEnum(uint16, MAGIC),
|
|
218
|
+
MajorLinkerVersion: binary.UINT8,
|
|
219
|
+
MinorLinkerVersion: binary.UINT8,
|
|
220
|
+
SizeOfCode: uint32,
|
|
221
|
+
SizeOfInitializedData: uint32,
|
|
222
|
+
SizeOfUninitializedData: uint32,
|
|
223
|
+
AddressOfEntryPoint: binary.asHex(uint32),
|
|
224
|
+
BaseOfCode: binary.asHex(uint32),
|
|
225
|
+
};
|
|
226
|
+
const OPTIONAL_HEADER32 = {
|
|
227
|
+
BaseOfData: binary.asHex(uint32),
|
|
228
|
+
ImageBase: binary.asHex(uint32),
|
|
229
|
+
SectionAlignment: uint32,
|
|
230
|
+
FileAlignment: uint32,
|
|
231
|
+
MajorOperatingSystemVersion: uint16,
|
|
232
|
+
MinorOperatingSystemVersion: uint16,
|
|
233
|
+
MajorImageVersion: uint16,
|
|
234
|
+
MinorImageVersion: uint16,
|
|
235
|
+
MajorSubsystemVersion: uint16,
|
|
236
|
+
MinorSubsystemVersion: uint16,
|
|
237
|
+
Win32VersionValue: uint32,
|
|
238
|
+
SizeOfImage: uint32,
|
|
239
|
+
SizeOfHeaders: uint32,
|
|
240
|
+
CheckSum: uint32,
|
|
241
|
+
Subsystem: uint16,
|
|
242
|
+
DllCharacteristics: binary.asFlags(uint16, DLLCHARACTERISTICS),
|
|
243
|
+
SizeOfStackReserve: uint32,
|
|
244
|
+
SizeOfStackCommit: uint32,
|
|
245
|
+
SizeOfHeapReserve: uint32,
|
|
246
|
+
SizeOfHeapCommit: uint32,
|
|
247
|
+
LoaderFlags: uint32,
|
|
248
|
+
DataDirectory: binary.objectWithNames(binary.ArrayType(uint32, exports.DATA_DIRECTORY), binary.names(Object.keys(exports.DIRECTORIES))),
|
|
249
|
+
};
|
|
250
|
+
const OPTIONAL_HEADER64 = {
|
|
251
|
+
ImageBase: binary.asHex(uint64),
|
|
252
|
+
SectionAlignment: uint32,
|
|
253
|
+
FileAlignment: uint32,
|
|
254
|
+
MajorOperatingSystemVersion: uint16,
|
|
255
|
+
MinorOperatingSystemVersion: uint16,
|
|
256
|
+
MajorImageVersion: uint16,
|
|
257
|
+
MinorImageVersion: uint16,
|
|
258
|
+
MajorSubsystemVersion: uint16,
|
|
259
|
+
MinorSubsystemVersion: uint16,
|
|
260
|
+
Win32VersionValue: uint32,
|
|
261
|
+
SizeOfImage: uint32,
|
|
262
|
+
SizeOfHeaders: uint32,
|
|
263
|
+
CheckSum: uint32,
|
|
264
|
+
Subsystem: uint16,
|
|
265
|
+
DllCharacteristics: binary.asFlags(uint16, DLLCHARACTERISTICS),
|
|
266
|
+
SizeOfStackReserve: uint64,
|
|
267
|
+
SizeOfStackCommit: uint64,
|
|
268
|
+
SizeOfHeapReserve: uint64,
|
|
269
|
+
SizeOfHeapCommit: uint64,
|
|
270
|
+
LoaderFlags: uint32,
|
|
271
|
+
DataDirectory: binary.objectWithNames(binary.ArrayType(uint32, exports.DATA_DIRECTORY), binary.names(Object.keys(exports.DIRECTORIES))),
|
|
272
|
+
};
|
|
273
|
+
class PE {
|
|
274
|
+
data;
|
|
275
|
+
header;
|
|
276
|
+
opt;
|
|
277
|
+
sections;
|
|
278
|
+
static check(data) {
|
|
279
|
+
return uint16.get(new binary.stream(data)) === binary.utils.stringCode("MZ");
|
|
280
|
+
}
|
|
281
|
+
constructor(data) {
|
|
282
|
+
this.data = data;
|
|
283
|
+
const file = new binary.stream(data);
|
|
284
|
+
this.header = binary.read(file, { ...DOS_HEADER, ...EXE_HEADER });
|
|
285
|
+
file.seek(this.header.lfanew);
|
|
286
|
+
if (uint32.get(file) == binary.utils.stringCode("PE\0\0")) {
|
|
287
|
+
const h = binary.read(file, FILE_HEADER);
|
|
288
|
+
if (h.SizeOfOptionalHeader) {
|
|
289
|
+
const opt = new binary.stream(file.read_buffer(h.SizeOfOptionalHeader));
|
|
290
|
+
const opt1 = binary.read(opt, OPTIONAL_HEADER);
|
|
291
|
+
if (opt1.Magic == 'NT32')
|
|
292
|
+
this.opt = binary.read_more(opt, OPTIONAL_HEADER32, opt1);
|
|
293
|
+
else if (opt1.Magic == 'NT64')
|
|
294
|
+
this.opt = binary.read_more(opt, OPTIONAL_HEADER64, opt1);
|
|
295
|
+
}
|
|
296
|
+
this.sections = Array.from({ length: h.NumberOfSections }, () => new Section(file));
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
this.sections = [];
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
get directories() {
|
|
303
|
+
return this.opt?.DataDirectory;
|
|
304
|
+
}
|
|
305
|
+
FindSectionRVA(rva) {
|
|
306
|
+
for (const i of this.sections) {
|
|
307
|
+
if (rva >= +i.VirtualAddress && rva < +i.VirtualAddress + i.SizeOfRawData)
|
|
308
|
+
return i;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
FindSectionRaw(addr) {
|
|
312
|
+
for (const i of this.sections) {
|
|
313
|
+
if (addr >= +i.PointerToRawData && addr < +i.PointerToRawData + i.SizeOfRawData)
|
|
314
|
+
return i;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
GetDataRVA(rva, size) {
|
|
318
|
+
const sect = this.FindSectionRVA(rva);
|
|
319
|
+
if (sect && sect.data)
|
|
320
|
+
return sect.data.at(rva, size);
|
|
321
|
+
}
|
|
322
|
+
GetDataRaw(addr, size) {
|
|
323
|
+
const sect = this.FindSectionRaw(addr);
|
|
324
|
+
if (sect && sect.data) {
|
|
325
|
+
const offset = addr - +sect.PointerToRawData;
|
|
326
|
+
return sect.data.data.subarray(offset, offset + size);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
GetDataDir(dir) {
|
|
330
|
+
if (dir.Size)
|
|
331
|
+
return this.GetDataRVA(dir.VirtualAddress, dir.Size);
|
|
332
|
+
}
|
|
333
|
+
ReadDirectory(name) {
|
|
334
|
+
const dir = this.opt?.DataDirectory[name];
|
|
335
|
+
if (dir?.Size) {
|
|
336
|
+
const data = this.GetDataDir(dir);
|
|
337
|
+
const info = exports.DIRECTORIES[name];
|
|
338
|
+
if (data && info?.read)
|
|
339
|
+
return info.read(this, data);
|
|
340
|
+
return data;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
exports.PE = PE;
|
|
345
|
+
//-----------------------------------------------------------------------------
|
|
346
|
+
// exports
|
|
347
|
+
//-----------------------------------------------------------------------------
|
|
348
|
+
const EXPORT_DIRECTORY = {
|
|
349
|
+
ExportFlags: uint32, // Reserved, must be 0.
|
|
350
|
+
TimeDateStamp: TIMEDATE, // The time and date that the export data was created.
|
|
351
|
+
MajorVersion: binary.asHex(uint16), // The major version number. The major and minor version numbers can be set by the user.
|
|
352
|
+
MinorVersion: binary.asHex(uint16), // The minor version number.
|
|
353
|
+
DLLName: RVA_STRING, // The address of the ASCII string that contains the name of the DLL. This address is relative to the image base.
|
|
354
|
+
OrdinalBase: uint32, // The starting ordinal number for exports in this image. This field specifies the starting ordinal number for the export address table. It is usually set to 1.
|
|
355
|
+
NumberEntries: uint32, // The number of entries in the export address table.
|
|
356
|
+
NumberNames: uint32, // The number of entries in the name pointer table. This is also the number of entries in the ordinal table.
|
|
357
|
+
FunctionTable: RVA_ARRAY32, // RVA of functions
|
|
358
|
+
NameTable: RVA_ARRAY32, // RVA of names
|
|
359
|
+
OrdinalTable: RVA_ARRAY16, // RVA from base of image
|
|
360
|
+
};
|
|
361
|
+
function ReadExports(file) {
|
|
362
|
+
const dir = binary.read(file, EXPORT_DIRECTORY);
|
|
363
|
+
const addresses = dir.FunctionTable;
|
|
364
|
+
const names = dir.NameTable;
|
|
365
|
+
const ordinals = dir.OrdinalTable;
|
|
366
|
+
const result = [];
|
|
367
|
+
for (let i = 0; i < dir.NumberEntries; i++) {
|
|
368
|
+
const sect = file.pe.FindSectionRVA(addresses[i]);
|
|
369
|
+
if (sect) {
|
|
370
|
+
const ordinal = (ordinals && i < dir.NumberNames ? ordinals[i] : i) + dir.OrdinalBase;
|
|
371
|
+
const name = names && i < dir.NumberNames ? binary.utils.decodeTextTo0(file.pe.GetDataRVA(names[i])?.data, 'utf8') : '';
|
|
372
|
+
result.push({ ordinal, name, address: addresses[i] });
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const sorted = result.sort((a, b) => a.address - b.address);
|
|
376
|
+
return sorted.map((v, i) => {
|
|
377
|
+
let j = i;
|
|
378
|
+
while (++j < sorted.length && sorted[j].address == v.address)
|
|
379
|
+
;
|
|
380
|
+
return [v.ordinal, v.name, file.pe.GetDataRVA(v.address, j < sorted.length ? sorted[j].address - v.address : undefined)];
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
//-----------------------------------------------------------------------------
|
|
384
|
+
// imports
|
|
385
|
+
//-----------------------------------------------------------------------------
|
|
386
|
+
class DLLImports extends Array {
|
|
387
|
+
}
|
|
388
|
+
exports.DLLImports = DLLImports;
|
|
389
|
+
const RVA_ITA64 = {
|
|
390
|
+
get(s) {
|
|
391
|
+
const r = binary.utils.to64(s.get_rva());
|
|
392
|
+
if (r) {
|
|
393
|
+
const result = Array.from(r.subarray(0, r.indexOf(0n)), i => i >> 63n
|
|
394
|
+
? `ordinal_${i - (1n << 63n)}`
|
|
395
|
+
: binary.utils.decodeTextTo0(s.pe.GetDataRVA(Number(i))?.data.subarray(2), 'utf8'));
|
|
396
|
+
Object.setPrototypeOf(result, DLLImports.prototype);
|
|
397
|
+
return result;
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
put(_s) { }
|
|
401
|
+
};
|
|
402
|
+
const IMPORT_DESCRIPTOR = {
|
|
403
|
+
Characteristics: uint32, // 0 for terminating null import descriptor
|
|
404
|
+
TimeDateStamp: TIMEDATE, // 0 if not bound, -1 if bound, and real date\time stamp in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) // O.W. date/time stamp of DLL bound to (Old BIND)
|
|
405
|
+
ForwarderChain: uint32, // -1 if no forwarders
|
|
406
|
+
DllName: RVA_STRING, //uint32,
|
|
407
|
+
FirstThunk: RVA_ITA64, //uint32, // RVA to IAT (if bound this IAT has actual addresses)
|
|
408
|
+
};
|
|
409
|
+
function ReadImports(file) {
|
|
410
|
+
const result = [];
|
|
411
|
+
while (file.remaining()) {
|
|
412
|
+
const r = binary.read(file, IMPORT_DESCRIPTOR);
|
|
413
|
+
if (!r.Characteristics)
|
|
414
|
+
break;
|
|
415
|
+
result.push([r.DllName, r.FirstThunk]);
|
|
416
|
+
}
|
|
417
|
+
return result;
|
|
418
|
+
}
|
|
419
|
+
//-----------------------------------------------------------------------------
|
|
420
|
+
// resources
|
|
421
|
+
//-----------------------------------------------------------------------------
|
|
422
|
+
class RESOURCE_DATA_ENTRY extends binary.ReadClass({
|
|
423
|
+
OffsetToData: uint32,
|
|
424
|
+
Size: uint32,
|
|
425
|
+
CodePage: uint32,
|
|
426
|
+
Reserved: uint32,
|
|
427
|
+
}) {
|
|
428
|
+
data;
|
|
429
|
+
constructor(file, data) {
|
|
430
|
+
super(file);
|
|
431
|
+
this.data = data.slice(this.OffsetToData, this.OffsetToData + this.Size).data;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
const RESOURCE_DIRECTORY = {
|
|
435
|
+
Characteristics: uint32,
|
|
436
|
+
TimeDateStamp: uint32,
|
|
437
|
+
MajorVersion: uint16,
|
|
438
|
+
MinorVersion: uint16,
|
|
439
|
+
NumberOfNamedEntries: uint16,
|
|
440
|
+
NumberOfIdEntries: uint16,
|
|
441
|
+
entries: binary.ArrayType(obj => obj.NumberOfNamedEntries + obj.NumberOfIdEntries, {
|
|
442
|
+
u0: uint32,
|
|
443
|
+
u1: uint32,
|
|
444
|
+
})
|
|
445
|
+
};
|
|
446
|
+
const IRT = {
|
|
447
|
+
0: 'NONE',
|
|
448
|
+
1: 'CURSOR',
|
|
449
|
+
2: 'BITMAP',
|
|
450
|
+
3: 'ICON',
|
|
451
|
+
4: 'MENU',
|
|
452
|
+
5: 'DIALOG',
|
|
453
|
+
6: 'STRING',
|
|
454
|
+
7: 'FONTDIR',
|
|
455
|
+
8: 'FONT',
|
|
456
|
+
9: 'ACCELERATOR',
|
|
457
|
+
10: 'RCDATA',
|
|
458
|
+
11: 'MESSAGETABLE',
|
|
459
|
+
12: 'GROUP_CURSOR',
|
|
460
|
+
14: 'GROUP_ICON',
|
|
461
|
+
16: 'VERSION',
|
|
462
|
+
17: 'DLGINCLUDE',
|
|
463
|
+
19: 'PLUGPLAY',
|
|
464
|
+
20: 'VXD',
|
|
465
|
+
21: 'ANICURSOR',
|
|
466
|
+
22: 'ANIICON',
|
|
467
|
+
23: 'HTML',
|
|
468
|
+
24: 'MANIFEST',
|
|
469
|
+
241: 'TOOLBAR',
|
|
470
|
+
};
|
|
471
|
+
function ReadResourceDirectory(file, data, type = 0) {
|
|
472
|
+
const dir = binary.read(file, RESOURCE_DIRECTORY);
|
|
473
|
+
const id_type = binary.StringType(uint16, 'utf16le');
|
|
474
|
+
const topbit = 0x80000000;
|
|
475
|
+
const result = {};
|
|
476
|
+
for (const i of dir.entries) {
|
|
477
|
+
const id = i.u0 & topbit ? id_type.get(file.seek(i.u0 & ~topbit)) : !type ? IRT[i.u0] : i.u0;
|
|
478
|
+
file.seek(i.u1 & ~topbit);
|
|
479
|
+
result[id] = i.u1 & topbit
|
|
480
|
+
? ReadResourceDirectory(file, data, type || i.u0)
|
|
481
|
+
: new RESOURCE_DATA_ENTRY(file, data);
|
|
482
|
+
}
|
|
483
|
+
return result;
|
|
484
|
+
}
|
package/package.json
CHANGED
|
@@ -9,11 +9,14 @@
|
|
|
9
9
|
"./mach": "./dist/mach.js",
|
|
10
10
|
"./pe": "./dist/pe.js"
|
|
11
11
|
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
12
16
|
"scripts": {
|
|
13
17
|
"build": "tsc",
|
|
14
18
|
"lint": "eslint \"src/**/*.ts\"",
|
|
15
|
-
"test": "echo \"No tests specified\" && exit 0"
|
|
16
|
-
"postinstall": "ts-patch install"
|
|
19
|
+
"test": "echo \"No tests specified\" && exit 0"
|
|
17
20
|
},
|
|
18
21
|
"keywords": [
|
|
19
22
|
"binary",
|
|
@@ -37,5 +40,5 @@
|
|
|
37
40
|
"dependencies": {
|
|
38
41
|
"@isopodlabs/binary": "^1.0.3"
|
|
39
42
|
},
|
|
40
|
-
"version": "0.1.
|
|
43
|
+
"version": "0.1.2"
|
|
41
44
|
}
|
package/.gitmodules
DELETED
package/.vscode/launch.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// Use IntelliSense to learn about possible attributes.
|
|
3
|
-
// Hover to view descriptions of existing attributes.
|
|
4
|
-
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
-
"version": "0.2.0",
|
|
6
|
-
"configurations": [
|
|
7
|
-
|
|
8
|
-
{
|
|
9
|
-
"type": "node-terminal",
|
|
10
|
-
"name": "Run Script: build",
|
|
11
|
-
"request": "launch",
|
|
12
|
-
"command": "npm run build",
|
|
13
|
-
"cwd": "${workspaceFolder}"
|
|
14
|
-
}
|
|
15
|
-
]
|
|
16
|
-
}
|
package/.vscode/settings.json
DELETED