您的位置:首页 > 其它

支付宝VR红包简陋破解方法。(红包图片处理)

2016-12-25 20:54 489 查看

临近新年,支付宝今年又出了新花样——VR红包。

大概玩法是,用户根据红包地图指引,走到红白位置,然后根据藏红包的具体地点图片扫描该地点便可打开红包。根据这种玩法,想要获取陌生人的红包难度可想而知,并且很多发红包者定的详细地点在其家中,这种红包根本无法获取。事实是不是这样呢?下面就介绍一种方法,可以破解部分附近的红包,该方法亲测可破解至少50%的红包。

首先说下劳动成果,VR红包每日领取上限是10个,小区附近的几个红包还未领完就到上限了,大概收获了20多块。



分析

我们根据红包的打开条件可知要打开VR红包需要两个技术:定位、图像识别。

定位来说,目前VR红包定位并不苛刻,是一个较大的范围,所以不用做考虑。

图像识别,这是红包打开的方式,也是突破点,我们要处理的也就是这一块。

下面是一张VR红包扫描界面的截图,方框显示的是详细地点,而实际场景需与图片中的地点是同一个,红包才可打开,采用的是图像识别技术。所以我们是不是可以直接扫描该截屏中的图片呢?

No,No,No,支付宝为了避免这种状况,所以加了条纹干扰,我们要做的就是讲这种干扰降到最低,让图片可以被识别。

处理前:



处理后:



限于本人技术有限,处理得不算太好,但是也勉强可识别了,下面就给出Java版本的处理方法。

处理思路

大概思路是依次读取像素点,根据像素点的RGB值判断是否为干扰线,是干扰线则进行一些处理。

1、我们看到,详细地点图片是内嵌在整个截图中的,所以我们需要首先把图片扣取出来。用到了BufferedImage的getSubimage方法。

public BufferedImage getCutImage(int x,int y,int w,int h) {
return bufImg.getSubimage(x,y,w,h);
}


2、判断黑色干扰线,判断干扰线有很多种方法,下面是大概的一种实现思路,读取到图片一行的像素点后,根据该行像素点rgb值得最大值与最小值之差判断,差值较小,则可大概判断该行在干扰线上。

public boolean isBlackLine(BufferedImage bi,int y) {
int min = 1000000000;
int max = -1000000000;
for(int x = bi.getMinX(),width = bi.getWidth();x < width; ++x) {
int pixel = bi.getRGB(x,y);
if(pixel > max) {
max = pixel;
}
if(pixel < min) {
min = pixel;
}
}
return max - min > 9000000 ? false : true;
}


3、处理,大概思路为找到干扰线后,获取到干扰线上方和下放非干扰线的首行像素点的rgb值,干扰线中的rgb值用干扰线上方值渐进到下方值代替,便可大概起到去除干扰线的效果。

下面贴出整个程序完整代码:

package test;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class PacketImage {

private BufferedImage bufImg;

public PacketImage(String path) {
try {
bufImg = ImageIO.read(new File(path));
} catch (IOException e) {
e.printStackTrace();
}
}

public void setImage(String path) {
try {
bufImg = ImageIO.read(new File(path));
} catch (IOException e) {
e.printStackTrace();
}
}

public BufferedImage getCutImage(int x,int y,int w,int h) { return bufImg.getSubimage(x,y,w,h); }

public BufferedImage getResult(int xx,int yy,int width,int height) {
BufferedImage cutImg = getCutImage(xx, yy, width, height);
int creY = 0;
boolean havaBlackLine = false;
for (int y = 0; y < height; y++) {
if(y < height - 1 && !isBlackLine(cutImg,y) && isBlackLine(cutImg,y + 1)) {
havaBlackLine = true;
continue;
}
if(havaBlackLine) {
creY++;
}
if(y == height - 1) {
break;
}
if(isBlackLine(cutImg,y) && !isBlackLine(cutImg,y + 1)) {
if(creY == 0) {
continue;
}
int startY = y - creY;
int endY = y + 2;
for(int x = 0;x < width;x++) {
int startRGB = cutImg.getRGB(x,startY);
int endRGB = cutImg.getRGB(x,endY);
int creR = (getR(endRGB) - getR(startRGB)) / creY;
int creG = (getG(endRGB) - getG(startRGB)) / creY;
int creB = (getB(endRGB) - getB(startRGB)) / creY;
for(int i = startY + 1,cr = 0;i < endY;i++,cr++) {
int subRGB = new Color(getR(startRGB) + cr * creR,
getG(startRGB) + cr * creG,
getB(startRGB) + cr * creB).getRGB();
cutImg.setRGB(x,i,subRGB);
}
}
havaBlackLine = false;
creY = 0;
}
}
return cutImg;
}

public boolean isBlackLine(BufferedImage bi,int y) { int min = 1000000000; int max = -1000000000; for(int x = bi.getMinX(),width = bi.getWidth();x < width; ++x) { int pixel = bi.getRGB(x,y); if(pixel > max) { max = pixel; } if(pixel < min) { min = pixel; } } return max - min > 9000000 ? false : true; }

private int getR(int rgb) {
return (rgb & 0xff0000) >> 16;
}

private int getG(int rgb) {
return (rgb & 0xff00) >> 8;
}

private int getB(int rgb) {
return rgb & 0xff;
}

public static void main(String[] args) {
try {
ImageIO.write(new PacketImage("C:\\222.PNG")
.getResult(220,715, 280, 280), "png", new File("C:\\111.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
}


好了,处理后的图片获取到了,用手机扫一扫领红包吧。

不可能只领住所附近的红包吧,所以想领别的地方的红包怎么办呢?

背着电脑去,太麻烦。下篇将会在此方法的基础上开发Android版本处理,就可以带着初级出去寻宝啦。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息