@cheatron/native 1.1.0 → 1.2.1
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 +17 -4
- package/dist/{src/handle.d.ts → handle.d.ts} +4 -0
- package/dist/handle.d.ts.map +1 -0
- package/dist/{src/handle.js → handle.js} +3 -3
- package/dist/handle.js.map +1 -0
- package/dist/{src/index.d.ts → index.d.ts} +8 -3
- package/dist/index.d.ts.map +1 -0
- package/dist/{src/index.js → index.js} +7 -2
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js.map +1 -0
- package/dist/module.d.ts +38 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +106 -0
- package/dist/module.js.map +1 -0
- package/dist/msvcrt-ext.d.ts +20 -0
- package/dist/msvcrt-ext.d.ts.map +1 -0
- package/dist/msvcrt-ext.js +120 -0
- package/dist/msvcrt-ext.js.map +1 -0
- package/dist/native-fn.d.ts +73 -0
- package/dist/native-fn.d.ts.map +1 -0
- package/dist/native-fn.js +214 -0
- package/dist/native-fn.js.map +1 -0
- package/dist/pattern.d.ts +36 -0
- package/dist/pattern.d.ts.map +1 -0
- package/dist/pattern.js +79 -0
- package/dist/pattern.js.map +1 -0
- package/dist/process.d.ts +104 -0
- package/dist/process.d.ts.map +1 -0
- package/dist/process.js +402 -0
- package/dist/process.js.map +1 -0
- package/dist/scan-result.d.ts +54 -0
- package/dist/scan-result.d.ts.map +1 -0
- package/dist/scan-result.js +128 -0
- package/dist/scan-result.js.map +1 -0
- package/dist/scanner.d.ts +22 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +116 -0
- package/dist/scanner.js.map +1 -0
- package/dist/thread.d.ts.map +1 -0
- package/dist/{src/thread.js → thread.js} +1 -1
- package/dist/thread.js.map +1 -0
- package/package.json +3 -2
- package/dist/eslint.config.d.ts +0 -3
- package/dist/eslint.config.d.ts.map +0 -1
- package/dist/eslint.config.js +0 -26
- package/dist/eslint.config.js.map +0 -1
- package/dist/src/handle.d.ts.map +0 -1
- package/dist/src/handle.js.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/logger.d.ts.map +0 -1
- package/dist/src/logger.js.map +0 -1
- package/dist/src/module.d.ts +0 -22
- package/dist/src/module.d.ts.map +0 -1
- package/dist/src/module.js +0 -55
- package/dist/src/module.js.map +0 -1
- package/dist/src/process.d.ts +0 -30
- package/dist/src/process.d.ts.map +0 -1
- package/dist/src/process.js +0 -104
- package/dist/src/process.js.map +0 -1
- package/dist/src/thread.d.ts.map +0 -1
- package/dist/src/thread.js.map +0 -1
- package/dist/tests/integration/memory.test.d.ts +0 -2
- package/dist/tests/integration/memory.test.d.ts.map +0 -1
- package/dist/tests/integration/memory.test.js +0 -82
- package/dist/tests/integration/memory.test.js.map +0 -1
- package/dist/tests/integration/thread.test.d.ts +0 -2
- package/dist/tests/integration/thread.test.d.ts.map +0 -1
- package/dist/tests/integration/thread.test.js +0 -37
- package/dist/tests/integration/thread.test.js.map +0 -1
- package/dist/tests/setup.d.ts +0 -2
- package/dist/tests/setup.d.ts.map +0 -1
- package/dist/tests/setup.js +0 -3
- package/dist/tests/setup.js.map +0 -1
- package/dist/tests/unit/kernel32.test.d.ts +0 -2
- package/dist/tests/unit/kernel32.test.d.ts.map +0 -1
- package/dist/tests/unit/kernel32.test.js +0 -28
- package/dist/tests/unit/kernel32.test.js.map +0 -1
- package/dist/tests/unit/logger.test.d.ts +0 -2
- package/dist/tests/unit/logger.test.d.ts.map +0 -1
- package/dist/tests/unit/logger.test.js +0 -29
- package/dist/tests/unit/logger.test.js.map +0 -1
- package/dist/tests/unit/msvcrt.test.d.ts +0 -2
- package/dist/tests/unit/msvcrt.test.d.ts.map +0 -1
- package/dist/tests/unit/msvcrt.test.js +0 -22
- package/dist/tests/unit/msvcrt.test.js.map +0 -1
- package/dist/tests/unit/process.test.d.ts +0 -2
- package/dist/tests/unit/process.test.d.ts.map +0 -1
- package/dist/tests/unit/process.test.js +0 -27
- package/dist/tests/unit/process.test.js.map +0 -1
- package/dist/tests/unit/thread.test.d.ts +0 -2
- package/dist/tests/unit/thread.test.d.ts.map +0 -1
- package/dist/tests/unit/thread.test.js +0 -35
- package/dist/tests/unit/thread.test.js.map +0 -1
- package/dist/tests/unit/thread_creation.test.d.ts +0 -2
- package/dist/tests/unit/thread_creation.test.d.ts.map +0 -1
- package/dist/tests/unit/thread_creation.test.js +0 -31
- package/dist/tests/unit/thread_creation.test.js.map +0 -1
- /package/dist/{src/logger.d.ts → logger.d.ts} +0 -0
- /package/dist/{src/logger.js → logger.js} +0 -0
- /package/dist/{src/thread.d.ts → thread.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -9,11 +9,13 @@ Ergonomic Win32 process and memory management API for Cheatron, powered by [Bun]
|
|
|
9
9
|
|
|
10
10
|
- **Process Management**: Open processes by PID, access the current process, and query memory information.
|
|
11
11
|
- **Memory Operations**: Read and write memory buffers from/to target processes.
|
|
12
|
-
- **Thread Management**: Create local/remote threads, get/set thread context, suspend/resume, and track exit codes.
|
|
13
|
-
- **Module Helper**: Easy access to loaded modules
|
|
14
|
-
- **
|
|
12
|
+
- **Thread Management**: Create local/remote threads (supports `CREATE_SUSPENDED` flags), get/set thread context, suspend/resume, and track exit codes.
|
|
13
|
+
- **Module Helper**: Easy access to loaded modules, complete `MODULEINFO` retrieval, module dimension sizing, and function addresses.
|
|
14
|
+
- **High-Performance Pattern Scanning**: Memory scanning powered by chunked processing and an assembly-injected `memmem` for wildcard-free patterns. Supports full process scan via `VirtualQuery`, module-scoped scan, or arbitrary range scan.
|
|
15
|
+
- **Assembly Generation**: Test x86 assembly scripts and integrate safely with `@cheatron/keystone`.
|
|
16
|
+
- **Low-level FFI**: Direct access to `Kernel32Impl`, `psapi`, and `MsvcrtImpl` (includes `memcmp` and `memmem`) for advanced Win32 API calls.
|
|
15
17
|
- **Safe Handles**: Automatic handle cleanup using `FinalizationRegistry`.
|
|
16
|
-
- **Integrated Logging**:
|
|
18
|
+
- **Integrated Logging**: Centralized, shared static logging powered by `@cheatron/log`.
|
|
17
19
|
|
|
18
20
|
## Installation
|
|
19
21
|
|
|
@@ -72,6 +74,17 @@ Enumerate and interact with loaded DLLs.
|
|
|
72
74
|
- `Module.get(name: string): Module`
|
|
73
75
|
- `Module.kernel32 / Module.crt`: Pre-defined instances.
|
|
74
76
|
- `getProcAddress(name: string): bigint`
|
|
77
|
+
- Retrieve memory size via `MODULEINFO` querying.
|
|
78
|
+
|
|
79
|
+
### Scanner & Pattern
|
|
80
|
+
|
|
81
|
+
High-performance memory pattern matching — no wildcards uses an **assembly-injected `memmem`** (faster than any JS-side byte loop), wildcard patterns use chunked byte comparison. Scanning is generator-based so it yields immediately on first match without loading all results into memory.
|
|
82
|
+
|
|
83
|
+
- `new Pattern("55 8B EC ?? 56")` — Create signatures with wildcard support.
|
|
84
|
+
- `process.findPattern(sig)` — **Full process scan** via `VirtualQuery` (all committed readable regions).
|
|
85
|
+
- `process.findPatternFromModules(sig, ['kernel32.dll'])` — Module-scoped scan.
|
|
86
|
+
- `process.findPatternInRange(sig, start, size)` — Arbitrary range scan.
|
|
87
|
+
- All of the above have `findAll*` variants that return every match.
|
|
75
88
|
|
|
76
89
|
## Advanced FFI
|
|
77
90
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle.d.ts","sourceRoot":"","sources":["../src/handle.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,UAAU,EACV,KAAK,MAAM,EACZ,MAAM,2BAA2B,CAAC;AAKnC;;GAEG;AACH,eAAO,MAAM,cAAc,8BAIzB,CAAC;AAEH;;GAEG;AACH,qBAAa,MAAM;IACjB,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEd,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,OAAc;IAOrD;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,KAAK;IASL;;;OAGG;IACH,IAAI,CAAC,SAAS,GAAE,MAAiB,GAAG,UAAU;IAS9C;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;CACF"}
|
|
@@ -4,7 +4,7 @@ const handleLog = log.child('Handle');
|
|
|
4
4
|
/**
|
|
5
5
|
* Handle management registry for automatic cleanup
|
|
6
6
|
*/
|
|
7
|
-
const
|
|
7
|
+
export const handleRegistry = new FinalizationRegistry((handle) => {
|
|
8
8
|
if (handle) {
|
|
9
9
|
Kernel32Impl.CloseHandle(handle);
|
|
10
10
|
}
|
|
@@ -17,7 +17,7 @@ export class Handle {
|
|
|
17
17
|
constructor(handle, autoClose = true) {
|
|
18
18
|
this._handle = handle;
|
|
19
19
|
if (autoClose && handle) {
|
|
20
|
-
|
|
20
|
+
handleRegistry.register(this, handle, this);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
@@ -33,7 +33,7 @@ export class Handle {
|
|
|
33
33
|
if (this.isValid()) {
|
|
34
34
|
const h = this._handle;
|
|
35
35
|
this._handle = null;
|
|
36
|
-
|
|
36
|
+
handleRegistry.unregister(this);
|
|
37
37
|
Kernel32Impl.CloseHandle(h);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle.js","sourceRoot":"","sources":["../src/handle.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,UAAU,GAEX,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAEtC;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,oBAAoB,CAAS,CAAC,MAAM,EAAE,EAAE;IACxE,IAAI,MAAM,EAAE,CAAC;QACX,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;AACH,CAAC,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,OAAO,MAAM;IACP,OAAO,CAAS;IAE1B,YAAY,MAAc,EAAE,YAAqB,IAAI;QACnD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;YACxB,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO;QACL,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,IAAK,CAAC;YACrB,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAChC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,YAAoB,QAAQ;QAC/B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACzD,SAAS,CAAC,KAAK,CAAC,0CAA0C,SAAS,KAAK,CAAC,CAAC;QAC1E,OAAO,YAAY,CAAC,mBAAmB,CACrC,IAAI,CAAC,OAAO,EACZ,SAAS,CACI,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF"}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
export { log } from './logger';
|
|
2
|
+
export * from '@cheatron/native-bindings';
|
|
3
|
+
export type * from '@cheatron/native-bindings';
|
|
4
|
+
export * from './handle';
|
|
5
|
+
export * from './pattern';
|
|
6
|
+
export * from './scan-result';
|
|
7
|
+
export * from './scanner';
|
|
2
8
|
export * from './thread';
|
|
3
9
|
export * from './process';
|
|
4
10
|
export * from './module';
|
|
5
|
-
export * from './
|
|
6
|
-
export * from '
|
|
7
|
-
export type * from '@cheatron/native-bindings';
|
|
11
|
+
export * from './native-fn';
|
|
12
|
+
export * from './msvcrt-ext';
|
|
8
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,mBAAmB,2BAA2B,CAAC;AAE/C,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export { log } from './logger';
|
|
2
|
+
export * from '@cheatron/native-bindings';
|
|
3
|
+
export * from './handle';
|
|
4
|
+
export * from './pattern';
|
|
5
|
+
export * from './scan-result';
|
|
6
|
+
export * from './scanner';
|
|
2
7
|
export * from './thread';
|
|
3
8
|
export * from './process';
|
|
4
9
|
export * from './module';
|
|
5
|
-
export * from './
|
|
6
|
-
export * from '
|
|
10
|
+
export * from './native-fn';
|
|
11
|
+
export * from './msvcrt-ext';
|
|
7
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAG1C,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,GAAG,uCAA4B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,CAAC,MAAM,GAAG,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC"}
|
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type HMODULE, type INT_PTR, type ModuleInfo } from '@cheatron/native-bindings';
|
|
2
|
+
import { Handle } from './handle';
|
|
3
|
+
import { Pattern } from './pattern';
|
|
4
|
+
import { ScanResult } from './scan-result';
|
|
5
|
+
export declare const STATIC_MODULES: Record<string, string>;
|
|
6
|
+
/**
|
|
7
|
+
* Represents a loaded module
|
|
8
|
+
*/
|
|
9
|
+
export declare class Module extends Handle {
|
|
10
|
+
protected _name: string;
|
|
11
|
+
readonly base: bigint;
|
|
12
|
+
readonly size: number;
|
|
13
|
+
readonly entryPoint: bigint;
|
|
14
|
+
readonly end: bigint;
|
|
15
|
+
readonly info: ModuleInfo;
|
|
16
|
+
static readonly ntdll: Module;
|
|
17
|
+
static readonly kernel32: Module;
|
|
18
|
+
static readonly kernelbase: Module;
|
|
19
|
+
static readonly crt: Module;
|
|
20
|
+
private static _staticCache;
|
|
21
|
+
constructor(handle: HMODULE, name: string);
|
|
22
|
+
/**
|
|
23
|
+
* Gets a module handle for the specified module name
|
|
24
|
+
* Automatically detects if the name is ANSI or Unicode
|
|
25
|
+
* @param name Module name (e.g., 'kernel32.dll')
|
|
26
|
+
*/
|
|
27
|
+
static get(name: string): Module;
|
|
28
|
+
getProcAddress(procName: string): INT_PTR;
|
|
29
|
+
get name(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Finds pattern matches within this module.
|
|
32
|
+
* Configure limit and protect filter on the Pattern object.
|
|
33
|
+
* @returns ScanResult with each entry tagged with this module
|
|
34
|
+
*/
|
|
35
|
+
findPattern(signature: string | Pattern): ScanResult;
|
|
36
|
+
toString(): string;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,UAAU,EAChB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAI3C,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKjD,CAAC;AAEF;;GAEG;AACH,qBAAa,MAAO,SAAQ,MAAM;IAChC,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC;IAExB,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,SAAgB,IAAI,EAAE,UAAU,CAAC;IAGjC,gBAAwB,KAAK,EAAE,MAAM,CAAC;IACtC,gBAAwB,QAAQ,EAAE,MAAM,CAAC;IACzC,gBAAwB,UAAU,EAAE,MAAM,CAAC;IAC3C,gBAAwB,GAAG,EAAE,MAAM,CAAC;IAEpC,OAAO,CAAC,MAAM,CAAC,YAAY,CAA8B;gBAE7C,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM;IAyBzC;;;;OAIG;IACH,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IA2BhC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAazC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;OAIG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU;IAW3C,QAAQ,IAAI,MAAM;CAG5B"}
|
package/dist/module.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { ffi, Kernel32Impl, PsapiImpl, MODULEINFO, MODULEINFO_SIZE, } from '@cheatron/native-bindings';
|
|
2
|
+
import { Handle } from './handle';
|
|
3
|
+
import { log } from './logger';
|
|
4
|
+
import { Pattern } from './pattern';
|
|
5
|
+
import { ScanResult } from './scan-result';
|
|
6
|
+
const moduleLog = log.child('Module');
|
|
7
|
+
export const STATIC_MODULES = {
|
|
8
|
+
ntdll: 'ntdll.dll',
|
|
9
|
+
kernel32: 'kernel32.dll',
|
|
10
|
+
kernelbase: 'kernelbase.dll',
|
|
11
|
+
crt: 'msvcrt.dll',
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Represents a loaded module
|
|
15
|
+
*/
|
|
16
|
+
export class Module extends Handle {
|
|
17
|
+
_name;
|
|
18
|
+
base;
|
|
19
|
+
size;
|
|
20
|
+
entryPoint;
|
|
21
|
+
end;
|
|
22
|
+
info;
|
|
23
|
+
static _staticCache = {};
|
|
24
|
+
constructor(handle, name) {
|
|
25
|
+
// Module handles from GetModuleHandle should not be closed with CloseHandle
|
|
26
|
+
super(handle, false);
|
|
27
|
+
this._name = name;
|
|
28
|
+
const processHandle = Kernel32Impl.GetCurrentProcess();
|
|
29
|
+
const moduleInfoBuffer = Buffer.alloc(MODULEINFO_SIZE);
|
|
30
|
+
const success = PsapiImpl.GetModuleInformation(processHandle, handle, moduleInfoBuffer, MODULEINFO_SIZE);
|
|
31
|
+
if (!success) {
|
|
32
|
+
throw new Error(`Failed to get module information for ${name}`);
|
|
33
|
+
}
|
|
34
|
+
this.info = ffi.decode(moduleInfoBuffer, MODULEINFO);
|
|
35
|
+
this.base = BigInt(this.info.lpBaseOfDll);
|
|
36
|
+
this.size = this.info.SizeOfImage;
|
|
37
|
+
this.entryPoint = BigInt(this.info.EntryPoint);
|
|
38
|
+
this.end = this.base + BigInt(this.size);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Gets a module handle for the specified module name
|
|
42
|
+
* Automatically detects if the name is ANSI or Unicode
|
|
43
|
+
* @param name Module name (e.g., 'kernel32.dll')
|
|
44
|
+
*/
|
|
45
|
+
static get(name) {
|
|
46
|
+
const lowerName = name.toLowerCase();
|
|
47
|
+
// Fast path for static core modules to prevent redundant handle requests
|
|
48
|
+
for (const key of Object.keys(STATIC_MODULES)) {
|
|
49
|
+
if (lowerName === STATIC_MODULES[key]?.toLowerCase() &&
|
|
50
|
+
this._staticCache[key]) {
|
|
51
|
+
return this._staticCache[key];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
moduleLog.debug(`Getting module handle for: ${name}`);
|
|
55
|
+
// Simple ASCII check: any char > 127 means we should use Unicode API
|
|
56
|
+
const isUnicode = Array.from(name).some((char) => char.charCodeAt(0) > 127);
|
|
57
|
+
const handle = isUnicode
|
|
58
|
+
? Kernel32Impl.GetModuleHandleW(name)
|
|
59
|
+
: Kernel32Impl.GetModuleHandleA(name);
|
|
60
|
+
if (!handle) {
|
|
61
|
+
throw new Error(`Failed to get module handle for ${name}`);
|
|
62
|
+
}
|
|
63
|
+
return new Module(handle, name);
|
|
64
|
+
}
|
|
65
|
+
getProcAddress(procName) {
|
|
66
|
+
if (!this.isValid())
|
|
67
|
+
throw new Error('Module handle is closed');
|
|
68
|
+
const address = Kernel32Impl.GetProcAddress(this._handle, procName);
|
|
69
|
+
if (!address) {
|
|
70
|
+
throw new Error(`Failed to get proc address for ${procName}`);
|
|
71
|
+
}
|
|
72
|
+
return address;
|
|
73
|
+
}
|
|
74
|
+
get name() {
|
|
75
|
+
return this._name;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Finds pattern matches within this module.
|
|
79
|
+
* Configure limit and protect filter on the Pattern object.
|
|
80
|
+
* @returns ScanResult with each entry tagged with this module
|
|
81
|
+
*/
|
|
82
|
+
findPattern(signature) {
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
84
|
+
const { CurrentProcess } = require('./process');
|
|
85
|
+
return CurrentProcess.current().findPatternInRange(signature, this.base, this.size, this);
|
|
86
|
+
}
|
|
87
|
+
toString() {
|
|
88
|
+
return `Module(${this.name})[0x${this.base.toString(16)}-0x${this.end.toString(16)}]`;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Initialize dynamic static getters for modules
|
|
92
|
+
for (const [propName, dllName] of Object.entries(STATIC_MODULES)) {
|
|
93
|
+
Object.defineProperty(Module, propName, {
|
|
94
|
+
get() {
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
96
|
+
const self = Module;
|
|
97
|
+
if (!self._staticCache[propName]) {
|
|
98
|
+
self._staticCache[propName] = Module.get(dllName);
|
|
99
|
+
}
|
|
100
|
+
return self._staticCache[propName];
|
|
101
|
+
},
|
|
102
|
+
enumerable: true,
|
|
103
|
+
configurable: true,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { MsvcrtImpl } from '@cheatron/native-bindings';
|
|
2
|
+
import type { LPVOID, SIZE_T } from '@cheatron/native-bindings';
|
|
3
|
+
type MemmemFn = (haystack: LPVOID, haystackLen: SIZE_T, needle: LPVOID, needleLen: SIZE_T) => LPVOID;
|
|
4
|
+
/**
|
|
5
|
+
* memmem - Find the first occurrence of a byte sequence in memory.
|
|
6
|
+
*/
|
|
7
|
+
export declare function memmem(haystack: LPVOID, haystackLen: SIZE_T, needle: LPVOID, needleLen: SIZE_T): LPVOID;
|
|
8
|
+
/**
|
|
9
|
+
* Extended MSVCRT interface including custom assembly functions
|
|
10
|
+
*/
|
|
11
|
+
export interface MSVCRTExt {
|
|
12
|
+
memmem: MemmemFn;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Extended MsvcrtImpl with custom functions typed in.
|
|
16
|
+
* Uses a Proxy to provide lazy memmem access without patching the base object.
|
|
17
|
+
*/
|
|
18
|
+
export declare const MsvcrtExtImpl: typeof MsvcrtImpl & MSVCRTExt;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=msvcrt-ext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msvcrt-ext.d.ts","sourceRoot":"","sources":["../src/msvcrt-ext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAO,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AA4FhE,KAAK,QAAQ,GAAG,CACd,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,KACd,MAAM,CAAC;AAsCZ;;GAEG;AACH,wBAAgB,MAAM,CACpB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,MAAM,CAGR;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,QAAQ,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAOpB,OAAO,UAAU,GAAG,SAAS,CAAC"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { MsvcrtImpl, Def } from '@cheatron/native-bindings';
|
|
2
|
+
import { nativeFn } from './native-fn';
|
|
3
|
+
import { log } from './logger';
|
|
4
|
+
const extLog = log.child('MsvcrtExt');
|
|
5
|
+
/**
|
|
6
|
+
* x86-64 assembly implementation of memmem.
|
|
7
|
+
* Finds the first occurrence of a needle in a haystack.
|
|
8
|
+
*/
|
|
9
|
+
const MEMMEM_ASM = [
|
|
10
|
+
// Prologue — save nonvolatile registers
|
|
11
|
+
'push rbx',
|
|
12
|
+
'push rsi',
|
|
13
|
+
'push rdi',
|
|
14
|
+
'push r12',
|
|
15
|
+
'push r13',
|
|
16
|
+
'push r14',
|
|
17
|
+
// Save args to nonvolatile regs
|
|
18
|
+
'mov rsi, rcx', // rsi = haystack
|
|
19
|
+
'mov r12, rdx', // r12 = haystackLen
|
|
20
|
+
'mov rdi, r8', // rdi = needle
|
|
21
|
+
'mov r13, r9', // r13 = needleLen
|
|
22
|
+
// needleLen == 0? return haystack
|
|
23
|
+
'test r13, r13',
|
|
24
|
+
'jz _ret_hs',
|
|
25
|
+
// needleLen > haystackLen? return NULL
|
|
26
|
+
'cmp r13, r12',
|
|
27
|
+
'ja _ret_null',
|
|
28
|
+
// r14 = outer limit = haystackLen - needleLen + 1
|
|
29
|
+
'mov r14, r12',
|
|
30
|
+
'sub r14, r13',
|
|
31
|
+
'inc r14',
|
|
32
|
+
// rbx = i (outer)
|
|
33
|
+
'xor rbx, rbx',
|
|
34
|
+
'_outer:',
|
|
35
|
+
'cmp rbx, r14',
|
|
36
|
+
'jae _ret_null',
|
|
37
|
+
// rcx = j (inner)
|
|
38
|
+
'xor rcx, rcx',
|
|
39
|
+
'_inner:',
|
|
40
|
+
'cmp rcx, r13',
|
|
41
|
+
'jae _found',
|
|
42
|
+
// Compare haystack[i+j] vs needle[j]
|
|
43
|
+
'mov rax, rbx',
|
|
44
|
+
'add rax, rcx',
|
|
45
|
+
'movzx eax, byte ptr [rsi + rax]',
|
|
46
|
+
'movzx edx, byte ptr [rdi + rcx]',
|
|
47
|
+
'cmp al, dl',
|
|
48
|
+
'jne _next',
|
|
49
|
+
'inc rcx',
|
|
50
|
+
'jmp _inner',
|
|
51
|
+
'_next:',
|
|
52
|
+
'inc rbx',
|
|
53
|
+
'jmp _outer',
|
|
54
|
+
// Found match
|
|
55
|
+
'_found:',
|
|
56
|
+
'lea rax, [rsi + rbx]',
|
|
57
|
+
'jmp _done',
|
|
58
|
+
// Return haystack (needleLen == 0)
|
|
59
|
+
'_ret_hs:',
|
|
60
|
+
'mov rax, rsi',
|
|
61
|
+
'jmp _done',
|
|
62
|
+
// Return NULL
|
|
63
|
+
'_ret_null:',
|
|
64
|
+
'xor eax, eax',
|
|
65
|
+
'_done:',
|
|
66
|
+
'pop r14',
|
|
67
|
+
'pop r13',
|
|
68
|
+
'pop r12',
|
|
69
|
+
'pop rdi',
|
|
70
|
+
'pop rsi',
|
|
71
|
+
'pop rbx',
|
|
72
|
+
'ret',
|
|
73
|
+
].join('\n');
|
|
74
|
+
/* eslint-enable no-unused-vars */
|
|
75
|
+
let _memmemFn = null;
|
|
76
|
+
/**
|
|
77
|
+
* Ensures that the custom memmem assembly function is injected and returns it.
|
|
78
|
+
*/
|
|
79
|
+
function ensureMemmem() {
|
|
80
|
+
if (_memmemFn)
|
|
81
|
+
return _memmemFn;
|
|
82
|
+
// Check if it's already registered in the shared nativeFn instance
|
|
83
|
+
const existing = nativeFn.getFunction('memmem');
|
|
84
|
+
if (existing) {
|
|
85
|
+
_memmemFn = existing;
|
|
86
|
+
return _memmemFn;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Inject the assembly function
|
|
90
|
+
*/
|
|
91
|
+
const memmemAddr = nativeFn.add({
|
|
92
|
+
memmem: [Def.voidPtr, [Def.voidPtr, Def.uint64, Def.voidPtr, Def.uint64]],
|
|
93
|
+
}, MEMMEM_ASM);
|
|
94
|
+
_memmemFn = nativeFn.getFunction('memmem');
|
|
95
|
+
if (!_memmemFn) {
|
|
96
|
+
throw new Error('Failed to retrieve memmem function after injection');
|
|
97
|
+
}
|
|
98
|
+
extLog.info(`memmem injected at 0x${memmemAddr.toString(16).toUpperCase()}`);
|
|
99
|
+
return _memmemFn;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* memmem - Find the first occurrence of a byte sequence in memory.
|
|
103
|
+
*/
|
|
104
|
+
export function memmem(haystack, haystackLen, needle, needleLen) {
|
|
105
|
+
const fn = _memmemFn ?? ensureMemmem();
|
|
106
|
+
return fn(haystack, haystackLen, needle, needleLen);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Extended MsvcrtImpl with custom functions typed in.
|
|
110
|
+
* Uses a Proxy to provide lazy memmem access without patching the base object.
|
|
111
|
+
*/
|
|
112
|
+
export const MsvcrtExtImpl = new Proxy(MsvcrtImpl, {
|
|
113
|
+
get(target, prop, receiver) {
|
|
114
|
+
if (prop === 'memmem') {
|
|
115
|
+
return memmem;
|
|
116
|
+
}
|
|
117
|
+
return Reflect.get(target, prop, receiver);
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
//# sourceMappingURL=msvcrt-ext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msvcrt-ext.js","sourceRoot":"","sources":["../src/msvcrt-ext.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** Function signature: [returnType, [paramTypes...]] */
|
|
2
|
+
export type FnSig = [string, string[]];
|
|
3
|
+
/** Function definition: { name: [returnType, [paramTypes...]] } */
|
|
4
|
+
export type FnDef = Record<string, FnSig>;
|
|
5
|
+
/** Tracks a single registered native function */
|
|
6
|
+
interface FunctionEntry {
|
|
7
|
+
name: string;
|
|
8
|
+
address: bigint;
|
|
9
|
+
size: number;
|
|
10
|
+
sig: FnSig;
|
|
11
|
+
callable: (...args: unknown[]) => unknown;
|
|
12
|
+
}
|
|
13
|
+
export declare const ALIGN = 16;
|
|
14
|
+
/**
|
|
15
|
+
* Rounds a number up to the nearest multiple of 16.
|
|
16
|
+
*/
|
|
17
|
+
export declare function addressAlign16(n: number): number;
|
|
18
|
+
export declare const codeAlign16: typeof addressAlign16;
|
|
19
|
+
export declare const stackAlign16: typeof addressAlign16;
|
|
20
|
+
/**
|
|
21
|
+
* Dynamically creates callable native functions from assembly or bytecode.
|
|
22
|
+
*
|
|
23
|
+
* Functions are written into a single VirtualAlloc'd executable page and
|
|
24
|
+
* exposed as callable methods on the instance via koffi.
|
|
25
|
+
*/
|
|
26
|
+
export declare class NativeFunctionCreator {
|
|
27
|
+
private page;
|
|
28
|
+
private pageAddr;
|
|
29
|
+
private offset;
|
|
30
|
+
private capacity;
|
|
31
|
+
private ks;
|
|
32
|
+
private functions;
|
|
33
|
+
[key: string]: any;
|
|
34
|
+
constructor(capacity?: number);
|
|
35
|
+
/**
|
|
36
|
+
* Add a native function from assembly source code.
|
|
37
|
+
* @param def Function definition { name: [returnType, [paramTypes...]] }
|
|
38
|
+
* @param asmSource x86-64 assembly instructions
|
|
39
|
+
* @returns Address of the function
|
|
40
|
+
*/
|
|
41
|
+
add(def: FnDef, asmSource: string): bigint;
|
|
42
|
+
/**
|
|
43
|
+
* Add a native function from raw bytecode.
|
|
44
|
+
* @param def Function definition { name: [returnType, [paramTypes...]] }
|
|
45
|
+
* @param bytes Raw machine code bytes
|
|
46
|
+
* @returns Address of the function
|
|
47
|
+
*/
|
|
48
|
+
addBytes(def: FnDef, bytes: number[]): bigint;
|
|
49
|
+
/**
|
|
50
|
+
* Get the address of a registered function by name.
|
|
51
|
+
*/
|
|
52
|
+
getAddress(name: string): bigint | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Get the callable function by name.
|
|
55
|
+
*/
|
|
56
|
+
getFunction(name: string): ((...args: unknown[]) => unknown) | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Get info about all registered functions.
|
|
59
|
+
*/
|
|
60
|
+
list(): FunctionEntry[];
|
|
61
|
+
/**
|
|
62
|
+
* Get remaining capacity in bytes.
|
|
63
|
+
*/
|
|
64
|
+
get remaining(): number;
|
|
65
|
+
/**
|
|
66
|
+
* Free the executable memory page.
|
|
67
|
+
*/
|
|
68
|
+
destroy(): void;
|
|
69
|
+
private _writeAndBind;
|
|
70
|
+
}
|
|
71
|
+
export declare const nativeFn: NativeFunctionCreator;
|
|
72
|
+
export {};
|
|
73
|
+
//# sourceMappingURL=native-fn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-fn.d.ts","sourceRoot":"","sources":["../src/native-fn.ts"],"names":[],"mappings":"AA0CA,wDAAwD;AACxD,MAAM,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAEvC,mEAAmE;AACnE,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE1C,iDAAiD;AACjD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,KAAK,CAAC;IAEX,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;CAC3C;AAED,eAAO,MAAM,KAAK,KAAK,CAAC;AAExB;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,eAAO,MAAM,WAAW,uBAAiB,CAAC;AAC1C,eAAO,MAAM,YAAY,uBAAiB,CAAC;AAE3C;;;;;GAKG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,SAAS,CAAyC;IAE1D,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;gBAEP,QAAQ,GAAE,MAAa;IA+BnC;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAgB1C;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM;IAc7C;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI5C;;OAEG;IAEH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,SAAS;IAIxE;;OAEG;IACH,IAAI,IAAI,aAAa,EAAE;IAIvB;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;OAEG;IACH,OAAO,IAAI,IAAI;IA+Bf,OAAO,CAAC,aAAa;CA4DtB;AAOD,eAAO,MAAM,QAAQ,EAAE,qBAmBtB,CAAC"}
|