iOS逆向之旅---在iPhone上开发微信自动跳一跳插件

感谢「杜泽旭」同学投稿,也欢迎广大安全逆向爱好者积极投稿,分享不仅是一种精神也是一种快乐,本文涉及到的iOS应用开发安全逆向问题可以去小密圈咨询他,包括微信,抖音等各种问题!

现在已有的实现方法基本是PC端利用Python来实现的,还得安装很多工具,使用起来非常不方便,这篇文章介绍如何在iOS上利用原生客户端实现自动跳一跳,方便随时使用

640?wx_fmt=gif&wxfrom=5&wx_lazy=1


原理

和PC端实现原理一致,先用系统API进行屏幕截图,利用OpenCV分析出棋子的位置和目标块的位置,计算出距离乘以系数后得出需要按压的时间,用FTFakeTouch模拟相应的按压事件就行了

如何进行不越狱插件开发

关于这部分,有很多相关的框架,例如IPAPatch或者MonkeyDev,这里就不在过多介绍了,可以参考相应的文章或者项目简介

1.搭建环境

本例子采用的是IPAPatch,我们先取得微信的砸壳文件(自己砸壳或者从越狱渠道下载都行),然后下载IPAPatch Demo工程,替换Assets文件夹下的app.iap为微信的iap砸壳文件,下载OpenCV代码编译为opencv2.framework添加入工程,下载FTFakeTouch工程编译成FTFakeTouch.a库添加入工程,新建WeChatJumpManager类添加入工程来作为我们实现相关功能的类,这样准备工作就完成了

2.触发方法

我们采用摇一摇的方式开启自动跳的功能,所以添加UIWindow的Category监听系统的摇一摇事件

