AST入门与实战(三):if节点转switch节点(瑞数5)

原文地址:https://zhuoyue360.com/jsnx/110.html

1. 期望

这是一个瑞数5代解混淆的案例,我们本章节需要做的是把if节点的内容转换成switch-case内容.以此来熟悉AST对JS混淆的对抗.

原始代码:

function whileState() {
  while (1) {
    aV = cA[wU++];

    if (aV < 4) {
      if (aV < 1) {
        zT = window, kD = String, bO = Array, xX = document, nZ = Date;
      } else if (aV < 2) {
        iG = zT['ab'] = {};
      } else if (aV < 3) {
        iG = zT['ab'];
      } else {
        mM = !iG;
      }
    } else {
      if (aV < 5) {
        xT(0);
      } else if (aV < 6) {
        if (!mM) wU += 1;
      } else if (aV < 7) {
        lG = [4, 16, 64, 256, 1024, 4096, 16384, 65536];
      } else {
        return;
      }
    }
  }
}

期望代码:

function whileState() {
  while (1) {
    switch (cA[wU++]) {
      case 0:
        zT = window, kD = String, bO = Array, xX = document, nZ = Date;
        break;
      case 1:
        iG = zT['ab'] = {};
        break;
      case 2:
        iG = zT['ab'];
        break;
      case 3:
        mM = !iG;
        break;
      case 4:
        xT(0);
        break;
      case 5:
        if (!mM) wU += 1;
        break;
      case 6:
        lG = [4, 16, 64, 256, 1024, 4096, 16384, 65536];
        break;
      case 7:
        return;
        break;
    }
  }
}

2. 思路分析

首先,我们需要明确一点,aV 的索引是从0开始的,它是不可能为负数的.

那么也就可以有如下的转换:

if (aV < 1) {
	zT = window, kD = String, bO = Array, xX = document, nZ = Date;
}

转换成

if (aV == 0) {
	zT = window, kD = String, bO = Array, xX = document, nZ = Date;
}

这是蔡老板所说的夹逼原理 ,奈何文化低,我不懂.知道有这么一个回事就行.

思路如下(更加详细的看代码注释):

  1. while循环的参数是NumericLiteral ,且内容为1.
  2. body中只有2个节点
  3. 提取出aV
  4. 找到WhileStatement
  5. 枚举WhileStatement下的IfStatement节点.
  6. leftname应该为我们提取出的aV
  7. operator<
  8. right类型不能为IfStatement, 因为它有嵌套.
  9. 记录下了所有符合条件的body
  10. 生成switch 节点

image-20230811172025893

3. 代码

function collectSwitchCase(whilePath,name){
    // 菜老板知识星球获得.
    let ifNodes = [];

    // 遍历WhilePath
    whilePath.traverse({
        "IfStatement"(path)
        {
            //遍历所有的ifStatement;
            let {test,consequent,alternate} = path.node; //获取子节点
            let {left,operator,right} = test; // 必定是BinaryExpression

            if (!types.isIdentifier(left,{name:name}) || operator != '<' || !types.isNumericLiteral(right)) 
            {//条件过滤
                return;
            }

            let value = right.value;

            //保存整个body,记得生成switchCase节点的时候加上break节点。
            ifNodes[right.value-1] = consequent.body;   
            if (!types.isIfStatement(alternate))
            {
                ifNodes[right.value] = alternate.body;  //最后一个else,其实就是上一个else-if 的 test.right的值
            }	

        }
    })
    return ifNodes;


}


const if2switchReplace = {
    WhileStatement(path){
		let {test,body} = path.node;
        // `while`循环的参数是`NumericLiteral` ,且内容为`1`.  body中只有2个节点
        if(!types.isNumericLiteral(test,{value:1}) || body.body.length != 2){
            return
        }

        // 判断while循环格式, 条件过滤
        let blockBody = body.body;
        if (!types.isExpressionStatement(blockBody[0]) || !types.isIfStatement(blockBody[1]))
		{
			return;
		}
        // left 左边的节点就是我们需要的变量名
		let {left,right} = blockBody[0].expression; //或者左右节点       aV = cA[wU++];
        let name = left.name;
        
        // 获取到了变量名称后, 就需要收集使用了aV的case
		let ifNodes = collectSwitchCase(path,name);   //收集case

        //无case,直接返回。
		if (ifNodes.length == 0) return;   

        let len = ifNodes.length;
        for (let i=0; i < len; i++)
		{
             //每一个case最后都加break
			ifNodes[i].push(types.BreakStatement()); 
			ifNodes[i] = types.SwitchCase(test = types.valueToNode(i),consequent = ifNodes[i]);  //生成SwitchCase节点
		}

        //生成SwitchCase节点
        let switchNode = types.SwitchStatement(right,ifNodes);   
        path.node.body.body = [switchNode]; //最后的while节点只有一个Switch Node;


    }   
}

