php模拟登录QQ空间3.0 2014-11-23

        本人不太喜欢玩qq空间的,最近加了一个QQ好友,看头像貌似一个大叔。错了,是他加的我,他咨询我微信自动打招呼不能使用的问题,本来上班就挺闲的,于是就和他聊开了。他问了我一句话,我顿时汗颜,感觉愧对自己这一两年。什么话呢?他说“最羡慕我们这群在网络上赚钱的了,你在网上转了几十万了吧?”。由此我内疚啊,几十万角还是几十万元,勒个。这些都是引言,他给我启发,我能否写一个网页工具,让用户导出他自己的QQ群好友呢,导出QQ成员邮箱呢?现在电子商务那么发达,有好些人都借助QQ群做营销,QQ号码的作用也就可想而知了 。上周五的 时候我找了个软件,自动提取QQ群成员的软件,能是能用,骂了隔壁的要收费。不说这些了,言归正传。

首先我找到QQ空间的登录界面i.qq.com,抓一下包 这里是想尝试找到他的登录链接,以及上传的参数信息。为了调试简便,直接找他的登录表单,地址是:http://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=http%3A//qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&pt_qzone_sig=1&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=http%3A//qzs.qq.com/qzone/v5/loginsucc.html?para=izone&pt_qr_app=%E6%89%8B%E6%9C%BAQQ%E7%A9%BA%E9%97%B4&pt_qr_link=http%3A//z.qzone.com/download.html&self_regurl=http%3A//qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=http%3A//z.qzone.com/download.html,这么长一串,看着头都晕了吧,这个地址不用管它,是写死的。



请求这个页面,会返回一个重要的参数,查看这个页面的源码,里面有个login_sig的玩意,登录的签名标识,这个参数在检查登录是否需要验证码的时候会用到


开启网络监听可以发现,在输入完QQ号码的时候,也就是QQ号码输入框失去焦点的时候,浏览器会发一个请求到腾讯服务器,检查此次登录是否需要输入验证码。请求地址:http://check.ptlogin2.qq.com/check?regmaster=&uin=qq号码&appid=549000912&js_ver=10100&js_type=1&login_sig=-C312hp6B8CxoeIKpP*g2HaPLthAwHxTGa5u5WRgaDwrDi*3DrpjYwh38eh8-nyu&u1=http%3A%2F%2Fqzs.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&r=0.22668678383342922,login_sig是上面得到的安全登录签名标识,其它参数可以不变,这个请求会返回一个字符串,ptui_checkVC('0','!GGG','\x00\x00\x00\x00\x23\xe8\xf1\xd0','ffa99a5e8b464c05ab1666287089353996556b1c4964173e52ac0d76716f2d5676c8b41555aa551e5ad33146945d2041');

这里有四个参数,第一个参数为是否需要验证码,1是,0否。如果第一个参数是0,那么第二个参数直接就是验证码,如果第,一个参数是1,第二个参数则是获取验证码的密文,第三个参数不用管它,第四个参数为登录的时候需要的 pt_verifysession_v1参数,除了第三个参数外,这几个都是很重要的参数。注意,如果此次登录需要验证码,那么第四个参数是空的,那么登录是需要的pt_verifysession_v1参数怎么得到呢


如果登录需要验证码,浏览器会发一个请求获取验证图片,地址是:http://captcha.qq.com/getimage?uin=$qq&aid=549000912&cap_cd=$p2&0.7444603350013494 ,

这里我们只需要注意一下cap_cd这个参数,这个参数是上面讲的第二个参数。这个请求回返回一个cookies值,这个值是保持当前验证码和登录一直的重要参数,抓包的时候查看cookies可以看到verifysession。

以上都是登录前的参数收集,现在我们来看一下登录地址:http://ptlogin2.qq.com/login?u=qq号&verifycode=验证码&pt_vcode_v1=0&pt_verifysession_v1=验证码返回的verifysession&p=加密的密码&pt_rsa=0&u1=http%3A%2F%2Fqzs.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=2-10-1416737142521&js_ver=10100&js_type=1&login_sig=安全登录标识符&pt_uistyle=32&aid=549000912&daid=5&pt_qzone_sig=1&

