WC3 1.29.2 client support (with real password auth) - #501
Open
Vegasq wants to merge 10 commits into
Open
Conversation
Confirmed planned section lists for CLAUDE.md and docs/architecture.md match the actual file inventory in src/, conf/, lua/, cmake/, and CI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add docs/architecture.md covering repository layout, daemons and binaries, bnetd/common/compat module maps, runtime model, configuration system, storage layer, protocol handlers with port defaults, optional Lua scripting, logging, and the CMake build option matrix. Every concrete claim (file paths, function names, port defaults, namespaces, option flags) is verified against the source in this snapshot. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Concise (~376 line) developer onboarding doc covering build/test/run commands, codebase map, coding conventions, logging, configuration workflow, storage backends, Lua scripting, command/protocol-handler extension points, common pitfalls, and CI. Links out to README.md, README.DEV, and docs/architecture.md for depth instead of duplicating their content. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final verification pass. Cross-checked every cited file path, function name, CMake option, namespace, port number, and default constant against the snapshot and corrected the drift that turned up: - t_handler signature was missing the trailing const on the t_packet pointer in both docs (handlers.h declares int(*)(t_connection *, t_packet const * const)). - Lua bridge teardown was misattributed to post_server_shutdown(); the function is only invoked from the SIGHUP rehash path in server_process() under restart_mode_lua / restart_mode_all. - Chat-command guidance contradicted itself on static vs unnamed namespace; rewrote it to acknowledge that command.cpp predates the README.DEV 5.e rule and to advise matching the surrounding style. CLAUDE.md is 383 lines (within the 300-500 target). No source, CMake, or configuration files were modified by this branch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- CLAUDE.md: udptest is not a standalone binary; clarify that src/client/udptest.cpp compiles into bnchat and bnstat - docs/readme.md: index the existing docs/versioncheck.md, which was missing from the table Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds enough server- and client-side glue for a vanilla Warcraft III
1.29.2.9231 client to log into a PvPGN server with real password
verification. The SRP3 protocol divergence between PvPGN and 1.29 is
sidestepped W3CE-style: the client is patched to emit
bnet_hash(password) where SRP3 would have sent its M1, and PvPGN's
existing legacy passhash1 / hash_eq fallback validates that without
any server-side cryptographic bypass.
Server side
-----------
- conf/versioncheck.json.in: add 0x1d verbyte rows under both WAR3
and W3XP for game version 1.29.2.15 (CheckRevision 0x3cc7eaf6).
- src/bnetd/handle_bnet.cpp:2951: fix a {fmt} crash in
_client_motdw3 where '"{}" + \'\\n\'' was C++ pointer arithmetic,
not concatenation. The daemon would FATAL on the first MOTD
render. Pre-existing bug; only manifested with 1.29 because that
was the first version that got far enough to request the W3 MOTD
on this code path.
Client patcher (contrib/wc3-1.29-client-patch/)
-----------------------------------------------
- bnet_hash.c: clean C reference port of PvPGN's modified-SHA1
(do_blizzard_hash variant of bnet_hash from
src/common/bnethash.cpp). Compiled with `gcc -m32 -O2
-ffreestanding -nostdlib`, no libc / no external symbols. Also
defines lph_checked_hook, the LphChecked replacement that calls
bnet_hash on the lowercased ASCII password.
- build_payload.py: orchestrator. Reads the input EXE, verifies
MD5, compiles bnet_hash.c via gcc + ld --oformat=binary,
assembles the CreateAccount trampoline + wrapper via
keystone-engine, strips the (now-invalid) Authenticode signature,
appends a new PE section ".pvpgnh" with the cave content, and
patches four entry points in .text:
0x00831424 6-byte JNE -> multibyte NOP (auth_req)
0x00830DDB 74 21 -> 75 20 (M2-dispatch flip)
0x0083A590 push ebp;... -> JMP lph_checked (LphChecked entry)
0x00986A50 push ebp;... -> JMP wrapper (CreateAccount)
Output for 1.29.2.9231 is deterministic; reference MD5
729ac6d7b8438d9579c9a1738ef2d42a.
- README.md: usage + how it works + caveats.
Documentation
-------------
- docs/wc3-1.29-pvpgn-notes.md: full binary-analysis writeup of
the 1.29.2.9231 internals (where the gateway INI lives, how
CheckRevision is keyed, the auth_req signature hunt, the M2
verifier hunt, the motdw3 bug). Historical bypass-mode
intermediate work is referenced; that lives in the separate
wc3-1.29-bypass-mode branch.
- docs/wc3-1.29-real-auth-plan.md: design plan + W3CE analysis
that produced the patcher.
- TODO.md: short status. What's done, what's still open.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Vegasq
marked this pull request as draft
May 2, 2026 13:17
Vegasq
marked this pull request as ready for review
May 2, 2026 13:25
Member
|
I don't have WC3 installed to confirm any of this. Accepting other reviewers to chime in |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WC3 1.29.2 client support (with real password auth)
Adds enough server- and client-side glue for a vanilla Warcraft III
1.29.2.9231 client to log into PvPGN with a properly verified password.
The SRP3 protocol divergence between PvPGN and 1.29 — PvPGN's
implementation was written for 1.27/1.28 and the proofs don't match —
is sidestepped W3CE-style: the client is patched to emit
bnet_hash(password)where SRP3 would have sent its M1, and PvPGN'sexisting legacy
passhash1/hash_eqfallback validates thatwithout any server-side cryptographic bypass.
End-to-end working against an upstream-style PvPGN. Wrong passwords
fail. Login then proceeds to channel join, MOTD, etc. as normal.
Server-side changes
conf/versioncheck.json.in— adds0x1dverbyte rows underboth
WAR3andW3XPblocks for game version 1.29.2.15(CheckRevision
0x3cc7eaf6).src/bnetd/handle_bnet.cpp:2951— fix a pre-existing{fmt}crash in
_client_motdw3. The linefmt::format_to(serverinfo, "{}" + '\n', ...)was C++ pointer arithmetic, not stringconcatenation, and crashed bnetd with
FATAL ERROR: argument index out of rangethe first time the W3 MOTD was rendered. Fixed to"{}\n". Independent of 1.29 work but only manifested with 1.29because that was the first version that got far enough to request
the W3 MOTD on this code path.
Client-side patcher (new,
contrib/wc3-1.29-client-patch/)A Linux-side EXE patcher that produces a self-contained patched
Warcraft III.exe— no DLLs, no loaders, no runtime injection.Mirrors what
W3CE's
PvPGNPatcherdoes (analysed from W3CE-v0.2.1-alpha) but as a staticpatch.
The patcher appends a new PE section (
.pvpgnh) containing:bnet_hash()fromsrc/common/bnethash.cpp(
do_blizzard_hashvariant), compiled from C with no libc and noexternal symbols.
LphCheckedreplacement (replaces the SRP3 M1 computation —the client now sends
bnet_hash(lower(password))as the 20-bytelogon proof).
CreateAccounttrampoline + wrapper that calls the original,then copies the plaintext password into the verifier slot — PvPGN
reads this as a null-terminated plaintext string and stores
passhash1 = bnet_hash(plaintext).Plus four byte patches in
.text:auth_req0x008314240x00830DDB74 21 → 75 20flip. Lets the client accept an all-zero M2 reply (which is what PvPGN's legacyhash_eqsuccess path emits).LphCheckedentry0x0083A590JMPto the newlph_checked_hookin the cave.CreateAccountentry0x00986A50JMPto the new wrapper.For 1.29.2.9231 the output is deterministic — current reference MD5
729ac6d7b8438d9579c9a1738ef2d42a.Build:
Documentation
docs/wc3-1.29-pvpgn-notes.md— full binary-analysis writeup ofthe 1.29.2.9231 internals: where the gateway INI lives (note the
1.29-specific
BattleNet\subfolder), how CheckRevision is keyed,the auth_req signature hunt, the M2 verifier hunt, the motdw3 bug.
docs/wc3-1.29-real-auth-plan.md— design plan + W3CE analysisthat produced the patcher.
contrib/wc3-1.29-client-patch/README.md— usage + caveats.Caveats
any byte breaks Blizzard's signature; the build also clears the
Security data directory entry. Windows SmartScreen may warn
("Unknown Publisher") on first launch.
ASCII A–Z. PvPGN's own create-account also lowercases ASCII-only
via
strtolower, so this matches upstream behaviour.byte offsets (vanilla MD5
c453b4a0bde1a47f41cb2475573edb84).Other 1.29.x sub-versions need offsets re-derived; methodology in
the docs.
BNCS entirely.
Testing
Verified end-to-end on a 1.29.2.9231 install on Windows 10, against
this branch's bnetd built on Ubuntu 24.04:
passhash1 = bnet_hash(lower(password))and
saltandverifier(the SRP3 ones from the client, unusedby the legacy auth path).
_client_logonproofreqhash_eqsuccess branch — log message"<user>" logged in (right password).got wrong client password proof for "<user>".Warcraft 3 Frozen Throne), MOTDloads, anongame info requests work.