驗(yàn)證碼的設(shè)計(jì)是為了防止計(jì)算機(jī)自動(dòng)填寫表格,驗(yàn)證你是一個(gè)真實(shí)的“人”。但隨著深度學(xué)習(xí)和計(jì)算機(jī)視覺(jué)的興起,現(xiàn)在他們往往容易被擊敗。
我一直在讀一本由AdrianRosebrock所寫的書《Deep Learning for Computer Vision with Python》(Python計(jì)算機(jī)視覺(jué)深度學(xué)習(xí))。在這本書中,Adrian回顧了如何通過(guò)機(jī)器學(xué)習(xí)破解e – zpass紐約網(wǎng)站上的驗(yàn)證碼系統(tǒng):

Adrian沒(méi)有訪問(wèn)生成驗(yàn)證碼圖像的應(yīng)用程序的源代碼。為了破解這個(gè)系統(tǒng),他不得不下載數(shù)百個(gè)示例圖像,并手動(dòng)解決它們以訓(xùn)練他的系統(tǒng)。
但是,如果我們想要破解一個(gè)開源的驗(yàn)證碼系統(tǒng),我們?nèi)ツ睦镌L問(wèn)源代碼呢?
我訪問(wèn)了WordPress.org插件登記網(wǎng)站,并搜索了“CAPTCHA”。上面的結(jié)果被稱為“Really Simple CAPTCHA”,并且有超過(guò)100萬(wàn)的安裝量:
WordPress.org插件登記地址:https://wordpress.org/plugins/

最棒的是,這里有它的源代碼!因?yàn)橛猩沈?yàn)證碼的源代碼,所以這應(yīng)該很容易被破解。為了讓事情變得更有挑戰(zhàn)性,讓我們給自己一個(gè)時(shí)間限制。我們能在15分鐘內(nèi)徹底破解這個(gè)驗(yàn)證碼系統(tǒng)嗎?讓我們?cè)囈辉?
重要提示:這絕不是批評(píng)“Really Simple CAPTCHA”插件或其作者。插件作者自己說(shuō)它已經(jīng)不安全了,建議你使用其他的東西。這只是一個(gè)有趣并且快速的技術(shù)挑戰(zhàn)。但如果你是100萬(wàn)用戶之一,或許你應(yīng)該有所防備了:)
挑戰(zhàn)
首先,讓我們需要知道 Really Simple CAPTCHA生成什么樣的圖像。在演示網(wǎng)站上,我們看到:
Really Simple CAPTCHA地址:https://wordpress.org/plugins/really-simple-captcha/

演示驗(yàn)證碼圖片
驗(yàn)證碼圖像看起來(lái)是四個(gè)字母。讓我們?cè)赑HP源代碼中驗(yàn)證這一點(diǎn):
public function __construct() { $this->chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; $this->char_length = 4;}
是的,它生成了4個(gè)字母的驗(yàn)證碼,使用4種不同字體的隨機(jī)組合。我們可以看到,在代碼中它從不使用“O”或“I”,以此避免用戶的混淆。這就給我們留下了32個(gè)可能的字母和數(shù)字。
到目前為止的時(shí)間:2分鐘
我們的工具集
在我們進(jìn)一步討論之前,我們先來(lái)討論一下解決這個(gè)問(wèn)題需要的工具:
Python 3
Python是一種很有趣的編程語(yǔ)言,包含很好的機(jī)器學(xué)習(xí)和計(jì)算機(jī)視覺(jué)庫(kù)。
OpenCV
OpenCV是一個(gè)流行的計(jì)算機(jī)視覺(jué)和圖像處理框架。我們將使用OpenCV來(lái)處理驗(yàn)證碼圖像。它有一個(gè)Python API,因此我們可以直接在Python中使用。
Keras
Keras是用Python編寫的深度學(xué)習(xí)框架。它使得定義、訓(xùn)練和使用具有最小編碼的深度神經(jīng)網(wǎng)絡(luò)變得很容易。
TensorFlow是谷歌的機(jī)器學(xué)習(xí)庫(kù)。我們將在Keras中編碼,但是Keras并沒(méi)有真正實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)邏輯本身。相反,它使用谷歌在幕后的TensorFlow庫(kù)來(lái)完成繁重的任務(wù)。
好了,回到挑戰(zhàn)。
創(chuàng)建數(shù)據(jù)集
訓(xùn)練任何機(jī)器學(xué)習(xí)系統(tǒng),都需要訓(xùn)練數(shù)據(jù)。要破解驗(yàn)證碼系統(tǒng),我們需要這樣的訓(xùn)練數(shù)據(jù):