@implementation UIWindow (Shake) -(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { if (motion == UIEventSubtypeMotionShake) { //监听到摇动事件 } } @end

3.截图

采用系统的截图方法

- (UIImage *)getCurrentScreenShot { UIWindow *screenWindow = [UIApplication sharedApplication].keyWindow; UIGraphicsBeginImageContextWithOptions(screenWindow.frame.size, NO, [UIScreen mainScreen].scale); [screenWindow drawViewHierarchyInRect:screenWindow.frame afterScreenUpdates:YES]; UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return viewImage; }UIImageToMat将UIImage转成OpenCV中使用的格式cv::Mat

4.定位棋子的位置

OpenCV的matchTemplate方法可以根据模板图片查找在对应的目标图片中的位置,正好符合我们的需求,我们先截取一个棋子的模板文件

640?wx_fmt=jpeg

放入Assert文件夹下的Resource文件夹下,初始化相应的资源文件传入,获得棋子的位置

- (CvPoint)chess_Loc:(cv::Mat)res tempImage:(cv::Mat)temp result:(cv::Mat)result { cv::matchTemplate(res, temp, result, CV_TM_SQDIFF); double minVal,maxVal; CvPoint minLoc,maxLoc,matchLoc; IplImage image = IplImage(result); cvMinMaxLoc(&image,&minVal,&maxVal,&minLoc,&maxLoc,NULL); matchLoc = minLoc; //matchLoc是最佳匹配的区域左上角点 chessRect = cvRect(matchLoc.x, matchLoc.y, temp.cols, temp.rows); //标记出棋子的位置 cv::rectangle(res, cvRect(matchLoc.x, matchLoc.y, temp.cols, temp.rows), cvScalar(225,225,0)); return cvPoint(matchLoc.x+temp.cols*0.5,matchLoc.y+temp.rows); }

这步完成我们可以运行测试下,将结果转成UIImage存入相册看下棋子的位置是够正确

640?wx_fmt=jpeg

5.获得下一步的位置

查找下一步位置的关键就是找出下一个方块的位置,我们暂且认为方块的上尖的位置就是下一个方块的位置,关键的方法是边缘检测函数Canny

  • 先用cvtColor将图片转化为灰度图

  • 边缘检测前用高斯模糊GaussianBlur处理下,方便边缘检测

  • Canny函数进行边缘检测

我们注意到由于下一步的位置距离上一个位置较近时可能会影响棋子的边缘可能会影响到下一步的位置判断,所以我们根据上一步棋子的位置将它的像素改为0

cv::rectangle(res, chessRect, cvScalar(0), -1);

由于有效的部分是图片的中间部分,所以我们只处理高度为0.25到0.6之间的部分

根据棋子的位置确定查找的范围,进行行扫描,扫描到的第一个值为255的即返回当前坐标值

实验中发现椭圆形的上尖是条直线,所以我们要获取第一行连续值是255的x值的中点

- (CvPoint)nextStep_Loc:(cv::Mat)res chessPoint:(CvPoint)point { cvtColor(res, res, CV_BGR2GRAY); cv::GaussianBlur(res,res,cvSize(3,3),0); cv::Canny(res, res, 3, 9); cv::rectangle(res, chessRect, cvScalar(0), -1); int minX = 0,maxX = 0; int x = 0,y = 0; if (point.x < res.cols/2.0) { for (int j = res.rows*0.25; j < res.rows*0.6; j++) { uchar* ptr = res.ptr<uchar>(j); for (int i = res.cols/3.0; i < res.cols; i++) { if (ptr[i] == 255) { if (minX == 0) { minX = i; } }else{ if (minX != 0 && maxX == 0) { maxX = i; x = (int)((maxX-minX)/2.0)+minX; y = j; return cvPoint(x, y); } } } } }else{ for (int j = res.rows*0.25; j < res.rows*0.6; j++) { uchar* ptr = res.ptr<uchar>(j); for (int i = 0; i < res.cols/3.0*2.0; i++) { if (ptr[i] == 255) { if (minX == 0) { minX = i; } }else{ if (minX != 0 && maxX == 0) { maxX = i; x = (int)((maxX-minX)/2.0)+minX; y = j; return cvPoint(x, y); } } } } } return cvPoint(0, 0); }

circle函数在我们计算出的位置上画个圈,也保存到相册,验证下结果

640?wx_fmt=jpeg

6.计算时间

根据上两部算出来的位置算出距离进而得出时间

- (CGFloat)timeWithImage:(UIImage *)image { @autoreleasepool { cv::Mat s; UIImageToMat(image, s); cv::Mat r = s.clone(); CvPoint p = [self chess_Loc:s tempImage:chess result:r]; CvPoint n = [self nextStep_Loc:s chessPoint:p]; s.release(); r.release(); if (n.x != 0&&n.y != 0) { double distance = [self distanceBetweenPointA:p pointB:cvPoint(n.x, n.y)]; return distance*coefficient/1000.0; }else{ return 0.3; } } }

7.操作按压

随机一个屏幕下部分的点,用FTFakeTouchlongPressAtPoint:duration:实现长按

CGFloat x = (int)(randomRect.origin.x + (arc4random() % (int)randomRect.size.width)); CGFloat y = (int)(randomRect.origin.y + (arc4random() % (int)randomRect.size.height)); [[FTFakeTouch sharedInstance] longPressAtPoint:CGPointMake(x, y) duration:time];

以上就实现了整个需求,大家可以根据自己的手机大小试验出自己的系数!


严重说明

本文的目的只有一个就是学习逆向分析技巧,如果有人利用本文技术进行非法操作带来的后果都是操作者自己承担,和本文以及本文作者没有任何关系,本文涉及到的代码可以去编码美丽小密圈自取,欢迎加入小密圈一起学习探讨技术!点击立即进入小密圈


手机查看文章不方便,可以网页看

http://www.520monkey.com



《Android开发艺术探索》作者任玉刚的公号,关注Android开发前沿、AI技术、前后端、职业发展、生活感悟、妹子图,欢迎大家关注。

640?wx_fmt=jpeg


《Android应用安全防护和逆向分析》 

360创始人周鸿祎、CSDN创始人蒋涛、看雪创始人段钢联袂推荐! 点击查看图书详情

640?wx_fmt=jpeg


编码美丽小密圈

小密圈中汇集众神分享技术,所有源码、工具、破解样本、插件都汇集在小密圈中

---点击立即进入小密圈---


天若有情天亦老,我为逆向续一秒!猛戳下方"阅读原文",开启安全逆向大门!

640

猜你喜欢

转载自blog.csdn.net/f0ed9czn4ly992g/article/details/80047189