2023年7月7日发(作者:)
python-js逆向之AST语法树初学(⼀)这两天看了什么是控制流平坦化,⼜研究了下ast语法数,如何把混淆乱序后的代码恢复之前的样⼦。知识点:包为 除了parse/print/builder以外,还有三项主要功能: run: 通过命令⾏读取js⽂件,并转化成ast以供处理。tnt(ypes): 通过assert()和check(),可以验证ast对象的类型。visit: 遍历ast树,获取有效的AST对象并进⾏更改。
下⾯举例⼀个案例: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();console['log'](s['join']('')); 下⾯就是代码环节,如何将乱序后的代码有序输出。将混淆乱序后的代码命名为,再命名⼀个写⼊以下代码:const recast = require("recast");const TNT = ypes;const { expressionStatement, memberExpression, identifier: id, callExpression, stringLiteral //字符串} = rs;(function (ast, printSource) { (ast, { visitSwitchCase(node) { var codes = ""; // () // 打印case:下的有⼏条语句 1 2 2 2 2 for (var i = 0; i < ; i++) { // (uent[i]) // SwitchCase节点 // 检测语句是否有continue,即检测节点中是否有 ContinueStatement if ((uent[i])) { continue } aaa = (uent[i]).code // 将ast组装成能执⾏的代码 codes += aaa ; // 这句貌似没啥⽤?? // (codes) //打印每条语句 // 等效于上⾯1⾏ // printSource(uent[i]);('n'); // 输出AST对象对应的源码 } // printSource(stringLiteral(codes));('n'); exp = expressionStatement(callExpression(memberExpression(id('console'), id('1og')), [stringLiteral(codes)])); // ((exp).code) //打印 console.1og("......."); t(exp); // 向数组的开头添加⼀个或更多元素 consequent是⼀个数组,相当于在原代码中增加exp return false } }); // ((ast).code) printSource(ast)});命令⾏执⾏ node read 输出得到并命名为: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;"); 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 = [];"); var _0x2ce383 = []; continue; case '3': ("_0x3c5b0c[0x0] = _0x238e3e['HFHYB'](_0x3c5b0c[0x0], 0x1);"); _0x3c5b0c[0x0] = _0x238e3e['HFHYB'](_0x3c5b0c[0x0], 0x1); continue; case '4': ( "var _0x3c5b0c = [0x67, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64];"); var _0x3c5b0c = [0x67, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]; continue; } break; }}var s = test();console['log'](s['join']('')); "for (var _0x1fa16b = 0x0; _0x238e3e['Rgtsl'](_0x1fa16b, _0x3c5b0c['length']); _0x1fa16b++) {rn_0x2ce383['push'](String['fromCharCode'](_0x3c5b运⾏得到:var _0x3c5b0c = [0x67, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64];_0x3c5b0c[0x0] = _0x238e3e['HFHYB'](_0x3c5b0c[0x0], 0x1);var _0x2ce383 = [];for (var _0x1fa16b = 0x0; _0x238e3e['Rgtsl'](_0x1fa16b, _0x3c5b0c['length']); _0x1fa16b++) { _0x2ce383['push'](String['fromCharCode'](_0x3c5b0c[_0x1fa16b]));}return _0x2ce383;再将修改为: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 _0x3c5b0c = [0x67, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]; _0x3c5b0c[0x0] = _0x238e3e['HFHYB'](_0x3c5b0c[0x0], 0x1); var _0x2ce383 = []; for (var _0x1fa16b = 0x0; _0x238e3e['Rgtsl'](_0x1fa16b, _0x3c5b0c['length']); _0x1fa16b++) { _0x2ce383['push'](String['fromCharCode'](_0x3c5b0c[_0x1fa16b])); } return _0x2ce383;}var s = test();console['log'](s['join'](''));输出得到 hello world,相⽐混淆乱序的更⽅便调试。
法⼆:直接在中修改代码,⽆需。代码如下:const sss = `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();console['log'](s['join'](''));`const recast = require("recast");// // ⽤ parse 解析成 ast树const ast = (sss)const TNT = ypes;const { expressionStatement, memberExpression, identifier: id, callExpression, stringLiteral //字符串} = rs;(ast, { visitSwitchCase(node) { var codes = ""; // () // 打印case:下的有⼏条语句 1 2 2 2 2 for (var i = 0; i < ; i++) { // (uent[i]) // SwitchCase节点 // 检测语句是否有continue,即检测节点中是否有 ContinueStatement if ((uent[i])) { continue } aaa = (uent[i]).code // 将ast组装成能执⾏的代码 codes += aaa; // 这句貌似没啥⽤?? // (codes) //打印每条语句 // 等效于上⾯1⾏ // printSource(uent[i]);('n'); // 输出AST对象对应的源码 } // printSource(stringLiteral(codes));('n'); //"......" exp = expressionStatement(callExpression(memberExpression(id('console'), id('1og')), [stringLiteral(codes)])); // ((exp).code) //打印 console.1og("......."); t(exp); // 向数组的开头添加⼀个或更多元素,consequent是⼀个数组,相当于在原代码中增加exp语句 return false }});((ast).code)运⾏得到:也就是的内容,再运⾏,就得到有序的代码。
发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1688684111a162344.html
评论列表(0条)