我們有了WordPress插件的源代碼,就可以修改它來(lái)保存10000個(gè)驗(yàn)證碼圖像,以及每個(gè)圖像的預(yù)期答案。
在對(duì)代碼進(jìn)行了幾分鐘的破解并添加了一個(gè)簡(jiǎn)單的for循環(huán)之后,我有了一個(gè)包含訓(xùn)練數(shù)據(jù)的文件夾—10,000個(gè)PNG文件,將正確的答案作為其文件名:

這是唯一的我不給你示例代碼的部分。我們這樣做是為了教學(xué),我不希望你真的去垃圾郵件網(wǎng)站。但是我會(huì)給你我在最后生成的10000張照片,這樣你就可以復(fù)制我的結(jié)果。
到目前為止的時(shí)間:5分鐘
簡(jiǎn)化問(wèn)題
現(xiàn)在我們有了訓(xùn)練數(shù)據(jù),我們可以直接用它來(lái)訓(xùn)練神經(jīng)網(wǎng)絡(luò):

如果有足夠的訓(xùn)練數(shù)據(jù),這種方法可能有效——但是我們可以使問(wèn)題變得簡(jiǎn)單得多。問(wèn)題越簡(jiǎn)單,訓(xùn)練數(shù)據(jù)越少,我們解決需要的計(jì)算力就越少。我們畢竟只有15分鐘!
幸運(yùn)的是,驗(yàn)證碼圖像通常只由四個(gè)字母組成。如果我們能把圖像分割開來(lái),這樣每個(gè)字母都是一個(gè)單獨(dú)的圖像,那么我們只需訓(xùn)練神經(jīng)網(wǎng)絡(luò)識(shí)別單個(gè)字母:

我沒(méi)有時(shí)間去瀏覽10000個(gè)訓(xùn)練圖像,并且用Photoshop將它們手工分割成單獨(dú)的圖像。這需要幾天的時(shí)間,但我只剩下10分鐘了。我們不能將圖像分割成4個(gè)等分大小的塊,因?yàn)轵?yàn)證碼隨機(jī)將字母放置在不同的水平位置,如下圖所示:

每個(gè)圖像中的字母都是隨機(jī)放置的,使圖像分割變得更加困難。
幸運(yùn)的是,我們?nèi)匀豢梢詫?shí)現(xiàn)自動(dòng)化。在圖像處理中,我們經(jīng)常需要檢測(cè)具有相同顏色的像素的“blob”。這些連續(xù)像素點(diǎn)的邊界稱為輪廓。OpenCV有一個(gè)內(nèi)置的findContours()函數(shù),我們可以用它來(lái)檢測(cè)這些連續(xù)區(qū)域。
我們將從一個(gè)原始的驗(yàn)證碼圖像開始:

然后我們將圖像轉(zhuǎn)換成純黑白像素點(diǎn)(這稱為色彩閾值法),這樣就很容易找到連續(xù)區(qū)域的輪廓邊界:

接下來(lái),我們將使用OpenCV的findContours()函數(shù)來(lái)檢測(cè)圖像中包含相同顏色連續(xù)像素塊的分離部分:

接著把每個(gè)區(qū)域作為一個(gè)單獨(dú)的圖像文件保存。因?yàn)槲覀冎烂總€(gè)圖像應(yīng)該包含從左到右的四個(gè)字母,所以我們可以用這些知識(shí)來(lái)標(biāo)記我們保存的字母。我們按這個(gè)順序把它們存起來(lái),并用相應(yīng)的字母名稱來(lái)保存每一個(gè)圖像字母。
但是等一下—我發(fā)現(xiàn)問(wèn)題了!有時(shí)驗(yàn)證碼有這樣重疊的字母:

這意味著我們最終將提取將兩個(gè)字母拼湊在一起的區(qū)域:

如果我們不處理這個(gè)問(wèn)題,我們就會(huì)產(chǎn)生糟糕的訓(xùn)練數(shù)據(jù)。我們需要解決這個(gè)問(wèn)題,這樣我們就不會(huì)偶然地讓機(jī)器將這兩個(gè)squashed – together字母識(shí)別為一個(gè)字母。
有一個(gè)簡(jiǎn)單的竅門:如果一個(gè)區(qū)域的寬比它的高度大,那就意味著我們可能有兩個(gè)字母擠壓在一起了。在這種情況下,我們可以把這兩個(gè)字母放在中間,把它分成兩個(gè)獨(dú)立的字母:
現(xiàn)在我們有了一種提取單個(gè)字母的方法,讓我們?cè)谒械尿?yàn)證碼圖像中運(yùn)行它。目的是收集每個(gè)字母的不同變體。我們可以把每個(gè)字母都保存在自己的文件夾里。
這是我摘取所有字母后,“W”文件夾的圖片:

到目前為止的時(shí)間:10分鐘
構(gòu)建并訓(xùn)練神經(jīng)網(wǎng)絡(luò)
因?yàn)槲覀冎恍枰R(shí)別單個(gè)字母的圖像,所以并需要一個(gè)非常復(fù)雜的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)。識(shí)別字母比識(shí)別像貓和狗這樣的復(fù)雜圖像要容易得多。
我們將使用一個(gè)簡(jiǎn)單的卷積神經(jīng)網(wǎng)絡(luò)架構(gòu),它有兩個(gè)卷積層和兩個(gè)完全連通的層:

定義這個(gè)神經(jīng)網(wǎng)絡(luò)架構(gòu)只需要使用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))) model.add(Flatten()) model.add(Dense(500, activation="relu")) model.add(Dense(32, activation="softmax")) model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
現(xiàn)在我們可以運(yùn)行它了。
# Train the neural network model.fit(X_train, Y_train, validation_data=(X_test, Y_test), batch_size=32, epochs=10, verbose=1)
經(jīng)過(guò)訓(xùn)練數(shù)據(jù)集10次之后,我們達(dá)到了接近100%的準(zhǔn)確度。我們應(yīng)該能夠在任何我們需要的時(shí)候自動(dòng)繞過(guò)這個(gè)驗(yàn)證碼。
時(shí)間過(guò)了:15分鐘
使用訓(xùn)練的模型來(lái)以解決驗(yàn)證碼
現(xiàn)在我們有了一個(gè)經(jīng)過(guò)訓(xùn)練的神經(jīng)網(wǎng)絡(luò),用它來(lái)破解驗(yàn)證碼是很簡(jiǎn)單的:
1. 從WordPress插件的網(wǎng)站上獲取真正的驗(yàn)證碼圖像。
2. 用我們用來(lái)創(chuàng)建訓(xùn)練數(shù)據(jù)集的方法將驗(yàn)證碼圖像分割成四個(gè)不同的字母圖像。
3. 讓我們的神經(jīng)網(wǎng)絡(luò)對(duì)每個(gè)字母圖像做一個(gè)單獨(dú)的預(yù)測(cè)。
4. 用四個(gè)預(yù)測(cè)字母作為驗(yàn)證碼的答案。
下面是我們的模型如何解碼真實(shí)的驗(yàn)證碼:
或從命令行:

-
源代碼
+關(guān)注
關(guān)注
96文章
2953瀏覽量
69614 -
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8540瀏覽量
136206 -
驗(yàn)證碼
+關(guān)注
關(guān)注
2文章
20瀏覽量
4863
原文標(biāo)題:利用機(jī)器學(xué)習(xí)在15分鐘內(nèi)破解驗(yàn)證碼
文章出處:【微信號(hào):worldofai,微信公眾號(hào):worldofai】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
無(wú)法驗(yàn)證郵箱,總是提示驗(yàn)證碼錯(cuò)誤,驗(yàn)證碼明明是正確的。
一文解析驗(yàn)證碼與打碼平臺(tái)的攻防對(duì)抗
打碼平臺(tái)是如何高效的破解市面上各家驗(yàn)證碼平臺(tái)的各種形式驗(yàn)證碼的?
多樣變換的手寫驗(yàn)證碼自動(dòng)識(shí)別算法
簡(jiǎn)單地描述了如何用機(jī)器學(xué)習(xí)繞過(guò)E-ZPass New York網(wǎng)站的驗(yàn)證碼

如何利用機(jī)器學(xué)習(xí)破解驗(yàn)證碼的源代碼教程
評(píng)論