首页 > 其他分享 >AST反混淆学习--化简常量

AST反混淆学习--化简常量

时间:2025-01-20 14:02:06浏览次数:3  
标签:化简 name AST -- init dict var path id

本文章是个人学习AST反混淆的笔记记录,发出来供大家参考指正,希望可以多多交流以提高个人技术!!!(注:本文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,否则后果自负,如有侵权,请联系作者立即删除!)

常见的常量混淆

常量混淆一直是js中最喜欢使用的一种方式之一,其形式包括计算,常量代替,ASCII码等等,有很多种类型
下面举例几种我最近遇到的比较多的情况:

  1. var a = 1 + 2;
  2. var b = ‘\x41’
  3. var c = ‘\u0041’
  4. var d = !![]
  5. var e = ‘hello, world’.length
  6. var f = String.fromCharCode(65)
  7. var g = ‘Win’;
    g += ‘dow’

解决方案

情况1-6

这种常量混淆比较小儿科,就是把一个固定的数以其他人类不易读的形式展现出来。
虽然人类不易读,但是程序是可以直接计算的。那我们的思路就是,直接匹配到这段被混淆的代码,然后eval执行它,然后把执行后获得的值替换即可
脚本如下:

const x = {
    VariableDeclarator(path) {
        try {
            path.node.init = types.valueToNode(eval(generator(path.node.init).code))
        } catch (e) {
            path.toString()
        }
    }
}
traverse(ast, x)

转换后代码如下:

情况七

这种是将一个变量拆开,然后用加法的方式组合形成最终的变量,这种就可能会麻烦不少
有很多种可能,比如这个加法的操作不是紧跟在声明变量操作的后面,而是隔了一段距离,比如

var a = 'win',
    b,
    c = 0;
    a += 'dow'
    c += 1

或者是与前面情况一至情况六这种融合一下,比如

var a = 1;
    a += 'asd'.length
var b = 'A';
    b += String.fromCharCode(65)

还有一种最最恶心的,就是不同作用域下的变量,变量名可能是一致的,比如

!function(){
   var a = 1
   var b = function(e){
      var a = 2;
          a += 3;
          a += e;
      return a
   }(4)
   a += 2
   console.log(a + b)
}()

对于前两种可能,我们可以考虑创建一个字典,将匹配到的var变量存入字典中,然后再次遍历+=的操作,如果+=操作的变量存在于字典中,就可以直接将右边的值与字典中已经存入的值进行相加,最后再替换掉原本的var变量即可
脚本如下:

var var_dict = {}
const g = {
    VariableDeclarator(path){
        let {id, init} = path.node
        if (init){
            try{
                var_dict[id.name] = eval(generator(init).code)
            }catch (e){
                console.log(path.toString())
            }
        }
    }
}
traverse(ast, g)

const g2 = {
    AssignmentExpression(path){
        let {left, operator, right} = path.node
        if (Object.keys(var_dict).includes(left.name) && operator === "+=" && types.isLiteral(right)){
            try{
                var_dict[left.name] += eval(generator(right).code)
                path.remove()
            }catch (e) {
                console.log(path.toString())
            }
        }
    }
}
traverse(ast, g2)

const g3 = {
    VariableDeclarator(path){
        let {id, init} = path.node
        if (Object.keys(var_dict).includes(id.name) && init){
            path.node.init = types.valueToNode(var_dict[id.name])
        }
    }
}
traverse(ast, g3)

转换后代码如下:

但是上面的做法遇到第三种情况就不好用了,因为作用域的不同,第三种情况下的两个a变量,其实指向的是不同的变量,如果仍旧使用上述的做法应对,就会导致出现以下情况

上图可以很明显的看出来最终的转换结果是不对的
所以面对作用域不同的情况,我个人的初步考虑是首先遍历整个代码,将所有的var变量放到一个dict中并记录其出现的数量,出现2次以上的就可以标记为可能作用域不同的变量(因为可能在同一个作用域重复声明,不过这种情况遇到的很少,重复声明会导致之前做的所有操作全部作废,一般很少有程序员会这么编写代码吧,所以这种情况以后遇到了再讨论吧)
然后,第二遍遍历就针对于这些会出现2次以上的变量进行操作,直接遍历每个函数(每个函数代表的作用域不一致),确定该函数下不会有新函数出现,此时作用域唯一,然后修改重复变量的变量名
等到所有的变量名都唯一时,就可以运行上面那套脚本了

var var_dict_2 = {}
const y = {
    VariableDeclarator(path){
        let {id, init} = path.node
        if (!var_dict_2[id.name] && init){
            var_dict_2[id.name] = 1
        }else if (var_dict_2[id.name] && init){
            var_dict_2[id.name] += 1
        }
    }
}
traverse(ast, y)
// console.log(var_dict_2)

