初试js反混淆

news2024/12/25 23:54:15

一、目标

最近js玩的花样越来越多了,本来简洁方便的一门开发语言,现在混淆的一塌糊涂。今天我们就介绍几种常见的反混淆方案。

混淆的本质就是等价替换,把 a = 12 ,替换成 a = 100 - 8 + 5 - 15 - 70。 把 “push” 替换成 “\u0070\u0075\u0073\u0068”, 基本上就让你调试起来很难受了。

反混淆就是一个逆过程,上古时期用的是最简单的正则匹配,然后再替换。现在时代进步了,我们有了一个更强大的工具 抽象语法树 (Abstract Syntax Tree),简称 AST ,它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。这样可以更方便的实现对源代码的处理。

二、步骤

先搭个架子

最近比较喜欢用JetBrains全家桶,先用WebStorm创建一个Node js项目,然后在工程目录下面执行


npm install @babel/core --save-dev

来安装js的@babel库,用于将JS源码转换成语法树AST

Tip:

我这边执行的时候,卡了半天,一直没反应,我第一个反应就是给他换个国内镜像


# 更换成淘宝镜像

npm config set registry https://registry.npmmirror.com

# 查看当前镜像

npm config get registry

结果不好使,问下了谷哥,哥说,可能是使用了代理,被乱七八糟的代理影响了npm,可以尝试禁用代理:


npm config delete proxy

npm config delete https-proxy

哥是对的,现在好使了

Show me the code


var parser = require("@babel/parser"); // 将JS源码转换成语法树AST

var template = require("@babel/template").default; // 为parser提供模板引擎

var traverse = require("@babel/traverse").default; // 遍历AST树节点操作

var types = require("@babel/types"); // 操作节点,比如判断节点类型,生成新的节点等

var generator = require("@babel/generator").default; // 将语法树AST转换为js代码

  


var fsrw = require("fs"); // 文件读取

  


var jscode = fsrw.readFileSync("./input/demo2.js", {encoding: "utf-8"}); // 读取原始混淆文件

var ast_parse = parser.parse(jscode); //将JS源码转换成语法树AST

  
  


// 做处理

var traverses_2 = {

......

}

  


console.log(" traverses 处理 \\u00 ======== ");

traverse(ast_parse, traverses_2)

  


// 生成还原后的js文件

var ast_js_code = generator(ast_parse);

fsrw.writeFileSync('./output/demo2_out.js', ast_js_code.code)

这就是一个基础的AST反混淆处理框架。

先把待处理的文件读取出来,转成语法树AST,然后针对性的做处理,最后生成还原后的js文件

Demo1 \uxxx 转换

第一个例子是


var e = "\u002e\u0068\u006f\u006c\u0064\u0065\u0072";

...

它把字符串做了一次unicode编码,我们还原的时候只需要做个正则匹配,把 ‘\uxxx’ 的字符串的extra 属性移除,就会重新解析成正常的字符串了


var traverses_2 = {

// B. 处理Unicode字符串,针对"\u0068\u0065\u006c\u006c" 》》'hell'

StringLiteral(path) {

cur_node = path.node;

if (cur_node.extra && /\\[ux]/gi.test(cur_node.extra.raw)) {

cur_node.extra = undefined;

}

},

}

得到的结果就是


var e = ".holder"

Demo2 a = 100 - 8 + 5 - 15 - 70 表达式替换


var a = 100 - 8 + 5 - 15 - 70;

var b = 1;

console.log(a+b);

这个js就有点小复杂了,我们需要一个分析工具 https://astexplorer.net/

在这里插入图片描述

1:ast1

从这个解析里面看一看出,a的值是一个二元表达式(BinaryExpression) 套着一个二元表达式,我们需要把每个二元表达式的结果计算出来,然后一层一层往上吐结果,这不就是妥妥的递归嘛。


