Neeke

伪全栈攻城狮

Java模拟腾讯微博的网页登录失败

想模拟腾讯微博的网页登录呢,结果没成功,暂时还没找到原因,我觉得应该没问题了啊,记录下来,等有空了继续折腾。 腾讯微博登录页面在这里:http://ui.ptlogin2.qq.com/login_weibo.html 已成功,可以选择继续阅读,或查看[Java模拟腾讯微博的网页登录成功]。 通过分析得到如下信息: 主要JS文件:
http://ui.ptlogin2.qq.com/login_t.js
验证码获取地址:
http://ptlogin2.qq.com/check?uin=9920317&appid=46000101&r=0.2535580481721431
在登录页载入的时候这个请求被发送,这个返回的是一个JavaScript,类似这么个格式:
ptui_checkVC('0','!Y2D')
在页面上通过eval()执行,将第二个参数(验证码)赋给表单的隐藏域。 登录时的请求:
http://ptlogin2.qq.com/login?u=9920317&p=33FB075FEFD31C2BBD38E3D1CD71491D&verifycode=!Y2D&aid=46000101&u1=http://t.qq.com&h=1&from_ui=1&fp=loginerroralert
通过测试发现登录时的参数p的值(MD5加密后的密码)每次都不一样,刚开始有点纳闷,假设数据库里面存的是33FB075FEFD31C2BBD38E3D1CD71491D,而我登录的时候发送的是33FB075FEFD31C2BBD38E3D1CD71491A或者33FB075FEFD31C2BBD38E3D1CD71491E,他这是怎么判断密码是否一致的?后来分析了login_t.js,其实腾讯的这个登录与之前我做过的[支付宝接口开发]和[支付宝接口开发(ColdFusion版)]是同一个道理。 从login_t.js中可以找到如下代码:
var f = "";
f += e.verifycode.value;
f = f.toUpperCase();
b += md5(md5_3(e.p.value) + f)
先将输入的原始密码A通过md5_3()加密得到字符串B,接着将验证码追加到B之后得到C,再用md5()加密C得到D。原始密码当然是不变的,而验证码每次都不一样(当然也有几率一样),这就是为什么每次发送的MD5值都不一样的原因了。 从登录的请求中可以找到verifycode这个参数,打眼一看就知道是验证码啦,从客户端将上面得到的D与verifycode都发送到服务器端,服务器端通过u值(QQ号)查出上面的密码B,然后在服务器端对B+verifycode进行md5求值,将结果与发送过来的D进行比较,一致则登录成功,反之失败。(这些都是结合支付宝那个猜的) 其它参数基本上都是死值,除了获取验证码时传递的那个随机数r。 都分析清楚了,我就用Java开工了,写了下面这么个类(因为是瞎捣鼓,所以没考虑什么规范):
public class QQ {

	public String md5(String p){
		return hex_md5(p);
	}

	public String md5_3(String p){
		
		int s[] = null;
	    s = core_md5(str2binl(p), p.length() * 8);
	    s = core_md5(s, 16 * 8);
	    s = core_md5(s, 16 * 8);
	    return binl2hex(s);
	}
	
	public String hex_md5(String p) {
	    return binl2hex(core_md5(str2binl(p), p.length() * 8));
	}
	
