开发工具逆向工程桌面应用【免费下载链接】TextractorExtracts text from video games and visual novels. Highly extensible.项目地址https://gitcode.com/gh_mirrors/te/Textractor点击查看免费下载Textractor曾用名 NextHooker是一个运行于 Windows 7 及 Wine 之上的 x86/x64 开源游戏文本提取工具通过向游戏进程注入 DLL、Hook 文本输出函数并借助命名管道回传数据实现对视觉小说与各类游戏引擎文本的实时捕获。本篇以项目的俄文 README 为主线完整覆盖其下载、功能、/H 与 /R 钩子码语法、扩展机制、编译方法与整体架构并结合作用户指南 docs/TUTORIAL.md帮助读者既会用工具也理解其底层实现。项目概述Textractor是一个高度可扩展的开源文本 Hook 器最初脱胎于 ITHVNRITH VNR 引擎项目用于从视频游戏与视觉小说中提取对话与 UI 文本。它同时支持 32 位与 64 位进程并可在 Wine 环境下列为可用方案。项目提供多语言 README含英文、简体中文、俄文等十余种语言用户也可观看 docs/TUTORIAL.md 中记录的教学视频快速上手。俄文 README 列出的核心特性如下与英文版一致可直接作为功能清单高度可扩展所有后处理逻辑都以扩展Extension形式实现自动捕获可从大量游戏引擎自动 Hook 文本其中包括部分 VNR 并不支持的引擎/H hook 码通过 Hook 码拦截指定函数的参数或返回值来捕获文本兼容大多数 AGTHAnother Game Text Hooker代码/R read 码不注入 Hook而是按地址周期性直接读取目标内存实现直读式文本抽取。获取版本Textractor 的正式发行版可在项目官方 Releases 中下载更早的 ITHVNR 版本在俄文 README 中给出了存档链接英文 README 还额外提到带调试信息的实验性构建可以从持续集成平台的 Artifacts 中获取。下载后解压即可运行Textractor.exe无需额外安装。若要针对某款特定游戏长期捕获项目约定游戏根目录下可放置TextractorConfig.txt配置文件见 include/defs.h 中GAME_CONFIG_FILE的定义用于保存该游戏的 Hook 码等设置。钩子码语法/H hook 码与 /R read 码钩子码是 Textractor 的核心使用方式一行代码即可描述在哪里、按什么格式读多少字节、如何解码。所有解析逻辑集中在 host/hookcode.cpp入口函数HookCode::Parse会去掉可选的前缀/与行尾斜杠兼容 legacy/AGTH 写法再按首字母分发到ParseHCode或ParseRCode参见 host/hookcode.cpp。/H hook 码/H 码的一般结构见ParseHCode实现host/hookcode.cpp/H {类型标志} [F] [null_length] [N] [codepage#] [padding] 偏移 [*间接索引] [:分割偏移 [*分割间接索引]] 地址[:模块[:函数]]各字段的含义字段取值作用类型标志A大端长度前置按长度前缀读取定长文本B小端长度前置同上小端序SANSI 字符串直到结尾QUnicode 字符串VUTF-8 字符串MUnicode 十六进制转储HEX dump 模式F—完整字符串模式按参数实际读取整串并补换行null_length数字文本长度位于字符串指针前null_length字节处负偏移写法N—不读取调用上下文NO_CONTEXTcodepage#数字指定代码页例如936#为 GBK、65001#为 UTF-8padding十六进制读取前跳过的填充字节偏移十六进制目标寄存器/参数偏移ITH 与 AGTH 的寄存器偏移相差 4解析时会自动校正*间接索引十六进制二级指针解引用DATA_INDIRECT:分割偏移十六进制从另一寄存器取长度USING_SPLIT可再带*表示二级解引用地址十六进制要 Hook 的函数地址:模块文件名地址相对模块基址如gdi.dll:函数符号名地址相对函数入口如GetTextOutA源码中自带的测试用例给出了真实可解析的完整示例host/hookcode.cpp/HQN936#-c*C:C*1C4AA:gdi.dll:GetTextOutA ; Hook gdi.dll!GetTextOutAGBK 解码双级指针 双级长度 /HB40 ; 长度前置的 ANSI 文本 /RS65001#44 ; UTF-8 直读码GenerateHCode还支持反向生成给定HookParam与进程 ID它会把绝对地址尝试折算成模块 偏移形式通过VirtualQueryEx找到所属模块使 Hook 码在 ASLR 下更稳定host/hookcode.cpp。/R read 码/R 码描述一次内存直读结构为见 host/hookcode.cpp/R {S|Q|V|M} [null_length] [codepage#] 地址SANSI 字符串QUnicode 字符串VUTF-8MUnicode 十六进制转储null_length长度前置位置codepage#代码页如/RS65001#44表示按 UTF-8 直读0x44处的字符串非法前缀如/RW44会解析失败被拒绝。/R 码与 /H 码的差异在于/H 需要注入一小段指令到目标函数首部把参数转发出来/R 则不需要 Hook 代码适合已知剧情文本缓冲区地址的场景。扩展机制俄文 README 指出官方扩展示例项目展示了如何构建扩展而仓库内的 extensions/ 文件夹本身就是扩展功能的活文档。该目录下包含十余个用 C 编写的扩展覆盖了从文本清洗到功能增强removerepeatchar.cpp/removerepeatphrase.cpp/removerepeatsentence.cpp去除重复字符、短语与句子游戏引擎反复重绘对话时的常见问题regexfilter.cpp/regexreplacer.cpp/replacer.cpp/styler.cpp基于正则与替换规则的过滤、改写与样式化extranewlines.cpp、exnewlines/extrawindow.cpp换行处理与独立文本窗口copyclipboard.cpp/threadlinker.cpp剪贴板同步与多线程文本关联bingtranslate.cpp/googletranslate.cpp/deepltranslate.cpp/translatewrapper.cpp多种翻译服务的封装lua.cpp/devtools.cppLua 脚本扩展与开发者调试工具。从源码结构看GUI 在显示每一条文本前会先把它连同元数据分发给所有扩展GUI/mainwindow.cpp 中调用DispatchSentenceToExtensions(sentence, GetSentenceInfo(thread).data())若某个扩展返回跳过则该句不显示。扩展与宿主之间的元数据接口定义在 extensions/extension.hSentenceInfo以名字 → 整型值的数组形式向扩展暴露线程名、代码页等信息扩展也可通过抛出自定义的SKIP异常主动丢弃文本。编译项目编译 Textractor 的前置条件俄文 README Compiling 一节原文要求安装支持 CMake 的 Visual Studio安装 Qt 5.13。随后直接用 Visual Studio 打开源码文件夹、选择配置并构建产物即为Textractor.exe。从 CMakeLists.txt 可以看到这些要求在工程层面的体现项目强制 MSVC非 MSVC 工具链会直接FATAL_ERROR终止配置CMakeLists.txt全局编译选项为 C17、多核编译/MP并按目标位数链接x64libs或x86libsCMakeLists.txt通过cmake/QtUtils.cmake注册表搜索定位 Qt 5 的Core、Widgets、WinExtras、WebSockets模块CMakeLists.txt工程由host、texthook、GUI、extensions、test五个子工程组成CMakeLists.txt分别对应宿主程序、被注入 DLL、图形界面、扩展与测试。注意英文版 README 额外提示从源码构建前需先克隆仓库并初始化子模块git submodule update --init因为texthook/minhook/等目录依赖子模块内容。项目架构俄文 README 的项目架构一节描述了完整的数据通路**宿主host向目标进程注入 texthook.dll两者通过两条命名管道通信texthook 等待管道接通后向文本输出函数如TextOut、GetGlyphOutline注入少量指令把它们的输入参数转发到管道宿主对收到的文本做初步处理后交回 GUIGUI 在显示前再把文本分发给扩展。**下面结合源码逐环节拆解。两条命名管道管道名与同步对象集中定义在 include/defs.hconstexpr auto HOOK_PIPE L\\\\.\\pipe\\TEXTRACTOR_HOOK; // texthook → host constexpr auto HOST_PIPE L\\\\.\\pipe\\TEXTRACTOR_HOST; // host → texthookhostPipeTEXTRACTOR_HOST宿主写入端向被注入的 DLL 下发命令hookPipeTEXTRACTOR_HOOKtexthook 写入端回传捕获的文本、控制台日志与钩子事件。两者都以PIPE_TYPE_MESSAGE消息型管道创建保证每条消息边界完整。texthook.dll 的启动与管道线程被注入的 DLL 生命周期入口在 texthook/main.cc 的DllMain用命名互斥量VNR_HOOKMAN_pid防止对同一进程重复注入创建内核对象文件映射即 README 中所说的文件视图 / section objectVNR_SECTION_pid并把其中一段内存映射为TextHook hooks[MAX_HOOK]数组——宿主进程稍后会只读映射同一块内存从而不经过管道即可查看当前所有 Hook 的状态地址、参数、名称等初始化 MinHook 后创建独立的Pipe线程texthook/main.cc。Pipe线程的工作循环等待事件TEXTRACTOR_PIPE_AVAILABLE随后以客户端身份连接两条管道CreateFileW打开HOST_PIPE与HOOK_PIPEtexthook/main.cc先通过 hookPipe 写入自己的进程 ID宿主据此建立进程记录调用Engine::Hijack()定义于 texthook/engine/match.cc启动各引擎的自动匹配/Hook 逻辑循环读取 hostPipe 命令switch分发四种HostCommandTypeHOST_COMMAND_NEW_HOOK按用户给定的HookParam插入新 Hook名称形如UserHook1HOST_COMMAND_REMOVE_HOOK移除指定地址附近的 HookHOST_COMMAND_FIND_HOOK按SearchParam搜索——给了文本则SearchForText按已知文本反查地址否则SearchForHooks自动搜索候选 HookHOST_COMMAND_DETACH结束循环DLL 自清理并FreeLibraryAndExitThread。捕获到的文本经TextOutput打包成ThreadParam头 原文写入 hookPipetexthook/main.cc找到的 Hook 通过NotifyHookFound上报宿主会据此生成/H码并打印到控制台方便用户保存为游戏配置。宿主侧管道管理、注入与文本整理宿主逻辑在 host/host.cpp。CreatePipe为每对连接创建两条消息管道hookPipe 为PIPE_ACCESS_INBOUNDhookPipe 连接成功后先读回 4 字节进程 ID 建立ProcessRecord再递归调用自身以便支持多进程同时挂接host/host.cpp。每个ProcessRecord保存该进程的 hostPipe 句柄、对VNR_SECTION_pid的只读映射视图README 所说映射到 TextHook 类引用的对象以及保护该视图的互斥量。读取 hookPipe 的主循环按HostNotificationType分派FOUND_HOOK转换编码后回调 GUI 控制台、RMVHOOK清理对应线程、TEXT控制台输出其余情况按默认分支视为文本数据——取出ThreadParam头按进程 地址 上下文哈希定位TextThread首次出现时触发OnCreate然后把原始字节Push进线程缓冲host/host.cpp。进程注入实现在Host::InjectProcesshost/host.cpp是标准的 CreateRemoteThread 注入用VNR_HOOKMAN_pid互斥量先占位已存在则提示已注入OpenProcess(PROCESS_ALL_ACCESS)打开目标IsWow64Process检查 32/64 位匹配VirtualAllocExWriteProcessMemory写入texthook.dll的完整路径再CreateRemoteThread调用LoadLibraryW完成加载。宿主还内置了两个特殊TextThreadconsole系统日志输出与clipboardhost/host.cpp后者借助WH_GETMESSAGE钩子监听WM_CLIPBOARDUPDATE把系统剪贴板里的文本也汇入统一管线——这解释了为何许多扩展能对复制出来的游戏文本同样生效。文本缓冲的整理逻辑在 host/textthread.cpp 的TextThread::Push双字节字符集DBCS保护当一次只读到 1 字节且是 DBCS 前导字节时IsDBCSLeadByteEx先暂存等下一字节配对避免 GBK 等编码在消息边界被切断编码转换按HEX_DUMP、USING_UNICODE或codepage分支处理Unicode 直接转换ANSI 经StringToWideString按指定代码页缺省为Host::defaultCodepage转宽字符重复过滤RemoveRepetition检测整句被引擎连续重绘 N 遍的情况并只保留一句对应英文 README 提到的 issue #40每 10 毫秒的定时器队列CreateTimerQueueTimer负责把缓冲按时间窗口切分成句子sentence向上层输出。数据流总览综合以上源码README 描述的链路可还原为游戏进程 └─ texthook.dllLoadLibrary 注入 ├─ DllMain: 建 VNR_SECTION_pid 共享视图 Pipe 线程 ├─ Pipe 线程: 连接管道 → Engine::Hijack() → 处理 /H、搜索、移除、断开 └─ 文本输出: ThreadParam 原文 → hookPipe (\\.\pipe\TEXTRACTOR_HOOK) 宿主 host ├─ CreatePipe: 建立双向消息管道按 PID 维护 ProcessRecord ├─ hostPipe 下发命令插入/移除/搜索/断开 ├─ 只读映射 VNR_SECTION_pid 查看 Hook 状态 └─ TextThread: DBCS 拼接、代码页转换、去重、定时切句 GUI ├─ 显示文本线程 / 控制台 / 剪贴板线程 └─ DispatchSentenceToExtensions: 每句先过扩展再显示支持与贡献俄文 README 给出了明确的协作约定反馈渠道任何 bug、Textractor 无法 Hook 的游戏、功能请求都欢迎提出若某款游戏无法捕获作者希望通过免费下载链接或 Steam 礼物获取该游戏用于实测贡献方式关于代码库的问题可邮件联系作者PR 遵循标准流程fork → 建分支 → 提交改动 → 向 master 发起 PR翻译贡献所有界面字符串集中在 text.cpp 中按语言分组维护俄文HIJACK_ERROR等字符串就在其中翻译该文件与 README 即可完成多语言贡献贡献者名单见 docs/CREDITS.md。小结Textractor 以宿主 被注入 DLL 双管道 共享视图的经典注入架构把游戏内的文本捕获做成了可编码化/H、/R 码、可搜索自动找 Hook、可后处理C/Lua 扩展管线的完整工具链。若你要为某款游戏做文本提取实践路径是先试自动引擎匹配 → 失败则用按文本搜索或手动/H码定位TextOut*/GetGlyphOutline类调用点 → 保存 Hook 码到TextractorConfig.txt→ 用 extensions/ 中的去重、正则扩展清洗输出。仓库中的 include/defs.h、texthook/main.cc、host/host.cpp 与 host/hookcode.cpp 是深入原理时最值得精读的四份文件。赞分享开发工具逆向工程桌面应用【免费下载链接】TextractorExtracts text from video games and visual novels. Highly extensible.项目地址https://gitcode.com/gh_mirrors/te/Textractor点击查看免费下载相关推荐Textractor 技术指南游戏文本 Hook 工具的项目架构、Hook 代码机制与构建详解Textractor 技术指南游戏文本 Hook 工具的项目架构、Hook 代码机制与构建详解 本文为基于 Textractor 官方文档README_DE开发工具逆向工程桌面应用Textractor强大的Windows游戏文本提取工具完全指南Textractor强大的Windows游戏文本提取工具完全指南 Textractor是一款专为Windows系统设计的开源游戏文本钩子工具能够精准捕获游戏开发工具逆向工程桌面应用Better Auth 环境变量完全指南2 个必配项、密钥轮换与避坑速查Better Auth 环境变量完全指南2 个必配项、密钥轮换与避坑速查 Better Auth 是目前覆盖面最广的开源认证框架邮箱密码、社交登录、Pass认证鉴权后端身份认证上一篇5分钟搭建高性能Python FTP服务器pyftpdlib终极指南 下一篇LogicStack-LeetCode 题解精讲1331. 数组序号转换 —— 排序 哈希表模拟的经典模板创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考