某些AI汉化组在汉化RPGMV的游戏时会插入礼包码功能,用户在购买了礼包码之后就能解锁诸如CG回想,事件回想,作弊等功能。
但是很多时候这些人在添加礼包码后,会删除游戏原本的回想功能。
一半情况下,你可以直接到CommonEvents.json中寻找礼包码是多少,一半在插入额外功能的时候都会直接添加到最后一行。或者你也可以直接搜索相关文字寻找具体位置。
但是有些组会对游戏文件进行强加密,这里就以一个游戏为例子写写怎么免费获得礼包码。
首相先去游戏的CommonEvents.json看看,结果是加密的。
对于RPGMV来说,本质上这东西就是一个浏览器,游戏本体就是一个网页。一般情况涉及到游戏加密解密的功能都会在\www\js\plugins文件夹下以插件形式存在。
看一下游戏中的所有插件,找到了一个明显有问题的。这个插件内容是经过混淆的。
这种混淆方式明显就是使用了 JS Obfuscator 进行的混淆。这时我们需要找一个找一个代码还原的网站。这里我使用的是这个。
把混淆的代码贴进去,这样我们就得到了源代码。
DataManager是用来读取所有json数据的。
通过读取代码我们不难发现,这里程序会读取data目录下的所有文件,如果文件名为CommonEvents.json,那就会通过decryptData()函数对CommonEvents.json进行解密。
这里我们可以直接使用fs模块直接把解密的CommonEvents.json写成文件。
当然为了继续探秘,我们继续往下看decryptData()函数。
函数本体就是AES解密函数,传入的第一个参数为密文,第二个参数为密钥。
也就是说代码46行的_0x36b42d.responseText为密文,"_!=Yxy@F/SC?ngT-"就是密钥了。
这样就简单了。直接写一段代码解密CommonEvents.json就好了。
const CryptoJS = require("crypto-js");
const fs = require("fs");
function decryptData(encryptedData, key) {
var decKey = CryptoJS.enc.Utf8.parse(key);
var decryptedData = CryptoJS.AES.decrypt(encryptedData, decKey, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
});
return CryptoJS.enc.Utf8.stringify(decryptedData).toString(CryptoJS.enc.Utf8);
}
try {
const encryptedData = fs.readFileSync("./CommonEvents.json", "utf8");
const decryptedData = decryptData(encryptedData, "_!=Yxy@F/SC?ngT-");
fs.writeFileSync("./dec_CommonEvents.json", decryptedData);
console.log("Success")
} catch (err) {
console.error("Error", error.message);
}
我们打开解密后的CommonEvents.json。在
在id516的事件中发现这里就是礼包码所在的位置。
格式化json发现这里礼包码的验证方式
要求变量XYOU2为770473。
这里只要把判断改成true(同时也要修改上面插件的代码防止解密),输入任意礼包码都能成功。
当然我们继续深入,看看XYOU2是怎么来的?往上看看。
好家伙,依然是混淆的。在这里有两段混淆过的代码,我们按照老方法把代码还原出来。
这里有一些需要注意的地方。
- 运算逻辑是在第二段混淆代码里的
- 第一段的逻辑是把你输入的数据存在XYOU1中
- 你需要手动解决json里的代码的转义字符的问题。
code = code
.replace(/\\'/g, "'")
.replace(/\\"/g, '"')
.replace(/\\\\/g, "\\");
这里我们已经能看到计算逻辑,由于礼包码一共就6位数,我们直接暴力算出来就好了。
for (var i = 0; i < 999999; i++) {
var k = (i ^ (i * 8 + 6)) % 1000000;
if (k === 770473) {
console.log(i, k);
break;
}
}
得到礼包码为530967
进入游戏验证成功