上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖

超星考试EncString破译

[复制链接]
  • TA的每日心情
    开心
    2023-2-28 23:59
  • 签到天数: 191 天

    [LV.7]常住居民III

    637

    主题

    5194

    回帖

    6076

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6076

    荣誉开发者管理员油中2周年生态建设者喜迎中秋

    发表于 2023-5-28 20:35:32 | 显示全部楼层 | 阅读模式

    FBI WARNING

    这里的超星考试指本人的原创单机游戏【超级星星V.666】单词大考验关卡
    并非通俗意义超星
    请勿联想

    正文

    点击考试预览可以追到AST部分
    这里可以看到是ob混淆+字符串转义
    图片.png
    我们先解决字符串转义部分
    直接利用babel的最小化就可以将字符串转义压缩成正常字符串

    const parser = require("@babel/parser");
    const generator = require("@babel/generator").default;
    const code_js = fs.readFileSync("./chaoxing_exam.js", {
      encoding: "utf-8",
    });
    const ast = parser.parse(code_js)
    let code = generator(ast, {
      minified: true,
      jsescOption: { minimal: true },
    }).code;
    fs.writeFile("./convert1.js", code, (err) => {});

    然后查看一下结果
    图片.png
    然后解字符串,这里是_0x56bc
    直接抬手一个转义,因为没有多层,所以只搜集_0x56bc即可
    老规矩,复制_0x56bc到nodejs作为解密函数
    首先测试一下,发现卡死了,多半是正则爆破,搜索Reg找到了

          _0x4337b4["prototype"]["RvZSqA"] = function () {
            var _0x403f16 = new RegExp(this["MTxJBI"] + this["FMdsHI"]);
            var _0x55e9af = _0x403f16["test"](this["ZxBleI"]["toString"]())
              ? --this["pNCgln"][1]
              : --this["pNCgln"][0];
            return this["AfmIcA"](_0x55e9af);
          };
          _0x4337b4["prototype"]["AfmIcA"] = function (_0x172353) {
            if (!Boolean(~_0x172353)) {
              return _0x172353;
            }
            return this["ebdBfN"](this["GRlANK"]);
          };
          _0x4337b4["prototype"]["ebdBfN"] = function (_0xa7fe72) {
            for (
              var _0x5f3bbf = 0, _0x1ed88a = this["pNCgln"]["length"];
              _0x5f3bbf < _0x1ed88a;
              _0x5f3bbf++
            ) {
              this["pNCgln"]["push"](Math["round"](Math["random"]()));
              _0x1ed88a = this["pNCgln"]["length"];
            }
            return _0xa7fe72(this["pNCgln"][0]);
          };

    应该是正则下面的三元运算符在捣乱,我们跑一下发现是false,所以直接强制改成true内的--this["pNCgln"][1]

          _0x4337b4["prototype"]["RvZSqA"] = function () {
            var _0x403f16 = new RegExp(this["MTxJBI"] + this["FMdsHI"]);
            var _0x55e9af = --this["pNCgln"][1]
            return this["AfmIcA"](_0x55e9af);
          };

    在运行发现还是存在内存爆破
    向上找到了字符串混淆内存在分支污染和内存爆破
    图片.png
    直接将第一个设为false,第二个设为true
    再运行crp函数
    图片.png
    解密成功
    然后直接开始解字符串混淆

    const fuck_js = fs.readFileSync("./convert2.js", {
      encoding: "utf-8",
    });
    const ast = parser.parse(fuck_js);
    traverse(ast, {
      CallExpression(path) {
        if (path.node.callee.name === "_0x56bc") {
          let loc1 = path.node.arguments[0].value;
          let loc2 = path.node.arguments[1]?.value;
          let str_node = types.stringLiteral(_0x56bc(loc1, loc2));
          path.replaceInline(str_node);
        }
      },
    });
    let code = generator(ast, {
      minified: true,
      jsescOption: { minimal: true },
    }).code;
    fs.writeFile("./convert3.js", code, (err) => {});

    已经具备基本的可读了
    图片.png
    接下来就是硬干了
    我们目标比较简单
    图片.png
    分析这些数据吧
    value像是鼠标的数据,我们先看value,确实是鼠标的相对页面键值

        var scrollLeft =
            document["documentElement"]["scrollLeft"] ||
            document["body"]["scrollLeft"],
          scrollTop =
            document["documentElement"]["scrollTop"] ||
            document["body"]["scrollTop"];
        (mouseMap["x"] =
          winEvent["pageX"] || winEvent["clientX"] + scrollLeft),
          (mouseMap["y"] =
            winEvent["pageY"] || winEvent["clientY"] + scrollTop),
        var value =
          "(" +
          Math["ceil"](mouseMap["x"]) +
          "|" +
          Math["ceil"](mouseMap["y"]) +
          ")";

    接下来看qid,取自页面的questionId数据

     _0x210627 = document["getElementById"]("questionId"),
    (qid = _0x210627["value"])

    看rd,随机数

    var rd = Math["random"](),

    接下来只剩enc和_edt了,先看enc
    里面是一个闭包
    看大概应该是一个转义字符代码,懒得搞了,直接抽离
    图片.png

    function getEncData(posData, userId, questionId, randomNum, rd) {
      let userIdAndQuestionIdAndRandom =
        userId + "_" + questionId + "|" + randomNum;
      if (
        null == userIdAndQuestionIdAndRandom ||
        userIdAndQuestionIdAndRandom["length"] <= 0
      )
        return null;
      for (
        var _0x469e62 = "", _0x388a1f = 0;
        _0x388a1f < userIdAndQuestionIdAndRandom["length"];
        _0x388a1f++
      )
        _0x469e62 +=
          userIdAndQuestionIdAndRandom["charCodeAt"](_0x388a1f)["toString"]();
      var _0x210627 = Math["floor"](_0x469e62["length"] / 5),
        _0x215858 = parseInt(
          _0x469e62["charAt"](_0x210627) +
            _0x469e62["charAt"](2 * _0x210627) +
            _0x469e62["charAt"](3 * _0x210627) +
            _0x469e62["charAt"](4 * _0x210627)
        ),
        _0x408603 = Math["ceil"](userIdAndQuestionIdAndRandom["length"] / 2),
        _0x3ed445 = Math["pow"](2, 31) - 1;
      if (_0x215858 < 2) return null;
      var rd = rd,
        _0x58d995 = Math["round"](1000000000 * rd) % 100000000;
      10 < (_0x469e62 += _0x58d995)["length"] &&
        (_0x469e62 = parseInt(_0x469e62["substring"](0, 10))["toString"]()),
        (_0x469e62 = (_0x215858 * _0x469e62 + _0x408603) % _0x3ed445);
      var _0x3c1f52 = "",
        _0x435dce = "";
      for (_0x388a1f = 0; _0x388a1f < posData["length"]; _0x388a1f++)
        (_0x435dce +=
          (_0x3c1f52 = parseInt(
            posData["charCodeAt"](_0x388a1f) ^
              Math["floor"]((_0x469e62 / _0x3ed445) * 255)
          )) < 16
            ? "0" + _0x3c1f52["toString"](16)
            : _0x3c1f52["toString"](16)),
          (_0x469e62 = (_0x215858 * _0x469e62 + _0x408603) % _0x3ed445);
      for (_0x58d995 = _0x58d995["toString"](16); _0x58d995["length"] < 8; )
        _0x58d995 = "0" + _0x58d995;
      return (_0x435dce += _0x58d995);
    }
    console.log(
      'getEncData("(1890|22)", userId, questionId, 265, 0.7836752714778081)',
      getEncData("(1890|22)", 用户id, 试卷id, 265, 0.7836752714778081)
    );
    

    官方数据
    图片.png
    抽离代码
    图片.png
    代码生成成功,然后看最后的_edt,来源是 "&_edt=" +
    (_0x408603 + randomNumA),其中randomNumA是一个生成的随机数

      function _0xe7b063() {
        if ("ySLJF" !== "ySLJF") {
          (function () {
            return ![];
          })
            ["constructor"]("debu" + "gger")
            ["apply"]("stateObject");
        } else {
          return Math["floor"](10 * Math["random"]());
        }
      }

    而另外一个603的变量则是时间

    _0x408603 = "" + new Date()["getTime"](),

    至此全部破译完毕

    结语

    撒花

    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
  • TA的每日心情
    慵懒
    昨天 20:22
  • 签到天数: 431 天

    [LV.9]以坛为家II

    148

    主题

    423

    回帖

    1144

    积分

    版主

    积分
    1144

    油中2周年生态建设者

    发表于 2023-5-29 10:04:29 | 显示全部楼层
    vjstool 哥哥可以试试
    I don't hate programming but the fucking world.
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2023-2-28 23:59
  • 签到天数: 191 天

    [LV.7]常住居民III

    637

    主题

    5194

    回帖

    6076

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6076

    荣誉开发者管理员油中2周年生态建设者喜迎中秋

    发表于 2023-5-29 13:03:14 | 显示全部楼层

    哥哥等我下次试试
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表