☰
用MHF抓取游戏文本钩子:从原理到接驳Textractor全流程
2026/10/2 13:01:21 网站建设 项目流程

如果你手头有一款日文或英文文字游戏,想借助翻译工具把它啃下来,或者你正打算自己动手给某个老游戏做本地化,那“文本钩子”这四个字你迟早得面对。简单说,文本钩子就是游戏进程里那些正在把文字绘制到屏幕上的代码位置,翻译软件如果能挂上钩子,就能在文字显示出来之前把原文截走,再吐给你一段译文。MisakaHookFinder(以下简称MHF)就是专门用来找这种钩子的工具,我这次就把自己摸索出来的完整流程写清楚,从原理到实操,从踩坑到接驳翻译工具,尽量一次说透。

1. 定位与原理:为什么要从内存里“钓”文本

1.1 三种拿游戏文本的方式,为何钩子最靠谱

想实时拿到游戏画面里的对白,不外乎三种路线。第一种是OCR截图识别,屏幕截下来再跑文字识别,优点是啥游戏都能用,缺点是速度慢、字体花哨一点就识别成乱码、遇到动态光影还会频繁误判,作为应急手段可以,日常阅读太折磨人。第二种是监听剪贴板,可大多数文字游戏根本不会主动复制文本到剪贴板,你点半天台词,剪贴板还是空的,这条路基本走不通。第三种就是我们说的Hook,程序在游戏把字符串交给系统绘制之前,先把它拦截下来,拿到的既是原始文本,又是实时文本,编码可控、格式干净,翻译工具拿到手就能用。

打个比方,OCR是在快递已经派送到门口之后,对着快递单拍照片认字;而Hook是在分拣中心直接把贴上标签的包裹抽走。显然后者更高效、更准确。

1.2 MHF在整套工具链里扮演什么角色

MHF的全名是MisakaHookFinder,社区里也叫“御坂钩子搜索器”。它做的事情非常聚焦:附加到目标游戏进程,扫描内存中正在显示的文本,然后帮你找出“这段文本是从哪个调用点输出到屏幕的”,这个调用点就是所谓的文本钩子。注意,MHF本身不负责翻译,也不负责展示译文,它更像一个探针或寻线仪,找到位置、验证可用,剩下的交给Textractor这类工具去做。

很多人会有个疑问:Textractor自己不是带Search Hook功能吗?为什么还要单独用MHF?实话实说,Textractor自带搜索对大部分热门游戏引擎已经够用,但遇到老游戏、小众引擎、文本经过二次拼接的情况,内置搜索经常一无所获。MHF更贴近底层,扫描策略更激进,可以看到更多候选地址和文本缓冲区信息,正好可以补上这个空缺。我的习惯是:Textractor搜不到、或者搜出来文本不全的时候,才开MHF手动排查。

这套方法的适用面很广,日系AVG视觉小说、老RPGMaker游戏、部分国产文字冒险,甚至Unity引擎的某些文字游戏,都可以用同一套思路提取文本。条件是游戏不能被反作弊、强DRM这类保护机制锁死进程,否则附加阶段就会失败。

2. 开工前准备:权限、编码与游戏状态

2.1 运行权限和杀软白名单别偷懒

MHF的本质是内存注入工具,Windows十有八九会拦你一下,杀毒软件更是容易把它误判成风险程序。第一次使用,建议直接把MHF所在目录加进杀软排除名单,然后右键“以管理员身份运行”。这一步不做,后面就会出现附加进程失败、候选列表刷不出来这些莫名其妙的问题。

顺带提醒一句,游戏本身也尽量用管理员模式启动,尤其是一些老游戏开了兼容模式之后权限会很别扭。游戏和工具一个管理员一个普通权限,注入经常卡在权限边界上,看似能用,实际搜起来又慢又缺项。

2.2 游戏画面和区域设置影响很大

启动游戏前,有几个能提前消掉的环境因素。第一个是转区,玩日文老游戏最好用Locale Emulator这类工具以日语区域启动,许多老引擎的文本输出逻辑和代码页直接挂钩,区域不对,内存里解析出来的字符串就会偏。第二个是画面模式,尽量选窗口模式,全屏独占状态容易让工具附加时刷新不了画面,给排查增加无谓的干扰。第三,把游戏里的特效字体、抗锯齿这类渲染增强关掉,它们不影响搜索原理,但会增加候选列表里的噪音。

还有一个非常关键的细节:开始搜索前,一定要先把游戏推进到有对白的正常界面,让当前屏幕上至少显示着一句完整的话。停在标题画面就点搜索,内存里连个像样的文本缓冲都没有,搜出来的东西要么是UI按钮名,要么是制作组Logo,对着这些找钩子当然找不到。

2.3 工具版本和目录路径

MHF有32位和64位之分,目标进程是64位就用64位版本,目标进程是32位就用32位版本,混用会附加失败。这是新手最常踩的坑之一。另外,工具解压目录最好放在纯英文无空格的路径下,比如D:\Tools\MHF,中文路径在某些编码处理环节会引发解析异常,属于可以提前规避的坑。至于具体版本,尽量选社区里最新发布版,老版本对新引擎的文本编码支持不够好。

