反编译腾讯vmp

反编译腾讯vmp

继续学习的过程 多翻译几个vmp 学习
看看他们的是怎么编译的 写一个自己的vmp

 function __TENCENT_CHAOS_VM(U, T, g, D, j, E, K, w) {
    // U指令起点
    // T是指令list
    // g是函数this 或window对象
    // D是内部变量和栈
 }
for (0; ;)
            try {
                for (var B = !1; !B;) {
                    let now = U;
                    if (now === -1) {
                        break
                    }
                    let op = T[U++];
                    // Q是一个大的函数数组 可以转为switch case 结构方便执行
                    B = Q(op, start);
                }
                // 获取返回值的地方
                var res = l ? (D.pop(), D.slice(3 + __TENCENT_CHAOS_VM.v)) : D.pop();
                return res
            } catch (c) {
                0;
                var Y = O.pop();
                if (Y === undefined)
                    throw c;
                W = c,
                    U = Y[0],
                    D.length = Y[1],
                Y[2] && (D[Y[2]][0] = W)
            }
Q

在这里插入图片描述

在这里可以看到Q函数的结构
最开始的地方给switch 加个default 用来处理未知的指令
从最第一个指令开始

// 54,3,10,2,41,1518,57,54,6,10,2,10,3,10,4,10,5,41,239,54,54,7,10,2,10,3,10,4,65,5,2,3,47,37,25,40,43,41,64,65,43,65,5,2,3,47,22,57,101,57,120,57,112,57,111,57,114,57,116,57,115,38,37,5,65,4,65,5,2,3,47,22,57,79,57,98,57,106,57,101,57,99,57,116,63,36,0,7,22,57,105,17,2,3,39,43,43,7,22,57
case 54:
    // 扩充栈长度
    D.length = T[U++];
    break;
case 10:
    // 初始化变量固定位置
    var l = T[U++];
    D[l] = D[l] === undefined ? [] : D[l];
    break;
case 41:
    // 直接跳转 这个在ifelse 和while循环中 都要加处理
    U = T[U++];

下一个地方是vmp的函数反编译了 拿出来说

case 31:
    // 构造一个函数部分
    // 第一个for 是处理函数要用到的其他地方定义的变量
    for (var W = T[U++], A = [], l = T[U++], O = T[U++], Q = [], B = 0; B < l; B++) A[T[U++]] = D[T[U++]];
    // 第二个for是参数入参长度和位置
    for (B = 0; B < O; B++) Q[B] = T[U++];
    D.push(function C() {
        // 这里是实际函数vmp执行的地方
        var l = A.slice(0);
        l[0] = [this], l[1] = [arguments], l[2] = [C];
        for (var O = 0; O < Q.length && O < arguments.length; O++) 0 < Q[O] && (l[Q[O]] = [arguments[O]]);
        return __TENCENT_CHAOS_VM(W, T, g, l, j, E, K, w);
    });

照着这么处理 先跳过函数反编译的地方 大概可以得到一个 这样的代码
在这里插入图片描述

然后继续看函数的反编译
反编译代码
在这里插入图片描述

然后看节点22的处理
这里的代码是为了优化反编译结果 连续生成一个字符串的地方
在这里插入图片描述

其他的就不一一介绍了 按部就班就可以了

再需要注意的就是处理 if-else while break continue try-catch-finally

先看看ifelse 和while

var l = T[U++];
D[D.length - 1] && (U = l);

这个部分的话 需要看后续跳转到哪里
比如D[D.length-1] = true
会跳到l 那么 l开始就是if 部分
继续走U+1 就是else 部分
然后看后面会不会在跳到当前U的上边 这个流程就可能是while的更新部分
循环这里大概就是这样去处理了

try catch

这里基本就是你在代码里搜一下 有没有 try
有的话 这个vmp就有这个处理逻辑了

case 58 
// 这里对应后面的Y 代表出现了异常后该怎么走
    O.push([T[U++], D.length, T[U++]]);
catch (c) {
    0;
    var Y = O.pop();
    if (Y === undefined) throw c;
    W = c, U = Y[0], D.length = Y[1], Y[2] && (D[Y[2]][0] = W);
}

在这里插入图片描述

基本就是这样处理了

看看结果

在这里插入图片描述

总结

这个的反编译过程就是这样了
我认为的难点就是变量和作用域跨函数的处理
还有循环的判断 否则会死循环一直走某些指令
下一步 想自己实现一个vmp 希望可以顺利一些吧

欢迎关注我的公众号 谢谢大家

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值