TensorFlow автоматически распознает проверочный код (2)

машинное обучение

0X000 Предисловие

В этой статье «Автоматическая идентификация кодов проверки с использованием tensorflow (1)» я кратко понимаю и описываю процесс использования tensorflow для автоматической идентификации кодов проверки. Итак, в сегодняшней статье мы изменим код из предыдущей статьи, чтобы добиться взлома проверочного кода для основной CMS.

0x001 шаги взлома

Давайте рассмотрим шаги кода автоматической проверки идентификации tensorflow.

  • выборка

  • Создайте модель распознавания

  • Обучите модель распознавания

  • Сохраните модель распознавания

  • проверять

Поскольку последние три шага в основном представляют собой тензорный поток, для автоматического завершения нашей основной работы являются первые два шага. Итак, шаги в основном следующие:

  • Ищем модули капчи в системах с открытым исходным кодом

  • Модифицировать и тестировать модули капчи

  • Модуль кода проверки адаптируется к коду выборки

  • Изменить идентификациюПараметры модели

0x002 Ищем модуль проверочного кода в системе с открытым исходным кодом

Сначала найдите cms, который хотите взломать (неважно, открываете вы исходники или нет, главное, чтобы исходники были у вас). Здесь мы используем XXXCMS (=.= заблокируйте ключевые слова, придумайте сами), давайте сначала авторизуемся под администратором, ОК, код проверки действительно есть.

Откройте редактор и найдите класс, генерирующий проверочный код.checkcode.class.php

<?php
/**
 * 生成验证码
 * @author chenzhouyu
 * 类用法
 * $checkcode = new checkcode();
 * $checkcode->doimage();
 * //取得验证
 * $_SESSION['code']=$checkcode->get_code();
 */
class checkcode {
    //验证码的宽度
    public $width=130;

    //验证码的高
    public $height=50;

    //设置字体的地址
    private $font;

    //设置字体色
    public $font_color;

    //设置随机生成因子
    public $charset = 'abcdefghkmnprstuvwyzABCDEFGHKLMNPRSTUVWYZ23456789';

    //设置背景色
    public $background = '#EDF7FF';

    //生成验证码字符数
    public $code_len = 4;

    //字体大小
    public $font_size = 20;

    //验证码
    private $code;

    //图片内存
    private $img;

    //文字X轴开始的地方
    private $x_start;

    function __construct() {
        $rand = rand(0,1);
        if($rand==0) {
            $this->font = PC_PATH.'libs'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'font'.DIRECTORY_SEPARATOR.'elephant.ttf';
        } else {
            $this->font = PC_PATH.'libs'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'font'.DIRECTORY_SEPARATOR.'Vineta.ttf';
        }
    }

    /**
     * 生成随机验证码。
     */
    protected function creat_code() {
        $code = '';
        $charset_len = strlen($this->charset)-1;
        for ($i=0; $i<$this->code_len; $i++) {
            $code .= $this->charset[rand(1, $charset_len)];
        }
        $this->code = $code;
    }

    /**
     * 获取验证码
     */
    public function get_code() {
        return strtolower($this->code);
    }

    /**
     * 生成图片
     */
    public function doimage() {
        $code = $this->creat_code();
        $this->img = imagecreatetruecolor($this->width, $this->height);
        if (!$this->font_color) {
            $this->font_color = imagecolorallocate($this->img, rand(0,156), rand(0,156), rand(0,156));
        } else {
            $this->font_color = imagecolorallocate($this->img, hexdec(substr($this->font_color, 1,2)), hexdec(substr($this->font_color, 3,2)), hexdec(substr($this->font_color, 5,2)));
        }
        //设置背景色
        $background = imagecolorallocate($this->img,hexdec(substr($this->background, 1,2)),hexdec(substr($this->background, 3,2)),hexdec(substr($this->background, 5,2)));
        //画一个柜形,设置背景颜色。
        imagefilledrectangle($this->img,0, $this->height, $this->width, 0, $background);
        $this->creat_font();
        $this->creat_line();
        $this->output();
    }

    /**
     * 生成文字
     */
    private function creat_font() {
        $x = $this->width/$this->code_len;
        for ($i=0; $i<$this->code_len; $i++) {
            imagettftext($this->img, $this->font_size, rand(-30,30), $x*$i+rand(0,5), $this->height/1.4, $this->font_color, $this->font, $this->code[$i]);
            if($i==0)$this->x_start=$x*$i+5;
        }
    }

