ie下提示SCRIPT1028: 缺少标识符、字符串或数字

<script>      

 var a = { 

           x: 1,

           y: 2,       

 };       

 </script>

 

如果在ie的兼容性视图,或者ie6 ie7下会报告下面的错误:

SCRIPT1028: 缺少标识符、字符串或数字 

ie下测试,按F12, 文档模式切换下就能看到效果

在旧版ie下json最后一项是不允许有逗号的,为了更好的兼容各个浏览器,json最后的逗号最好不加

 var a={

       x:1,

       y:2

}

 

<!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、付费专栏及课程。

余额充值