web qq 擷取好友名單hash演算法在使用web qq的介面進行好友名單擷取的時候,需要post一個參數:hash在對其js檔案進行分析之後,發現計算hash的函數位於:http://0.web.qstatic.com/webqqpic/pubapps/0/50/eqq.all.js
這個檔案中:
P = function(b, i) {for (var a = [], s = 0; s < i.length; s++) a[s % 4] ^= i.charCodeAt(s);var j = ["EC", "OK"],d = [];d[0] = b >> 24 & 255 ^ j[0].charCodeAt(0);d[1] = b >> 16 & 255 ^ j[0].charCodeAt(1);d[2] = b >> 8 & 255 ^ j[1].charCodeAt(0);d[3] = b & 255 ^ j[1].charCodeAt(1);j = [];for (s = 0; s < 8; s++) j[s] = s % 2 == 0 ? a[s >> 1] : d[s >> 1];a = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];d = "";for (s = 0; s < j.length; s++) d += a[j[s] >> 4 & 15],d += a[j[s] & 15];return d}
這樣可以寫一個python版本:
a=[0,0,0,0]s=0for s in range(0,len(i)):a[s%4] = a[s%4] ^ ord(i[s])j = ["EC", "OK"]d = [0,0,0,0]d[0] = int(b) >> 24 & 255 ^ ord(j[0][0])d[1] = int(b) >> 16 & 255 ^ ord(j[0][1])d[2] = int(b) >> 8 & 255 ^ ord(j[1][0])d[3] = int(b) & 255 ^ ord(j[1][1])j = range(0,8)for s in range(0,8):if s % 2 == 0:j[s] = a[s >> 1]else:j[s] = d[s >> 1]a = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"]d = ""for s in range(0,len(j)):d = d + a[j[s] >> 4 & 15]d = d + a[j[s] & 15]return d
但是第二天使用web qq介面擷取好友名單時,卻不能擷取了。後來發現原來是這個hash函數變了:
P = function(b, i) {for (var a = [], s = 0; s < b.length; s++) a[s] = b.charAt(s) - 0; alert(a);//agofor (var j = 0, d = -1, s = 0; s < a.length; s++) {j += a[s];j %= i.length;var c = 0;if (j + 4 > i.length) for (var l = 4 + j - i.length, x = 0; x < 4; x++) c |= x < l ? (i.charCodeAt(j + x) & 255) << (3 - x) * 8: (i.charCodeAt(x - l) & 255) << (3 - x) * 8;else for (x = 0; x < 4; x++) c |= (i.charCodeAt(j + x) & 255) << (3 - x) * 8;d ^= c}a = [];a[0] = d >> 24 & 255;a[1] = d >> 16 & 255;a[2] = d >> 8 & 255;a[3] = d & 255;d = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];s = "";for (j = 0; j < a.length; j++) s += d[a[j] >> 4 & 15],s += d[a[j] & 15];return s}
繼續改寫成python版:
a=[]s=0for s in range(0,len(b)):t=int(b[s])a.append(t)j = 0d = -1s = 0for s in range(0,len(a)):j = j + a[s]j = j % len(i)c = 0if (j + 4) > len(i): l = 4 + j - len(i)for x in range(0,4):if x < l:c = c | (( ord(i[j + x]) & 255) << (3 - x) * 8 )else:c = c | ( ( ord(i[x - l]) & 255) << (3 - x) * 8 )else:for x in range(0,4):c = c | (( ord(i[j + x]) & 255) << (3 - x) * 8 )d = d ^ ca = [0,0,0,0]a[0] = d >> 24 & 255a[1] = d >> 16 & 255a[2] = d >> 8 & 255a[3] = d & 255d = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"]s = ""for j in range(0,len(a)):s = s + d[a[j] >> 4 & 15]s = s + d[a[j] & 15]return s
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
在之後,又發現其計算hash的函數P一直在變,總不能一直去手動修改三?解決辦法:動態擷取這個js檔案---》擷取計算hash的js函數P的代碼--》使用PyV8執行js代碼擷取hash
def hash_p(self,b='',i=''):if b=='' and i=='':b=self.qqi=self.ptwebqqdata = urllib2.urlopen("http://0.web.qstatic.com/webqqpic/pubapps/0/50/eqq.all.js").read()data = data.split("P=function")[1].split(",r=function")[0]data = "P=function" + dataimport PyV8js = PyV8.JSContext() # create a context with an implicit global objectjs.enter() # enter the context (also support with statement) data = data + ';P("' + b + '","' + i + '");'print datas = js.eval(data)print sreturn s