Files
TankIC/3DTank/tools/wss_test.js
T
TermiNexus b6f2cb71ee feat(3dtank): 协议逆向工程与自研服务器入库(工具链 + 协议表 + 空间回放 + MySQL)
工具链(3DTank/tools/):extract(模块提取)、mine_evidence/apply_names(命名证据与别名回填)、extract_codec_fields(字段表 + 全库槽位类型 + PrimClassWire/ResourceClasses)、mine_downlink(下行字段表)、extract_space_init/rebase_space_init/audit_space_init(空间模板与记录切分审计)、extract_space_session(把真实会话切成按上行触发的回放模板)、pair_flow(请求→应答配对)、probe_containers、ingest/decrypt_frames(抓包入库与解密)、serve/fetch_assets(本地站点镜像)、import_db(抓包对象仓库导入 MySQL)。

服务器(3DTank/tools/server/):link/entry/codec/container/dispatch/world/space/semantic(协议层与 lt/pt/zt 三个容器布局)、session(会话回放,顺序推进)、db + schema.sql(MySQL 连接层与对象仓库表结构)、store/responder(查库组帧与定向应答;接管范围默认只开 ba.lcr)。

同时修 pair_flow 的时间轴偏移:timeline_c2s 与 timeline_s2c 的 0 点相差 144~4453ms,改前配对整体偏约 2 秒(实测 space-100073070 偏 2084ms),改后 22.4% 的触发者被纠正。

src/、src_named/、packets/、3DTank/local/(含数据库口令)不进库,可用上述工具重新生成。
2026-09-17 20:00:41 +08:00

85 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// wss_test.js - 本地中继自测客户端:验证「明文 → 加密」实时解码链路
// 用法: node wss_test.js [--url ws://localhost:9091/] [--key 42]
// 流程: 先发一条明文帧(应被识别为明文),再发 3 条用同一密钥加密的帧,
// 观察中继日志应出现「明文段结束 → 密钥已破解 K=42 → [密] 命令 ID=...」
const path = require('path');
const ROOT = path.resolve(__dirname, '..', '..');
function RequireWs() {
try {
return require('ws');
} catch (Err) {
return require(path.join(ROOT, 'sockets', 'node_modules', 'ws'));
}
}
const Ws = RequireWs();
const Argv = process.argv.slice(2);
const Arg = (Name, Def) => {
const I = Argv.indexOf('--' + Name);
return I >= 0 && Argv[I + 1] ? Argv[I + 1] : Def;
};
const URL = Arg('url', 'ws://localhost:9091/');
const KEY = Number(Arg('key', '42'));
function EncodeFrame(Payload, Nullmap) {
const Nm = Nullmap || Buffer.from([0x00]);
const Length = Nm.length + Payload.length;
if (Length < 0x4000) return Buffer.concat([Buffer.from([(Length >> 8) & 0xff, Length & 0xff]), Nm, Payload]);
return Buffer.concat([
Buffer.from([((Length >>> 24) & 0xff) | 0x80, (Length >>> 16) & 0xff, (Length >>> 8) & 0xff, Length & 0xff]),
Nm,
Payload,
]);
}
// 与中继侧同构的自变体 XOR 流密码(编码方向:密钥表再 ^87)
class Cipher {
constructor(K) {
this.Slot = new Int32Array(8);
for (let I = 0; I < 8; I++) this.Slot[I] = ((K ^ (I << 3)) ^ 87) & 0xff;
this.Idx = 0;
}
Apply(Buf) {
const Out = Buffer.alloc(Buf.length);
for (let I = 0; I < Buf.length; I++) {
const Plain = Buf[I] & 0xff;
Out[I] = (Plain ^ this.Slot[this.Idx]) & 0xff;
this.Slot[this.Idx] = Plain;
this.Idx = this.Idx ^ (Plain & 7);
}
return Out;
}
}
const Socket = new Ws(URL);
Socket.binaryType = 'nodebuffer';
Socket.on('open', () => {
// 1) 明文帧:命令 ID=1(Hash Request 形态,内容随意)
const PlainFrame = EncodeFrame(Buffer.concat([Buffer.from([1]), Buffer.from('0000000005f691cc', 'hex')]), Buffer.from([0x00]));
Socket.send(PlainFrame);
console.log('已发送明文帧 ' + PlainFrame.length + ' 字节');
// 2) 加密帧:命令 ID=7 / 19 / 42,用同一密钥
const Cipher1 = new Cipher(KEY);
for (const Id of [7, 19, 42]) {
const Payload = Buffer.concat([Buffer.from([Id]), Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22])]);
Socket.send(Cipher1.Apply(EncodeFrame(Payload, Buffer.from([0x00]))));
}
console.log('已发送 3 条加密帧(密钥 K=' + KEY + ')');
});
Socket.on('message', (Data) => console.log('<<< ' + Buffer.from(Data).length + ' 字节'));
Socket.on('close', (Code) => {
console.log('连接关闭 code=' + Code);
process.exit(0);
});
Socket.on('error', (Err) => {
console.log('错误: ' + Err.message);
process.exit(1);
});
setTimeout(() => {
Socket.close();
process.exit(0);
}, 4000);