    /**
     * 画线
     */
    private function creat_line() {
        imagesetthickness($this->img, 3);
        $xpos   = ($this->font_size * 2) + rand(-5, 5);
        $width  = $this->width / 2.66 + rand(3, 10);
        $height = $this->font_size * 2.14;

        if ( rand(0,100) % 2 == 0 ) {
          $start = rand(0,66);
          $ypos  = $this->height / 2 - rand(10, 30);
          $xpos += rand(5, 15);
        } else {
          $start = rand(180, 246);
          $ypos  = $this->height / 2 + rand(10, 30);
        }

        $end = $start + rand(75, 110);

        imagearc($this->img, $xpos, $ypos, $width, $height, $start, $end, $this->font_color);

        if ( rand(1,75) % 2 == 0 ) {
          $start = rand(45, 111);
          $ypos  = $this->height / 2 - rand(10, 30);
          $xpos += rand(5, 15);
        } else {
          $start = rand(200, 250);
          $ypos  = $this->height / 2 + rand(10, 30);
        }

        $end = $start + rand(75, 100);

        imagearc($this->img, $this->width * .75, $ypos, $width, $height, $start, $end, $this->font_color);
    }

    /**
     * 输出图片
     */
    private function output() {
        header("content-type:image/png\r\n");
        imagepng($this->img);
        imagedestroy($this->img);
    }
}скопировать код

Подготовительные работы в основном завершены. Далее модифицируем и тестируем модуль капчи.

0x003 Изменить и протестировать модуль проверочного кода

Поскольку коды проверки системы генерируются случайным образом и не поддаются контролю, нам необходимо преобразовать приведенный выше код в вид, подобныйcreate_img.php?code=XXXXТаким образом, мы можем контролировать генерацию проверочного кода с помощью параметров случайной генерации последнего py-кода для достижения цели генерации образцов. Стоит отметить, что эта система использует два шрифта для генерации своего проверочного кода, один из них удален, чтобы уменьшить нагрузку на распознавание.

После модификации сохранить какcreate_img.php

<?php
class checkcode
{
    //验证码的宽度
    public $width = 130;

    //验证码的高
    public $height = 50;

    //设置字体的地址
    private $font;

    //设置字体色
    public $font_color;

    //设置随机生成因子
    public $charset = 'abcdefghkmnprstuvwyzABCDEFGHKLMNPRSTUVWYZ23456789';

    //设置背景色
    public $background = '#EDF7FF';

    //生成验证码字符数
    public $code_len = 4;

    //字体大小
    public $font_size = 20;

    //验证码
    private $code;

    //图片内存
    private $img;

    //文字X轴开始的地方
    private $x_start;

    function __construct()
    {

        $this->font = './font/elephant.ttf';

    }

    /**
     * 生成随机验证码。
     */
    protected function creat_code()
    {

        $this->code = $_GET['code'];
    }

    /**
     * 获取验证码
     */
    public function get_code()
    {
        return strtolower($this->code);
    }

    /**
     * 生成图片
     */
    public function doimage()
    {
        $code = $this->creat_code();
        $this->img = imagecreatetruecolor($this->width, $this->height);
        if (!$this->font_color) {
            $this->font_color = imagecolorallocate($this->img, rand(0, 156), rand(0, 156), rand(0, 156));
        } else {
            $this->font_color = imagecolorallocate($this->img, hexdec(substr($this->font_color, 1, 2)), hexdec(substr($this->font_color, 3, 2)), hexdec(substr($this->font_color, 5, 2)));
        }
        //设置背景色
        $background = imagecolorallocate($this->img, hexdec(substr($this->background, 1, 2)), hexdec(substr($this->background, 3, 2)), hexdec(substr($this->background, 5, 2)));
        //画一个柜形,设置背景颜色。
        imagefilledrectangle($this->img, 0, $this->height, $this->width, 0, $background);
        $this->creat_font();
        $this->creat_line();
        $this->output();
    }

    /**
     * 生成文字
     */
    private function creat_font()
    {
        $x = $this->width / $this->code_len;
        for ($i = 0; $i < $this->code_len; $i++) {
            imagettftext($this->img, $this->font_size, rand(-30, 30), $x * $i + rand(0, 5), $this->height / 1.4, $this->font_color, $this->font, $this->code[$i]);
            if ($i == 0) $this->x_start = $x * $i + 5;
        }
    }

