100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 使用OpenCV 破解QQ登录中的滑动验证码

使用OpenCV 破解QQ登录中的滑动验证码

时间:2020-11-07 10:58:15

相关推荐

使用OpenCV 破解QQ登录中的滑动验证码

系列文章目录

第一篇:Java实现QQ登录

第二篇:Selenium QQ自动化登录

第三篇:使用OpenCV 破解QQ登录中的滑动验证码

文章目录

系列文章目录

文章目录

前言

一、登录流程

二、验证办法

1.滑动验证码

2.获取缺口坐标

2.1 获得两张验证码的url

2.2 处理图片获得x坐标

2.3 调用结果

总结

前言

前面几篇文章中介绍了在安全状态下,QQ登录的几种方法,但是只要是,该账号登录在新IP上,或用新账号登录本IP,都会使得登录流程转向非安全状态,即会有图片验证码,如下:

提示:以下是本篇文章正文内容,下面案例可供参考

一、登录流程

如我在第一篇文章中介绍那样:Java实现QQ登录,会多出几个请求,其中我们会看到又两个img的请求:

而这两个请求正是获得验证码图片和图片缺口的接口。

二、验证办法

1.滑动验证码

当我们拖动滑块并停止时,会向后台发送一个cap_union_new_verify的请求,这个request的data里,又这样一个关键的数据,ans

经过分析得知,这个ans的值,正式滑动验证码中缺口图片在原图中的位置,那么我们只要能获得这个缺口坐标,即可获得正确request data。

2.获取缺口坐标

我们使用OpenCV来处理图片

2.1 获得两张验证码的url

大图:

https://t./hycdn?index=1&image=937349372142954496?aid=21000501&sess=s0QmzAR9jp0J_P9zQf6-BikkZVSLAm3IZz9JBiMAkRnqiQQ-ehtcopO3OYgJzF9ZLrA1B6phmWOrNtG1YEarWRA9wRp2gHvMW9lzGN5bZgFvIdgvL1ljAEcUq-ASo3WNABJPoMJP-UWSkRsimXX2wetiGFbUg7pMjUYGBPJAUxL8gCiyRnbKExWMrjyzVu4onNqzoxRU4_Ou9jexaVzeERJRo-WahiuPG2NyiohF5390zOVQ1tmDAmDg**&sid=607792806632235317&img_index=1&subsid=9

缺口图:

https://t./hycdn?index=2&image=937349372142954496?aid=21000501&sess=s0QmzAR9jp0J_P9zQf6-BikkZVSLAm3IZz9JBiMAkRnqiQQ-ehtcopO3OYgJzF9ZLrA1B6phmWOrNtG1YEarWRA9wRp2gHvMW9lzGN5bZgFvIdgvL1ljAEcUq-ASo3WNABJPoMJP-UWSkRsimXX2wetiGFbUg7pMjUYGBPJAUxL8gCiyRnbKExWMrjyzVu4onNqzoxRU4_Ou9jexaVzeERJRo-WahiuPG2NyiohF5390zOVQ1tmDAmDg**&sid=607792806632235317&img_index=2&subsid=10

url中最重要的参数sess可从上一个请求:cap_union_prehandle中的response中获得。

验证码的图有时间限制,一段时间后会过期

2.2 处理图片获得x坐标

因为滑块是左右滑动的,所以y坐标固定,我们先滑动一下获得他的y坐标,本例中的y坐标是41。

使用下面程序:

