JavaScript代码混淆还原

还原sojson.v5方式混淆js代码

看到这么一段js代码,很多次遇到这样格式的,很多头部都是这个 sojson.v5 代码混淆

一 研究JS代码规则

js代码有如下大概分为三段,而且里面数字全部替换成16进制

  • 第一段是一个 array 和 还原array顺序的自执行匿名函数
  • 第二段是通过还原后的array 和一个 key 生成原始数据(说白了就是个还原的工具函数)
  • 第三段就是原函数,里面部分代码必须得通过第二段函数还原

以我分析的代码为例子,以下代码均为部分代码,完整代码已上传到 github

  • 第一段array和 还原array顺序匿名函数

var encode_version = "sojson.v5",
  jhpfl = "__0x84ddc",
  __0x84ddc = [
    "w4opwqU+Kwpow6fDhD7DlDTCiMOLK8KWfsO1Lw==",
    "w6vCkcO8UMKu",
    "wqzDnMORwrdb",
    "N8KYwq0=",
    "wpvCuWsd",
    "ccOqGHMTFcKN",
    "GXbCvUw=",
    "...太长删除部分"
  ];

// 用于还原 __0x84ddc 数组位置
(function (_0x10da58, _0x1ba35d) {
  var _0x401b02 = function (_0x3143fb) {
    while (--_0x3143fb) {
      _0x10da58["push"](_0x10da58["shift"]());
    }
  };
  _0x401b02(++_0x1ba35d);
})(__0x84ddc, 0x170);
  • 第二段还原函数一般是两个参数,函数名为 _0x3574 记住这个函数名, 这段代码不用分析,后面调用就可以
