首页
社区
课程
招聘
[原创]iOS平台游戏安全再议之存档修改与防御
发表于: 2012-10-17 12:19 17033

[原创]iOS平台游戏安全再议之存档修改与防御

2012-10-17 12:19
17033

因为博客中图片太多,需要图文并茂的,欢迎到原博客阅读http://danqingdani.blog.163.com/blog/static/1860941952012993941578/

    一款游戏,如果免费功能做得足够吸引,那玩家下一步就会想要尝试收费部分。这时候,单纯玩家会走上正常付费路线,而较为吝啬的玩家则会尝试搜寻该款游戏的外挂,比如说xxx破解版,xxx完整版,xxx补丁,xxx存档,xxx辅助。

       对于iOS游戏,玩家首先会在比较火的论坛里去搜索,例如威锋网 。我们试着用关键字“修改” 在这个论坛进行搜索,可以找到很多iOS游戏的修改攻略,说不定有一个就是你家开发的游戏。



       进入该论坛后,玩家会发现这里有很多“志同道合”的人,人多到可以为游戏存档修改建立了专门的分区。



       随着移动游戏的进一步兴起,专业的移动游戏修改网站也在兴起,例如BHGBOX论坛就是一个专门交流iOS内购解锁的论坛,该论坛近期还加入android游戏修改的专栏。

       有这种想学游戏修改攻略的”积极“玩家,也有那种懒得自己动手更想用钱解决问题的玩家,同样有需求,也有满足需求的地方,淘宝或拍拍上就有大量出售游戏作弊的店铺。



       其实像这种在淘宝上买卖iOS游戏中货币,装备,等级,新关卡解锁的店铺,从iOS游戏刚兴起到现在app繁荣,商品内容和商品说明也发生了不小的变化。

       第一阶段:利用的是黑卡充值。

       第二阶段:存档修改,这时候服务态度超好的商家会给亲远程协助,他们会在商品说明中给出操作方式甚至是操作原理,实诚得让你不好意思不买。(下面截图来自我非常喜欢的掌柜卷卷熊的商品说明,现在有不少店铺盗用这张说明,我可以证明是卷卷熊原创)





第三阶段:发展这个阶段,百花齐放,有了八门神器,也有了iap cracker,iap free,但绝大多数还是采取的存档替换,因为存档替换不走支付流程,不会产生非法订单, 不可能通过核对订单的方法发现问题,相对很安全(内存修改也不产生订单,也是较安全的作弊方式)。除了安全,还有一个就是较容易,很多开发没有意识到存档会被各种方法修改,于是在防御上,有不少裸奔的(完全明文),有不少穿薄纱的(简单编码),导致很容易作弊,当然应用在存档修改的猥亵下,也逐步穿上了防护服。存档修改不是iOS游戏首创,PC机上的单机游戏早就经历了并正在经历这种摧残,而主流的iOS游戏都是弱联网游戏,都更类似于单机游戏,因此很不幸的遗传了单机游戏与生俱来的改存档硬伤。

      
        从应用在设备上的安装目录结构上看,我们可以发现Documents和Library文件夹就是存档修改的重要关注对象。Documents主要用于存放用户文档和应用数据文件,例如用户的帐号信息,用户的游戏数据。而Library主要用户存放应用相关文件,例如应用内购相关文件就存放在此。除此之外应用的mac-o excutable文件也是重点关注对象,通常是在存档由于加密等因素无法简单的定位到存档修改点时用于逆向分析修改。



            
        
         在摸清了存档的存放位置,下一步需要了解存档的存储格式,不同的格式对应不同的修改方法。一般会有以下三种格式,明文格式,弱编码格式,二进制格式。下面看看具备不同存储格式的游戏存档修改实例:

1.明文格式

(1)PLIST
      例如游戏kingdom rush的内购相关数据文件 /Library/Preferences/com.armorgames.kingdomrush.plist, 用pledit编辑器就可以查看修改。



其中hashHeroDenas的值为true还是false决定了Denas关卡是否解锁。将其修改成true则解锁了Denas关卡。
      判断是否是plist格式,不能仅仅靠文件后缀名,在windows下可以用记事本打开,然后观察文件头是否含有bplist00这个标识来判断。也可以用strings | head -1 查看文件头字符和file命令查看文件类型。

(2)SQLite3(数据库)
     例如游戏鳄鱼小顽皮爱洗澡的内购相关数据文件/Library/water.db采用了sqlite3格式,在windows下可以用SQLite Database Browser工具进行查看与SQL操作。也可以用sqlite3命令操作。



  上图中红框部分的SQL操作就能解锁该游戏的所有关卡。
         同样判断是否是sqlite3格式,也不能仅仅靠文件后缀名,用记事本打开如果文件头为SQLite format 3则可以判断是sqlite3数据库格式。也可以用strings | head -1 查看文件头字符和file命令查看文件类型。

