当前位置: 首页 > news >正文

AST入门与反混淆初体验

文章目录

    • 1.什么是AST?
    • 2. AST反混淆的目的
    • 3. babel库安装
    • 4. 直观的理解AST
    • 5.如何用AST解混淆?思路是什么?
    • 6. babel库的学习
    • 7. AST反混淆初体验-常量折叠

1.什么是AST?

​ 在计算机科学中,抽象语法树(Abstract Syntax Tree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。

​ 它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。

​ 之所以说语法是“抽象”的,是因为这里的语法并不会表示出真实语法中出现的每个细节。(摘自百度百科)

2. AST反混淆的目的

我们想这样:

1 + 2   ==> 3

AST反混淆的目的:让代码变得更简单,其逻辑不变,可读性增强。

用库的话,需要去了解它的api,调用它,它帮我们进行裁剪。 babel 库,相当于剪刀,胶水等工具

具体在哪里进行裁剪,需要自己去分析。
比如:

"Hello," + "AST!";    ===>   "Hello,AST!"; 
function br() {function r(r, n) {return Ur(n - 491, r)}var n = t, v = document[n(r(616, 610))](n(r(591, 604)));v && (v[n("OiIKRksPEDQr")] += n("eSMEUVktXCoiAlFdbB4sOg"))}

==>

function br() {var v = document["querySelector"]("div.px-captcha-container");v && (v["className"] += " modal-slide-out");}

目的:想要分析更简单的代码。

3. babel库安装

环境搭建参考:

node环境,及AST环境搭建(基于windows10)

在Node.js下,有关AST的库很多,我这里使用的是babel库,其他的库没做了解,babel库简单,功能强大是它的特点

在下载并安装后Node.js,就可以直接安装 babel库了。

安装命令:

npm install @babel/core --save-dev

在这里插入图片描述

在导入 @babel/parser 库后没有报错,那说明可以正常使用babel库了。

运行js可能会遇到错误:

Error: Cannot find module '@babel/parser'

解决方法:在当前目录下执行npm install @babel/core --save

4. 直观的理解AST

在线的解析网站:

https://astexplorer.net/

5.如何用AST解混淆?思路是什么?

首先要明确的是,你要做什么。比如看到源代码中,有很多类似这样的代码:

var a = "\u0068\u0065\u006c\u006c\u006f\u002c\u0041\u0053\u0054";

这代码看起来,可读性就差了很多,如果不是特别记忆,根本看不出是什么字符。

这个时候,你想把它还原成本来的面目:

var a = "hello,AST";

这样对你来说,就清晰多了。这时,你的目的就出来了,想要将

"\u0068\u0065\u006c\u006c\u006f\u002c\u0041\u0053\u0054"

替换成:

"hello,AST"

在这里,如果只有这一行我们直接手动替换就好了。那如果代码中有大量这样的字符串呢?也是一个一个手动替换吗?

那我们肯定选择用工具来完成这个重复的工作,目的明确了,现在就是如何编写工具了。

var a = "\u0068\u0065\u006c\u006c\u006f\u002c\u0041\u0053\u0054";

放在在线网站进行解析,发现要处理的字符串是一个 StringLiteral 类型的节点:

在这里插入图片描述

在使用babel库操作时,只需遍历这个类型的节点,就会处理全部的 StringLiteral节点。

要处理节点,那肯定要理解babel库的相关知识。

1.babel库官方文档:

https://babeljs.io/docs/en/

2.babel库github地址:

https://github.com/babel/babel

3.babel库官方插件开发手册:

https://github.com/jamiebuilds/babel-handbook

4.babel库官方插件

https://www.babeljs.cn/docs/plugins

6. babel库的学习

  1. JavaScript源代码转AST结构,@babel/parser,代码路径:

    node_modules\@babel\parser\lib
    

    在 node_modules@babel\parser\bin\babel-parser.js 该文件中有一段打印AST的代码,如下:

    var filename = process.argv[2];
    if (!filename) {console.error("no filename specified");
    } else {var file = fs.readFileSync(filename, "utf8");var ast = parser.parse(file);console.log(JSON.stringify(ast, null, "  "));
    }
  2. AST结构转JavaScript源代码,@babel/generator,代码路径:

    node_modules\@babel\generator\lib\generators
    
  3. 遍历 AST结构 的相关api,@babel/traverse,代码路径:

    node_modules\@babel\traverse\lib
    

    该路径下的 path 和scope 子文件夹是学习的重点。

  4. 构建新的节点,@babel/types,代码路径:

    node_modules\@babel\types\lib
    

解混淆能用到的api,基本就在这四个目录里面了,建议直接从源代码开始学习。

7. AST反混淆初体验-常量折叠

建议先看一下蔡老板写的的先导知识:利用AST解混淆先导知识:调用babel库反混淆代码模板

解混淆通用框架:

//babel库及文件模块导入
const fs = require('fs');//babel库相关,解析,转换,构建,生产
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const types = require("@babel/types");
const generator = require("@babel/generator").default;
//读取文件
let encode_file = "./encode.js",decode_file = "./decode_result.js";
if (process.argv.length > 2)
{encode_file = process.argv[2];
}
if (process.argv.length > 3)
{decode_file = process.argv[3];
}let jscode = fs.readFileSync(encode_file, {encoding: "utf-8"});
//转换为ast树
let ast    = parser.parse(jscode);const visitor =
{//TODO  write your code here!
}// 可以将整个ast规整的打印出来
// JSON.stringify(ast,null,'\t');
//some function code//调用插件,处理源代码,顺序执行,依次调用
// traverse(ast,插件名称);
// traverse(ast,插件名称2);traverse(ast,visitor);//生成新的js code,并保存到文件中输出
let {code} = generator(ast);
fs.writeFile('decode_result.js', code, (err)=>{});

以下面最简单的一行js代码为例(encode.js):

var a = 1 + 2 ;

想转换成这样(decode_result.js);

var a = 3 ;

利用ast在线解析网站:AST在线解析

鼠标点到“+”号旁边,观察节点类型:

在这里插入图片描述

在解混淆通用框架visitor里开始编写插件规则,并导出,详细代码:

//babel库及文件模块导入
const fs = require('fs');//babel库相关,解析,转换,构建,生产
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const types = require("@babel/types");
const generator = require("@babel/generator").default;
//读取文件
let encode_file = "./encode.js",decode_file = "./decode_result.js";
if (process.argv.length > 2)
{encode_file = process.argv[2];
}
if (process.argv.length > 3)
{decode_file = process.argv[3];
}let jscode = fs.readFileSync(encode_file, {encoding: "utf-8"});
//转换为ast树
let ast    = parser.parse(jscode);const visitor =
{//TODO  write your code here!"BinaryExpression":{enter(path){let {left,operator,right} = path.node;if (types.isNumericLiteral(left) && operator == '+' && types.isNumericLiteral(right)){console.log(path.toString());let value = left.value + right.value;let newNode = types.NumericLiteral(value);path.replaceWith(newNode);}}},
}// JSON.stringify(ast,null,'\t');
//some function code//调用插件,处理源代码
traverse(ast,visitor);//生成新的js code,并保存到文件中输出
let {code} = generator(ast);
fs.writeFile('decode_result.js', code, (err)=>{});

运行以上代码,可以看到产生的decode_result.js文件内容成功转换:

在这里插入图片描述

大概就是这种处理思想。

但是如果是:

var b = 4 - 3;
var c = 1 + 2 + 3 + 4 ;

这样的就处理不了,多写几个判断又太繁琐,这里引入蔡老板写好的常量折叠通用插件:

const constantFold = 
{"BinaryExpression|UnaryExpression|ConditionalExpression"(path){if(path.isUnaryExpression({operator:"-"}) || path.isUnaryExpression({operator:"void"})){return;}const {confident,value} = path.evaluate();if (!confident || value == "Infinity") return;if (typeof value == 'number' && isNaN(value)) return;path.replaceWith(types.valueToNode(value));},
}

看一下需要解混淆的js:

var a = 1 + 2;
var b = 4 - 3;
var c = 1 + 2 + 3 + 4 ;

调用常量折叠通用插件的还原结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dg4WybOE-1675242038111)(AST总结文档.assets/image-20230201163454432.png)]
蔡老板写了很多这样好用的插件,感兴趣的话可以加入蔡老板的知识星球AST入门与实战,站在巨人的肩膀上,跟着大佬走总比自己摸索要强很多(工具人的觉悟)

文章到此结束,感谢您的阅读,下篇文章见!

http://www.xdnf.cn/news/847873.html

相关文章:

  • 史上最全Fragment介绍,包括fragment的定义,生命周期,用法
  • 详解nc命令
  • 各种GAN原理总结及对比
  • Linux命令(11)之chown
  • 别再问别人了,这是小白都能懂的拓扑图指南
  • 「NTFS:让你的硬盘更安全、更高效!」NTFS文件系统详解,
  • iperf3主页官方信息
  • 快速排序的三种方式以及快排的优化
  • CTF-密码学基础
  • Sonar简介及使用
  • nslookup命令详解
  • 【JavaWeb】-- thymeleaf视图模板技术
  • Acwing - 算法基础课 - 笔记(动态规划 · 二)
  • burst什么意思_burst是什么意思_burst的用法
  • 深入探讨Samba服务器的配置与使用
  • Linux基础命令:tar压缩命令
  • 10.Python从入门到精通—Python 列表,列表脚本操作符,列表截取,列表函数方法
  • 干货!一文读懂10种主流的图片格式
  • hint详解
  • 什么是AOI?
  • 国产化操作系统都有哪些?如何选择?
  • 【网络协议 02】ICMP协议报文
  • acl是什么
  • Qemu架构解析(二),涨知识
  • 字符串的全面解析
  • shiro(一):shiro基本概念及基本使用(认证、授权)
  • 手把手教你安装Kali Linux
  • PaddleOCR 的使用,极简介绍
  • 颜色代码对照表
  • 单点登录(SSO)看这一篇就够了