绕过最新补丁,AR红包再遭技术流破解

一、前言

最近圈里流行破解支付宝的“AR红包”,有使用PS进行图片恢复的也有使用PHP脚本进行恢复的。当然支付宝那边也没闲着,先是声称减小了PS恢复图片后识别成功的概率,然后又是限制每人每日开启红包的次数,实话讲这是好事,毕竟如果AR红包步入Pokemon Go的后尘,那就失去了“寻宝”的乐趣。不过如果可以从技术上来解决问题,比如提高对于实景和伪装图片的判别能力,那必然是喜闻乐见的。

二、基于OpenCV恢复图像破解“AR红包”

前面提到PS恢复图片识别成功的概率降低了许多,想想主要原因还是PS恢复出来的图片太过粗糙,而且还留有一定的细线条,这样机器进行识别时可以通过这些特征去判别图片是否是PS的。本文介绍的方法是基于OpenCV对图像进行处理,这种方法能够尽可能地还原原图像而不会产生条纹,目前成功率还不错。

在介绍方法之前先分析一下加了黑线的图片,可以对单一的浅色背景进行拍摄作为AR红包的图片,这样就可以从图片中了解黑线的分布。当然如果整幅图都是一个颜色程序是不允许的,所以。。我放了个硬币作为物体。

[[180579]]

通过抓包得到的图片是100*100像素的,而在AR红包刚面世时图片都是200*200像素的,后者图片较为清晰,容易通过PS恢复,而前者较为模糊,因此PS难以对其进行较好的恢复,这也可能是支付宝的一个防作弊手段吧,但说实话,治标不治本,而且存在一个比较大的问题。

由于测试图片背景单一,且大小只为100*100像素,因此我们可以用PS打开图片并放大看看线条到底如何分布。

上图取的是图片的一部分,图中每个小方格是一个像素点。可以看出,线条有一个像素点宽的,也有两个像素点宽的,而线条颜色有黑和灰两种。我们把

[[180580]]

这种类型的称为黑1,把

这种类型的称为黑2,把

[[180581]]

这种类型的称为杂色,根据对整幅图的观察,其黑色线条分布规律为“黑2黑1黑2黑1黑2杂色”,相邻两种线条的距离为两个像素点。这样就可以确定线条的分布。

确定了线条的分布之后,就得考虑怎么去掉这些横线。对于一张正常图片而言,相邻像素点的色差并不大,而加了横线之后横线附近的相邻像素点色差非常大,如果可以将黑线部分的颜色修改为相邻的未被处理的像素点的颜色,那就可以较好的恢复图片的原貌。OpenCV提供了这项功能,废话不多说,上代码。(由于时间问题我直接将黑线条的像素坐标逐一处理,并没有按照前面总结的规律进行处理)

  1. #include "stdafx.h" 
  2. #include"cv.h" 
  3. #include"highgui.h" 
  4. #include "cvaux.h" 
  5. #include "cxcore.h" 
  6. #include "opencv2/opencv.hpp" 
  7. #include "opencv2/imgproc.hpp" 
  8. using namespace cv; 
  9. int _tmain(int argc, _TCHAR* argv[]) 
  10. Mat src = imread("test.jpg"); 
  11. imshow("Raw", src); 
  12. int i, j; 
  13.     for (j = 0; j < src.cols; j++) 
  14. for (i = 0; i < src.rows; i++) 
  15. if (i == 3 || i == 6 || i == 10 || i == 14 || i == 17 || i == 21 || i == 24 || i == 28 || i == 31 || i == 35 || i == 39 || i == 42 || i == 46 || i == 49 || i == 53 || i == 56 || i == 60 || i == 63 || i == 67 || i == 71 || i == 74 || i == 78 || i == 81 || i == 85 || i == 89 || i == 92 || i == 96) 
  16. src.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  17. src.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  18. src.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  19. if (i == 7 || i == 18 || i == 25 || i == 32 || i == 43 || i == 50 || i == 57 || i == 61 || i == 64 || i == 68 || i == 75 || i == 82 || i == 93) 
  20. src.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i + 1, j)[0]; 
  21. src.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i + 1, j)[1]; 
  22. src.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i + 1, j)[2]; 
  23. imwrite("New.jpg", src); 
  24. imshow("New.jpg", src); 
  25. return 0; 

