AST还原实战|某数早期版本while-if 转 while-switch 语句

举报
悦来客栈的老板 发表于 2022/01/19 00:03:13 2022/01/19
【摘要】 免责声明: 本篇文章仅作为学术研究和安全交流使用,切勿用于商业用途。如因违反规定产生任何法律纠纷,本人概不负责。如果本篇文章影响到官方利益,请添加文末的作者微信号告知,本人会在第一时间将文章删除。 一.需求 先看如下一段简单的代码: function func (_$eE) { var _$0n, _$2L, _$sC, ...

免责声明:

本篇文章仅作为学术研究和安全交流使用,切勿用于商业用途。如因违反规定产生任何法律纠纷,本人概不负责。如果本篇文章影响到官方利益,请添加文末的作者微信号告知,本人会在第一时间将文章删除。

一.需求

先看如下一段简单的代码:


   
  1. function func (_$eE) {
  2. var _$0n, _$2L, _$sC, _$o9, _$NU, _$qo, _$hK;
  3. var _$tg, _$DM, _$ZZ = 0, _$Ce = [7, 3, 4, 0, 9, 2, 8, 6, 1, 5];
  4. while (1) {
  5. _$DM = _$Ce[_$ZZ++];
  6. if (_$DM < 4) {
  7. if (_$DM < 1) {
  8. _$tg = !_$NU;
  9. } else if (_$DM < 2) {
  10. _$Uy(0);
  11. } else if (_$DM < 3) {
  12. _$NU = _$sC['$_ts'] = {};
  13. } else {
  14. _$sC = window, _$hK = String, _$o9 = Array;
  15. }
  16. } else if (_$DM < 8) {
  17. if (_$DM < 5) {
  18. _$NU = _$sC['$_ts'];
  19. } else if (_$DM < 6) {
  20. _$ZZ += -3;
  21. } else if (_$DM < 7) {
  22. return;
  23. } else {
  24. _$0n = [4, 16, 64, 256, 1024, 4096, 16384, 65536];
  25. }
  26. } else {
  27. if (_$DM < 9) {
  28. _$ZZ += 1;
  29. } else {
  30. if (!_$tg) _$ZZ += 1;
  31. }
  32. }
  33. }
  34. }

现在有这么一个需求,需要把 代码中的while - if 语句 还原成 while - switch语句,再通过 上面的分发器彻底还原。

彻底还原先放一边,我们来看看如何将 while - if 语句 还原成 while - switch 语句

二.分析

俗话说,工欲善其事,必先利其器。 分析代码是还原过程中很重要的一环,只有分析透彻了,你才有思路去进行还原。

  1. 这是一个while + if 语句结构,由 _$Ce 这个数组来控制每一步走向哪个分支。_$Ce的元素 由 0 - 9组成,没有负值。

  2. 考虑下面的代码段:

    
         
    1. if (_$DM < 1) 
    2. {
    3. _$tg = !_$NU;
    4. }

    因为变量 _$DM 取自数组 _$Ce 。因此它不可能为负数,所以上面的代码等价于:

    
         
    1. if (_$DM == 0)
    2. {
    3. _$tg = !_$NU;
    4. }
  3. 同理下面这段代码:

    
         
    1. else if (_$DM < 2)
    2. {
    3. _$Uy(0);
    4. }

    这里 _$DM < 2 ,符合条件的只有 _$DM = 0 和 _$DM = 1,而又因为上面 _$DM 的值已经是 0 了,所以只有当_$DM = 1时,才会走这个if分支,即:

    
         
    1. else if (_$DM == 1)
    2. {
    3. _$Uy(0);
    4. }
  4. 依葫芦画瓢,所有的if分支都可以改成这种形式:

    
         
    1. if (_$DM == xxx)
    2. {
    3.   somecode...
    4. }
  5. 根据上面的思路,这段代码还原后,应该是这样的:

    
         
    1. function func(_$eE) {
    2. var _$0n, _$2L, _$sC, _$o9, _$NU, _$qo, _$hK;
    3. var _$tg,
    4. _$DM,
    5. _$ZZ = 0,
    6. _$Ce = [7, 3, 4, 0, 9, 2, 8, 6, 1, 5];
    7. while (1) {
    8. switch (_$Ce[_$ZZ++]) {
    9. case 0:
    10. _$tg = !_$NU;
    11. break;
    12. case 1:
    13. _$Uy(0);
    14. break;
    15. case 2:
    16. _$NU = _$sC['$_ts'] = {};
    17. break;
    18. case 3:
    19. _$sC = window, _$hK = String, _$o9 = Array;
    20. break;
    21. case 4:
    22. _$NU = _$sC['$_ts'];
    23. break;
    24. case 5:
    25. _$ZZ += -3;
    26. break;
    27. case 6:
    28. return;
    29. case 7:
    30. _$0n = [4, 16, 64, 256, 1024, 4096, 16384, 65536];
    31. break;
    32. case 8:
    33. _$ZZ += 1;
    34. break;
    35. case 9:
    36. if (!_$tg) _$ZZ += 1;
    37. break;
    38. }
    39. }
    40. }

三.思路

也许你会有疑问:这么简单的代码,直接手动处理不就完事了吗,还费劲的去写什么还原代码。我想说的是,对于这么几行,确实手动更省事,而成千上万行的混淆代码,手动去还原是非常不现实的,特别考验细心和耐心。

还原思路:

  1. 处理if语句,直接遍历最外层的if语句,在解析网站上可以看到,其父节点的父节点的类型为 WhileStatement 语句。

    
         
    1. const if2Switch =
    2. {
    3. IfStatement(path)
    4. {
    5. let {node,parentPath} = path;
    6. if (!parentPath.parentPath.isWhileStatement()) return; //定位到最外层的if语句
    7. ...
    8. },
    9. }
  2. 获取前一条语句节点,用其right节点构造siwtch的discriminant节点。

  3. 定义一个数组,用来保存每个if语句下面会真正执行的语句。

  4. 遍历这个path里面的 if语句,将符合条件的代码放在数组里。

  5. 遍历完成后,生成 switch节点,并进行替换即可。

完整代码我会放在星球里,仅供大家参考学习,需要的可自取。

三.结语

整个还原还是非常的容易,基本没啥需要注意的地方。整了个AST的交流群,有需要进群的可以加我微信,感谢阅读!

7097d47546939eab49ce829b75b863ef.png   

文章来源: blog.csdn.net,作者:悦来客栈的老板,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq523176585/article/details/122552030

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。