// 加载opencv环境public static String dllPath = "D:\\workcode\\txslider\\src\\main\\resources\\opencv\\opencv_java3413.dll";/*** 获取验证滑动距离** @return*/public static int getTencentDistance(String bUrl, String sUrl, int top) {System.load(dllPath);File bFile = new File("D:\\cap_union_new_getcapbysig.jpg");File sFile = new File("D:\\cap_union_new_getcapbysig.png");try {FileUtils.copyURLToFile(new URL(bUrl), bFile);FileUtils.copyURLToFile(new URL(sUrl), sFile);BufferedImage bgBI = ImageIO.read(bFile);BufferedImage sBI = ImageIO.read(sFile);// 裁剪bgBI = bgBI.getSubimage(360, top, bgBI.getWidth() - 370, sBI.getHeight());ImageIO.write(bgBI, "png", bFile);Mat s_mat = Imgcodecs.imread(sFile.getPath());Mat b_mat = Imgcodecs.imread(bFile.getPath());// 转灰度图像Mat s_newMat = new Mat();Imgproc.cvtColor(s_mat, s_newMat, Imgproc.COLOR_BGR2GRAY);// 二值化图像binaryzation(s_newMat);Imgcodecs.imwrite(sFile.getPath(), s_newMat);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_SQDIFF); // 归一化平方差匹配法// 归一化相关匹配法Core.normalize(g_result, g_result, 0, 1, Core.NORM_MINMAX, -1, new Mat());Core.MinMaxLocResult mmlr = Core.minMaxLoc(g_result);Point 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, 0, 0, 0));return (int) ((matchLocation.x + s_mat.cols() + 360 - sBI.getWidth()));} catch (Throwable e) {e.printStackTrace();return 0;} finally {bFile.delete();sFile.delete();}}/**** @param mat* 二值化图像*/public static void binaryzation(Mat mat) {int BLACK = 0;int WHITE = 255;int ucThre = 0, ucThre_new = 127;int nBack_count, nData_count;int nBack_sum, nData_sum;int nValue;int i, j;int width = mat.width(), height = mat.height();// 寻找最佳的阙值while (ucThre != ucThre_new) {nBack_sum = nData_sum = 0;nBack_count = nData_count = 0;for (j = 0; j < height; ++j) {for (i = 0; i < width; i++) {nValue = (int) mat.get(j, i)[0];if (nValue > ucThre_new) {nBack_sum += nValue;nBack_count++;} else {nData_sum += nValue;nData_count++;}}}nBack_sum = nBack_sum / nBack_count;nData_sum = nData_sum / nData_count;ucThre = ucThre_new;ucThre_new = (nBack_sum + nData_sum) / 2;}// 二值化处理int nBlack = 0;int nWhite = 0;for (j = 0; j < height; ++j) {for (i = 0; i < width; ++i) {nValue = (int) mat.get(j, i)[0];if (nValue > ucThre_new) {mat.put(j, i, WHITE);nWhite++;} else {mat.put(j, i, BLACK);nBlack++;}}}// 确保白底黑字if (nBlack > nWhite) {for (j = 0; j < height; ++j) {for (i = 0; i < width; ++i) {nValue = (int) (mat.get(j, i)[0]);if (nValue == 0) {mat.put(j, i, WHITE);} else {mat.put(j, i, BLACK);}}}}}

主要思想为:根据传入的y坐标和两个图片的url,将网络上的图片先保存在本地,然后对大图进行切图,减少一些计算量,然后二值化两张图,接着使用归一化相关匹配法,计算出切图后的x距离,最后加上原来的x距离,即可得到最终的x坐标。

2.3 调用结果

getTencentDistance("https://t./hycdn?index=1&image=937349372142954496?aid=21000501&sess=s0QmzAR9jp0J_P9zQf6-BikkZVSLAm3IZz9JBiMAkRnqiQQ-ehtcopO3OYgJzF9ZLrA1B6phmWOrNtG1YEarWRA9wRp2gHvMW9lzGN5bZgFvIdgvL1ljAEcUq-ASo3WNABJPoMJP-UWSkRsimXX2wetiGFbUg7pMjUYGBPJAUxL8gCiyRnbKExWMrjyzVu4onNqzoxRU4_Ou9jexaVzeERJRo-WahiuPG2NyiohF5390zOVQ1tmDAmDg**&sid=607792806632235317&img_index=1&subsid=9","https://t./hycdn?index=2&image=937349372142954496?aid=21000501&sess=s0QmzAR9jp0J_P9zQf6-BikkZVSLAm3IZz9JBiMAkRnqiQQ-ehtcopO3OYgJzF9ZLrA1B6phmWOrNtG1YEarWRA9wRp2gHvMW9lzGN5bZgFvIdgvL1ljAEcUq-ASo3WNABJPoMJP-UWSkRsimXX2wetiGFbUg7pMjUYGBPJAUxL8gCiyRnbKExWMrjyzVu4onNqzoxRU4_Ou9jexaVzeERJRo-WahiuPG2NyiohF5390zOVQ1tmDAmDg**&sid=607792806632235317&img_index=2&subsid=10",41)

调用getTencentDistance方法,传入大图和缺口图的地址,并传入y坐标。

最终结果为:

而实际y坐标为

相差6个像素点,在可接受范围内。

总结

本文主要介绍了用opencv,来识别滑动验证码中,缺口图片相对背景图的x坐标,获得了x坐标位置,即可模拟手动滑动,完成验证码的突破,结合前面几篇文章,即可完成有验证码情况下的登录。

当然还有更方便的方式,即通过Selenium自动模仿人手动滑动的方法,这种方法将在下篇文章中介绍。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。