反编译腾讯vmp 继续学习的过程 多翻译几个vmp 学习 看看他们的是怎么编译的 写一个自己的vmp
1 2 3 4 5 6 function __TENCENT_CHAOS_VM (U, T, g, D, j, E, K, w ) { }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 for (0 ; ;) try { for (var B = !1 ; !B;) { let now = U; if (now === -1 ) { break } let op = T[U++]; 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 用来处理未知的指令 从最第一个指令开始
1 2 3 4 5 6 7 8 9 10 11 12 13 case 54 : D.length = T[U++]; break ;case 10 : var l = T[U++]; D[l] = D[l] === undefined ? [] : D[l]; break ;case 41 : U = T[U++];
下一个地方是vmp的函数反编译了 拿出来说
1 2 3 4 5 6 7 8 9 10 11 12 13 case 31 : 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 (B = 0 ; B < O; B++) Q[B] = T[U++]; D.push (function C ( ) { 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
1 2 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就有这个处理逻辑了
1 2 3 4 5 6 7 8 9 10 case 58 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 希望可以顺利一些吧
欢迎关注我的公众号 谢谢大家