备份: 完整开发状态(含反混淆脚本和临时文件)

This commit is contained in:
ccdojox-crypto
2025-12-17 17:18:02 +08:00
parent 9e2333c90c
commit 7e9ea173a7
2872 changed files with 326818 additions and 249 deletions

230
run_codex_deobf.js Normal file
View File

@@ -0,0 +1,230 @@
/**
* 反混淆并美化原版 extension/out 下的核心文件,输出到 codexfanbianyi/extension/out。
* 策略:动态执行字符串数组 + 解码函数,解出所有形如 _0x****(0x123,'key') 的调用并替换为明文,再用 js-beautify 排版。
*/
const fs = require('fs');
const path = require('path');
const vm = require('vm');
const beautify = require('js-beautify').js;
const baseDir = __dirname;
const inputBase = path.join(baseDir, '原版本', 'extension', 'out');
const outputBase = path.join(baseDir, 'codexfanbianyi', 'extension', 'out');
const targets = [
'webview/provider.js',
'extension.js',
'utils/account.js',
'utils/sqlite.js',
'api/client.js'
];
const mapPaths = {
'webview/provider.js': path.join(baseDir, 'provider_decoded_map.json'),
'extension.js': path.join(baseDir, 'extension_decoded_map.json'),
'utils/account.js': path.join(baseDir, 'account_decoded_map.json'),
'utils/sqlite.js': path.join(baseDir, 'sqlite_decoded_map.json'),
'api/client.js': path.join(baseDir, 'client_decoded_map.json')
};
function ensureDir(dir) {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
}
function extractFunctionWithBody(code, nameRegex) {
const match = nameRegex.exec(code);
if (!match) return null;
const start = match.index;
const braceStart = code.indexOf('{', start);
if (braceStart === -1) return null;
let depth = 0;
for (let i = braceStart; i < code.length; i++) {
const ch = code[i];
if (ch === '{') depth++;
else if (ch === '}') {
depth--;
if (depth === 0) {
return {
name: match[1],
code: code.slice(start, i + 1),
end: i + 1
};
}
}
}
return null;
}
function buildSandbox() {
const sandbox = {
console: { log: () => {}, warn: () => {}, error: () => {} },
vip: 'cursor',
Buffer,
atob: (str) => Buffer.from(str, 'base64').toString('binary'),
btoa: (str) => Buffer.from(str, 'binary').toString('base64'),
decodeURIComponent,
encodeURIComponent,
parseInt,
String,
setTimeout,
clearTimeout,
setInterval,
clearInterval,
exports: {},
module: { exports: {} },
require: () => ({})
};
vm.createContext(sandbox);
return sandbox;
}
function buildDecoder(code) {
const arrayFunc = extractFunctionWithBody(code, /function\s+(_0x[a-f0-9]+)\s*\(\s*\)/i);
const decoderFunc = extractFunctionWithBody(code, /function\s+(_0x[a-f0-9]+)\s*\(\s*_0x[a-f0-9]+\s*,\s*_0x[a-f0-9]+\s*\)/i);
if (!arrayFunc || !decoderFunc) {
return null;
}
const sandbox = buildSandbox();
try {
// 1) 先只注入字符串数组函数 + 解码函数(避免执行到 exports/require 等顶层逻辑)
vm.runInContext(`${arrayFunc.code}\n${decoderFunc.code}`, sandbox, { timeout: 4000 });
// 2) 执行“数组旋转/IIFE”等启动代码通常位于文件开头exports 之前)
const stopMarkers = [
'var __createBinding',
'Object.defineProperty(exports',
'exports.',
'module.exports'
];
let bootstrapEnd = code.length;
for (const marker of stopMarkers) {
const idx = code.indexOf(marker);
if (idx !== -1 && idx < bootstrapEnd) bootstrapEnd = idx;
}
const bootstrapCode = code.slice(0, bootstrapEnd);
vm.runInContext(bootstrapCode, sandbox, { timeout: 4000 });
const decoder = sandbox[decoderFunc.name];
if (typeof decoder !== 'function') {
console.warn(` 解码器 ${decoderFunc.name} 不是函数`);
return null;
}
return decoder.bind(sandbox);
} catch (e) {
console.warn(` 解码器初始化失败: ${e.message}`);
return null;
}
}
function literalFor(decoded) {
if (decoded == null) return 'undefined';
if (typeof decoded !== 'string') return JSON.stringify(decoded);
if (decoded.includes('\n')) {
return '`' + decoded.replace(/`/g, '\\`') + '`';
}
return JSON.stringify(decoded);
}
function replaceCalls(code, decoder) {
const callPattern = /_0x[a-f0-9]+\s*\(\s*(0x[a-f0-9]+|\d+)\s*,\s*['"]([^'"]+)['"]\s*\)/gi;
const replacements = new Map();
let match;
while ((match = callPattern.exec(code)) !== null) {
const full = match[0];
if (replacements.has(full)) continue;
const index = match[1].startsWith('0x') ? parseInt(match[1], 16) : parseInt(match[1], 10);
const key = match[2];
try {
const decoded = decoder(index, key);
if (typeof decoded === 'string') {
replacements.set(full, literalFor(decoded));
}
} catch {
/* ignore individual decode errors */
}
}
let replacedCount = 0;
for (const [call, literal] of replacements) {
const newCode = code.split(call).join(literal);
if (newCode !== code) {
replacedCount++;
code = newCode;
}
}
return { code, replacedCount, found: replacements.size };
}
function replaceWithMap(code, relPath) {
const mapPath = mapPaths[relPath];
if (!mapPath || !fs.existsSync(mapPath)) {
return { code, replacedCount: 0, entries: 0 };
}
const decodeMap = JSON.parse(fs.readFileSync(mapPath, 'utf8'));
let replacedCount = 0;
for (const [pattern, decoded] of Object.entries(decodeMap)) {
const literal = literalFor(decoded);
const newCode = code.split(pattern).join(literal);
if (newCode !== code) {
replacedCount++;
code = newCode;
}
}
return { code, replacedCount, entries: Object.keys(decodeMap).length };
}
function cleanDecoderBlocks(code) {
// 保留原始函数,避免因匹配不准破坏结构
return code;
}
function processFile(relPath) {
const inputPath = path.join(inputBase, relPath);
const outputPath = path.join(outputBase, relPath);
if (!fs.existsSync(inputPath)) {
console.warn(`跳过缺失文件: ${relPath}`);
return;
}
let code = fs.readFileSync(inputPath, 'utf8');
console.log(`\n==== 处理 ${relPath} ====`);
const mapResult = replaceWithMap(code, relPath);
if (mapResult.entries > 0) {
console.log(` 预置映射 ${mapResult.entries} 条,替换 ${mapResult.replacedCount}`);
code = mapResult.code;
}
const decoder = buildDecoder(code);
if (!decoder) {
console.warn(' 未找到可用的解码器,直接美化原始代码');
} else {
const result = replaceCalls(code, decoder);
console.log(` 找到 ${result.found} 个唯一调用,成功替换 ${result.replacedCount}`);
code = result.code;
}
code = cleanDecoderBlocks(code);
code = beautify(code, { indent_size: 4, max_preserve_newlines: 2, end_with_newline: true });
ensureDir(path.dirname(outputPath));
fs.writeFileSync(outputPath, code, 'utf8');
console.log(` 输出: ${outputPath}`);
}
function main() {
targets.forEach(processFile);
console.log('\n全部处理完成。');
}
main();