Flex中字符串ReplaceAll

本文介绍两种在FLEX中实现字符串全部替换的方法:一种使用Array的split与join方法;另一种利用正则表达式进行全局替换,举例展示了如何去除字符串中的换行符。

用过FLEX中String类型的朋友可能知道,replace这个方法并不过替换所有内容。那么我们需要替换所有内容怎么办?只有自己动手,丰衣足食咯,呵呵。言归正专,有两种方法,一种是利用Array的方式,另一种是利用正则去替换。


/** * StringReplaceAll * @param source:String 源数据 * @param find:String 替换对象 * @param replacement:Sring 替换内容 * @return String * **/ private function StringReplaceAll( source:String, find:String, replacement:String ):String{ return source.split( find ).join( replacement ); } /** * StringReplaceAll * @param source:String 源数据 * @param find:String 替换对象 * @param replacement:Sring 替换内容 * @return String * **/ private function StringReplaceAll( source:String, find:String, replacement:String ):String{ return source.split( find ).join( replacement ); }
--------------------------------------------------------------------------------

利用正则的方式没有第一种方便,但也可以解决替换所有的。下面举个“去除换行符号”的例子:

var str:String = "ab\r\ncd\r\nefhi\r\njkl\rmn\nf"; trace(str.replace(new RegExp("[\r\n \r \n]", "g"), "")); var str:String = "ab\r\ncd\r\nefhi\r\njkl\rmn\nf"; trace(str.replace(new RegExp("[\r\n \r \n]", "g"), ""));

本文转自:http://blog.youkuaiyun.com/dante_k7/archive/2009/06/15/4270829.aspx