经过之前的收集 ,我们发现这里只有一个参数我们未知。那就是p参数,那么是怎么加密的呢,我们查看源码,会发现这样一个js文件


加密的算法都在里面了,经过查看源码,我们可以看到它的加密方式,先将密码md5加密,再讲加了密的密码转换为二进制码,然后再和QQ号首尾相连进行md5加密,结果在和验证码首尾相连md5加密,挺复杂的。加密获取p参数  var p = $.Encryption.getEncryption(password,$.str.uin2hex(qq), verifycode);

$.Encryption = function() {
    var hexcase = 1;
    var b64pad = "";
    var chrsz = 8;
    var mode = 32;
    function md5(s) {
        return hex_md5(s)
    }
    function hex_md5(s) {
        return binl2hex(core_md5(str2binl(s), s.length * chrsz))
    }
    function str_md5(s) {
        return binl2str(core_md5(str2binl(s), s.length * chrsz))
    }
    function hex_hmac_md5(key, data) {
        return binl2hex(core_hmac_md5(key, data))
    }
    function b64_hmac_md5(key, data) {
        return binl2b64(core_hmac_md5(key, data))
    }
    function str_hmac_md5(key, data) {
        return binl2str(core_hmac_md5(key, data))
    }
    function core_md5(x, len) {
        x[len >> 5] |= 128 << ((len) % 32);
        x[(((len + 64) >>> 9) << 4) + 14] = len;
        var a = 1732584193;
        var b = -271733879;
        var c = -1732584194;
        var d = 271733878;
        for (var i = 0; i < x.length; i += 16) {
            var olda = a;
            var oldb = b;
            var oldc = c;
            var oldd = d;
            a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
            d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
            c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
            b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
            a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
            d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
            c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
            b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
            a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
            d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
            c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
            b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
            a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
            d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
            c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
            b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
            a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
            d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
            c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
            b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
            a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
            d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
            c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
            b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
            a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
            d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
            c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
            b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
            a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
            d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
            c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
            b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
            a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
            d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
            c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
            b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
            a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
            d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
            c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
            b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
            a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
            d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
            c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
            b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
            a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
            d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
            c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
            b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
            a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
            d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
            c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
            b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
            a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
            d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
            c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
            b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
            a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
            d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
            c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
            b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
            a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
            d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
            c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
            b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
            a = safe_add(a, olda);
            b = safe_add(b, oldb);
            c = safe_add(c, oldc);
            d = safe_add(d, oldd)
        }
        if (mode == 16) {
            return Array(b, c)
        } else {
            return Array(a, b, c, d)
        }
    }
    function md5_cmn(q, a, b, x, s, t) {
        return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b)
    }
    function md5_ff(a, b, c, d, x, s, t) {
        return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t)
    }
    function md5_gg(a, b, c, d, x, s, t) {
        return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t)
    }
    function md5_hh(a, b, c, d, x, s, t) {
        return md5_cmn(b ^ c ^ d, a, b, x, s, t)
    }
    function md5_ii(a, b, c, d, x, s, t) {
        return md5_cmn(c ^ (b | (~d)), a, b, x, s, t)
    }
    function core_hmac_md5(key, data) {
        var bkey = str2binl(key);
        if (bkey.length > 16) {
            bkey = core_md5(bkey, key.length * chrsz)
        }
        var ipad = Array(16),
        opad = Array(16);
        for (var i = 0; i < 16; i++) {
            ipad[i] = bkey[i] ^ 909522486;
            opad[i] = bkey[i] ^ 1549556828
        }
        var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
        return core_md5(opad.concat(hash), 512 + 128)
    }
    function safe_add(x, y) {
        var lsw = (x & 65535) + (y & 65535);
        var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
        return (msw << 16) | (lsw & 65535)
    }
    function bit_rol(num, cnt) {
        return (num << cnt) | (num >>> (32 - cnt))
    }
    function str2binl(str) {
        var bin = Array();
        var mask = (1 << chrsz) - 1;
        for (var i = 0; i < str.length * chrsz; i += chrsz) {
            bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (i % 32)
        }
        return bin
    }
    function binl2str(bin) {
        var str = "";
        var mask = (1 << chrsz) - 1;
        for (var i = 0; i < bin.length * 32; i += chrsz) {
            str += String.fromCharCode((bin[i >> 5] >>> (i % 32)) & mask)
        }
        return str
    }
    function binl2hex(binarray) {
        var hex_tab = hexcase ? "0123456789ABCDEF": "0123456789abcdef";
        var str = "";
        for (var i = 0; i < binarray.length * 4; i++) {
            str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 15) + hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 15)
        }
        return str
    }
    function binl2b64(binarray) {
        var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var str = "";
        for (var i = 0; i < binarray.length * 4; i += 3) {
            var triplet = (((binarray[i >> 2] >> 8 * (i % 4)) & 255) << 16) | (((binarray[i + 1 >> 2] >> 8 * ((i + 1) % 4)) & 255) << 8) | ((binarray[i + 2 >> 2] >> 8 * ((i + 2) % 4)) & 255);
            for (var j = 0; j < 4; j++) {
                if (i * 8 + j * 6 > binarray.length * 32) {
                    str += b64pad
                } else {
                    str += tab.charAt((triplet >> 6 * (3 - j)) & 63)
                }
            }
        }
        return str
    }
    function hexchar2bin(str) {
        var arr = [];
        for (var i = 0; i < str.length; i = i + 2) {
            arr.push("\\x" + str.substr(i, 2))
        }
        arr = arr.join("");
        eval("var temp = '" + arr + "'");
        return temp
    }
    function getEncryption(password, uin, vcode, isMd5) {
        var str1 = hexchar2bin(isMd5 ? password: md5(password));
        var str2 = md5(str1 + uin);
        var str3 = md5(str2 + vcode.toUpperCase());
        return str3
    }
    function getRSAEncryption(password, vcode, isMd5) {
        var str1 = isMd5 ? password: md5(password);
        var str2 = str1 + vcode.toUpperCase();
        var str3 = $.RSA.rsa_encrypt(str2);
        return str3
    }
    return {
        getEncryption: getEncryption,
        getRSAEncryption: getRSAEncryption,
        md5: md5
    }
} ();