3. 实操核心:用MHF从零找到文本钩子

3.1 附加进程:顺序别弄反

实操的第一步,先把游戏开起来,进入对话界面,再打开MHF。顺序千万别反,工具先开也行,但有些游戏引擎附加时会给进程重新初始化缓冲区,导致你后面等半天搜不到内容。打开MHF后,会看到一个进程列表,找到游戏对应的exe进程名,选中,点附加。附加成功之后,工具界面下方一般会有状态提示,比如显示进程PID、模块数量这些信息,没有报错就可以继续。

提示:如果进程列表里看不到目标游戏,先确认游戏确实在运行,然后点一下“刷新进程列表”。还是看不见的话,大概率是MHF被以非管理员权限运行,重启MHF再试。

3.2 搜索参数怎么填:编码、文本长度与刷新时机

附加完成后,MHF会列出很多搜索选项,这里有几个参数直接影响命中质量,值得花点心思调。

第一是文本编码。日文游戏通常选Shift-JIS(也可能叫ANSI/JIS)或者UTF-16LE,中文游戏一般是GBK或UTF-8。拿不准的时候可以先用UTF-16LE跑一轮,很多引擎默认用宽字符存储字符串,命中率相对高。编码选错会怎么样?候选列表里全是问号乱码,一眼就能看出来,回头切换重扫就行,不会伤到游戏进程。

第二是最小文本长度。默认值可能很小,扫出一堆按钮上的单个字符,很吵。建议先设成5或6,确保候选文本至少是一句有意义的对白。如果游戏里全是短句,后面再调低也不迟。

第三是搜索的刷新时机。点开始搜索之后,你需要手动回到游戏窗口,把对白往下翻一句。让屏幕上的文本产生变化,MHF才有机会对比内存差异,把正在活动的文本地址暴露出来。一次搜索看不到理想结果很正常,来回多翻几句,候选列表会不断更新。

3.3 候选列表筛选:哪些钩子才是最干净的

刷出来的候选会以列表形式展示,每一行通常包括地址、偏移、模块名、文本预览。筛选的核心原则就一条:预览区里那句文本是否和游戏当前对白一致,且不掺杂多余内容。

我会按这个顺序来判断一个候选值不值得用。先看文本完整性,一句台词能完整显示出来是最基本的;再看纯净度,有些候选题词是“游戏标题+当前对白+UI按钮文字”一锅炖,这种钩子拿到的数据带着大量格式控制符,翻译时会被迫反复清洗;最后看稳定性,在游戏里连翻三到五句,候选文本每次都准确跟随剧情变化,没有重复历史台词、没有漏字,这就是理想钩子。

多行文本的情况值得单独说。很多引擎的文本是多段拼接的,一个钩子只能抓到其中一行,候选列表里会出现“同一句台词的前半句”“后半句”各占一条的情况。这时候不要急着嫌弃,把它们的位置都记下来,后续在Textractor里可以同时挂多个钩子做文本合并,拼起来才是完整台词。

3.4 记录地址的正确姿势:模块+偏移比绝对地址更稳

确认了一个可用的钩子之后,最重要的事情是把地址记准。MHF界面上往往会同时给出绝对地址和模块+偏移两种形式。我的建议是优先记录模块名+偏移,比如game.exe+0x12A3F4这种格式,而不是那一长串绝对地址。原因在于很多游戏开启ASLR(地址空间布局随机化)后,每次启动的绝对地址都不一样,但模块加载基址加偏移是常数关系,换一次启动仍然有效。

如果你看到的候选只有绝对地址,也没关系,先记下来,后面在Textractor里如果地址变红、抓不到文本,再手动减去模块基址算出偏移即可。不过MHF多数情况下会把偏移直接给你,省不少事。

4. 钩子接驳:把地址交到Textractor手里

4.1 在Textractor里添加钩子的完整步骤

MHF的任务到“找到并验证地址”这一步就算完成了,真正把文本稳定读出来的是Textractor。打开Textractor,先做和MHF相同的一件事:附加到同一个游戏进程。然后找到“Add Hook”输入框,把从MHF记录到的地址填进去,选定文本编码,回车确认。如果地址正确,Textractor主窗口会立刻开始滚动文本,游戏里每翻一句,它就输出一句。

这里有一个填写格式的问题。Add Hook的输入框通常兼容几种写法:绝对地址、模块+偏移、甚至符号名。我建议粘贴模块名+偏移形式,例如:

game.exe+0x12A3F4

填完回车后,正常情况下状态列会变成正常,文本区开始出字。如果一直空白,先检查编码,再检查偏移是否复制完整,最后确认Textractor附加的进程和MHF附加的是同一个进程。

4.2 多钩子合并:处理分行文本的必学操作

