@bingine/cemem 0.0.0-stage → 0.1.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.
Files changed (138) hide show
  1. package/PORT-SCOPE.md +169 -0
  2. package/README.md +451 -2
  3. package/dist/cjs/addr/expression.js +650 -0
  4. package/dist/cjs/addr/expression.js.map +1 -0
  5. package/dist/cjs/addresslist/memory-record.js +612 -0
  6. package/dist/cjs/addresslist/memory-record.js.map +1 -0
  7. package/dist/cjs/asm/assembler.js +354 -0
  8. package/dist/cjs/asm/assembler.js.map +1 -0
  9. package/dist/cjs/asm/autoassembler-directives.js +362 -0
  10. package/dist/cjs/asm/autoassembler-directives.js.map +1 -0
  11. package/dist/cjs/asm/autoassembler.js +2163 -0
  12. package/dist/cjs/asm/autoassembler.js.map +1 -0
  13. package/dist/cjs/asm/backend.js +394 -0
  14. package/dist/cjs/asm/backend.js.map +1 -0
  15. package/dist/cjs/asm/disassembler.js +715 -0
  16. package/dist/cjs/asm/disassembler.js.map +1 -0
  17. package/dist/cjs/backend/dbk-backend.js +683 -0
  18. package/dist/cjs/backend/dbk-backend.js.map +1 -0
  19. package/dist/cjs/backend/native-ce-backend.js +667 -0
  20. package/dist/cjs/backend/native-ce-backend.js.map +1 -0
  21. package/dist/cjs/backend/self-backend.js +449 -0
  22. package/dist/cjs/backend/self-backend.js.map +1 -0
  23. package/dist/cjs/backend/types.js +48 -0
  24. package/dist/cjs/backend/types.js.map +1 -0
  25. package/dist/cjs/cheattable/ct-format.js +533 -0
  26. package/dist/cjs/cheattable/ct-format.js.map +1 -0
  27. package/dist/cjs/index.js +219 -0
  28. package/dist/cjs/index.js.map +1 -0
  29. package/dist/cjs/lua/aa.js +230 -0
  30. package/dist/cjs/lua/aa.js.map +1 -0
  31. package/dist/cjs/lua/addressing.js +118 -0
  32. package/dist/cjs/lua/addressing.js.map +1 -0
  33. package/dist/cjs/lua/api.js +736 -0
  34. package/dist/cjs/lua/api.js.map +1 -0
  35. package/dist/cjs/lua/asm.js +220 -0
  36. package/dist/cjs/lua/asm.js.map +1 -0
  37. package/dist/cjs/lua/bridge.js +526 -0
  38. package/dist/cjs/lua/bridge.js.map +1 -0
  39. package/dist/cjs/lua/marshal.js +562 -0
  40. package/dist/cjs/lua/marshal.js.map +1 -0
  41. package/dist/cjs/lua/memory.js +213 -0
  42. package/dist/cjs/lua/memory.js.map +1 -0
  43. package/dist/cjs/lua/objects.js +1070 -0
  44. package/dist/cjs/lua/objects.js.map +1 -0
  45. package/dist/cjs/lua/scan.js +543 -0
  46. package/dist/cjs/lua/scan.js.map +1 -0
  47. package/dist/cjs/lua/types.js +103 -0
  48. package/dist/cjs/lua/types.js.map +1 -0
  49. package/dist/cjs/scanner/matcher.js +781 -0
  50. package/dist/cjs/scanner/matcher.js.map +1 -0
  51. package/dist/cjs/scanner/pointer-scan.js +546 -0
  52. package/dist/cjs/scanner/pointer-scan.js.map +1 -0
  53. package/dist/cjs/scanner/scanner.js +513 -0
  54. package/dist/cjs/scanner/scanner.js.map +1 -0
  55. package/dist/cjs/scanner/shared-layout.js +207 -0
  56. package/dist/cjs/scanner/shared-layout.js.map +1 -0
  57. package/dist/cjs/types.js +190 -0
  58. package/dist/cjs/types.js.map +1 -0
  59. package/dist/cjs/value-codec.js +515 -0
  60. package/dist/cjs/value-codec.js.map +1 -0
  61. package/dist/cjs/win/process.js +475 -0
  62. package/dist/cjs/win/process.js.map +1 -0
  63. package/dist/cjs/win/scan-worker.js +84 -0
  64. package/dist/cjs/win/scan-worker.js.map +1 -0
  65. package/dist/cjs/win/winapi.js +403 -0
  66. package/dist/cjs/win/winapi.js.map +1 -0
  67. package/dist/types/addr/expression.d.ts +98 -0
  68. package/dist/types/addr/expression.d.ts.map +1 -0
  69. package/dist/types/addresslist/memory-record.d.ts +218 -0
  70. package/dist/types/addresslist/memory-record.d.ts.map +1 -0
  71. package/dist/types/asm/assembler.d.ts +106 -0
  72. package/dist/types/asm/assembler.d.ts.map +1 -0
  73. package/dist/types/asm/autoassembler-directives.d.ts +118 -0
  74. package/dist/types/asm/autoassembler-directives.d.ts.map +1 -0
  75. package/dist/types/asm/autoassembler.d.ts +434 -0
  76. package/dist/types/asm/autoassembler.d.ts.map +1 -0
  77. package/dist/types/asm/backend.d.ts +167 -0
  78. package/dist/types/asm/backend.d.ts.map +1 -0
  79. package/dist/types/asm/disassembler.d.ts +194 -0
  80. package/dist/types/asm/disassembler.d.ts.map +1 -0
  81. package/dist/types/backend/dbk-backend.d.ts +353 -0
  82. package/dist/types/backend/dbk-backend.d.ts.map +1 -0
  83. package/dist/types/backend/native-ce-backend.d.ts +213 -0
  84. package/dist/types/backend/native-ce-backend.d.ts.map +1 -0
  85. package/dist/types/backend/self-backend.d.ts +64 -0
  86. package/dist/types/backend/self-backend.d.ts.map +1 -0
  87. package/dist/types/backend/types.d.ts +176 -0
  88. package/dist/types/backend/types.d.ts.map +1 -0
  89. package/dist/types/cheattable/ct-format.d.ts +100 -0
  90. package/dist/types/cheattable/ct-format.d.ts.map +1 -0
  91. package/dist/types/index.d.ts +54 -0
  92. package/dist/types/index.d.ts.map +1 -0
  93. package/dist/types/lua/aa.d.ts +107 -0
  94. package/dist/types/lua/aa.d.ts.map +1 -0
  95. package/dist/types/lua/addressing.d.ts +41 -0
  96. package/dist/types/lua/addressing.d.ts.map +1 -0
  97. package/dist/types/lua/api.d.ts +46 -0
  98. package/dist/types/lua/api.d.ts.map +1 -0
  99. package/dist/types/lua/asm.d.ts +42 -0
  100. package/dist/types/lua/asm.d.ts.map +1 -0
  101. package/dist/types/lua/bridge.d.ts +129 -0
  102. package/dist/types/lua/bridge.d.ts.map +1 -0
  103. package/dist/types/lua/marshal.d.ts +244 -0
  104. package/dist/types/lua/marshal.d.ts.map +1 -0
  105. package/dist/types/lua/memory.d.ts +61 -0
  106. package/dist/types/lua/memory.d.ts.map +1 -0
  107. package/dist/types/lua/objects.d.ts +210 -0
  108. package/dist/types/lua/objects.d.ts.map +1 -0
  109. package/dist/types/lua/scan.d.ts +106 -0
  110. package/dist/types/lua/scan.d.ts.map +1 -0
  111. package/dist/types/lua/types.d.ts +146 -0
  112. package/dist/types/lua/types.d.ts.map +1 -0
  113. package/dist/types/scanner/matcher.d.ts +122 -0
  114. package/dist/types/scanner/matcher.d.ts.map +1 -0
  115. package/dist/types/scanner/pointer-scan.d.ts +187 -0
  116. package/dist/types/scanner/pointer-scan.d.ts.map +1 -0
  117. package/dist/types/scanner/scanner.d.ts +150 -0
  118. package/dist/types/scanner/scanner.d.ts.map +1 -0
  119. package/dist/types/scanner/shared-layout.d.ts +96 -0
  120. package/dist/types/scanner/shared-layout.d.ts.map +1 -0
  121. package/dist/types/types.d.ts +239 -0
  122. package/dist/types/types.d.ts.map +1 -0
  123. package/dist/types/value-codec.d.ts +134 -0
  124. package/dist/types/value-codec.d.ts.map +1 -0
  125. package/dist/types/win/process.d.ts +190 -0
  126. package/dist/types/win/process.d.ts.map +1 -0
  127. package/dist/types/win/scan-worker.d.ts +51 -0
  128. package/dist/types/win/scan-worker.d.ts.map +1 -0
  129. package/dist/types/win/winapi.d.ts +144 -0
  130. package/dist/types/win/winapi.d.ts.map +1 -0
  131. package/docs/assembler.md +371 -0
  132. package/docs/autoassembler.md +423 -0
  133. package/docs/backend-dbk.md +305 -0
  134. package/docs/backends.md +273 -0
  135. package/docs/evidence/atomics-wait-io.js +20 -0
  136. package/docs/evidence/mini-repro.js +98 -0
  137. package/docs/lua-api.md +718 -0
  138. package/package.json +60 -4
