`

网页游戏外挂的设计与编写:QQ摩天大楼【二】(登陆准备-信息处理方式)

    博客分类:
  • C#
阅读更多

    上一篇文中提到,制作外挂的第一步,是与游戏进行连接,即登陆游戏。

    对于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分析完了,我们掌握了登陆所需的足够信息,下一篇我们就讲,如何模拟客户端进行登陆。

 

 

 

 

 

 

 

 

 

 

分享到:
评论
9 楼 sumee 2011-01-07  
这么忙啊..都不更新哦..!!!
8 楼 virginkj 2011-01-05  
哥们 赶紧更新啊 等着你呢
7 楼 sumee 2010-12-29  
ouyangjia7 写道
sumee 写道
怎么会没人看呢.很期待啊...更新吧!!!!强烈要求!

好,有时间立马写,最近年末了好忙。



嗯...强烈要求学习...我当你的大粉丝!!!!
6 楼 ouyangjia7 2010-12-28  
sumee 写道
怎么会没人看呢.很期待啊...更新吧!!!!强烈要求!

好,有时间立马写,最近年末了好忙。
5 楼 sumee 2010-12-25  
怎么会没人看呢.很期待啊...更新吧!!!!强烈要求!
4 楼 ouewqa 2010-12-24  
哥们继续更新呀,等着看你呢。
3 楼 mymelon 2010-12-13  
没下文了?我还。。
2 楼 ouyangjia7 2010-11-25  
zhaoxin1943 写道
哥们,怎么不更新了?

没人看,看了不评论,没心思写了。
1 楼 zhaoxin1943 2010-11-18  
哥们,怎么不更新了?

相关推荐

Global site tag (gtag.js) - Google Analytics