吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7110|回复: 21
收起左侧

[Android 原创] 某商业街游戏修改

[复制链接]
garfield028 发表于 2019-9-19 17:45
本帖最后由 garfield028 于 2019-9-19 18:52 编辑

最近在看论坛教程,学习一些移动安全上面的知识,索性也找了一个游戏学学修改。

我下载了一款游戏 -> Shopping Mall Tycoon_v1.1.2

通过查看APK文件,发现他是基于Unity开发,然后看到游戏已经打包成libil2cpp了。

依葫芦画瓢,使用 Il2CppDumper  https://github.com/Perfare/Il2CppDumper 进行dump,so。

至于DUMP教程,其实论坛很多,比如https://www.52pojie.cn/thread-733757-1-1.html

然后剩下就是分析DUMP文件了。

首先,我们必须要进入游戏看看游戏的场景,这个步骤很重要,发现一些游戏的特性。

如图:

{1831~{0}5~RL)EKN6R~A4P.png

发现了游戏中货币至少3种,然后体验下基础玩法,最后看了一下钻石的获得方式。

得到如下结论:

建筑物升级: 4个 分支

1.可容纳人数
2.人均消费
3.消费速度
4.改造

然后钻石是通过观看广告

然后还有一些细节,就是离线后,可以挂机,也就是说,有离线收益。

总和上面的信息,我在DUMP.CS中搜索如下关键字

gold , money , diamond , face , house , watch

然后看看有没有开发者的接口

搜索 debugcontrol , gm , gamemaster , gmui , testui

我一共从dump.cs中找到了如下关键函数


// Namespace:
public class GameData : MonoBehaviour // TypeDefIndex: 3339
{
        // Fields
        省略

        // Methods
        public void .ctor(); // RVA: 0x1D6FE0 Offset: 0x1D6FE0
        private void Awake(); // RVA: 0x1D71EC Offset: 0x1D71EC
        private void Update(); // RVA: 0x1D794C Offset: 0x1D794C
        public void Init(); // RVA: 0x1D7284 Offset: 0x1D7284
        public bool Lock(int id); // RVA: 0x1D7F44 Offset: 0x1D7F44
        public string LockString(int id); // RVA: 0x1D85F0 Offset: 0x1D85F0
        public void GetExp(int getExp); // RVA: 0x1D6840 Offset: 0x1D6840
        public void UpdateGround(); // RVA: 0x1D90F4 Offset: 0x1D90F4
        public float GetExpProgress(); // RVA: 0x1D98EC Offset: 0x1D98EC
        public string GetExpPorgressString(); // RVA: 0x1D99E8 Offset: 0x1D99E8
        public void MoneyNotSave(MoneyType type, long number); // RVA: 0x1D9B64 Offset: 0x1D9B64
        public long GetMoney(MoneyType type); // RVA: 0x1D445C Offset: 0x1D445C
        public void SaveMoney(MoneyType type, long number); // RVA: 0x1CA70C Offset: 0x1CA70C
        public bool GetMoneyEnough(MoneyType type, long need); // RVA: 0x1D9FA0 Offset: 0x1D9FA0
        public long GetMoneyReally(MoneyType type); // RVA: 0x1D9FD8 Offset: 0x1D9FD8
        public void SaveThiefNum(); // RVA: 0x1DA020 Offset: 0x1DA020
        public void Saveuuid(); // RVA: 0x1DA094 Offset: 0x1DA094
        public void SaveGround(GroundItem item); // RVA: 0x1D9634 Offset: 0x1D9634
        public void GetGround(GroundItem ground, int groundIndex); // RVA: 0x1DA108 Offset: 0x1DA108
        public void SaveRole(int id); // RVA: 0x1D7AB0 Offset: 0x1D7AB0
        public int GetRole(int id); // RVA: 0x1D7BF0 Offset: 0x1D7BF0
        public long GetRoleBasePower(int id); // RVA: 0x1DA628 Offset: 0x1DA628
        public float GetHouseCapcity(int buildingId, int pro); // RVA: 0x1DA834 Offset: 0x1DA834
        public long GetHouseCapcityGold(int buildingId, int pro); // RVA: 0x1DA9D8 Offset: 0x1DA9D8  容纳人数 升级需要资金
        public long GetHouseCost(int buildingId, int pro); // RVA: 0x1DABC8 Offset: 0x1DABC8
        public long GetHouseCostGold(int buildingId, int pro); // RVA: 0x1DADB8 Offset: 0x1DADB8  消费数 升级需要资金
        public float GetHouseTime(int buildingId, int pro); // RVA: 0x1DAFA8 Offset: 0x1DAFA8
        public long GetHouseTimeGold(int buildingId, int pro); // RVA: 0x1DB150 Offset: 0x1DB150  消费速度 升级需要资金
        public long GetHouseReformGold(int buildingId, int buildingLevel); // RVA: 0x1DB340 Offset: 0x1DB340  店铺升级 需要资金
        public int GetPeopleNum(); // RVA: 0x1DB530 Offset: 0x1DB530
        public int GetMaxCap(int buildingId); // RVA: 0x1DB640 Offset: 0x1DB640
        public void SaveAchieve(int id, int condition); // RVA: 0x1DB660 Offset: 0x1DB660
        public int GetAchieve(int id); // RVA: 0x1D7CC4 Offset: 0x1D7CC4
        public void SaveBuildingsBuild(int id); // RVA: 0x1DB770 Offset: 0x1DB770
        public int GetBuildingsBuild(int id); // RVA: 0x1D7D98 Offset: 0x1D7D98
        public void SaveGroundNum(); // RVA: 0x1D9878 Offset: 0x1D9878
        public void SaveSaleDay(); // RVA: 0x1C8808 Offset: 0x1C8808
        public void SaveOpenLevel(int value); // RVA: 0x1DB8B0 Offset: 0x1DB8B0
        public void SaveOpenHP(int value); // RVA: 0x1DB924 Offset: 0x1DB924
        public void SaveWatchTimes(); // RVA: 0x1D7E6C Offset: 0x1D7E6C
        public void SaveWatchGetCount(); // RVA: 0x1D7ED8 Offset: 0x1D7ED8
        public void SaveSellExp(int needExp); // RVA: 0x1DB998 Offset: 0x1DB998
        public int GetThisNeedExp(); // RVA: 0x1D8E18 Offset: 0x1D8E18
        public int GetNextNeedExp(); // RVA: 0x1DB99C Offset: 0x1DB99C
        public long GetWatchDiamond(); // RVA: 0x1DBA84 Offset: 0x1DBA84  看广告获得钻石数量
        public void ChangeScene(int scene); // RVA: 0x1DBAA0 Offset: 0x1DBAA0
        public void GetPlaying(); // RVA: 0x1DBB14 Offset: 0x1DBB14
        public void SavePlaying(); // RVA: 0x1DBF18 Offset: 0x1DBF18
        public static void SetVector3(string key, Vector3 vector); // RVA: 0x1DC440 Offset: 0x1DC440
        public static Vector3 GetVector3(string key); // RVA: 0x1DBDD4 Offset: 0x1DBDD4
        public void UpdateGiveRole(); // RVA: 0x1D8F00 Offset: 0x1D8F00
        public void UpdateVersion(); // RVA: 0x1DC560 Offset: 0x1DC560
        private static void .cctor(); // RVA: 0x1DC6C8 Offset: 0x1DC6C8
}

