C#實現QQ群成員列表匯出及郵件群發之模擬QQ登陸
前言
本文的重要部分:
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=46Flu6g0o2A1hcewVAPUpItgSNJncoqujR4vudgX8ZRnruuCSOzMGcbd3CnQhw0y&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®master=&fp=loginerroralert&action=11-52-1375668422981&mibao_css=&t=1&g=1&js_ver=10038&js_type=1&login_sig=46Flu6g0o2A1hcewVAPUpItgSNJncoqujR4vudgX8ZRnruuCSOzMGcbd3CnQhw0y
引數0:QQ號碼,引數1:加密以後的密碼,引數2:返回的驗證碼
本人文字功底實在太差,說不太清楚,抓包需要我多次試驗,多次分析,才可取得正確的地址。登陸的最重要目的是獲取請求頁面的cookie。
程式碼部分
1、http請求幫助程式碼
View Code2、獲取驗證碼
//取驗證碼 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號碼,密碼,驗證碼三個引數,有興趣的可自己研究下。
程式碼如下:
1 public static class PasswordHelper 2 { 3 /// <summary> 4 /// 根據QQ號碼和驗證碼加密密碼 5 /// </summary> 6 /// <param name="qqNum">QQ號碼</param> 7 /// <param name="password">QQ密碼</param> 8 /// <param name="verifycode">驗證碼</param> 9 /// <returns>密碼密文</returns> 10 public static string GetPassword(string qqNum, string password, string verifycode) 11 { 12 //uin為QQ號碼轉換為16位的16進位制 13 int qq; 14 int.TryParse(qqNum, out qq); 15 16 qqNum = qq.ToString("x"); 17 qqNum = qqNum.PadLeft(16, '0'); 18 19 String P = hexchar2bin(md5(password)); 20 String U = md5(P + hexchar2bin(qqNum)).ToUpper(); 21 String V = md5(U + verifycode.ToUpper()).ToUpper(); 22 return V; 23 } 24 25 public static string md5(string input) 26 { 27 byte[] buffer = MD5.Create().ComputeHash(Encoding.GetEncoding("ISO-8859-1").GetBytes(input)); 28 return binl2hex(buffer); 29 } 30 31 public static string binl2hex(byte[] buffer) 32 { 33 StringBuilder builder = new StringBuilder(); 34 for (int i = 0; i < buffer.Length; i++) 35 { 36 builder.Append(buffer[i].ToString("x2")); 37 } 38 return builder.ToString(); 39 } 40 41 public static string hexchar2bin(string passWord) 42 { 43 StringBuilder builder = new StringBuilder(); 44 for (int i = 0; i < passWord.Length; i = i + 2) 45 { 46 builder.Append(Convert.ToChar(Convert.ToInt32(passWord.Substring(i, 2), 16))); 47 } 48 return builder.ToString(); 49 } 50 }
到此為止,登陸需要的引數已經全了,下面就是實現登陸拿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=loginerroralert&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模擬登陸已經成功,完成了獲取群列表的第一步。下面一篇就到獲取群列表,群成員。