尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

UNNPK 解包指南:三步搞定网易 NPK 文件提取与脚本解密

UNNPK 解包指南:三步搞定网易 NPK 文件提取与脚本解密 UNNPK 解包指南三步搞定网易 NPK 文件提取与脚本解密【免费下载链接】unnpk解包网易游戏NeoX引擎NPK文件如阴阳师、魔法禁书目录。项目地址: https://gitcode.com/gh_mirrors/un/unnpk你有没有遇到过这样的场景下载了一款网易旗下使用 NeoX 引擎的游戏比如《阴阳师》《魔法禁书目录》想研究里面的美术资源、剧情文本甚至游戏逻辑却发现所有资源都装在一个后缀为.npk的神秘大文件里双击打不开、改名也无效网上搜到的工具要么失效要么收费UNNPK正是为解决这个痛点而生的开源命令行工具它能将网易 NeoX 引擎的 NPK 资源包解包成标准的 PNG、XML、JSON、GLSL 文件配合配套脚本还能还原加密的游戏 Python 脚本。本文会从零开始带你完成编译、解包、解密全流程并讲清它背后的实现原理。先认识一下这个项目UNNPK 是一个用 C 语言编写的小巧工具集整个仓库只有三个源码文件加三个 Python 辅助脚本却能完成从二进制资源包到可读文件的全链路工作组件作用依赖unnpk主解包工具读取 NPK 文件并输出所有内部文件zlib libmagicmapnpk结构探查器输出 NPK 内部索引表Markdown/CSV无tools/script_redirect.py解密游戏脚本rotor 加密逆向Python 2 rotortools/pyc_decryptor.py修正混淆的 Python 字节码生成标准 pycPython 2/3 rotortools/pymarshal.py自定义 marshal 实现支持 opcode 映射转换Python 2[!TIP] 无需安装任何运行时unnpk和mapnpk编译后是独立可执行文件拷贝到任何同架构 Linux/macOS 机器都能直接跑。5 分钟跑通从安装到第一次解包安装依赖不同系统安装 libmagic 开发库的方式不同二选一即可# macOSHomebrew brew install libmagic # CentOS / RHEL sudo yum install file-libs file-devel # Debian / UbuntuREADME 未列但同样可用 sudo apt-get install libmagic-dev编译获取源码并执行make# 克隆项目仓库 git clone https://gitcode.com/gh_mirrors/un/unnpk # 进入项目目录 cd unnpk # 一键编译生成 unnpk 与 mapnpk 两个可执行文件 make编译成功后用ls确认两个二进制文件已生成ls -la unnpk mapnpk第一次解包先准备好一个 NPK 文件游戏安装目录里通常以.npk结尾然后执行# 语法./unnpk [NPK文件] [输出目录] ./unnpk game_data.npk ./extracted命令运行后会看到类似下面的表格输出| Index | Offset | Size | Unzip size | zip | MIME Type | Extension | | - | - | - | - | - | - | - | | 00000001 | 0x00001000 | 1.2 MB | 3.5 MB | Yes | image/png | .png | | 00000002 | 0x00015000 | 450 KB | 450 KB | No | text/xml | .NeoX.xml | | 00000003 | 0x00023000 | 12 KB | 12 KB | No | text/plain | .json |解包出的文件会自动按 MIME 类型分类存放比如extracted/image/png/00000001.png、extracted/text/xml/00000002.NeoX.xml。到这里你已经完成了第一次成功的 NPK 解包 实战演示三个典型场景场景一快速摸清 NPK 的家底拿到一个陌生 NPK 文件别急着解包先用mapnpk探查一下内部结构确认里面到底有什么# 以 Markdown 格式输出结构报告 ./mapnpk game_data.npk # 保存为报告文件方便后续查阅 ./mapnpk game_data.npk -o report.md -f markdown输出内容会包含文件总大小、索引表偏移量以及每个内部文件的索引、偏移、压缩前后大小等元数据# mapnpk! File size: 4281346048 Byte Map offset: 0x000FEF00 | Index | Offset | Size (Byte) | Unzip size (Byte) | Chk | Unzip Chk | Is zip | | --- | --- | --- | --- | --- | --- | --- | | 0x00000001 | 0x00001000 | 0x00400000 | 0x00000001 | ... | ... | Yes |-t参数可以切换数值显示方式hex/int/original-f csv则输出便于程序解析的 CSV 格式这是后面做自动化的重要基础。场景二从《阴阳师》script.npk 里还原脚本源码这是 UNNPK 最有价值的用法不仅解包资源还能逆向还原游戏脚本。以阴阳师的script.npk为例完整链路如下第一步解包脚本资源./unnpk script.npk ./script解出的文件以偏移量十六进制命名比如0A0D60DC。第二步解密脚本内容rotor 加密逆向# 将加密脚本解密为原始字节流 python2 tools/script_redirect.py 0A0D60DC 0A0D60DC.out第三步修正混淆字节码# 将混淆的字节码恢复为标准 Python 2.7 pyc 文件 python tools/pyc_decryptor.py 0A0D60DC.out 0A0D60DC.pyc第四步反编译为可读源码# 需要先安装 uncompyle2 uncompyle2 -o 0A0D60DC.py 0A0D60DC.pyc至此一份可读的游戏脚本源码就呈现在你面前了。整个流程可以概括为解包 → 解密 → 修字节码 → 反编译。场景三批量提取并生成分类报告结合mapnpk的 CSV 输出你可以快速统计一个 NPK 包里各种资源的占比这在评估这个包值不值得解时非常实用# 生成 CSV 格式的结构清单 ./mapnpk game_data.npk -f csv -o structure.csv # 统计各类文件数量 awk -F, {print $7} structure.csv | sort | uniq -c原理拆解NPK 解包是怎么做到的NPK 文件的结构一本书的目录页NPK 文件本质上是一个带目录的容器。就像一本书在最前面会有目录页告诉你每章从第几页开始NPK 文件在固定偏移0x14处存放了一个map_offset值指向内部文件索引表的起始位置。// 读取 map 偏移量相当于翻到书的目录页 fseek(npk, 0x14, SEEK_SET); uint32_t map_offset; fread(map_offset, 4, 1, npk);索引表的每条记录固定为 7 个 32 位整数共 28 字节分别描述文件 ID、数据偏移、压缩后大小、原始大小、校验值、解压后校验值、是否压缩。因此主循环可以像翻目录一样逐条遍历// 从索引表起点一直读到文件末尾每条记录占 7*428 字节 for (int file_offset map_offset; file_offset npk_size; file_offset 7 * 4) { fseek(npk, file_offset, SEEK_SET); fread(file_info, 4, 7, npk); // 一次读入 7 个字段 // ...按偏移读取数据、按需解压、识别类型、写出文件 }[!TIP] 整个解包过程没有任何加密只有 zlib 压缩这也是 UNNPK 能一把梭解开的根本原因——uncompress()一行调用就完成了数据还原。类型识别libmagic 加自定义规则双保险解压出的数据是裸的没有文件名和扩展名。UNNPK 先用 libmagic 识别 MIME 类型再通过文件头特征做精细判断// 第一层libmagic 给出 MIME 类型 magic_t cookie magic_open(MAGIC_MIME_TYPE); magic_load(cookie, NULL); file_out_type (char *)magic_buffer(cookie, file_out_buf, file_info[3]); // 第二层根据文件头字节进一步细分 if (strcmp(file_out_buf, NeoX) 0) file_out_extension .NeoX.xml; // NeoX 引擎专属 XML else if (memmem(file_out_buf, file_info[3], vec4, 4)) file_out_extension .glsl; // GLSL 着色器 else if (file_out_buf[0] { ...) file_out_extension .json; // JSON 配置这就像先通过整体外观判断这是一本书再通过封面细节确认这是一本词典。对于 KTX、RGIS、PKM 这类游戏专用纹理格式libmagic 认不出来就需要第二层的文件头魔数Magic Number匹配来兜底。脚本解密三层嵌套的俄罗斯套娃script_redirect.py的核心逻辑非常简洁但每一层都对应一种保护手段def unnpk(data): # 拼接出 rotor 加密的密钥串 asdf_tm asdf_dn * 4 (asdf_dt asdf_dn asdf_df) * 5 ! # ... rotor rotor.newrotor(asdf_tm) # 第一层rotor 流加密 data rotor.decrypt(data) data zlib.decompress(data) # 第二层zlib 压缩 data _reverse_string(data) # 第三层字符串反转异或 return data解密后的数据还需要pyc_decryptor.py处理游戏对 Python 字节码的 opcode 做了置换混淆即把标准 opcode 编号映射成自定义编号。pymarshal.py维护了一张完整的 opcode 映射表在序列化时逐字节替换回来最终生成标准 PYC 文件供 uncompyle2 反编译。模块分工一览NPK 文件 │ ├─► unnpkC──── 解包 zlib 解压 类型识别 ──► 图片/XML/JSON/GLSL 等 │ ├─► mapnpkC─── 只读索引表输出结构报告 ────► Markdown / CSV │ └─► script_redirect.py ──► pyc_decryptor.py ──► uncompyle2 ──► 源码避坑指南常见问题与解决方案Q1编译时报fatal error: magic.h: No such file or directory说明 libmagic 开发库没装好。请确认安装的是libmagic-dev/file-devel带 dev 后缀的开发包而不是仅运行时的libmagic/file。Q2./unnpk报Z_DATA_ERROR: Data is not zlib这通常是索引表信息与实际数据不符导致的。UNNPK 的容错设计会直接输出原始数据而不是崩溃这种情况一般不影响其他文件的解包先检查是否拿错了文件。Q3script_redirect.py报ImportError: No module named rotorrotor 模块需要单独安装pip install rotor注意script_redirect.py是 Python 2 脚本请使用python2运行用 Python 3 大概率会报语法错误。Q4mapnpk输出的 CSV 用 Excel 打开乱码CSV 默认是 UTF-8 编码Excel 通常需要 UTF-8 with BOM。可以用sed -i 1s/^/\xef\xbb\xbf/ report.csv加上 BOM 头再打开。Q5解包出的文件没有扩展名当 libmagic 无法识别且自定义规则也未命中时扩展名为空。这类文件通常是游戏私有格式需要结合具体游戏另行分析。[!WARNING] 不同网易游戏的脚本加密参数可能不同script_redirect.py中的asdf_dn、asdf_dt、asdf_df是逆向自《阴阳师》特定版本。其他游戏需要先通过动态调试等手段找到对应的redirect.pyc它就藏在 script.npk 里文件名即偏移量十六进制再替换密钥参数。进阶玩法把 UNNPK 变成你的流水线批量处理脚本游戏更新后往往有几十个 NPK 要处理写个简单脚本一键搞定#!/bin/bash # 批量解包目录下所有 NPK 文件 for npk in ./npk_files/*.npk; do name$(basename $npk .npk) echo 正在处理: $npk ./unnpk $npk ./extracted/$name ./extracted/$name.log 21 done echo 全部处理完成集成到 Python 工作流借助mapnpk的 CSV 输出可以在 Python 里轻松拿到文件清单import csv, subprocess, tempfile def npk_file_list(npk_path, mapnpk_path./mapnpk): 返回 NPK 内部文件清单索引、偏移、大小、是否压缩 with tempfile.NamedTemporaryFile(moder, suffix.csv) as tmp: subprocess.run([mapnpk_path, npk_path, -f, csv, -o, tmp.name], checkTrue) tmp.seek(0) reader csv.DictReader(tmp) return [row for row in reader] files npk_file_list(game_data.npk) print(f该 NPK 共包含 {len(files)} 个内部文件)有了清单就能实现只提取特定类型文件按大小筛选资源等精细化需求将 UNNPK 无缝嵌入你的资源管理工具链。局限与展望UNNPK 目前是单线程解包处理数 GB 的大包时耗时明显类型识别依赖本机 libmagic 数据库识别不了最新格式时扩展名会缺失脚本解密参数也主要针对特定版本写死。不过作为开源项目这些问题恰好是社区贡献的机会提交 issue 时请附上 UNNPK 版本、操作系统、NPK 来源游戏及版本、完整报错日志方便维护者复现提交代码时遵循项目现有风格C 文件为 KR 风格Python 遵循 PEP8一次提交只做一件事完善文档各游戏 NPK 格式的差异分析、新版本解密参数的逆向成果都是非常受欢迎的贡献内容。写在最后从一个打不开的神秘大文件到分类整齐的 PNG、XML、脚本源码UNNPK 用不到 300 行 C 代码完成了资源解析的完整闭环。无论你是想研究游戏美术、分析剧情文本还是做 Mod 二次创作它都是一个轻量可靠的好帮手。现在就去克隆仓库、跑一次make用你自己的 NPK 文件试试吧——解包成功的那一刻你会真正理解技术民主化这四个字的分量。【免费下载链接】unnpk解包网易游戏NeoX引擎NPK文件如阴阳师、魔法禁书目录。项目地址: https://gitcode.com/gh_mirrors/un/unnpk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表