试图欺骗游戏的N3WB13

一切始于我的女友向我挥舞着手机,然后大声喊道“瞧瞧我对这件事的看法”。 “ THIS” == 2048,是一款益智游戏,一年半以前就非常有名。

因此,我拿起自己的Macbook并开始玩,确保我要去拥有她。 所以我惨败了:’(现在,我只想操心这场比赛并获得最高分。

记忆编辑

我想到的第一件事是,分数位于游戏记忆的某个位置,也许我可以覆盖它。 做一些研究(搜索周围的东西)时,我偶然发现了一个非常出色的开源软件:Bit Slicer。 正是我所需要的,它自己作为“ macOS通用游戏培训师”出售。

您要做的就是搜索所需类型的值,在我的情况下为Int32。 当时我的分数是216:

找到1702个内存地址,其中包含216个值。 太多了,您需要缩小搜索范围,而这样做需要稍微改变一下演奏的乐谱的值,并在第一个1702个地址中搜索哪个乐谱更改为您的新乐谱。 就我而言,我的新分数是240。

现在它只显示2个地址,也许是您在问为什么两个而不是一个,这可能是因为有些冗余,一个用于将数字保存为Integer,另一个用于保存String的值,诸如此类。 现在,我只需要将这两个编辑为1337。

游戏并未更改其值,但是如果您在其中进行了某些操作,它将更新该值。

是的,我的BEST真的很棒

不错! 我给我的女朋友看,她就像“你刚刚编辑记忆对吗? 卷起眼睛 ”。 但这太简单了:/

编辑保存

之后,我意识到游戏在关闭时会保存最后一个状态,这使我尝试找到保存状态的位置并进行编辑。 另一轮Google向我展示了所有程序的支持文件都在~/Library/Application Support/目录中。 不幸的是,该游戏不存在,也没有该软件的bundleId( com.codinn.2048在该应用的Info.plist中找到。 更多的Google告诉我,某些Apps使用“容器”,这是OS X应用的某种沙盒,位于~/Library/Containers/
在那里,我找到了一个带有游戏的bundleId的目录,以及一个包含游戏状态的plist: ~/Library/Containers/com.codinn.2048/Data/Library/Preferences/com.codinn.2048.plist 。 在Xcode中打开:

“ gameState”的值是:

 {"grid":{"size":4,"cells":[[{"position":{"x":0,"y":0},"value":4},{"position":{"x":0,"y":1},"value":8},{"position":{"x":0,"y":2},"value":32},{"position":{"x":0,"y":3},"value":8}],[{"position":{"x":1,"y":0},"value":8},{"position":{"x":1,"y":1},"value":16},{"position":{"x":1,"y":2},"value":2},{"position":{"x":1,"y":3},"value":4}],[{"position":{"x":2,"y":0},"value":2},{"position":{"x":2,"y":1},"value":8},null,{"position":{"x":2,"y":3},"value":2}],[{"position":{"x":3,"y":0},"value":4},{"position":{"x":3,"y":1},"value":2},null,{"position":{"x":3,"y":3},"value":2}]]},"score":1337,"over":false,"won":false,"keepPlaying":false} 

它不过是带有图块的值和位置的json。 所以我只编辑此内容,瞧,对吧? 否:/由于某些原因,可能是因为该应用程序是沙盒的,即使我编辑了它,gameState也不会改变。 我确信这一定是绕过和编辑此方法的方式,我会在将来尝试。

反转和编辑游戏

所以现在怎么办 ? Errrrrr,我可以编辑游戏的二进制文件以取得更多分,依此类推。 让我们开始吧!

首先,让我们在Radar2上打开它-不,我不是想炫耀不使用GUI工具,r2是免费和开源的,而且我只是一个没有钱购买IDA Pro或Hopper的学生。

 $ sudo r2 -w /Applications/2048+.app/Contents/MacOS/2048+ Password: arw 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020160000010000000000000000000000000000000000000000000000000000000000000000000000 -- You see it, you fix it! [0x100001620]> 

-w用于编写。 您要做的第一件事是aaa然后分析所有功能和名称。 r2有一种非常酷的方式来命名命令,它只是描述的前几个字母,第一个a表示“ analyse”,第二个表示“ all”,第三个表示“ autoname”。 r2还有一个非常有用的帮助(双关语不是故意的)界面,只需在命令后加上问号,它就会显示所有相邻项,例如:

因此,在运行aaa ,您要列出所有功能。 只需运行afl ,它将显示大量功能,如果在命令后加上~ ,它将对其进行grep。 我想搜索二进制文件的开头,所以我做了afl~main ; afl~entrypointafl~begin afl~start ,什么也没有(请注意,这是区分大小写的)。

我回到了基础知识,并在二进制文件中添加了strings ,这真的使我“ WTF”吗? :它显示了很多webView字符串。 所以,是的,那只是一个Web应用程序-‘

糟糕的实现之后,我只是在应用程序中打开“ Resources”目录,这真是该应用程序的所有html / js / css,实在令人沮丧。

 $ ls 
CONTRIBUTING.md README.md index.html sound LICENSE.txt fontello js style

这真的很容易编辑。
在文件Resources/2048/js/game_manager.js的第188行中,当两个图块合并时,游戏在其中计算新值,只需将前一个值乘以2。

 var merged = new Tile(positions.next, tile.value * 2); 

因此,只需将2更改为9999即可。 这就是美丽。

一切顺利,一切都很好。 但是真的很有趣。 现在我是全球排名第一的^^

比光速快

FTL是一款类似胭脂的独立游戏,具有太空飞船和不折不扣的战斗。 很多的乐趣,但是真的很努力(我从未击败过最后一个老板)。 因此,让我们摆脱困境。

记忆力不佳

我从与2048+相同的内存编辑开始。 您确实可以编辑所有变量,您的生活,敌人的生活,金钱等。 相同的程序,相同的结果,令人讨厌。

注意那些数字不适合盒子

编辑保存

但是游戏更加复杂,因此您必须不断编辑自己的生活,不能编辑伤害(因为您不知道要搜索什么),这很无聊。

我尝试的第一件事是编辑保存游戏,因为我在上一个游戏中失败了。 保存游戏位于~/Library/Application Support/fasterthanlight ,不在Containers ,因此没有沙箱,不错。 文件 :

 $ ls 
ae_prof.sav continue.sav prof.sav settings.ini

settings.ini只是一个包含游戏,声音,全屏等配置的txt文件。.sav文件是保存/统计/成就。 那么,wtf是吗?

 $ file continue.sav 
continue.sav: data
$ xxd continue.sav 0000000: 0900 0000 0000 0000 0100 0000 0100 0000 ................ 0000010: 0400 0000 1600 0000 0300 0000 0b00 0000 ................ 0000020: 5468 6520 4b65 7374 7265 6c10 0000 0050 The Kestrel....P 0000030: 4c41 5945 525f 5348 4950 5f48 4152 4401 LAYER_SHIP_HARD. 0000040: 0000 0000 0000 0003 0000 000a 0000 0066 ...............f 0000050: 6972 6564 5f73 686f 7405 0000 0006 0000 ired_shot....... 0000060: 0068 6967 686f 3201 0000 000c 0000 0075 .higho2........u 0000070: 7365 645f 6d69 7373 696c 6502 0000 0010 sed_missile..... 0000080: 0000 0050 4c41 5945 525f 5348 4950 5f48 ...PLAYER_SHIP_H 0000090: 4152 440b 0000 0054 6865 204b 6573 7472 ARD....The Kestr 00000a0: 656c 0700 0000 6b65 7374 7261 6c03 0000 el....kestral... 00000b0: 0005 0000 0068 756d 616e 0700 0000 4359 .....human....CY 00000c0: 2048 656e 6705 0000 0068 756d 616e 0600 Heng....human.. 00000d0: 0000 4772 6163 6965 0500 0000 6875 6d61 ..Gracie....huma 00000e0: 6e06 0000 0041 7472 6579 7501 0000 00c2 n....Atreyu..... ... ETC

那是专有的文件格式,所以我必须尝试了解我要编辑的值在哪里。 我使用了HexFiend应用程序,它是Mac的十六进制编辑器,也是开放源代码,实际上Bit Slicer使用了部分代码。

首先,我要编辑我有多少废品(这是游戏的钱)。 如果我使用BitSlicer进行此操作,则必须能够更改该值以缩小研究范围。
当时我的钱是10,在hexa中是0xa ,所以只需搜索:

0xa是一个很糟糕的值,因为它看起来很多,而不是内存中的很多,而是很多。 在文件的开头,它具有一些与我的船相匹配的信息,例如名称,船员,因此我认为第一个0A是金钱(是的,我是个猜测的骑士)。 只需将第一个外观编辑为FFFF (65535),保存它,然后砰!

哦! 另一个猜测是文件continue.sav ,其他文件具有游戏的其他状态,得分,成就。 我可以对二进制进行反向操作以找到更多的值,并且更加精确,但这将需要几天的时间。

反转二进制

我想做的另一件事是变得无敌,而无需一直手动编辑内存。 r2时间!

游戏的二进制文件位于/Library/Application Support/Steam/steamapps/common/FTL Faster Than Light/FTL.app/Contents/MacOS/FTL因为它在Steam上。 首先,我检查了它是否是WebApp,但不是:’(

在r2上运行并分析所有功能需要花费一些时间,然后我开始查看带有“损坏”功能的功能。

 [0x1000f9959]> afl~Damage 0x100018382 1 8 sym.Collideable::DamageBeam 0x10001838a 1 8 sym.Collideable::DamageArea 0x100018392 1 8 sym.Collideable::DamageShield 0x1000183bc 1 6 sym.Targetable::DamageTarget 0x1000184f2 1 60 sym.Projectile::SetDamage 0x10001a9b8 3 168 sym.IonDrone::GetRoomDamage 0x10001b778 3 35 sym.CrewDrone::ShipDamage 0x10001cb80 1 14 sym.CrewMember::GetDamageMultiplier 0x10001cbe2 1 83 sym.CrewMember::GetRoomDamage 0x10001ce52 1 14 sym.BoarderDrone::GetDamageMultiplier ... ETC ... ETC 

在分析了几个小时的功能之后,它们全部还是真的没什么特别的,或者由于一些非常奇怪的说明而无法进行编辑,例如:

确实,我不知道这些指令的作用,并且我已经搜索过,因为它是带有double / float类型的。
所以我有一个主意,该船能够躲避导弹和新芽,它必须具有计算该功能的功能。

 [0x1000f8104]> afl~Dodge 0x10001839a 1 8 sym.Collideable::GetDodged 0x1000f8828 19 340 sym.ShipManager::GetDodgeFactor 0x1000f9906 1 47 sym.ShipManager::GetNetDodgeFactor 0x1000f9935 1 18 sym.non_virtualthunktoShipManager::GetDodged__ 0x1000f9948 20 396 sym.ShipManager::GetDodged 0x100112c18 2 27 sym.ShipSystem::GetEngineDodgeFactor 0x1001137d0 8 159 -> 105 sym.EngineSystem::GetDodgeFactor 

并查看sym.ShipManager::GetDodged

 [0x1000f8104]> s sym.ShipManager::GetDodged [0x1000f9948]> VV 

s表示“搜索”,而VV表示进入可视模式。 p在可视模式下更改可视化的类型。

功能开始

功能结束

最后(第二次打印),在0x1000f9ac6它只是将寄存器bl移到了eax并返回了它,因此bl必须是持有该寄存器的寄存器,以防船舶能够躲避。 然后在0x1000f995b (第一次打印) 0x1000f995b 1移动到bl并跳转到函数的末尾。 现在,第一个跳转0x1000f9959是一个jne (不相等跳转),它检查最后一个cmp 0x1000f995是否成功,是否成功跳转到0x1000f9962 ,否则不只是继续执行。 好吧,导致0x1000f9962的执行链确实令人困惑,它进行了很多比较和检查,以确定它将bl 0x1000f9962 1还是0,所以我只想函数返回1并始终闪避。 编辑0x1000f99590x1000f9959一个nop (什么都不做的指令)代替jne ,它将导致函数始终将mov 1移至bl ,将jmp移至最后。 让我们这样做:

 [0x1000f9948]> s 0x1000f9959 [0x1000f9959]> wa nop Written 1 bytes (nop) = wx 90 

导致 :

现在,如果您查看0x1000f995a ,它将显示“ invalid”,因为作为nop十六进制表示形式的90不会覆盖所有jne hexa 7507 。 让我们只剩下一点,这一切都很好,也许有更好的方法可以做,但是操吧。

 [0x1000f995b]> s 0x1000f995a [0x1000f995a]> wa nop 

现在它总会躲闪东西,很好! 超级忍者模式(:SUPER NINJA MODE(:您可以编辑游戏中想要的任何内容,但这是我发现变得无敌的最简单方法)。

脚本编写

击败游戏的另一种方法是处理大量伤害,但是编辑装配很难,而编辑内存则不然。 但是如何使事情变得容易呢? 好吧,BitSlicer有一个可用于脚本编写的Python Python库,yaaaaay!

第一件事是找到敌人生命的记忆地址。 进行相同的搜索,找到地址后,右键单击它并单击“ Watch Write Accesses”,现在每次在该地址中写入一些指令时,我们都会看到。 取消暂停游戏并攻击您的敌人,然后再次暂停以查看在该敌人的生活地址中写了两条指令,将这两条指令添加到列表中。 一条指令进行了数百次写入,而另一条指令受到了您的攻击,请在调试器上以较少的写入次数打开一条指令,然后查看Symbol指向Ship::ProjectileStrike(int,float)的功能,该函数确实会损坏。

现在分析程序集: mov [rdi+0x70], eax[rdi+0x70]是保存敌人生命的寄存器,我们要对其进行编辑的寄存​​器存储在0xD642 ,该值不变,因此我制作了该脚本:

全部评论,将其添加到BitSlicer中,对敌人造成一些伤害以获得他的生命地址,并使用cntrl+a杀死它ˆ-ˆ

总结了在离线游戏中作弊的所有方法,我正在对在线游戏进行一些研究并逆转其协议,但这需要时间。

ty!