const y2 = {
    FunctionExpression(path){
        let isLast = true
        path.traverse({
            FunctionExpression(path_2) {
                if (path_2){
                    isLast = false
                    path_2.stop()
                }
            }
        })
        let change_id = []
        if (isLast){
            path.traverse({
                Identifier(id_path){
                    let id = id_path.node.name
                    if (Object.keys(var_dict_2).includes(id) && var_dict_2[id] > 1){
                        id_path.node.name = id + var_dict_2[id]
                        if (!change_id.includes(id)){
                            change_id.push(id)
                        }
                    }
                }
            })
            if (change_id.length !== 0){
                for (let id of change_id){
                    var_dict_2[id] -= 1
                }
            }
        }
    }
}
traverse(ast, y2)

转换后代码如下:

标签:化简,name,AST,--,init,dict,var,path,id
From: https://blog.csdn.net/Loronto_/article/details/145207147

相关文章

  • Unity3D中的OnTrigger和OnCollision
    Unity中的OnTrigger和OnCollision详解1.基本概念在做游戏开发中,几乎所有项目都会用到碰撞,常见的方法是为游戏对象添加Rigidbody和Collider组件,在检测或处理两个游戏对象碰撞或触发时通常会用到Unity中自带的OnTrigger和OnCollision方法,下面就浅介绍一下使用方法和区别。......
  • Java从零到1的开始-Day13
    一、String1.String介绍1.概述:String类代表字符串2.特点: a.Java程序中的所有字符串字面值(如"abc")都作为此类的实例(对象)实现  凡是带双引号的都是String的对象  Strings="abc"   String是数据类型,是一个字符串类型   s:对象名  ......
  • 【迁移学习】原型引导领域感知渐进表示学习(prototype-guided domain-aware progressiv
    【迁移学习】原型引导领域感知渐进表示学习(prototype-guideddomain-awareprogressiverepresentationlearningPG-DPRL)(二)【迁移学习】原型引导领域感知渐进表示学习(prototype-guideddomain-awareprogressiverepresentationlearningPG-DPRL)(二)文章目录【迁移学......
  • 深入解析:Postgres 和 MySQL 的核心差异与选择建议
    几十年来,关系数据库为无数应用程序提供了支持,它们仍然是许多现代系统的支柱。说到可用于生产的选项,有两种最为广泛使用的数据库,即PostgreSQL和MySQL。两者都提供了可靠的性能、可靠性和社区支持,但它们在处理数据的方式、功能集和配置难易程度方面存在明显差异。了解这些细微差......
  • 是时候用Circos震撼全场了
    Circos图是一种采用圆形布局展示数据的可视化图表,这种独特的圆形设计特别适合用来探索不同对象之间或位置之间的关系。如果你的数据涉及某种关联性,或者需要展示多层次、多尺度的注释信息,Circos图将是一个非常理想的选择。Circos图无论是基因组学研究、迁徙模式分析,还是数学艺......
  • 计算机视觉实战应用OpenCV
    9.0图片的旋转矫正技术实现过程结果:我们要对文字进行校正:如何实现?以下是实现过程:导入模块:importcv2:用于图像处理操作,如读取、显示图像,图像边界扩展,直线检测,图像旋转等。importnumpyasnp:用于处理数组数据,进行傅里叶变换等操作。frommatplotlibimportpyplotas......
  • 【大模型面试】常见问题及答案,一文搞定面试准备!2025年大模型最新最全面试题,助你吊打面
    大模型相关的面试问题通常涉及模型的原理、应用、优化以及面试者对于该领域的理解和经验。以下是一些常见的大模型面试问题以及建议的回答方式:请简述什么是大模型,以及它与传统模型的主要区别是什么?回答:大模型通常指的是参数数量巨大的深度学习模型,如GPT系列。它们与传统模......
  • CSS 实体
    如果希望在HTML中使用CSS显示以下任何字符,您可以使用下表中的CSS实体。实例<style>h1:after{content:'\00A7';}</style>所有<h1>元素都将在结尾显示该字符:<!DOCTYPEhtml><html><style>h1:after{content:'\00A7';}</style......
  • OpenCV实战技术应用
    10.0角点检测应用技术实现,使用SIFT算法进行特征点检测并绘制。结果:实现过程:解析过程:1.导入模块:importcv2:导入 opencv 库,用于图像处理操作,包括图像读取、特征提取、图像绘制、匹配等。importnumpyasnp:导入 numpy 库,用于处理数组数据,在特征描述符的存......
  • OpenCV技术学习
    7.1霍夫变换应用技术实现结果:对变化的线条检测:importcv2importnumpyimportnumpyasnpimportmathdefgetMask(img):mask=numpy.zeros_like(img)ignore_mask_color=255imshape=img.shapevertices=np.array([[(0,imshape[0]),(5,697),(5,40......