(3)JSON
例如游戏MyTown2的用户数据文件/Documents/LocalFiles/savegame.json,就是json格式的,一般是UTF-8 Unicode text编码,可以直接用记事本进行查看修改。



红框部分就是对应的游戏等级,经验值,游戏币数量。

2.Base64编码格式


例如游戏Cleopatra's Pyramid的内购相关数据就存放在文件/Library/Preferences/com.gameduell.cleopatraspyramid.plist中的CLEO_APP_SAVE_DATA部分,并采用了base64编码。base64编码比较容易识别,如何一段文本中包含大小写字母,数字,+,/,结尾有=基本就是base64编码格式了,除了好识别,同样的也非常容易解码,网上就有不少很好的在线解码网站。



如上图只需要用pledit编辑器打开该文件,将CLEO_APP_SAVE_DATA部分拷贝到base64解码网站转换为明文格式,然后再用pledit编辑器查看修改,再还原成base64编码格式,最后替换原文件的CLEO_APP_SAVE_DATA部分即可。

3.二进制格式(data格式)

例如里约热内卢:圣徒之城采取二进制方式保存存档Gangstar3.sav



其中A8 61就是25000的倒序存储(25000转换为十六进制为61 A8),为游戏中荣誉值。
这种格式的文件只能用十六进制编辑器打开。玩家会尝试修改文件中记录的等级,积分,道具,货币等在游戏界面有回显的数值。如果存档未加密,一般都是将游戏数值转换成十六进制,然后在文件中搜索(一般采用4字节倒序的存储方式),如果数值很小或者在文件中不是唯一,就需要回到游戏多次操作,对比文件的变化来定位修改点(很内存修改方法类似)。如果能定位到修改点但修改不成功则说明文件做了完整性检验,需要突破检验方法。如果不能定位到修改点则说明文件做了加密处理,则需要找出加密算法解密存档,难度比较大,需要逆向弄清逻辑。

        只是修改存档,对某些游戏,并不能达到内购解锁的效果,这时候,我们需要简单了解一下IAP的相关知识,产品类型不同和交付方式不同,带来的存档变化也不一样,所以我们在修改方式上可以看到,有的游戏只需要简单的修改一下配置选项,有的游戏则需要额外的数据文件覆盖。

app store的产品种类有四种
1. 内容型。包括电子书,电子杂志,照片,插图,游戏关卡,游戏角色,和其他的数字内容。
2.扩展功能。这些功能已经包含在app内部。在未购买之前被锁定。例如,你可以在一个游戏程序中包含若干小游戏,用户可以分别来购买这些游戏
3.服务。允许程序对单词服务收费。比如录音服务
4.订阅。支持对内容或服务的扩展访问。

也可以简化为以下三种:
1.消耗性商品,该类商品在需要时被单次购买,每次购买都需要再次验证帐号,例如游戏中额外的游戏货币,道具。

2.非消耗性商品,该类商品只需购买一次,一旦被购买,和该用户iTunes账户关联的设备都可以使用此商品。例如完整版游戏,额外的关卡。

3.订阅类,具备以上两种特性。和消耗性商品一样,可以被多次购买,订阅有效期过则可再次购买。和非消耗性商品一样,订阅类商品可以被和该用户iTunes账户关联的所有设备使用。但需要游戏服务器来支持多个设备间订阅服务的共享。

app store的交互方式分为以下两种:
1.内置类型(Built-in model)
这种模型的特点是整个购买流程不需要独立的游戏服务器,需要交付的产品已经存放在前端设备中了,需要前端自己的逻辑来处理。非消费性商品常采用这种模式。



从流程图可以看出,这种方式有个重要的优点,即可以及时的给客户交付产品(因为需要支付的产品已经存放在设备客户端)。当成功购买产品后,程序将相应的功能解锁,提供给用户。而解锁最简单的方式就是通过程序偏好设置application preferences来控制,不少游戏应用都采用了这种方式,从而造成了可以通过简单的修改特定的配置选项来解锁。