var _0x3574 = function (_0x25feec, _0x50b32e) {
      _0x25feec = _0x25feec - 0x0;
      var _0xc5096a = __0x84ddc[_0x25feec];
      if (_0x3574["initialized"] === undefined) {
        (function () {
          var _0x3a5d0c =
            typeof window !== "undefined"
              ? window
              : typeof process === "object" &&
                typeof require === "function" &&
                typeof global === "object"
              ? global
              : this;
         .....省略代码

      var _0xf97a0a = _0x3574["data"][_0x25feec];
      if (_0xf97a0a === undefined) {
        if (_0x3574["once"] === undefined) {
          _0x3574["once"] = !![];
        }
        _0xc5096a = _0x3574["rc4"](_0xc5096a, _0x50b32e);
        _0x3574["data"][_0x25feec] = _0xc5096a;
      } else {
        _0xc5096a = _0xf97a0a;
      }
      return _0xc5096a;
    };
  • 第三段代码 混淆后的原函数js代码,里面有很多_0x3574(16进制值, 参数二) 这样的数据,这个_0x3574就是第二段代码里面的还原函数

var nol_data = [[], [], []];
    var clideCount = 0;
    var isSend = ![];
    var touchHandler = function (_0x4ca7f8) {
      var _0x162621 = {
        xpUaV: _0x3574("0x0", "7ND["),
        mtSJG: _0x3574("0x1", "HF[@"),
        tppxc: function _0xe8ead(_0x4b0883, _0x665f4d) {
          return _0x4b0883 > _0x665f4d;
        },
        yECOB: "AGN",
        Bkfzz: "DEJ",
      };
      try {
        _0x4deadf += _0x21f5b7[_0x3574("0x35", "[Aq2")];
        _0x3f11e7 = encode_version;
        if (
          !(
            _0x21f5b7[_0x3574("0x36", "u2Zf")](
       ..... 代码太长 中间省略了
        ) {
          _0x383a8d[_0x4deadf](_0x21f5b7[_0x3574("0x3f", "ys&E")]);
        } else {
          document[_0x3574("0x40", "n&K@")](
            _0x21f5b7[_0x3574("0x41", "i^lN")],
            touchHandler
          );
          clideCount += 0x1;
          if (_0x21f5b7[_0x3574("0x42", "Xacf")](clideCount, 0x3)) {
            console[_0x3574("0x43", "xn1D")](nol_data);
            $["ajax"]({
              type: _0x3574("0x44", "B5kn"),
              url: nol_url,
              data: {
                user_id: userData[_0x3574("0x45", "[z)f")],
                code: userData[_0x3574("0x46", "3@ob")],
                data: nol_data,
                ua: navigator["userAgent"],
              },
              dataType: _0x21f5b7[_0x3574("0x47", "7eVJ")],
              success: function (_0x1e5cc1) {},
            });
          }
        }
      }
    })(window);
    encode_version = "sojson.v5";

以上就是很经典的 sojson.v5 代码混淆

二 尝试还原代码

暂时还做不到自动,只能手动还原代码了。 分析: 每个代码段的作用都清楚,所以了首先把第一段代码段给运行一次

依赖: node.js 环境

把第一段代码复制出来到一个新的js文件里面,如array_restore.js,然后在最下面输出那个 __0x84ddc array

  • 1 还原array
# 在第一段代码最下面 输出
console.log(__0x84ddc)

node arrayRestore.js

然后复制出还原后的array, 还原后的array 肯定是和原array顺序或者数值不一样的。

  • 2 尝试执行还原函数

    把上面还原的js array 复制到一个新的js文件, 如 execute_func.js文件, 然后在把上面的第二段函数 _0x3574 这个函数完整复制出来,最后测试下是否可执行。

  • 测试方法 把第三段函数中调用示例,随机取一个测试 如_0x3574("0x0", "7ND[")

// 代码格式如下

// 还原后的array
__0x84ddc = [
    "省略",

]
// 原封不动的 _0x3574() 函数

var _0x3574 = function (_0x25feec, _0x50b32e) {
    "省略"
}

// 新增输出函数 查看结果
console.log(_0x3574("0x0", "7ND["))

然后执行 node executeFunc.js 查看输出是否正确输出。如果报错,活着没有输出则前面步骤有误或者不是这种混淆。

正确的话,就可以自己一步步复制出来然后输出,在粘贴还原回去。少量代码还好,代码量多的话就不行了。

三 用代码批量自动还原

思路: 用正则把第三段代码里面的 _0x3574("0x0", "7ND[") 匹配出来,然后在调用_0x3574这个函数 ,传入匹配的参数,然后在替换回去。

我这里了用Python代码演示,用什么语言都可以,思路差不多。

  • 在同级目录下,创建一个 recovery.py文件, 然后使用Python execjs库 来执行js代码,需要安装node环境,否则execjs运行不起来。
#  导入正则 和 执行js的库
import re
import execjs

# 第三段混淆后源js代码 复制在这里
source_js_code = """

var nol_data = [[], [], []];
    var clideCount = 0;
    var isSend = ![];
    var touchHandler = function (_0x4ca7f8) {
      var _0x162621 = {
        xpUaV: _0x3574("0x0", "7ND["),
        mtSJG: _0x3574("0x1", "HF[@"),
        tppxc: function _0xe8ead(_0x4b0883, _0x665f4d) {
          return _0x4b0883 > _0x665f4d;
        },
        yECOB: "AGN",
        Bkfzz: "DEJ",
      };
      var _0x25eb36 = _0x162621["xpUaV"]["split"]("|"),
        _0x2bf820 = 0x0;
      while (!![]) {
        switch (_0x25eb36[_0x2bf820++]) {
          case "0":
            nol_data[clideCount]["push"](_0x321bff);
            continue;
          case "1":
            var _0x2ae4c7 =
              _0xe05337[_0x3574("0x2", "7$($")] ||
              _0xe05337[_0x3574("0x3", "7eVJ")] ||
              0x0;
            continue;
            ....太长省略
""" 

# 获取执行js的函数
def get_js():
    f = open("./execute_func.js", 'r', encoding='utf-8')  # 打开JS文件
    line = f.readline()
    html_str = ''
    while line:
        html_str = html_str + line
        line = f.readline()
    return html_str


# 执行js 获取返回值
def encrypt(n1, n2):
    """

    :param n1:
    :param n2:
    :return:
    """
    js_str = get_js()
    ctx = execjs.compile(js_str)  # 加载JS文件
    # _0x3574 是上面js的函数名字 后面是两个参数
    return ctx.call('_0x3574', n1, n2)


# 正则匹配出整体这样的格式 [('_0x3574("0x0", "7ND[")', '0x0', '7ND['), ("函数整体", "参数1", "参数2")]
res = re.findall(r"\[?(_0x3574\(\"(.*?)\", \"(.*?)\"\))\]?", source_js_code)

for i in res:

    # 获取执行后的结果
    new_i = encrypt(i[1], i[2])

    # 替换结果 
    source_js_code = source_js_code.replace(i[0], f"\"{new_i}\"")

# 还原后的函数
print(source_js_code)

上述步骤,基本还原了重要的Js混淆

源代码已上传 Github仓库

https://github.com/CoderCharm/JsDecrypt/tree/master/sojson_v5


文章作者: 王小右
版权声明: 咳咳想白嫖文章?本文章著作权归作者所有,任何形式的转载都请注明出处。 https://www.charmcode.cn !
  目录