AST使用(二)

    //在此之前,先了解下path和node
    /*
    path指的是路径  其常用的方法
    当前路径所对应的源代码 : path.toString
    判断path是什么type,使用path.isXXX 这个方法  : if(path.isStringLiteral()){}
    获取path的上一级路径 : let parent = path.parentPath;
    获取path的子路径 : path.get('test');
    删除path : path.remove()
    替换path(一个节点) : path.replaceWith({type:"NumericLiteral",value:3});
    替换path(多个节点) : path.replaceWithMultiple([{type:"NumericLiteral",value:3}]);
    插入path : path.insertAfter({type:"NumericLiteral",value:3}); 
    
    node指的是节点  是path的一个属性 可以通过path.node来获取node  本质是一个json结果的数据
    获取原码 :
        const generator = require("@babel/generator").default;
        let {code} = generator(node);
    删除节点 : path.node.init = undefined;
    访问子节点的值(init节点的value属性) : console.log(path.node.init.value);
    节点的类型判断 : 先引入types  if(types.isBlockStatement(path.node)){}

    path和node关系: node是path的一个属性
    举例: path.node.test === path.get("test").node  结果是True
     */

1.表达式还原

 js文件内容:

const a = !![]
const b = "abc" == "dsa";
const c = (1 << 2) | 2;
const d = parseInt("5" + "0")

还原代码:

import { parse } from "@babel/parser";
import traverse from "@babel/traverse";
import generate from "@babel/generator";
import * as types from "@babel/types";
import fs from "fs";
const code = fs.readFileSync("code/表达式还原.js","utf-8");
let ast = parse(code);
traverse(ast,{
    //下面对应的是一元表达式、二元表达式、条件表达式、调用表达式
    "UnaryExpression|BinaryExpression|ConditionalExpression|CallExpression" : (
        path
    ) => {
        //执行path对应的语句,并将结果中的value属性赋值给value变量,将confident属性赋值给confident变量
        //confident 是可信度  value是计算结果
        const { confident , value } = path.evaluate();
        //如果表达式计算的结果是正负无穷大,则return不做任何处理
        if (value == Infinity || value == -Infinity)return
        if (confident){
            //如果结果可信,将结果转换为节点替换当前节点
            path.replaceWith(types.valueToNode(value));
        }
    }
});
const{ code: output } = generate(ast);
console.log(output)

2.字符串还原

const strings = ["\x68\x65\x6c\x6c\x6f","\x77\x6f\x72\x6c\x64"]

将这段js代码解混淆如下,可以看出如果我们将raw的值变为正常,那么还原ast的时候就能的得到想要的代码

还原过程: 

import { parse } from "@babel/parser";
import traverse from "@babel/traverse";
import generate from "@babel/generator";
import * as types from "@babel/types";
import fs from "fs";
const code = fs.readFileSync("code/表达式还原.js","utf-8");
let ast = parse(code);
traverse(ast,{
    //此处的{ node } 写法就等价于 { node } = path  等价于 node = path.node
    StringLiteral({ node }){
        //    /正则内容/gi.test(要匹配的字符串)    这个写法是JS中正则的写法,返回值是布尔值  详情可见https://www.runoob.com/jsref/jsref-obj-regexp.html
        if (node.extra && /\\[ux]/gi.test(node.extra.raw)){
            node.extra.raw = node.extra.rawValue;
        }
    },
});
const{ code: output } = generate(ast);
console.log(output)

3.无用代码剔除(僵尸代码)

如下代码,第一个条件结果永远是true,第二个条件结果永远是false,所以可以通过判断IfStatement节点下的test节点的计算结果,来显示代码,其中if 下的条件对应的是consequent,else内的代码对应的是alternate

const _0x16c18d = function(){
    if(!![[]]){
        console.log("hello,world")
    }else{
        console.log("1111")
        console.log("2222")
        console.log("3333")
        console.log("4444")
    }
};
const _0x1f7292 = function (){
    if ("dhsanhdu7dsa8".charAt(4) !== String.fromCharCode(110)){
        console.log("this")
        console.log("is")
        console.log("dead")
        console.log("code")
    }else {
        console.log("nice to meet you")
    }
};
_0x16c18d();
_0x1f7292();
import { parse } from "@babel/parser";
import traverse from "@babel/traverse";
import generate from "@babel/generator";
import * as types from "@babel/types";
import fs from "fs";
const code = fs.readFileSync("code/表达式还原.js","utf-8");
let ast = parse(code);
traverse(ast,{
    IfStatement(path){
        let result = path.get("test").evaluateTruthy(); //计算test路径下代码的结果是否为真  返回布尔值
        let consequent = path.get("consequent")
        let alternate = path.get("alternate")
        if (result === true){
            if (consequent.isBlockStatement()){
                path.replaceWith(consequent.node)
            }
        }else if(result === false){
            if (alternate.isBlockStatement()){
                path.replaceWith(alternate.node)
            }
        }else{
            path.remove()
        }
    }
});
const{ code: output } = generate(ast);
console.log(output)

