如何用機器學習在15分鐘內破解網站驗證碼系統?

I7J2@ZC81PX$2ZFUMX}3ZLR.png

先聲明,雖然端午節假期將至,但我們今天聊的真不是破解12306的驗證碼,原因嘛你懂的。

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖2

我們今天 以破解世界上最流行的WordPress驗證碼插件為例


每個人都很討厭驗證碼吧?這些煩人的小照片里有很多文本信息,只有輸入它們后才能訪問網站。人們設計驗證碼系統的初衷是為了驗證訪問網站的用戶是一個真實的人。但隨著深度學習和計算機視覺技術的進步,我們很容易就能打敗這些驗證碼系統。(除非你遇到 12306 那種騷騷的圖片識別驗證,有時真的會陷入絕望)

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖3
我(本文作者 Adam Geitgey——譯者注)最近讀了一本很棒的書,Adrian Rosebrock 寫的《Deep Learning for Computer Vision with Python 》,在書里 Adrian 詳述了他怎樣用機器學習繞開了 E-Zpass New York 網站的驗證碼:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖4

Adrian 沒有訪問網站生成驗證碼照片的工具的源代碼,所以為了破解驗證碼,他必須下載幾百個示例圖像,然后手動用它們訓練自己創建的機器學習系統。

但如果我們想破解一個我們能訪問源代碼的開源驗證碼系統呢?

我去 WordPress 的插件注冊網站上搜了一下“captcha”,第一條搜索結果是“Really Simple CAPTCHA”,有超過1百萬的活動安裝量:

最棒的是它提供了源代碼。因為我們能獲取生成驗證碼的源代碼,那破解它就比較容易了。我們可以再提高點難度,變得更有挑戰性一點,比如在限定時間內完成破解。

我們能在15分鐘內完全破解這個驗證碼系統嗎?試試看!

特此聲明:這么做完全沒有批評“Really Simple CAPTCHA”插件及其作者的意思。插件作者自己也曾說過這款插件已經不是很安全了,建議換用其它插件。因此這純屬一次好玩的快速技術挑戰。不過,如果你也是這款插件的用戶,或許你真的該換其它的了。

挑戰開始

在“發動進攻”前,我們先看看“Really Simple CAPTCHA”能生成什么樣的驗證碼照片。在演示網站上,我們看到這樣:

C2W]HP$IKGF$6]CJ1~B5706.png 如何用機器學習在15分鐘內破解網站驗證碼系統?的圖8

OK,那么驗證碼似乎是4個字母和數字的組合形式。我們在PHP源代碼中驗證一下:

