一次简单steam版权保护移除
前面一段时间我在b站当云玩家的时候看到有个游戏叫大多数挺好玩的, 当我去steam上面找的时候, 发现这款游戏试玩期已经结束了, 网上搜了一下没找到啥盗版, 就自己上手看了一下, 发现基本上无保护, 当时想的是那应该只是套的官方steam验证接口, 事实雀氏如此, 不过听说这个游戏更新了之后, 就加入了很多反作弊内容, 具体我没有去看了, 等以后有需求再去学习吧.
il2cpp
这游戏用的是unity3d的框架, il2cpp的. 用Il2CppDumper进行一些处理.
steam drm 包装器
官方的介绍
Steam DRM 包装器是 Steam 平台的一个重要部分,因为它验证了游戏的所有权,并通过在启动游戏之前启动 Steam,确保 Steamworks 功能正常运作。
Steam DRM 包装器自身并非一个反盗版方案。 Steam DRM 包装器防范的是非常随意的盗版行为(如将所有游戏文件复制至另一台电脑),并进行一些模糊处理,但是蓄意攻击者很容易就可以将其移除。
我们建议使用无法在非法副本上运行的 Steamworks 功能(如在线多人游戏、成就、排行榜、集换式卡牌等)提升您游戏的合法副本的价值。
参见使用 Steam 包装器包装其他 DRM,了解同时使用 Steam DRM 包装器与其他 DRM 或反篡改方案的更多信息。
去除
我们可以看到节区多了一个.bind节区:
如果要手脱壳, 具体去除的细节就是和脱壳类似, 因为后面有专门的工具就不一一赘述了. 具体细节可以参考这个国外的师傅去除32位的过程录的视频
https://www.youtube.com/watch?v=yrrcL8xGPoE
steamless
这是一款专门去除steam 包装器的工具, 可以在github上面找到他
https://github.com/atom0s/Steamless
用这款工具跑一下这个入口exe, 发现.bind节区消失了
我们可以很容易的发现winMain函数
直接跳到了UnityMain.
steam api
上面仅仅只是去除了一个壳, 准确的来说是一个包装器. 下面我们得去除用户代码所包含的验证.
用dnspy打开Assembly-CSharp.dll, 通过符号可以找到steam相关的steamtool类和steammanger类.
把Assembly-CSharp.dll拖进ida中, 对这两个类进行分析.
Unity中的脚本都是继承自MonoBehaviour.
这其中有一些基本回调函数:
Awake:在加载脚本实例时调用 Awake。
update: 如果启用了 MonoBehaviour,则每帧都会调用更新。
start: 在第一次调用任何 Update 方法之前启用脚本时,在框架上调用 Start。
OnEnable: 当对象启用并处于活动状态时调用此函数。
进入ida分别对这些函数下好断点. awake作为最先调用的方法自然是最先断下. 在进行进一步调试的时候可以发现, 我们需要关注以下API:
1 | SteamAPI_RestartAppIfNecessary //检查 Steam 客户端是否正在运行,如果没有运行则启动它 |
要绕过这些API的检测, 可以通过直接更改逻辑来绕过, 但是这些API有些会有一些配置信息的获取可能需要你自己手动设置.
所以我使用更改API的内容的, 就是直接把DLL中的API改成我们自己的API.
直接更改程序逻辑
我这里直接更改程序的控制流, 意思就是跳过SteamAPI不执行.
注意, 基本上所有steamAPI都最好不要执行, 因为我并没有调用SteamAPI.Init函数.
应该调用的第二个 Steamworks 函数是 to SteamAPI.Init()
,这将启动 SteamAPI,并且必须在调用任何其他 Steamworks 函数之前调用。
因为steamAPI都没有执行, 所以我们有些关于获取steam信息的配置需要我们自己手动设置.
SteamTool__Update:
这里的CurLanguage对应的设置就是语言配置, 目前好像只支持中英文.
我们直接跳到LABEL_55对应的汇编处, 就可以将CurLanguage属性设置为1以及isUpdate设置为0, 而开头有一个判断为
如果isUpdate设置为0, 就不会进入获取语言配置的代码块.
在patch进入游戏后, 会有明显提示"重新下载最新包", 应该是某些steam配置没有找到.
根据字符串可以定位到关键地方
找到对应的类, 我们可以看到设置相应回调函数的地方
MenuPanel__InclusionFailure
MenuPanel__ShowPanel
这个应该是判断期限的意思, 这里直接修改控制流就可以直接正常运行了.
APIhook
上面讲的直接更改程序逻辑的方式虽然非常简单, 但是通用性不高(其实是没大哥帮我造轮子. 而采取APIhook, 也就是替换掉dll的方式, 可以绕过更多的游戏, 并且移植简单.
steam_api.dll的生成可以参考https://gitlab.com/Mr_Goldberg/goldberg_emulator这个项目
这个项目可以编译出我们需要的DLL(这个构建雀氏有点折腾人), 但是仍然有一些steam信息配置的API需要我们自己做一些修改, 比如:
Steamworks_NativeMethods__ISteamUtils_GetSteamUILanguage
根据前面的分析, 我们需要让他返回"schinese".
之间修改返回值就可以完成
flat.cpp:
1 | STEAMAPI_API const char * SteamAPI_ISteamUtils_GetSteamUILanguage( ISteamUtils* self ) |
完成dll编译之后替换掉原来的dll就可以进入游戏界面
之前的期限检查貌似和steam api无关, 所以这里不多说了(打过硬件断点去回溯写入地址, 但是居然断到了unityplayer.dll里面, 而api moitoring中检测不到unityplayer.dll调用steam api.
api moitoring
这里推荐一下一个API检测工具: api moitoring, 这个工具可以监控特定dll中的api调用情况, 这样我们就可以知道这个程序用了那些steamapi了, 再根据自己的需求更改相应的api再编译就可以了.
相关的文档
steam drm
https://partner.steamgames.com/doc/features/drm
steam api
https://partner.steamgames.com/doc/sdk/api
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !