网页游戏外挂的设计与编写:QQ摩天大楼【二】(登陆准备-信息处理方式)
??? 上一篇文中提到,制作外掛的第一步,是與游戲進(jìn)行連接,即登陸游戲。
????對(duì)于QQ的游戲來說,可以有兩種方法登陸游戲。一種是登陸空間再登陸游戲,QQ農(nóng)場(chǎng),QQ搶車位的游戲都可以這樣登陸;另一種是登陸QQ校友再登陸游戲,QQ農(nóng)場(chǎng),QQ摩天大樓都可以這樣登陸。
????我要給大家講的是第二種,或許有更好的方法,我在此權(quán)作是拋磚引玉。
我在第一篇文章中寫道 ????? 我們進(jìn)入網(wǎng)頁游戲是要先登陸的,像要進(jìn)入校內(nèi)(人人)網(wǎng)的應(yīng)用就需要先登陸人人網(wǎng),要進(jìn)入QQ的應(yīng)用就需要先登陸QQ校友或者QQ空間。沒有登陸,我們連游戲都進(jìn)不了,那么外掛就不能與游戲建立連接了,之后的偷菜又從何談起?那么我們又是從哪里登陸呢?我們從網(wǎng)頁登陸,由JavaScript負(fù)責(zé)發(fā)送與接收。所以看不懂(能看懂就行,不需要會(huì)寫)JavaScript的人,請(qǐng)?jiān)诖酥共?#xff0c;回去翻翻書再繼續(xù)。????有人可能要問了:“我們是否可以這樣做,用抓包工具把登陸時(shí)與QQ服務(wù)器交互的數(shù)據(jù)包截獲下來,查看一下發(fā)送的內(nèi)容和URL,然后我們?cè)僬罩瑯拥母袷?#xff0c;重放一遍,不就達(dá)到目的了嗎?這樣做就可以省去分析JavaScript的步驟了。”
????這個(gè)問題問得好,是的,登陸的時(shí)候只要知道URL,知道服務(wù)器地址,發(fā)送的內(nèi)容無非就是用戶名和密碼,把用戶名和密碼插在URL中相應(yīng)的位置就行了。但是真有這么簡(jiǎn)單嗎?答案是否定的,原因就是密碼不是用明文傳送的,用戶名可以是,但是密碼絕對(duì)不能是,不然密碼很容易被盜,只要對(duì)你的網(wǎng)絡(luò)實(shí)施搭線竊\聽就可以截獲你的QQ密碼了。所以密碼那部分是經(jīng)過處理的,一般的處理方式是用哈希算法,現(xiàn)在廣泛使用的哈希算法是MD5,但是具體他們?cè)趺从玫墓K惴?#xff0c;到底是不是用的MD5,就不得而知了,我們就是要通過分析他們的JavaScript代碼,知道他們是處理密碼的方式,然后我們用同樣的方法處理一下,然后發(fā)送給他們的服務(wù)器,才能登陸成功。
????不知大家做好準(zhǔn)備了沒,看懂JavaScript也不太難,相信有八成的人是做好準(zhǔn)備了。
?????????
????我們首先打開IE,轉(zhuǎn)到http://xiaoyou.pengyou.qq.com/index.html,這是QQ校友的登陸頁面,查看該頁面的代碼。這個(gè)頁面的代碼沒有什么有價(jià)值的東西,我們希望截取的是按下登陸按鈕后,發(fā)生了什么動(dòng)作。但是這些代碼里找不到那個(gè)函數(shù),甚至找不到那個(gè)按鈕,連輸入用戶名和密碼的textbox都找不到。不過別擔(dān)心,看那頁代碼靠近最下方,有一句
???? var iframe_src = 'http://ui.ptlogin2.qq.com/cgi-bin/login? appid=15000102&hide_title_bar=1&qlogin_jumpname=xiaoyou_qlogin&
s_url='+url+'&css=http://imgcache.qq.com/campus/login/login.css&
self_regurl=http://xiaoyou.pengyou.qq.com/emailreg.html';
??? 通過觀察其URL的名稱,我們猜測(cè),這iframe應(yīng)該就是裝有登陸零配件的iframe,輸入用戶名和密碼的textbox和登陸按鈕應(yīng)該在那個(gè)頁面上。
???我們把代碼中的URL復(fù)制到IE地址欄,回車之后會(huì)發(fā)現(xiàn)果然是我們要找的登陸頁面,截圖如下:
???? 我們繼續(xù)查看該網(wǎng)頁的代碼,可以找到一個(gè)onsubmit事件,那個(gè)form提交表單時(shí)執(zhí)行的事件,我們要找的就是這個(gè),代碼如下:
??????? onsubmit="if(!isAbleSubmit){return false;};return ptui_onLoginEx(loginform, 'qq.com')";
????? 我們發(fā)現(xiàn),這個(gè)事件最終執(zhí)行了一個(gè)ptui_onLoginEx函數(shù),我們接下來得找到這個(gè)函數(shù),按下Ctrl+F輸入"ptui_onLoginEx”,但是IE會(huì)提示找不到,不過大家放心,這段JavaScript代碼一定會(huì)在本機(jī)執(zhí)行的,要執(zhí)行就必須先下載到本機(jī),通過仔細(xì)查找,發(fā)現(xiàn)原來該頁面還加載了一個(gè)外部的js文件:
??? <script language="javascript" src="http://imgcache.qq.com/ptlogin/ac/v5/js/comm.js?v=1.8"></script>
????復(fù)制URL到IE地址欄,把comm.js文件下載到本機(jī),然后查看comm.js,我們?cè)谶@個(gè)文件中找到了ptui_onLoginEx函數(shù)。
function ptui_onLoginEx(B, C) {
??? g_time.time12 = new Date();
??? if (ptui_onLogin(B)) {
??????? var A = new Date();
??????? A.setHours(A.getHours() + 24 * 30);
??????? if (isNaN(B.u.value) && (B.u.value.indexOf("@") < 0)) {
??????????? setCookie("ptui_loginuin2", B.u.value, A, "/", "ui.ptlogin2." + C)
??????? } else {
??????????? setCookie("ptui_loginuin", B.u.value, A, "/", "ui.ptlogin2." + C)
??????? }
??? }
??? return false
}
??? 該函數(shù)調(diào)用了ptui_onLogin函數(shù),還在本地添加了COOKIE,可以看到QQ校友登陸成功后COOKIE的有效時(shí)間是30天。
??? 下面我們?cè)俨榭磒tui_onLogin函數(shù)。
?function ptui_onLogin(A) {
??????? try {
??????????? if (parent.ptlogin2_onLogin) {
??????????????? if (!parent.ptlogin2_onLogin()) {
??????????????????? return false
??????????????? }
??????????? }
??????????? if (parent.ptlogin2_onLoginEx) {
??????????????? var D = A.u.value;
??????????????? var B = A.verifycode.value;
??????????????? if (ptui_str(STR_UINTIP) == D) {
??????????????????? D = ""
??????????????? }
??????????????? if (!parent.ptlogin2_onLoginEx(D, B)) {
??????????????????? return false
??????????????? }
??????????? }
??????? } catch(C) {}
??????? return ptui_checkValidate(A)
??? }
????這個(gè)函數(shù)調(diào)用了parent的ptlogin2_onLogin以及ptloin2_onLoginEx等方法,這兩個(gè)方法的實(shí)現(xiàn)無光緊要,關(guān)鍵看最后一句返回return ptui_checkValidate(A)。
????于是我們繼續(xù)查看ptui_checkValidate函數(shù)。
function ptui_checkValidate(B) {
??? var A = B.u;
??? var D = B.p;
??? var E = B.verifycode;
??? if (A.value == "" || ptui_str(STR_UINTIP) == A.value) {
??????? alert(ptui_str(STR_NO_UIN));
??????? A.focus();
??????? return false
??? }
??? A.value = ptui_trim(A.value);
??? if (!ptui_checkQQUin(A.value)) {
??????? alert(ptui_str(STR_INV_UIN));
??????? A.focus();
??????? A.select();
??????? return false
??? }
??? if (D.value == "") {
??????? alert(ptui_str(STR_NO_PWD));
??????? D.focus();
??????? return false
??? }
??? if (E.value == "") {
??????? if (!isLoadVC) {
??????????? loadVC(true);
??????????? g_submitting = true;
??????????? return false
??????? }
??????? alert(ptui_str(STR_NO_VCODE));
??????? try {
??????????? E.focus()
??????? } catch(C) {}
??????? if (!g_loadcheck) {
??????????? ptui_reportAttr(78028)
??????? } else {
??????????? ptui_reportAttr(78029)
??????? }
??????? return false
??? }
??? if (E.value.length != 4) {
??????? alert(ptui_str(STR_INV_VCODE));
??????? E.focus();
??????? E.select();
??????? return false
??? }
??? D.setAttribute("maxlength", "32");
??? ajax_Submit();
??? ptui_reportNum(g_changeNum);
??? g_changeNum = 0;
??? return true
}
??? 我們注意最后有一句ajax_Submit,前面一大串別看了統(tǒng)統(tǒng)都沒用。
??? 繼續(xù)ajax_Submit函數(shù)。?
function ajax_Submit() {
??? var D = true;
??? var E = document.forms[0];
??? var B = "";
??? for (var A = 0; A < E.length; A++) {
??????? if (E[A].name == "fp" || E[A].type == "submit") {
??????????? continue
??????? }
??????? if (E[A].name == "ptredirect") {
??????????? g_ptredirect = E[A].value
??????? }
??????? if (E[A].name == "low_login_enable" && (!E[A].checked)) {
??????????? D = false;
??????????? continue
??????? }
??????? if (E[A].name == "low_login_hour" && (!D)) {
??????????? continue
??????? }
??????? if (E[A].name == "webqq_type" && (!E[A].checked)) {
??????????? continue
??????? }
??????? B += E[A].name;
??????? B += "=";
??????? if (t_appid == g_appid && E[A].name == "u" && E[A].value.indexOf("@") < 0 && isNaN(E[A].value)) {
??????????? B += "@" + E[A].value + "&";
??????????? continue
??????? }
??????? if (E[A].name == "p") {
??????????? var F = "";
??????????? F += E.verifycode.value;
??????????? F = F.toUpperCase();
??????????? B += md5(md5_3(E.p.value) + F)
??????? } else {
??????????? if (E[A].name == "u1" || E[A].name == "ep") {
??????????????? B += encodeURIComponent(E[A].value)
??????????? } else {
??????????????? B += E[A].value
??????????? }
??????? }
??????? B += "&"
??? }
??? B += "fp=loginerroralert";
??? var C = document.createElement("script");
??? C.src = E.action + "?" + B;
??? document.cookie = "login_param=" + encodeURIComponent(login_param) + ";domain=ui.ptlogin2." + g_domain + ";path=/";
??? document.body.appendChild(C);
??? return
}?
?? ?大家注意看我標(biāo)紅了的文字,這段就是對(duì)密碼的處理方法了,將這段代碼注釋一下,方便大家看懂。
????var F = "";
???? F += E.verifycode.value;//取出驗(yàn)證碼
?????F = F.toUpperCase();//轉(zhuǎn)換為大寫
?????B += md5(md5_3(E.p.value) + F)//將密碼明文用MD5算法連續(xù)哈希3次之后,加上驗(yàn)證碼再哈希一次。
?
?
?? 如是我們得到了QQ發(fā)送密碼的方式即將密碼明文用MD5算法連續(xù)哈希3次之后,加上驗(yàn)證碼再哈希一次,再知道發(fā)送的URL和服務(wù)器地址,就可以進(jìn)行登陸了。
???好了,JavaScript分析完了,我們掌握了登陸所需的足夠信息,下一篇我們就講,如何模擬客戶端進(jìn)行登陸。
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的网页游戏外挂的设计与编写:QQ摩天大楼【二】(登陆准备-信息处理方式)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 局域网下连接其他电脑的HDFS集群
- 下一篇: Redis Cluster集群搭建