来聊聊AST中exit和enter的区别

本文讲述了作者在学习蔡老板的AST课程中遇到的例题,涉及对混淆后的JavaScript代码进行解析,主要关注MemberExpression的使用以及如何在AST遍历中应用Enter方法,通过修改代码逻辑解决返回节点过滤问题。
摘要由CSDN通过智能技术生成

最近也是入手了蔡老板的AST课程 跟着蔡老板一步一步学 下面是学习的例题(笔记)做完了趁着不困梳理一下

31ad2550158a4297938b0d4d2741b3e8.png

function _u() {

  var n = r(v(980, 817));

  return (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = (n = n["replace"](/px_width/g, qu))["replace"](/px_cnt_width/g, hu))["replace"](/px_height/g, Iu))["replace"](/px_background/g, su))["replace"](/pxcntId/g, Uc))["replace"](/pxcId/g, Mc))["replace"](/pxdc/g, Bc))["replace"](/pxcd/g, Hc))["replace"](/pxcac/g, Ec))["replace"](/pxifc/g, Rc))["replace"](/pxbbwof/g, Uu))["replace"](/pxba/g, Zc))["replace"](/pxtc/g, jc))["replace"](/px_bar_height/g, wu))["replace"](/pxtId/g, bc))["replace"](/pxbtnwarpper/g, xc))["replace"](/px_border_width/g, tu))["replace"](/px_border_color/g, vu))["replace"](/px_border_radius/g, cu))["replace"](/px_fill_color/g, uu))["replace"](/px_text_color/g, iu))["replace"](/px_text_size/g, fu))["replace"](/px_text_font/g, ou))["replace"](/px_inner_height/g, eu))["replace"](/px_target_color/g, Cu))["replace"](/px_font_weight/g, zu))["replace"](/px_btn_padding/g, Lu))["replace"](/px_pressable_area_padding/g, ku))["replace"](/px_pressable_area_width/g, lu))["replace"](/px_pressable_area_top/g, du))["replace"](/px_text_transform/g, yu))["replace"](/px_checkmark_thickness/g, Du))["replace"](/px_checkmark_height/g, au))["replace"](/px_checkmark_width/g, Au))["replace"](/px_acc_text/g, Wc))["replace"](/px_acc_email_input/g, Tc))["replace"](/px_acc_value_box/g, Yc))["replace"](/px_acc_value_hyphen/g, Nc))["replace"](/px_acc_step_two_continue_btn/g, Jc))["replace"](/px_value_box_container/g, pc))["replace"](/px_acc_img/g, _c))["replace"](/px_acc_tooltip/g, Fc))["replace"](/pxvisuallyhidden/g, ru);

}

 

混淆后的代码

 

先用exit方法  exit方法:在退出某个节点时执行的操作。当 AST 遍历器完成访问该节点及其子节点后,会调用该节点类型对应的 exit 方法。  也就是从最后往前遍历

 

32b8bddec64b486783cec49b7a716efa.png

最里面的replace节点以及父节点

let {parentPath, node} = path;  

            if (!parentPath.isMemberExpression()){

                return;

            }

判断一下最里面那一层的节点是不是MemberExpression  不是返回

0397343ae52848c2ae6c72d9a3542dde.png

左节点类型

0a12de12a7c641ffb1040f64b3b27b8d.png

右节点类型

 let {left, operator, right} = node;

            if (!types.isIdentifier(left) || !types.isCallExpression(right) || operator != "=")

            {  

                return;

            }

判断一下左右节点类型还有中间操作符是否为= 如果不是 返回

 

e2d5a75564724d31b7e63002a811ce3a.png

return类型

let returnPath = path.findParent(p => p.isReturnStatement());  //获取祖先节点(return)

            if (!returnPath){

                return;

            }

判断一下是不是ReturnStatement  如果不是返回

 

上边三个判断用来去除无用的代码

然后遍历即可

function _u() {

  var n = r(v(980, 817));

  n = n["replace"](/px_width/g, qu);

  n = n["replace"](/px_cnt_width/g, hu);

  n = n["replace"](/px_height/g, Iu);

  n = n["replace"](/px_background/g, su);

  n = n["replace"](/pxcntId/g, Uc);

  n = n["replace"](/pxcId/g, Mc);

  n = n["replace"](/pxdc/g, Bc);

  n = n["replace"](/pxcd/g, Hc);

  n = n["replace"](/pxcac/g, Ec);

  n = n["replace"](/pxifc/g, Rc);

  n = n["replace"](/pxbbwof/g, Uu);

  n = n["replace"](/pxba/g, Zc);

  n = n["replace"](/pxtc/g, jc);

  n = n["replace"](/px_bar_height/g, wu);

  n = n["replace"](/pxtId/g, bc);

  n = n["replace"](/pxbtnwarpper/g, xc);

  n = n["replace"](/px_border_width/g, tu);

  n = n["replace"](/px_border_color/g, vu);

  n = n["replace"](/px_border_radius/g, cu);

  n = n["replace"](/px_fill_color/g, uu);

  n = n["replace"](/px_text_color/g, iu);

  n = n["replace"](/px_text_size/g, fu);

  n = n["replace"](/px_text_font/g, ou);

  n = n["replace"](/px_inner_height/g, eu);

  n = n["replace"](/px_target_color/g, Cu);

  n = n["replace"](/px_font_weight/g, zu);

  n = n["replace"](/px_btn_padding/g, Lu);

  n = n["replace"](/px_pressable_area_padding/g, ku);

  n = n["replace"](/px_pressable_area_width/g, lu);

  n = n["replace"](/px_pressable_area_top/g, du);

  n = n["replace"](/px_text_transform/g, yu);

  n = n["replace"](/px_checkmark_thickness/g, Du);

  n = n["replace"](/px_checkmark_height/g, au);

  n = n["replace"](/px_checkmark_width/g, Au);

  n = n["replace"](/px_acc_text/g, Wc);

  n = n["replace"](/px_acc_email_input/g, Tc);

  n = n["replace"](/px_acc_value_box/g, Yc);

  n = n["replace"](/px_acc_value_hyphen/g, Nc);

  n = n["replace"](/px_acc_step_two_continue_btn/g, Jc);

  n = n["replace"](/px_value_box_container/g, pc);

  n = n["replace"](/px_acc_img/g, _c);

  n = n["replace"](/px_acc_tooltip/g, Fc);

  return n["replace"](/pxvisuallyhidden/g, ru);

}

解完混淆代码效果

 

enter类型:在进入某个节点时执行的操作。当 AST 遍历器首次访问该节点时,会调用该节点类型对应的 enter 方法。也就是从最开始往后遍历

8c1ba80d75114736b0e51b67305eacb7.png

改为enter类型试一下

b76d02e51b9147718e0ed871826d14b5.png

结果是这样 显然出现了错误 原因是他是从开始往后遍历 改变了祖先节点的类型 可以看到祖先节点类型从被上边的代码过滤掉 return掉了。

第一次循环

d670899dabfb4f429ebef5d94f2c73bc.png

第二次循环:

b66e01a6250e4008ba508e31c759d0b8.png

然后我们把祖先节点判断那改一下即可,这里要说一下isStatement包含isReturnStatement,isStatement包含很多函数自己查吧。893c5a135110481da9aad4bc3cb6680a.png

最后效果是一样的。

7e7ecc73dad04247badb8e3eea7a2072.png

 

 

 

 

  • 15
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值