cheatengine 5.8.19 → 5.8.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README_CN.md CHANGED
@@ -383,47 +383,47 @@ Hook 函数以拦截调用并捕获参数。
383
383
 
384
384
  ## 推荐工作流
385
385
 
386
- ### 指针追踪
387
- ```python
388
- # 自动 (首选)
389
- result = ce_find_pointer_path(address="0x255D5E758")
390
- # 返回: base_address, offsets, ce_pointer_notation
391
-
392
- # 手动 (自动失败时)
393
- # 1. 查找访问该地址的代码
394
- accesses = ce_find_what_accesses(address="0x255D5E758")
395
- # 2. 获取寄存器值 (如 rcx = 0x255D5E658)
396
- # 3. 搜索存储该值的指针
397
- pointers = ce_value_scan(value="0x255D5E658", type="qword")
398
- # 4. 重复直到找到 game.exe+offset
399
- ```
400
-
401
- ### 函数分析
402
- ```python
403
- # 1. 查找函数边界
404
- bounds = ce_find_function_boundaries(address="0x14587EDB0")
405
-
406
- # 2. 跟踪执行
407
- trace = ce_break_and_trace(address="0x14587EDB0", max_steps=100)
408
-
409
- # 3. 生成特征码用于更新
410
- sig = ce_generate_signature(address="0x14587EDB0")
411
- ```
412
-
413
- ### 逆向未知代码
414
- ```python
415
- # 1. 反汇编
416
- code = ce_disassemble(address="0x14587EDB0", count=20)
417
-
418
- # 2. 符号跟踪理解逻辑
419
- symbolic = ce_symbolic_trace(address="0x14587EDB0", initial_state={"rcx": "this"})
420
-
421
- # 3. 为复杂函数构建 CFG
422
- cfg = ce_build_cfg(address="0x14587EDB0")
423
-
424
- # 4. 检测模式
425
- patterns = ce_detect_patterns(address="0x14587EDB0")
426
- ```
386
+ ### 指针追踪
387
+ ```json
388
+ // 自动 (首选)
389
+ {"name": "ce_find_pointer_path", "arguments": {"address": "0x255D5E758", "user_prompted": true}}
390
+ // 返回: base_address, offsets, ce_pointer_notation
391
+
392
+ // 手动 (自动失败时)
393
+ // 1. 查找访问该地址的代码
394
+ {"name": "ce_find_what_accesses", "arguments": {"address": "0x255D5E758", "user_prompted": true}}
395
+ // 2. 从结果获取寄存器值 (如 RBX=0x255D5E658)
396
+ // 3. 搜索存储该值的指针
397
+ {"name": "ce_value_scan", "arguments": {"value": "0x255D5E658", "type": "qword"}}
398
+ // 4. 重复直到找到 game.exe+offset
399
+ ```
400
+
401
+ ### 函数分析
402
+ ```json
403
+ // 1. 查找函数边界
404
+ {"name": "ce_find_function_boundaries", "arguments": {"address": "0x14587EDB0"}}
405
+
406
+ // 2. 跟踪执行
407
+ {"name": "ce_break_and_trace", "arguments": {"address": "0x14587EDB0", "max_steps": 100}}
408
+
409
+ // 3. 生成特征码用于更新
410
+ {"name": "ce_generate_signature", "arguments": {"address": "0x14587EDB0"}}
411
+ ```
412
+
413
+ ### 逆向未知代码
414
+ ```json
415
+ // 1. 反汇编
416
+ {"name": "ce_disassemble", "arguments": {"address": "0x14587EDB0", "count": 20}}
417
+
418
+ // 2. 符号跟踪理解逻辑
419
+ {"name": "ce_symbolic_trace", "arguments": {"address": "0x14587EDB0", "initial_state": {"rcx": "this"}}}
420
+
421
+ // 3. 为复杂函数构建 CFG
422
+ {"name": "ce_build_cfg", "arguments": {"address": "0x14587EDB0"}}
423
+
424
+ // 4. 检测模式
425
+ {"name": "ce_detect_patterns", "arguments": {"address": "0x14587EDB0"}}
426
+ ```
427
427
 
