前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >初试js反混淆

初试js反混淆

原创
作者头像
奋飞安全
修改于 2024-11-14 13:38:16
修改于 2024-11-14 13:38:16
44900
代码可运行
举报
文章被收录于专栏:奋飞安全奋飞安全
运行总次数:0
代码可运行

一、目标

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

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

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

二、步骤

先搭个架子

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm install @babel/core --save-dev

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

Tip:

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 更换成淘宝镜像
npm config set registry https://registry.npmmirror.com
# 查看当前镜像
npm config get registry

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm config delete proxy
npm config delete https-proxy

哥是对的,现在好使了

Show me the code

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 转换

第一个例子是

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var e = "\u002e\u0068\u006f\u006c\u0064\u0065\u0072";
...

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;
        }
    },
}

得到的结果就是

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var e = ".holder"

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var a = 100 - 8 + 5 - 15 - 70;
var b = 1;
console.log(a+b);

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

1:ast1

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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); // 递归处理
    }
}

跑一下,搞定

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var a = 12;
var b = 1;
console.log(a + b);

三、总结

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

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

Tip:

: 本文的目的只有一个就是学习更多的逆向技巧和思路,如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担,和本文以及作者没关系,本文涉及到的代码项目可以去 奋飞的朋友们 知识星球自取,欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: fenfei331 讨论下。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
ceph 运维操作-OSD
OSD全称Object Storage Device,也就是负责响应客户端请求返回具体数据的进程。一个Ceph集群一般都有很多个OSD。
Lucien168
2020/07/20
1.8K0
SUSE Ceph 增加节点、减少节点、 删除OSD磁盘等操作 – Storage6
之前我们已快速部署好一套Ceph集群(3节点),现要测试在现有集群中在线方式增加节点
星哥玩云
2022/07/28
1.5K0
SUSE Ceph 增加节点、减少节点、 删除OSD磁盘等操作 – Storage6
ceph 运维常用命令总结
    cluster be1756f2-54f7-4d8f-8790-820c82721f17
