淘寶滑動驗證碼研究


引言

悠閑的時候,總會去找些事做做。前些天在登錄淘寶的時候,發現了滑動驗證碼,雖然已經不是什么新事物,但還是產生了很大的興趣。

 

傳統的字符輸入驗證碼,變為了滑動驗證碼,這一看就是產品大師的手筆啊,不知道申請專利沒有。

這種“情感化”的驗證碼設計,可破解度高不高呢?如果是可破解度高,那就真是驗證碼的一次革命變新了。還是讓我先了解一下滑動驗證碼的資料吧!

沒有Google就百度,搜一搜,讓我很震驚,一般搜技術的東西,大多數來源於csdn,blogs.cn,更牛批一點的是來源於stackoverflow,這次居然來自於知乎,這顛覆了我對知乎的看法。

https://www.zhihu.com/question/32209043/answer/55252171

http://www.zhihu.com/question/35538123

特別是第二個鏈接里有一個評論,對我有很重要的啟示,原話為

響應時間,拖拽速度,時間,位置,軌跡,重試次數等。
這些因素能夠構成一個采樣結果或者辨識特性。

這下算是知道了,要破解這種驗證碼,就要用鼠標去模擬滑動。我再來分析淘寶驗證碼時,發現淘寶的登錄驗證碼是隨機的,並且有一個很明顯的延遲加載。

為破解淘寶的滑動驗證碼,我梳理了一個整個過程。

1,判斷驗證碼在什么時候出現。

2,驗證碼出現時,判斷何時加載完成。

3,確定驗證碼的位置。

4,用鼠標模擬拖動驗證碼。

5,檢驗本次操作是否成功。

下文,就是我針對這5個步驟,一步一步的去實現淘寶驗證碼的破解。

 一:判斷驗證碼在什么時候出現

 要想知道滑動驗證碼在什么時候出現,就顯得非常簡單了,用firefox一看,只要會點html的人,一下就明白了。

 

經過換電腦,換瀏覽器,清緩存的反復驗證,發現:有驗證碼時候與有沒驗證碼時,HTML的區別在於

<!--無驗證碼-->
<div id=imgCaptcha></div>

<!--有驗證碼-->
 <div id=imgCaptcha style="HEIGHT: 339px; MIN-HEIGHT: 0px; TOP: -202px"></div>

我在寫程序的時候,就是根據這兩行代碼的區別來分辨本次登錄是否需要驗證碼。

二:驗證碼出現時,判斷何時加載完成

        這個問題最先是困擾着我的,這個驗證碼是通過ajax加載的,一個外部程序去判斷一個網頁的ajax請求是否加載完成,顯然是有難度的,我搜了些資料,沒找到一個合適的方法。

        隨后我變了一種思路,我發現正在加載驗證碼的時候,span標簽里的文字是‘加載中’,加載成功后,span的文字變為了 ‘請按住滑塊,拖動到最右邊’。所以我通過這個區別很輕松的判斷了驗證碼是否已經加載完成了。

        換個思路,問題就簡單了。

三:確定驗證碼的位置

        判斷驗證碼的位置,這是一個真正的難點,且聽我娓娓道來。

        驗證碼X軸 = 瀏覽器在電腦屏上的X軸  +  驗證碼在瀏覽器中的X軸

        驗證碼Y軸 = 瀏覽器在電腦屏上的Y軸  +  驗證碼在瀏覽器中的Y軸

        我體會到了計算機與數學的關系,雖然只是小學數學。

1,驗證碼在網頁中的位置

        驗證碼是在網頁中的,要先確定驗證碼在網頁中的位置,這時,會javascript的同學就笑了。但是你的javascript要怎樣才能注冊到淘寶的網頁中去呢?顯然不太容易,后來我用HtmlDocument對象來確定網頁的位置,具體代碼如下。

        后來,我發現往淘寶網頁注冊javascript也是可行的,但還是用第一種吧!解決這個問題我只用一種方法就行了。

