标题 简介 类型 公开时间
关联规则 关联知识 关联工具 关联文档 关联抓包
参考1(官网)
参考2
参考3
详情
[SAFE-ID: JIWO-2024-1907]   作者: 对不起 发表于: [2018-09-12]

本文共 [478] 位读者顶过

0×01  验证码的获取

首先获取验证码。由于网站比较特殊,就不以他们的为例,自己生成验证码吧。这个不是重点,这里直接贴代码了。 [出自:jiwo.org]

<?php function createImage($word    ,$imagePath,$type    , $imageName){
   $fontPath = 'msyh.ttc' ;//字体 $fontSize = 20 * 0.75; foreach ($word as $v ) {
        $fontarea  =     imagettfbbox($fontSize, 0 , $fontPath, $v        );
        $textWidth =     $fontarea[2] -     $fontarea [0];
        $textHeight =     $fontarea[1] -     $fontarea [7];
        $tmp[ 'text'] = $v;
        $tmp[ 'size'] = $fontSize;
        $tmp[ 'width'] = $textWidth;
        $tmp[ 'height'] = $textHeight;
        $textArr[] =     $tmp;
   } list( $imageWidth    , $imageHeight,  $imageType) =         getimagesize( $imagePath); for( $i    =0;$i <        count($textArr );$i            ++){ list(    $x, $y) =  randPosition        ($textArr,  $imageWidth,             $imageHeight, $textArr[$i                ][ 'width'], $textArr[                    $i]['height'],                    $i,$type);
        $textArr[    $i]['x'] =     $x;
        $textArr[    $i]['y'] =     $y;
   } unset( $v    ); //创建图片的实例 $image =  imagecreatefromstring    (file_get_contents( $imagePath)); //字体颜色 $color =  imagecolorallocate    ($image, 0, 0, 0); //绘画文字  foreach( $textArr as $v){
        imagefttext (    $image, $v ['size' ], 0 , $v[ 'x' ], $v['y' ], $color,  $fontPath                ,$v ['text']);
   } if (imagepng    ( $image,$imageName )){ echo $imageName    ." \n";
   }
}
functionrandPosition ($textArr    ,  $imgW, $imgH ,         $fontW,  $fontH,$i            ,$type){ switch ($type    ) { case 0 :// 生成mp $x =     rand ($i* 60 , ($i +1)* 60-$fontW - 3);    
             $y =     rand (40, 80 ); break;
         case1    : //生成ap $x = (    $i )*25+ 5 ;
             $y = 25; default: break;
    }
    $return = array ( $x,  $y); return$return ;
}
$ap_imagePath  = 'ap_bg.png' ;
$mp_imagePath  = 'mp_bg.png' ;
$ap_imageName  = "ap_" .    time (). ".png" ;    
$mp_imageName  = "mp_" .    time (). ".png" ;    
$ap_word  = array ( ' 请 ' , ' 依 ' , ' 次 ' , ' 点 ' , ' 击 ' , ' 图 ' , ' 中 ' , ' 的 ' , ' 猎 ' , ' 户 ' , ' 室 ' )                                                                                                                                                                                                                                                                                                                                                                                                                                                ;
$mp_word  = array ( ' 猎 ' , ' 户 ' , ' 实 ' , ' 验 ' , ' 室 ' );
createImage ( $ap_word ,    $ap_imagePath , 1 ,    $ap_imageName );
createImage ( $mp_word ,    $mp_imagePath , 0 ,    $mp_imageName ); ?>

运行后生成这样两张图片。

ap_XXXXX.png

mp_XXXXX.png

ap_XXXXX.png是说明需要点击的文字,mp_XXXXX.png是需要点击的图片。

0×02  验证码识别

对于这种简单的点选验证码,可以有两种很容易的识别方式(机器学习算麻烦的,这里就不列出了。嗯,对,我也不会)。一种是opencv的图像模板匹配,另外一种是OCR识别。

1. opencv的图像模板匹配

第一种方式,使用opencv的图像模板匹配。模板匹配是一种在较大图像中搜索和查找模板图像位置的方法,opencv2和opencv3中提供了一个专门用于模板匹配的函数matchTemplate()。它是在输入图像上滑动模板图像(如在2D卷积中),并比较模板图像下的输入图像的模板和补丁。在OpenCV中实现了六种比较方法(这里用到的是cv2.TM_CCOEFF_NORMED),它返回一个灰度图像,其中每个像素表示该像素的邻域与模板匹配的程度。

获得结果后,可以使用cv.minMaxLoc()函数查找最大/最小值的位置。将其作为矩形的左上角,并将(w,h)作为矩形的宽度和高度,那个矩形就是模板区域。

我们进行使用模板匹配来识别这种验证码时,首先先将“模板”找出来,这里我们需要匹配的是“猎”、“户”、“室”这三个字。将这三个字所在的图片进行截取,然后使用matchTemplate()函数在mp中进行匹配。

首先截取第一个字“猎”。

截取之后,就可以在mp中进行匹配。

这里得到了最大和最小位置。我们使用最大位置,然后将最大值作为阈值。获取模板的尺寸,然后在 mp    中用矩形(红色区域)画出匹配的区域。如下所示。                                                                                                                                                                                                                                

同理,用黄色和蓝色矩形将“户”、“室”所在的区域画出来。

点选时发送所选区域中间的坐标即可,这里就不再给出实例了。这种方法虽然简单,但是对于字体不一的就不能很正确的标记出来。

修改生成图片的代码,将mp中的文字的字体设置为随机。修改的代码如下:

   switch($type) {

case0: //mp文字随机大小

$fontSize=rand (20,30) *0.75 ;

break;

case1 ://ap文字固定

$fontSize=20 *0.75;

break;

   }

ap生成的结果还是和之前一样, mp 的图片如下:                                                                                                                                 

使用同样的代码来匹配。                                                                                                                                                                         

此时匹配的结果就有些惨不忍睹了。所以就换另外一种识别方式-ocr 识别。     

2.OCR识别

这里采用的是腾讯云的OCR-通用印刷体识别(https://cloud.tencent.com/document/product/866/17600)。

参考文档。输入mp图片,返回的是json。

查看json内容,发现包含了图片中的文字、位置和大小等。

同理ap中内容也可以获取。    

此时匹配的时候直接就是匹配文字了。首先获取ap中后三个文字,然后与mp中返回的内容匹配,获取其位置和大小,然后再画矩形即可。

由于比较简单,这里直接贴结果。

匹配相当完美。 

0X03 总结

本文用了两种方法来自动识别汉字点选验证码,第一种采用的是opencv的模板匹配,这种方法虽然也可以匹配到,但这种方法缺点就是对于字体形状差异较大的验证码识别率较低。而第二种方法就比较快捷方便了,而且识别度高,比较推荐第二种方法。

当然这两种方法对于简单、“正规”的验证码可以,遇到复杂的、“扭曲的”验证码就不行了。这时候就要用到机器学习了,而本文只是简单的“识别”,将机器学习用到这里,就有些大材小用了。

评论

暂无
发表评论
 返回顶部 
热度(478)
 关注微信