对unity3D游戏kartriderrush.apk(跑跑卡丁车2008年韩文单机版)的逆向破解修改
本帖最后由 q77190858 于 2018-1-3 13:38 编辑跑跑卡丁车kartriderrush.apk(跑跑卡丁车2008年韩文单机版)是nexon公司在2008年出品的手机单机版类似PC版的赛车游戏,可谓是那时的一代经典,曾经在iOS平台和我那800x480屏幕的小破安卓手机上完美运行。
十年时间过去了,如今的手机屏幕分辨率已经达到1920x1080甚至2K、4K,高分屏的安卓手机上运行这个古老的apk,会出现游戏分辨率不能自适应的问题,触摸按钮位置和图标也出现漂移。
原因自然是当时这个游戏只适配了800x480屏幕的手机。经过3个多月不懈的努力,我利用unity3D游戏逆向的技术,终于成功让这个古老的游戏换发了生机,完美自适应适配各种屏幕的手机。同时顺便破解了付费跑道、人物和赛车。
最后总结一下,这三个月的经验与教训。
一、利用apktool或者androidkiller解包apk
assets文件夹,unity3d的东西基本都在里面android文件夹,
所有的跑道assetbundle在里面bin->data文件夹,unity3d的所有关卡(场景)资源和序列化的资源(就是乱码的那些文件)都在里面,可以使用disunity来把资源解包成贴图和shade文件等。
bin->data->Managed文件夹,里面都是c#编写的dll动态链接库(或者说是assembly文件),核心文件是Assembly-CSharp.dll,我们主要修改这个文件
二、回编译一下apk文件,看有没有签名验证
结果游戏闪退,证明存在签名验证,估计在java代码里面,
利用jd-gui查看java源码,搜索“sign”,发现在com\nexon\kartriderrush\android\olleh\KartRiderRushActivity.class类中存在判断代码
然后我们在smali文件中注释掉这个判断就可以了。
三、研究c#源码
打开Assembly-CSharp.dll,发现有500多个类,真是要命了~
我们主要修改GUI开头的类,下面我来分析一下
GUIAccomplishPopup.cs,跑完成弹出的一个什么东西,只要是带Popup都是关于弹出的窗口
GUIAtlas.cs这个atlas真没搞懂,好像是负责图片资源最初的加载的
GUIAtlasCreator.cs,顾名思义,atlas创建器
GUIAtlasManager.cs,atlas管理器
GUIBackground.cs,显示普通gui界面背景的类
GUIBackgroundHost.cs,显示当为蓝牙房主时的gui界面背景的类
GUIBase.cs,gui基类
GUIBlackBar.cs,黑条,忘记了
GUIBlackBarPanel.cs,黑条面板
GUIBoosterGauge.cs,加速计
GUIButton.cs,按钮基类
GUIController.cs,控制器基类
GUIControllerIPad.cs,面板控制器基类
GUIControls.cs,管理在进行比赛过程中打开菜单选择gui操纵方式控件的,例如左右方向键和漂移按键,减速按键等
GUIFBLoginPopup.cs,facebook相关
GUIFontCalculator.cs,字体计算器
GUIFontCalculatorEx.cs,字体计算器增强版
GUIFontCalculatorEx2.cs,字体计算器增强版2
GUIFontCalculatorExParam.csGUIFontManager.cs字体管理器
GUIGarage.cs,车库
GUIGauge.cs,加速计
GUIImage.cs,图片基类
GUIInfo.cs,管理选完地图开始游戏的加载界面的小提示的
GUIInfoControllers.cs,也是管理选完地图开始游戏的加载界面的小提示的
GUIInterface.cs,接口基类
GUIIPad.cs,是在玩游戏时的左右漂移减速等操纵面板的类,很关键
GUIIPadItemSlot.cs,道具赛和氮气图标管理类
GUIIPadPlayerMark.cs,左上角玩家排名相关类
GUIIPadPlayerPanel.cs,左上角玩家排名相关类
GUIIPadPlayerRank.cs,左上角玩家排名相关类
GUIKartViewer.cs,不知道,3d查看器?
GUILastItem.cs,最后一个列表项目基类(可用于跑道,赛车、人物等)
GUIListCtrl.cs,列表控件基类
GUIListCtrlItem.cs,列表项目基类GUILoading.cs,gui界面最初时“点击屏幕继续”的那个界面
GUILoadingPopup.csGUILoadingReplay.csGUIMain.cs,主界面,就是选竞速赛还是道具赛的那个界面
GUIMinimap.cs,跑车时右上角的小地图
GUIMinimapMark.cs,小地图标记
GUIMinimapPanel.cs,小地图面板
GUIMinimapPanelBehaviour.cs,小地图面板动态控制
GUIMode.cs,是控制最上方白条按钮栏的,不管在哪个GUI界面都控制
GUIMoreItemType.csGUINewRecord.cs,跑完新纪录产生弹出的那个2s的面板
GUIPackagePopup.csGUIPanel.cs,panel基类
GUIPanelBuilder.cspanel建造器
GUIPanelEx.cspanel扩展版
GUIPanelEx3Part.cspanel3部分扩展版(适用于中间那部分可随意伸长变宽)
GUIPanelEx3PartHorz.cspanel水平3部分,左中右
GUIPanelEx3PartVert.cspanel垂直3部分,上中下
GUIPanelExBuilder.cspanel扩展版建造器GUIPanelFactory.cs负责将贴图dds或tga等格式显示在屏幕上
GUIPanelLayout.cs一个基类
GUIPanelManager.cspanel管理器
GUIPanelPlayerBuilderForIPad.cs
GUIPanelPlayerMarkBuilderForIPad.cs
GUIPanelPlayerRankBuilderForIPad.cs
GUIPatchSummaryPopup.cs夏季补丁弹出
GUIPause.cs管理暂停时的一些东西
GUIPlayerElem.cs左上角玩家元素
GUIPosMoverWS.cs
GUIProgramVersion.cs程序版本
GUIPurchaseConfirmPopup.cs购买确认弹出
GUIQuestPopup.cs请求弹出
GUIQuitPopup.cs退出弹出
GUIRankingBgInSingle.cs
GUIRankingHeaderInSingle.cs
GUIRankingListInSingle.cs这一块rankinglist大概是facebook的排名列表,反正我没看到过
GUIRankingListItem.cs
GUIRankingResetPopup.cs
GUIRestorePurchasesPopup.cs
GUIResult.cs跑完到达终点后负责显示所有人排名和分数的计分板,带一点显示新纪录功能
GUIRoomSearchingPopup.cs房间搜索弹出
GUIScrollBar.cs滚动条基类
GUIScrollBarHorz.cs水平滚动条
GUIScrollBarVert.cs垂直滚动条
GUIScrollhelpItem.csGUIScrollImage.cs滚动图片,在帮助面板里有可以滚动的图片(就是那些链接、物品介绍之类的)
GUIScrollImageEx.cs扩展滚动图片
GUIShopList.cs不是商店,store才是内购商店,这个是车库和人物选择库
GUIShopListItem.cs车库和人物选择库的项目(车或人)
GUISingleMode.cs顾名思义是单人模式,但是就是一个状态切换,没太大作用
GUISpeed.cs速度计
GUISpeedArrow.cs速度计箭头,我都没看到过这个箭头
GUISpeedArrowBuilder.csGUIStoreItemInfo.cs内购商店项目(商品)信息
GUIStoreLeftBackground.cs商店左背景
GUIStoreList.cs商店背景
GUIStoreListItem.cs商店项目
GUIStoreListRestoreItem.cs以下都是商店的东西
GUIStoreListUnlockableItem.cs
GUIStoreListUnlockAllItem.cs
GUIStoreListUnlockOneItem.cs
GUIStorePurchaseButton.cs
GUIString.csGUI形式的string(字符串)
GUITachometer.cs按照翻译,还是速度计
GUITrackInfoInSingle.cs单人竞速和道具模式下的跑道信息
GUITrackListInSingle.cs单人竞速和道具模式下的跑道列表
GUITrackListItem.cs单人竞速和道具模式下的跑道项目类
GUITrophyPopup.cs
GUITutorial.cs教程(基本没用)
GUITutorial2.cs教程2(也是没用的)
GUITutorialMulti.cs教程多(都不是新手了)
GUIType.cs
GUIUpDownListItem.cs
GUIURLTouchRegion.cs好像和帮助里的链接触控区域有关
GUIUtil.cs
GUIUVScrollImage.cs
GUIWaitingPlayersPopup.cs等待玩家弹出窗口
GUIWifi.cs其实是蓝牙模式,以下wifi开头的都是蓝牙模式
GUIWifiClient.cs
GUIWifiHost.cs
GUIWifiRoomList.cs
GUIWifiRoomListItem.cs
GUIWifiTrackList.cs
GUIWifiTrackListItem.cs
GUIWrongWay.cs 反方向跑时弹出的
四、使图片全屏显示
GUIPanelFactory.Instance.CreateByWindowSpace(type,f, tex, 5, GUIFontCalculator.DEFAULT_GAP);
注意到显示图片的地方就有这个函数,实际上这个函数就是将tex贴图中我们需要的那部分图片截取出来(缩放)并且显示在屏幕上的。
type:类型f:float或者float,
如果长度为6则没有缩放,则f,f为图片左上角在屏幕上显示的坐标(横屏以左上角为坐标系原点,水平右方向为x正方向,垂直向下为y正方向)。(f,f)-(f,f)为在贴图tex文件中截取的区域,就是左上角到右下角的对角线。用ps打开,用添加参考线的功能就可以看出实际截图区域。
Dds格式的贴图可使用ps-dds插件打开,2345看图王也可以查看,但是按照坐标截取查图片时要将dds格式的图片垂直翻转过来,否则一眼看出就是反的
Float的情况就是增加了缩放,(float,float)-(float,float)是在手机屏幕上显示的区域的对角线,相对于float增加了2位,可以实现放大缩小贴图。(float,float)-(float,float)同样是贴图截取位置
有人想既然这个方法是负责显示所有图片的,那么只要改一个方法 让其适应屏幕宽高,不就一劳永逸了吗?结果是悲观的,还存在很多地方有问题,例如在批量显示时,每个图片之间的高度和宽度,还有有些水平3部分或垂直3部分的控件图片,就比较复杂。所以还是得慢慢查看源码,慢慢改。
例如
Guiloading类是负责显示刚打开游戏那个界面的,这里它获取了mainTex,就是
这个文件,这里基本不需要截去,直接用就可以了,所以前4位是显示图片到全屏的意思,后4位微微偏了2个像素截下图片。这是改后的代码,原来的代码是长度为6数组,没有f和f。
例如
这张图,一看就有左右和漂移按键,一定是初始化操纵界面时调用的资源。我们找到对应的类。
Ingame_ui_android.dds贴图对应的类是GUIIPad类(这个类不是专门给iPad准备的,误导我好久),至于怎么找到的,只能告诉你,猜的。
这一样是我修改过后的代码,原来的代码就是没有*Screen.width/800f 类似的缩放代码。
要是我们把未修改的屏幕位置标出来,
就是图上用白线圈出,用红笔标记出的位置,由于操纵方式有3中,所以这三个位置的按键功能是不固定的,所以就采取了先定位,在动态切换功能的方式。
要使这5个位置缩放到全屏,只需改一下代码就可以了。不过,这只是贴图的位置全屏了,触摸的位置还是没有变。
接下来我们来改触摸位置。
五、使触摸区域自适应屏幕
一般来说,触摸区域和贴图位置都是绑定的,只有很特殊的情况才需要专门分析修改。
但是这个左右漂移减速按键是特殊的。
它们的触控区域代码在:IOSControler类(设置漂移和方向按键触控区域的类)中的一个字段的get和set方法里
(真。大神才敢这么写,活久见)
把这么关键的代码放在一个set方法里面,
真的让我瑟瑟发抖,工程师厉害了!
判断操控方式type的值,有三种,对应三种操控方式,同样我给它加上了自动适应屏幕缩放。
六、破解付费跑道
这个是顺便做的,主要精力在适应高分屏上。
c#:GUITrackListInSingle类InitializeListctrl(): Void函数,this.visibleAssets_.Add(item);
删除if判断是否是付费的跑道,结果跑道全部显示,但是要钱的跑道为阴影且无法选择
c#:GUITrackListInSingle类InitializeTrackList(): Void函数, if (definition.Lock) { nONE =(GUITrackListItem.enItemLockType) definition.LockType;直接改成了等于GUITrackListItem.enItemLockType.NONE}
意思是在加载跑道列表时,不去判断是否跑道锁定或要钱,结果跑道没有阴影了但还是无法选择 到这一步,可以看见跑道,但是付费的就是无法选中,真的很急人。
没事,让我们分析一下这个跑道类结构。GUITrackListInSingle类是一个list类,list中的item类对应GUITrackListItem类,item被选中,最后发消息给list类,由list负责处理。所以,关键验证核心代码在GUITrackListInSingle类的ReceiveMessage()方法中,注释掉就可以了。
付费的车辆和人物都是同样的list-item结构,破解的方法也是类似的,就不废话了。
七、拾遗
6、GUITrackListInSingle类的方法protected override Rect GetAvailableRegion(){ returnGUIBase.ConvertWSToUS(12f, 78f, 458f, 474f);将474f改为(float)Screen.height}
7、GUIControls类是管理在进行比赛过程中打开菜单选择gui操纵方式控件的,例如左右方向键和漂移按键,减速按键等
8、对于CreateByWindowSpace(Int32,Single[], FiaTexture, Int32, Vector3) : GUIPanelEx函数,在single数组为6的情况下,singlesingle代表图片左上角在手机屏幕上的起始位置点坐标(以屏幕左上角为坐标系原点,确定),(single ,single)和(single,single)代表在贴图资源上截图的矩形的对角线(似乎都要统一减2才准确,可能是系统偏移修正)。在single数组长度为8的情况下,前四位数代表屏幕上显示的区域对角线两点的坐标(可以比图片实际大,会自动缩放填满),后四位仍然是贴图资源截取位置
12、 修改GUIIPad类的srtart()方法的this.panels_.SetTouchRegionByWindowPos((702f* Screen.width) / 800f, 0f, (float) Screen.width, (82f * Screen.height) /480f);使暂停触摸区域适应屏幕
13、修改数组layoutArray1的前两个浮点数,使右上角计时面板位置自适应屏幕14、GUIIPad类中的awake()方法给this.controlInfo赋值,这个this.controlInfo就是屏幕下方最多5个按键的图片显示位置坐标,前4位是左上角和右下角的坐标,我修改成根据屏幕大小缩放图标15、修改GUIIPad类的awake()和start()方法,使操纵按钮图标显示自适应屏幕缩放,修改iOSController类中的type字段的set_Type方法,使操纵按钮触摸位置自适应屏幕缩放。
16、class MinimapCameraControl类中修改小地图的位置
17、GUIMode类是控制最上方按钮栏的,不管在哪个GUI界面都控制18、GameLoadingBack和GameLoadingStage类是管理选择跑道点击开始后的载入界面的。
八、下载地址
链接:https://pan.baidu.com/s/1geWmnPT密码:1ms1管理员能加一个回复可见吗? king_秦飞雪 发表于 2018-1-5 14:03
自适应有时候还是有bug,又得手动修改对应型号的键位,不过总得还是不错的
楼主手机分辨率多少,什么型号? 吓死宝宝了 发表于 2018-1-8 20:30
我手机打开后第一个界面是中间空白,然后进不去游戏···
什么手机型号? 这排版,无力吐槽。。。 布局很乱。没有心情看!!!!!!! 排版太乱 不过感觉很牛逼 路过支持下 谢谢分享!!!!! 感谢分享 这个版本的跑跑卡丁车我还玩过 本帖最后由 q77190858 于 2018-1-3 14:09 编辑
純白p 发表于 2018-1-3 13:50
这个版本的跑跑卡丁车我还玩过
满满的回忆啊,赶快下下来看看 额,看不懂,慢慢看