$.str = (function() {
    var htmlDecodeDict = {
        quot: '"',
        lt: "<",
        gt: ">",
        amp: "&",
        nbsp: " ",
        "#34": '"',
        "#60": "<",
        "#62": ">",
        "#38": "&",
        "#160": " "
    };
    var htmlEncodeDict = {
        '"': "#34",
        "<": "#60",
        ">": "#62",
        "&": "#38",
        " ": "#160"
    };
    return {
        decodeHtml: function(s) {
            s += "";
            return s.replace(/&(quot|lt|gt|amp|nbsp);/ig,
            function(all, key) {
                return htmlDecodeDict[key]
            }).replace(/&#u([a-f\d]{4});/ig,
            function(all, hex) {
                return String.fromCharCode(parseInt("0x" + hex))
            }).replace(/&#(\d+);/ig,
            function(all, number) {
                return String.fromCharCode( + number)
            })
        },
        encodeHtml: function(s) {
            s += "";
            return s.replace(/["<>& ]/g,
            function(all) {
                return "&" + htmlEncodeDict[all] + ";"
            })
        },
        trim: function(str) {
            str += "";
            var str = str.replace(/^\s+/, ""),
            ws = /\s/,
            end = str.length;
            while (ws.test(str.charAt(--end))) {}
            return str.slice(0, end + 1)
        },
        uin2hex: function(str) {
            var maxLength = 16;
            str = parseInt(str);
            var hex = str.toString(16);
            var len = hex.length;
            for (var i = len; i < maxLength; i++) {
                hex = "0" + hex
            }
            var arr = [];
            for (var j = 0; j < maxLength; j += 2) {
                arr.push("\\x" + hex.substr(j, 2))
            }
            var result = arr.join("");
            eval('result="' + result + '"');
            return result
        },
        bin2String: function(a) {
            var arr = [];
            for (var i = 0,
            len = a.length; i < len; i++) {
                var temp = a.charCodeAt(i).toString(16);
                if (temp.length == 1) {
                    temp = "0" + temp
                }
                arr.push(temp)
            }
            arr = "0x" + arr.join("");
            arr = parseInt(arr, 16);
            return arr
        },
        utf8ToUincode: function(s) {
            var result = "";
            try {
                var length = s.length;
                var arr = [];
                for (i = 0; i < length; i += 2) {
                    arr.push("%" + s.substr(i, 2))
                }
                result = decodeURIComponent(arr.join(""));
                result = $.str.decodeHtml(result)
            } catch(e) {
                result = ""
            }
            return result
        },
        json2str: function(obj) {
            var result = "";
            if (typeof JSON != "undefined") {
                result = JSON.stringify(obj)
            } else {
                var arr = [];
                for (var i in obj) {
                    arr.push("'" + i + "':'" + obj[i] + "'")
                }
                result = "{" + arr.join(",") + "}"
            }
            return result
        },
        time33: function(str) {
            var hash = 0;
            for (var i = 0,
            length = str.length; i < length; i++) {
                hash = hash * 33 + str.charCodeAt(i)
            }
            return hash % 4294967296
        }
    }
})();


好了 ,参数都收集齐了,可以去登录了

登陆返回数据包

58
ptuiCB('0','0','http://web.qq.com/loginproxy.html?login2qq=1&webqq_type=10','0','登录成功!','dzzzzzzzz');

0

QQ登陆错误数据包
ptuiCB('7','0','','0','很遗憾,网络连接出现异常,请您稍后再试。(2772435371)', '624475210');
ptuiCB('3','0','','0','您输入的帐号或密码不正确,请重新输入。', '624475210');
ptuiCB('4','3','','0','登录失败,请重试。*', '624475210');
ptuiCB('4','2','','0','页面过期,请重试。(1485832416)', '602468816');


最后总结一下php模拟登录的几个步骤:

1、访问登录页面,获取login_sig参数,php中通过stream_get_contents函数获取网页内容,通过preg_match正则匹配可获得login_sig

2、检查本次登录是否需要验证码,获取验证码,verifysession参数.

3、如果需要验证码,则获取验证码图片和返回的verifysession,

function _getVImg($url = "", $filename = "") { 

$cookie_file = dirname(__FILE__).'/cookie.txt';

if(is_dir(basename($filename))) { 

echo "The Dir was not exits"; 

Return false; 

//去除URL连接上面可能的引号 

$url = preg_replace( '/(?:^[\'"]+|[\'"\/]+$)/', '', $url ); 

$hander = curl_init(); 

$fp = fopen($filename,'wb'); 

curl_setopt($hander,CURLOPT_URL,$url); 

curl_setopt($hander,CURLOPT_FILE,$fp); 

curl_setopt($hander,CURLOPT_HEADER,0); 

//curl_setopt($hander,CURLOPT_FOLLOWLOCATION,1); 

curl_setopt($hander, CURLOPT_COOKIEJAR,  $cookie_file); //存储cookies

//curl_setopt($hander,CURLOPT_RETURNTRANSFER,false);//以数据流的方式返回数据,当为false是直接显示出来 

curl_setopt($hander,CURLOPT_TIMEOUT,60); 


$content=curl_exec($hander); 

curl_close($hander); 

$fp2 = fopen($cookie_file,'r');

$ses='';

while(!feof($fp2))

{

$ses.=fgets($fp2);

}

$nodle='verifysession ';

$sw= strstr($ses,$nodle);

$result = trim(str_replace($nodle,'',$sw));



fclose($fp); 

fclose($fp2); 

Return $result; 

4、对密码进行加密,得到需要的p参数

var p = $.Encryption.getEncryption(password,$.str.uin2hex(qq), verifycode);

5、构建登录地址:http://ptlogin2.qq.com/login?u=qq号&verifycode=验证码&pt_vcode_v1=0&pt_verifysession_v1=验证码返回的verifysession&p=加密的密码&pt_rsa=0&u1=http%3A%2F%2Fqzs.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=2-10-1416737142521&js_ver=10100&js_type=1&login_sig=安全登录标识符&pt_uistyle=32&aid=549000912&daid=5&pt_qzone_sig=1&   把参数放进去就行了。接下来你知道该怎么做了吧

大功告成!

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页