const fs = require('fs');
const types = require("@babel/types");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const generator = require("@babel/generator").default;


//js混淆代码读取
process.argv.length > 2 ? encodeFile = process.argv[2] : encodeFile = "./captcha.js";
process.argv.length > 3 ? decodeFile = process.argv[3] : decodeFile = "./decodeResult.js";
//将源代码解析为AST
let sourceCode = fs.readFileSync(encodeFile, {encoding: "utf-8"});

let ast = parser.parse(sourceCode);


console.time("处理完毕，耗时");


function getRandomName(length) {

    let initArr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
    let puzzleArr = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
    let ranInx = Math.floor(Math.random() * initArr.length);
    let randomName = initArr[ranInx];

    for (var i = 1; i < length; i++) {
        ranInx = Math.floor(Math.random() * puzzleArr.length);
        randomName += puzzleArr[ranInx];
    }

    return randomName;
}


let allNewNames = new Map();  //定义一个全局变量，保存需要处理的函数
function getUnusedName() {//获取未被使用的名称,返回 Identifier 类型。
    do {
        var newName = "$C_" + getRandomName(3);

    } while (allNewNames.has(newName))

    allNewNames.set(newName, 1);


    return newName;
}

function getUnusedIdentifier() {//获取未被使用的名称,返回 Identifier 类型。
    do {
        var newName = "$C_" + getRandomName(3);

    } while (allNewNames.has(newName))

    allNewNames.set(newName, 1);

    let UnusedIdentifier = types.Identifier(newName);

    return UnusedIdentifier;
}


const renameFunc =
    {
        FunctionDeclaration(path) {
            let {node, parentPath} = path;
            let {id, params, body} = node;
            let name = id.name;

            // if (params.length != 2 || body.body.length != 1 ||
            //     !types.isReturnStatement(body.body[0]) || !types.isCallExpression(body.body[0].argument)) {
            //     return;
            // }

            let binding = parentPath.scope.getBinding(name);

            if (!binding || !binding.constant) {
                return;
            }
            // console.log('getName', name)
            let newNameId = getUnusedIdentifier();
            for (let referPath of binding.referencePaths) {
                referPath.replaceWith(newNameId);
            }

            let newName = newNameId.name;
            allNewNames.set(newName, name)
            path.node.id.name = newName;
        }
    }

traverse(ast, renameFunc);

var code = generator(ast, opts = {jsescOption: {"minimal": true}}).code;

fs.writeFileSync(decodeFile, code);
allNewNames.clear();


let funcNames = []
// traverse(ast, {
//     FunctionDeclaration(path) {
//         let node = path.node;
//         if (node.id.name === 'Aa') {
//             let code = generator(node).code;
//             if (code.includes('Aa = function ')) {
//                 console.log(node.id.name)
//                 let scope = path.parentPath.parentPath.scope;
//                 getBinding(scope, node.id.name, e => {
//                     // console.log(e.parent.type, generator(e.parent).code)
//                     if (types.isVariableDeclarator(e.parent)) {
//                         let initIdName = e.parent.id.name;
//                         funcNames.push(initIdName)
//                         getBinding(e.parentPath.parentPath.parentPath.parentPath.scope, initIdName, (i => {
//                             // console.log(initIdName, i.parent.type )
//
//                             if (types.isCallExpression(i.parent)) {
//                                 // console.log(generator(i.parent).code)
//                                 let {arguments} = i.parent
//                                 if (arguments.length === 1 && types.isNumericLiteral(arguments[0])) {
//                                     let value = Aa(arguments[0].value)
//                                     console.log(arguments[0].value, value)
//                                     i.parentPath.replaceWith(types.StringLiteral(value))
//
//                                 }
//                             }
//
//                         }))
//                     } else if (types.isCallExpression(e.parent)) {
//                         let {arguments} = e.parent
//                         if (arguments.length === 1 && types.isNumericLiteral(arguments[0])) {
//                             let value = Io(arguments[0].value)
//                             e.parentPath.replaceWith(types.StringLiteral(value))
//
//                         }
//                     }
//                 })
//
//
//             }
//         }
//
//
//     }
// })

