CheckRevision

CheckRevision is a module sent by the server during the logon process. The purpose of CheckRevision is to ensure that only official, unmodified Battle.net clients are connecting to Battle.net servers. Some PvPGN servers have been known to compile their own CheckRevision modules to add client-side features or detect hacks.

Procedure

In all versions of CheckRevision, the following procedure is used to obtain CheckRevision and run it to return some values to the server:

  1. The client sends the server its platform ID, product ID, and version byte via
    C>S 0x06 SID_STARTVERSIONING
    or C>S 0x50 SID_AUTH_INFO.

  2. The server will then determine which CheckRevision to serve the client and then send the appropriate filename and filetime of the CheckRevision MPQ and a formula for the CheckRevision function via S>C 0x06 SID_STARTVERSIONING or S>C 0x50 SID_AUTH_INFO.

  3. The client checks bncache for CheckRevision. If CheckRevision is not found in bncache, the client initiates a BNFTPv1 connection to download CheckRevision.

  4. The client verifies that the CheckRevision MPQ contains a valid Blizzard Weak Digital Signature. If one is not found, the client immediately closes the connection to the server. It appears that this does not apply for XMAC/PMAC clients.

  5. The client extracts the CheckRevision DLL, whose base filename is the same as the CheckRevision MPQ's base filename (e.g. CheckRevision.mpq contains CheckRevision.dll). Modern versions of game clients verifies the CheckRevision DLL's signature. If one is not found, the client immediately closes the connection to the server.

  6. The client calls CheckRevision(). If the function returns 0, the client immediately closes the connection to the server.

  7. Information returned from CheckRevision() is sent to the server via C>S 0x07 SID_REPORTVERSION or C>S 0x51 SID_AUTH_CHECK.

CheckRevision() function declaration in C++

extern "C" __declspec(dllexport) std::int32_t __stdcall CheckRevision(const char* filename1, const char* filename2, const char* filename3, const char* formula, std::uint32_t* version, std::uint32_t* checksum, char* exeinfo);

Filenames

Product filename1 filename2 filename3
W2BN WarCraft II BNE.exe Storm.dll Battle.snp
STAR, SEXP StarCraft.exe Storm.dll Battle.snp
D2DV, D2XP Game.exe Bnclient.dll D2Client.snp
WAR3, W3XP War3.exe Storm.dll Game.dll

* - In the more recent versions of some products, NULL pointers are passed in for the filename2 and filename3 when the corresponding files are missing.

Version 1a

Introduced around March 1997, and also known as "classic CheckRevision", this version uses the following naming format: {PLATFORM}ver{NUM}.mpq (ex: IX86ver0.mpq).

{PLATFORM}: IX86, XMAC, PMAC

{NUM}: 0 - 7

Formula/Seed

The formula given by the server is generally in the following format: A={int} B={int} C={int} 4 A=A{op}S B=B{op}C C=C{op}A A=A{op}B.

{int}: A positive integer, whose max value is presumably the max value of a 32-bit signed integer.

{op}: +, -, *, /, ^ (XOR)

Example formulas:

It is possible that some operators may never be used, and also possible that the operands will not be consistent, so custom implementations should be wary of this.

In some cases, Battle.net may return a "default" formula, A=0 B=0 C=0 4 A=A+S C=C+A.

Known Cases:

- Connecting with StarCraft pre-1.18

Checksum Algorithm

Each file is compiled with a different "hash code" that is first XOR'd with the A value from the formula.

For {NUM} 0-7, the hash codes are 0xE7F4CB62, 0xF6A14FFC, 0xAA5504AF, 0x871FCDC2, 0x11BF6A18, 0xC57292E6, 0x7927D27E, and 0x2FEC8733 respectively.

Each of up to 3 hash files are read in 4-byte chunks (as integers) as 'S' and then each operation in the formula is performed on every chunk. The resulting value of 'C' is returned as the checksum.

Version and EXE Info

The version value is a combination of dwProductVersionMS and dwProductVersionLS from VS_FIXEDFILEINFO for the EXE.

The exeinfo value is a space-delimited C string containing the following values:

  1. EXE Name (ex. war3.exe)
  2. Last Modified Date (ex. 08/16/09)
  3. Last Modified Time (ex. 19:21:59)
  4. Filesize in bytes (ex. 471040)

An example of a valid string would be: war3.exe 08/16/09 19:21:59 471040

Version 1b

In late 2006, Blizzard began to serve CheckRevision 1b to Diablo 2 and WarCraft 3 clients. Perhaps the main reason for this update is due to a bug in CheckRevision 1a's checksum algorithm that results in an access violation error on systems with Data Execution Prevention (DEP) enabled.

This version uses the following naming format: ver-{PLATFORM}-{NUM}.mpq (ex: ver-IX86-3.mpq).

{PLATFORM}: IX86, XMAC, PMAC, OSXI

{NUM}: 0 - 7

Formula/Seed

The formula format is the same as in CheckRevision 1a.

Checksum Algorithm

The only change in the algorithm is that the hashed files were padded to the next 1024-byte interval using bytes of descending values starting at 0xFF and going to 0x00 before looping back around.

