慢更费脑!!! 有一起讨论的首页小企鹅
参考文章系列
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~:`
网友评论