基础练一练,不喜勿喷。
jscode对应visitor,jscode1对应visitor1,以此类推。
/*
* 安装 npm install @babel/core
* */// 将JS源码转换成语法树
const parser = require("@babel/parser");
// 为parser提供模板引擎
const template = require("@babel/template").default;
// 遍历AST
const traverse = require("@babel/traverse").default;
// 操作节点,比如判断节点类型,生成新的节点等
const t = require("@babel/types");
// 将语法树转换为源代码
const generator = require("@babel/generator").default;
// 操作文件
const fs = require("fs");///
/*
type: 表示当前路径的类型;
start:表示当前节点的起始位置;
end: 表示当前节点的结束位置;
loc: 表示当前节点所在源代码中的起始和结束的行号和列号。
declarations :声明
kind:表示定义的类型*/const visitor = {VariableDeclarator(path) {// 当前路径所对应的源代码,使用toString方法console.String());// a = 123 b = 'ccc'//获取path的上一级路径,使用parentPathlet parent = path.parentPath;console.de.kind) //var let//获取path的子路径,使用 get方法,得到id节点let id = ('id');console.de.name); //a b//获取当前路径的节点const node = de;console.log(node.init.value);//123 ccc//得到init节点let init = ('init');//判断node下的init节点类型if (t.isNumericLiteral(node.init)) {id.replaceWith(t.Identifier('A'));console.de.name); //placeWith(t.NumericLiteral(4));console.log(node.init.value);//4}//直接拿init节点来判断类型if (init.isStringLiteral()) {id.replaceWith(t.Identifier('B'));console.de.name); //placeWith({type: "StringLiteral", value: 'qqq'});console.de.value);//qqq// 删除init节点// ve()// de.init;}}
};
//替换path,单路径可以使用replaceWith方法,多路径则使用replaceWithMultiple方法
//placeWith 和 placeWith区别:前者只是替换当前遍历节点里的init节点,后者是把当前遍历节点整个替换const visitor1 = {CallExpression(path) {console.String()); //aaa(1, 2)const node = de;// 获取CallExpression节点结构// console.log(JSON.stringify(node,null,'t'));console.log(node.callee.name); //aaaconsole.log(node.arguments[0].value); //1console.log(node.arguments[1].value); //2let callee = ('callee');// console.String()); //aaaconsole.de.name) //aaa}
};const visitor2 = {'StringLiteral|NumericLiteral'(path) {// let value = de.value// //此行效果等于上行// // let {value} = de// console.log(value)//之所以会以十六进制显示,完全是 raw这个节点造成的,那就删除de.extra}
};
const visitor3 = {MemberExpression(path) {// const node = de;// let property = ('property')// if (t.isStringLiteral(node.property)) {// let value = node.property.value;// console.log(value)// //原为true,改后的效果把[]变为.// nodeputed = false// //如果写成placeWith是将整个MemberExpression节点换为value,节点类型也变为Identifier,例:window.btoa变为btoa// //我们仅需要替换property节点// placeWith(t.Identifier(value))// }//效果同上let property = ('property')if (property.isStringLiteral()) {let value = de.value;console.log(deputed = placeWith(t.Identifier(value))}}
};
const visitor4 = {VariableDeclaration(path) {const operator = '='; //赋值语句的运算符是 =const left = t.Identifier('b'); //新建赋值语句左边的节点;const right = t.NumericLiteral(456);//新建赋值语句右边的节点;const new_assign = t.AssignmentExpression(operator, left, right) //构造一个赋值语句节点const new_express = t.ExpressionStatement(new_assign); //再构造成表达式语句path.insertBefore(new_express);//在变量声明语句前面插入const new_vdtor = t.VariableDeclarator(left, right)const new_vdtion = t.VariableDeclaration('let', [new_vdtor])path.insertAfter(new_vdtion); //在变量声明语句后面插入var str = String()const new_memberexp = t.MemberExpression(t.Identifier('console'), t.Identifier('log'),)const new_callexp = t.CallExpression(new_memberexp, [t.StringLiteral(str)])path.insertAfter(new_callexp); //在变量声明语句后面插入path.stop() //不停止会无限循环下去}}
const visitor5 = {SwitchCase(path) {const node = de;let consequent = ('consequent');//数组类型//长度// console.log(consequent.length)for (var i = 0; i < consequent.length; i++) {if (t.isContinueStatement(consequent[i])) continueconst conqt = consequent[i].toString();const new_memberexp = t.MemberExpression(t.Identifier('console'), t.Identifier('log'),);const new_callexp = t.CallExpression(new_memberexp, [t.StringLiteral(conqt)]);consequent[i].insertBefore(new_callexp); //在变量声明语句后面插入// 可删除原来的节点// t.isReturnStatement(consequent[i]) ? consequent[i].node.argument = null : consequent[i].remove()consequent[i].stop(); //不停止会无限循环下去}//运行得到的代码得到混淆前的代码}}
const visitor6 = {NumericLiteral(path) {// const node = de;// const value = node.value//等效上2行const value = String()const first = 0 - Math.floor(Math.random() * 10000000 + 10000000);const second = value ^ first;const binexp = t.BinaryExpression('^', t.NumericLiteral(first), t.NumericLiteral(second))placeWith(binexp)path.stop()}
}const visitor7 = {//默认是enter,先遍历顶层,修改为exit,则是先遍历底层,看visitor7_1'BinaryExpression|UnaryExpression|ConditionalExpression'(path) {// const value = path.evaluate().value;const {value} = path.evaluate();// console.String(),' ',value)switch (typeof value) {case 'boolean':placeWith(t.BooleanLiteral(value))break;case 'string':placeWith(t.StringLiteral(value))break;case 'number':placeWith(t.NumericLiteral(value))break;default:break;}}}
// visitor7另一种写法
const visitor7_1 = function (path) {// const value = path.evaluate().value;const {value} = path.evaluate();console.String(), ' ', value)// switch (typeof value) {// case 'boolean':// placeWith(t.BooleanLiteral(value))// break;// case 'string':// placeWith(t.StringLiteral(value))// break;// case 'number':// placeWith(t.NumericLiteral(value))// break;// default:// break;// }
}
const visitor8 = {VariableDeclarator(path) {//此法为替换原init,console.String())const init = ('init') //a = 123 | 456const left = de.left.value //123const right = de.right.value //456//重新构造一个函数const p_left = t.Identifier('s'), p_right = t.Identifier('h') //设定2个形参const params = [p_left, p_right] //数组类型const retsta = [t.ReturnStatement(t.BinaryExpression('|', p_left, p_right))]//数组类型const body = t.BlockStatement(retsta,) //第二参数默认[]const callee = t.functionExpression(null, params, body,)const arguments = [t.NumericLiteral(left), t.NumericLiteral(right)] //数组类型const new_callexp = t.callExpression(callee, placeWith(new_callexp)// 还可以直接在原init上修改// const init = ('init') //a = 123 | 456// const left = de.left.value //123// const right = de.right.value //456//// const p_left = t.Identifier('s'), p_right = t.Identifier('h') //设定2个形参// const params = [p_left, p_right] //数组类型// const retsta = [t.ReturnStatement(t.BinaryExpression('|', p_left, p_right))]//数组类型// const body = t.BlockStatement(retsta,)// pe = "CallExpression";// de.arguments = [t.NumericLiteral(left), t.NumericLiteral(right)];// de.callee = t.functionExpression(null, params, body,)}
}
const visitor9 = {StringLiteral(path) {de.extra;// 发现英文的Unicode形式被还原了,但是中文的没有被还原// 需要给generator(ast,)添加参数{jsescOption:{"minimal":true}}}}
const visitor10 = {VariableDeclarator(path) {const init = ('init');if (init.isFunctionExpression()) {const {init, id} = de;const name = id.name;const params = init.params;if (params.length !== 2) return;let first_arg = params[0].name;let second_arg = params[1].name;const body = init.body;if (!body.body || body.body.length !== 1) return;let return_body = body.body[0];let argument = return_body.argument;if (!t.isReturnStatement(return_body) ||!t.isBinaryExpression(argument)) return;let {left, right, operator} = argument;if (!t.isIdentifier(left, {name: first_arg}) ||!t.isIdentifier(right, {name: second_arg})) return;let scope = path.scope;console.log(scope)traverse(scope.block, {CallExpression: function(_path){let _node = _de;let args = _node.arguments;if (args.length === 2 && t.isIdentifier(_node.callee, {name: name}))_placeWith(t.BinaryExpression(operator, args[0], args[1]))},});}}
};const visitor11 = {}
const visitor12 = {}var jscode = `var a = 123;let b='ccc';`
var jscode1 = `function aaa(a,b){}aaa(1,2);`
var jscode2 = `h[$b('x30x78x37x31', 'x31x21x58x47') + 'x4ax61'] = function (Q, R) {return Q + R;}var num = 0x30+0x31;var $a = ['x77x71x78x70x55x41x3dx3d']`
var jscode3 = `if (!j) {g['setCookie'](['*'], 'counter', 0x1);} else if (j) {i = g['getCookie'](null, 'counter');} else {g['removeCookie']();}(function (_0x1a61bd) {})()['constructor']("while (true) {}")["apply"]("counter");`
var jscode4 = `var a = 123;`
var jscode5 = `function test() {var _0x238e3e = {'puzUT': '4|3|2|1|0', 'Rgtsl': function (_0x3a9ad8, _0x312b1a) {return _0x3a9ad8 < _0x312b1a;}, 'HFHYB': function (_0x13ea88, _0x2533df) {return _0x13ea88 + _0x2533df;}};var _0x388255 = _0x238e3e['puzUT']['split']('|');var _0xfbda52 = 0x0;while (!![]) {switch (_0x388255[_0xfbda52++]) {case'0':return _0x2ce383;case'1':for (var _0x1fa16b = 0x0; _0x238e3e['Rgtsl'](_0x1fa16b, _0x3c5b0c['length']); _0x1fa16b++) {_0x2ce383['push'](String['fromCharCode'](_0x3c5b0c[_0x1fa16b]));}continue;case'2':var _0x2ce383 = [];continue;case'3':_0x3c5b0c[0x0] = _0x238e3e['HFHYB'](_0x3c5b0c[0x0], 0x1);continue;case'4':var _0x3c5b0c = [0x67, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64];continue;}break;}
}
var s = test();`
var jscode6 = `var value = 12345678;`
var jscode7 = `var a=!![],b='hello '+'world '+'!',c=2+3*50,d=Math.abs(-200)%19,e=true ? 123:456;`
var jscode8 = `var a = 123 | 456;`
var jscode9 = `var test ='u4f60u597du4e16u754cu0054u0068u0069u0073u0020u0069u0073u0020u0061u0020u0074u0065u0073u0074u0021'`
var jscode10 = `var Xor = function (p,q){return p ^ q;}let a = Xor(111,222);`
var jscode11 = ``
var jscode12 = ``let ast = parser.parse(jscode10); //修改此处
// console.log(JSON.stringify(ast,null,'t'))
// traverse(ast,visitor) //var a = 123;let b='ccc';
// traverse(ast,visitor1) //aaa(1,2);
// traverse(ast, visitor2) //将x30x78x37x31转变为可识别字符串,十六进制数值还原成十进制
// traverse(ast, visitor3) //将a["length"]转变为a.length
// traverse(ast, visitor4) //插入节点
// traverse(ast, visitor5) //SwitchCase插入节点,平坦化还原
// traverse(ast, visitor6) //把12345678拆成两个数的异或操作
// traverse(ast, visitor7) //合并Literal类型的计算表达式
// traverse(ast, { //visitor7 的另一种写法
// 'BinaryExpression|UnaryExpression|ConditionalExpression': {
// enter: [visitor7_1]
// //exit: [visitor7_1]
// }
// })
// traverse(ast, visitor8) //将 BinaryExpression 类型转换为 CallExpression 类型
// traverse(ast, visitor9) //将unicode码转为可识别的字符
traverse(ast, visitor10) //CallExpression -> BinaryExpression
// traverse(ast, visitor11)
// traverse(ast, visitor12)let {code} = generator(ast,); //第9需要添加参数{jsescOption:{"minimal":true}}
console.log(code)
// fs.writeFile('xxxx.js', code, (err)=>{});
本文发布于:2024-01-27 20:48:33,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17063597132548.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |