@isopodlabs/binary_libs 0.0.1 → 0.1.0

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/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "node_modules/@isopodlabs/binary"]
2
+ path = node_modules/@isopodlabs/binary
3
+ url = https://github.com/adrianstephens/binary.git
@@ -0,0 +1,16 @@
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
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "eslint.lintTask.enable": false
3
+ }
package/README.md CHANGED
@@ -1,60 +1,168 @@
1
- # my-binary-package/my-binary-package/README.md
1
+ # Binary Libs
2
2
 
3
- # My Binary Package
3
+ This package provides readers for various library formats, using the @isopodlabs/binary binary file loading library
4
4
 
5
- This package provides a set of utilities for reading and writing binary data in TypeScript. It includes various interfaces, types, and functions to facilitate binary data manipulation.
6
5
 
7
- ## Installation
6
+ ## Supported File Types
8
7
 
9
- To install the package, use npm:
8
+ ### elf
9
+ ELF
10
+ ```typescript
11
+ class ELFFile {
12
+ segments: [string, any][];
13
+ sections: [string, any][];
14
+ symbols?: [string, any][];
15
+ dynamic_symbols?: [string, any][];
16
+ header: any;
17
+ static check(data: Uint8Array): boolean;
18
+ constructor(data: Uint8Array);
19
+ getSymbols(type: binary.Type, data: Uint8Array, names: Uint8Array): [string, any][];
20
+ }
10
21
 
11
22
  ```
12
- npm install my-binary-package
13
- ```
14
-
15
- ## Usage
16
-
17
- Here is a basic example of how to use the package:
18
23
 
24
+ ### pe
25
+ Portable Executable
19
26
  ```typescript