function evaluateBinaryExpression(path) {

let left = path.node.left ;

let right = path.node.right;

let operator = path.node.operator;

  


console.log(left);

console.log(right);

console.log(operator);

  


// 递归处理左、右两边

if (types.isBinaryExpression(left)) {

left = evaluateBinaryExpression(path.get('left'));

}

if (types.isBinaryExpression(right)) {

right = evaluateBinaryExpression(path.get('right'));

}

  


console.log(" =================== ");

console.log(left);

console.log(right);

  


// 如果左右两边都是数字类型,计算结果并替换

if (( isNumericLiteral(left)|| types.isUnaryExpression(left) ) && (isNumericLiteral(right) || types.isUnaryExpression(right) ) ) {

try {

const leftValue = getNodeValue(left);

const rightValue = getNodeValue(right);

const evalResult = eval(`${leftValue} ${operator} ${rightValue}`);

  


console.log( `${leftValue} ${operator} ${rightValue}` + " = " + evalResult);

// if(evalResult >=0)

path.replaceWith(types.numericLiteral(evalResult));

return path.node;

// else

// path.replaceWith(types.unaryExpression('-', types.numericLiteral(Math.abs(evalResult))));

} catch (e) {

console.log("Failed to evaluate numeric expression:", e);

}

}

  


// 如果左右两边都是字符串类型,拼接结果并替换

else if (isStringLiteral(left) && isStringLiteral(right) && operator === "+") {

const leftValue = getNodeValue(left);

const rightValue = getNodeValue(right);

const evalResult = leftValue + rightValue;

path.replaceWith(types.stringLiteral(evalResult));

return path.node;

}

  


return null;

}

  
  


var traverses_3= {

BinaryExpression(path) {

evaluateBinaryExpression(path); // 递归处理

}

}

跑一下,搞定


var a = 12;

var b = 1;

console.log(a + b);

三、总结

js反混淆基本上就是一次模版批量替换的套路,以前我们仅仅依赖查找替换,然后高级一点就是正则替换,现在有了AST解析,就更加灵活了。后面咱们在继续介绍一些高阶的用法。

在这里插入图片描述

1:ffshow

角弓玉剑,桃花马上春衫,犹忆少年侠气

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于微信小程序的乡村研学游平台设计与实现,LW+源码+讲解

摘 要 信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自…

odoo17 前端 在头像下拉 dropdown 自定义菜单

odoo17 前端 在头像下拉 dropdown 自定义菜单 其实很简单, 我们先找到原来已经创建好的, 找到代码位置 使用 我的资料 为例 odoo-17.0\addons\hr\static\src\user_menu\my_profile.js /** odoo-module **/import { _t } from "web/core/l10n/translation"; import …

【解决】Layout 下创建槽位后,执行 Image 同步槽位位置后表现错误的问题。

开发平台:Unity 6.0 编程语言:CSharp 编程平台:Visual Studio 2022   一、问题背景 | 开发库存系统 图1 位置同步失败问题 图2 位置正常同步效果表现 黑框 作用于 UnityEngine.UI.GridLayoutGruop,形成 4x6 布局,如…

2023年MathorCup数学建模B题城市轨道交通列车时刻表优化问题解题全过程文档加程序

2023年第十三届MathorCup高校数学建模挑战赛 B题 城市轨道交通列车时刻表优化问题 原题再现: 列车时刻表优化问题是轨道交通领域行车组织方式的经典问题之一。列车时刻表规定了列车在每个车站的到达和出发(或通过)时刻,其在实际…

07-案例-图书管理

欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…

vue 依赖注入(Provide、Inject )和混入(mixins)

Prop 逐级透传问题​ 通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props。想象一下这样的结构:有一些多层级嵌套的组件,形成了一棵巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。…

九州未来再度入选2024边缘计算TOP100

随着数智化转型的浪潮不断高涨,边缘计算作为推动各行业智能化升级的重要基石,正在成为支持万物智能化的关键点。近日,德本咨询(DBC)联合《互联网周刊》(CIW)与中国社会科学院信息化研究中心(CIS),共同发布《2024边缘计算TOP100》榜…

git相关知识

