@cheatron/nthread 1.0.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/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/crt.d.ts +24 -0
- package/dist/crt.d.ts.map +1 -0
- package/dist/crt.js +28 -0
- package/dist/crt.js.map +1 -0
- package/dist/errors.d.ts +50 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +84 -0
- package/dist/errors.js.map +1 -0
- package/dist/globals.d.ts +48 -0
- package/dist/globals.d.ts.map +1 -0
- package/dist/globals.js +132 -0
- package/dist/globals.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +2 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +3 -0
- package/dist/logger.js.map +1 -0
- package/dist/memory/alloc-options.d.ts +23 -0
- package/dist/memory/alloc-options.d.ts.map +1 -0
- package/dist/memory/alloc-options.js +1 -0
- package/dist/memory/alloc-options.js.map +1 -0
- package/dist/memory/heap.d.ts +147 -0
- package/dist/memory/heap.d.ts.map +1 -0
- package/dist/memory/heap.js +276 -0
- package/dist/memory/heap.js.map +1 -0
- package/dist/memory/romem.d.ts +69 -0
- package/dist/memory/romem.d.ts.map +1 -0
- package/dist/memory/romem.js +108 -0
- package/dist/memory/romem.js.map +1 -0
- package/dist/nthread-heap.d.ts +65 -0
- package/dist/nthread-heap.d.ts.map +1 -0
- package/dist/nthread-heap.js +193 -0
- package/dist/nthread-heap.js.map +1 -0
- package/dist/nthread.d.ts +146 -0
- package/dist/nthread.d.ts.map +1 -0
- package/dist/nthread.js +421 -0
- package/dist/nthread.js.map +1 -0
- package/dist/thread/captured-thread.d.ts +68 -0
- package/dist/thread/captured-thread.d.ts.map +1 -0
- package/dist/thread/captured-thread.js +167 -0
- package/dist/thread/captured-thread.js.map +1 -0
- package/dist/thread/proxy-thread.d.ts +92 -0
- package/dist/thread/proxy-thread.d.ts.map +1 -0
- package/dist/thread/proxy-thread.js +154 -0
- package/dist/thread/proxy-thread.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import * as Native from '@cheatron/native';
|
|
2
|
+
export const STACK_ADD = -8192n;
|
|
3
|
+
/**
|
|
4
|
+
* CapturedThread: A specialized Thread wrapper that manages the low-level state
|
|
5
|
+
* of a captured thread, including context caching, suspend/resume tracking,
|
|
6
|
+
* and register manipulation.
|
|
7
|
+
*
|
|
8
|
+
* It extends Native.Thread. A ProxyThread holds the reference back to this instance.
|
|
9
|
+
*/
|
|
10
|
+
export class CapturedThread extends Native.Thread {
|
|
11
|
+
/** Count of active suspensions to ensure balanced resume calls on close */
|
|
12
|
+
suspendCount = 0;
|
|
13
|
+
/** The register context captured immediately before hijacking */
|
|
14
|
+
savedContext;
|
|
15
|
+
/** The current live or modified context of the thread */
|
|
16
|
+
latestContext;
|
|
17
|
+
/** Pre-computed RSP value used for call() — set once during inject() */
|
|
18
|
+
callRsp = 0n;
|
|
19
|
+
/** Address of an infinite loop gadget ('jmp .') used to hold the thread */
|
|
20
|
+
sleepAddress;
|
|
21
|
+
/** The register key (e.g., 'Rbx') used for the pushret pivot */
|
|
22
|
+
regKey;
|
|
23
|
+
/**
|
|
24
|
+
* Creates a CapturedThread instance.
|
|
25
|
+
* @param thread Thread object or Thread ID to attach to.
|
|
26
|
+
* @param regKey The register key used for the pushret pivot.
|
|
27
|
+
* @param sleepAddress The sleep gadget address for parking the thread.
|
|
28
|
+
* @param processId Optional process ID for diagnostics and logging.
|
|
29
|
+
*/
|
|
30
|
+
constructor(thread, regKey, sleepAddress, processId) {
|
|
31
|
+
let threadObject;
|
|
32
|
+
if (thread instanceof Native.Thread) {
|
|
33
|
+
threadObject = thread;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
threadObject = Native.Thread.open(thread, processId);
|
|
37
|
+
}
|
|
38
|
+
const rawHandle = threadObject.rawHandle;
|
|
39
|
+
// Unregister original so CapturedThread owns the lifecycle via super()
|
|
40
|
+
Native.handleRegistry.unregister(threadObject);
|
|
41
|
+
super(rawHandle, threadObject.tid, true);
|
|
42
|
+
this.regKey = regKey;
|
|
43
|
+
this.sleepAddress = sleepAddress;
|
|
44
|
+
}
|
|
45
|
+
/** Calculates a new stack pointer offset from the current RSP */
|
|
46
|
+
calcStackBegin(baseRsp = BigInt(this.getContext().Rsp)) {
|
|
47
|
+
return Native.stackAlign16(baseRsp + STACK_ADD);
|
|
48
|
+
}
|
|
49
|
+
/** Gets the value of the pivot register */
|
|
50
|
+
getTargetReg() {
|
|
51
|
+
return this.getContext()[this.regKey];
|
|
52
|
+
}
|
|
53
|
+
/** Sets the value of the pivot register */
|
|
54
|
+
setTargetReg(reg) {
|
|
55
|
+
const ctx = this.getContext();
|
|
56
|
+
ctx[this.regKey] = reg;
|
|
57
|
+
this.setContext(ctx);
|
|
58
|
+
}
|
|
59
|
+
/** Helper to get RSP */
|
|
60
|
+
getRSP() {
|
|
61
|
+
return this.getContext().Rsp;
|
|
62
|
+
}
|
|
63
|
+
/** Helper to set RSP */
|
|
64
|
+
setRSP(rsp) {
|
|
65
|
+
const ctx = this.getContext();
|
|
66
|
+
ctx.Rsp = rsp;
|
|
67
|
+
this.setContext(ctx);
|
|
68
|
+
}
|
|
69
|
+
/** Helper to get RIP */
|
|
70
|
+
getRIP() {
|
|
71
|
+
return this.getContext().Rip;
|
|
72
|
+
}
|
|
73
|
+
/** Helper to set RIP */
|
|
74
|
+
setRIP(rip) {
|
|
75
|
+
const ctx = this.getContext();
|
|
76
|
+
ctx.Rip = rip;
|
|
77
|
+
this.setContext(ctx);
|
|
78
|
+
}
|
|
79
|
+
/** Returns the last fetched/modified context cache */
|
|
80
|
+
getContext() {
|
|
81
|
+
if (!this.latestContext) {
|
|
82
|
+
this.fetchContext();
|
|
83
|
+
}
|
|
84
|
+
return this.latestContext;
|
|
85
|
+
}
|
|
86
|
+
/** Updates the context cache (does not apply to hardware yet) */
|
|
87
|
+
setContext(ctx) {
|
|
88
|
+
this.latestContext = ctx;
|
|
89
|
+
}
|
|
90
|
+
/** Explicitly fetches context from the hardware into the cache */
|
|
91
|
+
fetchContext() {
|
|
92
|
+
this.latestContext = super.getContext();
|
|
93
|
+
}
|
|
94
|
+
/** Explicitly applies the cached context to the hardware */
|
|
95
|
+
applyContext() {
|
|
96
|
+
super.setContext(this.latestContext);
|
|
97
|
+
}
|
|
98
|
+
/** Suspends the thread and increments internal counter */
|
|
99
|
+
suspend() {
|
|
100
|
+
const result = super.suspend();
|
|
101
|
+
if (result) {
|
|
102
|
+
this.suspendCount++;
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
/** Resumes the thread and decrements internal counter */
|
|
107
|
+
resume() {
|
|
108
|
+
const result = super.resume();
|
|
109
|
+
if (result) {
|
|
110
|
+
this.suspendCount--;
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
/** Restores the saved context and resumes the thread (without closing the handle) */
|
|
115
|
+
release() {
|
|
116
|
+
this.suspend();
|
|
117
|
+
this.setContext(this.savedContext);
|
|
118
|
+
this.applyContext();
|
|
119
|
+
this.resume();
|
|
120
|
+
}
|
|
121
|
+
/** Closes the handle and ensures the thread is resumed if it was suspended by us */
|
|
122
|
+
close() {
|
|
123
|
+
try {
|
|
124
|
+
this.release();
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Thread may already be dead (e.g. ExitThread was called) — ignore
|
|
128
|
+
}
|
|
129
|
+
for (let i = 0; i < this.suspendCount; i++) {
|
|
130
|
+
try {
|
|
131
|
+
super.resume();
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
this.suspendCount = 0;
|
|
138
|
+
super.close();
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Custom wait that polls the thread's RIP to see if it landed at the sleepAddress.
|
|
142
|
+
* If the thread dies or crashes during wait, it returns FAILED.
|
|
143
|
+
*/
|
|
144
|
+
async wait(timeoutMs = Native.INFINITE) {
|
|
145
|
+
let count = 0;
|
|
146
|
+
while (count < timeoutMs) {
|
|
147
|
+
try {
|
|
148
|
+
this.fetchContext();
|
|
149
|
+
const rip = this.getContext().Rip;
|
|
150
|
+
if (BigInt(rip) === this.sleepAddress.valueOf()) {
|
|
151
|
+
return Native.WaitReturn.OBJECT_0;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch (_) {
|
|
155
|
+
const res = await super.wait(0);
|
|
156
|
+
if (res === Native.WaitReturn.OBJECT_0) {
|
|
157
|
+
return Native.WaitReturn.FAILED;
|
|
158
|
+
}
|
|
159
|
+
return res;
|
|
160
|
+
}
|
|
161
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
162
|
+
count++;
|
|
163
|
+
}
|
|
164
|
+
return Native.WaitReturn.TIMEOUT;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=captured-thread.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captured-thread.js","sourceRoot":"","sources":["../../src/thread/captured-thread.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as Native from '@cheatron/native';
|
|
2
|
+
import type { Arg } from '../nthread.js';
|
|
3
|
+
import type { AllocOptions } from '../memory/alloc-options.js';
|
|
4
|
+
/**
|
|
5
|
+
* Type signatures for proxy operations.
|
|
6
|
+
* Each receives the ProxyThread instance as the first argument for context.
|
|
7
|
+
*/
|
|
8
|
+
export type ReadMemoryFn = (proxy: ProxyThread, address: Native.NativePointer, size: number) => Promise<Buffer>;
|
|
9
|
+
export type WriteMemoryFn = (proxy: ProxyThread, address: Native.NativePointer, data: Buffer | Native.NativePointer, size?: number) => Promise<number>;
|
|
10
|
+
export type CallFn = (proxy: ProxyThread, address: Native.NativePointer, ...args: Arg[]) => Promise<Native.NativePointer>;
|
|
11
|
+
export type CloseFn = (proxy: ProxyThread, suicide?: number) => Promise<void>;
|
|
12
|
+
export type AllocFn = (proxy: ProxyThread, size: number, opts?: AllocOptions) => Promise<Native.NativePointer>;
|
|
13
|
+
export type FreeFn = (proxy: ProxyThread, ptr: Native.NativePointer) => Promise<void>;
|
|
14
|
+
/** Signature for a bound function on ProxyThread (e.g. proxy.malloc, proxy.memset) */
|
|
15
|
+
export type BoundCallFn = (...args: Arg[]) => Promise<Native.NativePointer>;
|
|
16
|
+
/**
|
|
17
|
+
* ProxyThread provides a high-level, extensible interface for interacting with a captured thread.
|
|
18
|
+
* Each operation (read, write, call) can be independently replaced via setter methods.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ProxyThread {
|
|
21
|
+
/** `msvcrt!fopen(path, mode)` */
|
|
22
|
+
fopen: (path: Arg, mode: Arg) => Promise<Native.NativePointer>;
|
|
23
|
+
/** `msvcrt!memset(dest, value, count)` */
|
|
24
|
+
memset: (dest: Arg, value: Arg, count: Arg) => Promise<Native.NativePointer>;
|
|
25
|
+
/** `msvcrt!malloc(size)` */
|
|
26
|
+
malloc: (size: Arg) => Promise<Native.NativePointer>;
|
|
27
|
+
/** `msvcrt!calloc(count, size)` */
|
|
28
|
+
calloc: (count: Arg, size: Arg) => Promise<Native.NativePointer>;
|
|
29
|
+
/** `msvcrt!fwrite(buffer, size, count, stream)` */
|
|
30
|
+
fwrite: (buffer: Arg, size: Arg, count: Arg, stream: Arg) => Promise<Native.NativePointer>;
|
|
31
|
+
/** `msvcrt!fflush(stream)` */
|
|
32
|
+
fflush: (stream: Arg) => Promise<Native.NativePointer>;
|
|
33
|
+
/** `msvcrt!fclose(stream)` */
|
|
34
|
+
fclose: (stream: Arg) => Promise<Native.NativePointer>;
|
|
35
|
+
/** `msvcrt!fread(buffer, size, count, stream)` */
|
|
36
|
+
fread: (buffer: Arg, size: Arg, count: Arg, stream: Arg) => Promise<Native.NativePointer>;
|
|
37
|
+
/** `msvcrt!realloc(ptr, size)` */
|
|
38
|
+
realloc: (ptr: Arg, size: Arg) => Promise<Native.NativePointer>;
|
|
39
|
+
private _read;
|
|
40
|
+
private _write;
|
|
41
|
+
private _call;
|
|
42
|
+
private _close;
|
|
43
|
+
private _alloc;
|
|
44
|
+
private _free;
|
|
45
|
+
constructor(close: CloseFn, process?: Native.Process);
|
|
46
|
+
/**
|
|
47
|
+
* Binds a named function onto this proxy instance.
|
|
48
|
+
* The bound function delegates to `this.call(address, ...args)`.
|
|
49
|
+
*
|
|
50
|
+
* @param name Function name — becomes a property on the proxy (e.g. 'malloc').
|
|
51
|
+
* @param address Target function address in the remote process.
|
|
52
|
+
*/
|
|
53
|
+
bind(name: string, address: Native.NativePointer): void;
|
|
54
|
+
/** Sets the read memory strategy */
|
|
55
|
+
setReader(fn: ReadMemoryFn): void;
|
|
56
|
+
/** Sets the write memory strategy */
|
|
57
|
+
setWriter(fn: WriteMemoryFn): void;
|
|
58
|
+
/** Sets the call strategy */
|
|
59
|
+
setCaller(fn: CallFn): void;
|
|
60
|
+
/** Sets the close strategy */
|
|
61
|
+
setCloser(fn: CloseFn): void;
|
|
62
|
+
/** Sets the alloc strategy */
|
|
63
|
+
setAllocer(fn: AllocFn): void;
|
|
64
|
+
/** Sets the free strategy */
|
|
65
|
+
setFreer(fn: FreeFn): void;
|
|
66
|
+
/** Reads memory from the remote process */
|
|
67
|
+
read(address: Native.NativePointer, size: number): Promise<Buffer>;
|
|
68
|
+
/** Writes memory into the remote process */
|
|
69
|
+
write(address: Native.NativePointer, data: Buffer | Native.NativePointer, size?: number): Promise<number>;
|
|
70
|
+
/** Calls a function, passing this proxy as context */
|
|
71
|
+
call(address: Native.NativePointer, ...args: Arg[]): Promise<Native.NativePointer>;
|
|
72
|
+
/**
|
|
73
|
+
* Restores the thread to its original state and releases it.
|
|
74
|
+
* @param suicide If provided, terminates the thread with this exit code instead of resuming it.
|
|
75
|
+
*/
|
|
76
|
+
close(suicide?: number): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Allocates memory in the remote process.
|
|
79
|
+
*
|
|
80
|
+
* - `opts.fill` undefined → `malloc(size)`
|
|
81
|
+
* - `opts.fill === 0` → `calloc(1, size)` (zero-initialized)
|
|
82
|
+
* - `opts.fill > 0` → `malloc(size)` + `memset(ptr, fill, size)`
|
|
83
|
+
* - `opts.type` → zone hint for HeapPool (READONLY / READWRITE)
|
|
84
|
+
* - `opts.address` → realloc mode: resize existing allocation
|
|
85
|
+
*/
|
|
86
|
+
alloc(size: number, opts?: AllocOptions): Promise<Native.NativePointer>;
|
|
87
|
+
/**
|
|
88
|
+
* Frees a previously allocated remote pointer.
|
|
89
|
+
*/
|
|
90
|
+
free(ptr: Native.NativePointer): Promise<void>;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=proxy-thread.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-thread.d.ts","sourceRoot":"","sources":["../../src/thread/proxy-thread.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import * as Native from '@cheatron/native';
|
|
2
|
+
import { crt } from '../crt.js';
|
|
3
|
+
/**
|
|
4
|
+
* ProxyThread provides a high-level, extensible interface for interacting with a captured thread.
|
|
5
|
+
* Each operation (read, write, call) can be independently replaced via setter methods.
|
|
6
|
+
*/
|
|
7
|
+
export class ProxyThread {
|
|
8
|
+
// Note: `free` is a first-class delegate method below — not a CRT auto-binding.
|
|
9
|
+
_read;
|
|
10
|
+
_write;
|
|
11
|
+
_call;
|
|
12
|
+
_close;
|
|
13
|
+
_alloc;
|
|
14
|
+
_free;
|
|
15
|
+
constructor(close, process) {
|
|
16
|
+
this._close = close;
|
|
17
|
+
this._read = async (_proxy, address, size) => {
|
|
18
|
+
if (!process)
|
|
19
|
+
throw new Error('read not configured and no Process provided.');
|
|
20
|
+
return process.memory.read(address, size);
|
|
21
|
+
};
|
|
22
|
+
this._write = async (_proxy, address, data, size) => {
|
|
23
|
+
if (!process)
|
|
24
|
+
throw new Error('write not configured and no Process provided.');
|
|
25
|
+
if (data instanceof Native.NativePointer) {
|
|
26
|
+
if (size) {
|
|
27
|
+
const written = process.memory.writeWithPointer(address, data, size);
|
|
28
|
+
if (written != size) {
|
|
29
|
+
throw new Error('Failed to write memory.');
|
|
30
|
+
}
|
|
31
|
+
return written;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
throw new Error('Size must be specified when writing a pointer.');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const writeSize = size ?? data.length;
|
|
39
|
+
const written = process.memory.write(address, data, writeSize);
|
|
40
|
+
if (written != writeSize) {
|
|
41
|
+
throw new Error('Failed to write memory.');
|
|
42
|
+
}
|
|
43
|
+
return written;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
this._call = async (_proxy, _address, ..._args) => {
|
|
47
|
+
throw new Error('call not configured.');
|
|
48
|
+
};
|
|
49
|
+
// Default alloc: malloc / calloc / malloc+memset depending on opts.fill
|
|
50
|
+
this._alloc = async (_proxy, size, opts) => {
|
|
51
|
+
if (opts?.address) {
|
|
52
|
+
// Basic realloc via CRT
|
|
53
|
+
const ptr = await this.realloc(opts.address.address, BigInt(size));
|
|
54
|
+
if (ptr.address === 0n)
|
|
55
|
+
throw new Error(`realloc(0x${opts.address.address.toString(16)}, ${size}) returned NULL`);
|
|
56
|
+
return ptr;
|
|
57
|
+
}
|
|
58
|
+
const fill = opts?.fill;
|
|
59
|
+
if (fill === undefined) {
|
|
60
|
+
return this.malloc(BigInt(size));
|
|
61
|
+
}
|
|
62
|
+
else if (fill === 0) {
|
|
63
|
+
return this.calloc(1n, BigInt(size));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const ptr = await this.malloc(BigInt(size));
|
|
67
|
+
await this.memset(ptr.address, BigInt(fill & 0xff), BigInt(size));
|
|
68
|
+
return ptr;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
// Default free: delegates to msvcrt!free via the call chain
|
|
72
|
+
this._free = async (_proxy, ptr) => {
|
|
73
|
+
await this.call(crt.free, ptr.address);
|
|
74
|
+
};
|
|
75
|
+
// Auto-bind all CRT functions except 'free' (free is a first-class delegate method)
|
|
76
|
+
for (const [name, address] of Object.entries(crt)) {
|
|
77
|
+
if (name !== 'free')
|
|
78
|
+
this.bind(name, address);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Binds a named function onto this proxy instance.
|
|
83
|
+
* The bound function delegates to `this.call(address, ...args)`.
|
|
84
|
+
*
|
|
85
|
+
* @param name Function name — becomes a property on the proxy (e.g. 'malloc').
|
|
86
|
+
* @param address Target function address in the remote process.
|
|
87
|
+
*/
|
|
88
|
+
bind(name, address) {
|
|
89
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
90
|
+
this[name] = (...args) => this.call(address, ...args);
|
|
91
|
+
}
|
|
92
|
+
/** Sets the read memory strategy */
|
|
93
|
+
setReader(fn) {
|
|
94
|
+
this._read = fn;
|
|
95
|
+
}
|
|
96
|
+
/** Sets the write memory strategy */
|
|
97
|
+
setWriter(fn) {
|
|
98
|
+
this._write = fn;
|
|
99
|
+
}
|
|
100
|
+
/** Sets the call strategy */
|
|
101
|
+
setCaller(fn) {
|
|
102
|
+
this._call = fn;
|
|
103
|
+
}
|
|
104
|
+
/** Sets the close strategy */
|
|
105
|
+
setCloser(fn) {
|
|
106
|
+
this._close = fn;
|
|
107
|
+
}
|
|
108
|
+
/** Sets the alloc strategy */
|
|
109
|
+
setAllocer(fn) {
|
|
110
|
+
this._alloc = fn;
|
|
111
|
+
}
|
|
112
|
+
/** Sets the free strategy */
|
|
113
|
+
setFreer(fn) {
|
|
114
|
+
this._free = fn;
|
|
115
|
+
}
|
|
116
|
+
/** Reads memory from the remote process */
|
|
117
|
+
read(address, size) {
|
|
118
|
+
return this._read(this, address, size);
|
|
119
|
+
}
|
|
120
|
+
/** Writes memory into the remote process */
|
|
121
|
+
write(address, data, size) {
|
|
122
|
+
return this._write(this, address, data, size);
|
|
123
|
+
}
|
|
124
|
+
/** Calls a function, passing this proxy as context */
|
|
125
|
+
async call(address, ...args) {
|
|
126
|
+
return this._call(this, address, ...args);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Restores the thread to its original state and releases it.
|
|
130
|
+
* @param suicide If provided, terminates the thread with this exit code instead of resuming it.
|
|
131
|
+
*/
|
|
132
|
+
close(suicide) {
|
|
133
|
+
return this._close(this, suicide);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Allocates memory in the remote process.
|
|
137
|
+
*
|
|
138
|
+
* - `opts.fill` undefined → `malloc(size)`
|
|
139
|
+
* - `opts.fill === 0` → `calloc(1, size)` (zero-initialized)
|
|
140
|
+
* - `opts.fill > 0` → `malloc(size)` + `memset(ptr, fill, size)`
|
|
141
|
+
* - `opts.type` → zone hint for HeapPool (READONLY / READWRITE)
|
|
142
|
+
* - `opts.address` → realloc mode: resize existing allocation
|
|
143
|
+
*/
|
|
144
|
+
alloc(size, opts) {
|
|
145
|
+
return this._alloc(this, size, opts);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Frees a previously allocated remote pointer.
|
|
149
|
+
*/
|
|
150
|
+
free(ptr) {
|
|
151
|
+
return this._free(this, ptr);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=proxy-thread.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-thread.js","sourceRoot":"","sources":["../../src/thread/proxy-thread.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cheatron/nthread",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Non-invasive x64 Windows thread hijacking library — seize control of existing threads without shellcode, remote allocation, or CreateRemoteThread.",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"LICENSE"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"thread-hijacking",
|
|
15
|
+
"windows",
|
|
16
|
+
"x64",
|
|
17
|
+
"game-hacking",
|
|
18
|
+
"cheat",
|
|
19
|
+
"native",
|
|
20
|
+
"process-injection",
|
|
21
|
+
"rop-gadget",
|
|
22
|
+
"memset",
|
|
23
|
+
"msvcrt"
|
|
24
|
+
],
|
|
25
|
+
"author": "Cheatron",
|
|
26
|
+
"homepage": "https://github.com/Cheatron/cheatron-nthread#readme",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/Cheatron/cheatron-nthread.git"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/Cheatron/cheatron-nthread/issues"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc",
|
|
36
|
+
"prepublishOnly": "bun run build",
|
|
37
|
+
"test": "bun test",
|
|
38
|
+
"lint": "eslint \"{src,tests}/**/*.ts\" --cache",
|
|
39
|
+
"lint:fix": "eslint \"{src,tests}/**/*.ts\" --fix",
|
|
40
|
+
"format": "prettier --write \"{src,tests}/**/*.ts\"",
|
|
41
|
+
"format:check": "prettier --check \"{src,tests}/**/*.ts\""
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@cheatron/keystone": "^1.0.1",
|
|
45
|
+
"@cheatron/native": "^1.2.6"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@eslint/js": "^10.0.1",
|
|
49
|
+
"@types/bun": "latest",
|
|
50
|
+
"eslint": "^10.0.0",
|
|
51
|
+
"eslint-config-prettier": "^10.1.8",
|
|
52
|
+
"globals": "^17.3.0",
|
|
53
|
+
"prettier": "^3.8.1",
|
|
54
|
+
"typescript": "^5.9.3",
|
|
55
|
+
"typescript-eslint": "^8.56.0"
|
|
56
|
+
}
|
|
57
|
+
}
|