【Arcaea/逆向记录合集】壳子额外修改详细教程

阅前说明:本文所写内容已经根本触犯了Lowiro Limited的核心利益,内容仅供学习交流,作者对于读者所做的任何行为概不负责,如果跟着本文所写内容操作,您需要对自己的行为导致的任何后果负责!
*本文不提供文中的逆向后资源,逆向前资源,逆向工具。
*不提供完整的,所有架构,所有版本的修改。
*对于普通的修改打包、如何改写指令这种基础操作,概不赘述。
*本人没有苹果公司推出的任何系统的设备,因此文中通篇使用安卓设备。
*对于三件套Hash校验、离线Beyond限制破解等,概不提供,请移步至其他文章。
使用架构:arm64-v8a/armeabi-v7a(均支持arm64-v8a)
IDA版本:7.0(建议附带Keypatch插件使用)
APK版本:不限(不保持最新版本更新,4.1.9的修改情况也适用于4.2大版本系列)
对于4.1.9,且使用架构为arm64-v8a的读者们,推荐配合@xingjiFIUG编写的安卓版arcaea 4.1.9自制逆向详细教程进行修改

排版很乱,原谅我吧orz
——目录:
——1.流速上限
——2.曲包锁
——3.三星PTT边框颜色
——4.背景解锁
——5.Beyond章节无条件解锁
——6.残片上限
——7.残片购买体力不减
——8.世界模式相关物品解锁
——9.修改EARLY & LATE的颜色
——10.修改Arc & 黑线的颜色
——11.修改光的离线技能
——12.风暴解锁挑战通过数量修改
——13.World Extend分类限制破解 & 整包下载

*流速上限*
-4.0.255之前/armeabi-v7a/3.5.3c-
打开Strings窗口,搜索HighspeedSettingLayer.csb,双击进入
进入到对应汇编位置后,按Tab查看伪代码
往上查看,看到HIDWORD(**) = 65,选中,按Tab返回汇编页面
对应汇编指令是MOVEQ,将后面的数值改为你想要的最高速

继续按Tab转回伪代码,看向上方的LODWORD,双击进后面=的函数
进入后按Tab返回汇编,找到IT HI和MOVHI,将两条汇编指令改为NOP即可



-4.0.255之前/arm64-v8a/3.5.3c-
打开Search - Immediate value,勾选Find all occurrence,输入0x41搜索
搜索完毕后,在Occurrence of value界面输入MOV,主要找后面为W9的指令
进去一个一个看汇编,一定会有两个MOV,一个SUBS,以及一个CMP


我们逐步解析各个数字的含义:
第一个MOV的0x41=最高速(可以为0)
第二个MOV的0xA=最低速(可以为0,不清楚副作用)
SUBS的0xB=减数(可以为0,不过会出现流速锁定为0的问题)
CMP的0x35=最高速-减数
减数最好不要太小,最低速也最好不要设为10以下,避免问题出现
我们只需要在每个有上述相同指令的函数内修改好对应数字即可

然后回到Strings窗口,搜索highspeed_setting_layer,进入第一个xref
按Tab查看伪代码,下翻找到>=11,将最低速+1,然后修改
再xref一下11前面的v5,找到>10,改成最低速即可完成
小知识:理论上64位最高速能改为429496729.5,但是因为CMP的限制导致最高速只能为409.6,最低速受最高速影响,虽然也能设置成429496729.5,但是会出现bug

-4.0.255开始/arm64-v8a/4.1.9-
打开Search - Immediate value,勾选Find all occurrence,输入0x41搜索
搜索完毕后,在Occurrence of value界面输入MOV,主要找后面为W10的指令
进去一个一个看汇编,一定会有两个MOV,一个SUB,以及两个CMP


我们逐步解析各个数字的含义:
第一个MOV的0xA=最低速(可以为0)
第二个MOV的0x41=最高速(可以为0)
SUB的0xB=减数(可以为0)
第一个CMP的0xA:最低速(可以为0)
第二个CMP的0x35=最高速-减数
我们只需要在每个有上述相同指令的函数内修改好对应数字即可

