李恒道 发表于 2022-10-19 20:52:02

JS混淆分析初步理论研究篇三

之前我们已经解密到了
```
let a = 0x1;
alert(a);
(function (_0xc2361a, _0x49f6b2, _0x4c5d49) {
var _0x4bbdd6 = {
    PTyWI: "ert",
    CFOau: function _0x2e9886(_0x27d2c4, _0x233ed3) {
      return _0x27d2c4 !== _0x233ed3;
    },
    yGZoO: "undefined",
    UQhqT: function _0xe650a3(_0x4590a1, _0x160226) {
      return _0x4590a1 === _0x160226;
    },
    TtTMq: "jsjiami.com.v5",
    FQggo: function _0x47c22c(_0x2fe61e, _0x50381a) {
      return _0x2fe61e + _0x50381a;
    },
    FTCAn: "删除版本号,js会定期弹窗",
};
_0x4c5d49 = "al";
try {
    _0x4c5d49 += _0x4bbdd6["PTyWI"];
    _0x49f6b2 = encode_version;
    if (
      !(
      _0x4bbdd6["CFOau"](typeof _0x49f6b2, _0x4bbdd6["yGZoO"]) &&
      _0x4bbdd6["UQhqT"](_0x49f6b2, _0x4bbdd6["TtTMq"])
      )
    ) {
      _0xc2361a(
      _0x4bbdd6["FQggo"]("删除", "版本号,js会定期弹窗,还请支持我们的工作")
      );
    }
} catch (_0x2d647c) {
    _0xc2361a(_0x4bbdd6["FTCAn"]);
}
})(window);
encode_version = "jsjiami.com.v5";
```
我们接下来来处理花指令
根据观察可以发现其特征都是访问对象.成员的形式,我们先丢Ast里看一下
![图片.png](data/attachment/forum/202210/19/201344dl1gcq897jmog9z1.png)
丢到Ast explorer看一下
可以发现成员.属性是一个MemberExpression结构
object.name是对象名
property.value是属性名
![图片.png](data/attachment/forum/202210/19/201504xsmrrydhodp8zz2r.png)
那我们可以假设一下
我们可以遍历MemberExpression对象
如果找到,就根据对象名找到对应的对象,然后查找属性
判断是不是字符串
如果是字符串则直接替换
如果是函数则判断是否只有一行,并且有两个关键词,且有一个操作符
理论建立完毕,实战开始!
我们先替换字符串
首先判断属性是否是一个string字符串,如果是则判断可能是一个对象.属性的花指令
```javascript
traverse(ast, {
MemberExpression(path) {
    let obj_name = path.node.object.name;
    let obj_value =
      path.node.property.type === "StringLiteral"
      ? path.node.property.value
      : undefined;
    if (obj_name && obj_value) {
      console.log("obj_name", obj_name, obj_value);
    }
},
});
```
然后找到对象,我们可以判断obj_name && obj_value是否都符合条件
如果符合则开始找对象
通过path.scope.getBinding找
path表示两个节点的链接,而scope表示该属性所在的函数作用域
找到函数作用域后通过getBinding获取该函数作用域绑定的哪个值

```javascript
    if (obj_name && obj_value) {
      let obj_binding = path.scope.getBinding(obj_name);
    }
```
那么这句话的代码就是
找到我们所用的path的函数作用域,并找到对应的绑定(Binding)
也就是说我们从一个节点,跳到了这个函数的范围,再找到该函数内对应的绑定字符串
![图片.png](data/attachment/forum/202210/19/203547rzfa7yq45dd3m7ra.png)
找到的是一个Bingding对象
Identifier表示声明得时候所用的标识符
path表示该ast的path对象
kind表示var还是let等
referenced表示是否被引用
references表示引用的次数
constant表示是否是常量
constantViolations表示有谁修改了这个变量
referencePaths表示有谁引用了这个变量
![图片.png](data/attachment/forum/202210/19/203621p5kgz992klz2t4yd.png)
通过打印我们确定了找到的binding在这里
![图片.png](data/attachment/forum/202210/19/204001sd7cdrdeo30st07f.png)
所以我们可以继续写
找到binding后,遍历他的init的properties,也就是对象里声明的属性
判断有没有与我们MemberExpression的属性相等
如果相等,且该属性的初始化值为String类型,则直接进行替换
```javascript
      if (obj_binding) {
      let prop_list = obj_binding.path.node.init.properties;
      for (let index = 0; index < prop_list.length; index++) {
          let item_prop = prop_list;
          let prop_name = item_prop?.key?.name;
          if (prop_name === obj_value) {
            if (item_prop.value.type === "StringLiteral") {
            path.replaceInline(item_prop.value);
            return;
            }
          }
      }
      }
```
可以看到已经还原了字符串
![图片.png](data/attachment/forum/202210/19/205121zde76daasf054548.png)
完整代码
```javascript
traverse(ast, {
MemberExpression(path) {
    let obj_name = path.node.object.name;
    let obj_value =
      path.node.property.type === "StringLiteral"
      ? path.node.property.value
      : undefined;
    if (obj_name && obj_value) {
      let obj_binding = path.scope.getBinding(obj_name);
      if (obj_binding) {
      let prop_list = obj_binding.path.node.init.properties;
      for (let index = 0; index < prop_list.length; index++) {
          let item_prop = prop_list;
          let prop_name = item_prop?.key?.name;
          if (prop_name === obj_value) {
            if (item_prop.value.type === "StringLiteral") {
            path.replaceInline(item_prop.value);
            return;
            }
          }
      }
      }
    }
},
});
```
那我们就搞定了属性的获取
下节课尝试恢复混淆花指令的函数部分!
# 结语
撒花~
页: [1]
查看完整版本: JS混淆分析初步理论研究篇三