console.log(funcNames)
// traverse(ast, {
//     CallExpression(path) {
//         let node = path.node;
//         let {callee, arguments} = node;
//         if (funcNames.includes(callee.name) && arguments.length === 1 && types.isNumericLiteral(arguments[0])){
//             let value = Aa(arguments[0].value)
//             console.log(callee.name, arguments[0].value , value)
//             if (value)path.replaceWith(types.StringLiteral(value))
//
//         }
//     }
// })
function n(n) {

    for (var i = atob(n), l = "IkEiYF9", a = "", c = 0; c < i.length; ++c) {
        var u = l.charCodeAt(c % 7);
        a += String.fromCharCode(u ^ i.charCodeAt(c))
    }
    return a
}

function getBinding(scope, name, func) {
    let binding = scope.getBinding(name);
    console.log(`scope.get(${name}).length = ${binding.references}`)
    if (binding.references > 0) {
        for (const referencePath of binding.referencePaths) {
            func(referencePath)
        }
    }

}

// traverse(ast, {
//     FunctionDeclaration(path) {
//         let node = path.node;
//         if (node.id.name === 'i') {
//             let code = generator(node).code;
//             if (code.includes('charCodeAt')) {
//                 // console.log(node.id.name)
//                 let scope = path.parentPath.parentPath.scope;
//                 getBinding(scope, node.id.name, e => {
//                     // console.log(e.parent.type, generator(e.parent).code)
//                     if (types.isVariableDeclarator(e.parent)) {
//                         let initIdName = e.parent.id.name;
//                         getBinding(e.parentPath.parentPath.parentPath.scope, initIdName, (i => {
//                             // console.log(initIdName, i.parent.type )
//
//                             if (types.isCallExpression(i.parent)) {
//                                 // console.log(generator(i.parent).code)
//                                 let {arguments} = i.parent
//                                 if (arguments.length === 1 && types.isStringLiteral(arguments[0])) {
//                                     let value = n(arguments[0].value)
//                                     // console.log(arguments[0].value, value)
//                                     i.parentPath.replaceWith(types.StringLiteral(value))
//
//                                 }
//                             }
//
//                         }))
//                     } else if (types.isCallExpression(e.parent)) {
//                         let {arguments} = e.parent
//                         if (arguments.length === 1 && types.isStringLiteral(arguments[0])) {
//                             let value = n(arguments[0].value)
//                             e.parentPath.replaceWith(types.StringLiteral(value))
//
//                         }
//                     }
//                 })
//
//
//             }
//         }
//
//
//     }
// })

