二维码获取:

首先Fiddler抓包分析其二维码获取方式,https://ssl.ptlogin2.qq.com/ptqrshow?appid=501004106&e=0&l=M&s=5&d=72&v=4&t=0.8446219663601369
抓到该https协议的二维码获取包。接下来分析其含义,抄起Chrome的js调试器就上。
猜测其中appid是应用标识,用来说明当前是用何种应用于该服务器通信的,而SmartQQ的appid是501004106。

支持两种协议,如果是http就将https换成http,并且删掉URL中的ssl即可。http://ptlogin2.qq.com/ptqrshow?appid=501004106&e=0&l=M&s=5&d=72&v=4&t=0.8446219663601369
其他参数固定,唯独参数t是随机生成。具体看js获取二维码源码:

get_qrlogin_pic: function() {
        var b = "ptqrshow";
        var a = (pt.isHttps ? "https://ssl." : "http://") + "ptlogin2." + g_domain + "/" + b + "?";
        if (pt.regmaster == 2) {
            a = "http://ptlogin2.function.qq.com/" + b + "?regmaster=2&"
        } else {
            if (pt.regmaster == 3) {
                a = "http://ptlogin2.crm2.qq.com/" + b + "?regmaster=3&"
            }
        }
        a += "appid=" + g_appid + "&e=0&l=M&s=5&d=72&v=4&t=" + Math.random();
        return a

二维码的扫描心跳:

有一个2000毫秒的循环,不断判断二维码是否被扫描,如果被扫描了,就准备登陆操作。或者超时提示二维码失效,单击重新获取。判断源码是这样的

pt.qrlogin_clock = window.setInterval("qrlogin_submit();", 2000);// 每2000毫秒执行一次qrlogin_submit()
function qrlogin_submit() {
    var a = getSubmitUrl("ptqrlogin");
    pt.winName.set("login_param", encodeURIComponent(login_param));
    pt.loadScript(a);
    return

getSubmitUrl是什么?

function getSubmitUrl(l) {
    var e = true;
    var c = document.forms[0];
    var a = (pt.isHttps ? "https://ssl." : "http://") + "ptlogin2." + g_domain + "/" + l + "?";
    var b = document.getElementById("login2qq");
    if (pt.regmaster == 2) {
        a = "http://ptlogin2.function.qq.com/" + l + "?regmaster=2&"
    } else {
        if (pt.regmaster == 3) {
            a = "http://ptlogin2.crm2.qq.com/" + l + "?regmaster=3&"
        }
    }
    for (var k = 0; k < c.length; k++) {
        if (l == "ptqrlogin" && (c[k].name == "u" || c[k].name == "p" || c[k].name == "verifycode" || c[k].name == "h")) {
            continue
        }
        if (c[k].name == "ipFlag" && !c[k].checked) {
            a += c[k].name + "=-1&";
            continue
        }
        if (c[k].name == "fp" || c[k].type == "submit") {
            continue
        }
        if (c[k].name == "ptredirect") {
            g_ptredirect = c[k].value
        }
        if (c[k].name == "low_login_enable" && (!c[k].checked)) {
            e = false;
            continue
        }
        if (c[k].name == "low_login_hour" && (!e)) {
            continue
        }
        if (c[k].name == "webqq_type" && !b && (!c[k].checked)) {
            continue
        }
        a += c[k].name;
        a += "=";
        if (c[k].name == "u" && pt.needAt) {
            a += pt.needAt + "&";
            continue
        }
        if (c[k].name == "p") {
            var n = c.p.value;
            var j = hexchar2bin(md5(n));
            var h = md5(j + pt.uin);
            var g = md5(h + c.verifycode.value.toUpperCase());
            a += g
        } else {
            if (c[k].name == "u1" || c[k].name == "ep") {
                var d = c[k].value;
                var m = "";
                if ((g_appid == "1003903" || g_appid == "501004106") && b) {
                    m = /\?/g.test(d) ? "&" : "?";
                    var f = document.getElementById("webqq_type").value;
                    m += "login2qq=" + b.value + "&webqq_type=" + f
                }
                a += encodeURIComponent(d + m)
            } else {
                a += c[k].value
            }
        }
        a += "&"
    }
    a += "fp=loginerroralert&action=" + pt.action.join("-") + "-" + (new Date() - g_begTime) + "&mibao_css=" + pt.mibao_css + "&t=" + pt.submitN[pt.uin] + "&g=1";
    a += "&js_type=" + pt.js_type + "&js_ver=" + window.g_pt_version + "&login_sig=" + window.g_login_sig;
    return a
}

这个先不管了量太大,(提交终点应该在53-69行,其他的是非SmartQQ用的)先看下一个。呃,pt这个对象困扰我许久了,本身设计代码量大,我就不全传了,看关键函数WinName.set以及他的LoadScript两个函数。

首先WinName.set–这个东西是搞什么的

set: function(c, a) {
            var b = window.name || "";
            if (b.match(new RegExp(";" + c + "=([^;]*)(;|$)"))) {
                window.name = b.replace(new RegExp(";" + c + "=([^;]*)"), ";" + c + "=" + a)
            } else {
                window.name = b + ";" + c + "=" + a
            }
        }

过滤后,设置WinName中的name值的,目前没有用到也放下吧。

最后是加载脚本到当前页面,loadScript~~

loadScript: function(b, c) {
        var a = document.createElement("script");
        a.charset = "UTF-8";
        a.onload = a.onreadystatechange = function() {
            if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") {
                if (typeof c == "function") {
                    c(a)
                }
                a.onload = a.onreadystatechange = null;
                if (a.parentNode) {
                    a.parentNode.removeChild(a)
                }
            }
        };
        a.src = b;
        document.getElementsByTagName("head")[0].appendChild(a)

 

我顺便分析了其中最常用的sys.getQueryValue函数用途。很多处理URL的地方都用到了。

getQueryValue: function(c, b) {
        var a = "";
        if (b) {
            a = "&" + b
        } else {
            a = window.location.search.replace(/(^\?+)|(#\S*$)/g, "")
        }
        a = a.match(new RegExp("(^|&)" + c + "=([^&]*)(&|$)"));
        return !a ? "" : decodeURIComponent(a[2])
    }

我去–正则过滤^\?+#\S*$等,替换空,这不是URL防注入过滤的节奏,然后最后在编码成URL形式返回。

先分析这些,目前分析还再继续~~

页面下部广告

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

鲁ICP备17018668号-1