bun-memory 1.1.38 → 1.1.40
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 +2 -2
- package/example/benchmark.ts +3 -3
- package/example/trigger-bot.ts +2 -2
- package/package.json +28 -28
- package/structs/Memory.ts +92 -36
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ bun add bun-memory
|
|
|
28
28
|
|
|
29
29
|
## Quick Start
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
For maximum performance, it is highly recommended to read about [using scratches](#example-using-scratches-recommended).
|
|
32
32
|
|
|
33
33
|
```ts
|
|
34
34
|
import Memory from 'bun-memory';
|
|
@@ -55,7 +55,7 @@ cs2.close();
|
|
|
55
55
|
- `indexOf(needle, address, length, [all])` — Search for a buffer or array in memory (returns all matches if all=true)
|
|
56
56
|
- `pattern(needle, address, length, [all])` — Find a byte pattern in memory (supports wildcards, returns all matches if all=true)
|
|
57
57
|
- `read(address, scratch)` — Read memory into a scratch (no allocations)
|
|
58
|
-
- `write(address, scratch)` — Write a scratch to memory
|
|
58
|
+
- `write(address, scratch, [force])` — Write a scratch to memory
|
|
59
59
|
- Module map: `memory.modules['client.dll']`
|
|
60
60
|
- Typed accessors: `bool`, `f32`, `i32`, `matrix4x4`, `u8`, `u64Array`, `vector3`, etc.
|
|
61
61
|
|
package/example/benchmark.ts
CHANGED
|
@@ -49,7 +49,7 @@ for (let i = 0; i < Iterations; i++) {
|
|
|
49
49
|
// Create caches and scratches to optimize performance…
|
|
50
50
|
const BaseEntityPtrs = new Map<string, bigint[]>();
|
|
51
51
|
|
|
52
|
-
const EntityChunkScratch = new BigUint64Array(
|
|
52
|
+
const EntityChunkScratch = new BigUint64Array(0xe000 / 0x08);
|
|
53
53
|
const EntityListScratch = new BigUint64Array(0x200 / 0x08);
|
|
54
54
|
|
|
55
55
|
const EntityClassInfoNames = new Map<bigint, string>();
|
|
@@ -77,8 +77,8 @@ for (let i = 0; i < 5; i++) {
|
|
|
77
77
|
|
|
78
78
|
void cs2.read(EntityChunkPtr, EntityChunkScratch);
|
|
79
79
|
|
|
80
|
-
// Traverse
|
|
81
|
-
for (let l =
|
|
80
|
+
// Traverse the potential 512 entities in that chunk…
|
|
81
|
+
for (let j = 0x00, l = 0x00; j < 0x200; j++, l += 0x0e) {
|
|
82
82
|
const BaseEntityPtr = EntityChunkScratch[l];
|
|
83
83
|
|
|
84
84
|
if (BaseEntityPtr === 0n) {
|
package/example/trigger-bot.ts
CHANGED
|
@@ -91,8 +91,8 @@ async function tick(ClientPtr: bigint) {
|
|
|
91
91
|
// Get the entity that we're aiming at from the entity list…
|
|
92
92
|
const EntityListPtr = cs2.u64(ClientPtr + Client.Other.dwEntityList);
|
|
93
93
|
/* */ const EntityChunkPtr = cs2.u64(EntityListPtr + (BigInt(Local_IDEntIndex) >> 0x09n) * 0x08n + 0x10n);
|
|
94
|
-
/* */ const BaseEntityPtr = cs2.u64(EntityChunkPtr + (BigInt(Local_IDEntIndex) & 0x1ffn) *
|
|
95
|
-
/* */ const EntityClassInfoPtr = cs2.u64(EntityChunkPtr + (BigInt(Local_IDEntIndex) & 0x1ffn) *
|
|
94
|
+
/* */ const BaseEntityPtr = cs2.u64(EntityChunkPtr + (BigInt(Local_IDEntIndex) & 0x1ffn) * 0x70n);
|
|
95
|
+
/* */ const EntityClassInfoPtr = cs2.u64(EntityChunkPtr + (BigInt(Local_IDEntIndex) & 0x1ffn) * 0x70n + 0x08n);
|
|
96
96
|
|
|
97
97
|
let Name = Cache_Names.get(EntityClassInfoPtr);
|
|
98
98
|
|
package/package.json
CHANGED
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
{
|
|
2
|
+
"name": "bun-memory",
|
|
3
|
+
"version": "1.1.40",
|
|
2
4
|
"author": "Stev Peifer <stev@bell.net>",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git://github.com/obscuritysrl/bun-memory.git"
|
|
5
8
|
},
|
|
6
|
-
"
|
|
9
|
+
"main": "./index.ts",
|
|
10
|
+
"module": "index.ts",
|
|
7
11
|
"devDependencies": {
|
|
8
12
|
"@types/bun": "latest"
|
|
9
13
|
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"typescript": "^5"
|
|
16
|
+
},
|
|
10
17
|
"exports": {
|
|
11
18
|
".": "./index.ts"
|
|
12
19
|
},
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
"name": "bun-memory",
|
|
16
|
-
"peerDependencies": {
|
|
17
|
-
"typescript": "^5"
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/obscuritysrl/bun-memory/issues"
|
|
18
22
|
},
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"url": "git://github.com/obscuritysrl/bun-memory.git"
|
|
23
|
+
"description": "Blazing fast, high-performance Windows process memory manipulation for Bun.",
|
|
24
|
+
"engines": {
|
|
25
|
+
"bun": ">=1.1.0"
|
|
23
26
|
},
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
"files": [
|
|
28
|
+
"index.ts",
|
|
29
|
+
"example/*.ts",
|
|
30
|
+
"runtime/*.ts",
|
|
31
|
+
"structs/*.ts",
|
|
32
|
+
"types/*.ts",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE"
|
|
35
|
+
],
|
|
27
36
|
"keywords": [
|
|
28
37
|
"bun",
|
|
29
38
|
"ffi",
|
|
@@ -35,20 +44,11 @@
|
|
|
35
44
|
"WriteProcessMemory",
|
|
36
45
|
"typescript"
|
|
37
46
|
],
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
"example/*.ts",
|
|
41
|
-
"runtime/*.ts",
|
|
42
|
-
"structs/*.ts",
|
|
43
|
-
"types/*.ts",
|
|
44
|
-
"README.md",
|
|
45
|
-
"LICENSE"
|
|
46
|
-
],
|
|
47
|
-
"engines": {
|
|
48
|
-
"bun": ">=1.1.0"
|
|
49
|
-
},
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"private": false,
|
|
50
49
|
"scripts": {
|
|
51
50
|
"run:benchmark": "bun ./example/benchmark.ts",
|
|
52
51
|
"run:trigger-bot": "bun ./example/trigger-bot.ts"
|
|
53
|
-
}
|
|
52
|
+
},
|
|
53
|
+
"type": "module"
|
|
54
54
|
}
|
package/structs/Memory.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CString, FFIType, dlopen, ptr } from 'bun:ffi';
|
|
2
2
|
|
|
3
|
-
import type { Module,
|
|
3
|
+
import type { Module, Point, QAngle, Quaternion, Region, RGB, RGBA, Scratch, UPtr, UPtrArray, Vector2, Vector3, Vector4 } from '../types/Memory';
|
|
4
4
|
import Win32Error from './Win32Error';
|
|
5
5
|
|
|
6
6
|
const {
|
|
@@ -920,41 +920,6 @@ class Memory {
|
|
|
920
920
|
return this;
|
|
921
921
|
}
|
|
922
922
|
|
|
923
|
-
/**
|
|
924
|
-
* Reads or writes a NetworkUtlVector (Uint32Array).
|
|
925
|
-
* @param address Address to access.
|
|
926
|
-
* @param values Optional Uint32Array to write.
|
|
927
|
-
* @param force When writing, if true temporarily changes page protection to allow the write.
|
|
928
|
-
* @returns The vector at address, or this instance if writing.
|
|
929
|
-
* @example
|
|
930
|
-
* ```ts
|
|
931
|
-
* const cs2 = new Memory('cs2.exe');
|
|
932
|
-
* const myVector = cs2.networkUtlVector(0x12345678n);
|
|
933
|
-
* cs2.networkUtlVector(0x12345678n, new Uint32Array([1,2,3]));
|
|
934
|
-
* ```
|
|
935
|
-
*/
|
|
936
|
-
public networkUtlVector(address: bigint): NetworkUtlVector;
|
|
937
|
-
public networkUtlVector(address: bigint, values: NetworkUtlVector, force?: boolean): this;
|
|
938
|
-
public networkUtlVector(address: bigint, values?: NetworkUtlVector, force?: boolean): NetworkUtlVector | this {
|
|
939
|
-
const elementsPtr = this.u64(address + 0x08n);
|
|
940
|
-
|
|
941
|
-
if (values === undefined) {
|
|
942
|
-
const size = this.u32(address);
|
|
943
|
-
|
|
944
|
-
const scratch = new Uint32Array(size);
|
|
945
|
-
|
|
946
|
-
void this.read(elementsPtr, scratch);
|
|
947
|
-
|
|
948
|
-
return scratch;
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
this.u32(address, values.length, force);
|
|
952
|
-
|
|
953
|
-
void this.write(elementsPtr, values, force);
|
|
954
|
-
|
|
955
|
-
return this;
|
|
956
|
-
}
|
|
957
|
-
|
|
958
923
|
/**
|
|
959
924
|
* Reads or writes a Point (object with x, y).
|
|
960
925
|
* @param address Address to access.
|
|
@@ -1772,6 +1737,97 @@ class Memory {
|
|
|
1772
1737
|
return this.u64Array(address, lengthOrValues, force);
|
|
1773
1738
|
}
|
|
1774
1739
|
|
|
1740
|
+
/**
|
|
1741
|
+
* Reads a UtlLinkedList of 64-bit unsigned integers and returns its elements as a BigUint64Array.
|
|
1742
|
+
*
|
|
1743
|
+
* This helper reads the list header at `address`, validates the capacity and element pointer,
|
|
1744
|
+
* reads the elements table, and walks the internal linked indices to produce a compact
|
|
1745
|
+
* BigUint64Array of present elements. If the list is empty or invalid an empty array is
|
|
1746
|
+
* returned.
|
|
1747
|
+
*
|
|
1748
|
+
* @param address Address of the UtlLinkedList header in the remote process.
|
|
1749
|
+
* @returns BigUint64Array containing the list elements (empty if the list is invalid or empty).
|
|
1750
|
+
* @todo Create a writer so that users can write linked lists…
|
|
1751
|
+
* @example
|
|
1752
|
+
* ```ts
|
|
1753
|
+
* const cs2 = new Memory('cs2.exe');
|
|
1754
|
+
* const myList = cs2.utlLinkedListU64(0x12345678n);
|
|
1755
|
+
* ```
|
|
1756
|
+
*/
|
|
1757
|
+
public utlLinkedListU64(address: bigint): BigUint64Array {
|
|
1758
|
+
const header = new Uint8Array(0x18);
|
|
1759
|
+
const headerUint16Array = new Uint16Array(header.buffer, header.byteOffset);
|
|
1760
|
+
const headerBigUint64Array = new BigUint64Array(header.buffer, header.byteOffset + 0x08, 2);
|
|
1761
|
+
|
|
1762
|
+
void this.read(address, header);
|
|
1763
|
+
|
|
1764
|
+
const capacity = headerUint16Array[0x01] & 0x7fff;
|
|
1765
|
+
const elementsPtr = headerBigUint64Array[0x00];
|
|
1766
|
+
let index = headerUint16Array[0x08]; // prettier-ignore
|
|
1767
|
+
|
|
1768
|
+
if (capacity === 0 || capacity <= index || elementsPtr === 0n || index === 0xffff) {
|
|
1769
|
+
return new BigUint64Array(0);
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
const scratch = new Uint8Array(capacity << 0x04);
|
|
1773
|
+
const scratchBigUint64Array = new BigUint64Array(scratch.buffer, scratch.byteOffset);
|
|
1774
|
+
const scratchUint16Array = new Uint16Array(scratch.buffer, scratch.byteOffset);
|
|
1775
|
+
|
|
1776
|
+
void this.read(elementsPtr, scratch);
|
|
1777
|
+
|
|
1778
|
+
let count = 0; // prettier-ignore
|
|
1779
|
+
const result = new BigUint64Array(capacity);
|
|
1780
|
+
|
|
1781
|
+
while (count < capacity && capacity > index && index !== 0xffff) {
|
|
1782
|
+
result[count++] = scratchBigUint64Array[index * 0x02];
|
|
1783
|
+
|
|
1784
|
+
const next = scratchUint16Array[0x05 + index * 0x08];
|
|
1785
|
+
|
|
1786
|
+
if (index === next || next === 0xffff) {
|
|
1787
|
+
break;
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
index = next;
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
return capacity === count ? result : result.subarray(0, count);
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
/**
|
|
1797
|
+
* Reads or writes a UtlVectorU32 (Uint32Array).
|
|
1798
|
+
* @param address Address to access.
|
|
1799
|
+
* @param values Optional Uint32Array to write.
|
|
1800
|
+
* @param force When writing, if true temporarily changes page protection to allow the write.
|
|
1801
|
+
* @returns The vector at address, or this instance if writing.
|
|
1802
|
+
* @example
|
|
1803
|
+
* ```ts
|
|
1804
|
+
* const cs2 = new Memory('cs2.exe');
|
|
1805
|
+
* const myVector = cs2.utlVectorU32(0x12345678n);
|
|
1806
|
+
* cs2.utlVectorU32(0x12345678n, new Uint32Array([1,2,3]));
|
|
1807
|
+
* ```
|
|
1808
|
+
*/
|
|
1809
|
+
public utlVectorU32(address: bigint): Uint32Array;
|
|
1810
|
+
public utlVectorU32(address: bigint, values: Uint32Array, force?: boolean): this;
|
|
1811
|
+
public utlVectorU32(address: bigint, values?: Uint32Array, force?: boolean): Uint32Array | this {
|
|
1812
|
+
const elementsPtr = this.u64(address + 0x08n);
|
|
1813
|
+
|
|
1814
|
+
if (values === undefined) {
|
|
1815
|
+
const size = this.u32(address);
|
|
1816
|
+
|
|
1817
|
+
const scratch = new Uint32Array(size);
|
|
1818
|
+
|
|
1819
|
+
void this.read(elementsPtr, scratch);
|
|
1820
|
+
|
|
1821
|
+
return scratch;
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
this.u32(address, values.length, force);
|
|
1825
|
+
|
|
1826
|
+
void this.write(elementsPtr, values, force);
|
|
1827
|
+
|
|
1828
|
+
return this;
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1775
1831
|
/**
|
|
1776
1832
|
* Reads or writes a Vector2 (object with x, y).
|
|
1777
1833
|
* @param address Address to access.
|