巧可甜恋的补丁安装器安装交互为何如此反人类

逆向工程 算法
138 编辑于

为什么这个补丁器反人类

0. 这个程序实际做的事

安装器的工作分两段:先校验游戏目录,再把 7 个补丁文件覆盖进去。业务代码集中在 4 个函数里:

WinMain(流程)

sub_401460(消息表)

sub_401780(目录校验)

sub_401BA0(安装)

补丁数据拖在 exe 尾部,从 0x60000 开始,没有压缩、加密或差分

难用的原因都在产品逻辑上:目录要靠手选、安装不可重入、失败不写日志、错误文案与真实原因脱节。下面按影响排序逐条给证据。

1. 问题清单

# 问题 严重度 关键证据
F1 从不自动找游戏目录,浏览框从 C:\ 起步 P0 sub_401780.c:837 起;初始路径 L"C:\\"
F2 “已打过”就拒绝重跑,无备份无回滚 P0 sub_401780 魔数 2 分支;WinMain 静默退出;sub_401BA0 只写不备份
F3 错误提示与真实原因无关 P0 摘要不匹配也报 “is not installed in the selected folder”;安装失败只剩 “for some reason”
F4 版本兼容只查 7 个文件里的 1 个 P1 sub_401780 只碰 data01100.arc;安装循环不读旧文件
F5 界面文案锁死英文,多语言表没用上 P1 .c:220.c:1640-1641.c:741-742
F6 用互斥体猜进程状态,双开时无提示 P1 WinMain 两个 CreateMutexasm:0x402A38
F7 选目录时点“取消”还要再确认一次 P2 sub_401780 取消分支;asm:0x401A3D-0x401A4A
F8 首次安装问 “Do you want to update?”,默认按钮是 No P2 WinMain.c:1673;按钮组合 0x124
F9 数据偏移写死 0x60000,找不到就报“安装程序可能损坏” P2 .c:1116-1118;文案 0x4114B0
F10 677 MB 全量整包覆盖,无差分 P2 sub_401BA0 索引循环;文件表见 patch_report.md
F11 错误无错误码、无日志,只有 OK 按钮 P2 .c:768/774(0x40/0x30 图标)

2. 逐条展开

F1 找目录靠手选,起点还是 C:\

sub_401780.c:837)对目录的“识别”只有三步:弹 SHBrowseForFolderW,拼 <所选目录>\data01100.arc,检查文件存在并比对摘要。初始路径写死为 C:\

c
sub_402CF0(v17, L"C:\\");

导入表里没有任何 Reg* API,也没有 Steam libraryfolders.vdf 相关读取,shell 相关只有 SHBrowseForFolderWSHGetPathFromIDListW

manifest 还要求 requireAdministrator。于是用户先过 UAC,再从 C:\ 逐级点到 Steam\steamapps\common\...,点错版本还会收到 F3 那条误导文案。

F2 单向状态机:打完就锁死

sub_401780 只认两个摘要:

摘要 含义 结果
44971AEE617DFCB0 原版 data01100.arc 放行,随后弹 “Do you want to update?”
84AD2F9C3C3EC4F2 补丁后 “The patch has already been applied.”,返回 0x80000009

装完后 data01100.arc 的摘要变成魔数 2,这个 exe 不会再处理任何文件。安装中断后重跑会被拒,残留的 .tmp 和部分覆盖没有入口修复;想装到第二份拷贝或 Steam 换盘后的新路径同样被拒。sub_401BA0 全程只写 .tmpMoveFileExW 覆盖,不产生任何备份文件。

Steam 若把文件校验还原回原版,摘要回到魔数 1,安装器又允许再打。能走的只有“原版到补丁版”这一条路,失败态没有恢复入口。

F3 报错与实际原因对不上

sub_401780 对两种失败给同一句文案:

  1. 文件不存在,返回 0x80000003,报 "'Amairo Chocolate' is not installed in the selected folder."
  2. 文件存在但摘要是第三种,比如日文版或别的版本,返回 0x80000008,报同样一句。

版本不对被说成“没装”,用户会反复重选目录。

安装阶段(sub_401BA0)的错误文案更少:.rdata 0x4113F0 的 "Installation cannot be performed for some reason." 和 0x4114B0 的 "The installation program may be corrupted."。没有错误码、没有指出哪个文件、没有日志。

F4 七个文件只校验第一个

安装器覆盖 7 个文件,安装前只检查 data01100.arc 的摘要。sub_401BA0 的安装循环从头到尾不读旧文件内容,写完后用 BGI.hvl 清单核对的摘要来自刚写进去的新内容。