2.服务器类型(server model)
这种模型的特点是整个购买流程需要独立的游戏服务器,需要游戏服务器将购买内容(data)传递给程序。适用于内容(例如新的关卡)、订阅和服务型商品。因为商品可以作为数据发送,而不需要改动app bundle。(注意:IAP不提供购买补丁的功能,如果需要更改app bundle,必须向app store提交新的app版本)



       这种模型由于需要从游戏服务器下载购买内容,不能简单的只修改某个配置选项,需要有人将解锁部分的数据共享出来,然后其他玩家再替换覆盖原数据文件来达到解锁。

         下面截图来自broad提供的《RealCover -Fake magazine covers》内购解锁方法,非常具备代表性,几乎所有的内购解锁攻略都是这种步骤。


      
      5.1,5.2步中的解锁文件就是通过正常购买后,对比解锁前后的安装文件目录/Documents和/Library变化来实现解锁文件的共享的。其中5.1步是用来控制内购情况的配置选项,5.2步是内购部分的数据内容。下面截图就是broad提供的通过购买分享解锁方法。

       自购解锁(自己通过游戏中购买,提取解锁方法来分享)和自购破解(自己通过购买收费的ipa游戏,然后去掉游戏DRM的,破解成可随意安装的ipa包)是随着苹果平台流行起来,各种发布苹果游戏应用的网站论坛吸引用户的一个重要噱头。



      解锁方法是在早期提出的,对于新推出的应用需要有些改变。例如苹果开始拒绝那些会访问用户设备UDID的APP进入其应用商店,UDID有了新的替换方法,伪造这唯一性标识也不在是伪造UDID,可能需要伪造MAC地址或其它别的东西,这取决于UDID替换算法是怎么实现的。例如http://www.cnblogs.com/zhulin/archive/2012/03/26/2417860.html中采取返回MAC和CFBundleIdentifier的MD5值来替换UDID作为用户唯一性标识,不同的应用有不同的替换法,但建议游戏应用不要单纯的使用MAC地址,因为MAC地址也是可以伪造的。

       bra bra地说了那么多,都证明了存档非常容易被破坏,那我们有什么一劳永逸的好办法来保障存档的安全呢?其实目前并没有非常有效的方法,判断的依据是火热的游戏修改网站每天都有几十款游戏的修改攻略,如果有好的防御,这些游戏公司应该早有所行动了。

       我的思路是从存档修改攻略中学习,总结哪些是容易修改的,我们避免做成那样;哪些是很难修改的,我们尽量做成那样。这也是我花大篇幅介绍游戏修改方式的原因,并不是为了宣传修改手段,而是希望游戏开发者能直视我们的游戏正遭受着什么,可能你会觉得修改手段不值得一提,但正是这些简单的可以大众化的方法使得你辛苦研发的游戏的部分收入打了水漂。

      其实,某些做外挂搞游戏破解的,如果不涉及到破坏他人劳动成果这一思想包袱,他们还是挺可爱的,服务态度好又风趣。例如BHG论坛就给不易破解的iOS应用来了个有趣的分类,并评出了最安全的游戏开发商http://bbs.bhgbox.org/thread-2490-1-1.html?from=threadlink。

       不易破解的游戏有5类



       (1)保护熊猫,意思对于国产游戏,他们不会主动在论坛中发帖解锁方式,也不会理睬论坛用户的解锁求助。但不会禁止论坛用户对国产游戏的内购解锁。我猜想是因为怕国内游戏开发商的律师函带来麻烦。

       (2)替身演员,意思是那种在内购中检测UDID的游戏。由于解锁存档中包含了UDID信息,需要伪造成解锁存档提供者的UDID,需要安装UDID faker软件,只能在越狱机上分享,而不能在非越狱机上使用,算有点难度类型。(如上文提到的,UDID被替换了,这里的说明需要更改一下)

       (3)星云锁链,就是”将解锁信息写入/var/Keychains/keychain-2.db的genp表中的游戏。应用每次运行都会检查这个数据库里是否偶相应的解锁信息。非越狱机是看不到这个文件的,无法修改这里,算有点难度类型。

      keychain-2.db数据库是iOS提供的一种安全保密信息,主要由以下4张表组成:



keychain没有那么安全,使用keychain-dump是可以将这个数据库存放的信息导出来查看的



        (4)凤姐上身,就是强联网游戏,数据在服务端,验证逻辑在服务端。这个的确困难,除非客户端与服务端之间的通信协议或服务端配置存在问题才有突破点。目前的网络游戏,以网页游戏为例,大多数的外挂就是由于服务器的配置错误,逻辑漏洞,不安全的协议设计及实现方式造成的。

       受到表彰安全游戏公司如下,其实是警告玩家遇到以下几家公司绕道而行,放弃解锁,避免浪费论坛货币。
      
   