traverse(ast, if2switchReplace);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/69995.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端笔试题1

HTML/CSS 题1&#xff1a; 1&#xff0e;使用CSS 让该节点不可见&#xff0c;方法越多越好。 <div class"hidden">Hi</div> 使用CSS 让节点不可见的方法有以下几种&#xff1a; 把 visibility 属性设置为 hidden&#xff0c;这样元素框不会被绘制&…

nodejs+vue+elementui学生档案信息管理系统_06bg9

利用计算机网络的便利&#xff0c;开发一套基于nodejs的大学生信息管理系统&#xff0c;将会给人们的生活带来更多的便利&#xff0c;而且在经济效益上&#xff0c;也会有很大的便利!这可以节省大量的时间和金钱。学生信息管理系统是学校不可缺少的一个环节&#xff0c;其内容直…

公司自建机房IDC还是选择云服务器?以腾讯云为例

大企业是选择自购服务器自建机房还是使用腾讯云服务器&#xff1f;都说企业上云是趋势&#xff0c;自建机房是一次性支出&#xff0c;上云租赁云服务器等产品需要年年续费&#xff0c;大型企业有必要把数据中心迁移上云吗&#xff1f;腾讯云服务器网想说&#xff0c;自建机房购…

面试八股文Mysql:(2)数据库调优

1. SQL优化很有必要 数据库优化在提升系统性能是很重要的一个方面&#xff0c;不管是MySQL还是MongoDB还是其它的数据库。 SQL优化在提升系统性能中是成本最低 && 优化效果最明显的途径&#xff0c;可以让吞吐量更大&#xff0c;响应速度更快。如果你的团队在SQL优化这…

安防监控视频汇聚平台EasyCVR分发的FLV视频流在VLC中无法播放是什么原因?

众所周知&#xff0c;TSINGSEE青犀视频汇聚平台EasyCVR可支持多协议方式接入&#xff0c;包括主流标准协议国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。在视频流的处理与分发上&#xff0c;视频监控…

集合数据类型

非数字型 列表[]&#xff08;其他语言叫数组&#xff09; 注意点&#xff1a;第一个成员的索引编号为0&#xff0c;不能访问不存在的索引编号 # list是列表变量名&#xff0c;列表中有三个成员 list[刘备,曹操,关羽] print(list[0]) print(list[1]) print(list[2]) print(li…

XXLJOB 怎么用

目录 1、数据库执行sql语句&#xff0c;建立表 2、配置Admin &#xff0c;连接xxl_job数据库 3、启动admin&#xff0c;访问 http://localhost:8080/xxl-job-admin 4、需要定时任务的微服务里导入依赖 5、配置yml&#xff08;admin地址&#xff0c;执行器名字 端口&#x…

湘大 XTU OJ 1260 Completed String 题解(非常详细):建立数组下标和数组元素之间的映射关系 ~scanf

一、链接 1260 Completed String 二、题目 题目描述 给一个字符串&#xff0c;请判断字符串是否出现了所有的英文字母&#xff08;不区分大小写&#xff09;。 输入 每行一个只含英文字母的字符串&#xff0c;长度不超过1000。 输出 每行输出一个样例的结果&#xff0c…

Vue.js2+Cesium1.103.0 七、Primitive 绘制航线元素

Vue.js2Cesium1.103.0 七、Primitive 绘制航线元素 用 Primitive 绘制航线元素&#xff0c;包括航点图标&#xff0c;航线线段&#xff0c;线段距离标注&#xff0c;航点序号&#xff0c;海拔标注&#xff0c;总航程等信息。 可同时绘制多条航线&#xff1b;可根据 id 清除指…

基于Vue+wangeditor实现富文本编辑

