通过比较rgb破解滑动验证码
阅读原文时间:2023年07月08日阅读:2

目标url:信用中国(广东中山)行政处罚

/**
* base64转BufferedImage
*
* @param base64
* @return
*/
public static BufferedImage base64ToBufferedImage(String base64) {
BufferedImage ret = null;
try {
Decoder decoder = Base64.getDecoder();
ByteArrayInputStream bais = new ByteArrayInputStream(decoder.decode(base64));
ret = ImageIO.read(bais);
return ret;
} catch (IOException ex) {
Logger.getLogger(SliderUtil.class.getName()).log(Level.SEVERE, null, ex);
return ret;
}
}

/\*\*  
 \* 获取滑块偏移距离和session  
 \*  
 \* @param url  
 \* @param session  
 \* @return  
 \* @throws IOException  
 \*/  
public static int getDistanceAndSession(String url, StringBuffer session) throws IOException {  
    int ret = -1;  
    Gson gson = new Gson();  
    Connection conn = Jsoup.connect(url);  
    conn.method(Connection.Method.GET).timeout(10 \* 1000).ignoreContentType(true).maxBodySize(0);  
    Response res = conn.execute();  
    //获取session  
    //先清空  
    session.delete(0, session.length());  
    session.append(res.cookie("JSESSIONID"));  
    HashMap<String, Object> hm = gson.fromJson(res.body(), HashMap.class);  
    //滑块相对于原图的y坐标偏移  
    int puzzleYAxis = Integer.parseInt(hm.get("puzzleYAxis").toString());  
    //图片的base64字符  
    String sourceBase64 = hm.get("sourceImg").toString().replace("\\r\\n", "");  
    String puzzleBase64 = hm.get("puzzleImg").toString().replace("\\r\\n", "");  
    //原图  
    BufferedImage sourceImg = base64ToBufferedImage(sourceBase64);  
    //滑块  
    BufferedImage puzzleImg = base64ToBufferedImage(puzzleBase64);  
    //滑块宽度  
    int puzzleImgWidth = puzzleImg.getWidth();  
    //滑块高度  
    int puzzleImgHeight = puzzleImg.getHeight();  
    //原图宽度  
    int width = sourceImg.getWidth();  
    //原图高度  
    int height = sourceImg.getHeight();  

// //用于保存原图的rgb
// int[] rgbArray = new int[width * height];
// sourceImg.getRGB(0, 0, width, height, rgbArray, 0, width);
//保存原图待对比的rgb数组
int[] sourceImgRgbArr = new int[width * puzzleImgHeight];
//保存滑块的rgb数组
int[] puzzleImgRgbArr = new int[puzzleImgWidth * puzzleImgHeight];
//将滑块的rgb复制到rgb数组中
puzzleImg.getRGB(0, 0, puzzleImgWidth, puzzleImgHeight, puzzleImgRgbArr, 0, puzzleImgWidth);
int k = 0;
//截取与滑块等高的rgb数组
for (int i = puzzleYAxis; i < puzzleYAxis + puzzleImgHeight; i++) {
for (int j = 0; j < width; j++) {
//获取需要对比的原图rgb数组
sourceImgRgbArr[k++] = sourceImg.getRGB(j, i);
// System.out.printf("%10x", img.getRGB(j, i));
// System.out.println(k);
}
// System.out.println();
}
//记录当前比对的第几列
int index = 0;
//记录已比对的列数
int c = 0;
//总的比对列数
//只要比对六列相等,就认为找到位置
int count = 6;
//是否找到rgb相等的值
boolean isFind = false;
//比对每一列的数据
for (int i = 0; i < width; i++) {
//记录当前比对的第几列
index = i;
for (int j = 0; j < puzzleImgHeight; j++) {
//判断rgb值是否相等
if (sourceImgRgbArr[j * width + i] != puzzleImgRgbArr[j * puzzleImgWidth + c]) {
//标志更新为false
isFind = false;
// System.out.println(i);
//重置比对的次数
c = 0;
//只要不相等就跳过此次列的比对
break;
} else if (c == count && isFind) {
//找count次并且标志为true就算找到
break;
}
isFind = true;
// System.out.print(" ");
}
////找count次并且标志为true就算找到,不再继续
if (isFind && c == count) {
break;
}
// System.out.println();
//更新目前已比对的列数
c++;
}
//如果找到,返回初始比对的第几列
//后比对的第几列 - 已经比对的列数 = 初始比对的位置(即滑块的正确位置)
if (isFind) {
ret = index - count;
}
return ret;
}

原理:通过滑块的rgb数组与原图rgb数组进行对比。

  1.把rgb数组看成二维

  2.比对滑块rbg数组的前几列(自定义)与原图rgb数组进行循环比对

  3.只要前几列对比成功就返回初始对比列的索引

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器