前言
本文的重要部分:
1、抓包獲取QQ空間或者郵箱登陸地址,分析參數,用戶名,密碼, 驗證碼,gtk,隨即數。
2、獲取每次登陸需要的驗證碼
3、用戶名,密碼,驗證碼加密得到登 陸密碼
4、Http模擬登陸拿cookie
本文實驗的思路也可換另一種方式,抓包獲取登陸的js,用代 碼操作js來計算密碼 ,gtk等實現登陸。
抓包
1、我們來訪問qq空間的地址http://i.qq.com/ ,打開網站,我們可以看到登陸的對話框,首先我們輸入一個錯誤的賬號和密碼,抓起提交的地址。
2、輸入用戶名和密碼之後我們用抓包工具看到有2個後台請求的地址,如下圖
>
我們可以根據返回的代碼可以看出第二個圖的地址是QQ登陸後台get請求的地址,所以我們實現登陸就是像這 個地址提交數據。第一張圖則是空間登陸每次返回的驗證碼產生的地址,通過多次輸入正確用戶名密碼,第一 張圖地址返回類似ptui_checkVC('0','!JWE','\x00\x00\x00\x00\x46\x86\xd2\x36');代碼,其中括號內參數 與登陸請求地址中verifycode=!JWE每次相同,這個便是登陸的驗證碼,登陸地址則返回類似ptuiCB ('0','0','http://qzs.qq.com/qzone/v5/loginsucc.html? para=izone','0','登錄成功!', 'xxx');返回此代碼則說明登陸成功。
通過抓包我們提取出來的2個地址:
1、驗證碼獲取地址(輸入用戶名時返回):
http://check.ptlogin2.qq.com/check?regmaster=&uin={0} &appid=549000912&js_ver=10038&js_type=1&login_sig=46Flu6g0o2A1hcewVAPUpItgSNJnco qujR4vudgX8ZRnruuCSOzMGcbd3CnQhw0y&u1=http%3A%2F%2Fqzs.qq.com%2Fqzone%2Fv5% 2Floginsucc.html%3Fpara%3Dizone&r={1}
參數0:QQ賬號,參數1:隨即數
說明:一般情 況下是不會產生手動輸入驗證碼的情況下,若是QQ號碼不存在或者錯誤,此時會出現圖片驗證碼,我們可以用 一個處理一下顯示在imge中手動輸入。
2、登陸提交地址:
http://ptlogin2.qq.com/login? u={0}&p={1}&verifycode={2}&aid=549000912&u1=http%3A%2F%2Fqzs.qq.com%2Fqzone% 2Fv5%2Floginsucc.html%3Fpara% 3Dizone&h=1&ptredirect=0&ptlang=2052&from_ui=1&dumy=&low_login_enable=0& amp;regmaster=&fp=loginerroralert&action=11-52- 1375668422981&mibao_css=&t=1&g=1&js_ver=10038&js_type=1&login_sig=46Flu6 g0o2A1hcewVAPUpItgSNJncoqujR4vudgX8ZRnruuCSOzMGcbd3CnQhw0y
參數0:QQ號碼,參數1:加密以後 的密碼,參數2:返回的驗證碼
本人文字功底實在太差,說不太清楚,抓包需要我多次試驗,多次分析 ,才可取得正確的地址。登陸的最重要目的是獲取請求頁面的cookie。
代碼部分
1、http請求 幫助代碼
public class HttpHelper { /// <summary> /// 獲取字符流 /// </summary> /// <param name="url"></param> /// <param name="cookieContainer"></param> /// <returns></returns> public static Stream GetStream(string url, CookieContainer cookieContainer) { HttpWebRequest httpWebRequest = null; HttpWebResponse httpWebResponse = null; try { httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url); httpWebRequest.CookieContainer = cookieContainer; httpWebRequest.ContentType = contentType; httpWebRequest.Referer = referer; httpWebRequest.Accept = accept; httpWebRequest.UserAgent = userAgent; httpWebRequest.Method = "GET"; httpWebRequest.ServicePoint.ConnectionLimit = int.MaxValue; httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse(); Stream responseStream = httpWebResponse.GetResponseStream(); return responseStream; } catch (Exception) { return null; } } /// <summary> /// 獲取HTML /// </summary> /// <param name="url"></param> /// <param name="cookieContainer"></param> /// <returns></returns> public static string GetHtml(string url, CookieContainer cookieContainer) { Thread.Sleep(1000); HttpWebRequest httpWebRequest = null; HttpWebResponse httpWebResponse = null; try { httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url); httpWebRequest.CookieContainer = cookieContainer; httpWebRequest.ContentType = contentType; httpWebRequest.Referer = referer; httpWebRequest.Accept = accept; httpWebRequest.UserAgent = userAgent; httpWebRequest.Method = "GET"; httpWebRequest.ServicePoint.ConnectionLimit = int.MaxValue; httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse(); Stream responseStream = httpWebResponse.GetResponseStream(); StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8); string html = streamReader.ReadToEnd(); streamReader.Close(); responseStream.Close(); httpWebRequest.Abort(); httpWebResponse.Close(); return html; } catch (Exception) { return string.Empty; } } }
2、獲取驗證碼
//取驗證碼 public static string GetVerfiyCode(string qqnum,CookieContainer cookie) { Random rand = new Random(); double r = rand.NextDouble(); string checkcodeurl = string.Format(@"http://check.ptlogin2.qq.com/check?uin={0} &appid=1006102&r={1}", qqnum, r); Stream stream = HttpHelper.GetStream(checkcodeurl, cookie); StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); return streamReader.ReadToEnd(); } //取圖片驗證碼,可將驗證碼直接輸出在image中 public static Stream GetVerfycodeImage(CookieContainer cookie, string qqnum) { Random rand = new Random(); double r = rand.NextDouble(); string codeimageurl = string.Format("http://captcha.qq.com/getimage? aid=1006102&r={0}&uin={1}", r, qqnum); return HttpHelper.GetStream(codeimageurl, cookie); }
通過GetVerfiyCode()的返回 值判斷,是否需要手動輸入驗證碼
//得驗證嗎 if (retString.Contains("ptui_checkVC('0','")) { //不需要手動輸入 this.txtverfiycode.Text = retString.Replace("ptui_checkVC('0','", "").Replace ("'", "").Replace(")", "").Replace(";", "").Substring(0, 4); } else if (retString.Contains("ptui_checkVC('1',")) { //需要手動輸入,將驗證碼輸出在image中 this.vefycodpicbox.Image = Image.FromStream(GetVerfycodeImage(retString, this.txtUseraccount.Text)); }
3、計算密碼,密碼的計算方法可以通過js計算,或者直接使用如下c#版的,總的來 說騰訊的密碼加密比較麻煩,需要QQ號碼,密碼,驗證碼三個參數,有興趣的可自己研究下。
代碼如 下:
public static class PasswordHelper { /// <summary> /// 根據QQ號碼和驗證碼加密密碼 /// </summary> /// <param name="qqNum">QQ號碼</param> /// <param name="password">QQ密碼</param> /// <param name="verifycode">驗證碼</param> /// <returns>密碼密文</returns> public static string GetPassword(string qqNum, string password, string verifycode) { //uin為QQ號碼轉換為16位的16進制 int qq; int.TryParse(qqNum, out qq); qqNum = qq.ToString("x"); qqNum = qqNum.PadLeft(16, '0'); String P = hexchar2bin(md5(password)); String U = md5(P + hexchar2bin(qqNum)).ToUpper(); String V = md5(U + verifycode.ToUpper()).ToUpper(); return V; } public static string md5(string input) { byte[] buffer = MD5.Create().ComputeHash(Encoding.GetEncoding("ISO-8859- 1").GetBytes(input)); return binl2hex(buffer); } public static string binl2hex(byte[] buffer) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < buffer.Length; i++) { builder.Append(buffer[i].ToString("x2")); } return builder.ToString(); } public static string hexchar2bin(string passWord) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < passWord.Length; i = i + 2) { builder.Append(Convert.ToChar(Convert.ToInt32(passWord.Substring(i, 2), 16))); } return builder.ToString(); } }
到此為止,登陸需要的參數已經全了,下面就是實現登陸拿cookie。
4、登陸的方法與 獲取驗證碼一樣
//登錄方法 public static bool IsLogin(string qqnum,string code,string passwords,CookieContainer cookie) { string password = PasswordHelper.GetPassword(qqnum, passwords, code); string loginUrlstring = @"http://ptlogin2.qq.com/login?u=" + qqnum + "&p=" + password + "&verifycode=" + code + "&aid=1006102&u1=http%3A%2F%2Fid.qq.com% 2Findex.html&h=1&ptredirect=1&ptlang=2052&from_ui=1&dumy=&fp=loginerrora lert&action=8-29-82478035&mibao_css=&t=1&g=1"; Stream stream = HttpHelper.GetStream(loginUrlstring, cookie); StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); string retString = streamReader.ReadToEnd();// retString "ptuiCB ('0','0','http://id.qq.com/index.html','1','登錄成功!', 'xxx');\r\n" string return retString.Contains("ptuiCB('0',") ? true : false; }
我們可以直接調用此方法驗證是否登陸成功,同時將cookie保存在一個全局變量中供以後使用。
到此為止,QQ用http模擬登陸已經成功,完成了獲取群列表的第一步。下面一篇就到獲取群列表,群 成員。