某三字游戏公司启动器的简单分析+过程
简单解析HYP启动器,以方便后续的逆向分析。
1. 观察启动器和启动器文件寻找分析思路
直接逆向可能会跳到思维惯性的坑里,所以我们可以先来根据启动器和启动器的文件和文件结构来进行推测,方便在逆向的时候更快得出我们想要的代码和实现。
1.1 观察启动器安装目录进行分析
来到启动器的安装位置,直接观察程序文件夹结构和文件进行猜测:
📁 HYP 使用CN版演示
📁 1.4.5.222 启动器版本文件夹
📁 bearer Qt 网络模块
📦 qgenericbearer.dll
📁 ico 一些游戏图标
🖼️ bh3_cn.ico
🖼️ hk4e_cn.ico
🖼️ hkrpg_cn.ico
🖼️ nap_cn.ico
📁 imageformats Qt 图像处理
📦 qgif.dll
📦 qicns.dll
...
📁 platforms Qt 平台实现
📦 qwindows.dll
📁 resources CEF 资源文件夹
📁 locales
📄 af.pak
...
📄 chrome_100_percent.pak
📄 chrome_200_percent.pak
📄 feapp.pak 启动器的资源文件?
📄 resources.pak
📁 styles Qt 页面样式
📦 qwindowsvistastyle.dll
📦 7z.dll 7z
🖥️ 7z.exe 7z
⚙️ app.conf.dat 启动器配置文件
📦 Astrolabe.dll 未知
📦 chrome_elf.dll CEF
📦 concrt140.dll MSVC 运行库
🖥️ crashreport.exe 崩溃日志上报用程序
📦 d3dcompiler_47.dll DirectX 11 组件
📦 HoYoDeviceFpSDK.dll 获取设备指纹SDK
🖥️ hpatchz.exe 游戏更新用工具
📦 HYBase.dll 基础框架?
📦 HYCommon.dll 公共工具?
📦 HYContainer.dll 启动器容器管理?
📦 HYContainerPlugin.dll 容器管理扩展?
📦 HYEngine.dll 引擎核心?
📦 HYGui.dll 用户页面?
📦 HYLauncher.dll 启动器核心功能逻辑库?
📦 HYLauncherPlugin.dll 功能扩展?
🖥️ HYP.exe 启动器主程序
🖥️ HYPHelper.exe 辅助服务程序?
📦 HYQComm.dll 未知 网络相关?
📦 HYSysTrayPlugin.dll 系统图标插件
📦 HYUiKit.dll 界面组件?
🖥️ HYUpdater.exe 启动器自更新程序
📦 HYUpdaterPlugin.dll 自更新扩展
📄 icudt71l.dat ICU
📄 icudtl.dat ICU
🖥️ launcher.exe 启动器兼容性入口程序
📦 libcef.dll CEF
📦 libcrypto-1_1-x64.dll OpenSSL 密码学库
📦 libEGL.dll OpenGL ES 接口库
📦 libGLESv2.dll OpenGL ES2.0 兼容层
📦 libssl-1_1-x64.dll OpenSSL HTTPS库
📦 MiHoYoMTRSDK.dll Mi Trace Reporter SDK?
📦 msvcp140.dll MSVC 运行库
📦 msvcp140_1.dll MSVC 运行库
📦 msvcp140_2.dll MSVC 运行库
📦 msvcp140_atomic_wait.dll MSVC 运行库
📦 msvcp140_codeecvt_ids.dll MSVC 运行库
📦 QCefView.dll CEF相关的库
📦 Qt5Core.dll Qt5
📦 Qt5Gui.dll Qt5
📦 Qt5Networl.dll Qt5
📦 Qt5Widgets.dll Qt5
📄 snapshot_blob.bin CEF
📦 sophon.dll 未知
📦 telemetry.dll 数据统计上报
📄 v8_context_snapshot.bin CEF
📦 vccorlib140.dll MSVC 运行库
📦 vcruntime140.dll MSVC 运行库
📦 vcruntime140_1.dll MSVC 运行库
📦 vk_swiftshader.dll Vulkan 兼容层
⚙️ vk_swiftshader_icd.json 驱动配置文件
📦 vulkan-1.dll Vulcan
📦 xyvodsdk.dll 视频相关SDK?
📁 games 游戏默认安装目录
📁 GenShen
...
📁 Honsan
...
📁 Hontie
...
📁 Zero
...
⚙️ config.ini 全局配置文件?
🖥️ launcher.exe 启动器兼容性入口程序
🖥️ uninstall.exe 卸载
🖥️ vc_redist.x64.exe MSVC 运行库安装程序
根据一些经验,我们可以很猜测HYP使用了Qt5作为基础框架,并使用CEF作为前端网页框架,并且使用.dll
实现模块化,使用插件实现功能解耦。
不过存在一些尚未清楚用途和功能的库,这时候我们可以利用搜索引擎直接搜索来推测大概的用途:
📦 sophon.dll 某环智能分析工具
📦 xyvodsdk.dll 某域云视频SDK
📦 QCefView.dll 基于QWidget集成CEF的Web View 组件
其中 Astrolabe.dll
的功能当时还不知道,不过在查看启动器内有什么线索时,我在点击启动器的设置-关于页面内的查看客户端日志选项后发现打开的文件夹路径为C:\Users\VTS\AppData\Roaming\miHoYo\HYP\1_1\modules\astrolabe\Log
,所以推测Astrolabe.dll
是日志记录工具。
如果不熟悉其他的一些库(如telemetry.dll
),最好是先使用浏览器搜索一下,实在不清楚的只能逆向分析来看了。
还存在一个似乎是HYP的资源文件的文件feapp.pak
,推测是一个压缩文件,使用hashcat
验证后确实是一个PKZIP压缩文件,并且有密码,暴力破解还是太吃时间了,所以看能不能在后续的逆向分析中找到密码。
我们已知QCefView是一个基于QWidget集成CEF的Web View 组件,并且feapp.pak
的位置在CEF资源文件夹下,所以直接去看QCefView的官方文档有什么线索:添加本地Zip文件到URL的映射
果然还是有线索的,从QCefView的官方文档得知这个文件应该是启动器所需的WebApp资源,应该是前端实现相关的资源文件,不过暂时不知道如何解压查看,所以暂时先跳过。
得出结论,HYP采用Qt5作为基础框架,前端通过QCefView加载并运行本地打包的WebApp资源,使用.dll
实现模块化开发,使用插件实现功能解耦,并使用sophon.dll
作为智能分析工具,使用xyvodsdk.dll
作为云视频SDK,使用Astrolabe.dll
作为日志记录工具。
1.2 根据启动器的配置和数据存储猜测一些便于逆向分析的思路
前面我在启动器设置-页面中的查看客户端日志得知了启动器存放配置和数据的路径,路径为C:\Users\VTS\AppData\Roaming\miHoYo\HYP\1_1
,所以尝试在这个路径下的文件夹中寻找一些便于逆向分析的思路和方式。
📁 cache
📁 crash
📁 data
📁 fedata
📁 fepak
📁 logs
📁 modules
查看各个文件夹后,筛选出应该有关键信息的文件夹:
📁 data
📁 fedata
📁 modules
1.2.1 data文件夹
📁 data
📄 appstore.dat
📄 appstore.dat.crc
📄 gamedata.dat
📄 gamedata.dat.crc
📄 notifications.dat
📄 notifications.dat.crc
📄 usersettings.dat
📄 usersettings.dat.crc
只看文件命名,这些文件都是启动器的配置文件+每个配置文件的校验文件,而且可以知道这里没有什么我们需要的信息,所以我们可以跳过这个文件夹。
1.2.2 fedata文件夹
📁 fedata
📁 blob_storage
📁 Cache
📁 Code Cache
📁 databases
📁 GPUCache
📁 IndexedDB
📁 Local Storage
📁 Network
📁 Sevice Worker
📁 Session Storage
📁 WebStorage
📄 DevToolsActivePort
📄 LocalPrefs.json
📄 Visited Links
这结构就非常明显就是浏览器的数据存储文件夹,也就是启动器的WebApp使用的浏览器数据存储文件夹,并且看到了DevToolsActivePort
这个文件,且我们已知HYP使用了QCefView作为前端网页框架,所以这个文件应该是QCefView的调试端口文件,也就代表有办法直接调试前端的WebApp了。
1.2.3 moudles文件夹
📁 modules
📁 astrolabe
📁 sophon
📁 telemetry
观察这些文件夹下的内容,可以印证之前的推测,不过具体是干什么用的还是需要逆向分析。
到这里我们已经猜测出了一些便于逆向分析的思路,但是这些思路都是基于启动器的文件结构和文件名等精细猜测,所以下一步便是尝试逆向分析这些文件,看看有没有什么线索。
2. 简单逆向分析
2.1 确认启动器WebApp使用的浏览器的调试端口并启用调试
直接打开,确认端口为9222,且使用的是QCefView作为前端网页框架,那就可以使用DnSpy直接调试启动器主程序并添加参数-remote-debugging-port=9222
。
启动程序后,在浏览器中打开localhost:9222
,就可以看到启动器的调试页面了。
" alt="" target="_blank" rel="noopener noreferrer nofollow" />
这个时候实际上已经可以不用关注之前发现有密码的feapp.dat
资源文件,直接去DevTools中查看即可。
具体的调试就看各路大神发挥了,后续我也会写一篇关于前端实现的分析。
2.2 分析app.conf.dat
解密app.conf.dat
的方法已在我的第一个帖子获取HYP(XX游启动器)的基本信息中详细解释思路和解密代码,这里就不再赘述了。
可以看到app.conf.dat
的可读字段结构:(隐藏的字段可以自己去解密看)
{
"_meta_ver": "1.4.5.222",
"App": {
"Region": "cn",
"Language": "zh-cn",
"Company": "miHoMo",
"Product": "HYP",
"ProductDisplayName": "\u7c73\u54c8\u6e38\u542f\u52a8\u5668",
"Standalone": false,
"Channel": "1",
"SubChannel": "1",
"LauncherId": "jGHBHlcOq1",
"CPS": "hyp_mihoyo",
"UAPC": "",
"PrimaryGame": "hyp_cn",
"ClientEnv": "production",
"ClientPreview": false,
"EnableBetaLogin": false,
"WebApiBaseUrl": "https://hyp-api.mihomo.com/hyp/hyp-connect",
"ThirdPartyLogin": null,
"StartMenuDirName": "\u7c73\u54c8\u6e38\u542f\u52a8\u5668"
},
"FE": {
"BridgeName": "HoYoPlayClient",
"PackageKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"Launcher": {
"LogDebugMode": false,
"PlatApp": "ddxf5qt290cg",
"Win7PatchUrl": "https://launcher-webstatic.mihomo.com/launcher-public/2023/06/08/fac986b82c31f75c0820803748a74af4_4452073143311314458.zip",
"Win7PatchMd5": "fac986b82c31f75c0820803748a74af4",
"Win7PatchEnable": true,
"LoginMode": 3,
"EnableMultiAccount": false
},
"ABTest": {
"Url": "https://data-abtest-api.mihomo.com/data_abtest_api/config/experiment/list"
},
"Box": {
"Url": "https://sdk-static.mihomo.com/combo/box/api/config/plat-launcher/plat-launcher"
},
"H5Log": {
"Url": "https://h5log-api-dualstack.mihomo.com/common/h5log/log/batch?topic=h5log-plat-launcher"
},
"DataUpload": {
"Url": "https://sdk-log-upload.mihomo.com/sdk/dataUpload"
},
"APM": {
"AppId": "plat_Windows_xxxxxxxxxx",
"AppKey": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
"Updater": {
"AppId": "xxxxxxxxxx",
"AppKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"ReportUrl": "https://api-takumi.mihomo.com/ptolemaios_api/api/reportStrategyData"
},
"Epic": {
"EnablePay": false,
"ProductId": "",
"SandboxId": "",
"DeploymentId": "",
"CredentialsId": "",
"CredentialsSecret": ""
}
}
app.conf.dat
主要还是配置启动器的各类参数:(这里只写出一部分字段)
基础配置(App):
字段 |
作用 |
Region |
运行区域 |
ProductDisplayName |
启动器显示的名称 |
EnableBetaLogin |
是否启用登录测试 |
PrimaryGame |
运行区域 |
LauncherId |
启动器ID |
WebApiBaseUrl |
后端API地址 |
前端配置(FE):
字段 |
作用 |
BridgeName |
QCefView桥接对象名称 |
PackageKey |
前端资源包密钥 |
有了PackageKey,就可以通过解密feapp.dat
来获取前端资源包。
2.3 分析feapp.dat
有密码了直接解压就好了,看了一下确实是前端的实现和一些资源文件,前端实现会单独写一篇,这里就不再赘述了。
2.4 分析 Qt5 、CEF 和 QCefView 使用的版本
2.4.1 Qt5版本
Qt5的版本很容易知道,直接拖到Binary Ninja中搜索字符串5.
就行了,得知Qt5的版本为Qt 5.15.17 (x86_64-little_endian-llp64 shared (dynamic) release build; by MSVC 2022)
,这个版本时Qt的商用版。
2.4.2 CEF版本
CEF的版本相对困难,不过已经知道使用了开源的QCefView库,那么可以直接去看源码,不过我发现QCefView的协议是LGPL-2.1
,所以某三字游戏公司应该是没有修改关于QCefView的源码,所以可以直接编译一份,然后将编译后生成的库文件中搜索编译时使用的CEF版本的字符串,应该能找到CEF的版本会在什么地方。
不过编译完后,发现文件结构和HYP的不一样,估计是之前版本呢的QCefView,不过不影响。编译后生成的文件有一个程序叫CefViewWing.exe
,不过没有在HYP的程序安装目录发现这个程序,同时QCefView的协议是LGPL-2.1
,所以继续查看QCefView的源码。
在QCefView的解决方案中找到了CefViewWing这个项目,右键打开文件夹所在位置,向上两级找到了CefViiewCore的源码,CefViewCore的协议是MIT
,所以HYP大概是修改了CefViewWing.exe
的实现,或者直接修改了CefViewCore的实现,不过仍不知道CefViewWing.exe
具体是哪个程序,所以想到了一个简单的办法:运行QCefViewTest.exe
,看看除了QCefviewTest.exe
之外CefViewWing.exe
有没有被运行,如果运行了,那么在运行HYP时,除了主程序外的程序就是要找的""CefViewWing.exe"
。
为什么要找这个程序呢?因为这个程序是连接Web端和Qt端的关键桥梁,且是CEF浏览器的宿主。
测试后发现,HYPHelper.exe
实现了"CefViewWing.exe"
的功能。直接使用Binary Ninja打开自己本地编译的CefViewWing.exe
,并搜索CEF的版本号,找到D:\\QCefView-main\\.build\\windows.x86_64\\_deps\\cefviewcore-src\\dep\\cef_binary_126.2.18+g3647d39+chromium-126.0.6478.183_windows64\\libcef_dll/ctocpp/ctocpp_ref_counted.h
,提取关键字符串ctocpp_ref_counted
并在HYPHelper.exe
的字符串内搜索,确认了CEF的版本为cef_binary_102.0.10+gf249b2e+chromium-102.0.5005.115_windows64
。
2.4.3 QCefView版本
具体的版本很难确定,不过可以通过对比最新的QCefView的编译后的QCefView.dll
中函数的区别大概判断一下:
最新提交的QCefView的JS调用C++的函数名为invoke
,不过在HYP所使用的QCefView中的函数名为invokeMethod
,查看历史提交后,确定HYP所使用的QCefView的版本一定在2024年12月之前。继续翻看历史提交,得知在2023年5月后QCefView添加了devtools方法,而HYP所使用的QCefView是有devtools方法的,所以HYP所使用的QCefView版本一定在2023年5月之后。这个启动器公布似乎是在2024年七月左右,算上开发时间,可能是2024年年初或者2023年年末的某个版本。
3. 总结
-
技术框架
- 后端框架: Qt5.15.17商业版
- 前端框架: CEF 102.0.10+gf249b2e+chromium-102.0.5005.115
- 前端集成: QCefView 未知版本
- 编译方式: Jenkins + MSVC
- 开发平台: GitLab
使用Qt+QCefView实现启动器,避免了使用QtWebEngine(QtWebEngine bug真的多),方便开发和调试;
-
安全机制(没什么用)
- 加密配置文件
app.conf.dat
- 加密WebApp静态资源
feapp.dat
- 配置文件
(appstore.dat等)
带有CRC校验
-
逆向的突破口
- 添加启动参数
-remote-debugging-port=9222
到HYP.exe
直接使用CEF调试端口调试前端实现
- 没有混淆关键的库
4. 后记
写这个帖子的时候地震了给我吓一跳...
- 现在HYP还没有实现启动器内登录,不过在
app.conf.dat
下看到了EnableBetaLogin
字段,这个字段是false
,所以HYP目前可能在测试版本已经有登录了,而且还存在EnableMultiAccount
字段,所以后续会有多账号登录吧...
- 后面可能会先研究HYP的前端实现,后端就简单很多了,直接读伪代码就可以了,如果有需要我也会写一个详细的帖子来分析后端实现。
- 这个帖子我写的可能有点乱或者有些地方没有解释清楚,如果有问题,欢迎留言,我会尽量及时回复。
- 这三字游戏公司把js用到的一些库的协议放在了加密的
feapp.dat
中......