/**
 * 动态反混淆 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✅ 完成！');
