wowdump 0.0.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +131 -0
- package/dist/adapters.js +101 -0
- package/dist/agent.js +1335 -0
- package/dist/analysis-path.js +38 -0
- package/dist/analysis-process-log.js +146 -0
- package/dist/broker-client.js +411 -0
- package/dist/broker-codec.js +148 -0
- package/dist/broker-core.js +1045 -0
- package/dist/broker-gateway.js +447 -0
- package/dist/broker-ledger.js +196 -0
- package/dist/broker-main.js +291 -0
- package/dist/broker-protocol.js +119 -0
- package/dist/broker-runtime.js +1283 -0
- package/dist/broker-server.js +466 -0
- package/dist/build-bundle-loader.js +183 -0
- package/dist/build-bundle.js +11 -0
- package/dist/discovery.js +59 -0
- package/dist/dry-run.js +38 -0
- package/dist/error-log.js +71 -0
- package/dist/focus-errors.js +63 -0
- package/dist/focus-service.js +1855 -0
- package/dist/focused-session.js +1357 -0
- package/dist/frida-runtime.js +711 -0
- package/dist/mcp-main.js +51 -0
- package/dist/mcp.js +924 -0
- package/dist/observability.js +41 -0
- package/dist/process-log-lock.js +181 -0
- package/dist/processes.js +47 -0
- package/dist/runtime-config.js +399 -0
- package/dist/session.js +145 -0
- package/dist/storage.js +12 -0
- package/dist/types.js +26 -0
- package/dist/wow-analysis.js +1430 -0
- package/package.json +64 -13
- package/resources/builds/retail/12.0.7.68974/build-profile.json +290 -0
- package/resources/builds/retail/12.0.7.68974/data-sources.json +1633 -0
- package/resources/builds/retail/12.0.7.68974/lua-targets.jsonl +5130 -0
- package/resources/builds/retail/12.0.7.68974/manifest.json +63 -0
- package/resources/builds/retail/12.0.7.68974/signatures.json +260 -0
- package/index.js +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Follenfang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1 +1,132 @@
|
|
|
1
1
|
# wowdump
|
|
2
|
+
|
|
3
|
+
`wowdump` is a build-aware World of Warcraft runtime analysis MCP server. It exposes Frida process control, focused Lua/C++ tracing, bounded data watches, build profile validation, and verified data readers over the MCP `2026-07-28` protocol.
|
|
4
|
+
|
|
5
|
+
The package supports multiple WoW flavors and builds. `retail` is a flavor in a build key such as `retail@12.0.7.68974`; it is not part of the product name.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Run directly from an MCP client:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"mcpServers": {
|
|
14
|
+
"wowdump": {
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": [
|
|
17
|
+
"-y",
|
|
18
|
+
"wowdump",
|
|
19
|
+
"--game-root",
|
|
20
|
+
"D:\\Game\\World of Warcraft"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or install it globally:
|
|
28
|
+
|
|
29
|
+
```powershell
|
|
30
|
+
npm install --global wowdump
|
|
31
|
+
wowdump --game-root "D:\Game\World of Warcraft"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The `wowdump` executable only starts the stdio MCP server. It is not a separate interactive CLI.
|
|
35
|
+
|
|
36
|
+
## Game Directories
|
|
37
|
+
|
|
38
|
+
Game directories are resolved once when the MCP server starts. The first non-empty source wins:
|
|
39
|
+
|
|
40
|
+
1. Repeatable `--game-root <path>` arguments.
|
|
41
|
+
2. `WOWDUMP_GAME_ROOTS` as a semicolon-separated list on Windows.
|
|
42
|
+
3. `game_roots` in the TOML file selected by `--config <path>`.
|
|
43
|
+
4. `%LOCALAPPDATA%\wowdump\config.toml`.
|
|
44
|
+
5. Automatic detection from verified Battle.net Agent installation metadata, followed by common Windows installation locations.
|
|
45
|
+
|
|
46
|
+
Example persistent configuration:
|
|
47
|
+
|
|
48
|
+
```toml
|
|
49
|
+
game_roots = [
|
|
50
|
+
"D:/Game/World of Warcraft",
|
|
51
|
+
"E:/World of Warcraft"
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
broker_idle_ms = 1200000
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`WOW_ROOT` remains a deprecated compatibility fallback. Invalid selected paths are reported on stderr and are not silently replaced by a lower-priority source.
|
|
58
|
+
|
|
59
|
+
PID, build, module base, Frida sessions, Hook IDs, and runtime addresses are never persisted in TOML. They are discovered and validated for the current process.
|
|
60
|
+
|
|
61
|
+
## Selecting A Target
|
|
62
|
+
|
|
63
|
+
Use these read-only tools before starting a dynamic session:
|
|
64
|
+
|
|
65
|
+
- `wow_install_list`: installed game directories and flavors.
|
|
66
|
+
- `wow_build_list`: detected build keys and versions.
|
|
67
|
+
- `wow_target_list`: running Wow.exe PIDs matched to an installation and build.
|
|
68
|
+
|
|
69
|
+
Focused and trace operations accept an explicit `pid` and `buildKey`. The server rejects PID/build mismatches and does not reuse a historical PID or module base.
|
|
70
|
+
|
|
71
|
+
## MCP Tools
|
|
72
|
+
|
|
73
|
+
The primary tool groups are:
|
|
74
|
+
|
|
75
|
+
- `frida_command`: generic Frida read, write, script, Hook, process, and session operations.
|
|
76
|
+
- `wow_lua_trace_*` and `wow_cpp_trace_*`: build-aware bounded trace sessions.
|
|
77
|
+
- `wow_focus_*`, `wow_watch_*`, and `wow_session_checkpoint`: explicit before/during/after analysis windows.
|
|
78
|
+
- `wow_data_source_*`, `wow_data_read`, and `wow_build_profile_validate`: verified build data and readers.
|
|
79
|
+
- `wow_broker_*`: Broker status, start, reconnect, and stop.
|
|
80
|
+
- `wow_analysis_coverage` and `wow_analysis_checkpoint`: static profile coverage and checkpoints.
|
|
81
|
+
|
|
82
|
+
The server rejects legacy MCP handshakes. Protocol output is written only to stdout; diagnostics are written to stderr.
|
|
83
|
+
|
|
84
|
+
## Runtime Layout
|
|
85
|
+
|
|
86
|
+
Production uses three distinct directory roles:
|
|
87
|
+
|
|
88
|
+
- Package `resources/builds`: read-only, build-specific profiles and signatures.
|
|
89
|
+
- `%LOCALAPPDATA%\wowdump`: writable Broker ledgers, focused sessions, logs, and cache.
|
|
90
|
+
- Repository `analyze/vm`: offline analysis inputs and intermediate evidence; it is not required by the installed package.
|
|
91
|
+
|
|
92
|
+
Stable overrides can be placed in TOML:
|
|
93
|
+
|
|
94
|
+
```toml
|
|
95
|
+
profile_root = "D:/wowdump-profiles"
|
|
96
|
+
runtime_root = "C:/Users/ACCOUNT/AppData/Local/wowdump"
|
|
97
|
+
log_level = "info"
|
|
98
|
+
broker_idle_ms = 1200000
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The MCP process does not own Frida sessions. A single per-user `wowdump-broker` process owns attach/detach, scripts, Hooks, Interceptors, request forwarding, and cleanup. Requests refresh its idle timer; the default idle timeout is 20 minutes.
|
|
102
|
+
|
|
103
|
+
## Packaged Builds
|
|
104
|
+
|
|
105
|
+
This release includes a verified profile for:
|
|
106
|
+
|
|
107
|
+
- `retail@12.0.7.68974`
|
|
108
|
+
|
|
109
|
+
Every build has its own RVA profile, entry signatures, data sources, and manifest hashes. A new build must be relocated and validated; old RVAs are not automatically reused.
|
|
110
|
+
|
|
111
|
+
## Development
|
|
112
|
+
|
|
113
|
+
```powershell
|
|
114
|
+
npm install
|
|
115
|
+
npm run typecheck
|
|
116
|
+
npm test
|
|
117
|
+
npm run build
|
|
118
|
+
npm run bundle:verify
|
|
119
|
+
npm run package:verify
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
To regenerate the packaged bundle from the repository-only analysis workspace:
|
|
123
|
+
|
|
124
|
+
```powershell
|
|
125
|
+
npm run bundle:build
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`npm run package:verify` enforces the npm file whitelist, creates a real tarball, installs it in a temporary directory, starts the installed `wowdump` bin, and performs an MCP `2026-07-28` handshake.
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
MIT
|
package/dist/adapters.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
const UNSUPPORTED_REASON = "No verified read-only adapter is registered for this build";
|
|
2
|
+
function normalizeBuildKey(buildKey) {
|
|
3
|
+
return buildKey.trim();
|
|
4
|
+
}
|
|
5
|
+
function cloneCapabilities(capabilities) {
|
|
6
|
+
return Object.freeze({
|
|
7
|
+
errorMessage: capabilities.errorMessage,
|
|
8
|
+
sourceLocation: capabilities.sourceLocation,
|
|
9
|
+
stackTrace: capabilities.stackTrace,
|
|
10
|
+
vmMetadata: capabilities.vmMetadata
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function cloneAdapter(adapter) {
|
|
14
|
+
return Object.freeze({
|
|
15
|
+
...adapter,
|
|
16
|
+
buildKey: normalizeBuildKey(adapter.buildKey),
|
|
17
|
+
capabilities: cloneCapabilities(adapter.capabilities)
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function assertAdapter(adapter) {
|
|
21
|
+
if (!adapter || typeof adapter !== "object") {
|
|
22
|
+
throw new TypeError("adapter must be an object");
|
|
23
|
+
}
|
|
24
|
+
if (typeof adapter.buildKey !== "string" || !normalizeBuildKey(adapter.buildKey)) {
|
|
25
|
+
throw new TypeError("adapter.buildKey must be a non-empty string");
|
|
26
|
+
}
|
|
27
|
+
if (typeof adapter.name !== "string" || !adapter.name.trim()) {
|
|
28
|
+
throw new TypeError("adapter.name must be a non-empty string");
|
|
29
|
+
}
|
|
30
|
+
if (typeof adapter.verification !== "string" || !adapter.verification.trim()) {
|
|
31
|
+
throw new TypeError("adapter.verification must identify the verification proof");
|
|
32
|
+
}
|
|
33
|
+
if (adapter.fridaPrelude !== undefined) {
|
|
34
|
+
if (typeof adapter.fridaPrelude !== "string") {
|
|
35
|
+
throw new TypeError("adapter.fridaPrelude must be a string when provided");
|
|
36
|
+
}
|
|
37
|
+
if (Buffer.byteLength(adapter.fridaPrelude, "utf8") > 1024 * 1024) {
|
|
38
|
+
throw new TypeError("adapter.fridaPrelude exceeds the 1 MiB limit");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const capabilities = adapter.capabilities;
|
|
42
|
+
if (!capabilities || typeof capabilities !== "object") {
|
|
43
|
+
throw new TypeError("adapter.capabilities must be provided");
|
|
44
|
+
}
|
|
45
|
+
for (const field of ["errorMessage", "sourceLocation", "stackTrace", "vmMetadata"]) {
|
|
46
|
+
if (typeof capabilities[field] !== "boolean") {
|
|
47
|
+
throw new TypeError(`adapter.capabilities.${field} must be boolean`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create an immutable registry from verified definitions.
|
|
53
|
+
*
|
|
54
|
+
* The default is intentionally empty: until a build-specific read-only proof
|
|
55
|
+
* is supplied, every build is reported as unsupported.
|
|
56
|
+
*/
|
|
57
|
+
export function createBuildAdapterRegistry(definitions = []) {
|
|
58
|
+
const adapters = new Map();
|
|
59
|
+
for (const definition of definitions) {
|
|
60
|
+
assertAdapter(definition);
|
|
61
|
+
const adapter = cloneAdapter(definition);
|
|
62
|
+
if (adapters.has(adapter.buildKey)) {
|
|
63
|
+
throw new Error(`Duplicate adapter for build key ${adapter.buildKey}`);
|
|
64
|
+
}
|
|
65
|
+
adapters.set(adapter.buildKey, adapter);
|
|
66
|
+
}
|
|
67
|
+
return Object.freeze({
|
|
68
|
+
lookup(buildKey) {
|
|
69
|
+
const key = normalizeBuildKey(buildKey);
|
|
70
|
+
const adapter = adapters.get(key);
|
|
71
|
+
if (!adapter) {
|
|
72
|
+
return Object.freeze({
|
|
73
|
+
buildKey: key,
|
|
74
|
+
status: "unsupported",
|
|
75
|
+
reason: UNSUPPORTED_REASON
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return Object.freeze({
|
|
79
|
+
buildKey: key,
|
|
80
|
+
status: "verified",
|
|
81
|
+
adapter
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
list() {
|
|
85
|
+
return Object.freeze([...adapters.values()]);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** Empty-by-default registry used by callers that have no verified builds. */
|
|
90
|
+
export const buildAdapterRegistry = createBuildAdapterRegistry();
|
|
91
|
+
/** Look up a build in the default empty registry. */
|
|
92
|
+
export function getBuildAdapter(buildKey) {
|
|
93
|
+
return buildAdapterRegistry.lookup(buildKey);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Convert a discovered install to an adapter lookup without widening the
|
|
97
|
+
* registry API or introducing build-specific assumptions.
|
|
98
|
+
*/
|
|
99
|
+
export function getBuildAdapterForBuild(build) {
|
|
100
|
+
return getBuildAdapter(build.buildKey);
|
|
101
|
+
}
|