bun-memory 1.1.18 → 1.1.21
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/README.md +13 -4
- package/example/trigger-bot.ts +8 -13
- package/package.json +1 -1
- package/structs/Memory.ts +81 -13
package/README.md
CHANGED
|
@@ -42,19 +42,28 @@ const modules = memory.modules;
|
|
|
42
42
|
|
|
43
43
|
const client = modules['client.dll'];
|
|
44
44
|
|
|
45
|
-
console.log(`Base
|
|
46
|
-
|
|
45
|
+
console.log(`Base: 0x%s — Size: %d bytes…`, client.base.toString(16), client.size);
|
|
46
|
+
|
|
47
|
+
const address = memory.follow(client.base + 0x12345678n, [0x10n, 0x20n, 0x30n]);
|
|
47
48
|
|
|
48
49
|
// Read a 32-bit integer…
|
|
49
|
-
const value = memory.i32(
|
|
50
|
+
const value = memory.i32(address);
|
|
50
51
|
|
|
51
52
|
// Write a float…
|
|
52
|
-
memory.f32(
|
|
53
|
+
memory.f32(address, 3.14159);
|
|
53
54
|
|
|
54
55
|
// Clean up…
|
|
55
56
|
memory.close();
|
|
56
57
|
```
|
|
57
58
|
|
|
59
|
+
### API — Follow / Read / Write
|
|
60
|
+
|
|
61
|
+
Low-level helpers for pointer resolution and raw, allocation-free memory transfers. Use these when you need maximum control or want to reuse your own scratches.
|
|
62
|
+
|
|
63
|
+
- follow
|
|
64
|
+
- read
|
|
65
|
+
- write
|
|
66
|
+
|
|
58
67
|
### API — Typed Reads / Writes
|
|
59
68
|
|
|
60
69
|
A `Memory` instance exposes typed helpers for reading and writing process memory. Pairs indicate
|
package/example/trigger-bot.ts
CHANGED
|
@@ -45,22 +45,17 @@ if (ClientPtr === undefined) {
|
|
|
45
45
|
}
|
|
46
46
|
// !
|
|
47
47
|
|
|
48
|
-
const dec = new TextDecoder('utf-8');
|
|
49
|
-
|
|
50
|
-
const buffer = Buffer.allocUnsafe(32);
|
|
51
|
-
const pointers = [4749947025128n, 4749937696488n, 4749757372648n, 4745786211048n, 4745800086248n, 4748263960808n, 4748274490088n, 4748287459048n, 4747096900328n, 4747107757288n];
|
|
52
|
-
|
|
53
48
|
console.time('test');
|
|
54
49
|
|
|
55
|
-
while (true) {
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
// while (true) {
|
|
51
|
+
// for (const pointer of pointers) {
|
|
52
|
+
// const cString = cs2.cString(pointer, 32).toString();
|
|
58
53
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
54
|
+
// if (cString.length > 32) {
|
|
55
|
+
// console.log(cString);
|
|
56
|
+
// }
|
|
57
|
+
// }
|
|
58
|
+
// }
|
|
64
59
|
|
|
65
60
|
console.timeEnd('test');
|
|
66
61
|
|
package/package.json
CHANGED
package/structs/Memory.ts
CHANGED
|
@@ -261,23 +261,91 @@ class Memory {
|
|
|
261
261
|
// Core memory operations
|
|
262
262
|
|
|
263
263
|
/**
|
|
264
|
-
*
|
|
265
|
-
*
|
|
264
|
+
* Follows a multi-level pointer chain and returns the resolved absolute address.
|
|
265
|
+
*
|
|
266
|
+
* This helper walks a sequence of offsets starting at `address`, repeatedly
|
|
267
|
+
* dereferencing intermediate pointers as 64-bit unsigned integers, and finally
|
|
268
|
+
* adding the last offset without dereferencing.
|
|
269
|
+
*
|
|
270
|
+
* Semantics:
|
|
271
|
+
* - If `offsets` is empty, the original `address` is returned unchanged.
|
|
272
|
+
* - For each offset except the last, the method adds the offset to the current
|
|
273
|
+
* address and dereferences a `uint64` at that location to get the next base.
|
|
274
|
+
* - If any intermediate dereference yields `0n`:
|
|
275
|
+
* - when `throw_` is `true`, an error is thrown;
|
|
276
|
+
* - otherwise, `-1n` is returned to indicate a null chain.
|
|
277
|
+
* - After all intermediate dereferences succeed, the final offset is **added**
|
|
278
|
+
* (no dereference) and the resulting absolute address is returned.
|
|
279
|
+
*
|
|
280
|
+
* @param address - Starting absolute memory address (BigInt).
|
|
281
|
+
* @param offsets - Readonly list of `bigint` offsets that define the pointer path.
|
|
282
|
+
* @param throw_ - When `true`, throw on a null pointer encounter (default: `false`).
|
|
283
|
+
* @returns The resolved absolute address, or `-1n` if a null pointer was encountered and `throw_` is `false`.
|
|
284
|
+
* @throws {Error} When a null pointer is encountered and `throw_` is `true`.
|
|
266
285
|
*
|
|
267
|
-
* @
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```typescript
|
|
288
|
+
* // Typical multi-level pointer chain (moduleBase + 0x123456 → [0x10, 0x20] → +0x30 final)
|
|
289
|
+
* const client = memory.modules['client.dll'];
|
|
290
|
+
* const resolved = memory.follow(client.base, [0x10n, 0x20n, 0x30n]);
|
|
291
|
+
*
|
|
292
|
+
* if (resolved !== -1n) {
|
|
293
|
+
* const health = memory.f32(resolved);
|
|
294
|
+
* console.log('Health:', health);
|
|
295
|
+
* }
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
public follow(address: bigint, offsets: readonly bigint[], throw_ = false): bigint {
|
|
299
|
+
const last = offsets.length - 1;
|
|
300
|
+
|
|
301
|
+
if (last === -1) {
|
|
302
|
+
return address;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
for (let i = 0; i < last; i++) {
|
|
306
|
+
address = this.u64((address += offsets[i]));
|
|
307
|
+
|
|
308
|
+
if (address === 0n) {
|
|
309
|
+
if (throw_) {
|
|
310
|
+
throw new Error('address must not be 0n.');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return -1n;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return address + offsets[last];
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Reads data from the target process memory into the provided scratch buffer and returns that
|
|
322
|
+
* same scratch object (strongly typed). This is a low-level, zero-copy helper used internally by
|
|
323
|
+
* typed readers.
|
|
324
|
+
*
|
|
325
|
+
* @typeParam T - Concrete scratch type extending {@link Scratch} (for example, `Scratch16`,
|
|
326
|
+
* `Scratch32`, a CString scratch, etc.).
|
|
327
|
+
*
|
|
328
|
+
* @param address - Absolute memory address to read from (BigInt).
|
|
329
|
+
* @param scratch - Destination scratch instance to receive the bytes.
|
|
330
|
+
* @returns The same scratch instance you passed in, typed as `T`.
|
|
331
|
+
* @throws {Win32Error} When the underlying `ReadProcessMemory` call fails.
|
|
271
332
|
*
|
|
272
333
|
* @todo Research what it will take to add CString to the Scratch type.
|
|
273
334
|
*
|
|
274
335
|
* @example
|
|
275
|
-
* ```
|
|
276
|
-
*
|
|
277
|
-
* memory.
|
|
336
|
+
* ```ts
|
|
337
|
+
* // Strongly typed result based on the scratch you pass in:
|
|
338
|
+
* const s16 = memory.Scratch16;
|
|
339
|
+
* const out16 = memory.read(0x12345678n, s16);
|
|
340
|
+
* ```
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```ts
|
|
344
|
+
* const myScratch = Buffer.allocUnsafe(64);
|
|
345
|
+
* const out = memory.read(0x1000_2000n, myScratch);
|
|
278
346
|
* ```
|
|
279
347
|
*/
|
|
280
|
-
public read(address: bigint, scratch:
|
|
348
|
+
public read<T extends Scratch>(address: bigint, scratch: T): T {
|
|
281
349
|
const lpBaseAddress = address;
|
|
282
350
|
const lpBuffer = scratch.ptr;
|
|
283
351
|
const nSize = scratch.byteLength;
|
|
@@ -289,7 +357,7 @@ class Memory {
|
|
|
289
357
|
throw new Win32Error('ReadProcessMemory', Kernel32.GetLastError());
|
|
290
358
|
}
|
|
291
359
|
|
|
292
|
-
return
|
|
360
|
+
return scratch;
|
|
293
361
|
}
|
|
294
362
|
|
|
295
363
|
/**
|
|
@@ -306,7 +374,7 @@ class Memory {
|
|
|
306
374
|
* memory.write(0x12345678n, buffer);
|
|
307
375
|
* ```
|
|
308
376
|
*/
|
|
309
|
-
private write(address: bigint, scratch: Scratch):
|
|
377
|
+
private write(address: bigint, scratch: Scratch): this {
|
|
310
378
|
const lpBaseAddress = address;
|
|
311
379
|
const lpBuffer = scratch.ptr;
|
|
312
380
|
const nSize = scratch.byteLength;
|
|
@@ -318,7 +386,7 @@ class Memory {
|
|
|
318
386
|
throw new Win32Error('WriteProcessMemory', Kernel32.GetLastError());
|
|
319
387
|
}
|
|
320
388
|
|
|
321
|
-
return;
|
|
389
|
+
return this;
|
|
322
390
|
}
|
|
323
391
|
|
|
324
392
|
// Public read / write methods…
|