开篇
首先声明此教程仅做学习交流和知识记录方便以后查看使用,如果涉及到利益相关的请告知本人进行删帖处理。
2020年 IOS 逆向 反编译 注入修改游戏或APP调用参数系列新手教程,之所有特别提出是2020年的是因为很多老的方法失效了,网络上大部分的教程都是基于2018年左右的IOS10及以下老版本来破解,而且教程新手很难看明白,当当就安装这些破解工具的环境的坑之多就足以劝退很多新手😭。本系列教程会列出破解的环境及工具版本,尽量避免新手入坑。
本人其实是对IOS领域从零开始的,都是通过看网上的博文和相关视频资料自学的,之前是搞PHP和Python等后台服务器程序的,对编程这方面是有热情和多年积累的。为什么会想搞IOS的破解,就是因为玩的一款游戏想改里面的头像,做成动态GIF的显示,游戏里正常上传图片是会被裁剪的,导致动图被剪成静态jpg;还有一个合成灯笼🏮小游戏,类似什么合成豪车,阳光养猪场那种合成游戏,我想写个脚本让它自动合成;还有修改游戏的金币啊、分数啊。就是觉得好玩~😂,OK,我这种学习过程是结果来驱动过程的,先把大的理念想好,接下来就是瀑布流一样的把所需要的知识点逐一分解,碰到哪里不懂就学哪里,最终实现我要的效果!并且学到了很多知识,对各类APP的修改也就得心应手了。其实编程的乐趣就是在于最终结果如愿以偿后的那种成就感。
感觉我把很多语言和工具都折腾过了~,后端、前端、手机端、游戏、都涉猎了。这些年接触很多语言,从开始C 、C++、Java、PHP、易语言、Python、还有很多web的js等组件、shell脚本、还有linux和kali等操作系统的黑客工具,折腾过各种工具、到最近学习的IOS objective-c等,接触多了,实际上语言只是实现的工具,语言的思路是一样的,就是数据结构+算法,不同语言只是语法的不同,写得好的软件是要用到设计模式的。学编程应该了解一下。计算机真是博大,0与1就衍生出这么多形式的计算机世界,就好比道生一一生二二生三三生万物一样,世界也如此,万物归根结底其实都是一,或者说是"道",抱歉,老子的道家书看多了😁。编译是从高级语言翻译成汇编、然后汇编又翻译成机器语言、机器只知道1和0,所有语言最终都会被转换成1和0被机器识别执行。当然这是对现代计算机的说法,未来量子计算机应该会改变这种0和1的传统模式吧。反编译就是从机器代码中转换成汇编再把汇编翻译成伪代码,通过伪代码一般能读懂七七八八以此来进行破解。
本人想通过这些博客记录自己这两周内折腾的过程以及分享最后成功的成果。另外想结交志同道合对IT行业感兴趣的盆友,互相交流学习。可以通过博客联系我或加QQ号:1321691245
需求&最终效果
对于从来没开发过IOS程序的我要怎么搞?从何学起?
首先先讲我上面提到的第二个我要实现的需求,让灯笼自动合成。其他需求我会新写文章来分享,大家可以关注或加我联系方式。
下图是某游戏的合成灯笼界面,通过拖拽把相同的灯笼合成更高一级的灯笼。我想用脚本来自动合成,完全自动化。
下图是实现后的效果
通过脚本大大提高合成速度!
其实这里并不是用到反编译和逆向的知识,只是用了按键精灵写了模拟合成的脚本,本篇文章就先讲按键精灵的使用吧,反编译的其他知识后面我会逐一分享,因为这个按键精灵也是我这段时间折腾的一部分。
进入正题
折腾吧😂
环境要求与即将使用的工具
环境 | 版本 |
---|---|
操作系统 | 本人的mac是双系统(MacOSX和win7),按键精灵脚本需要在windows开发 |
按键精灵手机助手 for windows | 3.5.2 |
按键精灵IOS版 | 1.5.2 |
手机系统 | Iphone7 IOS11 需要越狱 |
思路
一开始我的做法:
怎么让脚本知道是两个相同的灯笼,然后又怎么模拟灯笼拖拽去合并?我想到了按键精灵,早起用过电脑版的用来辅助游戏,想不到现在有手机版的了!所以想看看怎么弄,我基本也是从零学起的。了解按键精灵IOS版 可以模拟我们人手的任何触摸指令,我就有信心做这个合成判断了,按键精灵的代码是MQ语言,有相关手册大家可以去看。
思路是把12个灯笼区域分割成12个区域,坐标存放在数组中,然后拿每一个灯笼来和第一个灯笼比较特征,特征相同就触发模拟拖拽合并。
另一种做法:用冒泡算法不判断色点,简单粗暴每个格子都移动合并,不管是不是相同灯笼,没想到效率更高!代码更简单效率更快!
实现代码
这里只列出核心代码,具体代码见:github
ShowMessage "启动脚本。。。。。"
// 横屏
//x
//|__ y
Dim offsetX = 260
Dim offsetY = 292
Dim CloseXPoint = array(988,2010)
// 3 个特征点 array(y, x)
Dim point1 = array(876, 760)
Dim point2 = array(833,777)
Dim point3 = array(894,757)
// 第一个灯笼的特征
Dim firstDengLong = array(array(point1(0), point1(1), GetPixelColor(point1(0), point1(1))), array(point2(0), point2(1), GetPixelColor(point2(0), point2(1))), array(point3(0), point3(1), GetPixelColor(point3(0), point3(1))) )
Dim dengLongArr = array()
Dim i=0,count=0
// 所有灯笼的比较坐标点,12个 [[[5,3],[3,1]] , [[5,3],[3,1]]]
// 12 次循环
For i = 0 To 2
dim j = 0
For j = 0 To 3
dengLongArr(count) = array()
// 类似 dengLongArr[count][0]
dengLongArr(count, 0) = Array(firstDengLong(0, 0) - i * offsetX, firstDengLong(0, 1) + j * offsetY)
dengLongArr(count, 1) = Array(firstDengLong(1, 0) - i * offsetX, firstDengLong(1, 1) + j * offsetY)
dengLongArr(count, 2) = Array(firstDengLong(2, 0) - i * offsetX, firstDengLong(2, 1) + j * offsetY)
count = count + 1
Next
Next
// 合并灯笼
Function heBingDengLong()
i = 0
j = 0
// 第一个灯笼的特征
Dim firstDengLong = array(array(point1(0), point1(1), GetPixelColor(point1(0), point1(1))), array(point2(0), point2(1), GetPixelColor(point2(0), point2(1))), array(point3(0), point3(1), GetPixelColor(point3(0), point3(1))) )
Dim currDengLongColorArr = array()
// 11 次循环
For i = 0 To 11
currDengLongColorArr = array( GetPixelColor(dengLongArr(i,0,0), dengLongArr(i,0,1)), GetPixelColor(dengLongArr(i,1,0), dengLongArr(i,1,1)), GetPixelColor(dengLongArr(i,2,0), dengLongArr(i,2,1)))
For j = 1 To 11
closeX ()
closeComm()
TracePrint "这一点"
dim str = dengLongArr(j,0,0)&"|"& dengLongArr(j,0,1) & "|" & currDengLongColorArr(0) & "-101010," & dengLongArr(j,1,0)&"|"& dengLongArr(j,1,1) & "|" & currDengLongColorArr(1) & "-101010," & dengLongArr(j,2,0)&"|"& dengLongArr(j,2,1) & "|" & currDengLongColorArr(2) & "-101010"
If Not(i = j) and CmpColorEx(str, 0.9 ) = 1 Then
TracePrint str & "找到没有" & i+1 & "->" & j+1
// 合并灯笼
heBingDengLongTouch (dengLongArr(i,0,0), dengLongArr(i,0,1), dengLongArr(j,0,0), dengLongArr(j,0,1))
//EndScript
//Exit For
Else
//TracePrint 0
End If
Next
Next
End Function
Function hebingDengLong2()
i = 0
j = 0
Dim temp
// 11 次循环
For i = 0 To 10
closeX ()
closeComm()
temp = i
For j = 0 To 10
heBingDengLongTouch (dengLongArr(temp,0,0), dengLongArr(temp,0,1), dengLongArr(j,0,0), dengLongArr(j,0,1))
temp = j
Next
Next
End Function
// 移动指定灯笼到第一位置
Function moveToFirst(number)
TracePrint "----------------------------" & number
TouchDown dengLongArr(number-1,0,0),dengLongArr(number-1,0,1), 1//按住屏幕上的100,100坐标不放,并设置此触点ID=1
TouchMove firstDengLong(0,0),firstDengLong(0,1), 1//将ID=2的触点花200毫秒移动至500,500坐标
TouchUp 1//松开弹起ID=1的触点
// TracePrint "移动力"
End Function
// 拖拽合并
Function heBingDengLongTouch(x1, y1, x2, y2)
TracePrint "----------------------------"
TouchDown x1,y1, 1//按住屏幕上的100,100坐标不放,并设置此触点ID=1
TouchMove x2, y2, 1//将ID=1的触点花200毫秒移动至500,500坐标
TouchUp 1//松开弹起ID=1的触点
End Function
// 关
Function closeX()
// 免费升级的点击
//各种弹层的关闭处理
End Function
Function closeComm()
// 也是各种弹层的关闭处理
End Function
Function isInGameWindow()
// 是否在游戏窗口的判断
End Function
// 广告处理
Function adProcc()
// 各种广告处理。。。。
TracePrint "开始广告处理................"
// 存在倒计时形式的x按钮
// 误入横版的app store 显示页面
End Function
// 脚本主函数
Function heBingDengLongMain()
For ii = 1 To 12
closeX ()
closeComm()
If hasShadowWindow() = False Then
// 原始的判断逻辑,效率低
hebingDengLong()
// 如果想用第二种合并处理逻辑的话,上面的For可以去掉,下面的moveToFirst()也要去掉
//hebingDengLong2()
moveToFirst (ii)
Else
TracePrint "不合并"
End If
Next
End Function
If isInGameWindow() = False Then
TracePrint "不在游戏界面"
ShowMessage "不在游戏界面"
Delay 2000
adProcc()
Else
heBingDengLongMain()
End If
首先我用按键精灵窗口里面的抓抓功能取点,取第一张图片中第一个灯笼“SKR”的特征,我采用三个色点来作为一个灯笼的特征。
第一个单元的3 个特征点坐标:
Dim point1 = array(876, 760)
Dim point2 = array(833,777)
Dim point3 = array(894,757)
然后
Dim offsetX = 260
Dim offsetY = 292
指的是12个格子单元的横纵距离,也叫格子与格子之间的偏移量吧,这个是根据屏幕分辨率来算的,大屏小屏的手机是不同的,我这个脚本没有做到适应多屏幕兼容,按键精灵有自动兼容多分辨率的函数,我就没实现了,是用的iphone7 Pro 的1920×108的分辨率,换个手机就不准了哦。这里主要讲思路。
firstDengLong是指第一灯笼的特征。
然后下面有一个嵌套For循环,就是通过偏移量算出12个格子的坐标点,用来比色的点。放在dengLongArr数组里面。
然后翻代码看最底部。
isInGameWindow()是判断当前窗口是否在游戏界面,先讲是的情况,会进入到heBingDengLongMain()就是合并灯笼的主主函数。首先执行closeX ()和 closeComm()是为了关闭游戏界面的离线收益遮罩层,因为经常会弹出翻倍和升级提示的窗口,不关闭触摸就失效了。总之人的操作是什么顺序逻辑的,脚本也是根据各种情况来做判断的。然后进入具体合并逻辑hebingDengLong(),通过数组的遍历,逐个拿出来和第一个灯笼的特征比较,如果特征一样证明是相同级别的灯笼可以合并,
模拟拖拽的代码就在heBingDengLongTouch()里面,知道源坐标点和目的坐标点就能实现拖拽啦。核心就是每一个灯笼来和第一灯笼比较。合并后再在heBingDengLongMain()里面有一个
moveToFirst (ii)的操作,就是保证每个灯笼有机会移动至第一个格子,有被拿来比较的机会。
虽然是实现了,但是效率太低,后面我用了另外的代码实现,不需要比较特征,简单粗暴高效的做法,不判断是否相同灯笼,直接每每合并得了,反而更快!代码在hebingDengLong2()方法里面。类似冒泡算法。
不再游戏窗口的情况时就判断是否在看广告的界面的处理,经常会误点击到广告,或者某些升级灯笼的弹窗需要来看广告提高进度,是一种判断策略吧,某些广告看了收益高某些广告弹窗就直接close X掉。
然后广告处理部分也是抓取关闭按钮特征来判断,具体代码见github。
额外
shell 定时任务
其实上面的动图之所有每格几秒都有离线收益拿是因为我利用了游戏的一个bug实现的,这里我就不透漏bug了,我手机里面运行着shell的定时任务的脚本才能每隔几秒就收获离线收益。这里我分享一下IOS手机里面怎么使用定时任务吧。
linux的定时任务是通过crontab来配置的,而ios是通过LaunchDaemons来实现的。配置文件写在/Library/LaunchDaemons/下面。
比如我的配置文件(com.apple.mycrontest.plist)这样定义
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.apple.mycrontest.plist</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/var/root/myshelltest.sh</string>
</array>
<key>StartInterval</key>
<integer>1</integer>
</dict>
</plist>
以上配置文件指出每隔10秒执行一次/var/root/myshelltest.sh脚本。至于shell脚本里面写了啥我就不说了,是实现离线收益的方式。
打开手机terminal命令行软件,没有的话去cydia搜索相关资源下载。
然后启动配置文件命令如下:
launchctl load /Library/LaunchDaemons/com.apple.mycrontest.plist
需要root权限。
就会定时执行/var/root/myshelltest.sh啦
如果想关闭定时任务则:
launchctl unload /Library/LaunchDaemons/com.apple.mycrontest.plist
通过shell脚本和按键精灵脚本,实现了自动离线收益和自动合并灯笼的需求!😁
这是本人第一次写按键精灵脚本,没想到折腾一番还能搞出点花样~因为有了这一次成果,我才有更大的需求,想改游戏逻辑,这就需要用到逆向和IOS开发的知识了,致使我一步步折腾并入坑.........
结束
此教程仅做学习交流和知识记录方便以后查看使用,如果涉及到利益相关的请告知本人进行删帖处理。
本人想通过这些博客记录自己这两周内折腾的过程以及分享最后成功的成果。另外想结交志同道合对IT行业感兴趣的盆友,互相交流学习。可以通过博客联系我或加QQ号:1321691245
今天就先写到这,后面我再把我学习的其他相关知识分享给大家。下一篇就介绍bfinject进行脱壳打包和注入dycript的相关知识吧。
博文主索引目录入口
我会把这系列的文章更新到这个入口里面,分享我的心得,大家互相学习。
2020年 IOS 逆向 反编译 注入修改游戏或APP的调用参数新手系列教程主目录入口