Digital Signing

In May 2016, Blizzard signed CheckRevision 1b DLLs. Starting with StarCraft 1.17.0 and Diablo II 1.14d, the client will verify the signature of the CheckRevision DLL.

Version 2

CheckRevision 2 is a relatively sophisticated library introduced in late 2006 and served to Diablo, StarCraft, and WarCraft 2 clients. This version incorporates stronger defense measures than previous versions of CheckRevision.

There are two variants of CheckRevision 2, lockdown and psistorm for PC and Mac clients respectively. This version uses the following naming format: {VARIANT}-{PLATFORM}-{NUM}.mpq (ex: lockdown-IX86-03.mpq or psistorm-XMAC-11.mpq).

{VARIANT}: lockdown, psistorm

{PLATFORM}: IX86 (valid only for lockdown variant), XMAC(valid only for psistorm variant), PMAC(valid only for psistorm variant)

{NUM}: 00 - 19

Formula/Seed

TODO.

Checksum Algorithm

The algorithm for this version is somewhat more complicated. In short (for Lockdown at least), the seed string is shuffled and then hashed along with various parts of the game files, the library (DLL) itself, and a dump from the game's video memory. The hashing function used for this hash is another variation of SHA-1 (different from both standard SHA-1 and XSHA-1 used in password hashing).

For more information, see the following resources:

Version and EXE Info

The version value is the same as from CheckRevision v1.

The info value is a null-terminated, shuffled continuation of the hash digest returned when calculating the checksum. The shuffling process will sometimes affect the size of this value, so it may not always be 16 bytes in length (not including the terminator).

Version 3a

After a server reset on January 4, 2019, Battle.net began serving CheckRevision 3a to Diablo 2 clients. Unlike previous versions, this version does not have multiple variants. The file name is CheckRevision.mpq.

Formula/Seed

The seed is a base64-encoded, 9 byte (including the null terminator) value. Unlike previous versions, the seed appears to be randomly generated for each connection.

Example seeds:

Checksum Algorithm

The algorithm is much simpler than the algorithm from previous versions. It does not verify the full checksum of the client, instead it verifies the executable's file version number. Because of this it can be emulated without having a copy of the client executable.

Once decoded, the first 4 bytes of the seed are combined with a colon :, the executable's file version number (as a dot-separated string, ex: 1.14.3.71), another colon, and a single byte 0x01. This value is then hashed using standard SHA-1.

result = b64encode(sha1(b64decode(seed)[:4], ':' + version + ':', 0x01))

The first 4 bytes of this result are used as the checksum value.

Version and EXE Info

The version value is always 0.

The exeinfo value is a null-terminated continuation of the result. It should be 25 bytes long, including the null terminator.

Version 3b

Version 3b appeared along with the re-release of Diablo 1 and WarCraft 2. It is (so far) only used for these 2 games, and only on their entirely separate, special server connect-forever.classic.blizzard.com. Like version 3a, this version does not have any variants. The file name is CheckRevisionD1.mpq.

If calling the CheckRevision() function from the v3 DLL, the calling app's version needs to match the version of the game EXE and have any valid signature.

Formula/Seed

The seed format for this version is the same as for version 3a.

Checksum Algorithm

In addition to the checksum algorithm in version 3a, version 3b includes the base64-encoded SHA1 hash of the executable file signature's public key (as a hex string) and the 4-byte seed value, appended to the result, after a colon ':'. This only affects the value returned for exeinfo.

result += ':' + b64encode(sha1(public_key, value))

See the implementation in Warden.dll for more details.

Version and EXE Info

The version value is always 6.

The exeinfo value is a null-terminated continuation of the result.

History

| Edited: xboi209

Comments

Davnit

Added information on the new algorithm for v3.

xboi209

I found that if D2 1.13c is served IX86ver1.mpq, it crashes with a 0xc00000005 error. Serving it ver-IX86-1.mpq, which is what Battle.net served, no longer causes it to crash. This leads me to think that Blizzard didn't just rename CheckRevision v1 files in 2006, they probably recompiled CheckRevision v1 with the same code or different code while keeping the output the same.

xboi209

ix86std.dll is found in an MPQ embedded in DRTL 1.02, 1.03, and 1.04 manual patches.

xboi209

Recently (possibly on August 13), Blizzard removed many CheckRevision v2 files from US West, US East, and Europe servers. As of now, Asia server still retains all of the CheckRevision v2 files.

I tested the following at US West:

lockdown-IX86-{NUM}.mpq: 00 still exists, 01 - 19 are removed.

psistorm-PMAC-{NUM}.mpq: 00 still exists. 01, 02, and presumably the rest have been removed too.

psistorm-XMAC-{NUM}.mpq: 00 - 02 no longer exists, presumably the rest have been removed too.

When attempting to connect to US West, US East, or Europe with W2BN, Battle.net sends SID_STARTVERSIONING with a randomly chosen CheckRevision v2 filename despite that the chosen file may be missing. The filetime is null if the file is missing. The client hangs after receiving this packet if the filetime is null.