• 要在moc文件加载前将其加密,加载后解密,这需要在加载过程中插入代码。所以需要重写加载模块。在l2d对应的加载模块中拦截数据请求,将获取的二进制数据进行XOR还原后,再交由Live2D渲染器解析。

  • 重写init函数,添加白名单拦截功能

  • 先将moc文件进行加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const fs = require('fs');
const path = require('path');


// 密钥(0-255之间)
const KEY = 123;

const inputPath = path.join(__dirname, 'model.moc');
const outputPath = path.join(__dirname, 'model.enc');

try {
// 读取二进制文件
const data = fs.readFileSync(inputPath);
const encryptedData = Buffer.alloc(data.length);
for (let i = 0; i < data.length; i++) {
encryptedData[i] = data[i] ^ KEY;
}
// 写入新文件
fs.writeFileSync(outputPath, encryptedData);
} catch (err) {
console.error(' 加密失败,请检查路径是否正确:', err.message);
}

  • XOR 解密:重写live2d-widget.js/src/PlatformManager.js 中的 loadLive2DModel方法,完成后编译live2d-widget.js,替代原始文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
this.loadBytes(path, function(buf){
const KEY = 123;
const encryptedData = new Uint8Array(buf);
const decryptedData = new Uint8Array(encryptedData.length);

for (let i = 0; i < encryptedData.length; i++) {
decryptedData[i] = encryptedData[i] ^ KEY;
}

// 把解密后的数据交还给引擎(注意要把底层的 buffer 传进去)
model = Live2DModelWebGL.loadModel(decryptedData.buffer);
callback(model);
});

  • 实现init函数,验证白名单。导入的时候要注意放在live2d-widget.js后面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
(function() {
var _0x1 = ['init', 'https://cdn.jsdelivr.net/gh/btkrc/resource@main/dsr50_1801/dsr50_1801.model.json', 'live2dcanvas', '.live2d-widget', 'undefined', 'd3d3LnprcnluLmNvbQ==', 'YnRrcmMuZ2l0aHViLmlv', 'hostname', 'toLowerCase', 'includes', 'getElementById', 'querySelector'],
_0x2 = function(_0x3) {
try {
return atob(_0x3)
} catch (_0x4) {
return ""
}
},
_0x5 = [_0x2(_0x1[5]), _0x2(_0x1[6])],
_0x6 = function() {
var _0x7 = window.location[_0x1[7]][_0x1[8]]();

// 白名单校验与防重复加载
if (!_0x5[_0x1[9]](_0x7) || document[_0x1[10]](_0x1[2]) || document[_0x1[11]](_0x1[3]) || typeof L2Dwidget === _0x1[4]) return;

L2Dwidget[_0x1[0]]({
pluginRootPath: "l2dw/",
pluginJsPath: "l2dw/lib/",
pluginModelPath: "l2dw/assets/",
tagMode: false,
debug: false,
model: {
scale: 1,
jsonPath: _0x1[1]
},
display: {
position: "right",
width: 300,
height: 450,
hOffset: -60,
vOffset: -180
},
mobile: {
show: true
},
react: {
opacity: 0.7
},
log: false
})
};
_0x6()
})();