<!DOCTYPE html> <html> <head> <title>企业级 JS 混淆解密工具</title> <style> /* 样式沿用前版并优化进度条显示 */ .container { max-width: 1400px; margin: 0 auto; padding: 20px; } .alert { padding: 10px 15px; margin: 10px 0; border-radius: 4px; display: none; } .alert.error { background: #fee; color: #d32f2f; } .alert.success { background: #efe; color: #2e7d32; } .alert.show { display: block; } .config-panel { background: #f5f5f5; padding: 15px; border-radius: 4px; margin-bottom: 15px; } .config-group { display: flex; gap: 20px; flex-wrap: wrap; } .config-item { display: flex; align-items: center; gap: 5px; } .buttons { margin: 15px 0; display: flex; gap: 12px; } button { padding: 10px 20px; cursor: pointer; border: none; border-radius: 4px; background: #2196f3; color: white; transition: background 0.3s; } button:hover { background: #0b7dda; } button:disabled { background: #bbb; cursor: not-allowed; } .code-container { display: flex; gap: 20px; margin-top: 10px; } .code-box { flex: 1; display: flex; flex-direction: column; } textarea { width: 100%; height: 400px; padding: 12px; font-family: 'Consolas', monospace; border: 1px solid #ddd; border-radius: 4px; resize: vertical; } label { margin-bottom: 8px; font-weight: 500; } .progress { height: 4px; background: #eee; border-radius: 2px; margin: 10px 0; overflow: hidden; display: none; } .progress.show { display: block; } .progress-bar { height: 100%; background: #4caf50; width: 0%; transition: width 0.3s; } </style> </head> <body> <div class="container"> <div class="alert" id="alert"></div> <div class="config-panel"> <h4>混淆配置</h4> <div class="config-group"> <div class="config-item"> <input type="checkbox" id="mangleVars" checked> <label for="mangleVars">混淆变量名</label> </div> <div class="config-item"> <input type="checkbox" id="mangleFuncs" checked> <label for="mangleFuncs">混淆函数名</label> </div> <div class="config-item"> <input type="checkbox" id="mangleClasses" checked> <label for="mangleClasses">混淆类名</label> </div> <div class="config-item"> <input type="checkbox" id="flattenControl" checked> <label for="flattenControl">控制流扁平化</label> </div> </div> </div> <div class="buttons"> <button onclick="handleObfuscate()" id="obfBtn">混淆代码</button> <button onclick="handleDeobfuscate()" id="deobfBtn">解密代码</button> <button onclick="copyResult()">复制结果</button> </div> <div class="progress"> <div class="progress-bar" id="progressBar"></div> </div> <div class="code-container"> <div class="code-box"> <label for="inputCode">输入代码:</label> <textarea id="inputCode" placeholder="输入要处理的JS代码...">// 测试用例:包含转义字符和复杂作用域 const demo = `"包含\\"转义\\"的字符串"`; if (demo.length > 0) { let msg = `处理${demo}`; const log = (text) => { let prefix = "日志:"; console.log(prefix + text); }; log(msg); } else if (demo === "") { console.log("空字符串"); } else { console.log("其他情况"); }</textarea> </div> <div class="code-box"> <label for="outputCode">处理结果:</label> <textarea id="outputCode" placeholder="处理结果将显示在这里..." spellcheck="false"></textarea> </div> </div> </div> <!-- Web Worker 脚本(处理大文件避免阻塞) --> <script id="worker-script" type="javascript/worker"> // 注入工具函数到Worker self.window = self; // 模拟window对象 importScripts('https://cdn.jsdelivr.net/npm/text-encoding@0.7.0/lib/encoding.min.js'); // 编码兼容库 // 字符串工具类(独立模块) class StringUtil { /** * 处理字符串中的转义字符 * @param {string} str 原始字符串 * @returns {string} 处理后的字符串 */ static unescape(str) { return str.replace(/\\(["'\\])/g, '$1'); // 保留转义字符的原始含义 } /** * 转义字符串中的引号 * @param {string} str 原始字符串 * @param {string} quote 目标引号 * @returns {string} 转义后的字符串 */ static escapeQuotes(str, quote) { const escapeChar = quote === '"' ? '\\"' : "\\'"; return str.replace(new RegExp(quote, 'g'), escapeChar); } /** * 兼容IE的replaceAll实现 * @param {string} str 原始字符串 * @param {RegExp|string} search 搜索值 * @param {string} replacement 替换值 * @returns {string} 替换后的字符串 */ static replaceAll(str, search, replacement) { if (String.prototype.replaceAll) { return str.replaceAll(search, replacement); } // 降级实现 if (typeof search === 'string') { return str.split(search).join(replacement); } const match = str.match(search); if (!match) return str; return str.split(match[0]).join(replacement); } } // 加密工具类(独立模块) class CryptoUtil { /** * 检测Web Crypto支持 * @returns {boolean} 是否支持 */ static supportsWebCrypto() { return typeof crypto !== 'undefined' && 'subtle' in crypto; } /** * 生成动态密钥(从环境变量获取,这里模拟服务端分发) * @returns {string} 动态密钥 */ static getDynamicKey() { // 实际应用中应从服务端获取,此处仅为示例 const envKey = self.envKey || 'fallback_key_' + Date.now(); return btoa(envKey + Math.random().toString(36).slice(2, 10)); } /** * 异或加密(降级方案) * @param {string} str 待加密字符串 * @param {string} key 密钥 * @returns {string} 加密结果 */ static xorEncrypt(str, key) { const encrypted = []; for (let i = 0; i < str.length; i++) { encrypted.push(str.charCodeAt(i) ^ key.charCodeAt(i % key.length)); } return this.arrayToBase64(encrypted); } /** * 异或解密(降级方案) * @param {string} str 待解密字符串 * @param {string} key 密钥 * @returns {string} 解密结果 */ static xorDecrypt(str, key) { const decoded = this.base64ToArray(str); const decrypted = []; for (let i = 0; i < decoded.length; i++) { decrypted.push(decoded[i] ^ key.charCodeAt(i % key.length)); } return String.fromCharCode(...decrypted); } /** * Uint8Array转Base64 * @param {Uint8Array|number[]} arr 字节数组 * @returns {string} Base64字符串 */ static arrayToBase64(arr) { return btoa(String.fromCharCode(...arr)); } /** * Base64转Uint8Array * @param {string} base64 Base64字符串 * @returns {Uint8Array} 字节数组 */ static base64ToArray(base64) { return Uint8Array.from(atob(base64), c => c.charCodeAt(0)); } /** * 加密入口(自动选择方案) * @param {string} str 待加密字符串 * @returns {Promise<object>} 加密 payload */ static async encrypt(str) { try { const key = this.getDynamicKey(); if (this.supportsWebCrypto()) { const encoder = new TextEncoder(); const keyMaterial = await crypto.subtle.importKey( 'raw', encoder.encode(key), { name: 'AES-GCM' }, false, ['encrypt'] ); const iv = crypto.getRandomValues(new Uint8Array(12)); const encrypted = await crypto.subtle.encrypt( { name: 'AES-GCM', iv }, keyMaterial, encoder.encode(str) ); return { data: this.arrayToBase64(new Uint8Array(encrypted)), key, iv: this.arrayToBase64(iv), method: 'aes' }; } else { return { data: this.xorEncrypt(str, key), key, method: 'xor' }; } } catch (e) { throw new Error(`加密失败: ${e.message}`); } } /** * 解密入口 * @param {object} payload 加密 payload * @returns {Promise<string>} 解密结果 */ static async decrypt(payload) { try { if (payload.method === 'aes' && this.supportsWebCrypto()) { const decoder = new TextDecoder(); const keyMaterial = await crypto.subtle.importKey( 'raw', new TextEncoder().encode(payload.key), { name: 'AES-GCM' }, false, ['decrypt'] ); const iv = this.base64ToArray(payload.iv); const encrypted = this.base64ToArray(payload.data); const decrypted = await crypto.subtle.decrypt( { name: 'AES-GCM', iv }, keyMaterial, encrypted ); return decoder.decode(decrypted); } else { return this.xorDecrypt(payload.data, payload.key); } } catch (e) { throw new Error(`解密失败: ${e.message}`); } } } // 作用域分析器(增强版) class ScopeAnalyzer { constructor() { this.scopeStack = []; // 作用域栈 [当前作用域, 父作用域...] this.varIndex = 0; // 变量名索引 this.enterScope(); // 初始化全局作用域 } /** * 进入新作用域 */ enterScope() { this.scopeStack.push(new Map()); // 新作用域用Map存储变量映射 } /** * 退出当前作用域 */ exitScope() { if (this.scopeStack.length > 1) { // 保留全局作用域 this.scopeStack.pop(); } } /** * 生成安全的变量名(避免关键字和作用域冲突) * @param {number} index 索引值 * @returns {string} 变量名 */ generateVarName(index) { const keywords = new Set([ 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'export', 'extends', 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'new', 'return', 'super', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'let', 'void', 'while', 'with', 'yield', 'enum', 'implements', 'interface', 'package', 'protected', 'static' ]); const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; const char = chars[index % chars.length]; const num = Math.floor(index / chars.length); const name = `_${char}${num > 0 ? num : ''}`; return keywords.has(name) ? this.generateVarName(index + 1) : name; } /** * 获取变量在当前作用域的混淆名 * @param {string} originalName 原始变量名 * @returns {string} 混淆名 */ getMangledName(originalName) { const currentScope = this.scopeStack[this.scopeStack.length - 1]; // 检查当前作用域是否已存在映射 if (currentScope.has(originalName)) { return currentScope.get(originalName); } // 生成新变量名并检查作用域冲突 let mangled; do { mangled = this.generateVarName(this.varIndex++); } while (this.checkScopeConflict(mangled)); currentScope.set(originalName, mangled); return mangled; } /** * 检查变量名是否在任何父作用域中存在 * @param {string} mangledName 混淆名 * @returns {boolean} 是否冲突 */ checkScopeConflict(mangledName) { for (const scope of this.scopeStack) { if (Array.from(scope.values()).includes(mangledName)) { return true; } } return false; } /** * 获取当前作用域链中的所有变量映射 * @returns {Map<string, string>} 变量映射表 */ getAllMappings() { return this.scopeStack.reduce((acc, scope) => { scope.forEach((val, key) => acc.set(key, val)); return acc; }, new Map()); } } // 混淆处理器 class Obfuscator { /** * 处理字符串(支持转义字符) * @param {string} code 代码字符串 * @returns {Promise<string>} 处理后的代码 */ static async processStrings(code) { // 匹配所有字符串(支持转义字符和模板字符串) const strRegex = /("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`)/g; const matches = []; let match; // 收集所有匹配结果 while ((match = strRegex.exec(code)) !== null) { matches.push({ full: match[0], content: match[0].slice(1, -1), // 提取引号内内容 quote: match[0][0], // 记录原始引号类型 index: match.index }); } // 按索引倒序替换(避免替换后索引偏移) matches.sort((a, b) => b.index - a.index).forEach(async (item) => { // 处理转义字符(保留原始含义) const rawContent = StringUtil.unescape(item.content); const encrypted = await CryptoUtil.encrypt(rawContent); // 生成解密代码 const decryptCode = `(async()=>{const p=${JSON.stringify(encrypted)};return await CryptoUtil.decrypt(p)})()`; // 替换原始字符串 code = code.slice(0, item.index) + decryptCode + code.slice(item.index + item.full.length); }); return code; } /** * 处理作用域(块级作用域、箭头函数) * @param {string} code 代码字符串 * @param {object} config 混淆配置 * @returns {string} 处理后的代码 */ static processScopes(code, config) { const analyzer = new ScopeAnalyzer(); let result = ''; let index = 0; // 匹配作用域入口(函数、类、块级作用域) const scopeRegex = /(function\s+\w*|class\s+\w*|\{|\(.*?\)\s*=>)/g; // 流式处理代码,解析作用域 while ((match = scopeRegex.exec(code)) !== null) { // 添加匹配前的代码 result += code.slice(index, match.index); index = match.index + match[0].length; const scopeType = match[0]; // 处理作用域进入 if (scopeType === '{' || /function|class|=>/.test(scopeType)) { analyzer.enterScope(); // 处理函数名 if (config.mangleFuncs && /function\s+(\w+)/.test(scopeType)) { const funcName = scopeType.match(/function\s+(\w+)/)[1]; const mangled = analyzer.getMangledName(funcName); result += scopeType.replace(funcName, mangled); continue; } // 处理类名 if (config.mangleClasses && /class\s+(\w+)/.test(scopeType)) { const className = scopeType.match(/class\s+(\w+)/)[1]; const mangled = analyzer.getMangledName(className); result += scopeType.replace(className, mangled); continue; } result += scopeType; } } // 添加剩余代码 result += code.slice(index); return result; } /** * 控制流扁平化(支持else if) * @param {string} code 代码字符串 * @returns {string} 处理后的代码 */ static flattenControlFlow(code) { // 处理if-else if-else结构 let caseIndex = 1; return code // 处理if语句 .replace(/if\s*\((.*?)\)\s*\{/g, () => { const currentCase = caseIndex++; return `switch(true){case ${currentCase}:`; }) // 处理else if .replace(/}\s*else\s+if\s*\((.*?)\)\s*\{/g, () => { const currentCase = caseIndex++; return `break;case ${currentCase}:`; }) // 处理else .replace(/}\s*else\s*\{/g, 'break;default:'); } /** * 执行混淆 * @param {string} code 代码 * @param {object} config 配置 * @returns {Promise<string>} 混淆结果 */ static async run(code, config) { let processed = code; // 1. 处理字符串 processed = await this.processStrings(processed); // 2. 处理作用域和变量 processed = this.processScopes(processed, config); // 3. 控制流扁平化 if (config.flattenControl) { processed = this.flattenControlFlow(processed); } return processed; } } // 解密处理器 class Deobfuscator { /** * 执行解密 * @param {string} code 混淆代码 * @returns {Promise<string>} 解密结果 */ static async run(code) { // 匹配加密片段 const cryptoRegex = /\(async\(\)\=>\{const p=({.*?});return await CryptoUtil\.decrypt\(p\)\}\)\(\)/g; const matches = []; let match; while ((match = cryptoRegex.exec(code)) !== null) { matches.push({ full: match[0], payload: JSON.parse(match[1]), index: match.index }); } // 倒序替换解密结果 matches.sort((a, b) => b.index - a.index).forEach(async (item) => { const decrypted = await CryptoUtil.decrypt(item.payload); // 自动选择合适的引号并转义 const quote = decrypted.includes('"') ? "'" : '"'; const escaped = StringUtil.escapeQuotes(decrypted, quote); code = code.slice(0, item.index) + `${quote}${escaped}${quote}` + code.slice(item.index + item.full.length); }); return code; } } // Worker消息处理 self.onmessage = async (e) => { const { type, code, config, envKey } = e.data; self.envKey = envKey; // 注入环境变量密钥 self.CryptoUtil = CryptoUtil; // 暴露CryptoUtil供解密函数使用 try { let result; if (type === 'obfuscate') { result = await Obfuscator.run(code, config); } else { result = await Deobfuscator.run(code); } self.postMessage({ type: 'success', result }); } catch (e) { self.postMessage({ type: 'error', message: e.message }); } }; </script> <script> // 主页面脚本 (() => { // 工具函数 const showAlert = (message, isError = true) => { const alertEl = document.getElementById('alert'); alertEl.textContent = message; alertEl.className = `alert ${isError ? 'error' : 'success'} show`; setTimeout(() => alertEl.classList.remove('show'), 3000); }; const updateProgress = (percent) => { const progress = document.querySelector('.progress'); const bar = document.getElementById('progressBar'); progress.classList.add('show'); bar.style.width = `${Math.min(100, percent)}%`; if (percent >= 100) { setTimeout(() => progress.classList.remove('show'), 500); } }; // 创建Web Worker const createWorker = () => { const workerScript = document.getElementById('worker-script').textContent; const blob = new Blob([workerScript], { type: 'application/javascript' }); const url = URL.createObjectURL(blob); return new Worker(url); }; // 环境变量密钥(模拟服务端注入) const getEnvKey = () => { // 实际应用中应从服务端获取 return localStorage.getItem('obf_env_key') || `env_${Date.now().toString(36)}`; }; // 保存环境变量密钥 localStorage.setItem('obf_env_key', getEnvKey()); // 混淆处理 window.handleObfuscate = async () => { const input = document.getElementById('inputCode').value.trim(); if (!input) return showAlert('请输入要混淆的代码'); const obfBtn = document.getElementById('obfBtn'); obfBtn.disabled = true; updateProgress(10); try { const worker = createWorker(); const config = { mangleVars: document.getElementById('mangleVars').checked, mangleFuncs: document.getElementById('mangleFuncs').checked, mangleClasses: document.getElementById('mangleClasses').checked, flattenControl: document.getElementById('flattenControl').checked }; // 监听Worker消息 worker.onmessage = (e) => { if (e.data.type === 'success') { document.getElementById('outputCode').value = e.data.result; updateProgress(100); showAlert('混淆成功', false); } else { showAlert(e.data.message); updateProgress(0); } worker.terminate(); obfBtn.disabled = false; }; // 发送任务到Worker worker.postMessage({ type: 'obfuscate', code: input, config, envKey: getEnvKey() }); } catch (e) { showAlert(`处理失败: ${e.message}`); obfBtn.disabled = false; updateProgress(0); } }; // 解密处理 window.handleDeobfuscate = async () => { const input = document.getElementById('inputCode').value.trim(); if (!input) return showAlert('请输入要解密的代码'); const deobfBtn = document.getElementById('deobfBtn'); deobfBtn.disabled = true; updateProgress(10); try { const worker = createWorker(); worker.onmessage = (e) => { if (e.data.type === 'success') { document.getElementById('outputCode').value = e.data.result; updateProgress(100); showAlert('解密成功', false); } else { showAlert(e.data.message); updateProgress(0); } worker.terminate(); deobfBtn.disabled = false; }; worker.postMessage({ type: 'deobfuscate', code: input, envKey: getEnvKey() }); } catch (e) { showAlert(`处理失败: ${e.message}`); deobfBtn.disabled = false; updateProgress(0); } }; // 复制结果 window.copyResult = () => { const output = document.getElementById('outputCode'); if (!output.value) return showAlert('没有可复制的内容'); output.select(); document.execCommand('copy'); showAlert('复制成功', false); }; })(); </script> </body> </html>
11-06
<!DOCTYPE html> <html> <head> <title>终极版 JS 混淆解密工具</title> <style> /* 保留原有样式并优化布局 */ .container { max-width: 1400px; margin: 0 auto; padding: 20px; } .alert { padding: 10px 15px; margin: 10px 0; border-radius: 4px; display: none; } .alert.error { background: #fee; color: #d32f2f; } .alert.success { background: #efe; color: #2e7d32; } .alert.warning { background: #ffe; color: #f57c00; } .alert.show { display: block; } .config-panel { background: #f5f5f5; padding: 15px; border-radius: 4px; margin-bottom: 15px; } .config-group { display: flex; gap: 20px; flex-wrap: wrap; } .config-item { display: flex; align-items: center; gap: 5px; } .buttons { margin: 15px 0; display: flex; gap: 12px; } button { padding: 10px 20px; cursor: pointer; border: none; border-radius: 4px; background: #2196f3; color: white; transition: background 0.3s; } button:hover { background: #0b7dda; } button:disabled { background: #bbb; cursor: not-allowed; } .code-container { display: flex; gap: 20px; margin-top: 10px; } .code-box { flex: 1; display: flex; flex-direction: column; } textarea { width: 100%; height: 400px; padding: 12px; font-family: 'Consolas', monospace; border: 1px solid #ddd; border-radius: 4px; resize: vertical; } label { margin-bottom: 8px; font-weight: 500; } .progress { height: 4px; background: #eee; border-radius: 2px; margin: 10px 0; overflow: hidden; display: none; } .progress.show { display: block; } .progress-bar { height: 100%; background: #4caf50; width: 0%; transition: width 0.3s; } </style> </head> <body> <div class="container"> <div class="alert" id="alert"></div> <div class="config-panel"> <h4>混淆配置</h4> <div class="config-group"> <div class="config-item"> <input type="checkbox" id="mangleVars" checked> <label for="mangleVars">混淆变量名</label> </div> <div class="config-item"> <input type="checkbox" id="mangleFuncs" checked> <label for="mangleFuncs">混淆函数名</label> </div> <div class="config-item"> <input type="checkbox" id="mangleClasses" checked> <label for="mangleClasses">混淆类名</label> </div> <div class="config-item"> <input type="checkbox" id="flattenControl" checked> <label for="flattenControl">控制流扁平化</label> </div> <div class="config-item"> <input type="checkbox" id="antiDebug" checked> <label for="antiDebug">防调试保护</label> </div> </div> </div> <div class="buttons"> <button onclick="handleObfuscate()" id="obfBtn">混淆代码</button> <button onclick="handleDeobfuscate()" id="deobfBtn">解密代码</button> <button onclick="copyResult()">复制结果</button> </div> <div class="progress"> <div class="progress-bar" id="progressBar"></div> </div> <div class="code-container"> <div class="code-box"> <label for="inputCode">输入代码:</label> <textarea id="inputCode" placeholder="输入要处理的JS代码...">// 测试用例:模板字符串、try/catch、循环 const user = "World"; const str = `Hello ${user}! Current time: ${new Date().getHours()}`; try { let a = 10; if (a > 5) throw new Error("测试异常"); } catch (e) { let a = 20; // 应与try块中的a区分 console.log(`捕获异常: ${e.message}, a=${a}`); } // 循环结构测试 for (let i = 0; i < 3; i++) { console.log(`循环第${i}次`); } while (Math.random() > 0.5) { console.log("随机循环"); }</textarea> </div> <div class="code-box"> <label for="outputCode">处理结果:</label> <textarea id="outputCode" placeholder="处理结果将显示在这里..." spellcheck="false"></textarea> </div> </div> </div> <!-- 引入AST解析库 --> <script src="https://cdn.jsdelivr.net/npm/acorn@8.10.0/dist/acorn.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/walkes@0.2.0/walkes.min.js"></script> <!-- Web Worker 脚本 --> <script id="worker-script" type="javascript/worker"> // 导入所需库(Worker内通过importScripts加载) importScripts( 'https://cdn.jsdelivr.net/npm/acorn@8.10.0/dist/acorn.min.js', 'https://cdn.jsdelivr.net/npm/walkes@0.2.0/walkes.min.js', 'https://cdn.jsdelivr.net/npm/text-encoding@0.7.0/lib/encoding.min.js' ); // 模块封装:字符串工具 const StringUtil = (() => { class _StringUtil { /** * 处理模板字符串,分离静态和动态部分 * @param {string} template 模板字符串内容(不含外层`) * @returns {Array} 格式: [{type: 'static', value: 'xxx'}, {type: 'dynamic', value: 'expr'}] */ static parseTemplate(template) { const parts = []; let currentStatic = ''; let inExpression = false; let braceDepth = 0; for (let i = 0; i < template.length; i++) { // 检测模板表达式开始 ${ if (!inExpression && template[i] === '$' && template[i+1] === '{') { if (currentStatic) { parts.push({ type: 'static', value: currentStatic }); currentStatic = ''; } inExpression = true; i++; // 跳过{ continue; } // 检测模板表达式结束 } if (inExpression) { if (template[i] === '{') braceDepth++; if (template[i] === '}') { if (braceDepth === 0) { inExpression = false; continue; } braceDepth--; } parts.push({ type: 'dynamic', value: template[i] }); continue; } currentStatic += template[i]; } if (currentStatic) { parts.push({ type: 'static', value: currentStatic }); } return parts; } /** * 转义字符串中的引号 * @param {string} str 原始字符串 * @param {string} quote 目标引号 * @returns {string} 转义后字符串 */ static escapeQuotes(str, quote) { const escapeChar = quote === '"' ? '\\"' : "\\'"; return str.replace(new RegExp(quote, 'g'), escapeChar); } /** * 兼容IE的replaceAll * @param {string} str 原始字符串 * @param {string} search 搜索值 * @param {string} replacement 替换值 * @returns {string} 替换字符串 */ static replaceAll(str, search, replacement) { return String.prototype.replaceAll ? str.replaceAll(search, replacement) : str.split(search).join(replacement); } } return _StringUtil; })(); // 模块封装:加密工具 const CryptoUtil = (() => { class _CryptoUtil { /** * 生成会话级密钥(存储在sessionStorage) * @returns {string} 随机密钥 */ static generateSessionKey() { const key = Array.from(window.crypto.getRandomValues(new Uint8Array(16))) .map(b => b.toString(16).padStart(2, '0')) .join(''); sessionStorage.setItem('obf_session_key', key); return key; } /** * 获取会话密钥 * @returns {string} 密钥 */ static getSessionKey() { return sessionStorage.getItem('obf_session_key') || this.generateSessionKey(); } /** * AES-GCM加密 * @param {string} str 待加密字符串 * @returns {Promise<object>} 加密结果 */ static async encrypt(str) { try { const keyMaterial = await window.crypto.subtle.importKey( 'raw', new TextEncoder().encode(this.getSessionKey()), { name: 'AES-GCM' }, false, ['encrypt'] ); const iv = window.crypto.getRandomValues(new Uint8Array(12)); const encrypted = await window.crypto.subtle.encrypt( { name: 'AES-GCM', iv }, keyMaterial, new TextEncoder().encode(str) ); return { data: btoa(String.fromCharCode(...new Uint8Array(encrypted))), iv: btoa(String.fromCharCode(...iv)), method: 'aes' }; } catch (e) { throw new Error(`加密失败: ${e.message}`); } } /** * AES-GCM解密 * @param {object} payload 加密数据 * @returns {Promise<string>} 解密结果 */ static async decrypt(payload) { try { const keyMaterial = await window.crypto.subtle.importKey( 'raw', new TextEncoder().encode(this.getSessionKey()), { name: 'AES-GCM' }, false, ['decrypt'] ); const iv = Uint8Array.from(atob(payload.iv), c => c.charCodeAt(0)); const encrypted = Uint8Array.from(atob(payload.data), c => c.charCodeAt(0)); const decrypted = await window.crypto.subtle.decrypt( { name: 'AES-GCM', iv }, keyMaterial, encrypted ); return new TextDecoder().decode(decrypted); } catch (e) { throw new Error(`解密失败: ${e.message}`); } } } return _CryptoUtil; })(); // 模块封装:作用域分析器 const ScopeAnalyzer = (() => { class _ScopeAnalyzer { constructor() { this.scopeStack = [new Map()]; // 初始全局作用域 this.varIndex = 0; } /** * 进入新作用域 */ enterScope() { this.scopeStack.push(new Map()); } /** * 退出当前作用域 */ exitScope() { if (this.scopeStack.length > 1) this.scopeStack.pop(); } /** * 生成安全变量名 * @returns {string} 变量名 */ generateVarName() { const keywords = new Set(['break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'export', 'extends', 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'new', 'return', 'super', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'let', 'void', 'while', 'with', 'yield']); const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; let name; do { const char = chars[this.varIndex % chars.length]; const num = Math.floor(this.varIndex / chars.length); name = `_${char}${num > 0 ? num : ''}`; this.varIndex++; } while (keywords.has(name) || this.isNameInScope(name)); return name; } /** * 检查变量名是否在作用域中存在 * @param {string} name 变量名 * @returns {boolean} 是否存在 */ isNameInScope(name) { return this.scopeStack.some(scope => Array.from(scope.values()).includes(name) ); } /** * 获取变量混淆名 * @param {string} originalName 原始变量名 * @returns {string} 混淆名 */ getMangledName(originalName) { const currentScope = this.scopeStack[this.scopeStack.length - 1]; if (currentScope.has(originalName)) { return currentScope.get(originalName); } const mangled = this.generateVarName(); currentScope.set(originalName, mangled); return mangled; } /** * 获取当前作用域链的所有变量映射 * @returns {Map} 变量映射表 */ getAllMappings() { return this.scopeStack.reduce((acc, scope) => { scope.forEach((v, k) => acc.set(k, v)); return acc; }, new Map()); } } return _ScopeAnalyzer; })(); // 模块封装:混淆器 const Obfuscator = (() => { class _Obfuscator { /** * 处理模板字符串 * @param {string} code 代码 * @returns {Promise<string>} 处理后代码 */ static async processTemplates(code) { const ast = acorn.parse(code, { ecmaVersion: 2020, sourceType: 'module' }); let result = code; let offset = 0; walkes(ast, { TemplateLiteral(node) { // 提取模板字符串内容 const start = node.start + offset; const end = node.end + offset; const templateRaw = code.slice(start, end); const templateContent = templateRaw.slice(1, -1); // 移除外层` // 解析静态和动态部分 const parts = StringUtil.parseTemplate(templateContent); if (parts.length === 0) return; // 加密静态部分 const processedParts = parts.map(async part => { if (part.type === 'static') { const encrypted = await CryptoUtil.encrypt(part.value); return `await CryptoUtil.decrypt(${JSON.stringify(encrypted)})`; } return part.value; // 动态部分保留原样 }); // 生成新模板字符串 Promise.all(processedParts).then(processed => { const newTemplate = `\`\${[${processed.join(',')}].join('')}\``; // 替换原始模板 result = result.slice(0, start) + newTemplate + result.slice(end); offset += newTemplate.length - (end - start); }); } }); return result; } /** * 处理作用域(包含try/catch) * @param {string} code 代码 * @returns {string} 处理后代码 */ static processScopes(code) { const analyzer = new ScopeAnalyzer(); const ast = acorn.parse(code, { ecmaVersion: 2020 }); // 遍历AST标记作用域 walkes(ast, { // 函数作用域 FunctionDeclaration(node) { analyzer.enterScope(); node.params.forEach(param => this.processParam(param, analyzer)); }, FunctionExpression(node) { analyzer.enterScope(); node.params.forEach(param => this.processParam(param, analyzer)); }, ArrowFunctionExpression(node) { analyzer.enterScope(); node.params.forEach(param => this.processParam(param, analyzer)); }, // 块级作用域 BlockStatement() { analyzer.enterScope(); }, // try/catch作用域 TryStatement(node) { analyzer.enterScope(); // try块 if (node.handler) { analyzer.enterScope(); // catch块 this.processParam(node.handler.param, analyzer); } }, // 类作用域 ClassDeclaration() { analyzer.enterScope(); }, // 退出作用域 'FunctionDeclaration:exit'() { analyzer.exitScope(); }, 'FunctionExpression:exit'() { analyzer.exitScope(); }, 'ArrowFunctionExpression:exit'() { analyzer.exitScope(); }, 'BlockStatement:exit'() { analyzer.exitScope(); }, 'TryStatement:exit'(node) { analyzer.exitScope(); // 退出try块 if (node.handler) analyzer.exitScope(); // 退出catch块 }, 'ClassDeclaration:exit'() { analyzer.exitScope(); } }, this); // 替换变量名 return this.replaceIdentifiers(code, analyzer.getAllMappings()); } /** * 处理函数参数 * @param {object} param 参数节点 * @param {ScopeAnalyzer} analyzer 作用域分析器 */ static processParam(param, analyzer) { if (param.type === 'Identifier') { analyzer.getMangledName(param.name); } } /** * 替换标识符 * @param {string} code 代码 * @param {Map} mappings 变量映射表 * @returns {string} 处理后代码 */ static replaceIdentifiers(code, mappings) { let result = code; mappings.forEach((mangled, original) => { const regex = new RegExp(`\\b${original}\\b(?!\\.)`, 'g'); result = StringUtil.replaceAll(result, regex, mangled); }); return result; } /** * 控制流扁平化(支持循环和switch) * @param {string} code 代码 * @returns {string} 处理后代码 */ static flattenControlFlow(code) { // 处理for循环 code = code.replace(/for\s*\(\s*let\s+(\w+)\s*=\s*(\d+)\s*;\s*\1\s*<\s*(\d+)\s*;\s*\1\+\+\s*\)\s*\{/g, (match, varName, start, end) => { return `{let ${varName}=${start};const _loop=()=>{if(${varName}<${end}){`; } ).replace(/}\s*(\/\/.*)?$/gm, (match) => { return `${match}${varName}++;_loop();}};_loop();}`; }); // 处理while循环 code = code.replace(/while\s*\((.*?)\)\s*\{/g, `{const _loop=()=>{if($1){` ).replace(/}\s*(\/\/.*)?$/gm, (match) => { return `${match}_loop();}};_loop();}`; }); // 处理if-else if-else let caseIdx = 1; code = code.replace(/if\s*\((.*?)\)\s*\{/g, () => { const idx = caseIdx++; return `switch(true){case ${idx}:`; }).replace(/}\s*else\s+if\s*\((.*?)\)\s*\{/g, () => { const idx = caseIdx++; return `break;case ${idx}:`; }).replace(/}\s*else\s*\{/g, 'break;default:'); return code; } /** * 添加防调试保护 * @param {string} code 代码 * @returns {string} 处理后代码 */ static addAntiDebug(code) { const antiDebugCode = ` (()=>{ const check = ()=>{ const t=performance.now(); debugger; if(performance.now()-t>160)throw new Error("检测到调试行为"); }; setInterval(check, 100); })(); `; return antiDebugCode + code; } /** * 分块处理大文件 * @param {string} code 代码 * @param {object} config 配置 * @returns {Promise<string>} 混淆结果 */ static async processInChunks(code, config) { const chunkSize = 1024 * 10; // 10KB每块 const chunks = []; for (let i = 0; i < code.length; i += chunkSize) { chunks.push(code.slice(i, i + chunkSize)); } // 并行处理所有块 const processedChunks = await Promise.all(chunks.map(async (chunk, idx) => { self.postMessage({ type: 'progress', value: Math.floor((idx / chunks.length) * 80) }); let processed = chunk; processed = await this.processTemplates(processed); processed = this.processScopes(processed); if (config.flattenControl) processed = this.flattenControlFlow(processed); return processed; })); let result = processedChunks.join(''); if (config.antiDebug) result = this.addAntiDebug(result); self.postMessage({ type: 'progress', value: 100 }); return result; } /** * 执行混淆 * @param {string} code 代码 * @param {object} config 配置 * @returns {Promise<string>} 混淆结果 */ static async run(code, config) { try { return await this.processInChunks(code, config); } catch (e) { const category = e.message.includes('加密') ? 'security' : 'syntax'; throw { message: e.message, category }; } } } return _Obfuscator; })(); // 模块封装:解密器 const Deobfuscator = (() => { class _Deobfuscator { /** * 分块解密 * @param {string} code 代码 * @returns {Promise<string>} 解密结果 */ static async processInChunks(code) { const chunkSize = 1024 * 10; const chunks = []; for (let i = 0; i < code.length; i += chunkSize) { chunks.push(code.slice(i, i + chunkSize)); } const processedChunks = await Promise.all(chunks.map(async (chunk, idx) => { self.postMessage({ type: 'progress', value: Math.floor((idx / chunks.length) * 100) }); return await this.restoreStrings(chunk); })); return processedChunks.join(''); } /** * 还原加密字符串 * @param {string} code 代码 * @returns {Promise<string>} 处理后代码 */ static async restoreStrings(code) { const regex = /await CryptoUtil\.decrypt\((\{.*?\})\)/g; const matches = []; let match; while ((match = regex.exec(code)) !== null) { matches.push({ full: match[0], payload: JSON.parse(match[1]), index: match.index }); } // 倒序替换 matches.sort((a, b) => b.index - a.index).forEach(async (item) => { try { const decrypted = await CryptoUtil.decrypt(item.payload); code = code.slice(0, item.index) + decrypted + code.slice(item.index + item.full.length); } catch (e) { console.warn(`解密片段失败: ${e.message}`); } }); return code; } /** * 执行解密 * @param {string} code 代码 * @returns {Promise<string>} 解密结果 */ static async run(code) { try { return await this.processInChunks(code); } catch (e) { const category = e.message.includes('解密') ? 'security' : 'syntax'; throw { message: e.message, category }; } } } return _Deobfuscator; })(); // Worker消息处理 self.onmessage = async (e) => { const { type, code, config } = e.data; try { // 暴露加密工具供解密函数使用 self.CryptoUtil = CryptoUtil; let result; if (type === 'obfuscate') { result = await Obfuscator.run(code, config); } else { result = await Deobfuscator.run(code); } self.postMessage({ type: 'success', result }); } catch (e) { self.postMessage({ type: 'error', message: e.message, category: e.category || 'unknown' }); } }; </script> <script> // 主页面脚本 (() => { // 工具函数 const showAlert = (message, isError = true, category = 'unknown') => { const alertEl = document.getElementById('alert'); alertEl.textContent = message; alertEl.className = `alert ${ isError ? (category === 'security' ? 'error' : 'error') : 'success' } show`; setTimeout(() => alertEl.classList.remove('show'), 3000); }; const updateProgress = (percent) => { const progress = document.querySelector('.progress'); const bar = document.getElementById('progressBar'); progress.classList.add('show'); bar.style.width = `${Math.min(100, percent)}%`; if (percent >= 100) { setTimeout(() => progress.classList.remove('show'), 500); } }; // 创建Web Worker const createWorker = () => { const workerScript = document.getElementById('worker-script').textContent; const blob = new Blob([workerScript], { type: 'application/javascript' }); const url = URL.createObjectURL(blob); return new Worker(url); }; // 混淆处理 window.handleObfuscate = () => { const input = document.getElementById('inputCode').value.trim(); if (!input) return showAlert('请输入要混淆的代码'); const obfBtn = document.getElementById('obfBtn'); obfBtn.disabled = true; updateProgress(0); const worker = createWorker(); const config = { mangleVars: document.getElementById('mangleVars').checked, mangleFuncs: document.getElementById('mangleFuncs').checked, mangleClasses: document.getElementById('mangleClasses').checked, flattenControl: document.getElementById('flattenControl').checked, antiDebug: document.getElementById('antiDebug').checked }; worker.onmessage = (e) => { if (e.data.type === 'progress') { updateProgress(e.data.value); } else if (e.data.type === 'success') { document.getElementById('outputCode').value = e.data.result; showAlert('混淆成功', false); obfBtn.disabled = false; } else if (e.data.type === 'error') { showAlert(`混淆失败: ${e.data.message}`, true, e.data.category); obfBtn.disabled = false; } }; worker.postMessage({ type: 'obfuscate', code: input, config }); }; // 解密处理 window.handleDeobfuscate = () => { const input = document.getElementById('inputCode').value.trim(); if (!input) return showAlert('请输入要解密的代码'); const deobfBtn = document.getElementById('deobfBtn'); deobfBtn.disabled = true; updateProgress(0); const worker = createWorker(); worker.onmessage = (e) => { if (e.data.type === 'progress') { updateProgress(e.data.value); } else if (e.data.type === 'success') { document.getElementById('outputCode').value = e.data.result; showAlert('解密成功', false); deobfBtn.disabled = false; } else if (e.data.type === 'error') { showAlert(`解密失败: ${e.data.message}`, true, e.data.category); deobfBtn.disabled = false; } }; worker.postMessage({ type: 'deobfuscate', code: input }); }; // 复制结果 window.copyResult = () => { const output = document.getElementById('outputCode'); if (!output.value) return showAlert('没有可复制的内容'); output.select(); document.execCommand('copy'); showAlert('复制成功', false); }; })(); </script> </body> </html>
11-06
<!DOCTYPE html> <html> <head> <title>专业版 JS 混淆解密工具</title> <style> .container { max-width: 1400px; margin: 0 auto; padding: 20px; } .alert { padding: 10px 15px; margin: 10px 0; border-radius: 4px; display: none; } .alert.error { background: #fee; color: #d32f2f; } .alert.success { background: #efe; color: #2e7d32; } .alert.show { display: block; } .config-panel { background: #f5f5f5; padding: 15px; border-radius: 4px; margin-bottom: 15px; } .config-group { display: flex; gap: 20px; flex-wrap: wrap; } .config-item { display: flex; align-items: center; gap: 5px; } .buttons { margin: 15px 0; display: flex; gap: 12px; } button { padding: 10px 20px; cursor: pointer; border: none; border-radius: 4px; background: #2196f3; color: white; transition: background 0.3s; } button:hover { background: #0b7dda; } button:disabled { background: #bbb; cursor: not-allowed; } .code-container { display: flex; gap: 20px; margin-top: 10px; } .code-box { flex: 1; display: flex; flex-direction: column; } textarea { width: 100%; height: 400px; padding: 12px; font-family: 'Consolas', monospace; border: 1px solid #ddd; border-radius: 4px; resize: vertical; } label { margin-bottom: 8px; font-weight: 500; } .progress { height: 4px; background: #eee; border-radius: 2px; margin: 10px 0; overflow: hidden; display: none; } .progress.show { display: block; } .progress-bar { height: 100%; background: #4caf50; width: 0%; transition: width 0.3s; } </style> </head> <body> <div class="container"> <div class="alert" id="alert"></div> <div class="config-panel"> <h4>混淆配置</h4> <div class="config-group"> <div class="config-item"> <input type="checkbox" id="mangleVars" checked> <label for="mangleVars">混淆变量名</label> </div> <div class="config-item"> <input type="checkbox" id="mangleFuncs" checked> <label for="mangleFuncs">混淆函数名</label> </div> <div class="config-item"> <input type="checkbox" id="mangleClasses" checked> <label for="mangleClasses">混淆类名</label> </div> <div class="config-item"> <input type="checkbox" id="flattenControl" checked> <label for="flattenControl">控制流扁平化</label> </div> </div> </div> <div class="buttons"> <button onclick="handleObfuscate()" id="obfBtn">混淆代码</button> <button onclick="handleDeobfuscate()" id="deobfBtn">解密代码</button> <button onclick="copyResult()">复制结果</button> </div> <div class="progress"> <div class="progress-bar" id="progressBar"></div> </div> <div class="code-container"> <div class="code-box"> <label for="inputCode">输入代码:</label> <textarea id="inputCode" placeholder="输入要处理的JS代码...">function outer() { let a = 1; function inner() { let a = 2; console.log(a); } inner(); class MyClass { constructor() { this.value = a; } } return new MyClass(); }</textarea> </div> <div class="code-box"> <label for="outputCode">处理结果:</label> <textarea id="outputCode" placeholder="处理结果将显示在这里..." spellcheck="false"></textarea> </div> </div> </div> <script> // 工具函数:非阻塞提示 const showAlert = (message, isError = true) => { const alertEl = document.getElementById('alert'); alertEl.textContent = message; alertEl.className = `alert ${isError ? 'error' : 'success'} show`; setTimeout(() => alertEl.classList.remove('show'), 3000); }; // 进度更新 const updateProgress = (percent) => { const progress = document.querySelector('.progress'); const bar = document.getElementById('progressBar'); progress.classList.add('show'); bar.style.width = `${Math.min(100, percent)}%`; if (percent >= 100) { setTimeout(() => progress.classList.remove('show'), 500); } }; // 动态密钥生成 const getDynamicKey = () => { return Math.random().toString(36).slice(2, 10) + Date.now().toString(36); }; // 兼容IE的展开语法替代 const fromCharCode = (arr) => { if (Array.isArray(arr) && 'from' in String) { return String.fromCharCode(...arr); } // IE兼容:手动拼接 let str = ''; for (let i = 0; i < arr.length; i++) { str += String.fromCharCode(arr[i]); } return str; }; // 加密解密核心(使用动态密钥+Web Crypto降级) const cryptoUtil = { // 检测Web Crypto支持 supportsWebCrypto: () => typeof window !== 'undefined' && 'crypto' in window && 'subtle' in window.crypto, // 异或加密(降级方案) xorEncrypt: (str, key) => { const encrypted = []; for (let i = 0; i < str.length; i++) { const keyChar = key.charCodeAt(i % key.length); encrypted.push(str.charCodeAt(i) ^ keyChar); } return btoa(fromCharCode(encrypted)); }, // 异或解密(降级方案) xorDecrypt: (str, key) => { const decoded = atob(str); const decrypted = []; for (let i = 0; i < decoded.length; i++) { const keyChar = key.charCodeAt(i % key.length); decrypted.push(decoded.charCodeAt(i) ^ keyChar); } return fromCharCode(decrypted); }, // 加密入口(自动选择方案) encrypt: async (str) => { const key = getDynamicKey(); if (this.supportsWebCrypto()) { // Web Crypto加密(更安全) const encoder = new TextEncoder(); const keyMaterial = await window.crypto.subtle.importKey( 'raw', encoder.encode(key), { name: 'AES-GCM' }, false, ['encrypt'] ); const iv = window.crypto.getRandomValues(new Uint8Array(12)); const encrypted = await window.crypto.subtle.encrypt( { name: 'AES-GCM', iv }, keyMaterial, encoder.encode(str) ); return { data: btoa(fromCharCode([...new Uint8Array(encrypted)])), key, iv: btoa(fromCharCode([...iv])), method: 'aes' }; } else { // 降级为异或加密 return { data: this.xorEncrypt(str, key), key, method: 'xor' }; } }, // 解密入口 decrypt: async (payload) => { if (payload.method === 'aes' && this.supportsWebCrypto()) { const decoder = new TextDecoder(); const keyMaterial = await window.crypto.subtle.importKey( 'raw', new TextEncoder().encode(payload.key), { name: 'AES-GCM' }, false, ['decrypt'] ); const iv = new Uint8Array([...atob(payload.iv)].map(c => c.charCodeAt(0))); const encrypted = new Uint8Array([...atob(payload.data)].map(c => c.charCodeAt(0))); const decrypted = await window.crypto.subtle.decrypt( { name: 'AES-GCM', iv }, keyMaterial, encrypted ); return decoder.decode(decrypted); } else { // 异或解密 return this.xorDecrypt(payload.data, payload.key); } } }; // 变量名生成器(避免关键字) const keywordSet = new Set([ 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'export', 'extends', 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'new', 'return', 'super', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'let', 'void', 'while', 'with', 'yield', 'enum', 'implements', 'interface', 'package', 'protected', 'static' ]); const generateVarName = (index) => { const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; const char = chars[index % chars.length]; const num = Math.floor(index / chars.length); const name = `_${char}${num > 0 ? num : ''}`; return keywordSet.has(name) ? generateVarName(index + 1) : name; }; // 作用域解析器(简单实现嵌套作用域) class ScopeAnalyzer { constructor() { this.scopes = []; // 作用域栈 [当前作用域, 父作用域, ...] this.currentScope = new Map(); // 变量映射表: 原始名 -> 混淆名 this.varIndex = 0; } // 进入新作用域(如函数、类) enterScope() { this.scopes.push(this.currentScope); this.currentScope = new Map(); } // 退出当前作用域 exitScope() { this.currentScope = this.scopes.pop() || new Map(); } // 获取变量混淆名(同一作用域内同名变量复用) getMangledName(originalName) { if (this.currentScope.has(originalName)) { return this.currentScope.get(originalName); } // 检查所有父作用域,避免变量名冲突 let isConfict = false; for (const scope of this.scopes) { if (Array.from(scope.values()).includes(generateVarName(this.varIndex))) { isConfict = true; break; } } if (isConfict) { this.varIndex++; return this.getMangledName(originalName); } const mangled = generateVarName(this.varIndex++); this.currentScope.set(originalName, mangled); return mangled; } // 收集所有作用域的变量映射 getAllMappings() { return this.scopes.concat([this.currentScope]).reduce((acc, scope) => { scope.forEach((val, key) => acc.set(key, val)); return acc; }, new Map()); } } // 混淆器核心 const obfuscator = { // 处理字符串(支持转义字符和模板字符串) async processStrings(code) { const strRegex = /("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`)/g; const matches = []; let match; // 先收集所有匹配结果(避免替换时影响正则匹配) while ((match = strRegex.exec(code)) !== null) { matches.push({ full: match[0], content: match[0].slice(1, -1), quote: match[0][0], index: match.index }); } // 按索引倒序替换(避免索引偏移) matches.sort((a, b) => b.index - a.index).forEach(async (item) => { const encrypted = await cryptoUtil.encrypt(item.content); // 生成解密代码(包含密钥和方法) const decryptCode = `(async()=>{const p=${JSON.stringify(encrypted)};return await (${cryptoUtil.decrypt.toString()})(p)})()`; code = code.slice(0, item.index) + decryptCode + code.slice(item.index + item.full.length); }); return code; }, // 混淆标识符(变量、函数、类) mangleIdentifiers(code, config) { const analyzer = new ScopeAnalyzer(); const funcRegex = /function\s+(\w+)\s*\(/g; const classRegex = /class\s+(\w+)\s*/g; const varRegex = /(var|let|const)\s+([^=;]+)|([(,]\s*)(\w+)(?=\s*[),])/g; // 1. 处理函数名 if (config.mangleFuncs) { code = code.replace(funcRegex, (match, funcName) => { if (keywordSet.has(funcName)) return match; analyzer.enterScope(); // 函数进入新作用域 const mangled = analyzer.getMangledName(funcName); return `function ${mangled}(`; }); } // 2. 处理类名 if (config.mangleClasses) { code = code.replace(classRegex, (match, className) => { if (keywordSet.has(className)) return match; analyzer.enterScope(); // 类进入新作用域 const mangled = analyzer.getMangledName(className); return `class ${mangled} `; }); } // 3. 处理变量和参数 if (config.mangleVars) { code = code.replace(varRegex, (match, declType, declVars, prefix, arrowParam) => { if (declVars) { // 处理变量声明(var/let/const) return declVars.split(',').map(v => { const varName = v.trim().split('=')[0].trim(); if (!varName || keywordSet.has(varName)) return v; const mangled = analyzer.getMangledName(varName); return v.replace(varName, mangled); }).join(','); } else if (arrowParam) { // 处理箭头函数参数 const mangled = analyzer.getMangledName(arrowParam); return `${prefix}${mangled}`; } return match; }); } // 4. 退出所有作用域(简化处理) while (analyzer.scopes.length > 0) { analyzer.exitScope(); } // 5. 替换代码中所有标识符 const allMappings = analyzer.getAllMappings(); allMappings.forEach((mangled, original) => { // 避免替换关键字和对象属性 const identifierRegex = new RegExp(`\\b${original}\\b(?!\\.)`, 'g'); code = code.replace(identifierRegex, mangled); }); return code; }, // 控制流扁平化 flattenControlFlow(code) { if (!document.getElementById('flattenControl').checked) return code; // 简单的if语句转为switch return code.replace(/if\s*\((.*?)\)\s*\{/g, (match, condition) => { return `switch(+(${condition})){case 1:{`; }).replace(/}\s*else\s*\{/g, '}case 0:{'); }, // 主流程 async run(code) { try { updateProgress(10); const config = { mangleVars: document.getElementById('mangleVars').checked, mangleFuncs: document.getElementById('mangleFuncs').checked, mangleClasses: document.getElementById('mangleClasses').checked }; // 1. 处理字符串 let processed = await this.processStrings(code); updateProgress(40); // 2. 混淆标识符 processed = this.mangleIdentifiers(processed, config); updateProgress(70); // 3. 控制流扁平化 processed = this.flattenControlFlow(processed); updateProgress(100); return processed; } catch (e) { throw new Error(`混淆失败: ${e.message}`); } } }; // 解密器核心 const deobfuscator = { async run(code) { try { updateProgress(30); // 匹配加密 payload 并解密 const cryptoRegex = /\(async\(\)\=>\{const p=({.*?});return await \(\(.*?\)\)\(p\)\}\)\(\)/g; const matches = []; let match; while ((match = cryptoRegex.exec(code)) !== null) { matches.push({ full: match[0], payload: JSON.parse(match[1]), index: match.index }); } // 倒序替换解密结果 matches.sort((a, b) => b.index - a.index).forEach(async (item) => { const decrypted = await cryptoUtil.decrypt(item.payload); // 自动选择引号 const quote = decrypted.includes('"') ? "'" : '"'; code = code.slice(0, item.index) + `${quote}${decrypted.replace(new RegExp(quote, 'g'), `\\${quote}`)}${quote}` + code.slice(item.index + item.full.length); }); updateProgress(100); return code; } catch (e) { throw new Error(`解密失败: ${e.message}`); } } }; // 对外接口 async function handleObfuscate() { const input = document.getElementById('inputCode').value.trim(); if (!input) return showAlert('请输入要混淆的代码'); const obfBtn = document.getElementById('obfBtn'); obfBtn.disabled = true; try { const result = await obfuscator.run(input); document.getElementById('outputCode').value = result; showAlert('混淆成功', false); } catch (e) { showAlert(e.message); } finally { obfBtn.disabled = false; } } async function handleDeobfuscate() { const input = document.getElementById('inputCode').value.trim(); if (!input) return showAlert('请输入要解密的代码'); const deobfBtn = document.getElementById('deobfBtn'); deobfBtn.disabled = true; try { const result = await deobfuscator.run(input); document.getElementById('outputCode').value = result; showAlert('解密成功', false); } catch (e) { showAlert(e.message); } finally { deobfBtn.disabled = false; } } function copyResult() { const output = document.getElementById('outputCode'); if (!output.value) return showAlert('没有可复制的内容'); output.select(); document.execCommand('copy'); showAlert('复制成功', false); } </script> </body> </html>
11-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值