• Java轻松破解顶象滑动拼图验证码


    前言

    本文详细介绍了破解顶象滑动验证码的所有过程,包括破解思路,实现步骤还有测试结果,相信你看完之后也能轻松破解滑动验证码;
    另外,其他类似验证码的破解步骤请参考:
    《腾讯防水墙滑动拼图验证码》

    java OpenCV挑战极验滑动拼图验证码

    一丶解析验证码组成

    在这里插入图片描述
    从上面三张图来看,顶象滑动拼图验证码是由一个小的拼图和一个大的背景图组成,拼图的形状各式各样,背景图中有两个阴影缺口:一个跟拼图一样的阴影缺口,还有一个形状不确定大小也不确定的阴影缺口。
    在这里插入图片描述

    二丶分析出破解思路

    1. 首先根据这个验证码的组成,来分析一下我们人要做的事情:

    按照正常的手动操作流程来看,我们需要看出背景图中与拼图对应的阴影缺口的位置,然后鼠标按住下方滑块来把拼图对正到缺口位置来完成验证。

    1. 然后根据人要做的事情,来分析一下程序要做的事情:

    根据分析得出下面几个步骤:
    1.获取到两张图片(背景图、拼图)
    2.处理图片,得到阴影位置并计算滑动距离
    3.根据滑动距离模拟滑动

    三丶具体操作步骤

    1丶查看网页源码并提取图片信息

    在这里插入图片描述
    在这里插入图片描述
    从上图可以看到,拼图的网络地址存在<img>标签内,而背景图是以canves画布的形式展现出来的。
    拼图我们可以通过selenium获取到img标签中的网络地址,再通过请求获取到图片信息 。
    背景图可以参考《如何抓取canvas画布中的图片》来获取图片信息。

    2丶处理图片,计算滑动距离

    这里由于拼图的图片格式是webp不好处理,所以我们先将拼图转为png格式。
    需要导入jar包webp-imageio-core-0.1.0.jar

    String sUrl = driver.findElement(By.className("dx_captcha_basic_sub-slider")).findElement(By.tagName("img")).getAttribute("src");
    File f = new File("d://dximg.webp");
    FileUtils.copyURLToFile(new URL(sUrl), f);
    
    ImageReader reader = ImageIO.getImageReadersByMIMEType("image/webp").next();
    WebPReadParam readParam = new WebPReadParam();
    readParam.setBypassFiltering(true);
    reader.setInput(new FileImageInputStream(f));
    BufferedImage image = reader.read(0, readParam);
    ImageIO.write(image, "png", new File("d://dximg.png"));
    

    接下来是图片处理过程
    1.根据拼图在页面的高度位置将背景图裁剪,缩小匹配范围

    // 大图裁剪
    BufferedImage sBI = ImageIO.read(sFile);
    BufferedImage bgBI = ImageIO.read(bFile);
    bgBI = bgBI.getSubimage(0, top, bgBI.getWidth(), sBI.getHeight());
    ImageIO.write(bgBI, "png", bFile);
    
    

    在这里插入图片描述

    2.将拼图透明部分变为白色

    setWhite(sBI);
    ImageIO.write(sBI, "png", sFile);
    /**
    * 透明区域变白
     * 
     * @param image
     * @param param
     * @throws IOException
     */
    public void setWhite(BufferedImage image) throws IOException {
    	if (image == null) {
    		return;
    	} else {
    		int rgb;
    		for (int i = 0; i < image.getWidth(); i++) {
    			for (int j = 0; j < image.getHeight(); j++) {
    				rgb = image.getRGB(i, j);
    				int A = (rgb & 0xFF000000) >>> 24;
    				if (A < 100) {
    					image.setRGB(i, j, new Color(255, 255, 255).getRGB());
    				}
    			}
    		}
    	}
    }
    

    在这里插入图片描述
    3.将两张图分别转灰度图像再进行自适应阈值化

    Mat s_mat = Imgcodecs.imread(sFile.getPath());
    Mat b_mat = Imgcodecs.imread(bFile.getPath());
    
    // 转灰度图像
    Mat s_newMat = new Mat();
    Mat b_newMat = new Mat();
    Imgproc.cvtColor(s_mat, s_newMat, Imgproc.COLOR_BGR2GRAY);
    Imgproc.cvtColor(b_mat, b_newMat, Imgproc.COLOR_BGR2GRAY);
    Imgcodecs.imwrite(sFile.getPath(), s_newMat);
    Imgcodecs.imwrite(bFile.getPath(), b_newMat);
    // 自适应阈值化
    Mat s_nMat = new Mat();
    Imgproc.adaptiveThreshold(s_newMat, s_nMat, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 7, -4);
    Imgcodecs.imwrite(sFile.getPath(), s_nMat);
    Mat b_nMat = new Mat();
    Imgproc.adaptiveThreshold(b_newMat, b_nMat, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 7, -4);
    Imgcodecs.imwrite(bFile.getPath(), b_nMat);
    
    b_mat = Imgcodecs.imread(bFile.getPath());
    s_mat = Imgcodecs.imread(sFile.getPath());
    

    在这里插入图片描述
    在这里插入图片描述
    4.将处理过后的两张图进行模糊匹配

    int result_rows = b_mat.rows() - s_mat.rows() + 1;
    int result_cols = b_mat.cols() - s_mat.cols() + 1;
    Mat g_result = new Mat(result_rows, result_cols, CvType.CV_32FC1);
    Imgproc.matchTemplate(b_mat, s_mat, g_result, Imgproc.TM_CCOEFF); // 相关系数匹配法
    Core.normalize(g_result, g_result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
    Point matchLocation = new Point();
    MinMaxLocResult mmlr = Core.minMaxLoc(g_result);
    matchLocation = mmlr.maxLoc; // 此处使用maxLoc还是minLoc取决于使用的匹配算法
    Imgproc.rectangle(b_mat, matchLocation, new Point(matchLocation.x + s_mat.cols(), matchLocation.y + s_mat.rows()), new Scalar(0, 255, 0, 0));
    Imgcodecs.imwrite("d:/dx.png", b_mat);
    

    在这里插入图片描述
    5.根据图片再页面显示比例计算出需要滑动的距离

    (matchLocation.x + s_mat.cols() - sBI.getWidth()) * 3 / 4 - 8)
    
    3丶根据滑动距离模拟滑动

    得到滑动距离直接控制滑块滑动就可以了。
    滑动代码如下:

    
    	/**
    	 * 模拟人工移动
    	 * 
    	 * @param driver
    	 * @param element页面滑块
    	 * @param distance需要移动距离
    	 * @throws InterruptedException
    	 */
    	public static void move(WebDriver driver, WebElement element, int distance) throws InterruptedException {
    		int randomTime = 0;
    		if (distance > 90) {
    			randomTime = 250;
    		} else if (distance > 80 && distance <= 90) {
    			randomTime = 150;
    		}
    		List<Integer> track = getMoveTrack(distance - 2);
    		int moveY = 1;
    		try {
    			Actions actions = new Actions(driver);
    			actions.clickAndHold(element).perform();
    			Thread.sleep(200);
    			for (int i = 0; i < track.size(); i++) {
    				actions.moveByOffset(track.get(i), moveY).perform();
    				Thread.sleep(new Random().nextInt(300) + randomTime);
    			}
    			Thread.sleep(200);
    			actions.release(element).perform();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 根据距离获取滑动轨迹
    	 * 
    	 * @param distance需要移动的距离
    	 * @return
    	 */
    	public static List<Integer> getMoveTrack(int distance) {
    		List<Integer> track = new ArrayList<>();// 移动轨迹
    		Random random = new Random();
    		int current = 0;// 已经移动的距离
    		int mid = (int) distance * 4 / 5;// 减速阈值
    		int a = 0;
    		int move = 0;// 每次循环移动的距离
    		while (true) {
    			a = random.nextInt(10);
    			if (current <= mid) {
    				move += a;// 不断加速
    			} else {
    				move -= a;
    			}
    			if ((current + move) < distance) {
    				track.add(move);
    			} else {
    				track.add(distance - current);
    				break;
    			}
    			current += move;
    		}
    		return track;
    	}
    

    四丶结果展示

    所有的流程都走完了,测试效果。
    在这里插入图片描述
    怎么样还不错吧。

    五丶结果分析

    目标:

    识别阴影位置,推算出对应滑动距离,模拟滑动。

    实现思路:

    1.获取到两张图片(背景图、拼图)
    2.处理图片,得到阴影位置并计算滑动距离
    3.根据滑动距离模拟滑动

    识别耗时:

    15 - 50毫秒

    通过率:

    >95%

     更多参考 https://blog.csdn.net/weixin_49701447/article/details/111643881

    2021-03-31  附一个百度的

  • 相关阅读:
    装饰器 如何理解Python装饰器?
    python装饰器详解
    window 10下安装jdk
    Linux中pam认证详解(上)
    VMware/KVM/OpenStack虚拟化之网络模式总结
    java问题排查命令
    今日面试问题
    Qwtplot3D Qt5.12.0 MinGW 编译运行
    20212022年寒假学习进度06
    Springboot笔记<10>常用注解总结
  • 原文地址:https://www.cnblogs.com/interdrp/p/14371064.html
Copyright © 2020-2023  润新知