刚才提到有些引擎一个钩子只能抓到一行对白,这种场景在Textractor里也很常见。办法是同时添加多个钩子,让它们并行输出,然后在Textractor的扩展设置里开启“合并文本”或“追加行”功能。具体按钮在不同版本里叫法不一样,但思路一致:把两个钩子输出的内容按顺序拼成完整的一句话。

判断是否需要合并,看一眼MHF候选列表就可以:多个候选显示同一句台词的不同片段,或者Textractor里某一句对白总缺后半句,那就是合并需求。合并时要注意输出顺序,后一行不一定排在后面,极少数引擎的文本缓冲是反着读的,这种时候只需要交换两个钩子的顺序就能解决。

4.3 接翻译工具:从剪贴板到现代翻译集成

钩子稳定出文本之后,最后一步是把文本交给翻译工具。这个环节有两条路线,看你用的翻译工具是哪个年代的产品。

老牌工具通常走剪贴板模式。Textractor可以直接把抓到的文本复制到剪贴板,翻译工具监听剪贴板后自动出译文。优点是兼容性极好,什么工具只要能读剪贴板就能接,缺点是有时候频繁复制会把剪贴板原来的内容冲掉,日常用电脑受影响。

新一点的工作流则直接走扩展接口。比如LunaTranslator、MisakaTranslator这类现代翻译工具,原生支持读取Textractor的hook输出,不需要经过剪贴板中转,译文延迟更低,也支持句段换行、术语替换这些高级功能。我自己现在更推荐这个方式,链路短、稳定,还能省掉剪贴板冲突的烦恼。

推荐组合很简单:MHF负责找钩子地址,Textractor负责稳定输出原始文本,末端接一个支持Textractor直连的翻译工具。这套组合基本可以通吃绝大多数文字游戏。

5. 避坑实录:搜不到、乱码、重复文本的诊断清单

5.1 常见问题速查表

整理了我在实际使用中反复遇到的几个问题,按出现频率排序,可以当排查表用。

问题现象可能原因解决办法
搜不到任何候选游戏停在标题界面,没有文本变化把对白往前推进几句再搜
候选全是乱码编码选错切换Shift-JIS/UTF-16LE/GBK重试
附加进程失败权限不足、进程位数不匹配、杀软拦截管理员运行MHF,确认32/64位对应,加白名单
文本重复出现历史台词钩子挂在缓冲区上,包含滚动历史换一个候选,优先选“干净且跟随当前句”的钩子
钩子第一次能用,重启游戏就失效填了绝对地址,ASLR导致基址变化改用模块+偏移格式重新填写
Textractor里始终空白地址格式不对或偏移复制不完整核对模块名+偏移写法,确认无多余空格
候选列表太多无法下手最小文本长度设得太低提高长度阈值到5~8,过滤短串

5.2 特殊引擎的特殊处理手段

AR游戏这块,不同引擎的应对策略不太一样。

吉里吉里(Krkr)系的游戏,MHF候选通常能扫出一堆地址,但真正好使的往往集中在TVP相关的模块里。如果你知道游戏是吉里吉里引擎,可以优先看模块名里带TVP或krkr字样的候选。

Unity引擎的文字游戏稍微麻烦一些,文本经常存在Il2Cpp托管堆里,普通Hook不一定扫得准。这时候除了MHF,还要挂上Textractor对应的Unity插件辅助输出,MHF主要负责确认文本在内存中是否存在,能帮上忙但别指望一步到位。

RPGMaker老游戏是另一个经典难题,文本经常是一个字一个字地绘制,钩子抓到的可能只有单个字符,输出是“今”“日”“天”“气”“不”“错”这样被拆开的碎片。遇到这种,看候选列表里有没有标明“buffer”或“string”类型的钩子,拼合之后更接近原始整句。如果实在找不到整句缓冲,就在Textractor里加一个“文本间隔”设置,把逐字输出合并成词句后再交给翻译。

5.3 我自己的最后排查习惯

再分享几个和工具文档无关的野路子,都是平时被坑出来的经验。

第一,“翻句大法”永远有效。搜索命中率低的时候,不要干等候选刷新,回到游戏里快速把对白往前翻一句、往后翻一句,反复翻转几次。文本变化越明显、越频繁,候选里真正活动的文本地址就越容易被顶到前面来。

第二,多候选取舍时,优先选文本预览里“只有当前句”的那一个,而不是选带一堆方括号、引擎标记、控制字符的那个。控制字符少的钩子,接翻译工具时清洗成本最低,长期看最省心。

第三,MHF扫描对老游戏尤其友好,但对新游戏不保证。新游戏如果带了内存保护、反调试、防注入,附加失败就不要再折腾了,这跟技术无关,纯粹是工具边界外的事。

我见过不少刚开始尝试的人,在第一轮搜不出候选的时候就放弃了,其实很多时候只是停在标题画面没翻文本,或者编码选错。先调参数、再翻文本、最后换候选,这套流程走三遍,绝大多数游戏都能拿下。等钩子找到、文本成功接进翻译工具的那一刻,你回头再看,会觉得所谓“内存提取文本”也就是一层窗户纸的事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询