15 分鍾用 ML 破解一個驗證碼系統


人人都恨驗證碼——那些惱人的圖片,顯示着你在登陸某網站前得輸入的文本。設計驗證碼的目的是,通過驗證你是真實的人來避免電腦自動填充表格。但是隨着深度學習和計算機視覺的興起,現在驗證碼常常易被攻破。

我拜讀了 Adrian Rosebrock 寫的《Deep Learning for Computer Vision with Python》。在書中,Adrian 描述了他是怎樣用機器學習繞過紐約 E-ZPass 網站上的驗證碼:

1*4q8hCiIh1amCf2e9fJBQGg

Adrian 無法接觸到該應用生成驗證碼的源代碼。為了攻破該系統,他不得不下載數百張示例圖片,並手動處理它們來訓練他自己的系統。

但是如果我們想攻破的是一個開源驗證碼系統,我們確實能接觸到源代碼該怎么辦呢?

我訪問了 WordPress.org 的插件頻道,並搜索了“驗證碼”。第一條搜索結果是 Really Simple CAPTCHA,並且有超過一百萬次的活躍安裝:

1*3qc-gFTRWmleRXomopMAUQ

最好的一點是,它是開源的!既然我們已經有了生成驗證碼的源代碼,那它應該挺容易被攻破的。為了讓這件事更有挑戰性,讓我們給自己規定個時限吧。我們能在 15 分鍾內完全攻破這個驗證碼系統嗎?來試試吧!

重要說明:這絕不是對 Really Simple CAPTCHA 插件或對其作者的批評。該插件作者自己說它已經不再安全了,建議使用其他插件。這僅僅是一次好玩又迅速的技術挑戰。但是如果你是那剩余的一百多萬用戶之一,也許你應該改用其他插件 :)

挑戰

為了構思一個攻擊計划,來看看 Really Simple CAPTCHA 會生成什么樣的圖片。在示例網站上,我們看到了以下圖片:

1*WDu1xgEEQuP3tqgC-cPmzA

好了,所以驗證碼似乎是四個字母。在 PHP 源代碼中對其進行驗證:

沒錯,它用四種不同字體的隨機組合來生成四個字母的驗證碼。並且可以看到,它在代碼中從未使用 O 或者 I,以此避免用戶混淆。總共有 32 個可能的字母和數字需要我們識別。沒問題!

計時:2 分鍾

工具

在進行下一步前,提一下我們要用來解決問題的工具:

Python 3 

Python 是一種有趣的編程語言,它有大量的機器學習和計算機視覺庫。

OpenCV 

OpenCV 是一種流行的計算機視覺和圖片處理框架。我們要使用 OpenCV 來處理驗證碼圖片。由於它有 Python API,所以我們可以直接從 Python 中使用它。

Keras

Keras 是用 Python 編寫的深度學習框架。它使得定義、訓練和用最少的代碼使用深度神經網絡容易實現。

TensorFlow 

TensorFlow 是 Google 的機器學習庫。我們會用 Keras 編程,但是 Keras 並沒有真正實現神經網絡的邏輯本身,而是在幕后使用 Google 的 TensorFlow 庫來挑起重擔。

好了,回到我們的挑戰吧!

創造我們的數據集

為了訓練任何機器學習系統,我們需要訓練數據。為了攻破一個驗證碼系統,我們想要像這樣的訓練數據:

1*dC78m_XpcZmuaV_GlnAh5g

鑒於我們有 WordPress 插件的源代碼,我們可以調整它,一起保存 10,000 張驗證碼圖片及分別對應的答案。

經過幾分鍾對代碼的攻擊,並添加了一個簡單的 for 循環之后,我有了一個訓練數據的文件夾——10,000 個 PNG 文件,文件名為對應的正確答案:

1*leaOO0EYbgKVl7MEhflIFA

這是唯一一個我不會給你示例代碼的部分。我們做這個是為了教育,我不希望你們真去黑 WordPress 網站。但是,我最后會給你生成的這10,000 張圖片,這樣你就能重復我的結果了。

計時:5 分鍾

簡化問題

既然有了訓練數據,就可以直接用它來訓練神經網絡了:

1*4ScTIDYJ6rPCAtopRulzOg

有了足夠的訓練數據,這個方法可能會有用——但是我們可以使問題更簡化來解決。問題越簡單,要解決它需要的訓練數據就越少,需要的計算能力也越低。畢竟我們只有 15 分鍾!

