jsvmp
混淆的另一种常见毒瘤:jsvmp。jsvmp:全称 Virtual Machine based code Protection for JavaScript,即 JS 代码虚拟化保护方案。
八股文很多,但是了解很必要! 如果要是不理解一些运行基础的话,它理解起来会比较吃力。下面,我们浅浅的给大家介绍一下,目的就是让大家心里先有个数,jsvmp它到底在干些什么。以后我们再说处理它的方法。
首先,常见的jsvmp的实现方法,你可以理解为:就是自己写了一段代码解释器,用来解释自己的代码
而这个自己的代码:可以是密文,也可以是所谓的明文。
我们先不用管所谓的 寄存器 指针 指令 是什么东西。先给大家分析一段简单的代码。
var b = 1000;
var c = 1000;
var d = a + b;
var e = d + c;
js
上面这段代码,我们现在去理解它做了什么;
用我们人类的语言对它进行翻译(我们先不考虑变量提升那些乱七八糟的事儿):
- 声明一个变量 a, 并且给a赋值 1000;
- 声明一个变量 b, 并且给b赋值 1000;
- 声明一个变量 c, 并且给c赋值 1000;
- 声明一个变量 d, 计算 a+b 的值, 将值赋值给 d;
- 声明一个变量 e, 计算 d+c 的值, 将值赋值给 d;
那么下面,我们在把下面的分段再翻译成代码:
var a;
a = 1000;
var b;
b = 1000;
var c;
c = 1000;
var d;
? = a + b;
d = ?;
var e;
e = d + c;
js
OK, 我们完成了,下面我们开始定义指令
我们假设赋值指令为 66, 加和指令为 88,声明指令为 110(爱取什么名字取什么名字)
如果按照从上到下的顺序,我们就可以将他们的操作变成指令性的[用|分割左侧和右侧]
110 --- var | a
66 --- a | 1000
110 --- var | b
66 --- b | 1000
110 --- var | c
66 --- c | 1000
110 --- var | d
88 --- a | b -----> ?
66 --- d | ?
110 --- var | e
88 --- d | c -----> ?
66 --- e | ?(此处的d 与 c的和)
js
下一步,我们将每一步,都压入一个数组中,我们就得到了这样一个数组:
_stack = [
[110, 'var', 'a'],
[66, 'a', 1000],
[110, 'var', 'b'],
[66, 'b', 1000],
[110, 'var', 'c'],
[66, 'c', 1000],
[110, 'var', 'd'],
[88, 'a', 'b'],
[66, 'd', '?'],
[110, 'var', 'e'],
[88, 'd', 'c'],
[66, 'e', '?'],
]
js
然后我们就可以靠接下来这个数组去完成我们刚才的代码了,其实这个代码写起来就相当简单了
var register; // 这个就当做是问号的存储位置 即寄存器
var variable = {}; // 这个就当做是var变量的存储位置。由于没有其他声明方式的存在,所就不写其他的了
for(let i=0;i<_stack.length;i++){
instruct = _stack[i][0] // 我这么写是让大家看得懂,真正的时候,人家才不会那么好心
left = _stack[i][1] // 我这么写是让大家看得懂,真正的时候,人家才不会那么好心
right = _stack[i][2] // 我这么写是让大家看得懂,真正的时候,人家才不会那么好心
if(instruct === 110){
variable[right] = '';
}
if(instruct === 66){
if(right === '?'){
variable[left] = register;
}
else{
variable[left] = right;
}
}
if(instruct === 88){
register = variable[left] + variable[right];
}
}
js
这样代码就写完了,然后我们在简单的做一些加工, 封装到自执行函数里,注释去掉,再压缩一下
!function(_stack){var register;var variable={};for(let i=0;i<_stack.length;i++){instruct=_stack[i][0];left=_stack[i][1];right=_stack[i][2];if(instruct===110){variable[right]=''}if(instruct===66){if(right==='?'){variable[left]=register}else{variable[left]=right}}if(instruct===88){register=variable[left]+variable[right]}};console.log(variable)}([[110,'var','a'],[66,'a',1000],[110,'var','b'],[66,'b',1000],[110,'var','c'],[66,'c',1000],[110,'var','d'],[88,'a','b'],[66,'d','?'],[110,'var','e'],[88,'d','c'],[66,'e','?']])
js
目前我们就用这样的代码实现起初的效果,这样的代码调试起来会非常困难。
还可以思考以下问题:
这还是基于我只写了三个操作
那其他的呢。所有的操作都压成这个样子呢?
我在把传进来的数组按照某种逻辑随机呢?
我把数组分类开来呢?
可操作空间是不是太多啦
你懂我的意思把【狗头】