网页游戏外挂的设计与编写:QQ摩天大楼【二】(登陆准备-信息处理方式)
??? 上一篇文中提到,制作外掛的第一步,是與游戲進行連接,即登陸游戲。
????對于QQ的游戲來說,可以有兩種方法登陸游戲。一種是登陸空間再登陸游戲,QQ農場,QQ搶車位的游戲都可以這樣登陸;另一種是登陸QQ校友再登陸游戲,QQ農場,QQ摩天大樓都可以這樣登陸。
????我要給大家講的是第二種,或許有更好的方法,我在此權作是拋磚引玉。
我在第一篇文章中寫道 ????? 我們進入網頁游戲是要先登陸的,像要進入校內(人人)網的應用就需要先登陸人人網,要進入QQ的應用就需要先登陸QQ校友或者QQ空間。沒有登陸,我們連游戲都進不了,那么外掛就不能與游戲建立連接了,之后的偷菜又從何談起?那么我們又是從哪里登陸呢?我們從網頁登陸,由JavaScript負責發送與接收。所以看不懂(能看懂就行,不需要會寫)JavaScript的人,請在此止步,回去翻翻書再繼續。????有人可能要問了:“我們是否可以這樣做,用抓包工具把登陸時與QQ服務器交互的數據包截獲下來,查看一下發送的內容和URL,然后我們再照著同樣的格式,重放一遍,不就達到目的了嗎?這樣做就可以省去分析JavaScript的步驟了。”
????這個問題問得好,是的,登陸的時候只要知道URL,知道服務器地址,發送的內容無非就是用戶名和密碼,把用戶名和密碼插在URL中相應的位置就行了。但是真有這么簡單嗎?答案是否定的,原因就是密碼不是用明文傳送的,用戶名可以是,但是密碼絕對不能是,不然密碼很容易被盜,只要對你的網絡實施搭線竊\聽就可以截獲你的QQ密碼了。所以密碼那部分是經過處理的,一般的處理方式是用哈希算法,現在廣泛使用的哈希算法是MD5,但是具體他們怎么用的哈希算法,到底是不是用的MD5,就不得而知了,我們就是要通過分析他們的JavaScript代碼,知道他們是處理密碼的方式,然后我們用同樣的方法處理一下,然后發送給他們的服務器,才能登陸成功。
????不知大家做好準備了沒,看懂JavaScript也不太難,相信有八成的人是做好準備了。
?????????
????我們首先打開IE,轉到http://xiaoyou.pengyou.qq.com/index.html,這是QQ校友的登陸頁面,查看該頁面的代碼。這個頁面的代碼沒有什么有價值的東西,我們希望截取的是按下登陸按鈕后,發生了什么動作。但是這些代碼里找不到那個函數,甚至找不到那個按鈕,連輸入用戶名和密碼的textbox都找不到。不過別擔心,看那頁代碼靠近最下方,有一句
???? 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的名稱,我們猜測,這iframe應該就是裝有登陸零配件的iframe,輸入用戶名和密碼的textbox和登陸按鈕應該在那個頁面上。
???我們把代碼中的URL復制到IE地址欄,回車之后會發現果然是我們要找的登陸頁面,截圖如下:
???? 我們繼續查看該網頁的代碼,可以找到一個onsubmit事件,那個form提交表單時執行的事件,我們要找的就是這個,代碼如下:
??????? onsubmit="if(!isAbleSubmit){return false;};return ptui_onLoginEx(loginform, 'qq.com')";
????? 我們發現,這個事件最終執行了一個ptui_onLoginEx函數,我們接下來得找到這個函數,按下Ctrl+F輸入"ptui_onLoginEx”,但是IE會提示找不到,不過大家放心,這段JavaScript代碼一定會在本機執行的,要執行就必須先下載到本機,通過仔細查找,發現原來該頁面還加載了一個外部的js文件:
??? <script language="javascript" src="http://imgcache.qq.com/ptlogin/ac/v5/js/comm.js?v=1.8"></script>
????復制URL到IE地址欄,把comm.js文件下載到本機,然后查看comm.js,我們在這個文件中找到了ptui_onLoginEx函數。
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
}
??? 該函數調用了ptui_onLogin函數,還在本地添加了COOKIE,可以看到QQ校友登陸成功后COOKIE的有效時間是30天。
??? 下面我們再查看ptui_onLogin函數。
?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)
??? }
????這個函數調用了parent的ptlogin2_onLogin以及ptloin2_onLoginEx等方法,這兩個方法的實現無光緊要,關鍵看最后一句返回return ptui_checkValidate(A)。
????于是我們繼續查看ptui_checkValidate函數。
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,前面一大串別看了統統都沒用。
??? 繼續ajax_Submit函數。?
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
}?
?? ?大家注意看我標紅了的文字,這段就是對密碼的處理方法了,將這段代碼注釋一下,方便大家看懂。
????var F = "";
???? F += E.verifycode.value;//取出驗證碼
?????F = F.toUpperCase();//轉換為大寫
?????B += md5(md5_3(E.p.value) + F)//將密碼明文用MD5算法連續哈希3次之后,加上驗證碼再哈希一次。
?
?
?? 如是我們得到了QQ發送密碼的方式即將密碼明文用MD5算法連續哈希3次之后,加上驗證碼再哈希一次,再知道發送的URL和服務器地址,就可以進行登陸了。
???好了,JavaScript分析完了,我們掌握了登陸所需的足夠信息,下一篇我們就講,如何模擬客戶端進行登陸。
?
?
?
?
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的网页游戏外挂的设计与编写:QQ摩天大楼【二】(登陆准备-信息处理方式)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 局域网下连接其他电脑的HDFS集群
- 下一篇: Redis Cluster集群搭建