20
- import { stream, ReadStruct, WriteStruct } from 'my-binary-package';
21
-
22
- // Create a new stream from a Uint8Array
23
- const data = new Uint8Array([/* binary data */]);
24
- const binaryStream = new stream(data);
25
-
26
- // Define a structure to read from the stream
27
- const MyStruct = ReadStruct({
28
- // Define your structure here
29
- });
30
-
31
- // Read data from the stream
32
- const myData = new MyStruct(binaryStream);
33
-
34
- // Write data back to the stream
35
- const writeStream = new stream(new Uint8Array(1024));
36
- const myWriteStruct = WriteStruct({
37
- // Define your structure here
38
- });
39
- myWriteStruct.put(writeStream, myData);
27
+ class PE {
28
+ static check(data: Uint8Array): boolean;
29
+ constructor(data: Uint8Array);
30
+ get directories(): {
31
+ [k: string]: any;
32
+ } | undefined;
33
+ FindSectionRVA(rva: number): Section | undefined;
34
+ FindSectionRaw(addr: number): Section | undefined;
35
+ GetDataRVA(rva: number, size?: number): binary.utils.MappedMemory | undefined;
36
+ GetDataRaw(addr: number, size: number): Uint8Array | undefined;
37
+ GetDataDir(dir: { VirtualAddress: number; Size: number; } & {}): binary.utils.MappedMemory | undefined;
38
+ ReadDirectory(name: string): any;
39
+ }
40
40
  ```
41
41
 
42
- ## Key Features
43
-
44
- - **Interfaces**:
45
- - `_stream`: Base interface for stream handling.
46
- - `TypeReaderT`, `TypeWriterT`, `TypeT`: Types for reading and writing binary data.
47
- - `ReadType`: Type for reading structured data.
48
-
49
- - **Functions**:
50
- - `ReadStruct`: Create a reader for a specific structure.
51
- - `WriteStruct`: Create a writer for a specific structure.
52
- - `read`, `write`: Functions for reading and writing binary data.
42
+ ### clr
43
+ Common Language Runtime (embedded in pe files)
44
+ ```typescript
45
+ class CLR {
46
+ header: any;
47
+ table_info: any;
48
+ heaps: Uint8Array[];
49
+ tables: Record<TABLE, Table>;
50
+ raw?: Uint8Array;
51
+ Resources?: Uint8Array;
52
+ constructor(pe: pe.PE, clr_data: Uint8Array);
53
+ getEntry(t: TABLE, i: number): any;
54
+ getTable(t: TABLE.Module): ({ generation: number; name: string; mvid: string; encid: string; encbaseid: string; } & {})[];
55
+ getTable(t: TABLE.TypeRef): ({ scope: number; name: string; namespce: string; } & {})[];
56
+ getTable(t: TABLE.TypeDef): ({ flags: number; name: string; namespce: string; extends: number; fields: number; methods: number; } & {})[];
57
+ getTable(t: TABLE.Field): ({ flags: number; name: string; signature: Uint8Array; } & {})[];
58
+ getTable(t: TABLE.MethodDef): ({ code: number; implflags: number; flags: number; name: string; signature: Uint8Array; paramlist: number; } & {})[];
59
+ getTable(t: TABLE.Param): ({ flags: number; sequence: number; name: string; } & {})[];
60
+ getTable(t: TABLE.InterfaceImpl): ({ clss: number; interfce: number; } & {})[];
61
+ getTable(t: TABLE.MemberRef): ({ clss: number; name: string; signature: Uint8Array; } & {})[];
62
+ getTable(t: TABLE.Constant): ({ type: number; parent: number; value: Uint8Array; } & {})[];
63
+ getTable(t: TABLE.CustomAttribute): ({ parent: number; type: number; value: Uint8Array; } & {})[];
64
+ getTable(t: TABLE.FieldMarshal): ({ parent: number; native_type: Uint8Array; } & {})[];
65
+ getTable(t: TABLE.DeclSecurity): ({ action: number; parent: number; permission_set: Uint8Array; } & {})[];
66
+ getTable(t: TABLE.ClassLayout): ({ packing_size: number; class_size: number; parent: number; } & {})[];
67
+ getTable(t: TABLE.FieldLayout): ({ offset: number; field: number; } & {})[];
68
+ getTable(t: TABLE.StandAloneSig): ({ signature: Uint8Array; } & {})[];
69
+ getTable(t: TABLE.EventMap): ({ parent: number; event_list: number; } & {})[];
70
+ getTable(t: TABLE.Event): ({ flags: number; name: string; event_type: number; } & {})[];
71
+ getTable(t: TABLE.PropertyMap): ({ parent: number; property_list: number; } & {})[];
72
+ getTable(t: TABLE.Property): ({ flags: number; name: string; type: Uint8Array; } & {})[];
73
+ getTable(t: TABLE.MethodSemantics): ({ flags: number; method: number; association: number; } & {})[];
74
+ getTable(t: TABLE.MethodImpl): ({ clss: number; method_body: number; method_declaration: number; } & {})[];
75
+ getTable(t: TABLE.ModuleRef): ({ name: string; } & {})[];
76
+ getTable(t: TABLE.TypeSpec): ({ signature: Uint8Array; } & {})[];
77
+ getTable(t: TABLE.ImplMap): ({ flags: number; member_forwarded: number; name: string; scope: number; } & {})[];
78
+ getTable(t: TABLE.FieldRVA): ({ rva: number; field: number; } & {})[];
79
+ getTable(t: TABLE.Assembly): ({ hashalg: number; major: number; minor: number; build: number; rev: number; flags: number; publickey: Uint8Array; name: string; culture: string; } & {})[];
80
+ getTable(t: TABLE.AssemblyProcessor): ({ processor: number; } & {})[];
81
+ getTable(t: TABLE.AssemblyOS): ({ platform: number; minor: number; major: number; } & {})[];
82
+ getTable(t: TABLE.AssemblyRef): ({ major: number; minor: number; build: number; rev: number; flags: number; publickey: Uint8Array; name: string; culture: string; hashvalue: Uint8Array; } & {})[];
83
+ getTable(t: TABLE.AssemblyRefProcessor): ({ processor: number; assembly: number; } & {})[];
84
+ getTable(t: TABLE.AssemblyRefOS): ({ platform: number; major: number; minor: number; assembly: number; } & {})[];
85
+ getTable(t: TABLE.File): ({ flags: number; name: string; hash: Uint8Array; } & {})[];
86
+ getTable(t: TABLE.ExportedType): ({ flags: number; typedef_id: number; name: string; namespce: string; implementation: number; } & {})[];
87
+ getTable(t: TABLE.ManifestResource): ({ data: number; flags: number; name: string; implementation: number; } & {})[];
88
+ getTable(t: TABLE.NestedClass): ({ nested_class: number; enclosing_class: number; } & {})[];
89
+ getTable(t: TABLE.GenericParam): ({ number: number; flags: number; owner: number; name: string; } & {})[];
90
+ getTable(t: TABLE.MethodSpec): ({ method: number; instantiation: Uint8Array; } & {})[];
91
+ getTable(t: TABLE.GenericParamConstraint): ({ owner: number; constraint: number; } & {})[];
92
+ getResources(block: string): Record<string, any> | undefined;
93
+ getResource(block: string, name: string): any;
94
+ allResources(): {} | undefined;
95
+ }
96
+ ```
97
+ ### mach
98
+ Apple libraries
99
+ ```typescript
100
+ declare function segment(bits: 32 | 64): {
101
+ get(s: mach_stream): Promise<{
102
+ data: binary.utils.MappedMemory | undefined;
103
+ segname: string;
104
+ vmaddr: number | bigint;
105
+ vmsize: number | bigint;
106
+ fileoff: number | bigint;
107
+ filesize: number | bigint;
108
+ maxprot: number;
109
+ initprot: number;
110
+ nsects: number;
111
+ flags: Record<string, bigint | boolean> | Record<string, number | boolean>;
112
+ sections: Record<string, any> | undefined;
113
+ } & {}>;
114
+ };
115
+ export declare class MachFile {
116
+ header: any;
117
+ commands: { cmd: CMD; data: any; }[];
118
+ ready: Promise<void>;
119
+ static check(data: Uint8Array): boolean;
120
+ constructor(data: Uint8Array, mem?: binary.utils.memory);
121
+ load(data: Uint8Array, be: boolean, bits: 32 | 64, mem?: binary.utils.memory): Promise<void>;
122
+ getCommand(cmd: number): any;
123
+ getSegment(name: string): Promise<{ data: binary.utils.MappedMemory | undefined; segname: string; vmaddr: number | bigint; vmsize: number | bigint; fileoff: number | bigint; filesize: number | bigint; maxprot: number; initprot: number; nsects: number; flags: Record<string, bigint | boolean> | Record<string, number | boolean>; sections: Record<string, any> | undefined; } & {}> | undefined;
124
+ }
125
+ class FATMachFile {
126
+ archs: ({ cputype: string; cpusubtype: string | number; offset: number; size: number; align: number; contents: MachFile | undefined; } & {})[];
127
+ static check(data: Uint8Array): boolean;
128
+ constructor(data: Uint8Array, mem?: binary.utils.memory);
129
+ load(file: binary.stream_endian, mem?: binary.utils.memory): void;
130
+ }
131
+ ```
53
132
 
54
- ## Contributing
133
+ ### arch
134
+ Archive files for static linking
55
135
 
56
- Contributions are welcome! Please open an issue or submit a pull request for any enhancements or bug fixes.
136
+ ```typescript
137
+ type HEADER = {
138
+ name: string;
139
+ date: number;
140
+ uid: number;
141
+ gid: number;
142
+ mode: number;
143
+ size: number;
144
+ fmag: string;
145
+ contents: any;
146
+ };
147
+ declare class ArchFile {
148
+ members: HEADER[];
149
+ static check(data: Uint8Array): boolean;
150
+ constructor(data: Uint8Array);
151
+ }
152
+ ```
57
153
 
154
+ ### CompoundDocument
155
+ Not a library format at all, but useful for loading some related files
156
+ ```typescript
157
+ class Reader {
158
+ entries: DirEntry[];
159
+ private entry_chain;
160
+ constructor(sectors: Uint8Array, header: Header);
161
+ find(name: string, i?: number): DirEntry | undefined;
162
+ read(e: DirEntry): Uint8Array;
163
+ write(e: DirEntry, data: Uint8Array): void;
164
+ }
165
+ ```
58
166
  ## License
59
167
 
60
168
  This project is licensed under the MIT License. See the LICENSE file for more details.
@@ -0,0 +1,32 @@
1
+ // @ts-check
2
+ import eslint from "@eslint/js";
3
+ import tslint from "typescript-eslint";
4
+
5
+ export default tslint.config(
6
+ eslint.configs.recommended,
7
+ ...tslint.configs.recommended,
8
+ ...tslint.configs.stylistic,
9
+ {
10
+ rules: {
11
+ "semi": ["error", "always"], // Add this line to enforce semicolon use
12
+ "no-empty": "off",
13
+ //"@typescript-eslint/no-misleading-character-class": "off",
14
+ //"@typescript-eslint/no-this-alias": "off",
15
+ "@typescript-eslint/no-unused-vars": [
16
+ "warn", {
17
+ argsIgnorePattern: "^(_+$|_[^_])",
18
+ varsIgnorePattern: "^(_+$|_[^_])",
19
+ },
20
+ ],
21
+ "@typescript-eslint/no-explicit-any": "off",
22
+ //"@typescript-eslint/explicit-module-boundary-types": "off",
23
+ //"@typescript-eslint/no-non-null-assertion": "off"
24
+ "@typescript-eslint/no-empty-function": "off",
25
+ "@typescript-eslint/consistent-indexed-object-style": "off",
26
+ "@typescript-eslint/consistent-type-definitions": "off"
27
+ },
28
+ },
29
+ {
30
+ files: ["src/*.ts"],
31
+ }
32
+ );
package/package.json CHANGED
@@ -11,7 +11,9 @@
11
11
  },
12
12
  "scripts": {
13
13
  "build": "tsc",
14
- "test": "echo \"No tests specified\" && exit 0"
14
+ "lint": "eslint \"src/**/*.ts\"",
15
+ "test": "echo \"No tests specified\" && exit 0",
16
+ "postinstall": "ts-patch install"
15
17
  },
16
18
  "keywords": [
17
19
  "binary",
@@ -24,10 +26,16 @@
24
26
  "license": "MIT",
25
27
  "devDependencies": {
26
28
  "@types/node": "^22.13.8",
27
- "typescript": "^4.0.0"
29
+ "@typescript-eslint/eslint-plugin": "^8.26.0",
30
+ "@typescript-eslint/parser": "^8.26.0",
31
+ "eslint": "^9.21.0",
32
+ "ts-node": "^10.9.2",
33
+ "ts-patch": "^3.3.0",
34
+ "typescript": "~5.5.0",
35
+ "typescript-eslint": "^8.26.0"
28
36
  },
29
37
  "dependencies": {
30
38
  "@isopodlabs/binary": "^1.0.3"
31
39
  },
32
- "version": "0.0.1"
40
+ "version": "0.1.0"
33
41
  }
@@ -14,7 +14,7 @@ class FAT {
14
14
  dirty_fat = new Set<number>();
15
15
  dirty_sec = new Set<number>();
16
16
 
17
- constructor(size: number, public shift:number, public sectors: Uint8Array) {
17
+ constructor(size: number, public shift: number, public sectors: Uint8Array) {
18
18
  this.fat = new Int32Array(size);
19
19
  }
20
20
 
@@ -99,7 +99,7 @@ class FAT {
99
99
 
100
100
  }
101
101
 
102
- export class Header extends binary.ReadWriteStruct({
102
+ export class Header extends binary.Class({
103
103
  magic: binary.UINT64_BE,
104
104
  id: binary.Buffer(16),
105
105
  revision: binary.UINT16_LE,
@@ -137,7 +137,7 @@ const COLOUR = {
137
137
  RED: 0, BLACK: 1
138
138
  } as const;
139
139
 
140
- class DirEntry extends binary.ReadWriteStruct({
140
+ class DirEntry extends binary.Class({
141
141
  name: binary.StringType(64, 'utf16le'),
142
142
  name_size: binary.UINT16_LE,
143
143
  type: binary.UINT8,
@@ -164,7 +164,7 @@ class DirEntry extends binary.ReadWriteStruct({
164
164
  }
165
165
  }
166
166
 
167
- export class Master {
167
+ class Master {
168
168
  difat: Int32Array;
169
169
  fat: FAT;
170
170
  mini_fat: FAT;
@@ -259,7 +259,7 @@ export class Reader extends Master {
259
259
  this.entries[i] = new DirEntry(i, r2.seek(i * 128));
260
260
  }
261
261
 
262
- find(name: string, i: number = 0): DirEntry|undefined {
262
+ find(name: string, i = 0): DirEntry|undefined {
263
263
  const stack: number[] = [];
264
264
  let sp = 0;
265
265
 
package/src/arch.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  import * as binary from '@isopodlabs/binary';
2
2
 
3
- const AR_MEMBER_HEADER = {
4
- name: binary.as(binary.StringType(16), x => { x = x.trim(); return x.endsWith('/') ? x.slice(0, -1) : x; }),
3
+ const _HEADER = {
4
+ name: binary.as(binary.StringType(16), x => {
5
+ x = x.trim();
6
+ return x.endsWith('/') ? x.slice(0, -1) : x;
7
+ }),
5
8
  date: binary.asInt(binary.StringType(12)),
6
9
  uid: binary.asInt(binary.StringType(6)),
7
10
  gid: binary.asInt(binary.StringType(6)),
@@ -11,17 +14,18 @@ const AR_MEMBER_HEADER = {
11
14
  contents: binary.DontRead<any>()
12
15
  };
13
16
 
14
- const AR_SYM64 = {
17
+ export type HEADER = binary.ReadType<typeof _HEADER>;
18
+
19
+ const SYM64 = {
15
20
  name: binary.StringType(12),
16
21
  offset: binary.asInt(binary.StringType(4))
17
22
  };
18
23
 
19
24
  export class ArchFile {
20
- members: binary.ReadType<typeof AR_MEMBER_HEADER>[] = [];
25
+ members: HEADER[] = [];
21
26
 
22
27
  static check(data: Uint8Array): boolean {
23
- const x = binary.utils.decodeText(data.subarray(0, 8), 'utf8');
24
- return x == '!<arch>\n';
28
+ return binary.utils.decodeText(data.subarray(0, 8), 'utf8') == '!<arch>\n';
25
29
  }
26
30
  constructor(data: Uint8Array) {
27
31
  const s = new binary.stream(data);
@@ -32,7 +36,7 @@ export class ArchFile {
32
36
 
33
37
  let long_names;
34
38
  while (s.remaining() > 0) {
35
- const member = binary.read(s, AR_MEMBER_HEADER);
39
+ const member = binary.read(s, _HEADER);
36
40
  const data = s.read_buffer(member.size);
37
41
  s.align(2);
38
42
 
@@ -46,8 +50,8 @@ export class ArchFile {
46
50
  }
47
51
 
48
52
  if (member.name == '') {
49
- const s2 = new binary.stream(data);
50
- const offsets = binary.ArrayType(binary.INT32_BE, binary.INT32_BE).get(s2);
53
+ const s2 = new binary.stream(data);
54
+ const offsets = binary.ArrayType(binary.INT32_BE, binary.INT32_BE).get(s2);
51
55
  member.name = 'Symbols';
52
56
  member.contents = offsets.map(offset => [
53
57
  binary.NullTerminatedStringType.get(s2),
@@ -55,9 +59,8 @@ export class ArchFile {
55
59
  ]);
56
60
 
57
61
  } else if (member.name == '/SYM') {
58
- const s2 = new binary.stream(data);
59
- const syms = binary.ArrayType(binary.INT32_BE, binary.NullTerminatedStringType).get(s2);
60
-
62
+ const s2 = new binary.stream(data);
63
+ const syms = binary.ArrayType(binary.INT32_BE, binary.NullTerminatedStringType).get(s2);
61
64
  member.contents = syms.map(name => ({
62
65
  name,
63
66
  offset: binary.INT32_BE.get(s2)
@@ -65,7 +68,7 @@ export class ArchFile {
65
68
 
66
69
  } else if (member.name == '/SYM64') {
67
70
  const s2 = new binary.stream(data);
68
- member.contents = binary.RemainingArrayType(AR_SYM64).get(s2);
71
+ member.contents = binary.RemainingArrayType(SYM64).get(s2);
69
72
 
70
73
  } else {
71
74
  member.contents = data;
package/src/clr.ts CHANGED
@@ -26,7 +26,7 @@ const CLR_HEADER = {
26
26
  MajorRuntimeVersion: binary.UINT16_LE,
27
27
  MinorRuntimeVersion: binary.UINT16_LE,
28
28
  MetaData: pe.DATA_DIRECTORY,
29
- Flags: binary.UINT32_LE,
29
+ Flags: binary.asFlags(binary.UINT32_LE, CLR_FLAGS),
30
30
  EntryPoint: binary.UINT32_LE,
31
31
  Resources: pe.DATA_DIRECTORY,
32
32
  StrongNameSignature: pe.DATA_DIRECTORY,
@@ -185,16 +185,16 @@ class clr_dummy extends binary.dummy {
185
185
  }
186
186
 
187
187
  const clr_String = {
188
- get(s: clr_stream) { return s.getString(); },
189
- put(s: clr_stream, v : number) {}
188
+ get(s: clr_stream) { return s.getString(); },
189
+ put(_s: clr_stream, _v : number) {}
190
190
  };
191
191
  const clr_GUID = {
192
- get(s: clr_stream) { return s.getGUID(); },
193
- put(s: clr_stream, v : number) {}
192
+ get(s: clr_stream) { return s.getGUID(); },
193
+ put(_s: clr_stream, _v : number) {}
194
194
  };
195
195
  const clr_Blob = {
196
- get(s: clr_stream) { return s.getBlob(); },
197
- put(s: clr_stream, v : number) {}
196
+ get(s: clr_stream) { return s.getBlob(); },
197
+ put(_s: clr_stream, _v : number) {}
198
198
  };
199
199
  const Signature = clr_Blob;
200
200
  const CustomAttributeValue = clr_Blob;
@@ -429,7 +429,7 @@ const ENTRY_GenericParamConstraint = {
429
429
  constraint: TypeDefOrRef,
430
430
  };
431
431
 
432
- const TableReaders : Record<TABLE, any> = {
432
+ const TableReaders = {
433
433
  [TABLE.Module]: ENTRY_Module,
434
434
  [TABLE.TypeRef]: ENTRY_TypeRef,
435
435
  [TABLE.TypeDef]: ENTRY_TypeDef,
@@ -476,14 +476,12 @@ const ResourceManagerHeader = {
476
476
  skip: binary.UINT32_LE,
477
477
  };
478
478
 
479
- const pascal_string = binary.StringType(binary.UINT8);
480
-
481
479
  const ResourceManager = {
482
- reader: pascal_string,// Class name of IResourceReader to parse this file
483
- set: pascal_string,// Class name of ResourceSet to parse this file
480
+ reader: binary.StringType(binary.UINT8),// Class name of IResourceReader to parse this file
481
+ set: binary.StringType(binary.UINT8),// Class name of ResourceSet to parse this file
484
482
  version: binary.UINT32_LE,
485
483
  num_resources: binary.UINT32_LE,
486
- types: binary.ArrayType(binary.UINT32_LE, pascal_string),
484
+ types: binary.ArrayType(binary.UINT32_LE, binary.StringType(binary.UINT8)),
487
485
  };
488
486
 
489
487
  const ResourceEntry = {
@@ -497,7 +495,7 @@ export class CLR {
497
495
  header: any;
498
496
  table_info: any;
499
497
  heaps: Uint8Array[] = [];
500
- tables: {[K in TABLE]?: Table} = {};
498
+ tables!: Record<TABLE, Table>;
501
499
  raw?: Uint8Array;
502
500
  Resources?: Uint8Array;
503
501
  /*
@@ -511,56 +509,50 @@ export class CLR {
511
509
  }
512
510
  */
513
511
  constructor(pe: pe.PE, clr_data: Uint8Array) {
514
- try {
515
- this.header = binary.read(new binary.stream(clr_data), CLR_HEADER);
516
- const meta_data = pe.GetDataDir(this.header.MetaData);
517
- const meta_root = meta_data && binary.read(new binary.stream(meta_data.data), METADATA_ROOT);
518
-
519
- if (meta_root?.Signature != binary.utils.stringCode('BSJB'))
520
- console.log("oops");
521
-
522
- let table_data;
523
-
524
- for (const h of meta_root!.Streams) {
525
- const mem = meta_data!.data.subarray(h.Offset, h.Offset + h.Size);
526
- switch (h.Name) {
527
- case "#~": table_data = mem; break;
528
- case "#Strings": this.heaps[HEAP.String] = mem; break;
529
- case "#US": this.heaps[HEAP.UserString] = mem; break;
530
- case "#GUID": this.heaps[HEAP.GUID] = mem; break;
531
- case "#Blob": this.heaps[HEAP.Blob] = mem; break;
532
- }
512
+ this.header = binary.read(new binary.stream(clr_data), CLR_HEADER);
513
+ const meta_data = pe.GetDataDir(this.header.MetaData);
514
+ const meta_root = meta_data && binary.read(new binary.stream(meta_data.data), METADATA_ROOT);
515
+
516
+ if (meta_root?.Signature != binary.utils.stringCode('BSJB'))
517
+ throw new Error("Invalid CLR");
518
+
519
+ let table_data;
520
+
521
+ for (const h of meta_root!.Streams) {
522
+ const mem = meta_data!.data.subarray(h.Offset, h.Offset + h.Size);
523
+ switch (h.Name) {
524
+ case "#~": table_data = mem; break;
525
+ case "#Strings": this.heaps[HEAP.String] = mem; break;
526
+ case "#US": this.heaps[HEAP.UserString] = mem; break;
527
+ case "#GUID": this.heaps[HEAP.GUID] = mem; break;
528
+ case "#Blob": this.heaps[HEAP.Blob] = mem; break;
533
529
  }
530
+ }
534
531
 
535
- if (table_data) {
536
- const stream = new binary.stream(table_data);
537
- this.table_info = binary.read(stream, CLR_TABLES);
538
- const table_counts: number[] = [];
532
+ if (table_data) {
533
+ const stream = new binary.stream(table_data);
534
+ this.table_info = binary.read(stream, CLR_TABLES);
535
+ const table_counts: number[] = [];
539
536
 
540
- //read counts
541
- for (let b = this.table_info.Valid; b; b = binary.utils.clearLowest(b)) {
542
- const i = binary.utils.lowestSetIndex(b);
543
- table_counts[i] = binary.UINT32_LE.get(stream);
544
- }
537
+ //read counts
538
+ for (let b = this.table_info.Valid; b; b = binary.utils.clearLowest(b)) {
539
+ const i = binary.utils.lowestSetIndex(b);
540
+ table_counts[i] = binary.UINT32_LE.get(stream);
541
+ }
545
542
 
546
- this.raw = stream.remainder();
547
- //const stream2 = new clr_stream(stream.remainder(), this.heaps, table_info.HeapSizes, this.tables.map(i => i.count));
548
- const stream1 = new clr_dummy(this.table_info.HeapSizes, table_counts);
549
- let offset = 0;
550
-
551
- for (let b = this.table_info.Valid; b; b = binary.utils.clearLowest(b)) {
552
- const i = binary.utils.lowestSetIndex(b) as TABLE;
553
- stream1.seek(0);
554
- binary.read(stream1, TableReaders[i]);
555
- this.tables[i] = {offset, count: table_counts[i], size: stream1.tell()};
556
- offset += this.tables[i]!.size * this.tables[i]!.count;
557
- }
543
+ this.raw = stream.remainder();
544
+ const stream1 = new clr_dummy(this.table_info.HeapSizes, table_counts);
545
+ let offset = 0;
558
546
 
559
- this.Resources = pe.GetDataDir(this.header.Resources)?.data;
547
+ for (let b = this.table_info.Valid; b; b = binary.utils.clearLowest(b)) {
548
+ const i = binary.utils.lowestSetIndex(b) as TABLE;
549
+ stream1.seek(0);
550
+ binary.read(stream1, TableReaders[i]);
551
+ this.tables[i] = {offset, count: table_counts[i], size: stream1.tell()};
552
+ offset += this.tables[i]!.size * this.tables[i]!.count;
560
553
  }
561
554
 
562
- } catch (e) {
563
- console.log(e);
555
+ this.Resources = pe.GetDataDir(this.header.Resources)?.data;
564
556
  }
565
557
  }
566
558
 
@@ -573,6 +565,7 @@ export class CLR {
573
565
  }
574
566
  }
575
567
 
568
+ getTable<T extends TABLE> (t: T): binary.ReadType<typeof TableReaders[T]>[];
576
569
  getTable(t: TABLE) {
577
570
  const table = this.tables[t];
578
571
  if (table) {
@@ -639,7 +632,9 @@ function getResources(data: Uint8Array) {
639
632
  }
640
633
  }
641
634
 
642
- pe.DIRECTORIES.CLR_DESCRIPTOR.read = (pe: pe.PE, data: binary.utils.MappedMemory) => {
635
+ // hook into PE reader
636
+
637
+ pe.DIRECTORIES.CLR_DESCRIPTOR.read = (pe: pe.PE, data: binary.MappedMemory) => {
643
638
  function fix_names(table: any[]) {
644
639
  if ('name' in table[0])
645
640
  return Object.fromEntries(table.map(i => [i.name, i]));