4.反控制流平坦化

原代码:

const s = "3|1|2".split("|");
let x = 0;
while (true){
    switch (s[x++]){
        case "1":
            const a = 1;
            continue;
        case "2":
            const b = 3;
            continue;
        case "3":
            const c = 0;
            continue;
    }
    break;
}
import { parse } from "@babel/parser";
import traverse from "@babel/traverse";
import generate from "@babel/generator";
import * as types from "@babel/types";
import fs from "fs";
const code = fs.readFileSync("code/表达式还原.js","utf-8");
let ast = parse(code);
traverse(ast,{

    //反控制流平坦化
    WhileStatement(path){
      const { node,scope } = path;
      const { test,body } = node;
      let switchNode = body.body[0];
      let { discriminant,cases } = switchNode;
      let { object,property } = discriminant;
      let arrName = object.name;
      let binding = scope.getBinding(arrName);
      let { init } = binding.path.node;

      object = init.callee.object;
      property = init.callee.property;
      let argument = init.arguments[0].value;
      let arrayFlow = object.value[property.name](argument);

        // console.log(object.value[property.name])
        // console.log(argument)
        // console.log(arrayFlow)
      let resultBody = [];
      arrayFlow.forEach((index)=> {
          let switchCase = cases.filter((c) => c.test.value == index)[0];
          let caseBody = switchCase.consequent;
          if (types.isContinueStatement(caseBody[caseBody.length - 1])) {
              caseBody.pop();
          }
          resultBody = resultBody.concat(caseBody);
      });
      path.replaceWithMultiple(resultBody);
    },

});
const{ code: output } = generate(ast);
console.log(output)

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

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

相关文章

ARM基础(3):MPU内存保护单元详解及例子

MPU(Memory Protection Unit)是ARM处理器中的一个特性&#xff0c;它提供了内存保护和访问控制的功能&#xff0c;通常用于实现操作系统的内存隔离和保护。比如我们可以设置所有的RAM为不可执行&#xff0c;这样就可以避免代码注入攻击。最近做项目过程中&#xff0c;使用的几个…

中空百叶玻璃隔断怎么组装

以下是中空百叶玻璃隔断的组装步骤&#xff1a; 1. 准备材料&#xff1a;中空百叶玻璃、接头、U型槽、挂件、固定螺钉等。 2. 根据实际需要&#xff0c;将中空百叶玻璃按照尺寸进行切割。 3. 在地面上铺上一张软垫&#xff0c;将切好的玻璃放置在垫子上&#xff0c;然后在两侧标…

管理类联考——逻辑——真题篇——阅读新题型真题

阅读新题型真题 Part B-2010- Part B Directions: Read the following text and decide whether each of the statements is true or false. Choose T if the statement is true or F if the statement is not true. Mark your answers on ANSWER SHEET. (10 points) Copying…

之江实验室: 如何基于 JuiceFS 为超异构算力集群构建存储层 ?

今天&#xff0c;高性能计算结合人工智能技术正在推动科研创新。例如通过破解水稻基因密码推动作物育种从“试验选优”向“计算选优”发展&#xff0c;在医药领域快速分析分子与蛋白之间的相互作用&#xff0c;发现潜在的能够有效干预疾病发生的药物分子。 之江实验室就是上述科…

大学生实习周记总结

大学生实习周记总结1 经过两个月的实习&#xff0c;我收获了很多&#xff0c;也懂得了许多&#xff0c;同时也成熟了不少。下面我将把我两个月的实习生活分成五个部分进行总结&#xff1a;教学经验、班主任工作、做事态度、学生友谊、感恩的心。 教学经验&#xff1a;如何上好一…

4.4网络模型 4.5协议 4.6网络通信的过程

4.4网络模型 OSI七层参考模型 七层模型&#xff0c;亦称 OSI&#xff08;Open System Interconnection&#xff09;参考模型&#xff0c;即开放式系统互联。参考模型是国际标准化组织&#xff08;ISO&#xff09;制定的一个用于计算机或通信系统间互联的标准体系&#xff0c;…

【三维视觉】空间点集的最小包围盒计算

0 问题描述 假设有一个空间点集&#xff0c;不重合的点数有N个。 N1时&#xff0c;最小包围盒是一个点&#xff1a;中心为其本身&#xff0c;半径无穷小 N2时&#xff0c;最小包围盒是一个圆&#xff1a;中心为连线中点&#xff0c;半径为边长一半 N3时&#xff0c;不共线的三…

番茄工作法图解——简单易行的时间管理方法

ISBN: 978-7-115-24669-1 作者&#xff1a;【瑞典】诺特伯格&#xff08;Staffan Noteberg&#xff09; 页数&#xff1a;136页 阅读时间&#xff1a;2023-06-10 推荐指数&#xff1a;★★★★★ 番茄工作法&#xff08;意大利语&#xff1a;Pomodoro Technique&#xff09;是一…