前言:在学习git之前首先需要了解几个概念:工作区,暂存区,版本库。 工作区:是电脑上写代码或者文件的目录。 暂存区:一般存放在.git目录下的index中,也称索引。(git add&#xff09…

应用程序部署(IIS的相关使用,sql server的相关使用)

数据服务程序(API)部署 1、修改配置文件 打开部署包中的web.config配置文件,确认数据库登录名和密码正确 修改ip为电脑IP(winR输入cmd,输入ipconfig,IPv4对应的就是本机IP) 2、打开IIS&#x…

conda和conda的常用命令

目录 一、什么是conda 1. conda的定义和作用 2. conda的特点 3. conda与pip的区别 二、conda的常用命令 1. 环境管理 2.包管理 3. 查看信息 4. 清理和维护 5. 频道(channel)管理 6. 导出和复制环境 7. 加速相关(镜像) 一、什么是conda 1. conda的定义和作用 2. co…

mysql每日一题(上升的温度,date数据的计算)

日期之间的运算 日期类型的加法运算 data_add(now_data,interval 1 month) select date_add(now(), interval 1 day); -- 加1天 select date_add(now(), interval 1 hour); -- 加1小时 select date_add(now(), interval 1 minute); -- 加1分钟 select date_add(now(), inter…

kafka生产经验——消费者事务

如果想完成Consumer端的精准一次性消费,那么需要Kafka消费端将消费过程和提交offset 过程做原子绑定。此时我们需要将Kafka的offset保存到支持事务的自定义介质(比 如MySQL)。这部分知识会在后续项目部分涉及。 事务的四大特征:AC…

2024 年 Apifox 和 Postman 对比介绍详细版

Apifox VS Postman ,当下流行的的两款 API 开发工具,2024 版对比!

Rust @绑定(Rust@绑定)(在模式匹配的同时将值绑定到变量)

文章目录 Rust中的绑定基础概念示例:基本模式匹配 绑定的使用示例:范围匹配并绑定变量 深入探索绑定的好处示例:复杂数据结构中的应用 总结 附加 Rust中的绑定 Rust 语言以其强类型系统和内存安全的特性著称。在进行模式匹配时,R…

可靠UDP协议(KCP)使用说明

希望这篇文章&#xff0c;对学习和使用 KCP 协议的读者&#xff0c;有帮助。 1. KCPUDP 流程图 2. 示例代码&#xff08;待补充&#xff09; #include <iostream>int main() {// TODO: kcp examplereturn 0; }

《Python网络安全项目实战》项目4 编写网络扫描程序

《Python网络安全项目实战》项目4 编写网络扫描程序 项目4 编写网络扫描程序任务4.1 扫描内网有效IP地址任务描述任务分析任务实施任务拓展 任务4.2 编写端口扫描工具任务描述任务分析任务实施相关知识任务评价任务拓展项目评价 项目4 编写网络扫描程序 许多扫描工具是由Pytho…

CSS:导航栏三角箭头

用CSS实现导航流程图的样式。可根据自己的需求进行修改&#xff0c;代码精略的写了一下。 注&#xff1a;场景一和场景二在分辨率比较低的情况下会有一个1px的缝隙不太优雅&#xff0c;自行处理。有个方法是直接在每个外面包一个DIV&#xff0c;用动态样式设置底色。 场景一、…

【Python系列】浅析流式模式:基于 SSE 的实时响应体验

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Python3.11.9+selenium,选择证书用多线程+键盘enter解决

Python3.11.9+selenium,选择证书用多线程+键盘enter解决 1、遇到问题:弹出证书选择,无法点击确定 import pyautogui pyautogui.press(enter) 键盘enter也无法点击 2、解决办法:用多线程解决同时执行click链接和Enter点击证书的确定 1、点击操作 # # 通过文本链接文本…

前端开发快速进行 Mock 数据的方法

前端开发快速进行 Mock 数据的方法 在前端开发中&#xff0c;模拟数据&#xff08;Mock Data&#xff09;是不可或缺的一部分&#xff0c;它可以帮助开发者在没有后端接口的情况下快速推进项目进度。然而&#xff0c;在使用如 Mock.js 这样的工具时&#xff0c;开发者可能会遇…