幸運的是,驗證碼圖片總是由僅僅四個字母組成。如果我們能想辦法把圖片分開,使得每個字母都在單獨的圖片中,這樣我們只需要訓練神經網絡一次識別一個字母:

1*4ScTIDYJ6rPCAtopRulzOg

我沒有時間去瀏覽 10,000 張訓練圖片並在 Photoshop 中手動把它們拆分開。這得花掉好幾天的時間,而我只剩下 10 分鍾了。我們還不能把圖片分成相等大小的四塊,因為該驗證碼插件把字母隨機擺放在不同的水平位置上以防止這一做法:

1*yyfjNSCKt8IvY7JqANnOZg

幸運的是,我們仍然可以自動處理。在圖像處理中,常常需要檢測有相同顏色的像素塊。這些連續像素塊周圍的界限被稱為輪廓。OpenCV 中有一個 LndContours() 函數,可以被用來檢測這些連續區域。

所以我們用一個未經處理的驗證碼圖片開始:

接下來把該圖片轉換成純黑白(這叫做 thresholding),這樣容易找到連續區域:

接着,使用 OpenCV 的 LndContours() 函數來檢測該圖片中包含相同顏色像素塊的不同部分:

接下來就是簡單地把每個區域存成不同的圖片文件。鑒於我們知道每張圖片都應該包含從左到右的四個字母,我們可以利用這一點在保存的同時給字母標記。只要我們是按順序保存的,我們就應該能保存好每個圖片字母及其對應的字母名。

但是等等——我看到一個問題!有時驗證碼中有像這樣重疊的字母:

這意味着我們會把兩個字母分離成一個區域:

如果不處理這個問題,會創造出糟糕的訓練數據。我們得解決這個問題,這樣就不會意外地教機器把兩個重疊的字母識別成一個字母了。

一個簡單的方法是,如果一個輪廓區域比它的高度更寬,這意味着很可能有兩個字母重疊在一起了。在這種情況下,我們可以把重疊的字母從中間拆分成兩個,並將其看作兩個不同的字母:

既然我們找到拆分出單個字母的方法了,就對所有驗證碼圖片進行該操作。目標是收集每個字母的不同變體。我們可以將每個字母保存在各自對應的文件夾中,以保持條理。

在我分離出所有字母后,我的 W 文件夾長這樣:

計時:10 分鍾

構建並訓練神經系統

由於我們只需要識別單個字母和數字的圖片,我們不需要非常復雜的神經網絡結構。識別字母要比識別像貓狗這樣復雜的圖片容易得多。

我們要使用簡單的卷積神經網絡結構,有兩層卷積層以及兩層完全連接層:

如果你想要了解更多神經網絡的工作,以及為什么它們是圖片識別的理想工具,請參考 Adrian 的書或者我之前的文章

定義該神經網絡結構,只需要使用 Keras 的幾行代碼:

現在我們可以訓練它了!

在 10 通過了訓練數據集后,我們達到了幾乎 100% 的正確率。此時,我們應該能隨時自動繞過這個驗證碼了!我們成功了!

計時:15 分鍾(好險!)

使用訓練后的模型來處理驗證碼

既然有了一個訓練后的神經網絡,利用它來攻破真實的驗證碼要很容易了:

  • 1.從一個使用 WordPress 插件的網站上下載一張驗證碼圖片。
  • 2.使用文章中生成訓練數據集的方法,把該驗證碼圖片拆分成四張字母圖片。
  • 3.用神經網絡對每張字母圖片分別作預測。
  • 4.用四個預測字母作為驗證碼的答案。
  • 5.狂歡!廈門叉車租賃公司

在破解驗證碼時,我們的模型看起來是這樣:

1*L6scb0B2nCirZ_ZLyuONPg

或者從命令來看:

1*7RE-Ql6jaDu1jCfi0OgtTw

來試試吧!

如果你想自己試試,你可以從這里找到代碼( http://t.cn/R8yFJiN )。它包含 10,000 張示例圖片和文章中每一步的所有代碼。參考文件 README.md 中的運行指導。

但是如果你想了解每一行代碼都做了什么,我強烈建議你看看《 Deep Learning for Computer Vision with Python。該書覆蓋了更多的細節,而且有大量的詳細示例。這本書是我目前見過的唯一一本既包含了運行原理,又包含了如何在現實生活中用其來解決復雜問題的書。去看看吧!


免責聲明!

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



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