wows-tools/wows-depack
GitHub: wows-tools/wows-depack
开源的《战舰世界》资源文件解包工具与C库,支持索引解析、正则搜索、文件提取与实验性写入。
Stars: 8 | Forks: 0
# WoWs depack
[](https://github.com/kakwa/wows-depack/actions/workflows/ubuntu-x86_64.yml)
[](https://codecov.io/gh/wows-tools/wows-depack)
开源的《战舰世界》(World of Warships) 资源文件解包器。
# 链接
相关链接:
* Git 仓库:[github.com/wows-tools/wows-depack](https://github.com/wows-tools/wows-depack)
* 格式规范:[FORMAT.md](https://github.com/kakwa/wows-depack/blob/main/FORMAT.md)。
* 逆向工程过程:[REVERSING_STORY.md](https://github.com/kakwa/wows-depack/blob/main/REVERSING_STORY.md)
* Library API:[C API 文档](https://wows-tools.github.io/wows-depack/wows-depack_8h.html)
# 用法
## 安装
大多数主要发行版的软件包可以在[这个仓库](https://github.com/kakwa/kakwalab-pkg/blob/main/README.md)中找到。
按照说明设置仓库并安装以下软件包:
```
# 在 RHEL 上切换到 dnf
# CLI 工具
apt install wows-depack-cli
# 库
apt install libwows-depack0
# 开发 Header (用于 RHEL libwows-depack-devel)
apt install libwows-depack-dev
```
## 构建
```
# 安装 deps Debian/Ubuntu
apt install git cmake zlib1g-dev libpcre2-dev clang
# git clone + 进入项目目录
git clone https://github.com/kakwa/wows-depack.git
cd wows-depack/
# 构建
cmake .
make
```
## CLI 工具
### 帮助
```
./wows-depack-cli --help
Usage: wows-depack-cli [OPTION...] -W WOWS_BASE_DIR
World of Warships resource extractor tool.
[...]
```
### 打印所有文件
要打印存在的所有文件:
```
./wows-depack-cli -W ~/Games/World\ of\ Warships/ -p
/gui/modernization_icons/icon_modernization_PCM020_DamageControl_Mod_I.png
/gui/modernization_icons/icon_modernization_PCM047_Special_Mod_I_Montana.png
[...]
/clanbase/headquarters_2/6/29/31.png
/server_stats.xml
```
### 搜索
按名称模式搜索文件(perl 兼容正则表达式):
```
./wows-depack-cli -W ~/Games/World\ of\ Warships/ -s '.*[Pp]arams.*'
Found 3 matching files:
shipyardParams.xml
content/GameParams.data
content/UIParams.data
```
### 提取单个文件
要提取单个文件,请执行:
```
./wows-depack-cli -W ~/Games/World\ of\ Warships/ \
-e 'content/GameParams.data' -o GameParams.data
```
### 提取整个目录
要提取整个子目录,请执行:
```
./wows-depack-cli -W ~/Games/World\ of\ Warships/ \
-e 'content/' -O out/
```
### 提取所有《战舰世界》资源文件
要提取所有内容(当心你的可用磁盘空间),请运行:
```
./wows-depack-cli -W ~/Games/World\ of\ Warships/ \
-e '/' -O out/
```
### 解析特定的索引文件
除了使用 `-W/--wows-dir`,还可以通过 `-i` 或 `-I` 选项指定特定的索引文件或目录。
解析单个索引文件:
```
./wows-depack-cli -i ~/Games/World\ of\ Warships/bin/6831266/idx/system_data.idx -p
```
解析索引目录中的所有索引:
```
./wows-depack-cli -I ~/Games/World\ of\ Warships/bin/6831266/idx/ -p
```
注意,其他示例使用的是 `-W `,但通过 `-i ` 直接指定一个索引文件可能会更快。
具体来说,`GameParams.data` 在 `system_data.idx` 索引中被引用。
此外,请注意你需要调整你的 WoWs 安装路径以及 `idx/` 的父目录(每次更新时,`6831266` 这部分都会发生变化)。
## 库
### API 文档
API 文档[可在此处获取](https://wows-tools.github.io/wows-depack/wows-depack_8h.html)。
### 用法示例
#### 初始化 Context 并解析索引文件
要开始搜索/提取文件,你首先需要初始化并填充 context。
使用单个索引文件:
```
#include "wows-depack.h"
/* Other debug categories */
// WOWS_DEBUG_RAW_RECORD
// WOWS_DEBUG_FILE_LISTING
/* several debug categories can be enabled like so: */
// WOWS_DEBUG_FILE_LISTING | WOWS_DEBUG_RAW_RECORD;
WOWS_CONTEXT *context = wows_init_context(WOWS_NO_DEBUG);
/* Parse the index file */
int ret = wows_parse_index(index_file_path, context);
```
要解析索引,你可以指定一个特定的索引文件:
```
char *index_file_path = "Games/World of Warships/bin/6831266/idx/system_data.idx"
/* Parse the index file */
int ret = wows_parse_index(index_file_path, context);
```
或者,你可以解析给定目录中的所有索引文件:
```
// Note: the '6831266' directory changes every updates
char *index_dir_path = "Games/World of Warships/bin/6831266/idx"
/* Parse the index file */
int ret = wows_parse_index_dir(index_dir_path, context);
```
Wows depack 还提供了一个小助手来检测最新的 idx 目录。
```
char *index_dir_path;
get_latest_idx_dir("Games/World of Warships/", index_dir_path);
/* Parse the index file */
int ret = wows_parse_index_dir(index_dir_path, context);
// [...] do stuff
// You need to free index_dir_path after
free(index_dir_path);
```
这些操作将解析一个或多个索引文件,并构建一个随后可以浏览的伪文件系统树。
#### 搜索文件/目录
可以在索引中搜索匹配的文件:
```
// Init output variables
int resc;
char **res_files;
/* Supported search modes:
WOWS_SEARCH_FILE_ONLY < Search only on file names.
WOWS_SEARCH_DIR_ONLY < Search only on directory names.
WOWS_SEARCH_FILE_PLUS_DIR < Search on directory and file names.
WOWS_SEARCH_FULL_PATH < Search on the full path of files.
*/
// PCRE search pattern, please note that the final regex is "^$"
char *search_pattern = ".*Params.*";
// Search the files
wows_search(context, search_pattern, WOWS_SEARCH_FILE_ONLY, &resc, &res_files);
// Print and free the result
printf("Found %d matching files:\n", resc);
for (int i = 0; i < resc; i++) {
printf("%s\n", res_files[i]);
// Free Each file path must be freed
free(res_files[i]);
}
// Free the array containing these paths
free(res_files);
```
#### 提取文件
要提取文件,你可以执行以下操作:
```
char *output = "path/output.xml"
// Extract to output file
ret = wows_extract_file(context, "stuff.xml", output);
```
如果你想控制底层的 File Pointer(例如,写入内存流),提取函数还尽可能提供了 `_fp` 版本:
```
char *buf = NULL;
size_t buf_size = 0;
// Open the file
FILE *f = open_memstream(&buf, &buf_size);
// Extract to File *
ret = wows_extract_file_fp(context, "stuff.xml", f);
// Close the file
fclose(f);
free(buff);
```
你还可以递归提取给定目录下的文件:
```
char *output_dir = "./out/"
ret = wows_extract_dir(context, "/wows-resources/dockyard/", output_dir);
```
请注意,使用此提取方法,wows-depack 将以 `output_dir` 为根目录,重现 archive 中的伪文件系统。
#### 清理
完成后,你需要释放 context 的内存:
```
wows_free_context(context);
```
#### 错误处理与调试
大多数 `wows_*` 函数在成功时返回 0,在失败时返回错误码。
要将其转换为错误消息,你可以执行以下操作:
```
// wows_* function call example
int ret = wows_parse_index(index_file_path, context);
/* Error handling */
if (ret != 0) {
/* get an error message + additional info from context + return code */
char *err_msg = wows_error_string(ret, context);
printf("Error: %s\n", err_msg);
// the message must be freed
free(err_msg);
}
```
要将整个伪文件系统树打印到 `stdout`,你可以使用以下函数:
```
// Print a tree like layout
wows_print_tree(context);
// Print the full path of each file, one per line
wows_print_flat(context);
```
#### 写入支持
wows-depack 提供了用于创建 index 和 pkg 文件的实验性写入支持:
```
char *input_dir = "./tests";
FILE *nfd_pkg = fopen("stuff.pkg", "w+");
FILE *nfd_idx = fopen("stuff.idx", "w+");
wows_write_pkg(context, input_dir, "stuff.pkg", nfd_pkg, nfd_idx);
fclose(nfd_idx);
fclose(nfd_pkg);
```
请注意,写入支持是有限的,主要用于生成测试数据。
# 构建与开发
## 依赖项
在 Debian 上安装依赖项:
```
apt install cmake zlib1g-dev libpcre3-dev clang
```
安装测试/覆盖率/文档依赖项:
```
apt install lcov libcunit1-dev doxygen
```
## 构建
```
cmake .
make
```
## 安装
```
# 为系统安装移除 DESTDIR
make install DESTDIR=fakeroot
```
已安装的文件:
```
tree fakeroot
fakeroot
└── usr
└── local
├── bin
│ └── wows-depack-cli
├── include
│ └── wows-depack.h
└── lib
├── libwows-depack.so -> libwows-depack.so.0
├── libwows-depack.so.0 -> libwows-depack.so.0.1.0
└── libwows-depack.so.0.1.0
```
## 测试
要运行单元测试,请执行以下操作:
```
# cmake 运行 (按时)
cmake -DCOVERAGE=ON -DBUILD_TESTS=ON .
# 仅运行单元测试
make tests
# 也运行 coverage 测试
make coverage
```
如果遇到问题,你可以直接单独运行测试二进制文件:
```
# 直接:
./wows-depack-test
# 或使用 gdb:
gdb --args ./wows-depack-test
```
## 文档
构建 doxygen 文档:
```
cmake -DBUILD_DOC=ON .
make doc_doxygen
```
或者,获取一个更好的 doxygen 主题:
```
./misc/setup_doxycss.sh
make doc_doxygen
```
## Fuzzing
此工具/库解析二进制数据,因此检查溢出可能是个好主意。
为此,请安装 [american fuzzy lop++ (afl++)](https://aflplus.plus/):
```
# Debian/Ubuntu
apt install afl-clang
# Mac OS
brew install afl-fuzz
```
使用 afl 支持进行编译:
```
cmake -DCMAKE_CXX_COMPILER=afl-clang++ -DCMAKE_C_COMPILER=afl-clang .
make
```
运行 fuzzing
```
# 替换为你的 WoWs 安装目录
INDEX_DIR="~/Games/World\ of\ Warships/bin/6775398/idx/"
afl-fuzz -i "$INDEX_DIR" -o ./out -t 10000 -- ./wows-depack-cli -i '@@'
```
然后等待崩溃发生(希望这种情况不会出现)。
# 版本
## 0.3.0
* 切换到 libpcre2
## 0.2.0
* 修复解包时的字节序和对齐问题
## 0.1.0
* 初始版本
标签:Bash脚本, C++, CLI, CMake, PCRE2, WiFi技术, WoWs, zlib, 世界战舰, 云资产清单, 客户端加密, 工具, 库, 应急响应, 开发库, 开源, 数据擦除, 文件解包, 文件解析, 游戏, 资源提取, 逆向工程