public function __construct() { /* Characters available in images */ $this->chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; /* Length of a word in an image */ $this->char_length = 4; /* Array of fonts. Randomly picked up per character */ $this->fonts = array( dirname( __FILE__ ) . '/gentium/GenBkBasR.ttf', dirname( __FILE__ ) . '/gentium/GenBkBasI.ttf', dirname( __FILE__ ) . '/gentium/GenBkBasBI.ttf', dirname( __FILE__ ) . '/gentium/GenBkBasB.ttf', ); 復制代碼

沒錯,它以隨機混合 4 個不同字體的形式生成 4 個字的驗證碼。我們也能發現它從不用字母“O”和“I”,因為這倆字母比較容易被用戶搞混。所以我們需要識別 24 個英文字母和 10 個阿拉伯數字,也就是 32 個字混合組成的驗證碼。沒問題!

迄今用時:2 分鐘

使用工具

在正式開始挑戰前,先講一下我們會用到的工具:

Python 3

Python 是一種很有意思的編程語言,有很多用于機器學習和計算機視覺的很不錯的程序庫。

OpenCV

OpenCV 是計算機視覺和圖像處理中一個很流行的框架。我們會用 OpenCV 處理驗證碼照片。它有一個 Python API,所以我們可以直接從 Python 中使用它。

Keras

Keras 是一個用 Python 編寫的深度學習框架。用 Keras 可以只需編寫少量代碼就能很容易地定義、訓練和使用深度神經網絡。

TensorFlow

TensorFlow 是谷歌出品的一款用于機器學習的程序庫。我們會在 Keras 上的編程,但 Keras 自己并不會實際使用神經網絡邏輯,相反它會在幕后使用谷歌的 TensorFlow 程序庫挑起重擔。

OK,我們回到挑戰中!

創建我們的數據集

不管是訓練什么機器學習系統,我們都要有訓練數據。要破解一個驗證碼系統,我們希望能有這樣的訓練數據:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖9

如圖示:輸入驗證碼照片用以訓練模型,然后模型能夠輸出正確的答案。

因為我們有這款 WordPress 插件的源代碼,我們可以對其修改保存出 1 萬張驗證碼照片,以及每張照片的預期答案。

在花了幾分鐘修改代碼和添加一個簡單的 for 循環后,我獲得了一個訓練數據文件夾,包含了 1 萬張 PNG 照片,每張照片都有正確答案作為照片的文件名:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖10

這是本文唯一一部分沒有給出我的工作示例代碼的地方,因為我考慮再三后覺得,這篇教程純粹出于一個好玩的點子,我不希望有人真的用垃圾信息去刷爆 WordPress 網站。但我會在文末提供我上面生成的這1萬張照片,大家可以拿去用。

迄今用時:5分鐘

將問題簡單化

現在,我們已經獲取了所需的訓練數據,可以用它們直接訓練一個神經網絡:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖11

有了足夠的訓練數據,這種方法應該能湊效了,但我們可以讓問題更簡單些。問題越簡單,解決問題所需的訓練數據和計算力就越少。畢竟我們只有 15 分鐘啊!!

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖12

幸好,這款插件生成的驗證碼照片都是只有 4 個字,所以我們可以以某種方式將照片分拆,每個字作為一張單獨的小照片,這樣我們只需訓練神經網絡每次識別一個單獨的字:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖13
我沒時間從頭到尾看一遍這 1 萬張訓練照片,然后用 Photoshop 手動把它們分成單獨的照片。這要花好幾天功夫,而我只剩下 10 分鐘了。我們不能僅僅將照片分成 4 個相同大小的圖塊,因為驗證碼為了避免如下情況會隨機將字母和數字放在不同的水平位置:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖14
幸運的是,我們依然能將其自動化。在照片處理過程中,我們常常需要檢測相同顏色像素的“斑點”(blobs)。圍繞這些連續的像素斑點的界線被稱為輪廓線。OpenCV 有個內置的findContours()函數,我們可以用它檢測這些連續區域。

因此我們以一張原始驗證碼圖像開始:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖15

然后我們將其轉為純黑純白的照片(這步叫做闕值化),這樣就能比較容易地發現照片中的連續區域了:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖16
接著,我們用 OpenCV 的 findContours() 函數檢測照片的單獨部分,它們包含了相同顏色像素的連續斑點:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖17
那么,把每個區域保存為單獨的照片文件就是一件比較簡單的工作了。因為我們知道每張照片驗證碼應該自左至右包含 4 個字母,我們可以根據這點在保存這些字的時候給它們打上標簽。在按這種順序保存字母時,我們應該以相應的字母名保存每個字母照片,比如以字母 a 作為照片

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖18
的名字。

但是等等,我發現了一個問題!有時驗證碼會出現字母重疊的情況,比如這樣:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖19

這意味著我們有可能把兩個字母提取為一個區域:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖20
如果我們不解決這個問題,我們的訓練數據質量會很糟糕。我們需要解決這個麻煩,但額外再教機器將這兩個壓在一起的字幕識別為一個字母,會比較麻煩。

這里有個簡單的技巧,如果一個輪廓線區域的寬度遠大于其高度,這意味著可能有兩個字母相互重疊了。在這種情況下,我們只需從中間將它們切分,作為兩個分開的字母:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖21

現在我們能準確地獲取單個字母了,那就把所有的驗證碼照片過一遍吧。目標是收集每個字母的不同變體。為了容易整理,我們可以將每個字母保存在其自身文件夾內。

比如,下面是我提取所有字母后,字母“W”的文件夾狀況:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖22

迄今用時:10分鐘

搭建和訓練神經網絡

因為我們只需識別單個字母和數字,我們不需要用非常復雜的神經網絡架構。識別字母比識別阿狗阿貓這樣的復雜照片要容易的多。 我們會用到一個簡單的卷積神經網絡,它有兩個卷積層和兩個完全相連的層:

如果你想了解更多卷積神經網絡工作原理的知識,以及為何它們是用于照片識別理想工具,可以翻閱 Adrian 的書籍《Deep Learning for Computer Vision with Python》。

使用 Keras 只需幾行代碼就能定義這個神經網絡架構:

# 搭建神經網絡! model = Sequential() # 第一個卷積層并最大池化 model.add(Conv2D(20, (5, 5), padding="same", input_shape=(20, 20, 1), activation="relu")) model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2))) # 第二個卷積層并最大池化 model.add(Conv2D(50, (5, 5), padding="same", activation="relu")) model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2))) # 包含500個節點的隱藏層 model.add(Flatten()) model.add(Dense(500, activation="relu")) # 包含32個節點的輸出層 (每個節點對應我們預測的可能的字母或數字) model.add(Dense(32, activation="softmax")) # 用Keras搭建TensorFlow模型 model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"]) 復制代碼

現在可以訓練它了!

# 訓練神經網絡 model.fit(X_train, Y_train, validation_data=(X_test, Y_test), batch_size=32, epochs=10, ver 復制代碼

在用訓練數據集訓練 10 次后,我們達到了接近 100% 的準確率。這時,我們就能隨時自動通過這款工具的驗證碼了!完成任務!

迄今用時:15分鐘(Bingo!)

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖24

使用訓練后的模型解決填寫驗證碼問題

現在我們有了一個訓練后的神經網絡,用它破解真正的驗證碼非常簡單:

  • 從使用文中這款WordPress插件的網站中抓取一張真正的驗證碼照片。

  • 使用我們在創建訓練數據集時所用的方式,將驗證碼照片分成4個單獨的字母照片。

  • 讓我們的神經網絡為每張字母照片做出獨立的預測。

  • 使用4個預測的字母填寫驗證碼。

  • 歡呼吧!

這是我們的模型破解真正的驗證碼系統時的樣子:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖25
或以命令行模式:

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖26

自己動手試試吧!

如果你想自己動手嘗試,可以點擊這里獲取代碼,包含了本文所用的1萬張示例照片和每一步中所有的代碼。查看文件夾中的 README.md 文件,獲取運行代碼的說明。

但是如果你真的想學習每行代碼的運行知識,我還是強烈建議你看看《Deep Learning for Computer Vision with Python》這本書,講了很多細節知識,還有大量的詳細示例。這是我迄今看到的唯一一本既講解了原理又介紹了怎樣應用于解決實際問題的書籍,去看看吧!

如何用機器學習在15分鐘內破解網站驗證碼系統?的圖27

作者:景略集智
來源:掘金

登錄后免費查看全文
立即登錄
App下載
技術鄰APP
工程師必備
  • 項目客服
  • 培訓客服
  • 平臺客服

TOP