• 按键公众号 :
按键精灵电脑版
立即下载

软件版本:2014.06
软件大小:22.9M
更新时间:2021-12-03

按键精灵安卓版
立即下载

软件版本:3.7.2
软件大小:46.2M
更新时间:2023-05-10

按键精灵iOS版
立即下载

软件版本:1.8.0
软件大小:29.2M
更新时间:2023-03-21

按键手机助手
立即下载

软件版本:3.8.0
软件大小:262M
更新时间:2023-05-30

快捷导航

登录 后使用快捷导航
没有帐号? 注册

发新话题 回复该主题

[笨蛋熊] 【按键精灵X】一种滑块拼图验证码的解决思路 [复制链接]

1#
实现一些自动化功能的时候,经常会遇到这样的滑块拼图验证码:



这种新型验证非常烦人,一方面是拼图缺口位置的识别比较有难度,目前也缺乏成功率很高的打码平台;另一方面是模拟人手的拖动动作,需要生成一段加速度移动曲线。

这期教学我就来教大家如何用很短的代码来实现这类验证码的识别。



我们先观察一下这个验证码,可以发现一个明显的特征,就是拼图缺口处,是通过一张半透明的黑色背景标识的,按照Alpha混合公式,当混合一张半透明的黑色图案时,一同混合的图像RGB数值都会降低,说人话就是亮度变低了,所以缺口处,往往是这类验证码最暗的地方。

掌握了这个信息,识别缺口位置就变得很简单了,只需要扫描一行像素,统计每一个像素及四周(拼图块缺口宽度)一定数量的像素亮度均值,亮度最暗的位置,就是拼图缺口位置了。

由于按键精灵很难访问bitmap数据(图片像素数据),因此我们使用C语言实现这个功能,C语言访问bitmap数据很方便,但是访问图像数据却比较麻烦,好在之前我修改了一份bmp访问的功能,使它能够支持多种格式的bmp文件,通过这项功能,我们只需要实现少量代码,就可以搞定滑块拼图验证码的识别了:
  1. int max3(int a, int b, int c)
  2. {
  3.     int i = (a > b) ? a : b;
  4.     return (i > c) ? i : c;
  5. }

  6. int min3(int a, int b, int c)
  7. {
  8.     int i = (a < b) ? a : b;
  9.     return (i < c) ? i : c;
  10. }



  11. // 识别滑块拼图验证码(返回中心点坐标的位置)
  12. int CrackSliderVCode(char* sFile, int sw, int sh, int iTop)
  13. {
  14.     // 滑块至少从 1/ 4 的位置开始,至少从拼图图形一半的地方结束
  15.     ClImage* img = ffbot_LoadImage(sFile);
  16.     int iPosS = sw;
  17.     int iPosE = img->width - (sw / 2);
  18.     int iOffsetY1 = iTop + (0.33 * sh);
  19.     int iOffsetY2 = iTop + (0.67 * sh);
  20.     int light = 255;
  21.     int left = 0;
  22.     for ( int i = iPosS; i < iPosE; i++ ) {
  23.         int l1[43];
  24.         int l2[43];
  25.         int lt[43];
  26.         for ( int p = 0; p < 43; p++ ) {
  27.             int x = i - 21 + p;
  28.             ClRgbQuad c1 = img->bitmapRGBA[ ((img->height - iOffsetY1) * img->width) + x ];
  29.             ClRgbQuad c2 = img->bitmapRGBA[ ((img->height - iOffsetY2) * img->width) + x ];
  30.             l1[p] = (max3(c1.rgbBlue, c1.rgbGreen, c1.rgbRed) + min3(c1.rgbBlue, c1.rgbGreen, c1.rgbRed)) / 2;
  31.             l2[p] = (max3(c1.rgbBlue, c1.rgbGreen, c1.rgbRed) + min3(c1.rgbBlue, c1.rgbGreen, c1.rgbRed)) / 2;
  32.             lt[p] = (l1[p] + l2[p]) / 2;
  33.         }
  34.         int lsum = 0;
  35.         for ( int p = 0; p < 43; p++ ) {
  36.             lsum += lt[p];
  37.         }
  38.         lsum = lsum / 43;
  39.         if (lsum < light) {
  40.             light = lsum;
  41.             left = i;
  42.         }
  43.         //printf("%d, %d\n", i, lsum);
  44.     }
  45.     //printf("最终结果:%d, %d\n", left, light);
  46.     ffbot_FreeBMP(img);
  47.     return left;
  48. }