    /**
     * 画线
     */
    private function creat_line()
    {
        imagesetthickness($this->img, 3);
        $xpos = ($this->font_size * 2) + rand(-5, 5);
        $width = $this->width / 2.66 + rand(3, 10);
        $height = $this->font_size * 2.14;

        if (rand(0, 100) % 2 == 0) {
            $start = rand(0, 66);
            $ypos = $this->height / 2 - rand(10, 30);
            $xpos += rand(5, 15);
        } else {
            $start = rand(180, 246);
            $ypos = $this->height / 2 + rand(10, 30);
        }

        $end = $start + rand(75, 110);

        imagearc($this->img, $xpos, $ypos, $width, $height, $start, $end, $this->font_color);

        if (rand(1, 75) % 2 == 0) {
            $start = rand(45, 111);
            $ypos = $this->height / 2 - rand(10, 30);
            $xpos += rand(5, 15);
        } else {
            $start = rand(200, 250);
            $ypos = $this->height / 2 + rand(10, 30);
        }

        $end = $start + rand(75, 100);

        imagearc($this->img, $this->width * .75, $ypos, $width, $height, $start, $end, $this->font_color);
    }

    /**
     * 输出图片
     */
    private function output()
    {
        header("content-type:image/png\r\n");
        imagepng($this->img);
        imagedestroy($this->img);
    }
}

$checkcode = new checkcode();
$checkcode->doimage();скопировать код

Рядом с тестом напишитеtest.py

import requests as req
from PIL import Image
from io import BytesIO
import numpy as np

response = req.get('http://127.0.0.1:8080/xxxcms/create_img.php?code=1234')
image = Image.open(BytesIO(response.content))
gray = image.convert('L')  #灰值
gray = gray.point(lambda x: 0 if x<128 else 255, '1') #去杂质
gray.show()
img = np.array(gray.getdata()) #转换成数组

print  imgскопировать код

бегатьpython test.py

Если открыть и увидеть консоль и черно-белые картинки то От имени проверочного кода часть готова

0x004 Модуль кода проверки адаптируется к коду выборки

Ориентируйтесь на несколько параметров

  • код верификациипорождающий фактор

  • код верификациидлинная,ширина

  • код верификацииколичество цифр

В приведенном выше классе мы видим, что значения этих параметров в порядке

  • 生成因子: abcdefghkmnprstuvwyzABCDEFGHKLMNPRSTUVWYZ23456789

  • 长宽:130x50

  • 位数: 4;

сделать копиюgenerate_captcha.pyзаxxxcms_generate_captcha.py

Добавить кfrom io import BytesIOиimport requests as reqимпорт

В основном изменить два места

Первый параметр сборки в начале

width=130,  # 验证码图片的宽
 height=50,  # 验证码图片的高
 char_num=4,  # 验证码字符个数
 characters='abcdefghkmnprstuvwyzABCDEFGHKLMNPRSTUVWYZ23456789'):скопировать код

Второйgen_captchaМетод получения изображения в методе изменен наtest.pyметод в

X = np.zeros([batch_size, self.height, self.width, 1])
img = np.zeros((self.height, self.width), dtype=np.uint8)
Y = np.zeros([batch_size, self.char_num, self.classes])
image = ImageCaptcha(width=self.width, height=self.height)
while True:
    for i in range(batch_size):
        captcha_str = ''.join(random.sample(self.characters, self.char_num))
        imgurl = 'http://127.0.0.1:8080/xxxcms/create_img.php?code='+captcha_str
        response = req.get(imgurl)
        img = Image.open(BytesIO(response.content)).convert('L')
        img = np.array(img.getdata())
        X[i] = np.reshape(img, [self.height, self.width, 1]) / 255.0
        for j, ch in enumerate(captcha_str):
            Y[i, j, self.characters.find(ch)] = 1
    Y = np.reshape(Y, (batch_size, self.char_num * self.classes))
    yield X, Yскопировать код

Откройте train_captcha.py и поместитеimport generate_captchaизменить наimport xxxcms_generate_captcha as generate_captcha

повторный запускpython train_captcha.py

В остальном процесс аналогичен первому.

0x005 несколько советов

  • Как проверить, сработал ли мой алгоритм

    • Посмотрите, постепенно ли уменьшается стоимость потерянного

  • Можно ли взломать любой проверочный код?

    • Теоретически, большие и маленькие буквы + цифры и некоторые изображения только с несколькими линиями или точками в принципе подходят. проблема вероятности

  • Базовая скорость взлома составляет 4 бита. 5, 6 и выше требуют больших машин, чтобы ускорить создание моделей.

  • Как ускорить генерацию моей модели

    • Добавить оборудование

    • Настройка параметров генерации модели

    • Купить сервер Alibaba Cloud GPU в облаке Alibaba