@@ -0,0 +1,213 @@
1
+ /**
2
+ * 原生 CE 后端 —— 作为客户端连接 Cheat Engine 官方的 `ceserver`。
3
+ *
4
+ * 协议来源:`Cheat Engine/ceserver/ceserver.h`(命令号与结构体定义)+
5
+ * `ceserver.c` 的 `DispatchCommand` 分支(收发顺序与字段宽度)。
6
+ *
7
+ * 线上格式(全部小端):每个请求 = 1 字节命令号 + 该命令的输入负载;
8
+ * 每条命令使用一个独立连接。
9
+ *
10
+ * ## 为什么这个后端是异步的
11
+ *
12
+ * 它必须走 socket,而 socket 本质异步。
13
+ * 曾经尝试把它包装成同步接口,两条路都**实测失败**:
14
+ *
15
+ * 1. 主线程里 `Promise + Atomics.wait` → 阻塞把事件循环卡死,
16
+ * socket 回调永不执行(`_probe/atomics-wait-io.js` 可复现);
17
+ * 2. 把 socket 挪到 worker 线程、主线程仍 `Atomics.wait` → **同样死锁**,
18
+ * 因为 worker 线程被 `Atomics.wait` 阻塞后,它自己的事件循环也停了,
19
+ * socket 回调一样不会跑(`_probe/mini-repro.js` 可复现)。
20
+ *
21
+ * 结论:`Atomics.wait` 与 socket I/O 无法在任何同一线程内共存。
22
+ * 因此本后端**诚实地暴露为异步 API**(方法返回 Promise),
23
+ * 而不是用子进程或忙轮询去伪造同步 —— 那只会把复杂度推移到别处。
24
+ *
25
+ * ## 与 SelfBackend 的一致性
26
+ *
27
+ * 方法名、参数、返回类型语义与 `SelfBackend` 完全一致,区别只有一个 `await`:
28
+ * ```ts
29
+ * const buf = proc.readMemory(addr, 16); // 自研后端:同步
30
+ * const buf = await proc.readMemoryAsync(addr, 16); // 原生 CE:异步
31
+ * ```
32
+ * (`Process` 上的 `*Async` 变体对两种后端都可用。)
33
+ *
34
+ * ## 已对齐的命令
35
+ * GETVERSION(0)、GETARCHITECTURE(21)、OPENPROCESS(3)、CLOSEHANDLE(7)、
36
+ * CREATETOOLHELP32SNAPSHOT(4)、PROCESS32FIRST(5)、PROCESS32NEXT(6)、
37
+ * VIRTUALQUERYEX(8)、READPROCESSMEMORY(9)、WRITEPROCESSMEMORY(10)、
38
+ * MODULE32FIRST(22)、MODULE32NEXT(23)、ALLOC(26)、FREE(27)、
39
+ * CHANGEMEMORYPROTECTION(36)
40
+ *
41
+ * ## 未实现(调用会抛错,不假装支持)
42
+ * 线程枚举(CMD_CREATETOOLHELP32SNAPSHOTEX 响应布局随版本变化)、
43
+ * 调试器相关命令、速度修改、管道、符号文件加载。
44
+ */
45
+ import { BackendCapabilities, BackendModuleInfo, BackendProcessHandle, BackendProcessInfo, BackendRegion, BackendRegionFilter, MemoryBackend } from './types';
46
+ export declare const CESERVER_CMD: {
47
+ readonly GETVERSION: 0;
48
+ readonly CLOSECONNECTION: 1;
49
+ readonly TERMINATESERVER: 2;
50
+ readonly OPENPROCESS: 3;
51
+ readonly CREATETOOLHELP32SNAPSHOT: 4;
52
+ readonly PROCESS32FIRST: 5;
53
+ readonly PROCESS32NEXT: 6;
54
+ readonly CLOSEHANDLE: 7;
55
+ readonly VIRTUALQUERYEX: 8;
56
+ readonly READPROCESSMEMORY: 9;
57
+ readonly WRITEPROCESSMEMORY: 10;
58
+ readonly STARTDEBUG: 11;
59
+ readonly STOPDEBUG: 12;
60
+ readonly WAITFORDEBUGEVENT: 13;
61
+ readonly CONTINUEFROMDEBUGEVENT: 14;
62
+ readonly SETBREAKPOINT: 15;
63
+ readonly REMOVEBREAKPOINT: 16;
64
+ readonly SUSPENDTHREAD: 17;
65
+ readonly RESUMETHREAD: 18;
66
+ readonly GETTHREADCONTEXT: 19;
67
+ readonly SETTHREADCONTEXT: 20;
68
+ readonly GETARCHITECTURE: 21;
69
+ readonly MODULE32FIRST: 22;
70
+ readonly MODULE32NEXT: 23;
71
+ readonly GETSYMBOLLISTFROMFILE: 24;
72
+ readonly LOADEXTENSION: 25;
73
+ readonly ALLOC: 26;
74
+ readonly FREE: 27;
75
+ readonly CREATETHREAD: 28;
76
+ readonly LOADMODULE: 29;
77
+ readonly SPEEDHACK_SETSPEED: 30;
78
+ readonly VIRTUALQUERYEXFULL: 31;
79
+ readonly GETREGIONINFO: 32;
80
+ readonly GETABI: 33;
81
+ readonly SET_CONNECTION_NAME: 34;
82
+ readonly CREATETOOLHELP32SNAPSHOTEX: 35;
83
+ readonly CHANGEMEMORYPROTECTION: 36;
84
+ readonly GETOPTIONS: 37;
85
+ readonly GETOPTIONVALUE: 38;
86
+ readonly SETOPTIONVALUE: 39;
87
+ readonly PTRACE_MMAP: 40;
88
+ readonly OPENNAMEDPIPE: 41;
89
+ readonly PIPEREAD: 42;
90
+ readonly PIPEWRITE: 43;
91
+ readonly GETCESERVERPATH: 44;
92
+ readonly ISANDROID: 45;
93
+ readonly LOADMODULEEX: 46;
94
+ readonly SETCURRENTPATH: 47;
95
+ readonly GETCURRENTPATH: 48;
96
+ readonly ENUMFILES: 49;
97
+ readonly GETFILEPERMISSIONS: 50;
98
+ readonly SETFILEPERMISSIONS: 51;
99
+ readonly GETFILE: 52;
100
+ readonly PUTFILE: 53;
101
+ readonly CREATEDIR: 54;
102
+ readonly DELETEFILE: 55;
103
+ readonly AOBSCAN: 200;
104
+ readonly COMMANDLIST2: 255;
105
+ };
106
+ /** CE 官方 ceserver 的默认端口(ceserver.c 的 PORT 默认值) */
107
+ export declare const CESERVER_DEFAULT_PORT = 52736;
108
+ /** 累积式小端写入器 */
109
+ export declare class CeWriter {
110
+ private parts;
111
+ u8(v: number): this;
112
+ i32(v: number): this;
113
+ u32(v: number): this;
114
+ i64(v: bigint): this;
115
+ u64(v: bigint): this;
116
+ bytes(b: Buffer): this;
117
+ build(): Buffer;
118
+ }
119
+ /** 顺序小端读取器 */
120
+ export declare class CeReader {
121
+ private readonly buf;
122
+ private pos;
123
+ constructor(buf: Buffer);
124
+ get remaining(): number;
125
+ u8(): number;
126
+ i32(): number;
127
+ u32(): number;
128
+ i64(): bigint;
129
+ u64(): bigint;
130
+ bytes(n: number): Buffer;
131
+ skip(n: number): void;
132
+ }
133
+ export interface NativeCeBackendOptions {
134
+ /** ceserver 主机,默认 127.0.0.1 */
135
+ host?: string;
136
+ /** ceserver 端口,默认 52736 */
137
+ port?: number;
138
+ /** 单次命令超时(毫秒),默认 15000 */
139
+ timeoutMs?: number;
140
+ }
141
+ /**
142
+ * 原生 CE 后端(通过 ceserver 的 TCP 协议)。
143
+ *
144
+ * 所有方法都是**异步**的(返回 Promise),因为 socket 本质异步 —— 原因见文件头注释。
145
+ *
146
+ * ```ts
147
+ * const backend = new NativeCeBackend({ host: '127.0.0.1', port: 52736 });
148
+ * const h = await backend.openProcess(pid);
149
+ * const buf = await backend.readProcessMemory(h, addr, 64);
150
+ * await backend.dispose();
151
+ * ```
152
+ */
153
+ export declare class NativeCeBackend implements MemoryBackend {
154
+ readonly name = "native-ce";
155
+ readonly capabilities: BackendCapabilities;
156
+ readonly host: string;
157
+ readonly port: number;
158
+ readonly timeoutMs: number;
159
+ private readonly conn;
160
+ private disposed;
161
+ /** handle id -> ceserver 侧 HANDLE */
162
+ private nextHandleId;
163
+ private readonly handles;
164
+ private version;
165
+ constructor(options?: NativeCeBackendOptions);
166
+ /** 后端描述,用于日志 */
167
+ describe(): string;
168
+ /**
169
+ * 读取 ceserver 版本字符串(CMD_GETVERSION,结果缓存)。
170
+ *
171
+ * 响应布局:`{ int32 version; uint8 stringsize; char versionstring[stringsize]; }`
172
+ * 分两轮读(先读 5 字节头拿长度,再读全)—— 因为 ceserver 每条命令一个连接,
173
+ * 无法在一条连接上续读。
174
+ */
175
+ getVersion(): Promise<string>;
176
+ listProcesses(): Promise<BackendProcessInfo[]>;
177
+ openProcess(pid: number): Promise<BackendProcessHandle>;
178
+ closeProcess(handle: BackendProcessHandle): Promise<void>;
179
+ private closeServerHandle;
180
+ private serverHandle;
181
+ queryRegions(handle: BackendProcessHandle, filter?: BackendRegionFilter): Promise<BackendRegion[]>;
182
+ readProcessMemory(handle: BackendProcessHandle, address: bigint, size: number): Promise<Buffer>;
183
+ writeProcessMemory(handle: BackendProcessHandle, address: bigint, data: Buffer, fixProtection?: boolean): Promise<number>;
184
+ queryModules(handle: BackendProcessHandle): Promise<BackendModuleInfo[]>;
185
+ allocate(handle: BackendProcessHandle, size: number, protect?: number, preferred?: bigint): Promise<bigint>;
186
+ free(handle: BackendProcessHandle, address: bigint): Promise<void>;
187
+ changeProtection(handle: BackendProcessHandle, address: bigint, size: number, newProtect: number): Promise<number>;
188
+ queryThreads(): number[];
189
+ isWow64(): boolean;
190
+ /** 发送一帧、读回 expectedBytes 字节 */
191
+ private exchange;
192
+ /** 释放后端资源 */
193
+ dispose(): Promise<void>;
194
+ }
195
+ /**
196
+ * ceserver 的 TCP 通道。
197
+ *
198
+ * 每条命令使用一个独立连接:服务端 `DispatchCommand` 处理完一条命令即关闭,
199
+ * 而且"每条命令一个连接"能让"先读计数、再读数据"这类两步读取天然成立
200
+ * (两边各自重新发一次命令即可)。
201
+ */
202
+ export declare class CeServerConnection {
203
+ readonly host: string;
204
+ readonly port: number;
205
+ readonly timeoutMs: number;
206
+ constructor(host: string, port: number, timeoutMs?: number);
207
+ /** 发送一帧并读回 expectedBytes 字节 */
208
+ exchange(label: string, frame: Buffer, expectedBytes: number): Promise<Buffer>;
209
+ private connect;
210
+ private write;
211
+ private readExactly;
212
+ }
213
+ //# sourceMappingURL=native-ce-backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-ce-backend.d.ts","sourceRoot":"","sources":["../../../src/backend/native-ce-backend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * 自研后端 —— 在本进程内直接通过 Win32 API 操作目标进程。
3
+ *
4
+ * 这是默认后端,也是本移植的"自实现 CE"引擎本体:
5
+ * 对应 Cheat Engine 在**没有内核驱动时**走的那套用户态路径
6
+ * (`NewKernelHandler.pas` 的 `ReadProcessMemory`/`VirtualQueryEx` 分支)。
7
+ *
8
+ * 优点:无外部依赖,开箱即用,兼容性最强。
9
+ * 局限:受 Windows 进程保护约束(受保护进程 / 反作弊 / PPL 进程读不到),
10
+ * 也没有内核驱动那种绕过 ObRegisterCallbacks 的能力 —— 那需要 ring-0,
11
+ * Node 里不存在实现路径,见 PORT-SCOPE.md。
12
+ */
13
+ import { BackendCapabilities, BackendModuleInfo, BackendProcessHandle, BackendProcessInfo, BackendRegion, BackendRegionFilter, BackendUnsupportedError, MemoryBackend } from './types';
14
+ /** 判断保护属性是否可读 */
15
+ export declare function isReadable(protect: number): boolean;
16
+ /** 判断保护属性是否可写 */
17
+ export declare function isWritable(protect: number): boolean;
18
+ /** 判断保护属性是否可执行 */
19
+ export declare function isExecutable(protect: number): boolean;
20
+ /** 按过滤条件筛出可扫描区域(与后端无关的纯函数,供两个后端共用) */
21
+ export declare function filterScanRegions(regions: BackendRegion[], filter?: BackendRegionFilter): BackendRegion[];
22
+ export interface SelfBackendOptions {
23
+ /** 打开进程时请求的访问权限,默认 DEFAULT_PROCESS_ACCESS */
24
+ access?: number;
25
+ }
26
+ /**
27
+ * 自研后端(默认)。
28
+ *
29
+ * ```ts
30
+ * const backend = new SelfBackend();
31
+ * const h = backend.openProcess(pid);
32
+ * const buf = backend.readProcessMemory(h, addr, 64);
33
+ * ```
34
+ */
35
+ export declare class SelfBackend implements MemoryBackend {
36
+ readonly name = "self";
37
+ readonly capabilities: BackendCapabilities;
38
+ private readonly access;
39
+ private nextHandleId;
40
+ private readonly handles;
41
+ private disposed;
42
+ constructor(options?: SelfBackendOptions);
43
+ listProcesses(): BackendProcessInfo[];
44
+ openProcess(pid: number): BackendProcessHandle;
45
+ closeProcess(handle: BackendProcessHandle): void;
46
+ private raw;
47
+ private assertNotDisposed;
48
+ queryRegions(handle: BackendProcessHandle, filter?: BackendRegionFilter): BackendRegion[];
49
+ readProcessMemory(handle: BackendProcessHandle, address: bigint, size: number): Buffer;
50
+ writeProcessMemory(handle: BackendProcessHandle, address: bigint, data: Buffer, fixProtection?: boolean): number;
51
+ queryModules(handle: BackendProcessHandle): BackendModuleInfo[];
52
+ queryThreads(handle: BackendProcessHandle): number[];
53
+ allocate(handle: BackendProcessHandle, size: number, protect?: number, preferred?: bigint): bigint;
54
+ free(handle: BackendProcessHandle, address: bigint): void;
55
+ changeProtection(handle: BackendProcessHandle, address: bigint, size: number, newProtect: number): number;
56
+ isWow64(handle: BackendProcessHandle): boolean;
57
+ /** 挂起目标进程全部线程,返回可恢复的线程句柄 */
58
+ suspendAllThreads(handle: BackendProcessHandle): bigint[];
59
+ /** 恢复之前挂起的线程并关闭句柄 */
60
+ resumeThreads(handles: bigint[]): void;
61
+ dispose(): void;
62
+ }
63
+ export { BackendUnsupportedError };
64
+ //# sourceMappingURL=self-backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-backend.d.ts","sourceRoot":"","sources":["../../../src/backend/self-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,uBAAuB,EACvB,aAAa,EACd,MAAM,SAAS,CAAC;AA6DjB,iBAAiB;AACjB,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAanD;AAED,iBAAiB;AACjB,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAInD;AAED,kBAAkB;AAClB,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGrD;AAED,sCAAsC;AACtC,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,EAAE,EACxB,MAAM,GAAE,mBAAwB,GAC/B,aAAa,EAAE,CAgBjB;AAMD,MAAM,WAAW,kBAAkB;IACjC,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,qBAAa,WAAY,YAAW,aAAa;IAC/C,QAAQ,CAAC,IAAI,UAAU;IAEvB,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAYxC;IAEF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAS;gBAEb,OAAO,GAAE,kBAAuB;IAM5C,aAAa,IAAI,kBAAkB,EAAE;IA0BrC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB;IAgB9C,YAAY,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IAOhD,OAAO,CAAC,GAAG;IAMX,OAAO,CAAC,iBAAiB;IAMzB,YAAY,CAAC,MAAM,EAAE,oBAAoB,EAAE,MAAM,GAAE,mBAAwB,GAAG,aAAa,EAAE;IAyC7F,iBAAiB,CAAC,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IA6BtF,kBAAkB,CAChB,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,aAAa,UAAO,GACnB,MAAM;IA6CT,YAAY,CAAC,MAAM,EAAE,oBAAoB,GAAG,iBAAiB,EAAE;IA2B/D,YAAY,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,EAAE;IAqBpD,QAAQ,CACN,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,SAAO,EACd,SAAS,SAAK,GACb,MAAM;IAaT,IAAI,CAAC,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAOzD,gBAAgB,CACd,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,GACjB,MAAM;IAaT,OAAO,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO;IAS9C,4BAA4B;IAC5B,iBAAiB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,EAAE;IAazD,qBAAqB;IACrB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI;IAOtC,OAAO,IAAI,IAAI;CAMhB;AAED,OAAO,EAAE,uBAAuB,EAAE,CAAC"}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * 内存后端抽象 —— 让上层 API 与"用哪个引擎"解耦。
3
+ *
4
+ * 本移植提供三种可切换的调用方式:
5
+ *
6
+ * 1. `SelfBackend`(默认,自研引擎)
7
+ * 直接通过 Win32 API(koffi 绑定)在本进程内读写目标进程内存。
8
+ * 没有外部依赖,兼容性最强,扫描逻辑由本移植的 matcher 实现。
9
+ *
10
+ * 2. `NativeCeBackend`(原生 CE 兼容层)
11
+ * 作为客户端连接 Cheat Engine 官方的 `ceserver`(CE 源码里
12
+ * `Cheat Engine/ceserver/` 那套服务端程序),走 CE 自己的 TCP 协议。
13
+ * 好处是可以复用原生 CE 的能力(它跑在目标机器上、可能带驱动),
14
+ * 代价是需要一个正在运行的 ceserver。
15
+ *
16
+ * 3. `DbkBackend`(DBK 内核驱动,见 `dbk-backend.ts` 与 docs/backend-dbk.md)
17
+ * 通过 CE 自己的 DBK64 驱动 ioctl 读写,**同步**。
18
+ * 这是读**受保护进程**(PPL/反作弊/以更高权限运行)的唯一途径 ——
19
+ * 用户态连句柄都打不开。
20
+ * 前提:驱动已加载(加载需要管理员权限,插件侧用 `ce_kernel` 工具装)。
21
+ * 能力边界:`changeProtection`/`free` 仍是用户态实现(CE 驱动的
22
+ * `MAKEWRITABLE` 在 x64 上是空的),对受保护进程会失败;
23
+ * 且其驱动侧结构布局尚未在真机上验证。
24
+ *
25
+ * 上层的扫描会话、地址表、.CT 读写、地址表达式都对三者一视同仁:
26
+ * 它们只依赖本文件定义的 `MemoryBackend` 接口。
27
+ *
28
+ * DBK64 内核驱动接口(`DBK32functions.pas` 里的 `Dbk*` 系列 ioctl)
29
+ * 由 `DbkBackend` 实现(见上文第 3 条),协议细节与已知限制见
30
+ * `docs/backend-dbk.md`。
31
+ */
32
+ /**
33
+ * 一个值或它的 Promise。
34
+ *
35
+ * 之所以引入它:内存后端有两种性质完全不同的实现 ——
36
+ * - `SelfBackend` / `DbkBackend`:**同步**(本进程内调 Win32 API / 发驱动 ioctl),直接返回值;
37
+ * - `NativeCeBackend`:socket 通信,**本质异步**。
38
+ *
39
+ * 这里**不**试图把异步"伪装"成同步:实测证明 `Atomics.wait` 会卡死所在线程的
40
+ * 事件循环(无论 socket 放在哪个线程都不行,最小复现见 `_probe/mini-repro.js`),
41
+ * 因此同步调用原生 CE 是不可实现的。诚实的设计是让接口允许返回 Promise。
42
+ *
43
+ * 约定:
44
+ * - 同步后端(`capabilities.sync === true`)**必须**直接返回值,不能返回 Promise;
45
+ * - 异步后端返回 Promise,调用方需要 `await`;
46
+ * - 使用 `await` 对两种情况都安全(`await` 一个非 Promise 值原样返回)。
47
+ */
48
+ export type MaybePromise<T> = T | Promise<T>;
49
+ /** 一个进程的内存句柄(不透明) */
50
+ export interface BackendProcessHandle {
51
+ /** 后端内部使用的句柄标识 */
52
+ readonly id: number;
53
+ /** 目标进程 id */
54
+ readonly pid: number;
55
+ }
56
+ /** 内存区域信息(与 Win32 MEMORY_BASIC_INFORMATION 对齐) */
57
+ export interface BackendRegion {
58
+ baseAddress: bigint;
59
+ regionSize: bigint;
60
+ /** MEM_COMMIT / MEM_RESERVE / MEM_FREE */
61
+ state: number;
62
+ /** 保护属性(PAGE_*) */
63
+ protect: number;
64
+ /** MEM_IMAGE / MEM_MAPPED / MEM_PRIVATE */
65
+ type: number;
66
+ }
67
+ /** 进程信息 */
68
+ export interface BackendProcessInfo {
69
+ pid: number;
70
+ name: string;
71
+ parentPid: number;
72
+ threadCount: number;
73
+ }
74
+ /** 模块信息 */
75
+ export interface BackendModuleInfo {
76
+ name: string;
77
+ path: string;
78
+ baseAddress: bigint;
79
+ size: number;
80
+ }
81
+ /** 内存区域过滤条件 */
82
+ export interface BackendRegionFilter {
83
+ includeFree?: boolean;
84
+ maxAddress?: bigint;
85
+ writableOnly?: boolean;
86
+ executableOnly?: boolean;
87
+ includeImage?: boolean;
88
+ includeMapped?: boolean;
89
+ includePrivate?: boolean;
90
+ includeGuard?: boolean;
91
+ }
92
+ /** 后端能力声明,供上层做能力检查与降级 */
93
+ export interface BackendCapabilities {
94
+ /**
95
+ * 所有操作是否**同步**完成(直接返回值,而非 Promise)。
96
+ * `true` 的后端必须同步返回;`false` 的后端返回 Promise,调用方需 await。
97
+ */
98
+ sync: boolean;
99
+ /** 能否枚举进程 */
100
+ enumerateProcesses: boolean;
101
+ /** 能否枚举内存区域 */
102
+ queryRegions: boolean;
103
+ /** 能否枚举模块 */
104
+ queryModules: boolean;
105
+ /** 能否枚举线程 */
106
+ queryThreads: boolean;
107
+ /** 能否挂起/恢复线程 */
108
+ suspendThreads: boolean;
109
+ /** 能否在目标内分配内存 */
110
+ allocateMemory: boolean;
111
+ /** 能否修改内存保护属性 */
112
+ changeProtection: boolean;
113
+ /** 是否在目标机器本地运行 */
114
+ local: boolean;
115
+ /** 是否需要外部服务端 */
116
+ requiresServer: boolean;
117
+ }
118
+ /**
119
+ * 内存后端接口。
120
+ *
121
+ * ## 同步与异步
122
+ * 方法返回 `MaybePromise<T>`:同步后端(`capabilities.sync === true`)直接返回值,
123
+ * 异步后端返回 Promise。调用方一律可以 `await`,对两种后端都正确。
124
+ *
125
+ * ## 约定
126
+ * - 所有地址用 `bigint`(64 位语义),后端负责按目标进程位数处理;
127
+ * - 读内存失败(部分或全部)不抛错,返回实际读到的字节(长度可能小于请求);
128
+ * - 写内存/分配/改保护失败必须抛错(这些操作静默失败会写坏目标);
129
+ * - 句柄用 `BackendProcessHandle` 封装,关闭后所有操作应抛错。
130
+ */
131
+ export interface MemoryBackend {
132
+ /** 后端名称,用于日志与错误信息 */
133
+ readonly name: string;
134
+ /** 能力声明 */
135
+ readonly capabilities: BackendCapabilities;
136
+ /** 枚举进程。不支持时抛错(调用前应检查 capabilities) */
137
+ listProcesses(): MaybePromise<BackendProcessInfo[]>;
138
+ /** 打开进程,返回句柄 */
139
+ openProcess(pid: number): MaybePromise<BackendProcessHandle>;
140
+ /** 关闭句柄 */
141
+ closeProcess(handle: BackendProcessHandle): MaybePromise<void>;
142
+ /** 枚举内存区域 */
143
+ queryRegions(handle: BackendProcessHandle, filter?: BackendRegionFilter): MaybePromise<BackendRegion[]>;
144
+ /**
145
+ * 读取内存。失败时返回空 Buffer 或比请求更短的 Buffer,不抛错。
146
+ * @param address 起始地址
147
+ * @param size 请求字节数
148
+ */
149
+ readProcessMemory(handle: BackendProcessHandle, address: bigint, size: number): MaybePromise<Buffer>;
150
+ /**
151
+ * 写入内存。返回实际写入字节数;失败抛错。
152
+ * @param fixProtection 是否在写入前临时放开只读保护(本地后端支持)
153
+ */
154
+ writeProcessMemory(handle: BackendProcessHandle, address: bigint, data: Buffer, fixProtection?: boolean): MaybePromise<number>;
155
+ /** 枚举模块。不支持时抛出明确错误 */
156
+ queryModules(handle: BackendProcessHandle): MaybePromise<BackendModuleInfo[]>;
157
+ /** 枚举线程 id。不支持时抛出明确错误 */
158
+ queryThreads(handle: BackendProcessHandle): MaybePromise<number[]>;
159
+ /** 在目标进程内分配内存,返回地址。不支持时抛出明确错误 */
160
+ allocate(handle: BackendProcessHandle, size: number, protect?: number, preferred?: bigint): MaybePromise<bigint>;
161
+ /** 释放内存 */
162
+ free(handle: BackendProcessHandle, address: bigint): MaybePromise<void>;
163
+ /** 修改内存保护,返回旧保护值 */
164
+ changeProtection(handle: BackendProcessHandle, address: bigint, size: number, newProtect: number): MaybePromise<number>;
165
+ /** 目标是否为 32 位(WOW64)。不确定时返回 false */
166
+ isWow64(handle: BackendProcessHandle): MaybePromise<boolean>;
167
+ /** 释放后端自身资源(不关闭已打开的进程句柄) */
168
+ dispose?(): MaybePromise<void>;
169
+ }
170
+ /** 后端不支持某能力时抛出的错误 */
171
+ export declare class BackendUnsupportedError extends Error {
172
+ readonly backend: string;
173
+ readonly operation: string;
174
+ constructor(backend: string, operation: string, detail?: string);
175
+ }
176
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/backend/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Cheat Table (.CT) 读写 —— 对齐 Cheat Engine 的 XML 表格式。
3
+ *
4
+ * 元素与属性名严格对齐 `MemoryRecordUnit.pas` / `addresslist.pas` 的写出逻辑:
5
+ *
6
+ * ```xml
7
+ * <?xml version="1.0" encoding="utf-8"?>
8
+ * <CheatTable CheatEngineTableVersion="46">
9
+ * <CheatEntries>
10
+ * <CheatEntry>
11
+ * <ID>1</ID>
12
+ * <Description>"生命值"</Description>
13
+ * <VariableType>4 Bytes</VariableType>
14
+ * <Address>"game.exe"+0012AB34</Address>
15
+ * <Offsets><Offset>10</Offset><Offset>8</Offset></Offsets>
16
+ * <LastState Value="1000" RealAddress="7FF6..."/>
17
+ * <ShowAsHex>1</ShowAsHex>
18
+ * <Color>FF0000</Color>
19
+ * <CheatEntries> ... 子条目 ... </CheatEntries>
20
+ * </CheatEntry>
21
+ * </CheatEntries>
22
+ * </CheatTable>
23
+ * ```
24
+ *
25
+ * 关键映射(来自 CEFuncProc.VariableTypeToString / StringToVariableType):
26
+ * Byte→'Byte'、Word→'2 Bytes'、DWord→'4 Bytes'、QWord→'8 Bytes'、
27
+ * Single→'Float'、Double→'Double'、String→'String'、UnicodeString→'Unicode String'、
28
+ * ByteArray→'Array of byte'、Binary→'Binary'、All→'All'、Pointer→'Pointer'、
29
+ * AutoAssembler→'Auto Assembler Script'、Custom→'Custom'
30
+ *
31
+ * 关于 XML 解析:这里用自写的轻量解析器而不是 DOMParser,
32
+ * 目的是**保留原始元素顺序与未知元素**,从而做到"读进来再写出去不丢信息"
33
+ * (CE 表里存在大量本移植不关心的元素,例如 Hotkeys、Color、DropDownList)。
34
+ * 未知元素统一收进 MemoryRecordData.extra,写回时原样附着。
35
+ */
36
+ import { AddressList, MemoryRecord, MemoryRecordData } from '../addresslist/memory-record';
37
+ import { VariableType } from '../types';
38
+ /** 变量类型 → CE 表里的字符串 */
39
+ export declare function variableTypeToString(type: VariableType): string;
40
+ /** CE 表里的字符串 → 变量类型(未知时按 CE 一样回落到 Byte) */
41
+ export declare function stringToVariableType(s: string): VariableType;
42
+ interface XmlElement {
43
+ kind: 'element';
44
+ name: string;
45
+ attributes: Record<string, string>;
46
+ children: XmlNode[];
47
+ /** 直接文本内容(拼接所有文本子节点,已 trim) */
48
+ text: string;
49
+ }
50
+ interface XmlText {
51
+ kind: 'text';
52
+ value: string;
53
+ }
54
+ type XmlNode = XmlElement | XmlText;
55
+ /** 解析 XML 为元素树(保留顺序与未知元素)。 */
56
+ export declare function parseXml(source: string): XmlElement;
57
+ export interface ParsedCheatTable {
58
+ version: number;
59
+ comment: string;
60
+ records: MemoryRecordData[];
61
+ /** 用户自定义符号(<UserdefinedSymbols>) */
62
+ symbols: Array<{
63
+ name: string;
64
+ address: string;
65
+ }>;
66
+ /** 原始根元素属性,便于往返保留 */
67
+ rootAttributes: Record<string, string>;
68
+ }
69
+ /**
70
+ * 解析 .CT 内容为地址表数据。
71
+ */
72
+ export declare function parseCheatTable(xml: string): ParsedCheatTable;
73
+ export interface WriteCheatTableOptions {
74
+ /** CheatEngineTableVersion 属性值,默认 46(CE 6.x/7.x 常见值) */
75
+ version?: number;
76
+ /** 表注释 */
77
+ comment?: string;
78
+ /** 是否写入 <LastState>(默认写入当前值,便于 CE 打开时直接显示) */
79
+ includeLastState?: boolean;
80
+ /** 用户自定义符号 */
81
+ symbols?: Array<{
82
+ name: string;
83
+ address: string;
84
+ }>;
85
+ }
86
+ /**
87
+ * 把地址表序列化为 .CT 内容。
88
+ *
89
+ * @param list 地址表;若为纯数据数组也可直接传
90
+ */
91
+ export declare function writeCheatTable(list: AddressList | MemoryRecord[] | MemoryRecordData[], options?: WriteCheatTableOptions): string;
92
+ /** 从 .CT 文本构建 AddressList(不改动传入的 XML) */
93
+ export declare function loadCheatTable(xml: string, process?: Parameters<typeof AddressList.prototype.attachProcess>[0]): {
94
+ list: AddressList;
95
+ parsed: ParsedCheatTable;
96
+ };
97
+ /** 把地址表写回 .CT 文本 */
98
+ export declare function saveCheatTable(list: AddressList, options?: WriteCheatTableOptions): string;
99
+ export {};
100
+ //# sourceMappingURL=ct-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ct-format.d.ts","sourceRoot":"","sources":["../../../src/cheattable/ct-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EACL,WAAW,EACX,YAAY,EACZ,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AA4CxC,uBAAuB;AACvB,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAE/D;AAED,2CAA2C;AAC3C,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,MAAM,GAAG,YAAY,CAG5D;AAMD,UAAU,UAAU;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,OAAO;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,KAAK,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;AAEpC,8BAA8B;AAC9B,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAqGnD;AA8CD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,oCAAoC;IACpC,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,qBAAqB;IACrB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CA+B7D;AAiID,MAAM,WAAW,sBAAsB;IACrC,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU;IACV,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc;IACd,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AA0BD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,WAAW,GAAG,YAAY,EAAE,GAAG,gBAAgB,EAAE,EACvD,OAAO,GAAE,sBAA2B,GACnC,MAAM,CAwCR;AAyED,yCAAyC;AACzC,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAClE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAQjD;AAED,oBAAoB;AACpB,wBAAgB,cAAc,CAC5B,IAAI,EAAE,WAAW,EACjB,OAAO,GAAE,sBAA2B,GACnC,MAAM,CAWR"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * node-cheat-engine —— Cheat Engine 核心引擎的 Node.js 移植版。
3
+ *
4
+ * 公共 API 入口。设计目标:用 Node 复刻 CE 在**用户态**能做的核心能力:
5
+ * 跨进程内存读写、全类型内存扫描(对齐 memscan.pas 的比较语义)、
6
+ * 指针扫描、地址表与 .CT 读写、地址表达式解析、脚本桥。
7
+ *
8
+ * 明确不在范围内(Node 中不存在实现路径,详见 PORT-SCOPE.md):
9
+ * - dbk32/DBKKernel 内核驱动:ring-0 物理内存读写、绕过进程保护
10
+ * - dbvm/DBVM UEFI:VT-x/AMD-V hypervisor、硬件断点与隐身
11
+ * - LCL/VCL 图形界面(.lfm 窗体)
12
+ * - x86/x64 反汇编与汇编器(原样保留 AutoAssembler 语义需要独立移植)
13
+ */
14
+ export { VariableType, ScanOption, RoundingType, ScanType, PointerType, FastScanMethod, VARIABLE_TYPE_NAMES, VARIABLE_TYPE_SIZES, SCAN_OPTION_NAMES, MEM_COMMIT, MEM_RESERVE, MEM_FREE, MEM_PRIVATE, MEM_MAPPED, MEM_IMAGE, PAGE_NOACCESS, PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY, PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY, PAGE_GUARD, PROCESS_VM_READ, PROCESS_VM_WRITE, PROCESS_VM_OPERATION, PROCESS_QUERY_INFORMATION, DEFAULT_PROCESS_ACCESS, } from './types';
15
+ export type { ScanConfig, ScanResult, ScanProgressCallback, MemoryRegion, GroupElement, PointerTypes, AccessRights, } from './types';
16
+ export { roundTo, parseIntegerLiteral, parseFloatLiteral, decimalsOf, parseAob, parseBinaryPattern, buildFloatCompareParams, singleMatches, doubleMatches, aobMatchesAt, aobHasNibbleWildcard, } from './value-codec';
17
+ export type { ParsedNumber, FloatCompareParams, PatternByte, BinaryPattern } from './value-codec';
18
+ export type { MemoryBackend, BackendCapabilities, BackendProcessHandle, BackendProcessInfo, BackendRegion, BackendRegionFilter, BackendModuleInfo, } from './backend/types';
19
+ export { BackendUnsupportedError } from './backend/types';
20
+ export { SelfBackend, filterScanRegions } from './backend/self-backend';
21
+ export type { SelfBackendOptions } from './backend/self-backend';
22
+ export { NativeCeBackend, CeServerConnection, CeWriter, CeReader, CESERVER_CMD, CESERVER_DEFAULT_PORT, } from './backend/native-ce-backend';
23
+ export type { NativeCeBackendOptions } from './backend/native-ce-backend';
24
+ export { DbkBackend, DbkDeviceError, DBK_IOCTL, DBK_READ_INPUT_SIZE, DBK_WRITE_INPUT_SIZE, DBK_WRITE_BUFFER_SIZE, DBK_MAX_WRITE_PAYLOAD, DBK_MAX_READ_CHUNK, DBK_ALLOC_INPUT_SIZE, DEFAULT_DBK_SERVICE_NAME, packReadInput, packWriteBuffer, packAllocInput, readAllocResult, resolveDevicePath, readServiceNameFromDriverDat, } from './backend/dbk-backend';
25
+ export type { DbkBackendOptions } from './backend/dbk-backend';
26
+ export { Process, ProcessOpenError, listProcesses, findProcessesByName, enumerateRegions, selectScannableRegions, isReadable, isWritable, isExecutable, getDefaultBackend, setDefaultBackend, regionTypeName, openProcessAsync, openProcessByNameAsync, listProcessesAsync, findProcessesByNameAsync, } from './win/process';
27
+ export type { ProcessInfo, ProcessModule, RegionFilter, OpenProcessOptions } from './win/process';
28
+ export { win32ErrorMessage } from './win/winapi';
29
+ export { ScanSession } from './scanner/scanner';
30
+ export type { ScanSessionOptions, ScanStats, Chunk } from './scanner/scanner';
31
+ export { compileConfig, scanBlock, optionNeedsOldValue } from './scanner/matcher';
32
+ export type { CompiledConfig } from './scanner/matcher';
33
+ export { PointerScanner, formatPointerPath, applyPointerPath } from './scanner/pointer-scan';
34
+ export type { PointerPath, PointerScanOptions, PointerScanStats } from './scanner/pointer-scan';
35
+ export { compileExpression, evaluateExpression, resolveAddress, CompiledAddress, ExpressionError } from './addr/expression';
36
+ export type { EvalContext, ExprNode } from './addr/expression';
37
+ export { AddressList, MemoryRecord, addScanResults, buildRecordsFromScan } from './addresslist/memory-record';
38
+ export type { MemoryRecordData, RecordEvaluation } from './addresslist/memory-record';
39
+ export { parseCheatTable, writeCheatTable, loadCheatTable, saveCheatTable, variableTypeToString, stringToVariableType, } from './cheattable/ct-format';
40
+ export type { ParsedCheatTable, WriteCheatTableOptions } from './cheattable/ct-format';
41
+ export { LuaEngine, LuaScriptError, LuaError, LuaMarshal } from './lua/bridge';
42
+ export type { LuaValue, LuaEngineOptions } from './lua/types';
43
+ export type { ApiFunction } from './lua/api';
44
+ export { ensureAsmBackend, isAsmBackendReady, resetAsmBackendForTests, isArchitectureSupported, architectureInfo, normalizeArchitecture, archFromBitness, disassembleRaw, assembleRaw, instructionNameOf, backendVersions, toSafeNumberAddress, AsmBackendError, } from './asm/backend';
45
+ export type { AsmArchitecture, AsmEndianness, ArchitectureInfo, RawInstruction, RawAssembleResult, DisassembleRawOptions, AssembleRawOptions, } from './asm/backend';
46
+ export { disassemble, disassembleOne, disassembleAt, formatDisassembled, splitDisassembledString, formatBytes, branchTarget, instructionText, DisasmValueType, } from './asm/disassembler';
47
+ export type { DisassembledInstruction, DisassembleOptions } from './asm/disassembler';
48
+ export { assemble, assembleLines, assembleToBytes, AssemblerError } from './asm/assembler';
49
+ export type { AssembleOptions, AssembleResult, AssembledLine, } from './asm/assembler';
50
+ export { AutoAssembler, AutoAssemblerError, autoAssemble } from './asm/autoassembler';
51
+ export type { AutoAssemblerOptions, AutoAssembleResult, AutoAssemblerEntry, AutoAssemblerAllocation, AutoAssemblerLineInfo, AutoAssemblerPhase, AobScanRecord, RestoreMode, SourceLine, AsmLine, } from './asm/autoassembler';
52
+ export { parseCeInteger, splitDirectiveArguments, encodeDataDirective, encodeNop, encodeAlign, parsePseudoDirective, patternToDbArguments, bytesToDbArguments, } from './asm/autoassembler-directives';
53
+ export type { DataDirectiveKind, PseudoDirectiveKind, ParsedPseudoDirective, } from './asm/autoassembler-directives';
54
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}