然后回到Strings窗口,搜索Control the speed at\nwhich notes approach,进入汇编页面
右键,选择Graph View(如果不能切换,就打开Options- General的Graph,修改Max number of nodes),划到下面第一个CBZ
看上面的MOV,W9改成最高速,W7改成最低速即可


*曲包锁*
-armeabi-v7a/3.5.3c-
打开Strings窗口,搜索lock_icon,双击进入
按Tab查看伪代码,看到下面的if ( v20 || Pack::isExtendPack ),xref一下v20

Xref到上方后,双击进入该函数,进入伪代码,移动到最底下

看到此处result = 0,按下Tab查看对应汇编指令,将MOVS改为#1即可

-arm64-v8a/3.5.3c-
打开Strings窗口,搜索lock_icon,双击进入
按Tab查看伪代码,看到下面的if ( v19 & 1 ),xref一下v19(不要xref下面为operator delete的v155)

Xref到上方后,双击进入该函数,进入伪代码,移动到最底下

对着result xref,找到result = 0LL,双击跳转

看到此处result = 0LL,按下Tab查看对应汇编指令,将MOV改为#1即可
注:在大约4.1左右的版本,616修改了这里指向的函数,在这之前如果破解此项就会一并解锁单曲和曲包及曲包内的曲目,从这开始就只能破解曲包图片的锁标,其他所有均为锁定状态,需要另找函数修改

-arm64-v8a/4.1.9-
打开Strings窗口,搜索lock_icon,双击进入
按Tab查看伪代码,看到下面的if ( v67 & 1 ),xref一下v67,再xref对应的v63(不要xref下面为operator delete的v223)
注:如果这里没有这种xref到相关函数的(4.0.256),直接在PackSelectCell.csb至packImage这范围寻找函数,再双击进入


Xref到上方后,双击进入该函数,进入伪代码,移动到最底下

对着v4 xref,尽可能把你能看到的v4 = 0或者其他结果的汇编指令改为1

将用红框圈起来的v4 xref处的指令全部改为MOV W10, #1即可
(强烈建议arm64-v8a的读者使用4.2.0或以上版本破解,将下方提到的"世界模式相关物品"破解,在packlist给对应曲包加上"is_extend_pack": true可以绕过歌曲无法游玩的限制)

*三星PTT边框颜色*
-armeabi-v7a/4.0.1c-
-arm64-v8a/4.1.9-
打开Strings窗口,搜索rating_7.png,双击进入
按Tab查看伪代码,看到下面一行的104LL、9LL,52LL和255LL

这就是达到三星条件后的ptt边框颜色,往上翻到rating_off.png

这就是普通ptt边框颜色了,改为与三星一样的Hex值即可

*背景解锁*
-armeabi-v7a/3.5.3c & 4.0.255(c)-
-arm64-v8a/3.5.3c & 4.1.9-
切换至3.5.3c版本,打开Functions窗口,搜索SceneryManager::isUnlocked,双击进入Segment为.text的函数
按Tab查看伪代码,划到最底端,往上翻找到v14,Xref一下,看到v14 = 0,按Tab查看汇编指令,把对应MOV改为#1


打开4.1.9版本,并且切换回3.5.3c版本,回到刚才的函数底端
锁定一个函数目标,我们锁定函数底端的PurchaseManager::isWorldUnlocked,xref
选择SongSelectScene::promptNonExtendWorldLocked作为目标,查找里面的字符串
通过汇编寻找,锁定This song is available by progressing through World Mode.这个字符串


切换4.1.9版本,进入Strings窗口,查找上方的字符串,双击进入
跟3.5.3c伪代码对比,PurchaseManager::isWorldUnlocked在3.5.3c的函数开头,切换回4.1.9看函数开头
简单寻找一下,锁定到sub_E9ABC0就是PurchaseManager::isWorldUnlocked,我们就可以Xref一个一个找函数
打开3.5.3c版本的SceneryManager::isUnlocked,根据PurchaseManager::isWorldUnlocked的位置和函数总体进行对比

