美文网首页
尝试还原jsvmp-1

尝试还原jsvmp-1

作者: 周周周__ | 来源:发表于2023-04-06 00:06 被阅读0次

慢更费脑!!! 有一起讨论的首页小企鹅

参考文章系列
1、某乎x96参数与jsvmp初体验
2、给"某音"的js虚拟机写一个编译器
3、如何用AST还原某音的JSVMP
4、VM防护介绍及企鹅滑块分析

本系列重在尝试,思路不一定对

主要的参考还是上述参考文章2
以大佬的开源项目的进行测试还原。

1、测试效果

总结:每一个代码块 即js中函数的{}或者AST的BlockStatement 会进入到一个jsvmp的循环中,这也是为什么我们能看到那么多次进入到循环

简单加翻译日志(20230425)

待加密代码

"function add(a, b){return a+b}; add(1, 3);add(2, 3)"

加密后密文,运行逻辑在最后边代码块

var codestr = `y'l l!b+ s1l1z.!.#["c~2l1z.".#["c~3`

输出日志信息

修改作用域,将参数前置到当前vm_var
将var 0 = {} 放入vm_var
y'l l!b+ s1l1z.!.#["c~2l1z.".#["c~3
初始化函数
声明变量var_ 17 = [Function: anonymous_function] {
  body_str: 'l l!b+ ',
  entry: [Function: vmRun]
}
创建函数: var_17
取出var_ 17   放入vm_stack: [
  [Function: anonymous_function] {
    body_str: 'l l!b+ ',
    entry: [Function: vmRun]
  }
]
将值 1 入栈
将值 3 入栈
由此进入函数内部开始执行。。。。。
修改作用域,将参数前置到当前vm_var
将var 0 = 1 放入vm_var
将var 1 = 3 放入vm_var
l l!b+
取出var_ 0   放入vm_stack: [ 1 ]
取出var_ 1   放入vm_stack: [ 1, 3 ]
计算结果并放进堆栈: [ 4, 3 ]
结束当前循环, 并将结果返回 4
取出var_ 17   放入vm_stack: [
  4,
  [Function: anonymous_function] {
    body_str: 'l l!b+ ',
    entry: [Function: vmRun]
  },
  [ 1, 3 ],
  3
]
将值 2 入栈
将值 3 入栈
由此进入函数内部开始执行。。。。。
修改作用域,将参数前置到当前vm_var
将var 0 = 2 放入vm_var
将var 1 = 3 放入vm_var
l l!b+
取出var_ 0   放入vm_stack: [ 2 ]
取出var_ 1   放入vm_stack: [ 2, 3 ]
计算结果并放进堆栈: [ 5, 3 ]
结束当前循环, 并将结果返回 5
[]
[89,83,76,90,14,14,59,67,94,76,90,14,14,59,67,94,null]

待运行代码块

var codestr = `上边密文`
let deepClone = function (obj) {
    let _tmp = JSON.stringify(obj);//将对象转换为json字符串形式
    let result = JSON.parse(_tmp);//将转换而来的字符串转换为原生js对象
    return result;
};

function vmExpression_single_calc(symbol, opNum1) {
    switch (symbol) {
        case "!":
            return !opNum1
        case "+":
            return +opNum1
        case "-":
            return -opNum1
        case "~":
            return ~opNum1
        default:
            return undefined
    }
}

function vmExpression_calc(symbol, opNum2, opNum1) {
    switch (symbol) {
        case "!":
            return !opNum1
        case "*":
            return opNum1 * opNum2
        case "/":
            return opNum1 / opNum2
        case "%":
            return opNum1 % opNum2
        case "+":
            return opNum1 + opNum2
        case "-":
            return opNum1 - opNum2
        case "<<":
            return opNum1 << opNum2
        case ">>":
            return opNum1 >> opNum2
        case ">>>":
            return opNum1 >>> opNum2
        case ">":
            return opNum1 > opNum2
        case "<":
            return opNum1 < opNum2
        case ">=":
            return opNum1 >= opNum2
        case "<=":
            return opNum1 <= opNum2
        case "==":
            return opNum1 == opNum2
        case "===":
            return opNum1 === opNum2
        case "!==":
            return opNum1 !== opNum2
        case "!=":
            return opNum1 != opNum2
        case "&":
            return opNum1 & opNum2
        case "~":
            return ~opNum
        case "^":
            return opNum1 ^ opNum2
        case "|":
            return opNum1 | opNum2
        case "&&":
            return opNum1 && opNum2
        case "||":
            return opNum1 || opNum2
        case "=":
            return opNum1 = opNum2
        case "*=":
            return opNum1 *= opNum2
        case "/=":
            return opNum1 /= opNum2
        case "%=":
            return opNum1 %= opNum2
        case "&=":
            return opNum1 &= opNum2
        case "+=":
            return opNum1 += opNum2
        case "-=":
            return opNum1 -= opNum2
        case "<<=":
            return opNum1 <<= opNum2
        case ">>=":
            return opNum1 >>= opNum2
        case "^=":
            return opNum1 ^= opNum2
        case "|=":
            return opNum1 ^= opNum2
        default:
            return undefined
    }
}