如何选择到最合适的DDoS缓解服务?

DDoS缓解服务提供商的数量可能很多&#xff0c;但只有一些提供商提供高效服务的所有必要功能&#xff0c;因此如果要选择正确的 DDoS保护解决方案&#xff0c;必须考虑以下因素&#xff1a; 1.缩小风险范围 选择DDoS缓解服务的第一步&#xff0c;确定您组织的特定需求&#…

使用SQL语句创建存储过程

前言: 本篇文章是记录学校学习SQL server中知识,可用于复习资料. 目录 前言:一、存储过程的创建1、创建简单存储过程2、创建带参数的存储过程3、创建带输出参数的存储过程 二 、使用T一SQL语句管理和维护存储过程2.1 使用sp_helptext查看存储过程student_sc的定义脚本2.2 使用…

AI 绘画(1):生成一个图片的标准流程

文章目录 文章回顾感谢人员生成一个图片的标准流程前期准备&#xff0c;以文生图为例去C站下载你需要的绘画模型导入参数导入生成结果&#xff1f;可能是BUG事后处理 图生图如何高度贴合原图火柴人转角色 涂鸦局部重绘 Ai绘画公约 文章回顾 AI 绘画&#xff08;0&#xff09;&…

在Django项目中的各个应用中分别编写路由配置文件urls.py

目录 01-通过命令建立三个应用02-配置路由 /index/、/app1/index/、/app2/index/02-1-配置路由 /index/ 并将各个应用的urls.py文件包含进主路由目录中02-02-配置路由/app1/index/02-03-配置路由/app2/index/ 03-编写各个应用的视图views.py 文件04-注册模板文件所在目录05 创建…

一文吃透低代码平台的衍生历程、优势及未来趋势

一、低代码概念 低代码开发平台是一种无需编码或者只需要少量代码即可快速生成应用程序的开发平台&#xff0c;通过可视化进行应用程序开发的方法&#xff0c;让不同经验水平的开发人员可以通过图形化的用户界面&#xff0c;使用拖拽组件和模型驱动的逻辑来创建网页和移动应用程…

【统计模型】缺失数据处理方法

目录 一、缺失数据定义 二、缺失数据原因 三、缺失数据处理步骤 四、数据缺失机制 1.完全随机缺失&#xff08;MCAR&#xff09; 2.随机缺失&#xff08;MAR&#xff09; 3.非随机、不可忽略缺失&#xff08;NMAR&#xff09; 五、缺失数据处理方法 1.直接删除 2.缺失值…

从零开始理解Linux中断架构(2)-朴素的中断管理设计理念

既然是从零开始,我们先从最为简单的中断逻辑处理架构开始,这个逻辑结构跟CPU架构没有关系,纯逻辑上的。纯逻辑是跨越系统和应用的,不管对于应用程序员还是系统程序员,逻辑推导是基本的工具,设计原型是基本的出发点。 中断发起的时候,PC指针被设置为中断向量表中相对应的…

SpringBoot 中使用 JWT 案例分享详解

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

Qt6.5.1+WebRTC学习笔记(十二)环境搭建流媒体服务器(ubuntu22.04+SRS)

前言 若只是实现一对一通信&#xff0c;仅使用webrtc就足够了。但有时间需要进行多个人的直播会议&#xff0c;当人比较多时&#xff0c;建议使用一个流媒体服务器&#xff0c;笔者使用的是SRS。 这个开源项目资料比较全&#xff0c;笔者仅在此记录下搭建过程 一、准备 1.操…

这些方法可以手写扫描识别

小伙伴们知道有一项技术是可以将我们手写的东西识别出来吗&#xff1f;这一项创新的技术就是手写识别功能&#xff0c;它能够将手写内容快速转换为数字或文本格式&#xff0c;并提高信息处理和管理的效率。而且相比传统的手工记录方式&#xff0c;手写识别功能具有较高的准确性…

多行文本溢出显示省略号

1.css 实现单行省略 .ellipsis{white-space: nowrap;text-overflow: ellipsis; overflow: hidden;}2.在WebKit浏览器或移动端&#xff08;绝大部分是WebKit内核的浏览器&#xff09;的页面&#xff0c;直接使用WebKit的CSS扩展属性(WebKit是私有属性)-webkit-line-clamp 。 -w…

openEuler 开源汇智赢未来|2023开放原子全球开源峰会OpenAtom openEuler 论坛成功召开

6 月 12 日&#xff0c;2023 开放原子全球开源峰会 OpenAtom openEuler 分论坛在北京成功召开。分论坛以“openEuler 汇众智&#xff0c;奔涌向前赢未来”为主题&#xff0c;展示了 openEuler 社区的最新成果&#xff0c;阐述了 openEuler 开源开放的发展模式&#xff0c;介绍了…