最后我们锁定到sub_61A344就是对应的Scenery解锁函数
进入汇编修改对应的MOV即可(修改中段的MOV W23即可)

*Beyond章节无条件解锁*
-arm64-v8a/3.5.3c & 4.1.9-
打开Search - Immediate value,勾选Find all occurrence,输入0x383搜索
搜索完毕后,在Occurrence of value界面输入CMP,双击进入

-3.5.3c-
按Tab查看伪代码,找到return 0LL,按Tab查看汇编
找到对应的MOV,改为#1即可

-4.1.9-
看到CMP下面的B.GT,打开Edit - Patch Program - Change byte
找到开头的EC 00 00 54,改为07 00 00 14即可

*残片上限*
-arm64-v8a/3.5.3c & 4.1.9-
打开Search - Immediate value,勾选Find all occurrence

-3.5.3c-
输入0x270F搜索,搜索完毕后,在Occurrence of value界面输入MOV,看W9的指令
一个一个看伪代码,知道看到if ( v1 >= 9999 ),下面的v1 = 9999时,选中9999,按Tab查看汇编
修改对应MOV的#0x270F即可

-4.1.9-
输入0x752D搜索,搜索完毕后,在Occurrence of value界面输入MOV,看W10的指令
一个一个看伪代码,知道看到if ( v1 >= 29997 ),下面的v1 = 29997时,选中29997,按Tab查看汇编
修改对应MOV的#0x752D即可

*残片购买体力不减*
-arm64-v8a/3.5.3c & 4.1.9-
-3.5.3c-
打开Strings窗口,搜索Stamina Refilled,双击进入
按Tab查看伪代码,看到上方的三个1000,选中,按Tab查看汇编
看到MOV/CMP/SUB,将#0x3E8修改为#0即可

-4.1.9-
打开Search - Immediate value,勾选Find all occurrence,输入0x3E8搜索
找到对应的MOV(W9)/CMP(W8)/SUB(双W8),双击进入
找到对应的汇编指令,将#0x3E8修改为#0即可

*世界模式相关物品解锁*(破解这个也可以一并解锁背景)
-arm64-v8a/3.5.3c & 4.1.9-
-3.5.3c-
打开Functions窗口,搜索PurchaseManager::isWorldUnlocked,双击进入Segment为.text的函数
划到最底端,找到result = 0LL,按Tab查看汇编,把对应MOV改为#1即可


-4.1.9-
根据上文背景解锁的寻找方案,找到对应函数
划到最底端,找到return result,选中result xref
看到result = 0LL,双击跳转,按Tab查看汇编,把对应MOV改为#1即可


*修改EARLY & LATE的颜色*
-arm64-v8a/3.5.3c & 4.1.9-
打开Strings窗口,搜索EARLY或LATE,找到全大写的字符串,双击进入
按Tab查看伪代码

-3.5.3c-
往上看可以发现对应的Hex RGBA值

cocos2d::Color4B::Color4B中的透明度(170u)是双方通用的,更改这个会一起把双方的透明度更改(如果发现有负数,选中 右键Invert Sign)
其余三项根据v6的值判断填入的数,然后分别填入v35(R),v36(G)和v37(B)
修改对应的Hex RGBA值即可(将你想要的RGBA值拆成4部分,分别转换成十六进制填入。至于透明度以0~255的范围填入,例如128就是50%透明度)

-4.1.9-
往上看可以发现对应的Hex RGBA值

与3.5.3c不同的是,这次透明度能分情况自定义了
根据v5的值判断应用哪个RGBA值
修改对应的Hex RGBA值即可(将你想要的RGBA值拆成4部分,分别转换成十六进制填入。至于透明度以0~255的范围填入,例如128就是50%透明度)

*修改四种难度的颜色*
(参考Negative_3Uです的Arcaea自制:关于3.12.6版本iOS自制壳子修改)
-arm64-v8a/3.5.3c & 4.1.9-
打开Strings窗口,搜索maxComboCountLabel,双击进入

-3.5.3c-

从上到下,分别对应:Beyond、Future、Present,Past
只需要修改对应的Hex RGB值即可