可以看出来在存档安全方面,我们可以
1. 游戏逻辑尽量服务端验证,这个取决于游戏的类型,没法强制限制。
2. 重要文档加密存储,同时存档加密函数也需要加密。因为存档加密,需要逆向调试来定位存档加密方法,或直接修改关键函数来作弊,于是提高了门槛。千万不要采用游戏存档修改实例中提到的存储方式(plist,sqlite,json,base64,简单的二进制存储)。
3.增加存档中的唯一性标识,例如使用用户帐号、MAC地址等特定标识配合一定的转换算法来生成一个唯一性标识, 来避免不同帐号之间存档的替换。
4.存档完整性检验,在存档存储中写入完整性检验码,同时要注意检验算法的强度,千万不要使用和校验这种方式,因为对冲法可以绕过这种检验(对冲法就是在存档的某个地方增加了一定数量,同时找一个地方减少同额的数量,例如将游戏存档中游戏货币数量对应的00改成了FF,就可以搜索另一处FF,改为00)
5.IAP采取较为安全的server model模式,控制内购的配置表要加密存储,加密方式参照2,3,4点
6.要同时配合内存加密和正确的IAP内购流程措施(具体参照iOS平台游戏安全再议之八门神器内存修改,IAP Free内购破解的防御)
7.反逆向保护,存档加密函数,唯一性标识生成算法,完整性检验算法相关函数的加密处理。预计下一篇介绍

最后附上已介绍的破解方法在非越狱机与越狱机上的区别。



除了安装不符合app store审核标准的软件以外(破解软件是通过不了审核的),非越狱机可以遭遇越狱机上所有的威胁。

   总结一下,iOS上IAP内购解锁的方式有以下三种:

--------------------------------------------------------------------------------------------------------------------------------------------------------

      一种是利用IAP流程漏洞,包括伪造购买成功的交易状态,伪造合法收据,伪造app store server,这方面有成熟的利用软件,例如IAP cracker,IAP free,在iOS平台游戏安全再议之八门神器内存修改,IAP Free内购破解的防御一文中有详细介绍。

      一种是通过文档替换或覆盖来解锁,我们知道应用购买前后安装包中的Documents和Library目录发生的变化,就是解锁的内容。因此可以通过对比这两个目录的区别来完成IAP内购破解。也是是本文重点介绍的方式

       一种是通过对已破解(ipa cracker解密后)的mach-O executable文件进行动态调试和静态反汇编逆向分析,还原软件的整体结构,通过对相应的函数进行修改(也是常说的API hooker,malicious code injection),例如商店道具购买函数,任务奖励函数等来实现内购的解锁。这种类型的外挂通常以游戏插件形式提供,一般采用MobileSubstrate框架进行开发。计划下一篇文章介绍。
------------------------------------------------------------------------------------------------------------------------------------------------------------

参考
1. http://blog.sina.com.cn/s/blog_6b9c53390100p8ju.html
2. http://bbs.weiphone.com/read-htm-tid-2762157.html
3. http://bbs.bhgbox.org/forum.php?mod=viewthread&tid=16876
4.http://bbs.bhgbox.org/thread-4-1-1.html
5.http://bbs.bhgbox.org/thread-2490-1-1.html?from=threadlink
6.http://www.cnblogs.com/zhulin/archive/2012/03/26/2417860.html

欢迎讨论
博客地址http://danqingdani.blog.163.com
微博地址:http://weibo.com/tanjiti


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 6
支持
分享
最新回复 (8)
雪    币: 1413
活跃值: (401)
能力值: (RANK:270 )
在线值:
发帖
回帖
粉丝
2
我一直忽略了移动游戏安全这个方向,没想到问题这么多。。
2012-10-17 17:27
0
雪    币: 651
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
  听说这是个妹纸。
2012-10-17 18:00
0
雪    币: 47147
活跃值: (20445)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
4
文章不错,感谢分享!
图片是有些多,我手工将其转到论坛本地收藏了,方便以后整理到精华集中去。
2012-10-31 20:44
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
坛主精神可贵.居然是手动的
2012-11-1 01:41
0
雪    币: 134
活跃值: (84)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
谢谢碳基体大牛分享文章
2012-11-1 03:28
0
雪    币: 123
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
太爽了!!!!
鳄鱼小顽皮爱洗澡我改的是1.9版的,位置有点变化,语句也有点变化,但还是很感谢!
下面为改的语句:
update collectibleinfo set unlocked=1,hasviewed=1

update crankychallengeinfo set available=1

update foodinfo set unlocked=1,hasviewed=1

update hubinfo set bought=1,unlocked=1

update levelinfo set unlocked=1,available=1

update levelpackinfo set unlocked=1,hasplayed=1,hasalerted=0,bought=1
2012-11-3 00:22
0
雪    币: 71
活跃值: (58)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
有玩家,有利益,有交易。
2013-5-6 10:19
0
雪    币: 9
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
如果游戏中游戏金币每一次变化(如买和卖)都要做服务器验证,是不是就没法改了?
2014-11-29 16:57
0
游客
登录 | 注册 方可回帖
返回
//