163 lines
5.1 KiB
JavaScript
163 lines
5.1 KiB
JavaScript
/**
|
|
* 动态反混淆 provider.js
|
|
* 执行原始解码器并替换所有编码字符串
|
|
*/
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// 读取部分反混淆后的文件
|
|
const inputPath = 'D:/temp/破解/cursorpro-0.4.5/deobfuscated_full/extension/out/webview/provider_clean.js';
|
|
const outputPath = 'D:/temp/破解/cursorpro-0.4.5/deobfuscated_full/extension/out/webview/provider.js';
|
|
|
|
console.log('╔════════════════════════════════════════════════════╗');
|
|
console.log('║ Provider.js 动态反混淆工具 ║');
|
|
console.log('╚════════════════════════════════════════════════════╝');
|
|
|
|
let code = fs.readFileSync(inputPath, 'utf8');
|
|
console.log(`读取文件: ${(code.length / 1024).toFixed(2)} KB`);
|
|
|
|
// 提取字符串数组函数和解码器函数
|
|
// 找到 _0x4ff4 函数(字符串数组)
|
|
const arrayFuncMatch = code.match(/(function _0x4ff4\(\)\s*\{[\s\S]*?return _0x4ff4\(\);\s*\})/);
|
|
if (!arrayFuncMatch) {
|
|
console.error('未找到字符串数组函数 _0x4ff4');
|
|
process.exit(1);
|
|
}
|
|
|
|
// 找到 _0x56bd 解码器函数
|
|
const decoderMatch = code.match(/(function _0x56bd\(_0x[a-f0-9]+,\s*_0x[a-f0-9]+\)\s*\{[\s\S]*?return _0x[a-f0-9]+;\s*\})/);
|
|
if (!decoderMatch) {
|
|
console.error('未找到解码器函数 _0x56bd');
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log('找到字符串数组函数和解码器函数');
|
|
|
|
// 构建可执行的解码环境
|
|
const decoderCode = `
|
|
var vip = 'cursor';
|
|
|
|
${arrayFuncMatch[1]}
|
|
|
|
${decoderMatch[1]}
|
|
|
|
// 返回解码器
|
|
module.exports = { _0x56bd, _0x4ff4 };
|
|
`;
|
|
|
|
// 写入临时文件并执行
|
|
const tempFile = path.join(__dirname, '_temp_decoder.js');
|
|
fs.writeFileSync(tempFile, decoderCode);
|
|
|
|
let decoder;
|
|
try {
|
|
decoder = require(tempFile);
|
|
console.log('解码器加载成功');
|
|
} catch (e) {
|
|
console.error('解码器加载失败:', e.message);
|
|
// 尝试直接eval
|
|
try {
|
|
eval(`var vip = 'cursor'; ${arrayFuncMatch[1]} ${decoderMatch[1]}`);
|
|
decoder = { _0x56bd };
|
|
console.log('使用 eval 加载解码器成功');
|
|
} catch (e2) {
|
|
console.error('eval 也失败:', e2.message);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// 清理临时文件
|
|
try { fs.unlinkSync(tempFile); } catch(e) {}
|
|
|
|
// 查找所有 _0x56bd 调用并解码
|
|
const callPattern = /_0x56bd\s*\(\s*(0x[a-f0-9]+)\s*,\s*'([^']*)'\s*\)/g;
|
|
const decodeMap = new Map();
|
|
let match;
|
|
let callCount = 0;
|
|
|
|
while ((match = callPattern.exec(code)) !== null) {
|
|
const fullMatch = match[0];
|
|
const indexHex = match[1];
|
|
const key = match[2];
|
|
|
|
if (!decodeMap.has(fullMatch)) {
|
|
try {
|
|
const index = parseInt(indexHex, 16);
|
|
const decoded = decoder._0x56bd(index, key);
|
|
if (decoded && typeof decoded === 'string') {
|
|
decodeMap.set(fullMatch, decoded);
|
|
callCount++;
|
|
}
|
|
} catch (e) {
|
|
// 忽略解码错误
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log(`找到 ${decodeMap.size} 个唯一的编码字符串`);
|
|
|
|
// 替换所有编码调用
|
|
let newCode = code;
|
|
let replaceCount = 0;
|
|
|
|
for (const [pattern, decoded] of decodeMap) {
|
|
// 生成合适的字符串字面量
|
|
let replacement;
|
|
if (decoded.includes('\n') || decoded.includes('\r') || decoded.includes('`') || decoded.includes('${')) {
|
|
replacement = JSON.stringify(decoded);
|
|
} else if (decoded.includes("'") && !decoded.includes('"')) {
|
|
replacement = `"${decoded}"`;
|
|
} else if (decoded.includes('"') && !decoded.includes("'")) {
|
|
replacement = `'${decoded}'`;
|
|
} else {
|
|
replacement = JSON.stringify(decoded);
|
|
}
|
|
|
|
const before = newCode.length;
|
|
newCode = newCode.split(pattern).join(replacement);
|
|
if (newCode.length !== before) {
|
|
replaceCount++;
|
|
}
|
|
}
|
|
|
|
console.log(`替换了 ${replaceCount} 个模式`);
|
|
|
|
// 清理代码
|
|
// 1. 简化属性访问 obj['prop'] -> obj.prop
|
|
newCode = newCode.replace(/\['([a-zA-Z_$][a-zA-Z0-9_$]*)'\]/g, '.$1');
|
|
|
|
// 2. 简化布尔值
|
|
newCode = newCode.replace(/!!\[\]/g, 'true');
|
|
newCode = newCode.replace(/!\[\]/g, 'false');
|
|
|
|
// 3. 移除十六进制数字(转为十进制)
|
|
newCode = newCode.replace(/\b0x([a-fA-F0-9]+)\b/g, (match, hex) => {
|
|
const num = parseInt(hex, 16);
|
|
// 只转换较小的数字,避免破坏大数字
|
|
if (num < 10000) return num.toString();
|
|
return match;
|
|
});
|
|
|
|
// 保存
|
|
const outputDir = path.dirname(outputPath);
|
|
if (!fs.existsSync(outputDir)) {
|
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
}
|
|
|
|
fs.writeFileSync(outputPath, newCode);
|
|
console.log(`\n保存到: ${outputPath}`);
|
|
console.log(`新文件大小: ${(newCode.length / 1024).toFixed(2)} KB`);
|
|
|
|
// 保存解码映射
|
|
const mapPath = 'D:/temp/破解/cursorpro-0.4.5/provider_decoded_strings.json';
|
|
const mapObj = {};
|
|
for (const [k, v] of decodeMap) {
|
|
if (v.length < 200) {
|
|
mapObj[k] = v;
|
|
}
|
|
}
|
|
fs.writeFileSync(mapPath, JSON.stringify(mapObj, null, 2));
|
|
console.log(`解码映射保存到: ${mapPath}`);
|
|
|
|
console.log('\n✅ 完成!');
|