/// <summary>
/// 獲取驗證碼的位置
/// </summary>
/// <returns></returns>
private System.Windows.Point GetCaptchaPosition(System.Windows.Forms.HtmlDocument paraHtmlDoc)
{
    System.Windows.Point webControlPoint = default(System.Windows.Point);

    //獲取當前控件的所有父控件  Example  html -> body -> form -> div
    List<KeyValuePair<String, HtmlElement>> allElement = new List<KeyValuePair<string, HtmlElement>>();
    HtmlElement currentElement = paraHtmlDoc.GetElementById("TPL_username");
    while (currentElement != null)
    {
        allElement.Insert(0, new KeyValuePair<String, HtmlElement>(currentElement.TagName, currentElement));
        currentElement = currentElement.Parent;
    }

    int webControlX = 0;
    int webControlY = 0;
    for (int i = 0; i < allElement.Count; i++)
    {
        webControlX += allElement[i].Value.OffsetRectangle.X;
        webControlY += allElement[i].Value.OffsetRectangle.Y;
    }
    webControlPoint = new Point(webControlX, webControlY);
    return webControlPoint;
}

2,整個網頁在電腦中的位置:

    這個相對於第1點來說,技術上沒那么難,但是考慮的問題要多些,屏幕的大小,分辨率的改變,最小化,最大化窗口時,都要去考慮一下。

四:用鼠標模擬拖動驗證碼      

在c#中模擬鼠標的拖動,我調用了Windows自身的類庫,注釋我也寫的比較詳細了,如果實在是有不懂的,也可以互相研究哈!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
//using Microsoft.Win32;

namespace TaoBao.ClientWPFApp
{
    public class Win32Mouse
    {
        //鼠標移動
        //dX和dy保留移動的信息。給出的信息是絕對或相對整數值。
        public static readonly int MOUSEEVENTF_MOVE = 0x0001;
        //絕對位置
        //則dX和dy含有標准化的絕對坐標,其值在0到65535之間。
        //事件程序將此坐標映射到顯示表面。
        //坐標(0,0)映射到顯示表面的左上角,(65535,65535)映射到右下角
        //如果沒指定MOUSEEVENTF_ABSOLUTE,dX和dy表示相對於上次鼠標事件產生的位置(即上次報告的位置)的移動。
        //正值表示鼠標向右(或下)移動;負值表示鼠標向左(或上)移動。
        public static readonly int MOUSEEVENTF_ABSOLUTE = 0x8000;
        public static readonly int MOUSEEVENTF_LEFTDOWN = 0x0002;//左鍵按下
        public static readonly int MOUSEEVENTF_LEFTUP = 0x0004;//左鍵抬起
        public static readonly int MOUSEEVENTF_RIGHTDOWN = 0x0008; //右鍵按下 
        public static readonly int MOUSEEVENTF_RIGHTUP = 0x0010; //右鍵抬起 
        public static readonly int MOUSEEVENTF_MIDDLEDOWN = 0x0020; //中鍵按下 
        public static readonly int MOUSEEVENTF_MIDDLEUP = 0x0040;// 中鍵抬起 

        /// <summary>
        /// 得到光標的位置
        /// </summary>
        /// <param name="pt"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern bool GetCursorPos(out System.Windows.Point pt);

        /// <summary>
        /// 移動光標的位置
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        [DllImport("user32.dll")]
        public static extern void SetCursorPos(int x, int y);

        /// <summary>
        /// 第2個參數應該是為,
        /// </summary>
        /// <param name="dwFlags"></param>
        /// <param name="dx">DX=需要移動的X*65536/取屏幕寬度 ()+1</param>
        /// <param name="dy">DY=需要移動的Y*65536/取屏幕高度 ()+1</param>
        /// <param name="cButtons"></param>
        /// <param name="dwExtraInfo"></param>
        /// <returns></returns>
        [DllImport("user32")]
        public static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
    }
}

 五:檢驗本次操作是否成功

 這個和第一點“判斷驗證碼在什么時候出現”類似,主要比較HTML的差異。如果發現鼠標模擬拖動不成功,就得檢驗驗證碼的位置是否正確,以及再模擬拖動鼠標。

 經過反復修改測試,淘寶滑動驗證碼的破解成功率在100%。最后補一張效果圖,有點遺憾的是,我想截圖的時候,刷了好幾次驗證碼都沒有出來。

后記:

朋友開了網店,在網絡里下載些刷單軟件經常被騙,聽說后我義憤填膺啊,為了公道,必須得開發一個牛批的軟件來打擊這些騙子。前期功能就實現以下幾點:

1,實現自動輸入用戶名,密碼,自動拖拉驗證碼,實現全自動化淘寶登錄。

2,提取淘寶用戶的信息,比如等級,收貨信息,已購物的訂單詳情。

3,實現自動搜索商品。

4,實現自動貨比三家,添加收藏夾。

5,實現自動網頁旺旺聊天。

6,實現自動提交訂單。

7,實現付款。

8,自動好評。

源碼購買


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM