本文介绍了JavaScript中隐藏eval关键字的多种方法,从简单的字符串拼接和Function构造函数,到使用字符编码动态生成字符串。更复杂的方案包括通过JS混淆工具(如JShaman)将代码转换为难以辨识的格式,甚至模拟虚拟机执行字节码来重构eval。这些技术通过层层包装,使原始eval调用在代码审计中难以被发现。
JavaScript中隐藏eval关键字的技巧
某些情况下,我们在进行JS编程时,可能想要用eval执行一些特殊的代码,但想不想让他人轻易看出是使用了eval。那么,就得想办法隐藏eval关键字了。
简单的隐藏方法
ini
// 方法1:使用字符串分割
const ev = "ev";
const al = "al";
const hiddenEval = window[ev + al];
// 使用
hiddenEval('console.log("隐藏的eval执行")');
// 方法2:通过Function构造函数
const executeCode = new Function('code', 'return eval(code)');
executeCode('2 + 2'); // 返回4
复杂的隐藏方法
ini
// 使用字符编码
const encodedEval = () => {
const chars = [101, 118, 97, 108];
const str = String.fromCharCode(...chars);
return window[str];
};
const myEval = encodedEval();
更更更复杂的隐藏方法
如果还想隐藏的更深,可以再用JShaman进行JS代码混淆加密,上面代码会变成:
ini
const encodedEval = () => {
const _0x35ea38 = {
"\u006d\u004f\u0067\u006c\u0048": function (_0x55d02e, _0x5cdb2b) {
return _0x55d02e ^ _0x5cdb2b;
},
"\u0076\u006a\u0048\u0044\u0073": function (_0x4c98c3, _0xa2b4f0) {
return _0x4c98c3 ^ _0xa2b4f0;
}
};
const _0x2cd5ff = [0x47a4d ^ 0x47a28, _0x35ea38["\u006d\u004f\u0067\u006c\u0048"](0xd8290, 0xd82e6), _0x35ea38['vjHDs'](0xb9759, 0xb9738), _0x35ea38["\u0076\u006a\u0048\u0044\u0073"](0x7b450, 0x7b43c)];
const _0x3d45d7 = String['fromCharCode'](..._0x2cd5ff);
return window[_0x3d45d7];
};
const myEval = encodedEval();
或:
ini
function _0x927a(opcode) {
var op = {
push: 32,
add: 33,
sub: 34,
mul: 35,
div: 36,
pop: 37,
xor: 38
};
var stack = [];
var ip = -1;
var sp = -1;
while (ip < opcode.length) {
ip++;
switch (opcode[ip]) {
case op.push:
{
ip++;
stack.push(opcode[ip]);
sp++;
break;
}
case op.add:
{
stack.push(stack[sp - 1] + stack[sp]);
sp++;
break;
}
case op.sub:
{
stack.push(stack[sp - 1] - stack[sp]);
sp++;
break;
}
case op.mul:
{
stack.push(stack[sp - 1] * stack[sp]);
sp++;
break;
}
case op.div:
{
stack.push(stack[sp - 1] / stack[sp]);
sp++;
break;
}
case op.xor:
{
stack.push(stack[sp - 1] ^ stack[sp]);
sp++;
break;
}
case op.pop:
{
return stack[sp];
}
}
}
}
const encodedEval = () => {
const chars = [_0x927a([32, 865932, 32, 866025, 38, 37]), _0x927a([32, 625917, 32, 625803, 38, 37]), _0x927a([32, 750963, 32, 750866, 38, 37]), _0x927a([32, 753540, 32, 753640, 38, 37])];
const str = String['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65'](...chars);
return window[str];
};
const myEval = encodedEval();
怎么样,还能找到eval关键字吗?