@cheatron/native 1.1.0 → 1.2.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.
Files changed (98) hide show
  1. package/README.md +17 -4
  2. package/dist/{src/handle.d.ts → handle.d.ts} +4 -0
  3. package/dist/handle.d.ts.map +1 -0
  4. package/dist/{src/handle.js → handle.js} +3 -3
  5. package/dist/handle.js.map +1 -0
  6. package/dist/{src/index.d.ts → index.d.ts} +7 -3
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/{src/index.js → index.js} +6 -2
  9. package/dist/index.js.map +1 -0
  10. package/dist/logger.d.ts.map +1 -0
  11. package/dist/logger.js.map +1 -0
  12. package/dist/module.d.ts +45 -0
  13. package/dist/module.d.ts.map +1 -0
  14. package/dist/module.js +122 -0
  15. package/dist/module.js.map +1 -0
  16. package/dist/msvcrt-ext.d.ts +20 -0
  17. package/dist/msvcrt-ext.d.ts.map +1 -0
  18. package/dist/msvcrt-ext.js +120 -0
  19. package/dist/msvcrt-ext.js.map +1 -0
  20. package/dist/native-fn.d.ts +71 -0
  21. package/dist/native-fn.d.ts.map +1 -0
  22. package/dist/native-fn.js +212 -0
  23. package/dist/native-fn.js.map +1 -0
  24. package/dist/pattern.d.ts +15 -0
  25. package/dist/pattern.d.ts.map +1 -0
  26. package/dist/pattern.js +41 -0
  27. package/dist/pattern.js.map +1 -0
  28. package/dist/process.d.ts +72 -0
  29. package/dist/process.d.ts.map +1 -0
  30. package/dist/process.js +269 -0
  31. package/dist/process.js.map +1 -0
  32. package/dist/scanner.d.ts +25 -0
  33. package/dist/scanner.d.ts.map +1 -0
  34. package/dist/scanner.js +124 -0
  35. package/dist/scanner.js.map +1 -0
  36. package/dist/thread.d.ts.map +1 -0
  37. package/dist/{src/thread.js → thread.js} +1 -1
  38. package/dist/thread.js.map +1 -0
  39. package/package.json +3 -2
  40. package/dist/eslint.config.d.ts +0 -3
  41. package/dist/eslint.config.d.ts.map +0 -1
  42. package/dist/eslint.config.js +0 -26
  43. package/dist/eslint.config.js.map +0 -1
  44. package/dist/src/handle.d.ts.map +0 -1
  45. package/dist/src/handle.js.map +0 -1
  46. package/dist/src/index.d.ts.map +0 -1
  47. package/dist/src/index.js.map +0 -1
  48. package/dist/src/logger.d.ts.map +0 -1
  49. package/dist/src/logger.js.map +0 -1
  50. package/dist/src/module.d.ts +0 -22
  51. package/dist/src/module.d.ts.map +0 -1
  52. package/dist/src/module.js +0 -55
  53. package/dist/src/module.js.map +0 -1
  54. package/dist/src/process.d.ts +0 -30
  55. package/dist/src/process.d.ts.map +0 -1
  56. package/dist/src/process.js +0 -104
  57. package/dist/src/process.js.map +0 -1
  58. package/dist/src/thread.d.ts.map +0 -1
  59. package/dist/src/thread.js.map +0 -1
  60. package/dist/tests/integration/memory.test.d.ts +0 -2
  61. package/dist/tests/integration/memory.test.d.ts.map +0 -1
  62. package/dist/tests/integration/memory.test.js +0 -82
  63. package/dist/tests/integration/memory.test.js.map +0 -1
  64. package/dist/tests/integration/thread.test.d.ts +0 -2
  65. package/dist/tests/integration/thread.test.d.ts.map +0 -1
  66. package/dist/tests/integration/thread.test.js +0 -37
  67. package/dist/tests/integration/thread.test.js.map +0 -1
  68. package/dist/tests/setup.d.ts +0 -2
  69. package/dist/tests/setup.d.ts.map +0 -1
  70. package/dist/tests/setup.js +0 -3
  71. package/dist/tests/setup.js.map +0 -1
  72. package/dist/tests/unit/kernel32.test.d.ts +0 -2
  73. package/dist/tests/unit/kernel32.test.d.ts.map +0 -1
  74. package/dist/tests/unit/kernel32.test.js +0 -28
  75. package/dist/tests/unit/kernel32.test.js.map +0 -1
  76. package/dist/tests/unit/logger.test.d.ts +0 -2
  77. package/dist/tests/unit/logger.test.d.ts.map +0 -1
  78. package/dist/tests/unit/logger.test.js +0 -29
  79. package/dist/tests/unit/logger.test.js.map +0 -1
  80. package/dist/tests/unit/msvcrt.test.d.ts +0 -2
  81. package/dist/tests/unit/msvcrt.test.d.ts.map +0 -1
  82. package/dist/tests/unit/msvcrt.test.js +0 -22
  83. package/dist/tests/unit/msvcrt.test.js.map +0 -1
  84. package/dist/tests/unit/process.test.d.ts +0 -2
  85. package/dist/tests/unit/process.test.d.ts.map +0 -1
  86. package/dist/tests/unit/process.test.js +0 -27
  87. package/dist/tests/unit/process.test.js.map +0 -1
  88. package/dist/tests/unit/thread.test.d.ts +0 -2
  89. package/dist/tests/unit/thread.test.d.ts.map +0 -1
  90. package/dist/tests/unit/thread.test.js +0 -35
  91. package/dist/tests/unit/thread.test.js.map +0 -1
  92. package/dist/tests/unit/thread_creation.test.d.ts +0 -2
  93. package/dist/tests/unit/thread_creation.test.d.ts.map +0 -1
  94. package/dist/tests/unit/thread_creation.test.js +0 -31
  95. package/dist/tests/unit/thread_creation.test.js.map +0 -1
  96. /package/dist/{src/logger.d.ts → logger.d.ts} +0 -0
  97. /package/dist/{src/logger.js → logger.js} +0 -0
  98. /package/dist/{src/thread.d.ts → thread.d.ts} +0 -0