	public int[] core_md5(int[] s, int k){
		s[k >> 5] |= 128 << (k % 32);
		s[(((k + 64) >>> 9) << 4) + 14] = k;
		int o = 1732584193;
		int n = -271733879;
		int m = -1732584194;
		int l = 271733878;
		for (int g = 0; g < s.length; g += 16) {
	        int j = o;
	        int h = n;
	        int f = m;
	        int e = l;
	        o = md5_ff(o, n, m, l, s[g + 0], 7, -680876936);
	        l = md5_ff(l, o, n, m, s[g + 1], 12, -389564586);
	        m = md5_ff(m, l, o, n, s[g + 2], 17, 606105819);
	        n = md5_ff(n, m, l, o, s[g + 3], 22, -1044525330);
	        o = md5_ff(o, n, m, l, s[g + 4], 7, -176418897);
	        l = md5_ff(l, o, n, m, s[g + 5], 12, 1200080426);
	        m = md5_ff(m, l, o, n, s[g + 6], 17, -1473231341);
	        n = md5_ff(n, m, l, o, s[g + 7], 22, -45705983);
	        o = md5_ff(o, n, m, l, s[g + 8], 7, 1770035416);
	        l = md5_ff(l, o, n, m, s[g + 9], 12, -1958414417);
	        m = md5_ff(m, l, o, n, s[g + 10], 17, -42063);
	        n = md5_ff(n, m, l, o, s[g + 11], 22, -1990404162);
	        o = md5_ff(o, n, m, l, s[g + 12], 7, 1804603682);
	        l = md5_ff(l, o, n, m, s[g + 13], 12, -40341101);
	        m = md5_ff(m, l, o, n, s[g + 14], 17, -1502002290);
	        n = md5_ff(n, m, l, o, s[g + 15], 22, 1236535329);
	        o = md5_gg(o, n, m, l, s[g + 1], 5, -165796510);
	        l = md5_gg(l, o, n, m, s[g + 6], 9, -1069501632);
	        m = md5_gg(m, l, o, n, s[g + 11], 14, 643717713);
	        n = md5_gg(n, m, l, o, s[g + 0], 20, -373897302);
	        o = md5_gg(o, n, m, l, s[g + 5], 5, -701558691);
	        l = md5_gg(l, o, n, m, s[g + 10], 9, 38016083);
	        m = md5_gg(m, l, o, n, s[g + 15], 14, -660478335);
	        n = md5_gg(n, m, l, o, s[g + 4], 20, -405537848);
	        o = md5_gg(o, n, m, l, s[g + 9], 5, 568446438);
	        l = md5_gg(l, o, n, m, s[g + 14], 9, -1019803690);
	        m = md5_gg(m, l, o, n, s[g + 3], 14, -187363961);
	        n = md5_gg(n, m, l, o, s[g + 8], 20, 1163531501);
	        o = md5_gg(o, n, m, l, s[g + 13], 5, -1444681467);
	        l = md5_gg(l, o, n, m, s[g + 2], 9, -51403784);
	        m = md5_gg(m, l, o, n, s[g + 7], 14, 1735328473);
	        n = md5_gg(n, m, l, o, s[g + 12], 20, -1926607734);
	        o = md5_hh(o, n, m, l, s[g + 5], 4, -378558);
	        l = md5_hh(l, o, n, m, s[g + 8], 11, -2022574463);
	        m = md5_hh(m, l, o, n, s[g + 11], 16, 1839030562);
	        n = md5_hh(n, m, l, o, s[g + 14], 23, -35309556);
	        o = md5_hh(o, n, m, l, s[g + 1], 4, -1530992060);
	        l = md5_hh(l, o, n, m, s[g + 4], 11, 1272893353);
	        m = md5_hh(m, l, o, n, s[g + 7], 16, -155497632);
	        n = md5_hh(n, m, l, o, s[g + 10], 23, -1094730640);
	        o = md5_hh(o, n, m, l, s[g + 13], 4, 681279174);
	        l = md5_hh(l, o, n, m, s[g + 0], 11, -358537222);
	        m = md5_hh(m, l, o, n, s[g + 3], 16, -722521979);
	        n = md5_hh(n, m, l, o, s[g + 6], 23, 76029189);
	        o = md5_hh(o, n, m, l, s[g + 9], 4, -640364487);
	        l = md5_hh(l, o, n, m, s[g + 12], 11, -421815835);
	        m = md5_hh(m, l, o, n, s[g + 15], 16, 530742520);
	        n = md5_hh(n, m, l, o, s[g + 2], 23, -995338651);
	        o = md5_ii(o, n, m, l, s[g + 0], 6, -198630844);
	        l = md5_ii(l, o, n, m, s[g + 7], 10, 1126891415);
	        m = md5_ii(m, l, o, n, s[g + 14], 15, -1416354905);
	        n = md5_ii(n, m, l, o, s[g + 5], 21, -57434055);
	        o = md5_ii(o, n, m, l, s[g + 12], 6, 1700485571);
	        l = md5_ii(l, o, n, m, s[g + 3], 10, -1894986606);
	        m = md5_ii(m, l, o, n, s[g + 10], 15, -1051523);
	        n = md5_ii(n, m, l, o, s[g + 1], 21, -2054922799);
	        o = md5_ii(o, n, m, l, s[g + 8], 6, 1873313359);
	        l = md5_ii(l, o, n, m, s[g + 15], 10, -30611744);
	        m = md5_ii(m, l, o, n, s[g + 6], 15, -1560198380);
	        n = md5_ii(n, m, l, o, s[g + 13], 21, 1309151649);
	        o = md5_ii(o, n, m, l, s[g + 4], 6, -145523070);
	        l = md5_ii(l, o, n, m, s[g + 11], 10, -1120210379);
	        m = md5_ii(m, l, o, n, s[g + 2], 15, 718787259);
	        n = md5_ii(n, m, l, o, s[g + 9], 21, -343485551);
	        o = safe_add(o, j);
	        n = safe_add(n, h);
	        m = safe_add(m, f);
	        l = safe_add(l, e);
	    }
		int[] rs = new int[16];
		rs[0] = o;
		rs[1] = n;
		rs[2] = m;
		rs[3] = l;
		return rs;
	}
	
