淘寶滑動驗證碼研究

清閒的時候,總會去找些事作作。前些天在登陸淘寶的時候,發現了滑動驗證碼,雖然已經不是什麼新事物,但仍是產生了很大的興趣。javascript

 

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

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

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

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

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

特別是第二個連接裏有一個評論,對我有很重要的啓示,原話爲瀏覽器

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

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

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

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,自動好評。

相關文章
相關標籤/搜索