首页 > 技术文章 > ast入门 (二)

gaoyongjian 2020-08-10 22:39 原文

接上一章 ast指北一

简单实用

还原object对象

var a = {
  "YJJox": "object",
  "sbTga": function (b, c) {
    return b | c;
  },
  "iwvEK": function (b, c) {
    return b << c;
  },
  "HqkiD": function (b, c) {
    return b(c);
  }
};
b = a["iwvEK"](1, 3), c = a["sbTga"](111, 222), d = a["YJJox"], e = a["HqkiD"](String.fromCharCode, 49);

还原后

var a = {
  "YJJox": "object",
  "sbTga": function (b, c) {
    return b | c;
  },
  "iwvEK": function (b, c) {
    return b << c;
  },
  "HqkiD": function (b, c) {
    return b(c);
  }
};
b = 1 << 3, c = 111 | 222, d = "object", e = String.fromCharCode(49);

插件

const visitor =
    {
        VariableDeclarator(path) {
            const {id, init} = path.node;

            //特征判断,对象为空则不处理
            if (!t.isObjectExpression(init) || init.properties.length == 0) return;

            let name = id.name;
            let scope = path.scope;

            for (const property of init.properties) {//遍历key、value
                let key = property.key.value;
                let value = property.value;

                //一般ob混淆,key长度都是5,也有是3的,大家调整即可。
                if (key.length !== 5) return;

                //如果是字面量
                if (t.isLiteral(value)) {
                    scope.traverse(scope.block, {
                        //遍历MemberExpression,找出与key相同的表达式
                        MemberExpression(_path) {
                            let _node = _path.node;
                            if (!t.isIdentifier(_node.object, {name: name})) return;
                            if (!t.isLiteral(_node.property, {value: key})) return;
                            _path.replaceWith(value);
                        },
                    })
                }
                //如果是函数表达式
                else if (t.isFunctionExpression(value)) {
                    let ret_state = value.body.body[0];

                    //特征判断,如果不是return表达式
                    if (!t.isReturnStatement(ret_state)) continue;

                    scope.traverse(scope.block, {
                        CallExpression: function (_path) {

                            //遍历CallExpression
                            let {callee, arguments} = _path.node;
                            if (!t.isMemberExpression(callee)) return;
                            if (!t.isIdentifier(callee.object, {name: name})) return;
                            if (!t.isLiteral(callee.property, {value: key})) return;
                            if (t.isCallExpression(ret_state.argument) && arguments.length > 0) {

                                //构造节点
                                _path.replaceWith(t.CallExpression(arguments[0], arguments.slice(1)));
                            } else if (t.isBinaryExpression(ret_state.argument) && arguments.length === 2) {

                                //构造节点
                                let replace_node = t.BinaryExpression(ret_state.argument.operator, arguments[0], arguments[1]);
                                _path.replaceWith(replace_node);
                            } else if (t.isLogicalExpression(ret_state.argument) && arguments.length === 2) {

                                //构造节点
                                let replace_node = t.LogicalExpression(ret_state.argument.operator, arguments[0], arguments[1]);
                                _path.replaceWith(replace_node);
                            }
                        }
                    })
                }
            }
        },
    }

未完待续

全部代码在GitHub -> GitHub

推荐阅读