210 lines
6.4 KiB
JavaScript
210 lines
6.4 KiB
JavaScript
/**
|
||
* 动态反混淆 provider.js v8
|
||
* 包含 shuffle IIFE 以正确初始化数组
|
||
*/
|
||
const fs = require('fs');
|
||
|
||
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 动态反混淆工具 v8 ║');
|
||
console.log('╚════════════════════════════════════════════════════╝');
|
||
|
||
let code = fs.readFileSync(inputPath, 'utf8');
|
||
console.log(`读取文件: ${(code.length / 1024).toFixed(2)} KB`);
|
||
|
||
// 找到 _0x4ff4 函数的结束位置
|
||
const arrayFuncStart = code.indexOf('function _0x4ff4()');
|
||
let braceCount = 0;
|
||
let arrayFuncEnd = arrayFuncStart;
|
||
let started = false;
|
||
for (let i = arrayFuncStart; i < code.length; i++) {
|
||
if (code[i] === '{') {
|
||
braceCount++;
|
||
started = true;
|
||
} else if (code[i] === '}') {
|
||
braceCount--;
|
||
if (started && braceCount === 0) {
|
||
arrayFuncEnd = i + 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 找到 shuffle IIFE 的结束位置
|
||
let shuffleStart = arrayFuncEnd;
|
||
// 跳过空白和分号
|
||
while (code[shuffleStart] === ';' || code[shuffleStart] === '\n' || code[shuffleStart] === ' ' || code[shuffleStart] === '\r') {
|
||
shuffleStart++;
|
||
}
|
||
|
||
// 找到 IIFE 的结束
|
||
let parenCount = 0;
|
||
let shuffleEnd = shuffleStart;
|
||
if (code[shuffleStart] === '(') {
|
||
for (let i = shuffleStart; i < code.length; i++) {
|
||
if (code[i] === '(') parenCount++;
|
||
else if (code[i] === ')') {
|
||
parenCount--;
|
||
if (parenCount === 0) {
|
||
shuffleEnd = i + 1;
|
||
if (code[shuffleEnd] === ';') shuffleEnd++;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
console.log(`Shuffle IIFE: ${shuffleStart} - ${shuffleEnd}`);
|
||
|
||
// 提取完整的初始化代码(包括 _0x56bd, _0x4ff4, 和 shuffle IIFE)
|
||
const initCode = code.slice(0, shuffleEnd);
|
||
console.log(`初始化代码长度: ${(initCode.length / 1024).toFixed(2)} KB`);
|
||
|
||
// 使用 eval 执行
|
||
console.log('\n[1] 使用 eval 执行初始化代码...');
|
||
|
||
// 全局变量
|
||
var vip = 'cursor';
|
||
var _0x56bd, _0x4ff4;
|
||
|
||
try {
|
||
eval(initCode);
|
||
console.log('初始化成功');
|
||
console.log(`_0x56bd 类型: ${typeof _0x56bd}`);
|
||
console.log(`_0x4ff4 类型: ${typeof _0x4ff4}`);
|
||
} catch (e) {
|
||
console.error('初始化失败:', e.message);
|
||
console.error(e.stack?.slice(0, 500));
|
||
process.exit(1);
|
||
}
|
||
|
||
// 测试解码
|
||
console.log('\n[2] 测试解码...');
|
||
try {
|
||
// 从 shuffle IIFE 中提取的测试用例
|
||
const tests = [
|
||
[0x5f6, 'yoC7'],
|
||
[0x3d2, 'iDwM'],
|
||
[0x14e, 'yoC7'],
|
||
[0x532, 'ck7z']
|
||
];
|
||
|
||
for (const [index, key] of tests) {
|
||
try {
|
||
const result = _0x56bd(index, key);
|
||
console.log(` _0x56bd(0x${index.toString(16)}, '${key}') = "${result?.slice(0, 50) || '(empty)'}${result?.length > 50 ? '...' : ''}"`);
|
||
} catch (e) {
|
||
console.log(` _0x56bd(0x${index.toString(16)}, '${key}') = ERROR: ${e.message}`);
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.log('测试解码失败:', e.message);
|
||
}
|
||
|
||
// 查找所有 _0x56bd 调用并解码
|
||
console.log('\n[3] 查找所有解码调用...');
|
||
const callPattern1 = /_0x56bd\s*\(\s*(0x[a-f0-9]+)\s*,\s*'([^']*)'\s*\)/gi;
|
||
const callPattern2 = /_0x56bd\s*\(\s*(0x[a-f0-9]+)\s*,\s*"([^"]*)"\s*\)/gi;
|
||
|
||
const decodeMap = new Map();
|
||
let match;
|
||
let totalCalls = 0;
|
||
let successCalls = 0;
|
||
|
||
// 匹配单引号
|
||
while ((match = callPattern1.exec(code)) !== null) {
|
||
const fullMatch = match[0];
|
||
const indexHex = match[1];
|
||
const key = match[2];
|
||
totalCalls++;
|
||
|
||
if (!decodeMap.has(fullMatch)) {
|
||
try {
|
||
const index = parseInt(indexHex, 16);
|
||
const decoded = _0x56bd(index, key);
|
||
if (decoded && typeof decoded === 'string') {
|
||
decodeMap.set(fullMatch, decoded);
|
||
successCalls++;
|
||
}
|
||
} catch (e) {
|
||
// 跳过解码失败的
|
||
}
|
||
}
|
||
}
|
||
|
||
// 匹配双引号
|
||
while ((match = callPattern2.exec(code)) !== null) {
|
||
const fullMatch = match[0];
|
||
const indexHex = match[1];
|
||
const key = match[2];
|
||
totalCalls++;
|
||
|
||
if (!decodeMap.has(fullMatch)) {
|
||
try {
|
||
const index = parseInt(indexHex, 16);
|
||
const decoded = _0x56bd(index, key);
|
||
if (decoded && typeof decoded === 'string') {
|
||
decodeMap.set(fullMatch, decoded);
|
||
successCalls++;
|
||
}
|
||
} catch (e) {
|
||
// 跳过
|
||
}
|
||
}
|
||
}
|
||
|
||
console.log(`总调用数: ${totalCalls}, 成功解码: ${successCalls}, 唯一模式: ${decodeMap.size}`);
|
||
|
||
// 显示一些解码样本
|
||
console.log('\n[4] 解码样本:');
|
||
let sampCount = 0;
|
||
for (const [pattern, decoded] of decodeMap) {
|
||
if (sampCount < 20) {
|
||
console.log(` => "${decoded.slice(0, 60)}${decoded.length > 60 ? '...' : ''}"`);
|
||
sampCount++;
|
||
}
|
||
}
|
||
|
||
// 替换
|
||
console.log('\n[5] 替换编码字符串...');
|
||
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} 个模式`);
|
||
|
||
// 清理代码
|
||
console.log('\n[6] 清理代码...');
|
||
newCode = newCode.replace(/\['([a-zA-Z_$][a-zA-Z0-9_$]*)'\]/g, '.$1');
|
||
newCode = newCode.replace(/!!\[\]/g, 'true');
|
||
newCode = newCode.replace(/!\[\]/g, 'false');
|
||
|
||
// 保存
|
||
console.log('\n[7] 保存文件...');
|
||
fs.writeFileSync(outputPath, newCode);
|
||
console.log(`保存到: ${outputPath}`);
|
||
console.log(`新文件大小: ${(newCode.length / 1024).toFixed(2)} KB`);
|
||
|
||
console.log('\n✅ 完成!');
|