-4.1.9-

sub_795610就是难度颜色的函数,双击进入
进入后依旧是从上到下,对应Beyond、Future、Present,Past
只需要修改对应的Hex RGB值即可

*修改Arc & 黑线的颜色*
(参考Negative_3Uです的Arcaea自制:关于3.12.6版本iOS自制壳子修改)
-arm64-v8a/3.5.3c & 4.1.9-
-3.5.3c-
打开Functions窗口,搜索LogicColor::init,双击进入Segment为.text的函数

这就是正常模式时的Arc颜色了,我们只需要修改里面的RGB值即可
case 2:绿 case 1:红 case 0:蓝

打开Strings窗口,搜索img/height_indicator.png,双击进入
按Tab查看伪代码

在下面的if ( v8 != 1 )前面,是色盲模式下的Arc颜色
我们只需要修改里面的RGB值即可

在色盲模式的Arc颜色下面,连接的是营养丰富模式下的Arc & 黑线颜色
我们只需要修改里面的RGB值即可
在函数开头还有一串if ( v8 == 1 ),然后下面接着一些RGB值,暂时还不知是什么

初步判断为黑线,我们只需要修改里面的RGB值即可

-4.1.9-
先找到cocos2d::Color3B::Color3B,不过我们要找对格式
不过我们能利用上面刚讲完的修改四种难度的颜色里面的函数来找
就在函数底部我们就能找到

我们就能通过这里来xref,寻找LogicColor::init
首先先切回3.5.3c版本,我们可以看到LogicColor::init这个函数里面调用了cocos2d::Color3B::Color3B这个函数四次,我们就能在那一大坨xref里用排除法
我们只需要看在一个函数里面发现了四次或以上的xref就能找到了
经过寻找,sub_E65A90就是我们要找的函数了
我们只需要修改里面的RGB值即可

打开Strings窗口,搜索img/height_indicator.png,双击进入
按Tab查看伪代码,划到最上方
往下找if ( v9 == 1 )

从这里开始往下找,就是一一对应的各种模式下各物件的RGB值了



*修改曲包分类竖条位置*
-arm64-v8a/3.5.3c & 4.1.9-
打开Strings窗口,搜索img/divider_free.png,双击进入
按Tab查看伪代码

-3.5.3c-
看到上方的if句段,后面的v19 = 11和v19 = 7,前者对应联动曲包竖条,后者对应支线曲包竖条
再看到下方的v19 = 2/7/11这些if条件,里面对应的就是竖条前有多少个曲包,改CMP大数字即可
支线和联动曲包竖条修改对应条件数字之后,还需要把上述提到的v19 = 11以及v19 = 7改成一样的数字


故事曲包竖条虽然能更改其条件,但是会出bug(仅实测4.1.9),在不使用下面的方法的情况下保持原样
免费曲包竖条由于使用CBNZ进行判断,无法更改,倒是能使其消失(见下方↓)

回到divider_free.png上方的if句段,对着旁边的数按Tab查看汇编
将TST改为CMP W20, #[故事曲包竖条前置曲包数]
至于上方的MOV和MOVK直接NOP即可
这样就可以让免费曲包竖条消失,并且能自定义故事曲包竖条的位置了

-4.1.9-
由于4.0.255更新了Silent Answer这个曲包,曲包竖条跟以往有分不同情况
注:该部分所有图片都已经人为修改过,请不要混淆至原版情况


可以看到支线故事和联动曲包竖条不再是直接给出指定数字了,而是使用了v242和v241的值进行控制
对其xref,可以发现这两个值分别对v10进行了加法(ADD),再xref一下v10,除了这两处加法,还有三处xref
先看第一和第二个xref处,有一个if句段控制了v10的值

此处主要看else前的数,else后面的v10 = 2是上方的v10 = 1后的数+1
不难发现,此处应该是控制epilogue包是否存在时的情况
不存在则使用上方的数,而存在则使用下方的数
再来看看第三处xref

疑似没什么用,不过数值建议改成上两处对应的值
除了这个改动之外,favorite的分割符也被丢进来了,感兴趣自己改改