function H(t) {
    return f(U) === "function" ? U(t) : function (t) {
        var e,
            n,
            r,
            a,
            o = [],
            i = 0,
            c = t.length;
        try {
            if (/[^+/=0-9A-Za-z]/.test(t) || /=/.test(t) && (/=[^=]/.test(t) || /={3}/.test(t))) return null;
            for (c % 4 > 0 && (c = (t += p.Array(4 - c % 4 + 1).join("=")).length); i < c;) {
                for (n = [], a = i; i < a + 4;) n.push("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(t.charAt(i++)));
                for (r = [((e = (n[0] << 18) + (n[1] << 12) + ((63 & n[2]) << 6) + (63 & n[3])) & 255 << 16) >> 16, 64 === n[2] ? -1 : (65280 & e) >> 8, 64 === n[3] ? -1 : 255 & e], a = 0; a < 3; ++a) (r[a] >= 0 || 0 === a) && o.push(String.fromCharCode(r[a]));
            }
            return o.join("");
        } catch (t) {
            return null;
        }
    }(t);
}

// traverse(ast, {
//     CallExpression(path) {
//         let node = path.node;
//         if (node.callee.name === 'H') {
//             let {arguments} = node
//             if (arguments.length === 1 && types.isStringLiteral(arguments[0])) {
//                 let value = atob(arguments[0].value)
//                 path.replaceWith(types.StringLiteral(value))
//
//             }
//         }
//     }
// })

// 常量还原
function isNodePure(node, scope) {
    if (types.isLiteral(node)) {
        return true;
    }

    if (types.isUnaryExpression(node)) {
        return isNodePure(node.argument, scope)
    }

    if (types.isIdentifier(node)) {//处理 var c = String;
        if (scope && scope.isPure(node, true)) {
            return true;
        }

        if (typeof this[node.name] != 'undefined') {
            return true;
        }

        return false;
    }

    if (types.isMemberExpression(node)) {//处理 var d = String.fromCharCode;

        let {object, property, computed} = node;

        if (computed && !isNodePure(property, scope)) {
            return false;
        }
        if (isNodePure(object, scope)) {
            return true;
        }

        if (types.isIdentifier(object)) {

            let name = object.name;

            if (typeof this[name] != 'undefined' && name != 'window') {//注意object为window时，可能会还原出错
                return true;
            }

            return false;
        }
        if (types.isMemberExpression(object)) {
            return isNodePure(object, scope);
        }

        return false;
    }

    if (types.isBinary(node) && scope) {
        return isNodePure(node.left, scope) && isNodePure(node.right, scope);
    }

    return false;
}

// traverse(ast, {
//     VariableDeclaration(path) {
//         let {node} = path;
//         let {declarations} = node;
//         let res = [];
//         // console.log(path.parentPath.type)
//         if (types.isForStatement(path.parentPath)) return
//         if (!declarations || declarations.length == 1) return
//         for (let i = 0; i < declarations.length; i++) {
//             let declaration = declarations[i];
//             res.push(types.VariableDeclaration('var', [declaration]))
//         }
//         path.replaceWithMultiple(res)
//         path.skip()
//
//     }
// })
//
//
// const restoreVarDeclarator = {
//
//     VariableDeclarator(path) {
//         let scope = path.scope;
//         let {id, init} = path.node;
//         if (!init && (!types.isNumericLiteral(init) || !types.isStringLiteral(init))) return
//         if (id.name === 'c' && init.value === 0) return
//         if (!types.isIdentifier(id) || !isNodePure(init, scope)) {
//             return;
//         }
//
//         const binding = scope.getBinding(id.name);
//         try {
//             var {
//                 constant, referencePaths, constantViolations
//             } = binding;  //变量的定义一定会有binding.
//
//         } catch (e) {
//             return;
//         }
//
//
//         if (constantViolations.length > 1) {
//             return;
//         }
//
//         if (constant || constantViolations[0] == path) {
//             for (let referPath of referencePaths) {
//                 // console.log(init.value)
//                 // console.log(id.name, referPath.type, generator(referPath.container).code,  generator(init).code)
//                 referPath.replaceWith(init);
//             }
//             // console.log(path.toString())
//             path.remove();//没有被引用，或者替换完成，可直接删除
//         }
//     },
// }
// traverse(ast, restoreVarDeclarator)
//
// //还原object
// traverse(ast, {
//     VariableDeclaration(path) {
//         let {scope, node} = path;
//         let {declarations} = node;
//         if (!declarations) return
//
//         if (declarations.length !== 1) return;
//
//         let {id, init} = declarations[0]
//         if (!types.isObjectExpression(init)) return
//         let {properties} = init;
//
//         if (properties.length === 0) return;
//         for (let i = 0; i < properties.length; i++) {
//             let {key, value} = properties[i];
//             if (!types.isNumericLiteral(value)) return
//         }
//
//
//         let binding = scope.getBinding(id.name);
//         if (!binding) return
//         let {constant, referencePaths, constantViolations} = binding;
//         if (!constant) {//新版本的babel库，在循环里面的变量定义，默认非常量
//             if (constantViolations.length != 1 || constantViolations[0] != path) //旧版本屏蔽该行即可
//             {
//                 return;
//             }
//         }
//
//         let newMap = new Map();
//         for (const property of properties) {
//             let {key, value} = property;
//             newMap.set(key.name, value);
//         }
//
//         let canBeRemoved = true;
//         for (const referPath of referencePaths) {
//             let {parentPath} = referPath;
//             if (!parentPath.isMemberExpression()) {
//                 canBeRemoved = false;
//                 return;
//             }
//
//             let AncestorPath = parentPath.parentPath;
//
//             if (AncestorPath.isAssignmentExpression({"left": parentPath.node})) {
//                 canBeRemoved = false;
//                 return;
//             }
//             if (AncestorPath.isUpdateExpression() && ['++', '--'].includes(AncestorPath.node.operator)) {
//                 canBeRemoved = false;
//                 return;
//             }
//
//             let curKey = parentPath.node.property.name;
//             if (!newMap.has(curKey)) {
//                 canBeRemoved = false;
//                 break;
//             }
//             parentPath.replaceWith(newMap.get(curKey));
//         }
//         canBeRemoved && path.remove();
//         newMap.clear();
//     }
// })

function strArrToNodeList(strs) {
    let res = [];
    for (let j = 0; j < strs.length; j++) {
        res.push(types.StringLiteral(strs[j]))
    }
    return types.ArrayExpression(res)
}

let funcs = {};
let funcTemp = {}
let nameMap = {};
traverse(ast, {
    FunctionDeclaration(path) {
        let {id, body} = path.node;
        let scope = path.scope;
        if (body.body.length !== 2) return
        if (!types.isVariableDeclaration(body.body[0]) || !types.isReturnStatement(body.body[1])) return
        let {declarations} = body.body[0];
        if (declarations.length !== 1) return;
        let declaration = declarations[0];
        if (types.isArrayExpression(declaration.init)) {
            let elements = declaration.init.elements;
            if (elements.length === 0) return

            for (let i = 0; i < elements.length; i++) {
                if (!types.isStringLiteral(elements[i])) {
                    return;
                }
            }
            // console.log(generator(path.node).code)
            let binding = scope.getBinding(id.name);

            if (!binding) return;
            let code1, code2, code3;
            code1 = generator(path.node).code;
            console.log('开始一个新的反混淆', id.name)
            // console.log(code1)
            // console.log(binding.references)
            if (id.name === 'Vn') {
                // debugger;
                return;
            }
            let d = 0;

            let reference;
            for (const referencePath of binding.referencePaths) {
                // console.log(generator(referencePath.parentPath.parentPath.parentPath.parentPath.parent).code)

                // console.log(referencePath.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.type)
                if (types.isCallExpression(referencePath.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.parent)
                    || types.isUnaryExpression(referencePath.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.parent)
                ) {
                    let code = `!${generator(referencePath.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.parent).code}`
                    if (code.indexOf('parseInt') > -1 && code.length < 1000) {
                        code2 = code;
                        console.log(code2.length)
                        console.log()
                        referencePath.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.replaceWith(
                            types.CallExpression(
                                types.FunctionExpression(
                                    null, [],
                                    types.BlockStatement([])
                                ),
                                []
                            )
                        )


                    }
                }
                if (types.isCallExpression(referencePath.parentPath.parentPath.parentPath.parentPath.parentPath.parent)) {
                    let code = `!${generator(referencePath.parentPath.parentPath.parentPath.parentPath.parentPath.parent).code}`
                    if (code.indexOf('parseInt') > -1 && code.length < 1000) {
                        code2 = code;
                        console.log(code2.length)
                        console.log()
                        referencePath.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.replaceWith(
                            types.CallExpression(
                                types.FunctionExpression(
                                    null, [],
                                    types.BlockStatement([])
                                ),
                                []
                            )
                        )

                    }
                }
                if (types.isBlockStatement(referencePath.parentPath.parentPath.parentPath.parentPath)
                    && referencePath.parentPath.parentPath.parentPath.parentPath.parent.body.body.length == 2
                ) {
                    // && referencePath.parentPath.parentPath.parentPath.parentPath.parent.body.length ==2
                    //     console.log(referencePath.parentPath.parentPath.parentPath.parentPath.parent.body.body.length)
                    try {
                        code3 = generator(referencePath.parentPath.parentPath.parentPath.parentPath.parent).code
                        reference = referencePath;
                    } catch (e) {
                        continue
                    }
                }
            }
            if (code1 && code2 && code3) {
                let res = eval((code1 + ';' + code2 + ';' + code3).replaceAll(`function ${id.name}`, `let ${id.name} = function`) + `;${id.name}()`)
                let result = strArrToNodeList(res)
                reference.parentPath.replaceWith(result);
                // console.log('result', generator(result).code)
                let tName = reference.parentPath.parentPath.parentPath.parentPath.parent.id.name;
                let binding2 = reference.scope.getBinding(tName)
                let code = generator(reference.parentPath.parentPath.parentPath.parentPath.parent).code;
                let nn = getUnusedName();
                console.log('newFunc', nn, `funcTemp.${nn} = function (a, b) {
                    return ${code}(a, b)
                }`)
                eval(`funcTemp.${nn} = function (a, b) {
                    return ${code}(a, b)
                }`)
                for (const referPath2 of binding2.referencePaths) {
                    if (!types.isCallExpression(referPath2.parent)) continue;
                    let refer = referPath2.parent;
                    console.log(generator(refer).code)
                    let {callee, arguments} = refer;
                    if (!arguments) continue
                    if (arguments.length !== 2) continue
                    let ifExec = true;
                    for (let j = 0; j < arguments.length; j++) {
                        if (!types.isNumericLiteral(arguments[0])) {
                            ifExec = false;
                        }
                    }
                    if (ifExec) {
                        // 直接执行
                    } else {
                        // 再次引用
                        if (types.isFunctionDeclaration(referPath2.parentPath.parentPath.parentPath.parent)) {
                            let dName = referPath2.parentPath.parentPath.parentPath.parent.id.name;
                            // 差 要减去的值
                            let arguments2 = referPath2.parent.arguments;
                            if (arguments2.length == 2 && types.isNumericLiteral(arguments2[0].right)) {
                                d = arguments2[0].right.value
                                console.log(callee.name, nn, arguments2[0].right.value)
                            }
                            if (arguments2.length == 2 && types.isUnaryExpression(arguments2[0].right)
                                && arguments2[0].right.operator === '-') {
                                d = -arguments2[0].right.argument.value
                                console.log(callee.name, nn, arguments2[0].right.value)
                            }
                            let code22 = generator(referPath2.parent).code
                            code22 = code22.replace(`${callee.name}(`, `funcTemp.${nn}(`)
                            console.log(`funcTemp.${dName} = function (r, n) {
                                    return ${code22}
                                }`)
                            eval(`funcTemp.${dName} = function (r, n) {
                                return ${code22}
                            }`)
                            let binding3 = referPath2.scope.getBinding(dName)
                            funcs[dName] = {
                                name: nn,
                                v: d
                            };
                            console.log(dName, nn)
                            if (!binding3) continue;
                            console.log(dName)
                            // for (const referPath3 of binding3.referencePaths) {
                            //     let {callee, arguments} = referPath3.parent;
                            //     if (!arguments) continue;
                            //     if (arguments.length !== 2) continue;
                            //     let ifExec = true;
                            //     for (let j = 0; j < arguments.length; j++) {
                            //         if (!types.isNumericLiteral(arguments[0])) {
                            //             ifExec = false;
                            //         }
                            //     }
                            //     if (!ifExec) {
                            //         let dName2 = referPath3.parentPath.parentPath.parentPath.parent.id.name;
                            //         let binding4 = referPath2.scope.getBinding(dName2)
                            //         console.log(dName2)
                            //         for (const referPath4 of binding4.referencePaths) {
                            //             let {callee, arguments} = referPath4.parent;
                            //             if (!arguments) continue;
                            //             if (arguments.length !== 2) continue;
                            //             let ifExec = true;
                            //             for (let j = 0; j < arguments.length; j++) {
                            //                 if (!types.isNumericLiteral(arguments[0])) {
                            //                     ifExec = false;
                            //                 }
                            //             }
                            //             if (ifExec) {
                            //
                            //             } else {
                            //                 try {
                            //                     let res = eval(`${nn}(${arguments[0].value}, ${arguments[1].value})`)
                            //                     console.log(tName, arguments[0].value, arguments[1].value, '=>', res)
                            //                 } catch (e) {
                            //
                            //                 }
                            //             }
                            //
                            //         }
                            //
                            //     } else {
                            //         try {
                            //             let res = eval(`${nn}(${arguments[0].value}, ${arguments[1].value})`)
                            //             console.log(tName, arguments[0].value, arguments[1].value, '=>', res)
                            //         } catch (e) {
                            //
                            //         }
                            //     }
                            //
                            // }

                        }
                    }
                    console.log(referPath2.parentPath.type)

                }
                path.skip()
            }

            //  let {id} = parentPath.parentPath.node
            // funcs[id.name] = {
            //     array: generator(path.node).code
            // }
        }


    }
})

console.log(funcs)
// traverse(ast, {
//     FunctionDeclaration(path) {
//         let {id, body} = path.node;
//         if (body.body.length !== 2) return
//         if (!types.isVariableDeclaration(body.body[0]) || !types.isReturnStatement(body.body[1])) return
//         let {declarations} = body.body[0];
//         if (declarations.length !== 1) return;
//         let declaration = declarations[0];
//         let {node, scope} = path;
//         if (!types.isCallExpression(declaration.init)) {
//             return
//         }
//         if (Object.keys(funcs).includes(declaration.init.callee.name)) {
//             funcs[declaration.init.callee.name]['call'] = generator(node).code
//             funcs[declaration.init.callee.name]['name'] = id.name
//         }
//     }
// })
// traverse(ast, {
//     UnaryExpression(path) {
//         let {id, body} = path.node;
//         let {node, scope} = path;
//         let {operator, argument} = node;
//         if (operator !== '!') return
//         let {callee, arguments} = argument;
//         if (!arguments) return
//         if (arguments.length !== 1) return
//         let arg = arguments[0]
//         if (!types.isIdentifier(arg)) return
//         if (Object.keys(funcs).includes(arg.name)) {
//             funcs[arg.name]['rever'] = generator(node).code
//         }
//     }
// })
// console.log(funcs)


var newMap = {}
let keys = Object.keys(funcs);
let keys2 = [];
for (let i = 0; i < keys.length; i++) {
    newMap[funcs[keys[i]].name] = funcs[keys[i]]
    keys2.push(funcs[keys[i]].name)
}
var map2 = {};

// 开始还原
// for (let j = 0; j < 3; j++) {
//     traverse(ast, {
//         VariableDeclaration(path) {
//             let {declarations} = path.node;
//             let scope = path.scope;
//             if (declarations.length !== 1) return;
//             let declaration = declarations[0]
//             let {id, init} = declaration;
//             if (!init) return
//             if (!types.isIdentifier(init)) return;
//             if (init.name === '$d') {
//                 debugger;
//             }
//
//             if (keys2.includes(init.name)) {
//                 let t = newMap[init.name];
//                 let jsCode = t.array + ';' + t.rever + ';' + t.call;
//                 // console.log(jsCode)
//                 jsCode = `funcTemp.${t.name} = function(t,e){
//                 ${jsCode}
//                 return ${t.name}(t,e)
//                 }`
//                 eval(jsCode)
//                 // console.log('eval', t.name)
//                 keys2.push(id.name)
//                 newMap[id.name] = t;
//                 map2[id.name] = t.name
//                 funcTemp[id.name] = funcTemp[t.name]
//                 map2[init.name] = t.name
//                 let binding = scope.getBinding(id.name);
//
//                 if (!binding) return;
//                 console.log(id.name, init.name, keys2.includes(init.name), binding.references)
//
//
//                 if (id.name === 'zo') {
//                     // console.log(id.name, init.name, keys2.includes(init.name), binding.references)
//                     debugger
//                 }
//
//                 for (const referencePath of binding.referencePaths) {
//                     // console.log(referencePath.parentPath.type);
//                     if (types.isCallExpression(referencePath.parent)) {
//                         let {callee, arguments} = referencePath.parent;
//                         if (id.name === 'zo') {
//
//                             // console.log(generator(referencePath.parentPath.node).code)
//                         }
//                         if (arguments.length === 1 && types.isNumericLiteral(arguments[0])) {
//                             let res = funcTemp[t.name](arguments[0].value)
//                             if (id.name === 'zo') {
//
//                                 // console.log(arguments[0].value, res)
//                             }
//                             referencePath.parentPath.replaceWith(types.StringLiteral(res))
//                         }
//                     }
//                 }
//
//             }
//         }
//     })
// }

for (let j = 0; j < 3; j++) {
    traverse(ast, {
        CallExpression(path) {
            let callee = path.node.callee;
            let args = path.node.arguments;
            if (args.length !== 2) return;
            if (args[1] === undefined) return;
            // console.log('xxx', callee.name)
            // console.log(generator(path.node).code)
            if (generator(path.node).code.indexOf('(1277, 1264)') > -1) debugger
            if (funcTemp[callee.name]) {

                let arggs = [];
                if (types.isBinaryExpression(args[0]) || types.isBinaryExpression(args[1])) {
                    let code22 = generator(path.parent).code;
                    // console.log(code22)
                    try {
                        let tName = path.parentPath.parentPath.parent.id.name;
                        eval(`funcTemp.${tName} = function (r, n) {
                            return funcTemp.${generator(path.node).code}
                        }`)
                        // console.log(`funcTemp.${tName} = function (r, n) {
                        //     return funcTemp.${generator(path.node).code}
                        // }`)
                    } catch (e) {
                    }
                    return;
                }
                if (types.isNumericLiteral(args[0])) {
                    // let res = funcs[callee.name](arguments[0].value, arguments[1].value)
                    try {
                        arggs[0] = args[0].value
                        // console.log(callee.name, args[0].value,args[1].value)
                        // let res = funcTemp[callee.name](args[0].value, args[1].value)
                        // console.log(callee.name, args[0].value,args[1].value, res)
                        // if (!res) return
                        // path.replaceWith(types.StringLiteral(res))
                    } catch (e) {
                    }
                    // if (id.name === 'zo') {

                    // console.log(arguments[0].value, res)
                    // }
                }
                if (types.isUnaryExpression(args[0]) && args[0].operator === '-') {
                    arggs[0] = -args[0].argument.value
                }

                if (types.isNumericLiteral(args[1])) {
                    // let res = funcs[callee.name](arguments[0].value, arguments[1].value)
                    try {
                        arggs[1] = args[1].value
                        // console.log(callee.name, args[0].value,args[1].value)
                        // let res = funcTemp[callee.name](args[0].value, args[1].value)
                        // console.log(callee.name, args[0].value,args[1].value, res)
                        // if (!res) return
                        // path.replaceWith(types.StringLiteral(res))
                    } catch (e) {
                    }
                    // if (id.name === 'zo') {

                    // console.log(arguments[0].value, res)
                    // }
                }
                if (types.isUnaryExpression(args[1]) && args[1].operator === '-') {
                    arggs[1] = -args[1].argument.value
                }
                if (arggs.length == 2) {
                    try {
                        let res = funcTemp[callee.name](arggs[0], arggs[1])
                        console.log(callee.name, arggs[0], arggs[1], res)
                        if (!res) return
                        path.replaceWith(types.StringLiteral(res))
                    } catch (e) {
                    }
                }


            }

        }
    })
}


// console.log(keys2 + '')
console.log(funcs)

function t() {
    return Date.now();
}

var i = function () {
    try {
        if (atob && "test" === atob("dGVzdA==")) return atob;
    } catch (t) {
    }

    function t(t) {
        this.message = t;
    }

    t.prototype = new Error(), t.prototype.name = "InvalidCharacterError";
    return function (e) {
        var n = String(e).replace(/[=]+$/, "");
        if (n.length % 4 == 1) throw new t("'atob' failed: The string to be decoded is not correctly encoded.");
        for (var r, i, a = 0, o = 0, c = ""; i = n.charAt(o++); ~i && (r = a % 4 ? 64 * r + i : i, a++ % 4) ? c += String.fromCharCode(255 & r >> (-2 * a & 6)) : 0) i = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(i);
        return c;
    };
}();

function o(n) {
    var r = t();
    for (var c = i(n), u = "", l = 0; l < c.length; ++l) {
        var s = "j6yKtVh".charCodeAt(l % 7);
        u += String.fromCharCode(s ^ c.charCodeAt(l));
    }
    return u;
}

traverse(ast, {
    VariableDeclaration(path) {
        let {declarations} = path.node;
        let scope = path.scope;
        if (declarations.length !== 1) return;
        let declaration = declarations[0]
        let {id, init} = declaration;
        if (!init) return
        if (!types.isIdentifier(init)) return;
        if (init.name === 'u') {
            let binding = scope.getBinding(id.name);
            if (id.name === 'xs') {
                debugger
            }
            if (!binding) return;
            console.log(id.name, init.name, binding.references)

            for (const referencePath of binding.referencePaths) {
                // console.log(referencePath);
                console.log(generator(referencePath.parent).code)
                // console.log(referencePath.parentPath.type)

                if (types.isCallExpression(referencePath.parent)) {
                    let {callee, arguments} = referencePath.parent;

                    if (arguments.length === 1 && types.isStringLiteral(arguments[0])) {
                        let res = o(arguments[0].value)
                        // if (id.name === 'xs') {
                        //
                        console.log(generator(referencePath.parent).code, res)
                        // }
                        referencePath.parentPath.replaceWith(types.StringLiteral(res))
                    }
                } else {

                }
            }
        }

    }
})
traverse(ast, {
    CallExpression(path) {

        // console.log(referencePath.parentPath.type)

        let {callee, arguments} = path.node;
        if (!types.isIdentifier(callee))return;
        if (arguments.length === 1 && types.isStringLiteral(arguments[0])
         && arguments[0].value.length < 50) {
            try {
                let res = o(arguments[0].value)
                // if (id.name === 'xs') {
                //
                console.log(generator(path.node).code, res)
                // }
                path.replaceWith(types.StringLiteral(res))
            } catch (e) {
            }
        }
    }
})

//end
console.timeEnd("处理完毕，耗时");


code = generator(ast, opts = {jsescOption: {"minimal": true}}).code;

fs.writeFile(decodeFile, code, (err) => {
});