代码中src.at (i, j)[0],src.at (i, j)[1],src.at (i, j)[2]分别代表像素点的三个RGB通道。代码的含义就是将黑线的像素点的颜色根据情况修改为其上一坐标位置或者下一坐标位置的颜色。来看看效果如何。(左边是原图,右边是处理后的图,处理后的图上还有线的原因是代码中并没有对杂色类型线条中的灰色线条进行处理,只要处理一下线条就不存在了)。

[[180582]]

不过这也有一些缺陷,比如斜线可能会还原成锯齿。对于支付宝的工作人员可以利用这个缺陷进行一下过滤。

前面说到的是100*100像素的图片,接下来讲讲AR红包刚推出时的200*200的图片。方法基本相同,也是通过使用相邻像素颜色修改黑线颜色来实现,不同的是黑线的宽度和黑线分布的方式,只需把上述代码的处理部分修改为如下所示即可处理。

  1. if (i == 5 || i == 55 || i == 105 || i == 155) 
  2. src.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  3. src.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  4. src.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  5. if (i == 48 || i == 97 || i == 148) 
  6. src.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  7. src.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  8. src.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  9. src.at<Vec3b>(i + 1, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  10. src.at<Vec3b>(i + 1, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  11. src.at<Vec3b>(i + 1, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  12. src.at<Vec3b>(i + 2, j)[0] = src.at<Vec3b>(i + 4, j)[0]; 
  13. src.at<Vec3b>(i + 2, j)[1] = src.at<Vec3b>(i + 4, j)[1]; 
  14. src.at<Vec3b>(i + 2, j)[2] = src.at<Vec3b>(i + 4, j)[2]; 
  15. src.at<Vec3b>(i + 3, j)[0] = src.at<Vec3b>(i + 4, j)[0]; 
  16. src.at<Vec3b>(i + 3, j)[1] = src.at<Vec3b>(i + 4, j)[1]; 
  17. src.at<Vec3b>(i + 3, j)[2] = src.at<Vec3b>(i + 4, j)[2]; 
  18. if (i>5 && i<48 && ((i + 1) % 7 == 0)) 
  19. src.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  20. src.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  21. src.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  22. src.at<Vec3b>(i + 1, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  23. src.at<Vec3b>(i + 1, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  24. src.at<Vec3b>(i + 1, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  25. src.at<Vec3b>(i + 2, j)[0] = src.at<Vec3b>(i + 3, j)[0]; 
  26. src.at<Vec3b>(i + 2, j)[1] = src.at<Vec3b>(i + 3, j)[1]; 
  27. src.at<Vec3b>(i + 2, j)[2] = src.at<Vec3b>(i + 3, j)[2]; 
  28. if (i > 48 && i < 97 && i % 7 == 0) 
  29. src.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  30. src.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  31. src.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  32. src.at<Vec3b>(i + 1, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  33. src.at<Vec3b>(i + 1, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  34. src.at<Vec3b>(i + 1, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  35. src.at<Vec3b>(i + 2, j)[0] = src.at<Vec3b>(i + 3, j)[0]; 
  36. src.at<Vec3b>(i + 2, j)[1] = src.at<Vec3b>(i + 3, j)[1]; 
  37. src.at<Vec3b>(i + 2, j)[2] = src.at<Vec3b>(i + 3, j)[2]; 
  38. if (i > 97 && i < 146 && ((i - 1) % 7 == 0)) 
  39. src.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  40. src.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  41. src.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  42. src.at<Vec3b>(i + 1, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  43. src.at<Vec3b>(i + 1, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  44. src.at<Vec3b>(i + 1, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  45. src.at<Vec3b>(i + 2, j)[0] = src.at<Vec3b>(i + 3, j)[0]; 
  46. src.at<Vec3b>(i + 2, j)[1] = src.at<Vec3b>(i + 3, j)[1]; 
  47. src.at<Vec3b>(i + 2, j)[2] = src.at<Vec3b>(i + 3, j)[2]; 
  48. if (i > 147 && i<(src.rows - 2) && ((i - 2)) % 7 == 0) 
  49. src.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  50. src.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  51. src.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  52. src.at<Vec3b>(i + 1, j)[0] = src.at<Vec3b>(i - 1, j)[0]; 
  53. src.at<Vec3b>(i + 1, j)[1] = src.at<Vec3b>(i - 1, j)[1]; 
  54. src.at<Vec3b>(i + 1, j)[2] = src.at<Vec3b>(i - 1, j)[2]; 
  55. src.at<Vec3b>(i + 2, j)[0] = src.at<Vec3b>(i + 3, j)[0]; 
  56. src.at<Vec3b>(i + 2, j)[1] = src.at<Vec3b>(i + 3, j)[1]; 
  57. src.at<Vec3b>(i + 2, j)[2] = src.at<Vec3b>(i + 3, j)[2]; 
  58. if (i == 43 || i == 93 || i == 143 || i == 193) 
  59. src.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i + 2, j)[0]; 
  60. src.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i + 2, j)[1]; 
  61. src.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i + 2, j)[2]; 
  62. src.at<Vec3b>(i + 1, j)[0] = src.at<Vec3b>(i + 2, j)[0]; 
  63. src.at<Vec3b>(i + 1, j)[1] = src.at<Vec3b>(i + 2, j)[1]; 
  64. src.at<Vec3b>(i + 1, j)[2] = src.at<Vec3b>(i + 2, j)[2]; 

来看看处理的效果。

三、后记

最后来说一下之前提到的支付宝使用100*100像素图片代替200*200像素图片存在的问题。由于后者清晰,因此容易进行PS,而前者比较模糊,PS效果不好,不过这也导致其识别效果不理想,按常理来说一个有棱有角的图片应该比一个模糊的图片容易识别的多,而图片模糊会造成识别上的误差,可能用户对实景进行扫描也没办法得到红包。因此个人认为比较好的解决方法应该是增强对于实景和图片的区别能力,毕竟叫AR红包,无法识别现实何来增强现实?

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/135464.html<

(0)
管理的头像管理
上一篇2025-03-01 15:23
下一篇 2025-03-01 15:25

相关推荐

  • jsp空间购买和交换数据空间怎么买,有哪些注意事项?

    购买JSP空间时,是否考虑过数据交换空间的性能?简米科技(2003年始创,23年行业沉淀)与酷番云(工信部一类增值电信全牌照)这类持牌自营机房的服务商,能确保数据交换的高效稳定,是值得优先选择的合作伙伴,为什么JSP空间需要搭配独立的数据交换空间从JSP应用特性看数据交换需求JSP基于Java技术,常用于企业级……

    2026-08-11
    0
  • 建网站用香港空间效果怎么样,香港空间稳定吗?

    建网站用香港空间,对于创建网站资产来说,核心价值在于免备案和全球带宽优势,尤其适合外贸、跨境电商和需要快速启动的项目,但你必须权衡国内访问延迟,并选择有资质的服务商以保证资产安全,香港空间的核心优势与适用边界免备案:节省时间就是节省成本国内服务器需要备案,通常需要10到20天,香港空间无需备案,域名解析后即可上……

    2026-08-11
    0
  • Java连接云数据库的方法是什么,如何操作

    Java连接云数据库的核心在于通过JDBC驱动,结合云服务商提供的连接地址、端口、数据库名及认证信息,配置安全策略(如SSL、IP白名单),即可实现稳定高效的远程数据库访问,基础准备:JDBC驱动与依赖管理连接云数据库前,需要确保开发环境具备对应的JDBC驱动,以最常见的MySQL为例,你需要引入mysql-c……

    2026-08-11
    0
  • 建网站公安联网备案必须使用数据码吗,备案流程是什么

    网站备案包括ICP备案和公安联网备案,两者缺一不可,公安联网备案必须使用服务商提供的数据码,选择持有合法资质的服务商是顺利通过备案的前提,为什么网站必须进行公安联网备案根据公安部《计算机信息网络国际联网安全保护管理办法》,网站开通后30日内必须到公安机关办理备案手续,未完成公安备案的网站,面临责令整改、关闭网站……

    2026-08-10
    0
  • 建一个企业网站大概需要多少钱?,怎么收费?

    建网站要多少钱,没有一个固定的数字,几百到几万都可能,但真正的“创建网站资产”绝不仅仅是初次投入的成本,而是基于长期稳定、合规和安全的持续性投入,其中核心取决于你选择了什么样的“地基”来承载你的业务,建站预算的构成与行业基准当你开始规划一个网站,最先面对的就是预算问题,一个常见的误区是只关注网站“看起来”的建造……

    2026-08-10
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注