这套校验能发现拷贝损坏,发现不了目标目录是否配套版本。其余 6 个 arc 版本不匹配时,安装器照样覆盖并弹“安装完成”。

F5 文案锁死英文,多语言表形同虚设

消息表确实存在:sub_401460 每个消息 ID 存 4 个指针,按 v5[dword_415018] 取值(.c:741-742),.rdata 0x411AC8、0x411AF0、0x411B18 分别有繁体、简体、英文标题。

dword_415018.c:220 初始化为 2,WinMain.c:1640-1641)又写了一遍:

c
GetSystemDefaultLangID();   // 返回值被丢弃
dword_415018 = 2;           // 始终选英文槽位

全程序只有这两处赋值,运行时始终为 2。中文用户看不到界面语言切换入口。

F6 用互斥体猜进程状态,双开时无提示

WinMain 创建两个互斥体:

text
"Updater for AmairoChocolate is executing."                    // 防自己双开
"Buriko General Interpreter for AmairoChocolate is executing." // 假定游戏在跑时会创建同名互斥体

游戏检测依赖 BGI 引擎使用同名互斥体。引擎改版、名字变化、兼容层启动都会让检测失效;反过来,同名互斥体被无关进程占用时,会误报 "The update cannot be performed because the game or installer is running.",文案自己也分不清是游戏还是安装器。

第一把互斥体创建失败(已有安装器在跑)时,WinMain 直接跳到清理退出(asm:0x402A38jne 0x402C47),连提示框都不弹。第二次双击后程序闪现即退,用户得不到任何反馈。

F7 取消选目录后还要再确认一次

选目录对话框点“取消”,sub_401780 的取消分支(asm:0x401A3D-0x401A4A)先弹一次确认:

c
v15 = sub_401460(4);       // "Cancel the patch installation."
sub_401650(v15);
return -2147483642;

用户已经表达过取消意图,程序再用一个 OK 框要求确认,没有给出任何后续选择。

F8 首次安装问“是否更新”,默认按钮是 No

WinMain.c:1673)用 0x124MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2)弹 “Do you want to update?”(0x4119CC)。首次安装的用户还没装过任何版本就要回答“要不要更新”,且默认焦点在 No 上,需要先看懂再手动选 Yes。

F9 数据偏移写死,找不到就甩锅给安装包

sub_401BA0.c:1116-1118)先要求文件大小不小于 0x60000,再直接 SetFilePointer(393216),不搜索魔数。任何重打包或尾部追加了其它数据的变体都会走到 "The installation program may be corrupted.",用户无法从这行字里知道该检查什么。

F10 全量 677 MB 整包覆盖

7 个文件整体替换,最大的是 data02251.arc,420,991,779 字节。文件按索引顺序处理,前 4 个合计不到 1 MB,瞬间完成,然后停在 421 MB 的文件上。界面有两条进度条:一条 0..0xFFFF 按字节推进(.c:1422),一条 0..7 按文件推进(.c:1305-1306.c:1469),但没有剩余时间或百分比文字。

失败时残留的 .tmp 只在收尾路径清理,崩溃或断电后会留在游戏目录里。

F11 错误没有代码也没有日志

错误全部走 MessageBoxW.c:768 用 0x40 图标,.c:774 用 0x30 图标。sub_401BA0 内部返回一串 0x8000000x 风格的值,WinMain 只按区间映射成两三句笼统文案。用户拿不到错误码,开发者也没有日志可查。

3. 它还做对的几件事

以下设计可以保留:

  1. 先写 .tmpMoveFileExW(REPLACE_EXISTING) 覆盖,单文件替换接近原子操作。
  2. 安装循环按 1 MB 分块流式读写,没有把 677 MB 一次性载入内存。
  3. 写完每个文件后用 BGI.hvl 清单摘要核对,能挡掉数据截断或损坏。
  4. 有取消标志(0x416A40/0x416A3C),按块检查,可以中途退出。

4. 重写时逐条消除

原版 替代做法
手动选目录、C:\ 起步 先查注册表、Steam 库和常见路径,找不到再让用户选,并把浏览框定位到候选目录
单向状态机 幂等处理:原版、已打、半打三种状态都能重跑、校验、修复
无备份 覆盖前备份到 backup/,提供 --restore
“for some reason” 错误码 + 具体文件 + 日志
锁死英文 跟随系统语言或首屏提供语言选项
整包 677 MB 格式本身是整包,按文件显示字节进度和剩余时间,跳过摘要已一致的文件
找不到就报“可能损坏” 搜索魔数自定位,失败时说明具体原因

本文版权遵循 CC BY-NC 协议 本站版权政策

(。>︿<。) 已经一滴回复都不剩了哦~