ast.js 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. const fs = require("fs");//文件读写
  2. const parse = require("@babel/parser"); //解析为ast
  3. const traverse = require('@babel/traverse').default;//遍历节点
  4. const t = require('@babel/types');//类型
  5. const generator = require('@babel/generator').default;//ast解析为代码
  6. //读取混淆js文件
  7. const jsCode = fs.readFileSync('./encode.js', {encoding: 'utf-8'});
  8. const visitor = {
  9. WhileStatement(path) { // 处理 While 循环语句
  10. const {test, body} = path.node; // 解构循环条件和循环体
  11. // 硬编码状态变量名和初始值(需后续从代码动态提取)
  12. let init_name = 'index'; // 状态变量名(示例值)
  13. let init_value = 0; // 初始状态值(示例值)
  14. const switch_body = body.body[0]; // 提取循环体内的第一个()语句
  15. // 验证是否为 Switch 语句,否则终止处理
  16. if (!t.isSwitchStatement(switch_body)) return;
  17. const {discriminant, cases} = switch_body; // 解构 Switch 的条件和分支列表
  18. // 验证 Switch 条件是否为指定状态变量
  19. if (!t.isIdentifier(discriminant, {name: init_name})) return;
  20. const ret_body = []; // 存储最终生成的代码块集合
  21. let end_flag = false; // 终止循环处理标志
  22. while (true) { // 循环处理所有状态分支
  23. if (end_flag) break; // 检测终止条件
  24. for (const each_case of cases) { // 遍历 Switch 的所有 case 分支
  25. const {test, consequent} = each_case;
  26. // 跳过非当前状态的 case 分支
  27. if (init_value !== test.value) continue;
  28. // 移除分支末尾的 continue 语句
  29. if (t.isContinueStatement(consequent[consequent.length - 1])) {
  30. consequent.pop();
  31. }
  32. // 处理状态变量更新逻辑
  33. if (t.isExpressionStatement(consequent[consequent.length - 1])) {
  34. const {expression} = consequent[consequent.length - 1];
  35. // 解析状态变量赋值表达式
  36. if (t.isAssignmentExpression(expression)) {
  37. const {left, right} = expression;
  38. // 更新状态变量值并移除赋值语句
  39. if (t.isIdentifier(left, {name: init_name})) {
  40. init_value = right.value;
  41. consequent.pop();
  42. }
  43. }
  44. }
  45. // 检测 return 语句作为终止信号
  46. if (t.isReturnStatement(consequent[consequent.length - 1])) {
  47. end_flag = true;
  48. }
  49. ret_body.push(...consequent); // 合并处理后的代码块
  50. break; // 退出当前分支处理循环
  51. }
  52. }
  53. path.replaceInline(ret_body); // 用线性代码替换原循环结构
  54. }
  55. };
  56. let ast = parse.parse(jsCode);//js转ast
  57. traverse(ast, visitor) // 处理控制流平坦化
  58. let {code} = generator(ast)
  59. console.log(code)