开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 1911|回复: 1
收起左侧

[JS相关教程] js 通过ast抽象语法树对代码进行fan'hun'x

[复制链接]
发表于 2020-10-31 09:12:20 | 显示全部楼层 |阅读模式   湖北省荆州市
最近做完一个项目,项目是Windows桌面客户游戏产品,基于NW架构开发,核心代码是基于js语言,cocos2d框架开发的h5游戏,分析js加密的过程当中使用到了js AST抽象语法树,对魂效果的js代码进行反混淆,增加代码可读性,更同意解密js相关的业务逻辑。

项目需求不复杂,就是一个打地鼠的游戏,每个房间两个人,游戏开始后,谁比对手多打10个地鼠就算赢。游戏本身很多通过按键xx等jiaob软件录制软件做的脚本在游戏**,客户觉得慢了,想以xieyi或者请求的方式定制软件。

游戏长这样
1.png


开始以为是unity  后来研究软件安装包 其实就是nw,和electron一样,使用的是js前端的技术栈

2.png

确定是js,通过fd抓包找到登录链接,就能看到项目源码,抓包后在Chrome中打开如下

4.png


发现代码中导出都是混淆过的代码,可读性非常差。通过Chrome network对游戏的协yi分析,了解到游戏是通过websocket加密,搜索websocket、onopen、onmessage、onclose、oneroor,等websocket比用的关键词,找到相关代码如下


可以看到这个源码文件导出都是_0x2b3c9d[_0x2568('0x3cb')]这样的代码,看上去像是从一个数组中,取对应索引的值,而且单引号内的0x开头的是16进制的数字,自己用微软的计算器,可以转换成10进制。

把代码拉到第一行,看到第一行的代码,其实就是一个大数组,里面基本都是明文,可以确定,这个代码文件里面的所有_0x2b3c9d[0xxxxx],就是从第一行的这个大树组里面取值。
6.png



这个大树组维护了几百个值,源文件几万行,不可能手工一个个拿计算器换算成10进制的数值后,再去找数组对应的索引值。那这个项目没法做。

这时候就需要使用到js AST抽象语法树相关的概念。

各位下次遇到js源码分析,代码里面有一个这样的值固定的很大的数组,其他代码中导出都是类似于数组[索引],这样的代码结构,就可以使用到抽象语法树的技术对代码进行反混淆。使用起来也相对简单。

给大家提供一个AST抽象语法树,代码结构分析的网站 https://astexplorer.net/,打开后将上面找到的websocket相关代码复制到左边,得到如下界面。

7.png



其实就是根据js语言的编译规则, 将所有的胆码拆分成相应的单元, 对代码结构进行分析。找到对应的代码结构,就可以通过编码的方式,将所有数组【索引】这样结构的代码全部找出来,然后在进行替换。

具体编码方式如下, 需要使用到nodejs的环境,先通过npm安装相应的包,然后把这个大树组复制进去,通过上面AST分析找到需要替换的节点,通过node fs模块,读取源代码,然后再对符合条件的节点进行替换。

8.png
没法截图了 上传附件了, 除了上面包引入,和大数组, 其他关键代码如下





// 数组调用切换为字符串
const traverse_arr = {
    Identifier: {
        exit(path) {
            if (t.isIdentifier(path.node, {
                    name: '_0x2568'
                })) {
                // 参数
                let args = path.parentPath.node.arguments
                // 节点替换
                if (args) {
                    args = args[0]
                    const len = arr.length
                    let index = parseInt(args.value, 16)
                    const val = arr[index]
                    path.parentPath.replaceWith(t.expressionStatement(t.stringLiteral(val)))
                }
            }
        }
    }
}

const traverse_member = {
    MemberExpression(path) {
        let property = path.get('property')
        if (property.isStringLiteral()) {
            const val = property.node.value
            path.node.computed = false
            property.replaceWith(t.Identifier(val))
        }
    }
}


const jscode = fs.readFileSync("./demo.js", {
    encoding: "utf-8"
})

const ast = parser.parse(jscode)
traverse(ast, traverse_arr)
traverse(ast, remove_commma)
traverse(ast, remove_var_commma)
// traverse(ast, traverse_member)
const {
    code
} = generator(ast)

fs.writeFile('./decode.js', code, (err) => {});







最后将反混淆之后的代码进行输出。得到基本能够看得懂的明文代码如下