复制代码
这里讲解这段代码的含义,我们定义了一个函数CrackSliderVCode,它有四个参数,第一个参数是验证码截图,第二个参数是拼图块的宽度(也就是缺口的宽度),第三个参数是拼图块的高度(也就是缺口的高度),第四个参数是拼图块位于截图的纵坐标偏移(可以通过网页元素获取到)。

当然,也有一些最新的拼图验证码,通过元素无法获取到拼图块纵坐标偏移了,这种情况我们暂不考虑(实现起来也不难,之后可以单独开一篇教程)。

为什么需要拼图块的宽度和高度呢?这个实现充分考虑了不同拼图块大小,提供这些信息可以帮助我们更准确的定位,同样可以通过截图工具直接测量,或者获取拼图块网页元素的宽度和高度。

ffbot_LoadImage 这个函数载入了第一个参数传入的 bmp 图片,它会自动把像素格式转换为32位,这样memory对齐访问起来非常方便。

随后我们通过int iOffsetY1 = iTop + (0.33 * sh); 和 int iOffsetY2 = iTop + (0.67 * sh); 两行代码计算出了拼图款的 1/3 位置和 2/3 位置,因为拼图块有四周和中间可能有缺口,这两个位置是最完整的,可以确保统计的数值可信度较高。

接下来我们会遍历这两条线,获取这两个点及其附近的像素数据,通过 max3 和 min3 两个函数,将RGB值转换为 HSL 值(这里只获取了L值,也就是亮度,相关的算法可以百度 RGB转HSL)

当我们发现一个点的亮度比之前的亮度更低,就会保存这个点的坐标,最后把亮度最低的位置返回。



这篇教程的目的是给大家讲解这类验证码的一种解题思路,bitmap 数据里总是能够挖掘出很多玩法,一些看似复杂的命题,当你掌握了bitmap数据的访问能力,就可以用很巧妙的方法解决掉。

当然,也考虑到很多按键精灵用户不具备C语言开发能力,这里也会将源代码编译为DLL,供按键精灵X调用,为什么不提供按键精灵普通版本调用的版本呢?

因为C语言写COM有点麻烦,暂时先这样,文件我会编译后放在2L提供下载地址(编辑这个帖子会导致代码格式丢失……),补充的内容也都会跟帖。

2#

源代码 + 编译好的DLL下载地址:
vcodeslider.zip (, 下载次数:724)


源代码内置编译器了,直接运行 build.bat 即可编译出 vcode.dll,自己修改了也可以很方便的编译DLL。



按键精灵X可以通过这样的定义来访问函数:

Declare Function CrackSliderVCode Lib "vcode.dll" (sFile As String, sw As Long, sh As Long, iTop As Long) As Long

最后编辑笨蛋熊 最后编辑于 2022-04-10 22:34:49
3#

这类功能使用起来比较麻烦,有一定门槛,因为每一种验证码的情况都不一样,可能需要针对不同的验证码进行单独适配。

只是提供一种解题思路,解题思路当然不止这一种,大家可以充分发挥想象力,挖掘 bitmap 数据的潜能。

4#

卧槽 这还是按键嘛 C都上了 论坛需要你这种人才

5#

不懂C语言,但是很值得学习!非常好的代码!~

6#

感谢指导
最近差点绷不住,找遍全网都没有VB上合适的bmp处理方式,
100*100分辨率都要处理几秒
果然还是得自己搞dll

发新话题 回复该主题