@@ -0,0 +1,212 @@
1
+ import { ffi, MsvcrtImpl as msvcrt, MemoryProtection, MemoryState, MemoryFreeType, } from '@cheatron/native-bindings';
2
+ import { KeystoneX86 } from '@cheatron/keystone';
3
+ import { log } from './logger';
4
+ const nfLog = log.child('NativeFn');
5
+ /** Registry for automatic cleanup of memory pages */
6
+ const registry = new FinalizationRegistry((page) => {
7
+ if (page) {
8
+ // Lazy require to avoid circular dependencies
9
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
10
+ const { currentProcess } = require('./process');
11
+ // Free the allocated memory using currentProcess.free
12
+ try {
13
+ const success = currentProcess.free(page, 0, MemoryFreeType.RELEASE);
14
+ if (success) {
15
+ nfLog.info('Garbage collection: cleaned up executable memory page');
16
+ }
17
+ else {
18
+ nfLog.error('Garbage collection: currentProcess.free returned false during cleanup');
19
+ }
20
+ }
21
+ catch (err) {
22
+ const message = err instanceof Error ? err.message : String(err);
23
+ nfLog.error(`Garbage collection: cleanup failed: ${message}`);
24
+ }
25
+ }
26
+ });
27
+ export const ALIGN = 16;
28
+ /**
29
+ * Rounds a number up to the nearest multiple of 16.
30
+ */
31
+ export function align16(n) {
32
+ return (n + ALIGN - 1) & ~(ALIGN - 1);
33
+ }
34
+ /**
35
+ * Dynamically creates callable native functions from assembly or bytecode.
36
+ *
37
+ * Functions are written into a single VirtualAlloc'd executable page and
38
+ * exposed as callable methods on the instance via koffi.
39
+ */
40
+ export class NativeFunctionCreator {
41
+ page;
42
+ pageAddr;
43
+ offset = 0;
44
+ capacity;
45
+ ks;
46
+ functions = new Map();
47
+ constructor(capacity = 8192) {
48
+ this.capacity = capacity;
49
+ this.ks = new KeystoneX86();
50
+ // Lazy require to avoid circular dependencies
51
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
52
+ const { currentProcess } = require('./process');
53
+ // Allocate executable memory using currentProcess.alloc
54
+ this.page = currentProcess.alloc(BigInt(capacity), null, MemoryState.COMMIT | MemoryState.RESERVE, MemoryProtection.EXECUTE_READWRITE);
55
+ if (!this.page) {
56
+ throw new Error('VirtualAlloc failed: could not allocate executable memory');
57
+ }
58
+ // Register for automatic cleanup. Use 'this' as the unregister token.
59
+ registry.register(this, this.page, this);
60
+ this.pageAddr = ffi.address(this.page);
61
+ nfLog.info(`Allocated ${capacity} bytes of executable memory at 0x${this.pageAddr.toString(16).toUpperCase()}`);
62
+ }
63
+ /**
64
+ * Add a native function from assembly source code.
65
+ * @param def Function definition { name: [returnType, [paramTypes...]] }
66
+ * @param asmSource x86-64 assembly instructions
67
+ * @returns Address of the function
68
+ */
69
+ add(def, asmSource) {
70
+ const name = Object.keys(def)[0];
71
+ if (!name) {
72
+ throw new Error('Invalid function definition: name is missing');
73
+ }
74
+ const sig = def[name];
75
+ if (!sig) {
76
+ throw new Error(`Invalid function definition: signature is missing for '${name}'`);
77
+ }
78
+ const funcAddr = this.pageAddr + BigInt(this.offset);
79
+ const bytes = this.ks.asm(asmSource, funcAddr);
80
+ return this._writeAndBind(name, sig, bytes);
81
+ }
82
+ /**
83
+ * Add a native function from raw bytecode.
84
+ * @param def Function definition { name: [returnType, [paramTypes...]] }
85
+ * @param bytes Raw machine code bytes
86
+ * @returns Address of the function
87
+ */
88
+ addBytes(def, bytes) {
89
+ const name = Object.keys(def)[0];
90
+ if (!name) {
91
+ throw new Error('Invalid function definition: name is missing');
92
+ }
93
+ const sig = def[name];
94
+ if (!sig) {
95
+ throw new Error(`Invalid function definition: signature is missing for '${name}'`);
96
+ }
97
+ return this._writeAndBind(name, sig, bytes);
98
+ }
99
+ /**
100
+ * Get the address of a registered function by name.
101
+ */
102
+ getAddress(name) {
103
+ return this.functions.get(name)?.address;
104
+ }
105
+ /**
106
+ * Get the callable function by name.
107
+ */
108
+ // eslint-disable-next-line no-unused-vars
109
+ getFunction(name) {
110
+ return this.functions.get(name)?.callable;
111
+ }
112
+ /**
113
+ * Get info about all registered functions.
114
+ */
115
+ list() {
116
+ return [...this.functions.values()];
117
+ }
118
+ /**
119
+ * Get remaining capacity in bytes.
120
+ */
121
+ get remaining() {
122
+ return this.capacity - this.offset;
123
+ }
124
+ /**
125
+ * Free the executable memory page.
126
+ */
127
+ destroy() {
128
+ if (this.page) {
129
+ // Unregister from finalizer as we are doing manual cleanup
130
+ registry.unregister(this);
131
+ // Lazy require to avoid circular dependencies
132
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
133
+ const { currentProcess } = require('./process');
134
+ // Perform the actual free using currentProcess.free
135
+ const success = currentProcess.free(this.page, 0, MemoryFreeType.RELEASE);
136
+ if (success) {
137
+ nfLog.info('NativeFunctionCreator destroyed');
138
+ }
139
+ else {
140
+ nfLog.warn('currentProcess.free failed during NativeFunctionCreator destruction');
141
+ }
142
+ this.page = null;
143
+ this.functions.clear();
144
+ }
145
+ }
146
+ // ── Internal ──────────────────────────────────────────────
147
+ _writeAndBind(name, sig, bytes) {
148
+ if (this.functions.has(name)) {
149
+ throw new Error(`Function '${name}' already registered`);
150
+ }
151
+ const alignedSize = align16(bytes.length);
152
+ if (this.offset + alignedSize > this.capacity) {
153
+ throw new Error(`Not enough space: need ${alignedSize} bytes, ${this.remaining} remaining`);
154
+ }
155
+ const funcOffset = this.offset;
156
+ const funcAddr = this.pageAddr + BigInt(funcOffset);
157
+ // Write bytecode into executable page
158
+ const buf = Buffer.from(bytes);
159
+ msvcrt.memcpy(funcAddr, buf, BigInt(bytes.length));
160
+ nfLog.debug(`Written '${name}' (${bytes.length} bytes) at 0x${funcAddr.toString(16).toUpperCase()} [offset: ${funcOffset}]`);
161
+ // Advance offset (aligned)
162
+ this.offset += alignedSize;
163
+ // Create koffi prototype
164
+ const [retType, paramTypes] = sig;
165
+ const protoName = `__nf_${name}_${Date.now()}`;
166
+ const paramStr = paramTypes.map((t, i) => `${t} p${i}`).join(', ');
167
+ const protoStr = `${retType} ${protoName}(${paramStr})`;
168
+ const proto = ffi.proto(protoStr);
169
+ // Decode function pointer from base page + offset
170
+ // koffi.decode(ptr, type, offset) offsets from the base external pointer
171
+ const callable = ffi.decode(this.page, proto, funcOffset);
172
+ // Bind as method on this instance
173
+ Object.defineProperty(this, name, {
174
+ enumerable: true,
175
+ configurable: true,
176
+ value: callable,
177
+ });
178
+ // Track
179
+ const entry = {
180
+ name,
181
+ address: funcAddr,
182
+ size: bytes.length,
183
+ sig,
184
+ callable,
185
+ };
186
+ this.functions.set(name, entry);
187
+ return funcAddr;
188
+ }
189
+ }
190
+ /**
191
+ * Global shared NativeFunctionCreator instance.
192
+ * Lazy initialized to prevent circular dependency issues during module load.
193
+ */
194
+ let _nativeFn;
195
+ export const nativeFn = new Proxy({}, {
196
+ get(_target, prop) {
197
+ if (!_nativeFn) {
198
+ _nativeFn = new NativeFunctionCreator();
199
+ }
200
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
201
+ const val = _nativeFn[prop];
202
+ // Don't bind non-functions or constructor
203
+ if (typeof val === 'function' && prop !== 'constructor') {
204
+ return val.bind(_nativeFn);
205
+ }
206
+ return val;
207
+ },
208
+ getPrototypeOf() {
209
+ return NativeFunctionCreator.prototype;
210
+ },
211
+ });
212
+ //# sourceMappingURL=native-fn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-fn.js","sourceRoot":"","sources":["../src/native-fn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Represents a parsed memory signature/pattern
3
+ */
4
+ export declare class Pattern {
5
+ bytes: Buffer;
6
+ mask: string;
7
+ limit: number;
8
+ /**
9
+ * @param signature Pattern string (e.g. "55 8B EC ?? 56")
10
+ * @param limit Maximum number of results to find (0 = no limit)
11
+ */
12
+ constructor(signature: string, limit?: number);
13
+ get length(): number;
14
+ }
15
+ //# sourceMappingURL=pattern.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern.d.ts","sourceRoot":"","sources":["../src/pattern.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,qBAAa,OAAO;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IAErB;;;OAGG;gBACS,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU;IAyBhD,IAAI,MAAM,IAAI,MAAM,CAEnB;CACF"}
@@ -0,0 +1,41 @@
1
+ import { log } from './logger';
2
+ const scanLog = log.child('Scanner');
3
+ /**
4
+ * Represents a parsed memory signature/pattern
5
+ */
6
+ export class Pattern {
7
+ bytes;
8
+ mask;
9
+ limit;
10
+ /**
11
+ * @param signature Pattern string (e.g. "55 8B EC ?? 56")
12
+ * @param limit Maximum number of results to find (0 = no limit)
13
+ */
14
+ constructor(signature, limit = 0) {
15
+ this.limit = limit;
16
+ const parts = signature.split(/\s+/).filter(Boolean);
17
+ const bytes = [];
18
+ let mask = '';
19
+ for (const part of parts) {
20
+ if (part === '??' || part === '?') {
21
+ bytes.push(0);
22
+ mask += '?';
23
+ }
24
+ else {
25
+ const byte = parseInt(part, 16);
26
+ if (isNaN(byte)) {
27
+ throw new Error(`Invalid byte in signature: ${part}`);
28
+ }
29
+ bytes.push(byte);
30
+ mask += 'x';
31
+ }
32
+ }
33
+ this.bytes = Buffer.from(bytes);
34
+ this.mask = mask;
35
+ scanLog.debug(`Parsed pattern: ${signature} -> ${mask}`);
36
+ }
37
+ get length() {
38
+ return this.bytes.length;
39
+ }
40
+ }
41
+ //# sourceMappingURL=pattern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern.js","sourceRoot":"","sources":["../src/pattern.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AAErC;;GAEG;AACH,MAAM,OAAO,OAAO;IACX,KAAK,CAAS;IACd,IAAI,CAAS;IACb,KAAK,CAAS;IAErB;;;OAGG;IACH,YAAY,SAAiB,EAAE,QAAgB,CAAC;QAC9C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,IAAI,GAAG,EAAE,CAAC;QAEd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBAClC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACd,IAAI,IAAI,GAAG,CAAC;YACd,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAChC,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,EAAE,CAAC,CAAC;gBACxD,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjB,IAAI,IAAI,GAAG,CAAC;YACd,CAAC;QACH,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,mBAAmB,SAAS,OAAO,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,72 @@
1
+ import { Thread } from './thread';
2
+ import { ThreadCreationFlags, MemoryFreeType, type SecurityAttributes, type MemoryBasicInformation, type HANDLE, type LPVOID, type SIZE_T } from '@cheatron/native-bindings';
3
+ import { Handle } from './handle';
4
+ import { Pattern } from './pattern';
5
+ /**
6
+ * Represents a process handle
7
+ */
8
+ export declare class Process extends Handle {
9
+ protected _pid: number;
10
+ constructor(handle: HANDLE, pid?: number, autoClose?: boolean);
11
+ static open(pid: number, access?: number): Process;
12
+ readMemory(address: LPVOID, size: number): Buffer;
13
+ read: (address: LPVOID, size: number) => Buffer;
14
+ writeMemory(address: LPVOID, buffer: Buffer): void;
15
+ write: (address: LPVOID, buffer: Buffer) => void;
16
+ createThread(startAddress: LPVOID, parameter?: LPVOID | null, stackSize?: SIZE_T, flags?: ThreadCreationFlags | number, attributes?: SecurityAttributes | LPVOID | null): Thread;
17
+ virtualQuery(address: LPVOID): MemoryBasicInformation;
18
+ query: (address: LPVOID) => MemoryBasicInformation;
19
+ /**
20
+ * Allocates memory in the process.
21
+ */
22
+ alloc(size: SIZE_T, address?: LPVOID | null, allocationType?: number, protection?: number): LPVOID;
23
+ /**
24
+ * Frees memory in the process.
25
+ */
26
+ free(address: LPVOID, size?: SIZE_T, freeType?: MemoryFreeType | number): boolean;
27
+ /**
28
+ * Finds a pattern in a specific memory range
29
+ * @param signature Pattern string (e.g. "55 8B EC ?? 56")
30
+ * @param start Start address
31
+ * @param size Scan size
32
+ */
33
+ findPatternInRange(signature: string | Pattern, start: bigint, size: number): bigint | null;
34
+ /**
35
+ * Finds all matches of a pattern in a specific memory range
36
+ */
37
+ findAllPatternsInRange(signature: string | Pattern, start: bigint, size: number, limit?: number): bigint[];
38
+ /**
39
+ * Finds a pattern in all committed and readable memory of the process
40
+ */
41
+ findPattern(signature: string | Pattern): bigint | null;
42
+ /**
43
+ * Finds all matches of a pattern in all committed and readable memory
44
+ */
45
+ findAllPatterns(signature: string | Pattern, limit?: number): bigint[];
46
+ /**
47
+ * Scans specific loaded modules for a given pattern.
48
+ * Finds the first pattern match across the specified (or default) modules.
49
+ * @param signature Pattern string (e.g. "55 8B EC ?? 56") or Pattern object
50
+ * @param moduleNames Array of module names (e.g. ['kernel32.dll', 'msvcrt.dll'])
51
+ * @returns The first matched address, or null if not found
52
+ */
53
+ findPatternFromModules(signature: string | Pattern, moduleNames?: string[]): bigint | null;
54
+ /**
55
+ * Finds all matches of a pattern across specified modules
56
+ */
57
+ findAllPatternsFromModules(signature: string | Pattern, moduleNames?: string[], limit?: number): bigint[];
58
+ static current(): CurrentProcess;
59
+ get pid(): number;
60
+ }
61
+ /**
62
+ * Represents the current process (singleton)
63
+ */
64
+ export declare class CurrentProcess extends Process {
65
+ constructor();
66
+ createThread(startAddress: LPVOID, parameter?: LPVOID | null, stackSize?: SIZE_T, flags?: ThreadCreationFlags | number, attributes?: SecurityAttributes | LPVOID | null): Thread;
67
+ alloc(size: SIZE_T, address?: LPVOID | null, allocationType?: number, protection?: number): LPVOID;
68
+ free(address: LPVOID, size?: SIZE_T, freeType?: MemoryFreeType | number): boolean;
69
+ close(): void;
70
+ }
71
+ export declare const currentProcess: CurrentProcess;
72
+ //# sourceMappingURL=process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,269 @@
1
+ import { Thread } from './thread';
2
+ import { Kernel32Impl, ffi, ProcessAccess, ThreadCreationFlags, MEMORY_BASIC_INFORMATION, MBI_SIZE, MemoryProtection, MemoryState, MemoryFreeType, } from '@cheatron/native-bindings';
3
+ import { Handle } from './handle';
4
+ import { log } from './logger';
5
+ import { Scanner } from './scanner';
6
+ import { Pattern } from './pattern';
7
+ const processLog = log.child('Process');
8
+ /**
9
+ * Represents a process handle
10
+ */
11
+ export class Process extends Handle {
12
+ _pid;
13
+ constructor(handle, pid, autoClose = true) {
14
+ super(handle, autoClose);
15
+ this._pid = pid ?? Kernel32Impl.GetProcessId(handle);
16
+ }
17
+ static open(pid, access = ProcessAccess.ALL_ACCESS) {
18
+ processLog.debug(`Opening process ${pid} with access ${access}`);
19
+ const handle = Kernel32Impl.OpenProcess(access, 0, pid);
20
+ if (!handle) {
21
+ processLog.warn(`Failed to open process ${pid}`);
22
+ throw new Error(`Failed to open process ${pid}`);
23
+ }
24
+ return new Process(handle, pid);
25
+ }
26
+ readMemory(address, size) {
27
+ if (!this.isValid())
28
+ throw new Error('Process handle is closed');
29
+ const buf = Buffer.alloc(size);
30
+ const success = Kernel32Impl.ReadProcessMemory(this._handle, address, buf, size, null);
31
+ if (!success) {
32
+ const addrHex = ffi.address(address).toString(16).toUpperCase();
33
+ processLog.error(`ReadProcessMemory failed at 0x${addrHex}`);
34
+ throw new Error(`ReadProcessMemory failed at 0x${addrHex}`);
35
+ }
36
+ return buf;
37
+ }
38
+ read = this.readMemory;
39
+ writeMemory(address, buffer) {
40
+ if (!this.isValid())
41
+ throw new Error('Process handle is closed');
42
+ const success = Kernel32Impl.WriteProcessMemory(this._handle, address, buffer, buffer.length, null);
43
+ if (!success) {
44
+ const addrHex = ffi.address(address).toString(16).toUpperCase();
45
+ processLog.error(`WriteProcessMemory failed at 0x${addrHex}`);
46
+ throw new Error(`WriteProcessMemory failed at 0x${addrHex}`);
47
+ }
48
+ }
49
+ write = this.writeMemory;
50
+ createThread(startAddress, parameter = null, stackSize = 0, flags = ThreadCreationFlags.IMMEDIATE, attributes = null) {
51
+ if (!this.isValid())
52
+ throw new Error('Process handle is closed');
53
+ processLog.debug(`Creating remote thread at 0x${ffi.address(startAddress).toString(16)} (PID: ${this._pid})`);
54
+ const handle = Kernel32Impl.CreateRemoteThread(this._handle, attributes, stackSize, startAddress, parameter, flags, null);
55
+ if (!handle) {
56
+ processLog.error('CreateRemoteThread failed');
57
+ throw new Error('CreateRemoteThread failed');
58
+ }
59
+ return new Thread(handle);
60
+ }
61
+ virtualQuery(address) {
62
+ if (!this.isValid())
63
+ throw new Error('Process handle is closed');
64
+ const buf = Buffer.alloc(MBI_SIZE);
65
+ const result = Kernel32Impl.VirtualQueryEx(this._handle, address, buf, MBI_SIZE);
66
+ if (result === 0) {
67
+ const addrHex = ffi.address(address).toString(16).toUpperCase();
68
+ processLog.error(`VirtualQueryEx failed at 0x${addrHex}`);
69
+ throw new Error(`VirtualQueryEx failed at 0x${addrHex}`);
70
+ }
71
+ return ffi.decode(buf, MEMORY_BASIC_INFORMATION);
72
+ }
73
+ query = this.virtualQuery;
74
+ /**
75
+ * Allocates memory in the process.
76
+ */
77
+ alloc(size, address = null, allocationType = MemoryState.COMMIT | MemoryState.RESERVE, protection = MemoryProtection.READWRITE) {
78
+ if (!this.isValid())
79
+ throw new Error('Process handle is closed');
80
+ const result = Kernel32Impl.VirtualAllocEx(this._handle, address, size, allocationType, protection);
81
+ if (!result) {
82
+ processLog.error(`VirtualAllocEx failed (PID: ${this._pid}, size: ${size})`);
83
+ }
84
+ return result;
85
+ }
86
+ /**
87
+ * Frees memory in the process.
88
+ */
89
+ free(address, size = 0, freeType = MemoryFreeType.RELEASE) {
90
+ if (!this.isValid())
91
+ throw new Error('Process handle is closed');
92
+ const result = Kernel32Impl.VirtualFreeEx(this._handle, address, size, freeType);
93
+ if (!result) {
94
+ const addrHex = ffi.address(address).toString(16).toUpperCase();
95
+ processLog.error(`VirtualFreeEx failed at 0x${addrHex}`);
96
+ }
97
+ return !!result;
98
+ }
99
+ /**
100
+ * Finds a pattern in a specific memory range
101
+ * @param signature Pattern string (e.g. "55 8B EC ?? 56")
102
+ * @param start Start address
103
+ * @param size Scan size
104
+ */
105
+ findPatternInRange(signature, start, size) {
106
+ const results = this.findAllPatternsInRange(signature, start, size, 1);
107
+ return results[0] ?? null;
108
+ }
109
+ /**
110
+ * Finds all matches of a pattern in a specific memory range
111
+ */
112
+ findAllPatternsInRange(signature, start, size, limit = 0) {
113
+ if (this._pid !== Kernel32Impl.GetCurrentProcessId()) {
114
+ throw new Error('Memory scanning is only supported for the current process');
115
+ }
116
+ const pattern = signature instanceof Pattern ? signature : new Pattern(signature, limit);
117
+ const results = [];
118
+ const searchLimit = limit > 0 ? limit : pattern.limit > 0 ? pattern.limit : -1;
119
+ const hasLimit = searchLimit !== -1;
120
+ for (const addr of Scanner.scan(start, size, pattern)) {
121
+ results.push(addr);
122
+ if (hasLimit && results.length >= searchLimit)
123
+ break;
124
+ }
125
+ return results;
126
+ }
127
+ /**
128
+ * Finds a pattern in all committed and readable memory of the process
129
+ */
130
+ findPattern(signature) {
131
+ const results = this.findAllPatterns(signature, 1);
132
+ return results[0] ?? null;
133
+ }
134
+ /**
135
+ * Finds all matches of a pattern in all committed and readable memory
136
+ */
137
+ findAllPatterns(signature, limit = 0) {
138
+ const results = [];
139
+ let address = 0n;
140
+ const pattern = signature instanceof Pattern ? signature : new Pattern(signature, limit);
141
+ const searchLimit = limit > 0 ? limit : pattern.limit > 0 ? pattern.limit : -1;
142
+ const hasLimit = searchLimit !== -1;
143
+ // Max address for x64 user-space: 0x7FFFFFFFFFFF
144
+ const maxAddress = 0x7fffffffffffn;
145
+ try {
146
+ while (address < maxAddress) {
147
+ const mbi = this.virtualQuery(address);
148
+ // Region is committed, not guarded, and has some form of read access
149
+ const isReadable = mbi.State === MemoryState.COMMIT &&
150
+ !(mbi.Protect & MemoryProtection.GUARD) &&
151
+ (mbi.Protect & MemoryProtection.READONLY ||
152
+ mbi.Protect & MemoryProtection.READWRITE ||
153
+ mbi.Protect & MemoryProtection.EXECUTE_READ ||
154
+ mbi.Protect & MemoryProtection.EXECUTE_READWRITE);
155
+ if (isReadable) {
156
+ const regionLimit = hasLimit ? searchLimit - results.length : 0;
157
+ const regionResults = this.findAllPatternsInRange(pattern, BigInt(mbi.BaseAddress), Number(mbi.RegionSize), regionLimit);
158
+ results.push(...regionResults);
159
+ if (hasLimit && results.length >= searchLimit)
160
+ break;
161
+ }
162
+ const nextAddress = BigInt(mbi.BaseAddress) + BigInt(mbi.RegionSize);
163
+ if (nextAddress <= address)
164
+ break;
165
+ address = nextAddress;
166
+ }
167
+ }
168
+ catch {
169
+ // Loop finished
170
+ }
171
+ return results;
172
+ }
173
+ /**
174
+ * Scans specific loaded modules for a given pattern.
175
+ * Finds the first pattern match across the specified (or default) modules.
176
+ * @param signature Pattern string (e.g. "55 8B EC ?? 56") or Pattern object
177
+ * @param moduleNames Array of module names (e.g. ['kernel32.dll', 'msvcrt.dll'])
178
+ * @returns The first matched address, or null if not found
179
+ */
180
+ findPatternFromModules(signature, moduleNames = []) {
181
+ const results = this.findAllPatternsFromModules(signature, moduleNames, 1);
182
+ return results[0] ?? null;
183
+ }
184
+ /**
185
+ * Finds all matches of a pattern across specified modules
186
+ */
187
+ findAllPatternsFromModules(signature, moduleNames = [], limit = 0) {
188
+ // Lazy load Module to prevent circular dependencies at the top level
189
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
190
+ const { Module, STATIC_MODULES } = require('./module');
191
+ if (this._pid !== Kernel32Impl.GetCurrentProcessId()) {
192
+ throw new Error('Module scanning is only supported for the current process');
193
+ }
194
+ if (moduleNames.length === 0) {
195
+ moduleNames = Object.values(STATIC_MODULES);
196
+ }
197
+ const pattern = signature instanceof Pattern ? signature : new Pattern(signature, limit);
198
+ const results = [];
199
+ const searchLimit = limit > 0 ? limit : pattern.limit > 0 ? pattern.limit : -1;
200
+ const hasLimit = searchLimit !== -1;
201
+ for (const name of moduleNames) {
202
+ try {
203
+ const mod = Module.get(name);
204
+ const modResults = mod.findAllPatterns(pattern);
205
+ for (const addr of modResults) {
206
+ results.push(addr);
207
+ if (hasLimit && results.length >= searchLimit)
208
+ break;
209
+ }
210
+ if (hasLimit && results.length >= searchLimit)
211
+ break;
212
+ }
213
+ catch (err) {
214
+ processLog.warn(`findAllPatternsFromModules: Failed to process module ${name}: ${err}`);
215
+ }
216
+ }
217
+ return results;
218
+ }
219
+ static current() {
220
+ return currentProcess;
221
+ }
222
+ get pid() {
223
+ return this._pid;
224
+ }
225
+ }
226
+ /**
227
+ * Represents the current process (singleton)
228
+ */
229
+ export class CurrentProcess extends Process {
230
+ constructor() {
231
+ // Current process uses a pseudo-handle that doesn't need closing
232
+ super(Kernel32Impl.GetCurrentProcess(), Kernel32Impl.GetCurrentProcessId());
233
+ }
234
+ createThread(startAddress, parameter, stackSize = 0, flags, attributes) {
235
+ return Thread.create(startAddress, parameter, stackSize, flags, attributes);
236
+ }
237
+ alloc(size, address = null, allocationType = MemoryState.COMMIT | MemoryState.RESERVE, protection = MemoryProtection.READWRITE) {
238
+ const result = Kernel32Impl.VirtualAlloc(address, size, allocationType, protection);
239
+ if (!result) {
240
+ processLog.error(`VirtualAlloc failed (size: ${size})`);
241
+ }
242
+ return result;
243
+ }
244
+ free(address, size = 0, freeType = MemoryFreeType.RELEASE) {
245
+ const result = Kernel32Impl.VirtualFree(address, size, freeType);
246
+ if (!result) {
247
+ const addrHex = ffi.address(address).toString(16).toUpperCase();
248
+ processLog.error(`VirtualFree failed at 0x${addrHex}`);
249
+ }
250
+ return !!result;
251
+ }
252
+ close() {
253
+ this._handle = null;
254
+ }
255
+ }
256
+ // Export a pre-initialized instance of the current process (lazy via Proxy)
257
+ let _currentProcess;
258
+ export const currentProcess = new Proxy({}, {
259
+ get(_target, prop, receiver) {
260
+ if (!_currentProcess) {
261
+ _currentProcess = new CurrentProcess();
262
+ }
263
+ return Reflect.get(_currentProcess, prop, receiver);
264
+ },
265
+ getPrototypeOf() {
266
+ return CurrentProcess.prototype;
267
+ },
268
+ });
269
+ //# sourceMappingURL=process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"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"}