@bingine/cemem 0.0.0-stage → 0.1.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/PORT-SCOPE.md +169 -0
- package/README.md +451 -2
- package/dist/cjs/addr/expression.js +650 -0
- package/dist/cjs/addr/expression.js.map +1 -0
- package/dist/cjs/addresslist/memory-record.js +612 -0
- package/dist/cjs/addresslist/memory-record.js.map +1 -0
- package/dist/cjs/asm/assembler.js +354 -0
- package/dist/cjs/asm/assembler.js.map +1 -0
- package/dist/cjs/asm/autoassembler-directives.js +362 -0
- package/dist/cjs/asm/autoassembler-directives.js.map +1 -0
- package/dist/cjs/asm/autoassembler.js +2163 -0
- package/dist/cjs/asm/autoassembler.js.map +1 -0
- package/dist/cjs/asm/backend.js +394 -0
- package/dist/cjs/asm/backend.js.map +1 -0
- package/dist/cjs/asm/disassembler.js +715 -0
- package/dist/cjs/asm/disassembler.js.map +1 -0
- package/dist/cjs/backend/dbk-backend.js +683 -0
- package/dist/cjs/backend/dbk-backend.js.map +1 -0
- package/dist/cjs/backend/native-ce-backend.js +667 -0
- package/dist/cjs/backend/native-ce-backend.js.map +1 -0
- package/dist/cjs/backend/self-backend.js +449 -0
- package/dist/cjs/backend/self-backend.js.map +1 -0
- package/dist/cjs/backend/types.js +48 -0
- package/dist/cjs/backend/types.js.map +1 -0
- package/dist/cjs/cheattable/ct-format.js +533 -0
- package/dist/cjs/cheattable/ct-format.js.map +1 -0
- package/dist/cjs/index.js +219 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/lua/aa.js +230 -0
- package/dist/cjs/lua/aa.js.map +1 -0
- package/dist/cjs/lua/addressing.js +118 -0
- package/dist/cjs/lua/addressing.js.map +1 -0
- package/dist/cjs/lua/api.js +736 -0
- package/dist/cjs/lua/api.js.map +1 -0
- package/dist/cjs/lua/asm.js +220 -0
- package/dist/cjs/lua/asm.js.map +1 -0
- package/dist/cjs/lua/bridge.js +526 -0
- package/dist/cjs/lua/bridge.js.map +1 -0
- package/dist/cjs/lua/marshal.js +562 -0
- package/dist/cjs/lua/marshal.js.map +1 -0
- package/dist/cjs/lua/memory.js +213 -0
- package/dist/cjs/lua/memory.js.map +1 -0
- package/dist/cjs/lua/objects.js +1070 -0
- package/dist/cjs/lua/objects.js.map +1 -0
- package/dist/cjs/lua/scan.js +543 -0
- package/dist/cjs/lua/scan.js.map +1 -0
- package/dist/cjs/lua/types.js +103 -0
- package/dist/cjs/lua/types.js.map +1 -0
- package/dist/cjs/scanner/matcher.js +781 -0
- package/dist/cjs/scanner/matcher.js.map +1 -0
- package/dist/cjs/scanner/pointer-scan.js +546 -0
- package/dist/cjs/scanner/pointer-scan.js.map +1 -0
- package/dist/cjs/scanner/scanner.js +513 -0
- package/dist/cjs/scanner/scanner.js.map +1 -0
- package/dist/cjs/scanner/shared-layout.js +207 -0
- package/dist/cjs/scanner/shared-layout.js.map +1 -0
- package/dist/cjs/types.js +190 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/value-codec.js +515 -0
- package/dist/cjs/value-codec.js.map +1 -0
- package/dist/cjs/win/process.js +475 -0
- package/dist/cjs/win/process.js.map +1 -0
- package/dist/cjs/win/scan-worker.js +84 -0
- package/dist/cjs/win/scan-worker.js.map +1 -0
- package/dist/cjs/win/winapi.js +403 -0
- package/dist/cjs/win/winapi.js.map +1 -0
- package/dist/types/addr/expression.d.ts +98 -0
- package/dist/types/addr/expression.d.ts.map +1 -0
- package/dist/types/addresslist/memory-record.d.ts +218 -0
- package/dist/types/addresslist/memory-record.d.ts.map +1 -0
- package/dist/types/asm/assembler.d.ts +106 -0
- package/dist/types/asm/assembler.d.ts.map +1 -0
- package/dist/types/asm/autoassembler-directives.d.ts +118 -0
- package/dist/types/asm/autoassembler-directives.d.ts.map +1 -0
- package/dist/types/asm/autoassembler.d.ts +434 -0
- package/dist/types/asm/autoassembler.d.ts.map +1 -0
- package/dist/types/asm/backend.d.ts +167 -0
- package/dist/types/asm/backend.d.ts.map +1 -0
- package/dist/types/asm/disassembler.d.ts +194 -0
- package/dist/types/asm/disassembler.d.ts.map +1 -0
- package/dist/types/backend/dbk-backend.d.ts +353 -0
- package/dist/types/backend/dbk-backend.d.ts.map +1 -0
- package/dist/types/backend/native-ce-backend.d.ts +213 -0
- package/dist/types/backend/native-ce-backend.d.ts.map +1 -0
- package/dist/types/backend/self-backend.d.ts +64 -0
- package/dist/types/backend/self-backend.d.ts.map +1 -0
- package/dist/types/backend/types.d.ts +176 -0
- package/dist/types/backend/types.d.ts.map +1 -0
- package/dist/types/cheattable/ct-format.d.ts +100 -0
- package/dist/types/cheattable/ct-format.d.ts.map +1 -0
- package/dist/types/index.d.ts +54 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/lua/aa.d.ts +107 -0
- package/dist/types/lua/aa.d.ts.map +1 -0
- package/dist/types/lua/addressing.d.ts +41 -0
- package/dist/types/lua/addressing.d.ts.map +1 -0
- package/dist/types/lua/api.d.ts +46 -0
- package/dist/types/lua/api.d.ts.map +1 -0
- package/dist/types/lua/asm.d.ts +42 -0
- package/dist/types/lua/asm.d.ts.map +1 -0
- package/dist/types/lua/bridge.d.ts +129 -0
- package/dist/types/lua/bridge.d.ts.map +1 -0
- package/dist/types/lua/marshal.d.ts +244 -0
- package/dist/types/lua/marshal.d.ts.map +1 -0
- package/dist/types/lua/memory.d.ts +61 -0
- package/dist/types/lua/memory.d.ts.map +1 -0
- package/dist/types/lua/objects.d.ts +210 -0
- package/dist/types/lua/objects.d.ts.map +1 -0
- package/dist/types/lua/scan.d.ts +106 -0
- package/dist/types/lua/scan.d.ts.map +1 -0
- package/dist/types/lua/types.d.ts +146 -0
- package/dist/types/lua/types.d.ts.map +1 -0
- package/dist/types/scanner/matcher.d.ts +122 -0
- package/dist/types/scanner/matcher.d.ts.map +1 -0
- package/dist/types/scanner/pointer-scan.d.ts +187 -0
- package/dist/types/scanner/pointer-scan.d.ts.map +1 -0
- package/dist/types/scanner/scanner.d.ts +150 -0
- package/dist/types/scanner/scanner.d.ts.map +1 -0
- package/dist/types/scanner/shared-layout.d.ts +96 -0
- package/dist/types/scanner/shared-layout.d.ts.map +1 -0
- package/dist/types/types.d.ts +239 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/value-codec.d.ts +134 -0
- package/dist/types/value-codec.d.ts.map +1 -0
- package/dist/types/win/process.d.ts +190 -0
- package/dist/types/win/process.d.ts.map +1 -0
- package/dist/types/win/scan-worker.d.ts +51 -0
- package/dist/types/win/scan-worker.d.ts.map +1 -0
- package/dist/types/win/winapi.d.ts +144 -0
- package/dist/types/win/winapi.d.ts.map +1 -0
- package/docs/assembler.md +371 -0
- package/docs/autoassembler.md +423 -0
- package/docs/backend-dbk.md +305 -0
- package/docs/backends.md +273 -0
- package/docs/evidence/atomics-wait-io.js +20 -0
- package/docs/evidence/mini-repro.js +98 -0
- package/docs/lua-api.md +718 -0
- package/package.json +60 -4
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lua 侧的内存属性层:保护属性解析、区域查询、分配/释放。
|
|
3
|
+
*
|
|
4
|
+
* 与 CE 的 `LuaHandler.pas` 里 `getMemoryProtection` / `setMemoryProtection` /
|
|
5
|
+
* `fullAccess` / `allocateMemory` / `deAlloc` / `getRegionSize` 对齐。
|
|
6
|
+
*
|
|
7
|
+
* ## 为什么要单独成文件
|
|
8
|
+
*
|
|
9
|
+
* 这几组函数共享同一套底层能力(`Process.regions` / `Process.protect` /
|
|
10
|
+
* `Process.allocate` / `Process.free`),并且都要处理**同一类语义问题**:
|
|
11
|
+
* Win32 的页保护值是「一组位的组合」,而 CE 的 Lua 接口用的是**可读的名字**
|
|
12
|
+
* (`'X' 'W' 'R' 'n'` 之类)。转换规则如果散落在各个 API 里,很容易出现
|
|
13
|
+
* 「读的时候认得、的时候不认得」的不对称 bug,所以集中在这里维护。
|
|
14
|
+
*/
|
|
15
|
+
import type { Process } from '../win/process';
|
|
16
|
+
import { MEM_COMMIT, MEM_FREE, MEM_IMAGE, MEM_MAPPED, MEM_PRIVATE, MEM_RESERVE } from '../types';
|
|
17
|
+
/**
|
|
18
|
+
* 把 CE 的保护属性名解析成 Win32 数值。
|
|
19
|
+
*
|
|
20
|
+
* 接受的写法(大小写不敏感):
|
|
21
|
+
* `'X'` / `'WX'` / `'RWX'` 可执行 / 可写可执行 / 可读写可执行
|
|
22
|
+
* `'XW'` 同上(顺序无关)
|
|
23
|
+
* `'?G'` PAGE_GUARD(CE 里 guard 用 `?G` 表示)
|
|
24
|
+
* 数字 0x40 原样使用(已带完整位,如 PAGE_GUARD 组合)
|
|
25
|
+
*
|
|
26
|
+
* @returns 数值;无法识别返回 null
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseProtectName(input: string | number): number | null;
|
|
29
|
+
/**
|
|
30
|
+
* Win32 保护值 → CE 风格的名字(`'?'` 无法直接展示,返回可读描述)。
|
|
31
|
+
*
|
|
32
|
+
* 优先用 CE 自己的字母序(`X`/`W`/`R`),因为脚本通常拿它做字符串比较。
|
|
33
|
+
*/
|
|
34
|
+
export declare function protectName(protect: number): string;
|
|
35
|
+
/** CE 的 `getMemoryProtection` 返回的是可读串,这里同时给出数值(供脚本精确比较)。 */
|
|
36
|
+
export declare function describeProtect(protect: number): {
|
|
37
|
+
name: string;
|
|
38
|
+
readable: boolean;
|
|
39
|
+
writable: boolean;
|
|
40
|
+
executable: boolean;
|
|
41
|
+
guard: boolean;
|
|
42
|
+
};
|
|
43
|
+
/** CE 的 `getRegionSize(address)`:返回该地址所在区域的字节数。 */
|
|
44
|
+
export declare function regionSizeAt(proc: Process, address: bigint): number | null;
|
|
45
|
+
/** 找到覆盖某地址的区域。 */
|
|
46
|
+
export declare function regionAt(proc: Process, address: bigint): import("../types").MemoryRegion | null;
|
|
47
|
+
/** CE 的 `enumRegions` / `enumRegionsSQL`:返回目标进程已提交的区域列表。 */
|
|
48
|
+
export declare function enumRegions(proc: Process, filter?: {
|
|
49
|
+
protection?: string;
|
|
50
|
+
type?: string;
|
|
51
|
+
}): {
|
|
52
|
+
StartAddress: bigint;
|
|
53
|
+
EndAddress: bigint;
|
|
54
|
+
Size: bigint;
|
|
55
|
+
Protect: string;
|
|
56
|
+
ProtectValue: number;
|
|
57
|
+
Type: string;
|
|
58
|
+
State: string;
|
|
59
|
+
}[];
|
|
60
|
+
export { MEM_COMMIT, MEM_RESERVE, MEM_FREE, MEM_IMAGE, MEM_MAPPED, MEM_PRIVATE };
|
|
61
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/lua/memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EACL,UAAU,EACV,QAAQ,EACR,SAAS,EACT,UAAU,EACV,WAAW,EACX,WAAW,EAUZ,MAAM,UAAU,CAAC;AAkClB;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCtE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAuBnD;AAED,4DAA4D;AAC5D,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAS5I;AAMD,mDAAmD;AACnD,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS1E;AAED,kBAAkB;AAClB,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,0CAKtD;AAED,4DAA4D;AAC5D,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO;;;;;;;;IA6B7F;AASD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lua userdata 对象桥 + CE 风格的宿主对象。
|
|
3
|
+
*
|
|
4
|
+
* 实现方式对齐 Cheat Engine 的 luaclass:
|
|
5
|
+
* - 每个「类」有一个元表,元表的 `__index` 是一个 C 闭包,先查方法表
|
|
6
|
+
* (方法表里存的是原始 C 函数),命中就直接返回该函数 —— Lua 用冒号调用时
|
|
7
|
+
* `self` 作为第 1 个参数传进来,与 CE 的 luaclass_getClassObject 一致;
|
|
8
|
+
* - 查不到方法就按属性 getter 处理(`list.Count`、`record.Value` 这类活属性);
|
|
9
|
+
* - 对象本身是 4 字节 userdata,里面存 JS 侧句柄(i32),
|
|
10
|
+
* JS 侧用 Map<句柄, 对象> 保存真实对象。
|
|
11
|
+
*
|
|
12
|
+
* 之所以不用普通 Lua table 模拟:table 承载不了「活属性」,
|
|
13
|
+
* 也没有 CE 对象该有的 destroy()/GC 语义;CE 的对象本来就是 userdata。
|
|
14
|
+
*/
|
|
15
|
+
import type { Process } from '../win/process';
|
|
16
|
+
import { VariableType, type ScanConfig } from '../types';
|
|
17
|
+
import { LuaMarshal, type LuaRaw } from './marshal';
|
|
18
|
+
import type { BridgeClass, ILuaBridgeObject, ScannerFacade } from './types';
|
|
19
|
+
export declare class LuaObjectBridge {
|
|
20
|
+
private readonly cm;
|
|
21
|
+
private readonly objects;
|
|
22
|
+
/**
|
|
23
|
+
* 每个句柄当前有多少个**活的 userdata** 指向它。
|
|
24
|
+
*
|
|
25
|
+
* 只有当计数归零时才能真正从 `objects` 里摘除宿主对象 ——
|
|
26
|
+
* 详见 `closureGc` 与 `handleOf` 的注释。
|
|
27
|
+
*/
|
|
28
|
+
private readonly handleRefs;
|
|
29
|
+
private readonly handleOfObject;
|
|
30
|
+
private readonly classes;
|
|
31
|
+
private readonly classIds;
|
|
32
|
+
private readonly metatableRefs;
|
|
33
|
+
/** 未声明 setter 的属性写入会落到这里(脚本可以往对象上挂自己的字段) */
|
|
34
|
+
private readonly extras;
|
|
35
|
+
private readonly fnPtrs;
|
|
36
|
+
private readonly indexPtr;
|
|
37
|
+
private readonly newIndexPtr;
|
|
38
|
+
private readonly methodPtr;
|
|
39
|
+
private readonly gcPtr;
|
|
40
|
+
private nextHandle;
|
|
41
|
+
private nextClassId;
|
|
42
|
+
constructor(cm: LuaRaw);
|
|
43
|
+
/** 注册一个类(同名只注册一次),返回类 id。 */
|
|
44
|
+
registerClass(cls: BridgeClass): number;
|
|
45
|
+
/**
|
|
46
|
+
* 对象 → 句柄(同一个存活对象复用同一个句柄)。
|
|
47
|
+
*
|
|
48
|
+
* ## 为什么必须校验 `objects` 里还存在
|
|
49
|
+
*
|
|
50
|
+
* 句柄缓存用的是 `WeakMap<object, number>`,但**同一对象可能被多个 userdata 共用**——
|
|
51
|
+
* 典型例子是 `getAddressList()`:它每次都返回**同一个** `LuaAddressList` 单例,
|
|
52
|
+
* 于是所有拿到的 userdata 都写着同一个 handle。
|
|
53
|
+
*
|
|
54
|
+
* 只要其中**任意一个** userdata 被 Lua GC 回收,`__gc`(`closureGc`)就会执行
|
|
55
|
+
* `objects.delete(handle)`。此时 `WeakMap` 里的缓存还在(宿主对象仍被强引用),
|
|
56
|
+
* 但 `objects` 表里已经没有这个 handle 了。若 `handleOf` 无脑返回缓存值,
|
|
57
|
+
* 新压栈的 userdata 就会指向一个空槽位,之后任何一次属性/方法访问都会得到
|
|
58
|
+
* `readUserdata → found:false`,最终抛出误导性的
|
|
59
|
+
* 「self 不是本引擎的对象(收到 userdata)」——而且是**永久性**的,
|
|
60
|
+
* 该类对象从此再也不能用(`__gc` 删表是单向的,没有任何路径会把它加回来)。
|
|
61
|
+
*
|
|
62
|
+
* 因此这里必须同时检查「WeakMap 命中」**且**「objects 里确实还有这个 handle」,
|
|
63
|
+
* 不一致就重新分配一个新句柄。
|
|
64
|
+
*/
|
|
65
|
+
handleOf(obj: any): number;
|
|
66
|
+
objectOf(handle: number): any;
|
|
67
|
+
/** 该索引是不是本桥的 userdata;是则返回宿主对象。 */
|
|
68
|
+
readUserdata(m: LuaMarshal, index: number): {
|
|
69
|
+
found: boolean;
|
|
70
|
+
value?: unknown;
|
|
71
|
+
};
|
|
72
|
+
/** 把宿主对象压栈成 userdata。 */
|
|
73
|
+
pushObject(m: LuaMarshal, obj: ILuaBridgeObject): boolean;
|
|
74
|
+
/** 把类的元表压栈(首次调用时创建并缓存到注册表)。 */
|
|
75
|
+
private pushMetatable;
|
|
76
|
+
private header;
|
|
77
|
+
private classFromUpvalue;
|
|
78
|
+
private objectAt;
|
|
79
|
+
/** __index:先查方法表,再查属性 getter,最后查数字下标 / 附加字段。 */
|
|
80
|
+
private closureIndex;
|
|
81
|
+
/** __newindex:属性 setter / 数字下标 / 附加字段。 */
|
|
82
|
+
private closureNewIndex;
|
|
83
|
+
/** 方法分发:self 是参数 1,其余是方法参数。 */
|
|
84
|
+
private closureMethod;
|
|
85
|
+
/**
|
|
86
|
+
* `__gc`:某个 userdata 被 Lua GC 回收时调用。
|
|
87
|
+
*
|
|
88
|
+
* ## 这里**不能**无条件 `objects.delete(handle)`
|
|
89
|
+
*
|
|
90
|
+
* 同一个宿主对象会有**多个** userdata 指向它(`getAddressList()` 是全局单例,
|
|
91
|
+
* 每调一次就多一个 userdata,但 handle 相同)。若某个 userdata 被回收就把
|
|
92
|
+
* handle 从 `objects` 里摘掉,**其余仍然存活的 userdata 会全部悬垂**:
|
|
93
|
+
* 它们读到的 handle 在表里查不到,`readUserdata` 返回 `found:false`,
|
|
94
|
+
* 于是后续任何属性/方法访问都抛出误导性的
|
|
95
|
+
* 「self 不是本引擎的对象(收到 userdata)」,而且是永久性的 ——
|
|
96
|
+
* 没有任何路径会把条目加回 `objects`。
|
|
97
|
+
*
|
|
98
|
+
* 所以正确做法是**引用计数**:每次 `pushObject` 加一,这里减一,
|
|
99
|
+
* 只有归零(即最后一个 userdata 也没了)才真正回收宿主对象。
|
|
100
|
+
*/
|
|
101
|
+
private closureGc;
|
|
102
|
+
/** 引擎销毁时释放 addFunction 注册的函数指针。 */
|
|
103
|
+
dispose(): void;
|
|
104
|
+
}
|
|
105
|
+
export declare class LuaStringList implements ILuaBridgeObject {
|
|
106
|
+
readonly luaClass: BridgeClass;
|
|
107
|
+
private items;
|
|
108
|
+
private objects;
|
|
109
|
+
private destroyed;
|
|
110
|
+
constructor(initial?: string[]);
|
|
111
|
+
get count(): number;
|
|
112
|
+
get isDestroyed(): boolean;
|
|
113
|
+
toArray(): string[];
|
|
114
|
+
add(s: string, data?: number): number;
|
|
115
|
+
addText(text: string): void;
|
|
116
|
+
clear(): void;
|
|
117
|
+
delete(index: number): void;
|
|
118
|
+
getString(index: number): string | null;
|
|
119
|
+
setString(index: number, value: string): void;
|
|
120
|
+
indexOf(value: string): number;
|
|
121
|
+
insert(index: number, value: string): void;
|
|
122
|
+
remove(value: string): void;
|
|
123
|
+
getText(): string;
|
|
124
|
+
setText(text: string): void;
|
|
125
|
+
getData(index: number): number;
|
|
126
|
+
setData(index: number, value: number): void;
|
|
127
|
+
destroy(): void;
|
|
128
|
+
}
|
|
129
|
+
export declare const STRING_LIST_CLASS: BridgeClass;
|
|
130
|
+
/** MemoryRecord 需要的宿主能力,由 api 层注入。 */
|
|
131
|
+
export interface RecordHost {
|
|
132
|
+
resolve(expr: string): bigint;
|
|
133
|
+
read(addr: bigint, size: number): Buffer;
|
|
134
|
+
write(addr: bigint, data: Buffer): number;
|
|
135
|
+
}
|
|
136
|
+
export declare class LuaMemoryRecord implements ILuaBridgeObject {
|
|
137
|
+
readonly luaClass: BridgeClass;
|
|
138
|
+
address: string;
|
|
139
|
+
description: string;
|
|
140
|
+
type: VariableType;
|
|
141
|
+
active: boolean;
|
|
142
|
+
selected: boolean;
|
|
143
|
+
readonly id: number;
|
|
144
|
+
private cachedValue;
|
|
145
|
+
private deleted;
|
|
146
|
+
private readonly host;
|
|
147
|
+
constructor(host: RecordHost, address: string, description: string, type: VariableType, id: number);
|
|
148
|
+
/** 解析出当前真实地址(对齐 CE 的 GetRealAddress)。 */
|
|
149
|
+
currentAddress(): bigint;
|
|
150
|
+
private width;
|
|
151
|
+
/** 读值并格式化成字符串(CE 的 MemoryRecord.Value 就是字符串)。 */
|
|
152
|
+
readValueString(): string;
|
|
153
|
+
/** 写值(对齐 CE:setValue 会真的写进目标内存)。 */
|
|
154
|
+
writeValueString(value: string): void;
|
|
155
|
+
numericalValue(): number | bigint | null;
|
|
156
|
+
setNumericalValue(value: number | bigint): void;
|
|
157
|
+
markDeleted(): void;
|
|
158
|
+
get isDeleted(): boolean;
|
|
159
|
+
}
|
|
160
|
+
/** 把读到的原始字节格式化成 CE 风格的字符串。 */
|
|
161
|
+
export declare function formatRecordValue(raw: Buffer, type: VariableType): string;
|
|
162
|
+
/** 把 CE 风格的字符串编码成要写入的字节。 */
|
|
163
|
+
export declare function encodeRecordValue(value: string, type: VariableType): Buffer;
|
|
164
|
+
export declare class LuaAddressList implements ILuaBridgeObject {
|
|
165
|
+
readonly luaClass: BridgeClass;
|
|
166
|
+
private readonly records;
|
|
167
|
+
private selected;
|
|
168
|
+
private nextId;
|
|
169
|
+
private readonly host;
|
|
170
|
+
constructor(host: RecordHost);
|
|
171
|
+
get count(): number;
|
|
172
|
+
createMemoryRecord(address?: string, description?: string, type?: VariableType): LuaMemoryRecord;
|
|
173
|
+
getMemoryRecord(index: number): LuaMemoryRecord | null;
|
|
174
|
+
getMemoryRecordByDescription(description: string): LuaMemoryRecord | null;
|
|
175
|
+
getMemoryRecordByID(id: number): LuaMemoryRecord | null;
|
|
176
|
+
select(rec: LuaMemoryRecord | null): void;
|
|
177
|
+
get selectedRecord(): LuaMemoryRecord | null;
|
|
178
|
+
remove(rec: LuaMemoryRecord): void;
|
|
179
|
+
}
|
|
180
|
+
export declare const ADDRESS_LIST_CLASS: BridgeClass;
|
|
181
|
+
export declare const MEMORY_RECORD_CLASS: BridgeClass;
|
|
182
|
+
export declare class LuaScanSession implements ILuaBridgeObject {
|
|
183
|
+
readonly luaClass: BridgeClass;
|
|
184
|
+
private readonly session;
|
|
185
|
+
private readonly proc;
|
|
186
|
+
private destroyed;
|
|
187
|
+
constructor(proc: Process, facade: ScannerFacade, options?: {
|
|
188
|
+
parallel?: boolean;
|
|
189
|
+
maxSnapshotBytes?: number;
|
|
190
|
+
blockSize?: number;
|
|
191
|
+
parallelMinBytes?: number;
|
|
192
|
+
});
|
|
193
|
+
private assertAlive;
|
|
194
|
+
firstScan(cfg: ScanConfig): number;
|
|
195
|
+
nextScan(cfg: ScanConfig): number;
|
|
196
|
+
get count(): number;
|
|
197
|
+
result(index: number): bigint | null;
|
|
198
|
+
all(): bigint[];
|
|
199
|
+
/** 读取当前结果的值(按类型)。 */
|
|
200
|
+
values(type: VariableType, max?: number): Array<number | bigint>;
|
|
201
|
+
reset(): void;
|
|
202
|
+
destroy(): void;
|
|
203
|
+
get stats(): unknown;
|
|
204
|
+
get processId(): number;
|
|
205
|
+
get hasSnapshot(): boolean;
|
|
206
|
+
}
|
|
207
|
+
export declare const SCAN_SESSION_CLASS: BridgeClass;
|
|
208
|
+
/** 注册全部内置类。 */
|
|
209
|
+
export declare function registerBuiltinClasses(bridge: LuaObjectBridge): void;
|
|
210
|
+
//# sourceMappingURL=objects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"objects.d.ts","sourceRoot":"","sources":["../../../src/lua/objects.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lua 桥的扫描支持层。
|
|
3
|
+
*
|
|
4
|
+
* 负责两件事:
|
|
5
|
+
* 1. 把 Lua 传过来的「扫描配置表」翻译成引擎的 `ScanConfig`(字段名对齐 CE Lua 习惯);
|
|
6
|
+
* 2. AOB 扫描(AOBScan / AOBScanUnique / AOBScanModule*)。
|
|
7
|
+
*
|
|
8
|
+
* AOB 扫描的两条路径:
|
|
9
|
+
* - 全地址空间且保护属性只做「包含」过滤时,直接复用 `ScanSession`(可走 worker 并行,
|
|
10
|
+
* 并且快照上限设为 0,避免为一次性 AOB 扫描白白占用几百 MB);
|
|
11
|
+
* - 需要排除某类内存、或限定模块范围时,用 `scannableRegions()` + `scanBlock()`
|
|
12
|
+
* 自己做分块扫描(本文件内的 `scanAobManual`)。
|
|
13
|
+
* 两条路径都复用 `matcher.compileConfig / scanBlock`,不重复实现匹配算法。
|
|
14
|
+
*/
|
|
15
|
+
import { Process } from '../win/process';
|
|
16
|
+
import { CompiledConfig } from '../scanner/matcher';
|
|
17
|
+
import { MemoryRegion, ScanConfig, VariableType } from '../types';
|
|
18
|
+
import { LuaMarshal } from './marshal';
|
|
19
|
+
import type { LuaValue, ScannerFacade } from './types';
|
|
20
|
+
/**
|
|
21
|
+
* 解析 Lua 的扫描配置表 → ScanConfig。
|
|
22
|
+
*
|
|
23
|
+
* 支持的键(别名用 `/` 分隔):
|
|
24
|
+
* type / variableType 变量类型(名字或 NumericType 数值)
|
|
25
|
+
* option / scanOption 扫描选项(名字或数值)
|
|
26
|
+
* value / value1 扫描值
|
|
27
|
+
* value2 区间上界
|
|
28
|
+
* hex / hexadecimal 按十六进制解析 value
|
|
29
|
+
* signed 有符号解释
|
|
30
|
+
* caseSensitive 字符串区分大小写
|
|
31
|
+
* rounding 浮点比较策略(rounded / extreme / truncated)
|
|
32
|
+
* accuracy / floatAccuracy 小数位数(默认 -1,即由字符串推导)
|
|
33
|
+
* writableOnly / executableOnly / includeImage / includeMapped / includePrivate / includeGuard
|
|
34
|
+
* is32Bit 只扫 4GB 以下
|
|
35
|
+
* alignment 'unaligned' | 'aligned' | <数值/十六进制串>(末位对齐步长)
|
|
36
|
+
* group 分组长扫描元素数组
|
|
37
|
+
* groupOutOfOrder / groupAligned
|
|
38
|
+
* floatScanWithoutExponents
|
|
39
|
+
* blockSize 扫描块大小
|
|
40
|
+
* aob / binary 附加的 AOB/位串(用于 ByteArray/Binary 类型时覆盖 value1)
|
|
41
|
+
*/
|
|
42
|
+
export declare function parseScanConfig(m: LuaMarshal, raw: LuaValue, funcName: string): ScanConfig;
|
|
43
|
+
/** 把 CE 的 alignmentparam(十进制或十六进制串)解析成步长。 */
|
|
44
|
+
export declare function parseAlignmentParam(param: string): number | null;
|
|
45
|
+
/** 把字符串或数字翻译成变量类型(供对象属性 setType 等复用)。 */
|
|
46
|
+
export declare function parseVariableType(m: LuaMarshal, value: LuaValue | undefined, funcName: string, def?: VariableType): VariableType;
|
|
47
|
+
/** 变量类型宽度(变长类型返回 0)。 */
|
|
48
|
+
export declare function variableWidth(type: VariableType): number;
|
|
49
|
+
export type TriState = 'dontcare' | 'include' | 'exclude';
|
|
50
|
+
export interface ProtectionFilter {
|
|
51
|
+
writable: TriState;
|
|
52
|
+
executable: TriState;
|
|
53
|
+
copyOnWrite: TriState;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 解析 CE 的保护属性串,语义与 `TMemScan.parseProtectionflags` 一致:
|
|
57
|
+
* '-' 之后的字母为「排除」,'+' 之后为「包含」,'*' 之后为「无所谓」。
|
|
58
|
+
* W=可写,X=可执行,C=copy-on-write。
|
|
59
|
+
* 空串(AOBScan 的默认值)表示三者都是 dontcare。
|
|
60
|
+
*/
|
|
61
|
+
export declare function parseProtectionFlags(flags: string): ProtectionFilter;
|
|
62
|
+
/** 区域是否满足保护属性过滤。 */
|
|
63
|
+
export declare function regionMatchesProtection(region: MemoryRegion, pf: ProtectionFilter): boolean;
|
|
64
|
+
export interface AobScanOptions {
|
|
65
|
+
/** AOB 特征串,例如 'DE AD BE EF 90 90 ?? 7*' */
|
|
66
|
+
pattern: string;
|
|
67
|
+
/** CE 的保护属性串 */
|
|
68
|
+
protection?: string;
|
|
69
|
+
/** TFastScanMethod:0=不对齐 1=按类型宽度对齐 2=末位对齐 */
|
|
70
|
+
alignmentType?: number;
|
|
71
|
+
/** CE 的 alignmentparam */
|
|
72
|
+
alignmentParam?: string;
|
|
73
|
+
/** 限定模块名(AOBScanModule*) */
|
|
74
|
+
moduleName?: string;
|
|
75
|
+
/** 找到第一个就返回(AOBScanUnique) */
|
|
76
|
+
unique?: boolean;
|
|
77
|
+
/** 模块查找函数 */
|
|
78
|
+
findModule: (name: string) => {
|
|
79
|
+
baseAddress: bigint;
|
|
80
|
+
size: number;
|
|
81
|
+
} | null;
|
|
82
|
+
}
|
|
83
|
+
/** CE 的 `inttohex(address, 8)`:至少 8 位大写十六进制,无 0x 前缀。 */
|
|
84
|
+
export declare function addressToCeHex(address: bigint): string;
|
|
85
|
+
/** 构造 AOB 的扫描配置。 */
|
|
86
|
+
export declare function buildAobConfig(m: LuaMarshal, opts: AobScanOptions): ScanConfig;
|
|
87
|
+
/**
|
|
88
|
+
* AOB 扫描入口。
|
|
89
|
+
*
|
|
90
|
+
* @returns 命中地址(升序,按区域顺序 + 块内偏移)
|
|
91
|
+
*/
|
|
92
|
+
export declare function scanAob(proc: Process, facade: ScannerFacade, m: LuaMarshal, opts: AobScanOptions): bigint[];
|
|
93
|
+
/**
|
|
94
|
+
* 手工分块 AOB 扫描(限定模块 / 需要排除某类内存时使用)。
|
|
95
|
+
*
|
|
96
|
+
* 与 ScanSession 的差异:单线程、按 4MB 分块、块之间带 (模式长度-1) 字节重叠,
|
|
97
|
+
* 保证跨块边界的特征也能命中。
|
|
98
|
+
*/
|
|
99
|
+
export declare function scanAobManual(proc: Process, facade: ScannerFacade, cfg: ScanConfig, opts: AobScanOptions, pf: ProtectionFilter): bigint[];
|
|
100
|
+
/** 供 AOBScanUnique 使用:全地址空间的手工扫描(命中即停)。 */
|
|
101
|
+
export declare function scanAobFirst(proc: Process, facade: ScannerFacade, m: LuaMarshal, opts: AobScanOptions): bigint | null;
|
|
102
|
+
/** 供引擎内部复用:把 ScanConfig 直接交给 compileConfig(避免重复 import)。 */
|
|
103
|
+
export declare function compileScanConfig(cfg: ScanConfig): CompiledConfig;
|
|
104
|
+
/** 供引擎内部复用:单块扫描转发。 */
|
|
105
|
+
export declare function scanBuffer(cc: CompiledConfig, buf: Buffer, out: number[]): void;
|
|
106
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../../src/lua/scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lua 桥的公共类型定义。
|
|
3
|
+
*
|
|
4
|
+
* 桥的两侧类型约定(重要):
|
|
5
|
+
* - JS 侧地址一律用 `bigint`;Lua 侧(Lua 5.4)是 64 位 integer。
|
|
6
|
+
* - `wasmoon` 自带的 JS↔Lua 函数桥会把 Lua integer 转成 JS `number`,
|
|
7
|
+
* 超过 2^53 就丢精度,而且不支持 bigint 返回值。
|
|
8
|
+
* 因此本桥**不使用** wasmoon 的高层函数注册(`global.set`),
|
|
9
|
+
* 而是用 Lua 原始 C API(lua_pushcclosure + addFunction)自建桥,
|
|
10
|
+
* 整数通过 `lua_pushinteger` / `lua_tointegerx` 以 BigInt 原样传递。
|
|
11
|
+
*
|
|
12
|
+
* 该文件只放类型与纯数据类,不放任何 Lua 依赖,便于被其它模块安全引用。
|
|
13
|
+
*/
|
|
14
|
+
import type { Process, ProcessModule } from '../win/process';
|
|
15
|
+
import type { LuaMarshal } from './marshal';
|
|
16
|
+
/** 可以跨桥传递的 Lua 值(JS 侧表示)。 */
|
|
17
|
+
export type LuaValue = null | undefined | boolean | number | bigint | string | LuaValue[] | LuaTable | Map<LuaValue, LuaValue> | ILuaBridgeObject;
|
|
18
|
+
/** 普通 Lua table(字符串键)。 */
|
|
19
|
+
export interface LuaTable {
|
|
20
|
+
[key: string]: LuaValue;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 多返回值标记。
|
|
24
|
+
*
|
|
25
|
+
* Lua 函数可以返回多个值,但 JS 的数组语义被占用为「Lua table」,
|
|
26
|
+
* 因此用本类显式表示多返回值(与 wasmoon 的 LuaMultiReturn 同款思路):
|
|
27
|
+
* return new MultiReturn(1n, 'abc', true);
|
|
28
|
+
*/
|
|
29
|
+
export declare class MultiReturn extends Array<LuaValue> {
|
|
30
|
+
constructor(...values: LuaValue[]);
|
|
31
|
+
}
|
|
32
|
+
/** 可以被桥接成 Lua userdata 的 JS 对象。 */
|
|
33
|
+
export interface ILuaBridgeObject {
|
|
34
|
+
readonly luaClass: BridgeClass;
|
|
35
|
+
}
|
|
36
|
+
/** 判断是否是桥接对象。 */
|
|
37
|
+
export declare function isBridgeObject(v: unknown): v is ILuaBridgeObject;
|
|
38
|
+
/** 对象方法:obj 是宿主 JS 对象,args 是除 self 以外的参数。 */
|
|
39
|
+
export type BridgeMethod = (obj: any, args: LuaValue[], m: LuaMarshal) => LuaValue | MultiReturn | void;
|
|
40
|
+
/** 对象属性访问器。 */
|
|
41
|
+
export interface BridgeProperty {
|
|
42
|
+
get?: (obj: any, m: LuaMarshal) => LuaValue;
|
|
43
|
+
set?: (obj: any, value: LuaValue, m: LuaMarshal) => void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 一个 Lua 侧的「类」描述。
|
|
47
|
+
*
|
|
48
|
+
* 实现方式与 Cheat Engine 的 luaclass 一致:Lua 对象是带元表的 userdata,
|
|
49
|
+
* 元表的 `__index` 先查方法表(命中的是原始 C 函数,`self` 作为第 1 个参数),
|
|
50
|
+
* 查不到再调用属性 getter。
|
|
51
|
+
*/
|
|
52
|
+
export interface BridgeClass {
|
|
53
|
+
/** 元表名(`getmetatable(obj).__name`) */
|
|
54
|
+
readonly name: string;
|
|
55
|
+
/** 方法名 → 实现 */
|
|
56
|
+
readonly methods: Record<string, BridgeMethod>;
|
|
57
|
+
/** 属性名 → getter/setter */
|
|
58
|
+
readonly properties: Record<string, BridgeProperty>;
|
|
59
|
+
/** 数字下标的读取(CE 的 default array property,如 list[0]) */
|
|
60
|
+
indexKey?(obj: any, key: number): LuaValue;
|
|
61
|
+
/** 数字下标的写入 */
|
|
62
|
+
newIndexKey?(obj: any, key: number, value: LuaValue): void;
|
|
63
|
+
/** 字符串键的兜底读取 */
|
|
64
|
+
extraIndex?(obj: any, key: string): LuaValue;
|
|
65
|
+
/** 字符串键的兜底写入(没有 setter 的未知属性会走这里) */
|
|
66
|
+
extraNewIndex?(obj: any, key: string, value: LuaValue): void;
|
|
67
|
+
/** 对象被 Lua GC 回收时调用 */
|
|
68
|
+
onGc?(obj: any): void;
|
|
69
|
+
}
|
|
70
|
+
export interface LuaEngineOptions {
|
|
71
|
+
/** 初始目标进程(可选;之后仍可用 openProcess/attachProcess 切换) */
|
|
72
|
+
process?: Process;
|
|
73
|
+
/**
|
|
74
|
+
* print / showMessage 的输出回调。默认写 process.stdout。
|
|
75
|
+
* 第二个参数是来源:'print' 或 'message'。
|
|
76
|
+
*/
|
|
77
|
+
onOutput?: (text: string, kind: 'print' | 'message') => void;
|
|
78
|
+
/** 是否在引擎内保存输出历史(engine.output),默认 true */
|
|
79
|
+
captureOutput?: boolean;
|
|
80
|
+
/** sleep 的最大毫秒数,默认 60000;防止脚本误写 sleep(1e9) 卡死 */
|
|
81
|
+
maxSleepMs?: number;
|
|
82
|
+
/** 模块列表缓存时长(毫秒),默认 2000。设为 0 表示每次都重新枚举 */
|
|
83
|
+
moduleCacheMs?: number;
|
|
84
|
+
}
|
|
85
|
+
/** API 实现需要的引擎能力(由 LuaEngine 提供,避免 api.ts 反向依赖 bridge.ts)。 */
|
|
86
|
+
export interface ApiContext {
|
|
87
|
+
/** 当前已打开进程,未打开返回 null */
|
|
88
|
+
currentProcess(): Process | null;
|
|
89
|
+
/** 当前已打开进程,未打开时抛中文错误 */
|
|
90
|
+
requireProcess(): Process;
|
|
91
|
+
/** 切换当前进程(会清掉共享的扫描会话与模块缓存) */
|
|
92
|
+
attachProcess(proc: Process | null): void;
|
|
93
|
+
/** 官方 API 里的进程号(0 表示未打开) */
|
|
94
|
+
processId(): number;
|
|
95
|
+
/** 符号表 */
|
|
96
|
+
readonly symbols: SymbolTable;
|
|
97
|
+
/** 按名字找模块(大小写不敏感;可省略扩展名) */
|
|
98
|
+
findModule(name: string): ProcessModule | null;
|
|
99
|
+
/** 列出模块(带缓存) */
|
|
100
|
+
listModules(): ProcessModule[];
|
|
101
|
+
/** 输出一行文本 */
|
|
102
|
+
output(text: string, kind: 'print' | 'message'): void;
|
|
103
|
+
/** sleep 上限 */
|
|
104
|
+
readonly maxSleepMs: number;
|
|
105
|
+
/** 默认扫描会话(首次使用时按需创建) */
|
|
106
|
+
defaultScanSession(): any;
|
|
107
|
+
/** 清掉默认扫描会话 */
|
|
108
|
+
dropDefaultScanSession(): void;
|
|
109
|
+
/** 直接执行 scanBlock 用的原始配置编译入口(见 scan.ts) */
|
|
110
|
+
readonly scanner: ScannerFacade;
|
|
111
|
+
}
|
|
112
|
+
/** 扫描相关能力的外观(由 bridge.ts 组装,内部委托 src/scanner)。 */
|
|
113
|
+
export interface ScannerFacade {
|
|
114
|
+
/** 编译扫描配置(转发 matcher.compileConfig) */
|
|
115
|
+
compile(config: any): any;
|
|
116
|
+
/** 单块扫描(转发 matcher.scanBlock) */
|
|
117
|
+
scanBlock(cc: any, buf: Buffer, prev: Buffer | null, out: number[]): void;
|
|
118
|
+
/** 创建 ScanSession */
|
|
119
|
+
createSession(proc: Process, options?: any): any;
|
|
120
|
+
}
|
|
121
|
+
/** 符号表:registerSymbol / unregisterSymbol / getAddress 用。 */
|
|
122
|
+
export declare class SymbolTable {
|
|
123
|
+
private readonly map;
|
|
124
|
+
private readonly lower;
|
|
125
|
+
register(name: string, address: bigint): void;
|
|
126
|
+
unregister(name: string): boolean;
|
|
127
|
+
/** 精确查找(CE 的符号区分大小写) */
|
|
128
|
+
get(name: string): bigint | undefined;
|
|
129
|
+
/** 大小写不敏感查找(用于 getAddress 的兜底) */
|
|
130
|
+
getCaseInsensitive(name: string): bigint | undefined;
|
|
131
|
+
has(name: string): boolean;
|
|
132
|
+
entries(): Array<[string, bigint]>;
|
|
133
|
+
/**
|
|
134
|
+
* 导出符号表快照(浅拷贝)。
|
|
135
|
+
*
|
|
136
|
+
* 用途:Auto Assembler 的引擎需要一个 `Map<string, bigint>` 作为初值
|
|
137
|
+
* (它内部会在脚本执行过程中往这份 Map 里加 `alloc`/`label`/`aobscan` 的结果)。
|
|
138
|
+
* 传快照而不是内部 Map,是为了让"AA 注册了哪些符号"这件事可被显式同步回来。
|
|
139
|
+
*/
|
|
140
|
+
snapshot(): Map<string, bigint>;
|
|
141
|
+
/** 从一份 Map 批量灌入(用于把 AA 的结果同步回来) */
|
|
142
|
+
mergeFrom(source: Map<string, bigint>): void;
|
|
143
|
+
clear(): void;
|
|
144
|
+
get size(): number;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lua/types.ts"],"names":[],"mappings":"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"}
|