首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 實現 QQ 群成員匯出與群發郵件(二):模擬 QQ 登入取得 Cookie

     編輯:關於C#

系列第二篇:模擬 QQ 網頁版登入,核心流程——抓包分析登入端點、驗證碼獲取、密碼加密演算法(MD5 多輪雜湊)、HTTP POST 取得 Cookie。

抓包分析:兩個關鍵請求

1. 驗證碼檢查端點

輸入帳號後自動請求:

GET https://check.ptlogin2.qq.com/check?
    uin={QQ號}&appid=1006102&r={隨機數}
    &js_ver=10038&js_type=1
    &login_sig=...&u1=http%3A%2F%2Fqzs.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone

回傳 JS 片段:

  • ptui_checkVC('0','!JWE',...) → 不需圖形驗證碼,第二參數為 verifycode
  • ptui_checkVC('1',...) → 需圖形驗證碼,需額外請求圖片端點

2. 圖形驗證碼圖片端點(僅需時呼叫)

GET https://captcha.qq.com/getimage?aid=1006102&r={隨機數}&uin={QQ號}

3. 登入提交端點

GET https://ptlogin2.qq.com/login?
    u={QQ號}&p={加密密碼}&verifycode={驗證碼}
    &aid=1006102&u1=http%3A%2F%2Fid.qq.com%2Findex.html
    &h=1&ptredirect=1&ptlang=2052&from_ui=1
    &fp=loginerroralert&action=...&mibao_css=&t=1&g=1
    &js_ver=10038&js_type=1&login_sig=...

成功回傳:ptuiCB('0','0','https://id.qq.com/index.html','1','登錄成功!', 'xxx')

密碼加密演算法(C# 移植)

騰訊採三層 MD5:

  1. P = MD5(密碼明文)
  2. U = MD5(P + QQ號十六進位)
  3. V = MD5(U + verifycode大寫) → 最終提交密碼
public static class PasswordHelper {
    public static string GetPassword(string qqNum, string pwd, string verifycode) {
        // QQ 號轉 16 位十六進位
        var uinHex = int.Parse(qqNum).ToString("x").PadLeft(16, '0');

        // P = MD5(pwd)
        var P = MD5(pwd);
        // U = MD5(P + uinHex)
        var U = MD5(P + HexToBin(uinHex)).ToUpper();
        // V = MD5(U + verifycode)
        var V = MD5(U + verifycode.ToUpper()).ToUpper();
        return V;
    }

    static string MD5(string input) {
        using (var md5 = System.Security.Cryptography.MD5.Create()) {
            var bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(input);
            return BitConverter.ToString(md5.ComputeHash(bytes)).Replace("-", "").ToLower();
        }
    }

    static string HexToBin(string hex) {
        var sb = new StringBuilder();
        for (int i = 0; i < hex.Length; i += 2)
            sb.Append((char)Convert.ToInt32(hex.Substring(i, 2), 16));
        return sb.ToString();
    }
}

HTTP 輔助類(GET 請求 + Cookie 容器)

public static class HttpHelper {
    const string userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36";
    const string accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
    const string contentType = "application/x-www-form-urlencoded";
    const string referer = "https://ui.ptlogin2.qq.com/";

    public static Stream GetStream(string url, CookieContainer cc) {
        var req = (HttpWebRequest)WebRequest.Create(url);
        req.CookieContainer = cc;
        req.UserAgent = userAgent; req.Accept = accept; req.ContentType = contentType; req.Referer = referer;
        req.Method = "GET"; req.ServicePoint.ConnectionLimit = int.MaxValue;
        return req.GetResponse().GetResponseStream();
    }

    public static string GetHtml(string url, CookieContainer cc) {
        Thread.Sleep(1000); // 禮貌延遲
        using (var stream = GetStream(url, cc))
        using (var reader = new StreamReader(stream, Encoding.UTF8))
            return reader.ReadToEnd();
    }
}

完整登入流程

// 1. 取得驗證碼
var vcHtml = HttpHelper.GetHtml($"https://check.ptlogin2.qq.com/check?uin={qq}&appid=1006102&r={rnd.NextDouble()}", _cookie);
string verifycode;
if (vcHtml.Contains("ptui_checkVC('0','")) {
    verifycode = vcHtml.Replace("ptui_checkVC('0','", "").Replace("')", "").Substring(0, 4);
} else {
    // 需圖形驗證碼:顯示圖片讓使用者手動輸入
    var imgStream = HttpHelper.GetStream($"https://captcha.qq.com/getimage?aid=1006102&r={rnd.NextDouble()}&uin={qq}", _cookie);
    picCaptcha.Image = Image.FromStream(imgStream);
    verifycode = txtManualInput.Text; // 使用者輸入
}

// 2. 計算加密密碼
var pwdEncrypted = PasswordHelper.GetPassword(qq, txtPwd.Text, verifycode);

// 3. 提交登入
var loginUrl = $"https://ptlogin2.qq.com/login?u={qq}&p={pwdEncrypted}&verifycode={verifycode}&aid=1006102&u1=http%3A%2F%2Fid.qq.com%2Findex.html&h=1&ptredirect=1&ptlang=2052&from_ui=1&fp=loginerroralert&action=8-29-82478035&mibao_css=&t=1&g=1";
var ret = HttpHelper.GetHtml(loginUrl, _cookie);

// 4. 判斷成功
bool ok = ret.Contains("ptuiCB('0',");
if (ok) MessageBox.Show("登入成功,Cookie 已儲存!");

登入成功後,_cookie 即攜帶 skey 等關鍵憑證,供下一篇群組/成員抓取使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved