15 分鐘用 ML 破解一個驗證碼系統
人人都恨驗證碼——那些惱人的圖片,顯示著你在登陸某網站前得輸入的文字。設計驗證碼的目的是,通過驗證你是真實的人來避免電腦自動填充表格。但是隨著深度學習和計算機視覺的興起,現在驗證碼常常易被攻破。
我拜讀了 Adrian Rosebrock 寫的《Deep Learning for Computer Vision with Python》。在書中,Adrian 描述了他是怎樣用機器學習繞過紐約 E-ZPass 網站上的驗證碼:
Adrian 無法接觸到該應用生成驗證碼的原始碼。為了攻破該系統,他不得不下載數百張示例圖片,並手動處理它們來訓練他自己的系統。
但是如果我們想攻破的是一個開源驗證碼系統,我們確實能接觸到原始碼該怎麼辦呢?
我訪問了 WordPress.org 的外掛頻道,並搜尋了“驗證碼”。第一條搜尋結果是 Really Simple CAPTCHA,並且有超過一百萬次的活躍安裝:
最好的一點是,它是開源的!既然我們已經有了生成驗證碼的原始碼,那它應該挺容易被攻破的。為了讓這件事更有挑戰性,讓我們給自己規定個時限吧。我們能在 15 分鐘內完全攻破這個驗證碼系統嗎?來試試吧!
重要說明:這絕不是對 Really Simple CAPTCHA 外掛或對其作者的批評。該外掛作者自己說它已經不再安全了,建議使用其他外掛。這僅僅是一次好玩又迅速的技術挑戰。但是如果你是那剩餘的一百多萬使用者之一,也許你應該改用其他外掛 :)
挑戰
為了構思一個攻擊計劃,來看看 Really Simple CAPTCHA 會生成什麼樣的圖片。在示例網站上,我們看到了以下圖片:
好了,所以驗證碼似乎是四個字母。在 PHP 原始碼中對其進行驗證:
1234567891011121314 | publicfunction__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',); |
沒錯,它用四種不同字型的隨機組合來生成四個字母的驗證碼。並且可以看到,它在程式碼中從未使用 O 或者 I,以此避免使用者混淆。總共有 32 個可能的字母和數字需要我們識別。沒問題!
計時:2 分鐘
工具
在進行下一步前,提一下我們要用來解決問題的工具:
Python 3
Python 是一種有趣的程式語言,它有大量的機器學習和計算機視覺庫。
OpenCV
OpenCV 是一種流行的計算機視覺和圖片處理框架。我們要使用 OpenCV 來處理驗證碼圖片。由於它有 Python API,所以我們可以直接從 Python 中使用它。
Keras
Keras 是用 Python 編寫的深度學習框架。它使得定義、訓練和用最少的程式碼使用深度神經網路容易實現。
TensorFlow
TensorFlow 是 Google 的機器學習庫。我們會用 Keras 程式設計,但是 Keras 並沒有真正實現神經網路的邏輯本身,而是在幕後使用 Google 的 TensorFlow 庫來挑起重擔。
好了,回到我們的挑戰吧!
創造我們的資料集
為了訓練任何機器學習系統,我們需要訓練資料。為了攻破一個驗證碼系統,我們想要像這樣的訓練資料:
鑑於我們有 WordPress 外掛的原始碼,我們可以調整它,一起儲存 10,000 張驗證碼圖片及分別對應的答案。
經過幾分鐘對程式碼的攻擊,並添加了一個簡單的 for 迴圈之後,我有了一個訓練資料的資料夾——10,000 個 PNG 檔案,檔名為對應的正確答案:
這是唯一一個我不會給你示例程式碼的部分。我們做這個是為了教育,我不希望你們真去黑 WordPress 網站。但是,我最後會給你生成的這10,000 張圖片,這樣你就能重複我的結果了。
計時:5 分鐘
簡化問題
既然有了訓練資料,就可以直接用它來訓練神經網路了:
有了足夠的訓練資料,這個方法可能會有用——但是我們可以使問題更簡化來解決。問題越簡單,要解決它需要的訓練資料就越少,需要的計算能力也越低。畢竟我們只有 15 分鐘!
幸運的是,驗證碼圖片總是由僅僅四個字母組成。如果我們能想辦法把圖片分開,使得每個字母都在單獨的圖片中,這樣我們只需要訓練神經網路一次識別一個字母:
我沒有時間去瀏覽 10,000 張訓練圖片並在 Photoshop 中手動把它們拆分開。這得花掉好幾天的時間,而我只剩下 10 分鐘了。我們還不能把圖片分成相等大小的四塊,因為該驗證碼外掛把字母隨機擺放在不同的水平位置上以防止這一做法:
幸運的是,我們仍然可以自動處理。在影象處理中,常常需要檢測有相同顏色的畫素塊。這些連續畫素塊周圍的界限被稱為輪廓。OpenCV 中有一個 LndContours() 函式,可以被用來檢測這些連續區域。
所以我們用一個未經處理的驗證碼圖片開始:
接下來把該圖片轉換成純黑白(這叫做 thresholding),這樣容易找到連續區域:
接著,使用 OpenCV 的 LndContours() 函式來檢測該圖片中包含相同顏色畫素塊的不同部分:
接下來就是簡單地把每個區域存成不同的圖片檔案。鑑於我們知道每張圖片都應該包含從左到右的四個字母,我們可以利用這一點在儲存的同時給字母標記。只要我們是按順序儲存的,我們就應該能儲存好每個圖片字母及其對應的字母名。
但是等等——我看到一個問題!有時驗證碼中有像這樣重疊的字母:
這意味著我們會把兩個字母分離成一個區域:
如果不處理這個問題,會創造出糟糕的訓練資料。我們得解決這個問題,這樣就不會意外地教機器把兩個重疊的字母識別成一個字母了。
一個簡單的方法是,如果一個輪廓區域比它的高度更寬,這意味著很可能有兩個字母重疊在一起了。在這種情況下,我們可以把重疊的字母從中間拆分成兩個,並將其看作兩個不同的字母:
既然我們找到拆分出單個字母的方法了,就對所有驗證碼圖片進行該操作。目標是收集每個字母的不同變體。我們可以將每個字母儲存在各自對應的資料夾中,以保持條理。
在我分離出所有字母后,我的 W 資料夾長這樣:
計時:10 分鐘
構建並訓練神經系統
由於我們只需要識別單個字母和數字的圖片,我們不需要非常複雜的神經網路結構。識別字母要比識別像貓狗這樣複雜的圖片容易得多。
我們要使用簡單的卷積神經網路結構,有兩層卷積層以及兩層完全連線層:
如果你想要了解更多神經網路的工作,以及為什麼它們是圖片識別的理想工具,請參考 Adrian 的書或者我之前的文章。
定義該神經網路結構,只需要使用 Keras 的幾行程式碼:
1234567891011121314151617181920 | # Build the neural network!model=Sequential()# First convolutional layer with max poolingmodel.add(Conv2D(20,(5,5),padding="same",input_shape=(20,20,1),activation="relu"))model.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))# Second convolutional layer with max poolingmodel.add(Conv2D(50,(5,5),padding="same",activation="relu"))model.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))# Hidden layer with 500 nodesmodel.add(Flatten())model.add(Dense(500,activation="relu"))# Output layer with 32 nodes (one for each possible letter/number we predict)model.add(Dense(32,activation="softmax"))# Ask Keras to build the TensorFlow model behind the scenesmodel.compile(loss="categorical_crossentropy",optimizer="adam",metrics=["accuracy"]) |
現在我們可以訓練它了!
12 | # Train the neural networkmodel.fit(X_train,Y_train,validation_data=(X_test,Y_test),batch_size=32,epochs=10,verbose=1) |
在 10 通過了訓練資料集後,我們達到了幾乎 100% 的正確率。此時,我們應該能隨時自動繞過這個驗證碼了!我們成功了!
計時:15 分鐘(好險!)
使用訓練後的模型來處理驗證碼
既然有了一個訓練後的神經網路,利用它來攻破真實的驗證碼要很容易了:
- 1.從一個使用 WordPress 外掛的網站上下載一張驗證碼圖片。
- 2.使用文章中生成訓練資料集的方法,把該驗證碼圖片拆分成四張字母圖片。
- 3.用神經網路對每張字母圖片分別作預測。
- 4.用四個預測字母作為驗證碼的答案。
- 5.狂歡!
在破解驗證碼時,我們的模型看起來是這樣:
或者從命令來看:
來試試吧!
如果你想自己試試,你可以從這裡找到程式碼( http://t.cn/R8yFJiN )。它包含 10,000 張示例圖片和文章中每一步的所有程式碼。參考檔案 README.md 中的執行指導。
但是如果你想了解每一行程式碼都做了什麼,我強烈建議你看看《 Deep Learning for Computer Vision with Python》。該書覆蓋了更多的細節,而且有大量的詳細示例。這本書是我目前見過的唯一一本既包含了執行原理,又包含了如何在現實生活中用其來解決複雜問題的書。去看看吧!
相關推薦
15 分鐘用 ML 破解一個驗證碼系統
人人都恨驗證碼——那些惱人的圖片,顯示著你在登陸某網站前得輸入的文字。設計驗證碼的目的是,通過驗證你是真實的人來避免電腦自動填充表格。但是隨著深度學習和計算機視覺的興起,現在驗證碼常常易被攻破。 我拜讀了 Adrian Rosebrock 寫的《Deep Learning fo
15分鐘破解網站驗證碼
概述 http://www.bugcode.cn/break_captcha.html 很多開發者都討厭網站的驗證碼,特別是寫網路爬蟲的程式設計師,而網站之所以設定驗證碼,是為了防止機器人訪問網站,造成不必要的損失。現在好了,隨著機器學習技術的發展,機器識別驗證碼的問題比較好解決了。 樣本採集
使用php寫出一個驗證碼圖片,由於寬度被定死了,所以操作起來不太方便,之後盡量寫靈活,成為一個可調用的函數。
新手 put 由於 -type draw cat 驗證 font 寬度 <?php // Due to the height and width of the captcha image is fixed, not so easy to use, change
爬取有驗證碼的網站,(爬之前最好看一下君子協定)robots.txt,以人人網為例,每爬100條資料需要驗證一次(需要自己購買一個驗證碼破解會員,不是很貴,我這裡選擇的是超級鷹),簡版
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/10/15 14:03 # @Author : zhangz # @File : day4_yanzhengma.py # @Software: Py
Flask學習之旅--用 Python + Flask 製作一個簡單的驗證碼系統
一、寫在前面 現在無論大大小小的網站,基本上都會使用驗證碼,登入的時候要驗證,下載的時候要驗證,而使用的驗證碼也從那些簡簡單單的字元圖形驗證碼“進化”成了需要進行圖文識別的驗證碼、需要拖動滑塊的滑動驗證碼、甚至還有手機驗證碼。當你與之打交道的時候,有沒有考慮過其背後的原理呢?當然
用Canvas生成隨機驗證碼(後端前端都可以)
ntb inf pre text contex back data listen nload 一 、使用前端生成驗證碼 <!DOCTYPE html> <html> <head> <meta charse
根據提示輸入一個驗證碼 並判斷正誤
cnblogs 掃描 正則表達 rom tro 強制轉換 mat 空字符串 強制 源代碼: import javax.swing.JOptionPane;import java.util.Scanner;import javax.swing.JOptionPane;
Python Cookbook(第3版)中文版:15.9 用WSIG包裝C代碼
轉換 -i 代碼 第3版 deb mac 變量 cor bundle 15.9 用WSIG包裝C代碼? 問題? 你想讓你寫的C代碼作為一個C擴展模塊來訪問,想通過使用 Swig包裝生成器 來完成。 解決方案? Swig通過解析C頭文件並自動創建擴展代碼來操作。要使用它,
使用nodejs去做一個驗證碼
req sta 一個 驗證 buffer class red apt img let express = require(‘express‘); let captchapng = require(‘captchapng‘); let app = express();
爬蟲 - 用ocr來識別驗證碼
open roc pen bre ocr mage 灰度 mode 證明 用OCR來識別 直接識別效果不好,因為驗證碼內的多余線條幹擾了圖片的識別。先轉為灰度圖像,再二值化。經實踐證明,該方法不是100%正確。 # 獲取圖片 curl -X GET http://my.cn
使用深度學習的CNN神經網路破解Captcha驗證碼
樣本資料的生成與處理: 我們先來看看mnist(一個手寫體數字圖片的資料集,有55000張0-9的手寫體數字的圖片)中圖片和圖片標籤的資料形式: 已知mnist資料集中的每張圖片是28x28畫素的灰度影象。每張圖片上是一個單獨的手寫體數字。 程式碼如下: from tensorf
破解滑動驗證碼(極驗)
from selenium.webdriver import ActionChains from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui im
python selenium接入打碼平臺破解豆瓣驗證碼登入
from selenium import webdriverimport requestsimport timeimport refrom chaojiying import Chaojiying_Clientfrom selenium.common.exceptions import NoSuchEleme
keras入門(三)搭建CNN模型破解網站驗證碼
專案介紹 在文章CNN大戰驗證碼中,我們利用TensorFlow搭建了簡單的CNN模型來破解某個網站的驗證碼。驗證碼如下: 在本文中,我們將會用Keras來搭建一個稍微複雜的CNN模型來破解以上的驗證碼。 資料集 對於驗證碼圖片的處理過程在本文中將不再具體敘
搭建CNN模型破解網站驗證碼!Python大法真的好!
專案介紹 在文章CNN大戰驗證碼中,我們利用TensorFlow搭建了簡單的CNN模型來破解某個網站的驗證碼。驗證碼如下: 網站驗證碼 在本文中,我們將會用Keras來搭建一個稍微複雜的CNN模型來破解以上的驗證碼。 資料集 對於驗證碼圖片的處理過程在本文
Servlet和Image如何做出一個驗證碼程式的完整版的原始碼?
馬克-to-win:(視訊下載) (全部書籍) 根據上面程式,我做了一個驗證碼程式的大概。所有的技術點都已經涵蓋了。有興趣的同學可以自己把完整版的驗證碼程式做出來。 例:4.4.4 <%@ page contentType="text/html; charset=GBK"%&
做出一個驗證碼
package cn.itcast.other; import java.util.Random; /* 需求: 實現一個四位的驗證碼。 */ public class Demo6 { public static void main(String[] args) { c
開箱即用的vue獲取驗證碼元件
<template> <button :style="config.cssSet?config.cssSet:''" class="common-getCodeBtn" @click="toget
[TensorFlow深度學習深入]實戰二·使用CNN網路識別破解數字驗證碼
[TensorFlow深度學習深入]實戰二·使用CNN網路識別破解數字驗證碼 參考部落格。 在此基礎上做了小修改。 其中CNN網路部分仿照我們入門實戰六的內容,如果不太清楚CNN可以再去回顧一下。 本博文資料集。 程式碼部分 import os os.environ["KMP_D
用Python生成圖片驗證碼,
用Python生成圖片驗證碼, Python版本:Python3.6 程式碼如下: # -*-coding:utf-8 -*- from PIL import Image, ImageDraw, ImageFont, ImageFilter import random import