某小说站点签名算法破解

#某小说站点签名算法破解

某小说站点在加载小说内容时会对url进行签名操纵,通过分析apk ipa 发现存在混淆加壳等乱七八糟的东西,为了快速解决问题输出结果,对目标进行简单收集发现了,web 站点。web站点也是同样的签名算法。
通过url 发现具有sign字符。
通过页面加载的js中字符串定位到 setParams 函数

key: "setParams",
value: function() {
    var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
    t.token = V.get("token") || "",
    t.app = t.app ? t.app : "qutoutiao",
    t.device = Object($.b)(),
    t.dtu = "h5",
    t.version = U.a.integer,
    t.nonce = Math.ceil(1e4 * Math.random()),
    t.time = Math.floor((new Date).getTime() / 1e3);
    var e = z(P()(this.getMD5(t) + "&key=" + Q));
    return t.sign = e,t
}

通过分析代码代码,完整模拟请求需要了解 this.getMD5()方法、常量Q、函数P()()、函数z(),

return t.sign
console.log(1,this.getMD5(t));console.log(2,Q);console.log(3,z);console.log(4,P());console.log(5,P()(this.getMD5(t) + "&key=" + Q));console.log(6,e);console.log(7,P()('admin'));return t.sign

sign 生产需要t和key,t最主要的是bookid找到key 并验证其方法可以获取每本书的详情,替换代码:

    var e = z(P()(this.getMD5(t) + "&key=" + Q));
    console.log(1, this.getMD5(t)); // 1 "app=qutoutiao&book_id=4095a188215e222eb82ad622a33da624&device=pageuser&dtu=h5&nonce=210&time=1550728569&token=&version=290"
    console.log(2, Q);                                  // 2 "T^xS0x31XL%wEowC"
    console.log(3, z);                                  // 3 f 放到下面
    console.log(4, P());                                // 4 ƒ 放到下面
    console.log(5, P()(this.getMD5(t) + "&key=" + Q));  // 5 "b7b669fcc20b73e0f9fb56ef801e78d2"
    console.log(6,e);               // 6 "67326733333c63666637356732366035633c6367303360633d353460323d6137"
    console.log(7,P()('admin'));    // 7 "21232f297a57a5a743894a0e4a801fc3"
    return t.sign = e,
    // 函数 z
    var z = function(t) {
        for (var e = t.split("").map(function(t) {
            return t.charCodeAt()
        }), n = e.length, o = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"].map(function(t) {
            return t.charCodeAt()
        }), a = 0; a < n; a++)
            e[a] = 5 ^ e[a];
        for (var i = [], r = 0, s = 0, c = 0; ; ) {
            var l = 255 & e[r];
            if (c = s + 1,
            i[s] = o[l >> 4],
            s = c + 1,
            i[c] = o[15 & l],
            (r += 1) >= n)
                break
        }
        return i.map(function(t) {
            return String.fromCharCode(t)
        }).join("")
    }
    // p()
            function g(t, e, n) {
            return e ? n ? m(e, t) : function(t, e) {
                return h(m(t, e))
            }(e, t) : n ? y(t) : function(t) {
                return h(y(t))
            }(t)
        }

通过P()('admin') 输出的是21232f297a57a5a743894a0e4a801fc3,验证结果为md5算法。推论伪代码为

qingfengdeMacBook-Pro:Desktop$ cat xxxx.py 
import hashlib
key ="T^xS0x31XL%wEowC"
src= "app=qutoutiao&book_id=4095a188215e222eb82ad622a33da624&device=pageuser&dtu=h5&nonce=210&time=1550728569&token=&version=290"+"&key="+key
m2 = hashlib.md5()   
m2.update(src) 
print(m2.hexdigest())
qingfengdeMacBook-Pro:Desktop$ python xxxx.py 
b7b669fcc20b73e0f9fb56ef801e78d2

通过上面已得知 P()() 是完成一个md5()方法,而方法z() 是十六进制异或5

    s=""
    for i in md5:
        s+="{:02x}".format(ord(i)^5)
    print("sign:{}".format(s))
    return s
qingfengdeMacBook-Pro:Desktop$ python xxxx.py 
md5:b7b669fcc20b73e0f9fb56ef801e78d2
sign:67326733333c63666637356732366035633c6367303360633d353460323d6137

完整签名代码

def sign2(data):
    # 签名算法:对所有字段进行排序并生成签名
    src = "&".join(["{}={}".format(i, data[i]) for i in sorted(data.keys())])
    key = "T^xS0x31XL%wEowC"
    src = src+"&key="+key
    m2 = hashlib.md5()
    m2.update(src.encode('utf-8'))
    md5 = m2.hexdigest()
    s = ""
    for i in md5:
        s += "{:02x}".format(ord(i) ^ 5)
    return s

流水账,搞定。
之后就是对每个接口API编写模拟代码