没法上传附件了,随便扣一段反混淆之后的明文代码,结合上面截图中的混淆代码对比看一下



    var _0x90c116 = _0x43e0bb("./MessageHelper"),
        _0xbab33a = _0x43e0bb("./Logger"),
        _0xe92f43 = _0x43e0bb("../Net/NetMsgHandler"),
        _0x2072e8 = function () {
      function _0x5064cc() {
        this["connected"] = !0x1, this["socket"] = null;
      }

      return _0x5064cc["prototype"]["handleConnect"] = function (_0x342fe6) {
        this["connected"] = _0x342fe6, null != this["onConnect"] && this['onConnect'](_0x342fe6);
      }, _0x5064cc["prototype"]["handleOpen"] = function () {
        this["handleConnect"](!0x0);
      }, _0x5064cc['prototype']['handleMessage'] = function (_0x2bd9a6) {
        if (null != this["onMessage"]) {
          var _0x22c348 = _0x90c116["default"]["decode"](_0x2bd9a6["data"]);

          this["onMessage"](_0x22c348["tag"], _0x22c348["tagGame"], _0x22c348["body"]);
        } else _0xbab33a["logger"]["error"]("handleMessage:: this.onMessage is null! isConnected=%s", _0xe92f43["netMsgHandler"]["isConnected"]());
      }, _0x5064cc["prototype"]["handleError"] = function () {
        this['handleConnect'](!0x1);
      }, _0x5064cc["prototype"]["handleClose"] = function () {
        null != this["onClose"] && this["onClose"](), this["connected"] = !0x1;
      }, _0x5064cc["prototype"]["connect"] = function (_0x18d706, _0x3fd53f) {
        try {
          'WebSocket' in window ? this["socket"] = new WebSocket("ws://" + _0x18d706 + ':' + _0x3fd53f) : "MozWebSocket" in window && (this['socket'] = new MozWebSocket("ws://" + _0x18d706 + ':' + _0x3fd53f)), this['socket']["binaryType"] = "arraybuffer", this["socket"]["session"] = this, this["socket"]["onopen"] = this["handleOpen"]["bind"](this), this['socket']["onmessage"] = this["handleMessage"]['bind'](this), this["socket"]["onclose"] = this["handleClose"]['bind'](this), this["socket"]["onerror"] = this["handleError"]['bind'](this);
        } catch (_0x201db4) {
          return this["handleConnect"](!0x1), void _0xbab33a["logger"]["error"](_0x201db4["message"] + '\x0a' + _0x201db4["stack"]);
        }
      }, _0x5064cc["prototype"]["setCallback"] = function (_0x59d05b, _0x26b217, _0x3d761e) {
        this['onConnect'] = _0x59d05b, this["onMessage"] = _0x26b217, this["onClose"] = _0x3d761e;
      }, _0x5064cc['prototype']['send'] = function (_0x2ef6f4, _0x30ae76, _0xf65e69) {
        return this["socket"]['readyState'] === WebSocket["OPEN"] && (this["socket"]["send"](_0x90c116["default"]["encode"](_0x2ef6f4, _0x30ae76, _0xf65e69)), !0x0);
      }, _0x5064cc["prototype"]["sendGameMsg"] = function (_0x4dbbf3, _0x37be87, _0x2298b8) {
        return this["socket"]["readyState"] === WebSocket['OPEN'] && (this["socket"]["send"](_0x90c116["default"]["encodeGameMsg"](_0x4dbbf3, _0x37be87, _0x2298b8)), !0x0);
      }, _0x5064cc["prototype"]["close"] = function () {
        console["log"]('net.Close------>'), this['socket']['close']();
      }, _0x5064cc["prototype"]["getWSState"] = function () {
        return null == this['socket'] ? WebSocket["CLOSED"] : this["socket"]["readyState"];
      }, _0x5064cc;
    }();





反混淆之后,socket onmessage 等等,将上面大树组里面的值都替换到源代码里面去,就能很方便的对代码进行分析了。


有js,websocket,java,c#,安卓,等技术相关的协yi、逆向项目需求的老板可以找我详聊。




评分

参与人数 1好评 +1 精币 +3 收起 理由
冰点 + 1 + 3 奉上小小红包希望笑纳

查看全部评分

结帖率:50% (1/2)

签到天数: 9 天

发表于 2023-8-3 09:41:14 | 显示全部楼层   广东省珠海市
惨。没人看得懂啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 诚聘英才| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 800073686,邮箱:800073686@b.qq.com
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

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