小Mi Web JS 逆向.

寻深圳逆向/爬虫坑位 , wx:cjh-18888

https://account.xiaomi.com/

1.externalId 和 EUI

image-20220425100938980

image-20220425104652272

本菜菜喜欢用堆栈法, 所以找找堆栈。 跟着下图这样,一层层找,看看上下文。很快就可以看到有params的。

image-20220425101211057

在:1434下断点,然后重新进入一次调试.

image-20220425101328071

再继续从堆栈向上推.可以看到在:1560开始的case:8中十分的像是我们需要的东西.

image-20220425101512124

下断点.重新进来一次~,

O = h.encryptAes,
    j = O({
    externalId: s.email
}),
    v = j.encryptedParams,
    c.prev = 12,
    c.next = 15,
    r((function(e) {
    var t = e.icode;
    return Object(g.M)({
        externalId: v.externalId || "",
        type: g.a.Email,
        icode: t
    }, {
        EUI: j.EUI
    })
}
      ), {
    action: "register",
    icodeType: "register"
});

然后咱来调试一下 j = O({externalId: s.email}),同样的东西,每次加密都不一样,极有可能是RSA. 进去O看看.

image-20220425101720133

咱们都看到setPublicKey,知道有rsa.下面的代码其实应该要分开阅读

function Pt(t) {
    var e, r;
    t = t || {};
    var i = function(t) {
        for (var e = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*", r = "", i = 0; i < t; i++) {
            var n = Math.floor(Math.random() * e.length);
            r += e.substring(n, n + 1)
        }
        return r
    }(16)
    , s = new Ct({});
    s.setPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYEVrK/4Mahiv0pUJgTybx4J9P5dUT/Y0PuwMbk+gMU+jrZnBiXGv6/hCH1avIhoBcE535F8nJQQN3UavZdFkYidsoXuEnat3+eVTp3FslyhRwIBDF09v4vDhRtxFOT+R7uH7h/mzmyA2/+lfIMWGIrffXprYizbV76+YQKhoqFQIDAQAB");
    var h = s.encrypt(window.btoa(i))
    , u = l.a.parse("0102030405060708")
    , f = l.a.parse(i)
    , p = window.btoa(a()(t).join(","))
    , g = {};
    return o()(e = a()(t)).call(e, (function(e) {
        var r = t[e]
        , i = c.a.encrypt(r, f, {
            iv: u,
            padding: d.a
        });
        i = i.toString(),
            g[e] = i
    }
                                   )),
        {
        EUI: n()(r = "".concat(h, ".")).call(r, p),
        encryptedParams: g
    }
}

>1. O方法

1. 随机秘钥生成

生成长度为16的随机数字.

var i = function(t) {
        for (var e = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*", r = "", i = 0; i < t; i++) {
            var n = Math.floor(Math.random() * e.length);
            r += e.substring(n, n + 1)
        }
        return r
    }(16)

2. 对秘钥进行 BASE64 + RSA

对上面生成的i进行base64后,再进行一个rsa。很明显的rsa特征了.

s.setPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYEVrK/4Mahiv0pUJgTybx4J9P5dUT/Y0PuwMbk+gMU+jrZnBiXGv6/hCH1avIhoBcE535F8nJQQN3UavZdFkYidsoXuEnat3+eVTp3FslyhRwIBDF09v4vDhRtxFOT+R7uH7h/mzmyA2/+lfIMWGIrffXprYizbV76+YQKhoqFQIDAQAB");
var h = s.encrypt(window.btoa(i))

3. AES加密

 u = l.a.parse("0102030405060708")  // 设置key
    , f = l.a.parse(i) // 设置iv
    , p = window.btoa(a()(t).join(","))  // a()(t).join(",") 的结果是key
    , g = {};
return o()(e = a()(t)).call(e, (function(e) {  // o()(e = a()(t)) 是 foreach
    var r = t[e]  // 对象的值
    , i = c.a.encrypt(r, f, {
        iv: u,
        padding: d.a
    }); // AES 加密
    i = i.toString(),
        g[e] = i
}
                               )),
            {
                EUI: n()(r = "".concat(h, ".")).call(r, p),
                encryptedParams: g
            }

先看看c.a.encrypt,一看就是crypto加密库,对应的参数应该是 (加密内容,key,{ iv,填充模式}),有key有iv,不可能是ecb(ecb没有iv),所以大概率是ecb.

根据对代码的批注,因为o()(e = a()(t))是foreach, 所有 e是我们遍历的对象, 匿名函数的e是key, 没啥好说的

EUI就是把 RSA的加密结果和 p(邮箱base64)进行一个拼凑。就没啥了,代码没混淆,思路很难清晰。

>极验

好久没搞滑块了,抽空好好弄弄