	public int[] str2binl(String p){
		
		int[] s = new int[16];
		int a = 254;
		for(int i = 0; i < p.length() * 8; i += 8){
			s[ i >> 5] |= ((p.charAt(i / 8)) & a + 1) << (i % 32);
		}
		return s;
	}
	
	public static void main(String[] args){
		QQ q = new QQ();
		String verifyURL = "http://ptlogin2.qq.com/check?uin=9920317&appid=46000101&r=0.37908964480776913";
		String loginURL = "http://ptlogin2.qq.com/login?";
		String redirectURL = "";
		String cookie = "";
		String qqn = "9920317";
		String md5Pass = "";
		String verifyCode = "";
		
		HttpURLConnection urlConn = (HttpURLConnection)(new URL(verifyURL)).openConnection();
		urlConn.setDoOutput(true);
		urlConn.setDoInput(true);
		urlConn.setUseCaches(false);
		urlConn.setAllowUserInteraction(false);
		urlConn.setRequestMethod("GET");
		urlConn.connect();
		String cookie1 = urlConn.getHeaderField("Set-Cookie");
		BufferedReader br = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
		StringBuffer sb = new StringBuffer();
		String str = br.readLine();
		while(null != str){
			sb.append(str);
			str = br.readLine();
		}
		br.close();
		urlConn.disconnect();
		verifyCode = sb.substring(18, sb.length() - 3);
		
		loginURL += "u=9920317&p=";
		loginURL += qq.md5(qq.md5_3("") + verifyCode.toUpperCase());
		loginURL += "&verifycode="+verifyCode.toUpperCase()+"&aid=46000101&u1=http%3A%2F%2Ft.qq.com&h=1&from_ui=1&fp=loginerroralert";
		urlConn = (HttpURLConnection)(new URL(loginURL)).openConnection();
		urlConn.setDoOutput(true);
		urlConn.setDoInput(true);
		urlConn.setUseCaches(false);
		urlConn.setAllowUserInteraction(false);
		urlConn.setRequestProperty("Cookie", cookie1);
		urlConn.connect();
		String[] setCookies = urlConn.getHeaderFields().get("Set-Cookie").toString().split(";");
		
		String cookie2 = "";
		cookie2 += setCookies[30];
		cookie2 += setCookies[27];
		cookie2 += setCookies[24];
		cookie2 += setCookies[4];
		cookie2 = cookie2.replace(',', ';');
		cookie2 = cookie2.substring(2, cookie2.length());
		out.print(cookie2 + "
"); br = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));; str = br.readLine(); sb = new StringBuffer(); while(null != str){ sb.append(str); str = br.readLine(); } br.close(); urlConn.disconnect(); } public int md5_cmn(int h, int e, int d, int c, int g, int f){ return safe_add(bit_rol(safe_add(safe_add(e, h), safe_add(c, f)), g), d); } public int md5_ff(int g, int f, int k, int j, int e, int i, int h) { return md5_cmn((f & k) | ((~f) & j), g, f, e, i, h); } public int md5_gg(int g, int f, int k, int j, int e, int i, int h) { return md5_cmn((f & j) | (k & (~j)), g, f, e, i, h); } public int md5_hh(int g, int f, int k, int j, int e, int i, int h) { return md5_cmn(f ^ k ^ j, g, f, e, i, h); } public int md5_ii(int g, int f, int k, int j, int e, int i, int h) { return md5_cmn(k ^ (f | (~j)), g, f, e, i, h); } public int safe_add(int a, int d){ int c = (a & 65535) + (d & 65535); int b = (a >> 16) + (d >> 16) + (c >> 16); return (b << 16) | (c & 65535); } public int bit_rol(int a, int b){ return (a << b) | (a >>> (32 - b)); } public String binl2hex(int[] c) { String b = "0123456789ABCDEF"; String d = ""; for (int a = 0; a > 2] >> ((a % 4) * 8 + 4)) & 15); char y = (char)b.charAt((c[a >> 2] >> ((a % 4) * 8)) & 15); d += x; d += y; } return d.substring(0, 32); } }
跑了几次都返回的是:
ptuiCB('7','0','','0');
提示:您的输入有误, 请重试。 而按理来说返回的应该是:
ptuiCB('0','0','http://t.qq.com','0');
密码错误则是:
ptuiCB('3','0','','0');
用同样的参数在我写的和官方JavaScript产生的请求地址是一模一样的,可就是不成功。 目前想到的两点: 1.我使用了两次HttpURLConnection,Session不一致。 2.服务器上对Referer进行了验证。 虽说没成功,但是也学到了不少,NND,光这个login_t.js里面的算法就够学的了 n:-gg 。 发现一个有意思的地方:在login_t.js的str2binl函数中有如下一行代码(chrsz是个常数8,我的代码中直接写的8):
c[b>>5] |= (d.charCodeAt(b / chrsz) & a) << (b % 32)
而我用Java语言来写这个方法时必须得写成这样:
s[i>> 5] |= ((p.charAt(i / 8)) & a + 1) << (i % 32);
不然结果就不一致。
  • 评论列表:
  •  转烛
     发布于 2010-09-19 21:22:16  回复该评论
  • 不知道为什么一直在登录获取cookie时出错,获得不到cookie,就是get("Set-Cookie")是空的。
    •  neeke
       发布于 2010-09-20 09:06:34  回复该评论
    • n:-sk 你的http请求是不是没连接成功啊?
      •  转烛
         发布于 2010-09-20 09:11:31  回复该评论
      • 连接成功了,第一步有返回,第二步也有返回,只不过返回值里没有Set-Cookie,还告诉我输入的用户错误,但是我已经尝试了几个用户,不可能是错误的用户,php下试验时可以的,java始终不行。
        •  neeke
           发布于 2010-09-20 09:30:50  回复该评论
        • 呵呵 用户错误?如果你参数中使用的是用户名,那么用户名前必须加@,不然就提示这个错误,如果是QQ号则不需要加。
          •  转烛
             发布于 2010-09-20 09:36:24  回复该评论
          • 非常感谢,的确是没有@的缘故。。。完全没有留意到这个。。。貌似我获得的set-cookie比你的少,难道登录方式又变了?继续进行下一步发表的测试,有问题还得麻烦你呢。
  •  nihao
     发布于 2010-09-21 16:46:19  回复该评论
  • 你好!谢谢你的文章。我有个问题想请教一下,在个人微博页码,我想抓取全部个人微博,怎么显示出所有的微博呢?望不吝赐教!
    •  neeke
       发布于 2010-09-23 10:41:10  回复该评论
    • 那个...腾讯那边展示的是分页的,你找找分页规律,每个页面都抓取一下应该就可以了。
    •  haha109
       发布于 2010-12-12 20:32:32  回复该评论
    • 你好,请问下在登录成功的状态下如何去获得微薄的内容呢?爬去的链接是哪个呢?
      •  neeke
         发布于 2010-12-13 13:55:08  回复该评论
      • 解析登录成功后的页面呀。参见:http://www.ineeke.com/archives/tencent-microblog-api/
        •  haha109
           发布于 2010-12-13 15:09:41  回复该评论
        • 你好,我对PHP不是太熟悉,能加你QQ吗?我的是412965470
          •  neeke
             发布于 2010-12-13 15:47:10  回复该评论
          • n:-sk 杯具...我对PHP也不熟,那个我还是现学现卖的,我主要搞java。
            •  haha109
               发布于 2010-12-13 15:51:04  回复该评论
            • 呵呵,就是因为你给我那个参考页面是PHP写的,我用的也是Java,所以想问你呢
  •  lifehopper
     发布于 2010-10-03 15:16:53  回复该评论
  • java6已经有了javascript引擎,完全可以照搬在本地存一个js文件,之后用java直接调用,楼主费尽心机的javasource,应该可以避免:)
    •  neeke
       发布于 2010-10-07 14:23:54  回复该评论
    • 哦?孤陋寡闻了,还真不知道。
  •  明锐
     发布于 2010-10-25 09:38:46  回复该评论
  • 楼主啊、我想问一下,在拿验证码那一块,后面那个随机的r要怎么拿的啊。或者说怎么拿它这个验证码图片的地址啊、?
    •  neeke
       发布于 2010-10-25 11:30:20  回复该评论
    • 那个R你可以不用理睬,其实有没有都无所谓,腾讯是通过JavaScript取的随机数。据我测试,一般情况下腾讯是不出现图片验证码的,除非你登录过程中多次出现登录异常(密码错误之类的),至于那张图片的地址,你在它上面右键看属性就可以看到啦。
  •  wangydm
     发布于 2011-05-25 20:22:51  回复该评论
  • 不能由mail.qq.com处登陆,再跳转到QQ徽博吗?这样要容易得多,楼主可加我QQ:8728609探讨下
    •  neeke
       发布于 2011-05-26 08:42:23  回复该评论
    • 呵呵 这个都是当时自己的一些想法瞎折腾的,没想太周全。
  •  Vanior
     发布于 2012-10-20 16:40:19  回复该评论
  • LZ你好。。我也在试着写这个模拟登陆。。。一直登陆不成功,求指教。。
    •  neeke
       发布于 2012-10-24 21:20:40  回复该评论
    • 用smartsniff抓包分析吧
      •  Vanior
         发布于 2012-10-24 21:50:47  回复该评论
      • @Neeke: 抓包了。。加密密码是对的,但是返回结果一直是ptuiCB('4','3',。。。。。
        呜呜,还有个问题想请教,你们怎么知道验证码,在那个url可以得到,我登陆抓包并没有看到有那个url。。。呜呜呜。。
  •  天亮
     发布于 2012-11-26 11:56:05  回复该评论
  • 楼主好,你这个登陆应该是旧版腾讯微博登陆,有新版的模拟登陆吗?
    •  neeke
       发布于 2012-11-27 10:09:26  回复该评论
    • 没有的,自从腾讯微博提供了API接口及各种调用挂件之后就没研究这个了,你可以自己抓数据包分析分析的。
      •  爱之物语
         发布于 2013-07-26 16:58:04  回复该评论
      • @Neeke: 最近你的腾讯微博的模拟登陆做出来了吗???可不可以给我间借鉴的看看一下,请加:997659148
        •  neeke
           发布于 2013-07-29 10:15:47  回复该评论
        • 呃...这玩意早就不折腾了,腾讯现在不是已经开放API了嘛

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

«   2016年11月   »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
搜索
最新留言
文章归档
友情链接

Powered By Z-BlogPHP 1.5 Zero

Copyright Your WebSite.Some Rights Reserved.