反编译抖音 a_bogus vmp

接上篇的继续 反编译 vmp 来进行学习

抖音的不太一样的点在于 他的vmp代码是分散的
好几段代码都是vmp的 然后指令对应的操作还不一样 就很蛋疼…
而且 指令对应的操作也是if else 还有三元表达式形式的 不太好找位置

第一步 看vmp代码结构

484e4f4a403f524300033604d6dbeab10000045d18187b
他通过一系列操作把这个长字符串转成了操作指令集

        for (var g = []; ;) try {
            var m = i[r++];
            // i 就是上面的长字符串处理后的结果
            if (m < 37) if (m < 18) if (m < 7) m < 3 ? p[++d] = 0 === m || null : 3 === m ? (c = i[r++], p[++d] = c << 24 >> 24) : (c = ((c = ((c = i[r++]) << 8) + i[r++]) << 8) + i[r++], p[++d] = (c << 8) + i[r++]); else if (m < 13) 7 === m ? (c = (i[r] << 8) + i[r + 1], r += 2, p[++d] = o[c]) : p[++d] = void 0; else if (m < 14) p[++d] = {}; else if (14 === m) c = (i[r] << 8) + i[r + 1], r += 2, s = o[c], u = p[d--], p[d][s] = u; else {
                for (s = i[r++], u = i[r++], b = v; s > 0; --s) b = b.p;
                p[++d] = b[u]
            } else if (m < 28) if (m < 20) 18 === m ? (c = (i[r] << 8) + i[r + 1], r += 2, s = o[c], p[d] = p[d][s]) : (s = p[d--], p[d] = p[d][s]); else if (m < 22) {
                for (s = i[r++], u = i[r++], b = v; s > 0; --s) b = b.p;
                b[u] = p[d--]
            } else if (22 === m) s = p[d--], u = p[d--], b = p[d--], u[s] = b; else {
                for (s = i[r++], u = i[r++], b = v, b = v; s > 0; --s) b = b.p;
                p[++d] = b, p[++d] = u
            } else m < 33 ? 28 === m ? (s = p[d--], p[d] %= s) : p[d] = -p[d] : m < 35 ? (s = p[d--], b = (u = p[d--])[s]++, p[++d] = b) : 35 === m ? (s = p[d--], p[d] = p[d] == s) : (s = p[d--], p[d] = p[d] != s); else if (m < 58) m < 51 ? m < 39 ? 37 === m ? (s = p[d--], p[d] = p[d] === s) : (s = p[d--], p[d] = p[d] !== s) : m < 44 ? (s = p[d--], p[d] = p[d] < s) : 44 === m ? (s = p[d--], p[d] = p[d] >> s) : p[d] = !p[d] : m < 53 ? 51 === m ? (c = (c = (i[r] << 8) + i[r + 1]) << 16 >> 16, r += 2, p[d] ? --d : r += c) : (c = (c = (i[r] << 8) + i[r + 1]) << 16 >> 16, r += 2, p[d] ? r += c : --d) : m < 54 ? (s = p[d--], (u = p[d--])[s] = p[d]) : 54 === m ? (s = p[d--], p[d] = p[d] in s) : p[d] = void 0; else if (m < 68) if (m < 64) 58 === m ? p[d] = typeof p[d] : (c = i[r++], s = p[d--], (u = function e() {
                var r = e._v;
                return (0, e._u)(r[0], arguments, r[1], r[2], this)
            })._v = [s, c, v], u._u = e, p[++d] = u); else {
                if (m < 66) throw s = p[d--];
                if (66 === m) {
                    for (s = p[d--], u = null; b = g.pop();) if (2 === b[0] || 3 === b[0]) {
                        u = b;
                        break
                    }
                    if (u) r = u[2], u[0] = 0, g.push(u); else {
                        if (!h) return s;
                        r = h[1], f = h[2], v = h[3], g = h[4], p[++d] = s, h = h[0]
                    }
                } else d -= c = i[r++], u = p.slice(d + 1, d + c + 1), s = p[d--], b = p[d--], s._u === e ? (s = s._v, h = [h, r, f, v, g], r = s[0], null == b && (b = function () {
                    return this
                }()), f = b, (v = [u].concat(u)).length = Math.min(s[1], c) + 1, v.p = s[2], g = []) : (l = s.apply(b, u), p[++d] = l)
            } else if (m < 71) if (68 === m) {
                for (c = i[r++], b = [void 0], l = c; l > 0; --l) b[l] = p[d--];
                u = p[d--], l = new (s = Function.bind.apply(u, b)), p[++d] = l
            } else r += 2 + (c = (c = (i[r] << 8) + i[r + 1]) << 16 >> 16); else m < 73 ? (c = (c = (i[r] << 8) + i[r + 1]) << 16 >> 16, r += 2, (s = p[d--]) || (r += c)) : 73 === m ? --d : (s = p[d], p[++d] = s)
        } catch (e) {
            for (; (c = g.pop()) && !c[0];) ;
            if (!c) {
                e:for (; h;) {
                    for (s = h[4]; c = s.pop();) if (c[0]) break e;
                    h = h[0]
                }
                if (!h) throw e;
                r = h[1], f = h[2], v = h[3], g = h[4], h = h[0]
            }
            1 === (s = c[0]) ? (r = c[2], c[0] = 0, g.push(c), p[++d] = e) : 2 === s ? (r = c[2], c[0] = 0, g.push(c)) : (r = c[3], c[0] = 2, g.push(c), p[++d] = e)

首先要简化 他那一大堆 if else 变成 switch case 方便后续的操作
在这里插入图片描述

变成这样就好了 方便后续的操作

第二步 看一些关键的变量

解释都在代码里了

var c, s, u, b, l, d = -1, p = [], h = null, v = [t];
// 这些变量分别代表了不同的含义 比如 栈 函数变量 函数入参 寄存器 等
// 需要注意反编译过程中的 变量作用域问题
for (s = Math.min(t.length, n), u = 0; u < s; ++u) v.push(t[u]);
v.p = a;

第三步 开始反编译

反编译函数

这是源代码中定义函数的地方

    i = r[f++];// i 是函数入参数量
    l = o[p--];// l是函数起点指令下标
    console.log('newFunc',now,l,i);
    (n = function e() {
        var f = e._v;
        return (0, e._u)(f[0], arguments, f[1], f[2], this);
    })._v = [l, i, h];
    n._u = e;
    o[++p] = n;
    console.log(p)

反编译成这样

i = r[f++];
l = o[p--];
let body63 = [];
// (n = function e() {
//     var f = e._v;
//     return (0, e._u)(f[0], arguments, f[1], f[2], this);
// })._v = [l, i, h];
// if (now === 1192)debugger
console.log('newFunc', l , i, h.idx, p+1) 
let func63 = types.identifier('func' + +l)
// if (s == 1582){
let hCopy = h.slice();
let args = types.identifier('arguments');
args.idx = h.idx+1
e(l, args, i, h, this,body63, -1) // 自己处理了一些东西
// h = hCopy.slice();
let v61 = types.functionDeclaration(func63, [], types.blockStatement(body63))
body.push(v61)
// func63._u = e;
func63._v = [l, i, h];
o[++p] = func63;
反编译判断
 i = (i = (r[f] << 8) + r[f + 1]) << 16 >> 16;
f += 2;
if (o[p]) {
    f += i; // 跳过一部分指令
} else {
    --p;
}
i = (i = (r[f] << 8) + r[f + 1]) << 16 >> 16;
f += 2;
let body52 = [];
// 这种不是函数的反编译 需要处理好作用域问题 否则会报错
e(f, h, c, b, a,body52, i-2-1, false, o,p) 
body.push(types.ifStatement(o[p], types.blockStatement(body52)))

最终结果

var tmp2248 = {};
    var tmp2249 = X["apply"](true, []);
    var tmp2250 = func618["apply"](true, [tmp2248, tmp2249]);
    var tmp2251 = {};
    var tmp2252 = {};
    var tmp2253 = navigator["platform"];
    tmp2252["platform"] = tmp2253;
    var tmp2254 = func618["apply"](true, [tmp2250, tmp2251, tmp2252]);
    tmp2018 = tmp2254;
    var tmp2255 = func1198["apply"](true, [tmp2254]);
    tmp2019 = tmp2255;
    var tmp2256 = func1086["apply"](true, [tmp2255]);
    tmp2020 = tmp2256;
    var tmp2257 = tmp2256["length"];
    tmp2021 = tmp2257;
    var tmp2258 = 255;
    var tmp2259 = tmp2257 & tmp2258;
    tmp2023 = tmp2259;
    var tmp2260 = 8;
    var tmp2261 = tmp2257 >> tmp2260;
    var tmp2262 = 255;
    var tmp2263 = tmp2261 & tmp2262;
    tmp2027 = tmp2263;
    var tmp2264 = "";
    tmp2028 = tmp2264;
    var tmp2265 = func1086["apply"](true, [tmp2264]);
    tmp2029 = tmp2265;
    var tmp2266 = tmp2265["length"];
    tmp2030 = tmp2266;
    var tmp2267 = 255;
    var tmp2268 = tmp2266 & tmp2267;
    tmp2032 = tmp2268;
    var tmp2269 = 8;
    var tmp2270 = tmp2266 >> tmp2269;
    var tmp2271 = 255;
    var tmp2272 = tmp2270 & tmp2271;
    tmp2036 = tmp2272;
    var tmp2273 = tmp2100 ^ tmp2112;
    var tmp2274 = tmp2273 ^ tmp2139;
    var tmp2275 = tmp2274 ^ tmp2152;
    var tmp2276 = tmp2275 ^ tmp2168;
    var tmp2277 = tmp2276 ^ tmp2180;
    var tmp2278 = tmp2277 ^ tmp2184;
    var tmp2279 = tmp2278 ^ tmp2188;
    var tmp2280 = tmp2279 ^ tmp2116;
    var tmp2281 = tmp2280 ^ tmp2143;
    var tmp2282 = tmp2281 ^ tmp2156;
    var tmp2283 = tmp2282 ^ tmp2172;
    var tmp2284 = tmp2283 ^ tmp2182;
    var tmp2285 = tmp2284 ^ tmp2186;
    var tmp2286 = tmp2285 ^ tmp2190;
    var tmp2287 = tmp2286 ^ tmp2120;
    var tmp2288 = tmp2287 ^ tmp2147;
    var tmp2289 = tmp2288 ^ tmp2160;
    var tmp2290 = tmp2289 ^ tmp2176;
    var tmp2291 = tmp2290 ^ tmp2122;
    var tmp2292 = tmp2291 ^ tmp2149;
    var tmp2293 = tmp2292 ^ tmp2164;
    var tmp2294 = tmp2293 ^ tmp2178;
    var tmp2295 = tmp2294 ^ tmp2194;
    var tmp2296 = tmp2295 ^ tmp2198;
    var tmp2297 = tmp2296 ^ tmp2202;
    var tmp2298 = tmp2297 ^ tmp2204;
    var tmp2299 = tmp2298 ^ tmp377;
    var tmp2300 = tmp2299 ^ tmp2210;
    var tmp2301 = tmp2300 ^ tmp2217;
    var tmp2302 = tmp2301 ^ tmp2128;
    var tmp2303 = tmp2302 ^ tmp2135;
    var tmp2304 = tmp2303 ^ tmp2222;
    var tmp2305 = tmp2304 ^ tmp2226;
    var tmp2306 = tmp2305 ^ tmp2230;
    var tmp2307 = tmp2306 ^ tmp2232;
    var tmp2308 = tmp2307 ^ tmp2235;
    var tmp2309 = tmp2308 ^ tmp2239;
    var tmp2310 = tmp2309 ^ tmp2243;
    var tmp2311 = tmp2310 ^ tmp2247;
    var tmp2312 = tmp2311 ^ tmp2259;
    var tmp2313 = tmp2312 ^ tmp2263;
    var tmp2314 = tmp2313 ^ tmp2268;
    var tmp2315 = tmp2314 ^ tmp2272;
    tmp2079 = tmp2315;
    var tmp2316 = [tmp2100, tmp2112, tmp2222, tmp2139, tmp2152, tmp2168, tmp2239, tmp2180, tmp2184, tmp2226, tmp2188, tmp2116, tmp2143, tmp2230, tmp2232, tmp2156, tmp2172, tmp2235, tmp2182, tmp2186, tmp2190, tmp2120, tmp2147, tmp2160, tmp2247, tmp2176, tmp2122, tmp2149, tmp2164, tmp2178, tmp2194, tmp2198, tmp2243, tmp2202, tmp2204, tmp377, tmp2210, tmp2217, tmp2128, tmp2135, tmp2259, tmp2263, tmp2268, tmp2272];
    var tmp2317 = tmp2316["concat"];
    var tmp2318 = func120["apply"](true, [tmp2256]);
    var tmp2319 = func120["apply"](true, [tmp2265]);
    var tmp2320 = [tmp2315];
    var tmp2321 = tmp2317["apply"](tmp2316, [tmp2318, tmp2319, tmp2320]);
    tmp2085 = tmp2321;
    var tmp2322 = func1382["apply"](true, [tmp2099]);
    var tmp2323 = func1538["apply"](true, [tmp2108]);
    tmp2322 += tmp2323;
    var tmp2324 = String["fromCharCode"];
    var tmp2325 = 121;
    var tmp2326 = tmp2324["apply"](String, [tmp2325]);
    var tmp2327 = String["fromCharCode"];
    var tmp2328 = tmp2327["apply"];
    var tmp2329 = tmp2328["apply"](tmp2327, [true, tmp2321]);
    var tmp2330 = ee["apply"](true, [tmp2326, tmp2329]);
    tmp2322 += tmp2330;
    tmp2086 = tmp2322;
    var tmp2331 = "s4";
    var tmp2332 = re["apply"](true, [tmp2322, tmp2331]);
    return tmp2332;

大概就是这样 一共三千多行 可以很明白的看到他的执行逻辑了

总结

他的麻烦点就是变量作用域问题 其他的按部就班的按照他的代码逻辑去改成ast节点的操作就行了

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

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值