public sealed class HOUSE : IMessage`1<HOUSE>, IMessage, IEquatable`1<HOUSE>, IDeepCloneable`1<HOUSE> // TypeDefIndex: 3382
{
        // Fields
        省略

        // Properties
        省略

        // Methods
        [DebuggerNonUserCodeAttribute] // RVA: 0x16BE2C Offset: 0x16BE2C
        public void .ctor(); // RVA: 0x3F8888 Offset: 0x3F8888
        [DebuggerNonUserCodeAttribute] // RVA: 0x16BE3C Offset: 0x16BE3C
        public void .ctor(HOUSE other); // RVA: 0x3F8964 Offset: 0x3F8964
        public static MessageParser`1<HOUSE> get_Parser(); // RVA: 0x3F8C50 Offset: 0x3F8C50
        public static MessageDescriptor get_Descriptor(); // RVA: 0x3F8CDC Offset: 0x3F8CDC
        private MessageDescriptor Google.Protobuf.IMessage.get_Descriptor(); // RVA: 0x3F8E84 Offset: 0x3F8E84
        [DebuggerNonUserCodeAttribute] // RVA: 0x16BE4C Offset: 0x16BE4C
        public HOUSE Clone(); // RVA: 0x3F8EFC Offset: 0x3F8EFC
        public int get_ID(); // RVA: 0x3F8F6C Offset: 0x3F8F6C
        public void set_ID(int value); // RVA: 0x3F8F74 Offset: 0x3F8F74
        public int get_Name(); // RVA: 0x3F8F7C Offset: 0x3F8F7C
        public void set_Name(int value); // RVA: 0x3F8F84 Offset: 0x3F8F84
        public int get_CapacityStart(); // RVA: 0x3F8F8C Offset: 0x3F8F8C
        public void set_CapacityStart(int value); // RVA: 0x3F8F94 Offset: 0x3F8F94
        public float get_Capcity(); // RVA: 0x3F8F9C Offset: 0x3F8F9C
        public void set_Capcity(float value); // RVA: 0x3F8FA4 Offset: 0x3F8FA4
        public long get_CapcityGold(); // RVA: 0x3F8FAC Offset: 0x3F8FAC
        public void set_CapcityGold(long value); // RVA: 0x3F8FB4 Offset: 0x3F8FB4
        public float get_CapcityMulti(); // RVA: 0x3F8FC4 Offset: 0x3F8FC4
        public void set_CapcityMulti(float value); // RVA: 0x3F8FCC Offset: 0x3F8FCC
        public long get_EarningStart(); // RVA: 0x3F8FD4 Offset: 0x3F8FD4
        public void set_EarningStart(long value); // RVA: 0x3F8FDC Offset: 0x3F8FDC
        public float get_ShopPower(); // RVA: 0x3F8FEC Offset: 0x3F8FEC
        public void set_ShopPower(float value); // RVA: 0x3F8FF4 Offset: 0x3F8FF4
        public long get_ShopPowerGold(); // RVA: 0x3F8FFC Offset: 0x3F8FFC
        public void set_ShopPowerGold(long value); // RVA: 0x3F9004 Offset: 0x3F9004
        public float get_ShopPowerMulti(); // RVA: 0x3F9014 Offset: 0x3F9014
        public void set_ShopPowerMulti(float value); // RVA: 0x3F901C Offset: 0x3F901C
        public int get_TimeStart(); // RVA: 0x3F9024 Offset: 0x3F9024
        public void set_TimeStart(int value); // RVA: 0x3F902C Offset: 0x3F902C
        public float get_WaitTime(); // RVA: 0x3F9034 Offset: 0x3F9034
        public void set_WaitTime(float value); // RVA: 0x3F903C Offset: 0x3F903C
        public long get_WaitTimeGold(); // RVA: 0x3F9044 Offset: 0x3F9044
        public void set_WaitTimeGold(long value); // RVA: 0x3F904C Offset: 0x3F904C
        public float get_WaitTimeMulti(); // RVA: 0x3F905C Offset: 0x3F905C
        public void set_WaitTimeMulti(float value); // RVA: 0x3F9064 Offset: 0x3F9064
        public string get_Reform(); // RVA: 0x3F906C Offset: 0x3F906C
        public void set_Reform(string value); // RVA: 0x3F9074 Offset: 0x3F9074
        public long get_ReformGold(); // RVA: 0x3F90F4 Offset: 0x3F90F4
        public void set_ReformGold(long value); // RVA: 0x3F90FC Offset: 0x3F90FC
        public float get_ReformMulti(); // RVA: 0x3F910C Offset: 0x3F910C
        public void set_ReformMulti(float value); // RVA: 0x3F9114 Offset: 0x3F9114
        public string get_Desc(); // RVA: 0x3F911C Offset: 0x3F911C
        public void set_Desc(string value); // RVA: 0x3F9124 Offset: 0x3F9124
        public int get_OpenLevel(); // RVA: 0x3F91A4 Offset: 0x3F91A4
        public void set_OpenLevel(int value); // RVA: 0x3F91AC Offset: 0x3F91AC
        public string get_BuildValue(); // RVA: 0x3F91B4 Offset: 0x3F91B4
        public void set_BuildValue(string value); // RVA: 0x3F91BC Offset: 0x3F91BC
        public string get_BuildImage(); // RVA: 0x3F923C Offset: 0x3F923C
        public void set_BuildImage(string value); // RVA: 0x3F9244 Offset: 0x3F9244
        public int get_Score(); // RVA: 0x3F92C4 Offset: 0x3F92C4
        public void set_Score(int value); // RVA: 0x3F92CC Offset: 0x3F92CC
        public long get_NeedGold(); // RVA: 0x3F92D4 Offset: 0x3F92D4
        public void set_NeedGold(long value); // RVA: 0x3F92DC Offset: 0x3F92DC
        [DebuggerNonUserCodeAttribute] // RVA: 0x16BE5C Offset: 0x16BE5C
        public override bool Equals(object other); // RVA: 0x3F92EC Offset: 0x3F92EC
        [DebuggerNonUserCodeAttribute] // RVA: 0x16BE6C Offset: 0x16BE6C
        public bool Equals(HOUSE other); // RVA: 0x3F9370 Offset: 0x3F9370
        [DebuggerNonUserCodeAttribute] // RVA: 0x16BE7C Offset: 0x16BE7C
        public override int GetHashCode(); // RVA: 0x3F96B4 Offset: 0x3F96B4
        [DebuggerNonUserCodeAttribute] // RVA: 0x16BE8C Offset: 0x16BE8C
        public override string ToString(); // RVA: 0x3F9B1C Offset: 0x3F9B1C
        [DebuggerNonUserCodeAttribute] // RVA: 0x16BE9C Offset: 0x16BE9C
        public void WriteTo(CodedOutputStream output); // RVA: 0x3F9BA4 Offset: 0x3F9BA4
        [DebuggerNonUserCodeAttribute] // RVA: 0x16BEAC Offset: 0x16BEAC
        public int CalculateSize(); // RVA: 0x3FA598 Offset: 0x3FA598
        [DebuggerNonUserCodeAttribute] // RVA: 0x16BEBC Offset: 0x16BEBC
        public void MergeFrom(HOUSE other); // RVA: 0x3FAC10 Offset: 0x3FAC10
        [DebuggerNonUserCodeAttribute] // RVA: 0x16BECC Offset: 0x16BECC
        public void MergeFrom(CodedInputStream input); // RVA: 0x3FADEC Offset: 0x3FADEC
        private static void .cctor(); // RVA: 0x3FB3CC Offset: 0x3FB3CC
        [CompilerGeneratedAttribute] // RVA: 0x16BEDC Offset: 0x16BEDC
        private static HOUSE <_parser>m__0(); // RVA: 0x3FB4A8 Offset: 0x3FB4A8
}
关键函数我已经标红,然后标红的都是我自己修改的函数。