function init_vm() {

    var e = {}

    var instance_run = (function anonymous() {
        function vmExpression(symbol, opNum2, opNum1) {
            //var raw = pthis_Functions("x,y", "return x " + symbol + " y")(opNum1, opNum2)
            var now = vmExpression_calc(symbol, opNum2, opNum1)
            return now
        }

        function vmExpression_single(symbol, opNum) {
            //var raw = pthis_Functions("x", "return " + symbol + "x")(opNum)
            var now = vmExpression_single_calc(symbol, opNum)
            return now
        }

        function vmNewObject(vm_stack, obj_point, argNum) {
            //return (k[argNum] || (k[argNum] = pthis_Functions("x,y", "return new x[y](" + Array(argNum + 1).join(",x[++y]").substr(1) + ")")))(vm_stack, obj_point)
        }

        function vmEnter(codes, argumentss, vars) {
            var n,
                t,
                i,
                s = {}
            b = s.d = vars ? vars.d + 1 : 0;
            for (s["$" + b] = s, t = 0; t < b; t++) {
                s[n = "$" + t] = vars[n];

                //������һ�����ȡ, Ϊ�˼��ݱ��뷽ʽ
                for (i in vars) {
                    if (parseInt(i) >= 15 && i.indexOf('$') < 0)
                        s[i] = vars[i]
                }

            }
            console.log("修改作用域,将参数前置到当前vm_var")
            for (t = 0, b = s.length = argumentss.length; t < b; t++) {
                console.log("将var", t, "=", argumentss[t], "放入vm_var")
                s[t] = argumentss[t];
            }
            return vmRun(codes, 0, s)
        }

        function vmRun(codes, index, vm_vars) {
            function vm_push(e) {
                vm_stack[vm_esp++] = e
            }

            function vm_substring() {
                g = codes.charCodeAt(index++) - 32
                var str = codes.substring(index, index += g)
                return str
            }

            function call() {
                try {
                    y = vmRun(codes, index, vm_vars)
                } catch (e) {
                    h = e,
                        y = call //�쳣��
                }
            }

            var num_znb = [];
            var ast_body = []; // 代码块
            var my_stack = []; // 记录堆栈的值
            var my_esp = 0; // 记录堆栈中数据操作的索引
            var my_var_vm = []; // 记录变量的堆栈
            console.log(codes)
            for (var h, y, d, g, vm_stack = [], vm_esp = 0; ;) {
                g = codes.charCodeAt(index++) - 32
                num_znb.push(g)

                // console.log(g, vm_stack, vm_esp)
                // console.log("vm_vars:",vm_vars)

                if (Number.isNaN(g)) {
                    console.log(ast_body)
                    console.log(JSON.stringify(num_znb))
                    break
                }
                switch (g) {
                    case 1:
                        vm_push(!vm_stack[--vm_esp]);
                        break;
                    case 4:
                        vm_stack[vm_esp++] = vm_substring();

                        break;
                    case 5:
                        vm_push(function (e) {
                            var a = 0,
                                r = e.length; //ȡ����
                            return function () {
                                var c = a < r; //�жϳ����Ƿ����0
                                return c && vm_push(e[a++]), //�����߼���һ��û�з���ֵ�ĺ���, ���һ����undefined
                                    c
                            }
                        }
                        (vm_stack[--vm_esp]));

                        break;
                    case 6:
                        y = vm_stack[--vm_esp]
                        var func = vm_stack[--vm_esp]
                        var result = func(y)
                        vm_push(result);

                        break;
                    case 8: //���ú�������һ�ַ�ʽ
                        if (g = codes.charCodeAt(index++) - 32, //ȡ������VM�ֽ���
                            call(), //���ú���
                            index += g, //����ִ�����, eip+VM�ֽ���
                            g = codes.charCodeAt(index++) - 32,
                        y === vmRun) //y�Ƿ���ֵ
                            index += g;
                        else if (y !== call) {

                            return y; //����y
                        }

                        break; //�޷���ֵ
                    case 9:
                        vm_stack[vm_esp++] = vmRun;

                        break;
                    case 10:
                        vm_push(s(vm_stack[--vm_esp])); //����ִ�в�����, û��s����
                        break;
                    case 11:
                        y = vm_stack[--vm_esp],
                            x = vm_stack[--vm_esp],
                            vm_push(x + y);

                        break;
                    case 12:
                        for (y = vm_substring(), d = [], g = 0; g < y.length; g++)
                            d[g] = y.charCodeAt(g) ^ g + y.length;
                        str = String.fromCharCode.apply(null, d)
                        vm_push(str);

                        break;
                    case 13:
                        y = vm_stack[--vm_esp],
                            obj = vm_stack[--vm_esp][y]

                        //h = delete obj;
                        break;
                    case 14: // 将后一个值入栈
                        g = codes.charCodeAt(index++) - 32;
                        console.log("将值", g, "入栈")
                        vm_stack[vm_esp++] = g
                        ///////////////////////////////////////////
                        my_stack[my_esp++] = g
                        ///////////////////////////////////////////
                        break;
                    case 59: // 截取函数的参数放进数组,并放入堆栈
                        g = codes.charCodeAt(index++) - 32
                        var end = vm_esp
                        var begin = vm_esp -= g
                        ary = g ? vm_stack.slice(begin, end) : []
                        vm_push(ary);

                        break;
                    case 61:
                        var temp = vm_stack[--vm_esp][codes.charCodeAt(index++) - 32]
                        vm_push(temp)
                        //var index = vm_esp - 1;

                        break;
                    case 62:
                        g = vm_stack[--vm_esp]
                        vm_vars[0] = 65599 * vm_vars[0] + vm_vars[1].charCodeAt(g) >>> 0;

                        break;
                    case 65:
                        h = vm_stack[--vm_esp],
                            y = vm_stack[--vm_esp],
                            vm_stack[--vm_esp][y] = h;

                        break;
                    case 66: // 进行计算的位置
                        vm_push(vmExpression(codes[index++], vm_stack[--vm_esp], vm_stack[--vm_esp]));
                        console.log('计算结果并放进堆栈:', vm_stack)
                        ////////////////////////////////////////////////////
                        my_esp = vm_esp
                        var var_1 = my_stack[my_esp]
                        var var_2 = my_stack[--my_esp]
                        // 当不是变量赋值,是直接的数字时,需要判断
                        var test = var_2 + codes[index - 1] + var_1
                        my_stack[my_esp] = test
                        ////////////////////////////////////////////////////
                        break;
                    case 67: // 分别将函数和参数取出,并执行后将结果推进堆栈
                        y = vm_stack[--vm_esp]
                        d = vm_stack[--vm_esp]
                        g = vm_stack[--vm_esp]
                        console.log("由此进入函数内部开始执行。。。。。")
                        if (g.x === vmRun)
                            vm_push(vmEnter(g.y, y, vm_vars))
                        else
                            vm_push(g.apply(d, y))
                        break;
                    case 68:
                        var symbol;
                        g = codes[index++]
                        if (g < "<") {
                            index--
                            symbol = vm_substring()
                        } else
                            symbol = g + g
                        vm_push(vmExpression(symbol, vm_stack[--vm_esp], vm_stack[--vm_esp]));

                        break;
                    case 70:
                        vm_push(!1);

                        break;
                    case 71:
                        vm_stack[vm_esp++] = pthis;

                        break;
                    case 72:
                        vm_stack[vm_esp++] = +vm_substring();

                        break;
                    case 73:
                        vm_push(parseInt(vm_substring(), 36));

                        break;
                    case 75:
                        ////////////////////////////////////////////////////
                        if (vm_stack[vm_esp]) {
                            ast_body.push('if (' + my_stack[my_esp] + ')')
                        }


                        ////////////////////////////////////////////////////
                        if (vm_stack[--vm_esp]) {
                            index++;
                            break
                        }


                    case 74: //������������, ������ѭ�������
                        g = codes.charCodeAt(index++) - 32
                        g = g << 16 >> 16

                        index += g;
                        break;
                    case 76: // 将后一个code对应的变量追加vm_stack
                        var vars_idx = codes.charCodeAt(index) - 32;
                        vm_push(vm_vars[codes.charCodeAt(index++) - 32]);
                        console.log('取出var_',codes.charCodeAt(index - 1) - 32, "  放入vm_stack:", vm_stack)
                        //////////////////////////////////////////////////////
                        var znb_index = index - 1
                        my_esp = vm_esp - 1
                        my_stack[my_esp] = ("var_" + [codes.charCodeAt(znb_index) - 32])
                        //////////////////////////////////////////////////////

                        break;
                    case 77:
                        y = vm_stack[--vm_esp],
                            vm_push(vm_stack[--vm_esp][y]);

                        break;
                    case 78:
                        g = codes.charCodeAt(index++) - 32
                        vm_push(vmNewObject(vm_stack, vm_esp -= g + 1, g));

                        break;
                    case 79:
                        g = codes.charCodeAt(index++) - 32;
                        vm_push(vm_vars["$" + g]);

                        break;
                    case 81:
                        h = vm_stack[--vm_esp]
                        str = vm_substring()
                        vm_stack[--vm_esp][str] = h;

                        break;
                    case 82:
                        var str = vm_substring();
                        vm_push(vm_stack[--vm_esp][str]);

                        break;
                    case 83: // 将刚刚初始的值放进vm_vars
                        h = vm_stack[--vm_esp];
                        var vars_idx = codes.charCodeAt(index) - 32;
                        vm_vars[codes.charCodeAt(index++) - 32] = h;
                        console.log("声明变量var_",codes.charCodeAt(index-1) - 32, "=", h, )
                        /////////////////////////////////////////////
                        my_esp = vm_esp
                        if (codes.charCodeAt(index - 4) - 32 === 66) { // 上一步是计算
                            ast_body.push(
                                "var var_" + [codes.charCodeAt(index - 1) - 32] + "=" + my_stack[my_esp] + ';'
                            )
                        }
                        if (codes.charCodeAt(index - 4) - 32 === 14 || codes.charCodeAt(index - 4) - 32 === 76) { // 上一步是赋值,或者是其他
                            ast_body.push(
                                "var var_" + [codes.charCodeAt(index - 1) - 32] + "=" + h + ';'
                            )
                        }
                        if (num_znb.slice(-2)[0] === 89) { // 上一步是函数声明
                            console.log("创建函数:", "var_" + [codes.charCodeAt(index - 1) - 32])
                        }
                        /////////////////////////////////////////////
                        break;
                    case 84:
                        vm_stack[vm_esp++] = !0;

                        break;
                    case 85:
                        vm_stack[vm_esp++] = void 0;

                        break;
                    case 86:
                        vm_push(vm_stack[vm_esp - 1]);

                        break;
                    case 88:
                        h = vm_stack[--vm_esp],
                            y = vm_stack[--vm_esp],
                            vm_stack[vm_esp++] = h,
                            vm_stack[vm_esp++] = y;

                        break;
                    case 89:
                        console.log('初始化函数')
                        vm_push(function () {
                            function anonymous_function() {
                                return vmEnter(anonymous_function.body_str, arguments, vm_vars)
                            }

                            return anonymous_function.body_str = vm_substring(),
                                anonymous_function.entry = vmRun,
                                anonymous_function
                        }
                        ());

                        break;
                    case 90: //
                        vm_stack[vm_esp++] = null;

                        break;
                    case 91:
                        vm_stack[vm_esp++] = h;

                        break;
                    case 93:
                        h = vm_stack[--vm_esp];

                        break;
                    case 94: // 未知 还没走到条件内
                        if (vm_esp >= 1 && vm_stack[vm_esp - 1] != undefined) {
                            h = vm_stack[vm_esp - 1];
                            var vars_idx = codes.charCodeAt(index) - 32;
                            vm_vars[codes.charCodeAt(index++) - 32] = h;

                        } else
                            index++
                        break
                    case 95:
                        vm_push(parseFloat(vm_substring()));

                        break;
                    case 96: //
                        var a_idx = vm_stack[--vm_esp]
                        var ary = vm_stack[--vm_esp]
                        vm_push(ary[a_idx]);

                        break;
                    case 97:
                        var a_idx = vm_stack[--vm_esp]
                        var ary = vm_stack[--vm_esp]
                        var vlaue = vm_stack[--vm_esp]
                        ary[a_idx] = vlaue

                        break;
                    case 98:
                        vm_push(vmExpression_single(codes[index++], vm_stack[--vm_esp]));

                        break;
                    case 99:
                        var str = vm_stack[--vm_esp]
                        vm_push(global[str])

                    case 0: // 结束当前堆栈
                        console.log("结束当前循环, 并将结果返回", vm_stack[vm_esp-1])
                        return vm_stack[--vm_esp]; //����һ�����ʽ
                    default:

                        vm_push((g << 16 >> 16) - 16)
                }
            }
        }

        var pthis = global
        //pthis_Functions = pthis.Function
        var s = Object.keys || function (e) {
            var a = {},
                r = 0;
            for (var c in e)
                a[r++] = c;
            return a.length = r,
                a
        }
        var b = {};
        var k = {};
        return vmEnter
    })

    function init() {
        global.console = console;
        global.Date = Date;
        global.String = String;
        global.encodeURIComponent = encodeURIComponent;
        global.decodeURIComponent = decodeURIComponent;
        global.Array = Array;
        global.parseInt = parseInt;
        global.Math = Math;
        global.JSON = JSON;
        instance_run = instance_run()
        instance_run = instance_run(codestr, [e])
    }

    init()

}


init_vm()

var codestr = `y'l l!b+ s1y'l l!b- s4y@.!s5."s6l1zl5l6["c~7l4zl7l6["c~8s9l9z[ c~:`

相关文章

网友评论

      本文标题:尝试还原jsvmp-1

      本文链接:https://www.haomeiwen.com/subject/imbyddtx.html