1. 程式人生 > >C#實現QQ群成員列表匯出及郵件群發之模擬QQ登陸

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&regmaster=&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 Code

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號碼,密碼,驗證碼三個引數,有興趣的可自己研究下。

程式碼如下:

複製程式碼
 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模擬登陸已經成功,完成了獲取群列表的第一步。下面一篇就到獲取群列表,群成員。