DevinGeng
2019/04/09
5.7K0
外包技能--Ceph(L版)手动剔除osd与增加osd
Godev
2023/08/02
8560
Ceph CRUSH Map简介
CRUSH是ceph的核心设计之一,CRUSH算法通过简单计算就能确定数据的存储位置。因此ceph客户端无需经过传统查表的方式来获取数据的索引,进而根据索引来读写数据,只需通过crush算法计算后直接和对应的OSD交互进行数据读写。这样,ceph就避免了查表这种传统中心化架构存在的单点故障、性能瓶颈以及不易扩展的缺陷。
Xkrroeon
2022/09/07
1.9K0
Ceph: 关于Ceph 中创建和管理自定义 CRUSH Map的一些笔记整理
对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》
山河已无恙
2023/11/13
9420
Ceph: 关于Ceph 中创建和管理自定义 CRUSH Map的一些笔记整理
ceph分布式存储-管理crushmap
CRUSH 算法通过计算数据存储位置来确定如何存储和检索。 CRUSH 授权 Ceph 客户端直接连接 OSD ,而非通过一个中央服务器或代理。数据存储、检索算法的使用,使 Ceph 避免了单点故障、性能瓶颈、和伸缩的物理限制。
Lucien168
2020/07/20
1K0
ceph luminous 新功能之磁盘智能分组
本篇是luminous一个新功能介绍,关于磁盘智能分组的,这个在ceph里面叫crush class,这个我自己起名叫磁盘智能分组,因为这个实现的功能就是根据磁盘类型进行属性关联,然后进行分类,减少了很多的人为操作
用户2772802
2018/08/06
9870
ceph 运维操作-CRUSH MAP
CRUSH 算法通过计算数据存储位置来确定如何存储和检索。 CRUSH 授权 Ceph 客户端直接连接 OSD , 而非通过一个中央服务器或代理。数据存储、检索算法的使用,使 Ceph 避免了单点故障、性能瓶颈、和伸缩的物理限制。
Lucien168
2020/07/20
1.6K0
ceph 指定OSD创建pool
在我们的ceph集群中,可能不只有sata盘或者ssd盘,有些时候服务器上同时插了ssd和sata盘用作osd,那如果我们按照默认的crush分布规则,那会使所有pg均分在ssd和sata盘上,造成sata盘的存储空间浪费和整个ceph集群的性能浪费,其实我们可以改变ceph的默认存储规则,来使那些io要求较高的数据存储在由ssd的osd组成的存储池上,将备份数据或者时效性要求不高的数据存储在由sata的osd组成的存储池上,既提高了性能,又可以减少较大数据量存储的成本。
没有故事的陈师傅
2022/12/06
8480
ceph 指定OSD创建pool
Ceph集群常用命令参考
如果一个OSD处于up状态,那么它可以是在集群内,也可以是在集群外,如果之前的状态为 up 且 in,现在变成 up out了,那么ceph会把PG迁移到其他的OSD上。如果某个OSD的变成out了,则crush就不会再分配PG给它,如果状态为down,那么它的状态就会为out,默认在OSD down掉300s后标记它为out状态
dogfei
2020/07/31
9800
ceph osd full故障 原
资料(传送门)[http://bbs.ceph.org.cn/question/363]
domain0
2018/08/02
1.6K0
proxmox集群节点崩溃处理
在现有集群加入一个物理节点,接着再此节点创建ceph监视器、创建OSD。从宿主机系统执行ceph osd tree查看状态,创建起来的几个OSD状态都正常(up),从proxmox管理界面看也是这样。
全栈程序员站长
2022/06/29
1.5K0
proxmox集群节点崩溃处理
OpenStack 系列之Cinder multi backend
补充内容: 1.修改 crushmap 有两种方式:在线修改和离线修改 2.为了保险起见一般都是采用离线修改,也就是导出来修改 3.导出默认的 crushmap,这个是二进制文件打不开 ceph osd getcrushmap -o {compiled-crushmap-filename} 4.将刚才的二进制文件转换成可视化的文本文件 crushtool -d {compiled-crushmap-filename} -o {decompiled-crushmap-filename} 5.转换成可视化的文本文件之后,建议不要把默认的二进制文件删掉避免修改 crushmap 造成 ceph 集群瘫痪,这样我们还留了一个备份 6.修改 crushmap,也就是下面讲述的 crushmap 详解,根据实际情况修改 7.将刚才修改的可视化文本文件转换成二进制文件 crushtool -c {decompiled-crush-map-filename} -o {compiled-crush-map-filename} 8.设置 OSD 的 crushmap,也就是把刚才转换的二进制文件让他生效 ceph osd setcrushmap -i {compiled-crushmap-filename} 9.创建 ssd 和 sata 两个 pool ceph osd pool create ssd 128 ceph osd pool create sata 128 10.创建完 ssd 和 sata 两个 pool 之后更新下 cinder 密钥的权限 ceph auth caps client.cinder mon 'allow r'  osd 'allow class-read object_prefix rbd_children, allow rwx pool=volumes, allow rx pool=p_w_picpaths, allow rwx pool=ssd, allow rwx pool=sata'
DevinGeng
2019/04/09
8740
OpenStack 系列之Cinder multi backend
如何在单节点 Ceph 中配置多数据副本
在服务器资源不足,或者测试环境下,Ceph 通常只有一个节点,就算有多个服务器组成集群,往往存储服务器也往往只有一台,Ceph 的默认配置下,只能设置单数据备份,也就是说数据只存了一份,如果磁盘坏了,数据就丢了。虽然测试环境数据没那么重要,总保不齐就会有关键数据放在上面,所以还是要想办法在资源有限的条件下实现数据的高可用,另外这也是一个很好的进一步理解 Ceph 概念的好机会,接下来就让我们来看看是如何实现的吧。
用户2443625
2018/08/23
3K0
如何在单节点 Ceph 中配置多数据副本
由OSD class配置引发的PG异常状态修复
ceph版本12.2.8,一个PG卡在remapped状态,但是集群状态是OK的,为了修复这个remapped状态,才有了下面的操作。
用户1260683
2018/10/25
3.4K0
掉电后osdmap丢失无法启动osd的解决方案
本篇讲述的是一个比较极端的故障的恢复场景,在整个集群全部服务器突然掉电的时候,osd里面的osdmap可能会出现没刷到磁盘上的情况,这个时候osdmap的最新版本为空或者为没有这个文件
用户2772802
2018/08/06
1.2K0
Ceph 故障排查笔记 | 万字经验总结
删除当前 osd 的所有数据,并且重新加载 osd,此操作一定要保证有冗余可用的 osd,否则会造成整个 osd 数据损坏。
米开朗基杨
2021/05/11
8K0
Ceph 集群整体迁移方案
场景介绍:在我们的IDC中,存在着运行了3-6年的Ceph集群的服务器,这些服务器性能和容量等都已经无法满足当前业务的需求,在购入一批高性能机器后,希望将旧机器上的集群整体迁移到新机器上,当然,是保证业务不中断的前提下,再将旧机器下架回收。本文就介绍了一种实现业务不中断的数据迁移方案,并已经在多个生产环境执行。 本文的环境均为:Openstack+Ceph 运行虚拟机的场景,即主要使用RBD,不包含RGW,MDS。虚机的系统盘(Nova),云硬盘(Cinder),镜像盘(Glance)的块均保存在共享存储C
腾讯云TStack
2018/04/02
4.1K0
ceph运维常用指令
[root@node1 ~]# ceph-deploy purgedata node1
IT运维技术圈
2022/06/26
1.8K0
相关推荐
ceph 运维操作-OSD
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验