wowdump 0.0.0 → 0.2.1

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.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +131 -0
  3. package/dist/adapters.js +101 -0
  4. package/dist/agent.js +1335 -0
  5. package/dist/analysis-path.js +38 -0
  6. package/dist/analysis-process-log.js +146 -0
  7. package/dist/broker-client.js +411 -0
  8. package/dist/broker-codec.js +148 -0
  9. package/dist/broker-core.js +1045 -0
  10. package/dist/broker-gateway.js +447 -0
  11. package/dist/broker-ledger.js +196 -0
  12. package/dist/broker-main.js +291 -0
  13. package/dist/broker-protocol.js +119 -0
  14. package/dist/broker-runtime.js +1283 -0
  15. package/dist/broker-server.js +466 -0
  16. package/dist/build-bundle-loader.js +183 -0
  17. package/dist/build-bundle.js +11 -0
  18. package/dist/discovery.js +59 -0
  19. package/dist/dry-run.js +38 -0
  20. package/dist/error-log.js +71 -0
  21. package/dist/focus-errors.js +63 -0
  22. package/dist/focus-service.js +1855 -0
  23. package/dist/focused-session.js +1357 -0
  24. package/dist/frida-runtime.js +711 -0
  25. package/dist/mcp-main.js +51 -0
  26. package/dist/mcp.js +924 -0
  27. package/dist/observability.js +41 -0
  28. package/dist/process-log-lock.js +195 -0
  29. package/dist/processes.js +47 -0
  30. package/dist/runtime-config.js +399 -0
  31. package/dist/session.js +145 -0
  32. package/dist/storage.js +12 -0
  33. package/dist/types.js +26 -0
  34. package/dist/wow-analysis.js +1430 -0
  35. package/package.json +64 -13
  36. package/resources/builds/retail/12.0.7.68974/build-profile.json +290 -0
  37. package/resources/builds/retail/12.0.7.68974/data-sources.json +1633 -0
  38. package/resources/builds/retail/12.0.7.68974/lua-targets.jsonl +5130 -0
  39. package/resources/builds/retail/12.0.7.68974/manifest.json +63 -0
  40. package/resources/builds/retail/12.0.7.68974/signatures.json +260 -0
  41. 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
@@ -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
+ }