428
428
  ---
429
429
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cheatengine",
3
- "version": "5.8.19",
3
+ "version": "5.8.21",
4
4
  "description": "Cheat Engine MCP Server - AI-assisted reverse engineering bridge",
5
5
  "main": "ce_mcp_server.js",
6
6
  "bin": {
@@ -86,30 +86,32 @@ class PipeClient extends EventEmitter {
86
86
  _handleData(data) {
87
87
  this.responseBuffer = Buffer.concat([this.responseBuffer, data]);
88
88
 
89
- // Try to parse response
90
- if (this.pendingResponse && this.responseBuffer.length >= 4) {
91
- const respLen = this.responseBuffer.readUInt32LE(0);
92
-
93
- if (respLen === 0 || respLen > Config.MAX_RESPONSE_SIZE) {
94
- this.pendingResponse.reject(new Error(`Invalid response size: ${respLen}`));
95
- this.pendingResponse = null;
96
- this.responseBuffer = Buffer.alloc(0);
97
- return;
98
- }
89
+ // Try to parse response only if we have a pending request
90
+ if (!this.pendingResponse || this.responseBuffer.length < 4) {
91
+ return;
92
+ }
93
+
94
+ const respLen = this.responseBuffer.readUInt32LE(0);
95
+
96
+ if (respLen === 0 || respLen > Config.MAX_RESPONSE_SIZE) {
97
+ this.pendingResponse.reject(new Error(`Invalid response size: ${respLen}`));
98
+ this.pendingResponse = null;
99
+ this.responseBuffer = Buffer.alloc(0);
100
+ return;
101
+ }
99
102
 
100
- if (this.responseBuffer.length >= 4 + respLen) {
101
- const respData = this.responseBuffer.slice(4, 4 + respLen);
102
- this.responseBuffer = this.responseBuffer.slice(4 + respLen);
103
-
104
- try {
105
- const decoded = this._decodeResponse(respData);
106
- const result = JSON.parse(decoded);
107
- this.pendingResponse.resolve(result);
108
- } catch (err) {
109
- this.pendingResponse.reject(err);
110
- }
111
- this.pendingResponse = null;
103
+ if (this.responseBuffer.length >= 4 + respLen) {
104
+ const respData = this.responseBuffer.slice(4, 4 + respLen);
105
+ this.responseBuffer = this.responseBuffer.slice(4 + respLen);
106
+
107
+ try {
108
+ const decoded = this._decodeResponse(respData);
109
+ const result = JSON.parse(decoded);
110
+ this.pendingResponse.resolve(result);
111
+ } catch (err) {
112
+ this.pendingResponse.reject(err);
112
113
  }
114
+ this.pendingResponse = null;
113
115
  }
114
116
  }
115
117
 
@@ -258,7 +260,27 @@ class PipeClient extends EventEmitter {
258
260
  _waitForResponse() {
259
261
  return new Promise((resolve, reject) => {
260
262
  this.pendingResponse = { resolve, reject };
261
- this.responseBuffer = Buffer.alloc(0);
263
+
264
+ // Check if we already have data in buffer (race condition fix)
265
+ if (this.responseBuffer.length >= 4) {
266
+ const respLen = this.responseBuffer.readUInt32LE(0);
267
+ if (respLen > 0 && respLen <= Config.MAX_RESPONSE_SIZE && this.responseBuffer.length >= 4 + respLen) {
268
+ const respData = this.responseBuffer.slice(4, 4 + respLen);
269
+ this.responseBuffer = this.responseBuffer.slice(4 + respLen);
270
+
271
+ try {
272
+ const decoded = this._decodeResponse(respData);
273
+ const result = JSON.parse(decoded);
274
+ this.pendingResponse = null;
275
+ resolve(result);
276
+ return;
277
+ } catch (err) {
278
+ this.pendingResponse = null;
279
+ reject(err);
280
+ return;
281
+ }
282
+ }
283
+ }
262
284
  });
263
285
  }
264
286