接下来就是修改了,修改的教程论坛也可以找到很多

比如:https://www.52pojie.cn/forum.php?mod=viewthread&tid=818304

我就不多做介绍了。

上面 4个升级函数差不多,在IDA中,我修改如下位置:
这4个升级函数代码段还是比较长,他要计算等级 周期 然后计算最后的花费。
但我们只需要关注最后计算的结果:

(EPVD1}5%_GK{I[2P{4CM@S.png

关键就在这里了:
.text:001DAF6C 3F 40 FD EB                                                     BL              j___floatdisf
.text:001DAF70 10 0A 00 EE                                                     VMOV            S0, R0
.text:001DAF74 10 4A 01 EE                                                     VMOV            S2, R4
.text:001DAF78 01 0A 20 EE                                                     VMUL.F32        S0, S0, S2
.text:001DAF7C 10 0A 10 EE                                                     VMOV            R0, S0
.text:001DAF80 9B 3F FD EB                                                     BL              j___fixsfdi
.text:001DAF84 F0 8D BD E8                                                     LDMFD           SP!, {R4-R8,R10,R11,PC}

其实,我也不怎么看的懂ARM汇编,猜就是把一个浮点付给R0,然后,我只需要把一个固定值付给R0就好了。
所以我改成了MOV R0,0x0 ,对应的机器码:00 00 A0 E3 ,然后用UE等BINHEX编辑工具,找到OFFSET去修改就好了。然后我把4个升级函数都改成0。

接下来就是Diamond观看函数,差不多的原理,我就不截图了,直接贴代码段
这个是watch diamon 我修改后的代码段: 我把修改了的地方也标红了
.text:001DBA84 3C 00 90 E5                                                     LDR             R0, [R0,#0x3C]
.text:001DBA88 00 01 80 E0                                                     ADD             R0, R0, R0,LSL#2
.text:001DBA8C 05 00 80 E2                                                     ADD             R0, R0, #5
.text:001DBA90 FF 00 50 E3                                                     CMP             R0, #0xFF
.text:001DBA94 FF 0F 0F E3                                                     MOVLT           R0, #0xFFFF
.text:001DBA98 40 1E A0 E1                                                     MOV             R1, R0,ASR#28   
.text:001DBA9C 1E FF 2F E1                                                     BX              LR

这里我说一下,我第一次修改后,发现不对,因为对ARM汇编不熟悉,所以忽略了ASR这个指令。。。。然后修改了操作位数后,结果正确了。但是这个并不完美,因为还是要观看一次广告。。。

剩下就是收益了,具体方法和上面差不多,我就不继续废话了。

最后,给一个几个结果截图吧:
然后分享一下修改后的APK

HX47L_QVO`J~M]8NX5H4O.png 1INIR%T9$HTW]16_J$[}57O.png P39UUCN1Q_PWZU9}VD9%`7F.png


修改后的APK包:

下载:https://www.lanzouj.com/i69kc9g 密码:heb3


初学者,很多地方都是摸着过河,不清楚的,说错的,大家多多包涵:)

免费评分

参与人数 4吾爱币 +12 热心值 +4 收起 理由
qtfreet00 + 9 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
abigsun + 1 + 1 用心讨论,共获提升!
147 + 1 + 1 该安装包未包含任何证书。安装失败,华为安卓8.1
onihot + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

onihot 发表于 2019-9-20 14:23
本帖最后由 onihot 于 2019-9-20 14:26 编辑

这类教程得多支持,感谢楼主分享技术!我也是很喜欢研究游戏修改,尤其汇编,可以学习到的东西比较多,我现在改汇编遇到最大的问题,不知怎么增加指令,比如说我改个金钱或者经验倍数,遇到双字节的thumb指令根本无从下手修改,因为增加指令会导致很多指令偏移地址。
jyhh09 发表于 2019-9-20 22:27
garfield028 发表于 2019-9-20 16:08
我是用的模拟器,我没有android真机。。抱歉啊。。。 看看能不能网上搜下方法,或者去签个名之类的。。。 ...

你模拟器有广告加载吗?什么模拟器?  这个版本游戏怎么都是广告!!
啊笨 发表于 2019-9-20 11:57
a16565001 发表于 2019-9-20 12:19
显示广告没有加载
cyj158 发表于 2019-9-20 13:05
高手技术贴,顶起!
wuyaqing981206 发表于 2019-9-20 13:21
顶顶顶,萌新路过
信仰自由 发表于 2019-9-20 13:30
华为手机想玩玩  但是显示没有证书
jyhh09 发表于 2019-9-20 14:26
把广告获取的判断值该一下就完美了
starlancer 发表于 2019-9-20 14:48
游戏下着玩试试!
啊笨 发表于 2019-9-20 15:59
安装失败,提示安装包损坏!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-27 12:45

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表