免费曲包竖条依旧使用CBNZ判断,无法更改
让其消失并且控制故事曲包竖条:参考上方3.5.3c的方法,作用是一样的,不过MOVK要改成LDR W8, [SP,#0x420+var_368]

*修改光的离线技能*
-arm64-v8a/3.5.3c & 4.1.9-
打开Strings窗口,搜索img/empty.png,双击进入

-3.5.3c-
往下翻一下,会看见这样一个汇编

MOV W1~W6分别对应不同的技能附加,可以叠加修改
如果技能要用替换函数的话,找到对应方案替换即可(353有点麻烦我就不写了)

-4.1.9-
往上翻,会看见这样一个汇编

结构比3.5.3c精简了不少,MOV W1~W6分别对应不同的技能附加,可以叠加修改
如果技能要用替换函数的话,找到MOV W5后面的BL,替换跳转函数即可
建议把格式也改为对应函数的格式,以免BUG

*风暴解锁挑战通过数量修改*
-arm64-v8a/3.5.3c & 4.1.9-
打开Strings窗口,搜索continue_line.png,xref
找上方有一处判断某个值是否为4的if句段的xref

-3.5.3c-

更改v203的4即可

-4.1.9-

更改HIDWORD(v154)的4即可

*World Extend分类限制破解 & 整包下载*
-arm64-v8a/3.5.3c-
打开Strings窗口,搜索extend,xref
在xref的函数里找SongListLayer::getGroupsForSonglist、SongSelectScene::showSongSelect、SongListLayer::updateSongList,Song::isRemoteDownloadPresent和SongSelectScene::promptDownload,分别双击进入
在SongListLayer::getGroupsForSonglist里面,把CBNZ W0, loc_6B8B90改成B loc_6B8B90,这样我们就解决了固定分类为日期的问题
切换到SongSelectScene::showSongSelect里面,在汇编里面找到CBNZ W0, loc_56E580,改为B loc_56E580,这样我们就解决了默认不显示分类按钮的问题
切换到SongListLayer::updateSongList里面,在汇编里面找到CBNZ W0, loc_6B6128,改为B loc_6B6128,这样我们就解决了排序固定日期的问题
切换到Song::isRemoteDownloadPresent里面,在汇编里面找到CBZ W0, loc_68AEE8,改为B loc_68AEE8,这样我们就解决了下载的问题
切换到SongSelectScene::promptDownload里面,在汇编里面找到CBZ W0, loc_57286C,改为B loc_57276C,这样我们就解决了下载界面的问题
(单曲下载可以修改Song::isRemoteDownloadPresent和SongSelectScene::promptDownload达成,将跳转到整包下载的跳转全部指向单曲类下载即可)
改完以上这些后,WE包开了之后跟目前正常曲包没啥两样了

*角色偏移修改*
-arm64-v8a/3.5.3c-
先打开3.5.3c版本,打开Functions窗口,搜索Offset,名称排序后可以看到Character::getCenterScreenOffset/CharacterSelectOffset/ResultsOffset/SkillOffset,这就是角色偏移位置的储存函数,分别对应的是主界面/搭档选择界面/结算界面/游玩曲目时的技能显示框(这玩意第一次看挺脑梗的真的),除了CharacterSelectOffset/ResultsOffset,其他的几乎是塞满了全部角色的偏移情况(而且塞的很乱),我们进去看getCenterScreenOffset
使用armeabi-v7a辅助伪代码分析,图例已修改(因为我ida64伪代码就jumpout让我很脑梗)

其实很多自己试一下在看就试出来了()用的全部都是浮点数,有些是仅有X坐标或者Y坐标,用浮点数转16进制填入即可

3.5.3以上的话,打开Search - Immediate value,勾选Find all occurrence,在上面随便找一个没那么多重复的浮点数十六进制,输入搜索即可,其他Offset同理

写了好多寄吧废东西啊我超
应该不会动这玩意了
怎么ida识别不出来BR啊我快死了
以后有更新会直接更正专栏,耗费3次次数后直接开篇新的看看)