备份: 完整开发状态(含反混淆脚本和临时文件)
This commit is contained in:
242
deobfuscate_provider_v9.js
Normal file
242
deobfuscate_provider_v9.js
Normal file
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
* 动态反混淆 provider.js v9
|
||||
* 100% 解码率 - 处理特殊字符 key
|
||||
*/
|
||||
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 动态反混淆工具 v9 ║');
|
||||
console.log('║ 100% 解码率 - 处理特殊字符 ║');
|
||||
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++;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const initCode = code.slice(0, shuffleEnd);
|
||||
console.log(`初始化代码长度: ${(initCode.length / 1024).toFixed(2)} KB`);
|
||||
|
||||
// 使用 eval 执行
|
||||
console.log('\n[1] 初始化解码器...');
|
||||
var vip = 'cursor';
|
||||
var _0x56bd, _0x4ff4;
|
||||
|
||||
try {
|
||||
eval(initCode);
|
||||
console.log('初始化成功');
|
||||
} catch (e) {
|
||||
console.error('初始化失败:', e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// 智能解析 _0x56bd 调用
|
||||
console.log('\n[2] 智能解析所有调用...');
|
||||
|
||||
function findAllCalls(code) {
|
||||
const calls = [];
|
||||
const pattern = /_0x56bd\s*\(\s*(0x[a-f0-9]+)\s*,\s*'/gi;
|
||||
let match;
|
||||
|
||||
while ((match = pattern.exec(code)) !== null) {
|
||||
const startPos = match.index;
|
||||
const indexHex = match[1];
|
||||
|
||||
// 找到 key 的开始位置(单引号后)
|
||||
let keyStart = match.index + match[0].length;
|
||||
|
||||
// 向后找到匹配的结束单引号和右括号
|
||||
// key 可能包含 ) 和 ' 等特殊字符
|
||||
// 格式: _0x56bd(0x123, 'key')
|
||||
// 需要找到 ') 这个组合
|
||||
|
||||
let keyEnd = -1;
|
||||
for (let i = keyStart; i < code.length - 1; i++) {
|
||||
if (code[i] === "'" && code[i + 1] === ')') {
|
||||
keyEnd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (keyEnd !== -1) {
|
||||
const key = code.slice(keyStart, keyEnd);
|
||||
const fullMatch = code.slice(startPos, keyEnd + 2); // 包括 ')
|
||||
|
||||
calls.push({
|
||||
fullMatch,
|
||||
indexHex,
|
||||
index: parseInt(indexHex, 16),
|
||||
key,
|
||||
startPos,
|
||||
endPos: keyEnd + 2
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return calls;
|
||||
}
|
||||
|
||||
const allCalls = findAllCalls(code);
|
||||
console.log(`找到 ${allCalls.length} 个调用`);
|
||||
|
||||
// 解码所有调用
|
||||
console.log('\n[3] 解码所有字符串...');
|
||||
const decodeMap = new Map();
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
const failedCalls = [];
|
||||
|
||||
for (const call of allCalls) {
|
||||
if (!decodeMap.has(call.fullMatch)) {
|
||||
try {
|
||||
const decoded = _0x56bd(call.index, call.key);
|
||||
if (decoded && typeof decoded === 'string') {
|
||||
decodeMap.set(call.fullMatch, decoded);
|
||||
successCount++;
|
||||
} else {
|
||||
failCount++;
|
||||
failedCalls.push(call);
|
||||
}
|
||||
} catch (e) {
|
||||
failCount++;
|
||||
failedCalls.push({ ...call, error: e.message });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`成功: ${successCount}, 失败: ${failCount}, 唯一模式: ${decodeMap.size}`);
|
||||
|
||||
if (failedCalls.length > 0) {
|
||||
console.log('\n失败的调用:');
|
||||
failedCalls.slice(0, 10).forEach(c => {
|
||||
console.log(` ${c.fullMatch.slice(0, 50)} - ${c.error || 'null result'}`);
|
||||
});
|
||||
}
|
||||
|
||||
// 显示一些解码样本
|
||||
console.log('\n[4] 解码样本:');
|
||||
let sampCount = 0;
|
||||
for (const [pattern, decoded] of decodeMap) {
|
||||
if (sampCount < 15) {
|
||||
console.log(` => "${decoded.slice(0, 60)}${decoded.length > 60 ? '...' : ''}"`);
|
||||
sampCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 替换 - 按位置从后向前替换,避免位置偏移问题
|
||||
console.log('\n[5] 替换编码字符串...');
|
||||
let newCode = code;
|
||||
|
||||
// 收集所有需要替换的位置
|
||||
const replacements = [];
|
||||
for (const call of allCalls) {
|
||||
const decoded = decodeMap.get(call.fullMatch);
|
||||
if (decoded) {
|
||||
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);
|
||||
}
|
||||
replacements.push({
|
||||
start: call.startPos,
|
||||
end: call.endPos,
|
||||
replacement
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 按位置从后向前排序
|
||||
replacements.sort((a, b) => b.start - a.start);
|
||||
|
||||
// 执行替换
|
||||
for (const r of replacements) {
|
||||
newCode = newCode.slice(0, r.start) + r.replacement + newCode.slice(r.end);
|
||||
}
|
||||
|
||||
console.log(`替换了 ${replacements.length} 处`);
|
||||
|
||||
// 清理代码
|
||||
console.log('\n[6] 清理代码...');
|
||||
|
||||
// 1. 方法定义: async ['_method']() -> async _method()
|
||||
newCode = newCode.replace(/(async\s+)\[(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\2\]\s*\(/g, '$1$3(');
|
||||
|
||||
// 2. 方法定义: } ['_method']() 或换行后的 ['method']()
|
||||
newCode = newCode.replace(/(\}\s*)\[(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\2\]\s*\(/g, '$1$3(');
|
||||
newCode = newCode.replace(/(\n\s*)\[(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\2\]\s*\(/g, '$1$3(');
|
||||
|
||||
// 3. 属性访问+方法调用: obj['method']() -> obj.method()
|
||||
newCode = newCode.replace(/\[(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\1\]\s*\(/g, '.$2(');
|
||||
|
||||
// 4. 普通属性访问: obj['prop'] -> obj.prop
|
||||
newCode = newCode.replace(/\[(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\1\]/g, '.$2');
|
||||
|
||||
// 5. 布尔值简化
|
||||
newCode = newCode.replace(/!!\[\]/g, 'true');
|
||||
newCode = newCode.replace(/!\[\]/g, 'false');
|
||||
|
||||
// 移除混淆基础设施
|
||||
console.log('\n[7] 移除混淆基础设施...');
|
||||
const moduleStart = newCode.indexOf('var __createBinding = this && this');
|
||||
if (moduleStart !== -1) {
|
||||
newCode = "'use strict';\n" + newCode.slice(moduleStart);
|
||||
console.log('已移除混淆函数定义');
|
||||
}
|
||||
|
||||
// 保存
|
||||
console.log('\n[8] 保存文件...');
|
||||
fs.writeFileSync(outputPath, newCode);
|
||||
console.log(`保存到: ${outputPath}`);
|
||||
console.log(`新文件大小: ${(newCode.length / 1024).toFixed(2)} KB`);
|
||||
|
||||
// 验证
|
||||
const remaining = (newCode.match(/_0x56bd\s*\(/g) || []).length;
|
||||
console.log(`\n剩余 _0x56bd 调用: ${remaining}`);
|
||||
|
||||
console.log('\n✅ 完成!');
|
||||
Reference in New Issue
Block a user