汉化 foobar2000 的一种方案
PE(Portable Executable)格式是 Windows 下可执行文件的标准格式。PE 文件中包含菜单、对话框、字符串等资源数据。汉化的原理就是使用 Resource Hacker 或 eXeScope 等 PE 文件资源编辑软件,用中文替换掉资源中的英文。
然而,foobar2000 的菜单并没有使用资源的方式保存在 PE 文件中,也未使用字符串资源。除了部分对话框资源可以用资源编辑器行汉化之外,其余诸如菜单、按钮、列表等,均无法采用上面的方法进行汉化。这些用户界面上的字符串都是以静态数据的方式保存在 .rdata 节中。现在需要定位这些 PE 文件中的静态字符串。用十六进制编辑器打开 foobar2000.exe 文件,可以看到这些字符串。但是手工定位非常繁琐,可以采用 strings 命令来简化操作。
strings 命令属于 GNU binutils 中的一个工具,可以通过 Scoop 安装:
powershellscoop install binutils
使用 strings 获取 PE 文件中的所有静态字符串:
powershellstrings -d -t x foobar2000.exe
1c3418 File
... ...
1c45b0 Exit
1c4848 Edit
1c4850 View
1c4858 Library
1c4860 Help
返回的每一行代表找到的静态字符串,每行开头的十六进制数据表示字符串在文件中的偏移量。只要把这些找到的字符串替换成中文就可以完成汉化了。
不过还有个问题,就是 foobar2000 内部采用 UTF-8 编码,而一个 UTF-8 编码的汉字要占用三个字节。也就是说,原来英文字符串所占用的长度可能容纳不下翻译后的中文。这就比较麻烦了。虽然可以通过数据重新定位等方式来进行扩容,但是要反编译软件后手工修正。如果不适用自动化工具,人力成本未免太高了。现在网上流行的汉化版 foobox-cn 似乎就是通过这种方式来实现汉化的。
另辟蹊径的方法是通过 Component 的方式将 dll 加载到 foobar2000 的进程中去,然后在运行时将软件 UI 上的文字进行中文替换。
通过 Spy++ 探测可知,foobar2000 的菜单是 ToolbarWindow32 窗口,也就是 Windows 通用控件里的工具条,通过 Win32 API CreateToolbarEx 创建 。如果能通过 API Hook 的方式,将 CreateToolbarEx 的 lpButtons 参数替换掉,就可以实现菜单的汉化了。以此类推,将所有和渲染用户界面相关的 API 都 Hook 了,就能实现软件汉化了。
这种汉化方式的优点是不需要 Patch 原来的二进制文件,可以通过 Component 的形式独立发布。