目录 前言分析实现具体解决的问题有具体代码实现如下效果图总结前言 一个网站需要富文本编辑器功能的原因有很多,以下是一些常见的原因: 方便用户编辑内容:富文本编辑器提供了类似于Office Word的编辑功能,使得那些不太懂HTML的用户也能够方便地编辑网站内容。提高用户体验…

【C++】虚继承(virtual base classes)

【C】虚继承&#xff08;virtual base classes) 文章目录 【C】虚继承&#xff08;virtual base classes)1. 使用原因2. 解决方法3. 例题练习 1. 使用原因 在多重继承(Multiple Inheritance) 的情况下&#xff0c;尤其是菱形继承时&#xff0c;容易出现问题&#xff0c;关于菱…

SpringSecurity 详解(通俗易懂)

SpringSecurity 详解 1、SpringSecurity讲解1.1、SpringSecurity完整流程1.2、认证流程 2、登录&#xff0c;退出&#xff0c;注册_分析说明2.1、登录2.2、校验2.3、退出2.4、注册2.5、SecurityContextHolder说明 3、代码实现3.1、引入依赖3.2、登录 退出 注册3.2.1、SpringSec…

Xcode 基座打包

Xcode基座打包-APP更新版本内容无效 问题&#xff1a;解决&#xff1a; 问题&#xff1a; 使用xcode基座打包之后&#xff0c;上传到appstore进行提审发布。 用户在appstore商城进行更新下载&#xff0c;打开更新后的APP发现版本号是最新的&#xff0c;APP里面的其他内容还是上…

HTML5基础

1、HTML5概述 2014年10月28日&#xff0c;W3C&#xff08;world wide web consortium&#xff0c;万维网联盟&#xff09;的HTML工作组发布了HTML5的正式推荐标准。HTML5作为构建开放Web平台的核心&#xff0c;增加了支持Web应用的许多新特性&#xff0c;以及更符合开发者使用…

Arcgis地图实战二:地图实时轨迹展示

1.最终效果预览 2.定时器执行方法 进入页面执行执行器 this.locationInterval setInterval(() > {this.getCurrentPosition();}, this.conf.LocateInterval);离开页面销毁 clearInterval(this.locationInterval);this.conf.LocateInterval为获取的数据同步中的定时器间隔…

你的服务器安全吗?--服务器防渗透

1、概述 在本人所处的公司的服务器正式遭到黑客攻击之前&#xff0c;一直都以为 黑客 是个遥不可及的词&#xff0c;直到真正成为了受害者时&#xff0c;才猛然意识到安全的重要性。有一些基本经验和心得总结出来&#xff0c;和同行分享一下吧。 2、暴破手段 最粗暴的黑客行为…

C++ 多态性——虚函数

虚函数是动态绑定的基础。虚函数必须是非静态的成员函数。虚函数经过派生之后&#xff0c;在类族中就可以实现运行过程的多态。 根据类型兼容规则&#xff0c;可以使用派生类的对象代替基类的对象。如果基类类型的指针指向派生类对象&#xff0c;就可以通过这个指针来访问该对…

用ChatGPT和六顶帽思考法帮助自己更好地决策和解决问题

当我们在解决复杂问题时&#xff0c;我们常常陷入单一视角的状态。创造性思维领域的先驱爱德华德博诺&#xff0c;提出了六顶帽思考法[1]&#xff0c;这意味着我们可以从六个不同的视角来思考一个问题&#xff0c;以实现高水平决策和解决问题。 每一顶“帽子”代表不同的视角。…

【写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串】

写一个函数&#xff0c;判断一个字符串是否为另外一个字符串旋转之后的字符串 1.题目 写一个函数&#xff0c;判断一个字符串是否为另外一个字符串旋转之后的字符串。 例如&#xff1a;给定s1 AABCD和s2 BCDAA&#xff0c;返回1 给定s1abcd和s2ACBD&#xff0c;返回0. AABCD左…

当前服务器版本不支持该功能,请联系经销商升级服务器 - - 达梦数据库报错

当前服务器版本不支持该功能&#xff0c;请联系经销商升级服务器 - - 达梦数据库报错 环境介绍1 搭建测试环境2 报错内容3 标准版介绍 环境介绍 某项目使用标准版数据库中&#xff0c;使用insert into 正常操作表&#xff0c;插入数据时报错&#xff0c;表为普通表。 1 搭建测…