Valhalla Legends Forums Archive | Battle.net Bot Development | Deriving version byte?

AuthorMessageTime
iago
I know it's been discussed before, but has anybody done any work on deriving the version byte from the game's files?  I've always meant to go back and figure out where it comes from, but I've never gotten around to it. 
January 29, 2006, 7:45 PM
Skywing
There is no good way to do this.  It's hardcoded as part of an immediate instruction operand in most cases.

For some games, it has often been the rule that the version code is always the minor version, but this is not the case for all games and not something I'd rely on.

The perhaps most reliable way to do it is to just bruteforce the version code starting at the current one and incrementing once per connection attempt until you find the new one.
January 29, 2006, 7:54 PM
Yegg
[quote author=Skywing link=topic=14049.msg143689#msg143689 date=1138564486]
The perhaps most reliable way to do it is to just bruteforce the version code starting at the current one and incrementing once per connection attempt until you find the new one.
[/quote]

I once considered that very same method. However, the game client must somehow obtain the version byte. It makes sense that the server would send it to the client? Why is it that we cannot immitate the client in this area?
January 29, 2006, 8:48 PM
UserLoser
[quote author=Yegg link=topic=14049.msg143695#msg143695 date=1138567734]
I once considered that very same method. However, the game client must somehow obtain the version byte. It makes sense that the server would send it to the client? Why is it that we cannot immitate the client in this area?
[/quote]

Because:
[quote author=Skywing link=topic=14049.msg143689#msg143689 date=1138564486]
It's hardcoded as part of an immediate instruction operand in most cases.

For some games, it has often been the rule that the version code is always the minor version, but this is not the case for all games and not something I'd rely on.
[/quote]
January 29, 2006, 8:49 PM
Yegg
[quote author=UserLoser link=topic=14049.msg143696#msg143696 date=1138567788]
[quote author=Yegg link=topic=14049.msg143695#msg143695 date=1138567734]
I once considered that very same method. However, the game client must somehow obtain the version byte. It makes sense that the server would send it to the client? Why is it that we cannot immitate the client in this area?
[/quote]

Because:
[quote author=Skywing link=topic=14049.msg143689#msg143689 date=1138564486]
It's hardcoded as part of an immediate instruction operand in most cases.

For some games, it has often been the rule that the version code is always the minor version, but this is not the case for all games and not something I'd rely on.
[/quote]
[/quote]

I figured I'd get an answer like this. However I don't understand the hardcoded part. Does the client send the server something to check for an updated version of the game? Or does the server send something to the client? I don't understand how if the server were to send something to the client, we cant receive this message and figure out what the value is.
January 29, 2006, 8:52 PM
Topaz
The client sends the current version byte, and the server checks it against the current.
January 29, 2006, 9:07 PM
iago
When the game is updated, parts of the game are re-written to work differently.  The version byte is part of one of those sections.  So there might be code like:

version_byte = 0xC7;
game.send(version_byte);

Which, when you update it, changes to:

version_byte = 0xC9;
game.send(version_byte);

There is no good way to find that code, unfortunately. 
January 29, 2006, 9:10 PM
UserLoser
[quote author=Yegg link=topic=14049.msg143697#msg143697 date=1138567933]
I figured I'd get an answer like this. However I don't understand the hardcoded part. Does the client send the server something to check for an updated version of the game? Or does the server send something to the client? I don't understand how if the server were to send something to the client, we cant receive this message and figure out what the value is.
[/quote]

The version byte is hardcoded in your bot, unless you're using BNLS/something else like it so I don't get the confusion.

When there's a new patch, you'll get a version update required message, say, in SID_AUTH_CHECK.  Then the client downloads the patch file given, and performs the patching routine.  Then the game files the client has (Starcraft.exe, Battle.snp, etc) are updated and the game restarts.  Since Starcraft.exe was patched, there is a new hardcoded value for the version code and then that's just sent again next time you connect.
January 29, 2006, 9:42 PM
iago
[quote author=UserLoser link=topic=14049.msg143704#msg143704 date=1138570971]
[quote author=Yegg link=topic=14049.msg143697#msg143697 date=1138567933]
I figured I'd get an answer like this. However I don't understand the hardcoded part. Does the client send the server something to check for an updated version of the game? Or does the server send something to the client? I don't understand how if the server were to send something to the client, we cant receive this message and figure out what the value is.
[/quote]

The version byte is hardcoded in your bot, unless you're using BNLS/something else like it so I don't get the confusion.

When there's a new patch, you'll get a version update required message, say, in SID_AUTH_CHECK.  Then the client downloads the patch file given, and performs the patching routine.  Then the game files the client has (Starcraft.exe, Battle.snp, etc) are updated and the game restarts.  Since Starcraft.exe was patched, there is a new hardcoded value for the version code and then that's just sent again next time you connect.
[/quote]

Somebody failed to understand what "hardcoded" means. 
January 29, 2006, 9:57 PM
FrOzeN
Maybe you could download patch.txt of Battle.net's FTP. Then there might be a simple formula for each game plus to update the Version Byte (excluding revisions; letters).

Eg, StarCraft:
Hex(179 + 2 x Patch)

That formula seems to work like so:
1.13: Hex(179 + 2 * 13) = CD
1.12: Hex(179 + 2 * 12) = CB
1.11: Hex(179 + 2 * 11) = C9
And so fourth...

Just a theory that came to mind. :)
January 29, 2006, 10:19 PM
Skywing
There is no guarantee that patches will follow the same pattern in the future.
January 29, 2006, 10:21 PM
Quarantine
I've found the best solution is to have configuration overrides for the version byte incase it changes in another way than that known along with the "smart" bruteforce method Frozen posted.
January 29, 2006, 10:26 PM
iago
[quote author=Warrior link=topic=14049.msg143717#msg143717 date=1138573563]
I've found the best solution is to have configuration overrides for the version byte incase it changes in another way than that known along with the "smart" bruteforce method Frozen posted.
[/quote]

Yeah, same.  I'm also going to provide an automatic-updater which will pull the current version byte from BNLS/RCRS.  I just need to find a way to download the hash files.. :)
January 29, 2006, 11:51 PM
Skywing
[quote author=iago link=topic=14049.msg143727#msg143727 date=1138578676]
[quote author=Warrior link=topic=14049.msg143717#msg143717 date=1138573563]
I've found the best solution is to have configuration overrides for the version byte incase it changes in another way than that known along with the "smart" bruteforce method Frozen posted.
[/quote]

Yeah, same.  I'm also going to provide an automatic-updater which will pull the current version byte from BNLS/RCRS.  I just need to find a way to download the hash files.. :)
[/quote]
As I alluded to in previous threads, you might look into calling bnupdate with a slightly modified patch script with the patch mpq you get from Battle.net when you try to log in with an old version of a product.

You could also try to implement the entire patch language yourself, though I can tell you from experience that it's a lot of work to do so.

The way BC does it is if it gets a too-old-version reply, it will download the given patch MPQ and apply a subset of it (only the parts affecting the files relevant for CheckRevision) and then do a brute force search for the new version code to update in its configuration.

BNLS has something similar, although you have to manually tell it which patch MPQ to download and what the new version code is as it does not have a built in Battle.net client.
January 30, 2006, 12:23 AM
iago
[quote author=Skywing link=topic=14049.msg143735#msg143735 date=1138580613]
As I alluded to in previous threads, you might look into calling bnupdate with a slightly modified patch script with the patch mpq you get from Battle.net when you try to log in with an old version of a product.

You could also try to implement the entire patch language yourself, though I can tell you from experience that it's a lot of work to do so.

The way BC does it is if it gets a too-old-version reply, it will download the given patch MPQ and apply a subset of it (only the parts affecting the files relevant for CheckRevision) and then do a brute force search for the new version code to update in its configuration.

BNLS has something similar, although you have to manually tell it which patch MPQ to download and what the new version code is as it does not have a built in Battle.net client.
[/quote]
It would definitely be useful for use the automatic-updater, but I don't have the time or motivation to figure out enough about it to be useful.  Plus, I'm trying to implement everything in Java in a cross-platform manner, so I'd probably have to figure out the patch scripting myself; of course, to do that, I would also have to figure out how to read the .mpq.  That is a lot more work than I want to do. 

Maybe some day, though....

By the way, do they ever ban you for too many old/invalid version bytes?
January 30, 2006, 4:01 AM
Spht
[quote author=iago link=topic=14049.msg143753#msg143753 date=1138593701]By the way, do they ever ban you for too many old/invalid version bytes?[/quote]

A more relevant inquiry would be regarding the time between connection attempts to try those version messages.
January 30, 2006, 8:29 PM
iago
[quote author=Spht link=topic=14049.msg143799#msg143799 date=1138652980]
[quote author=iago link=topic=14049.msg143753#msg143753 date=1138593701]By the way, do they ever ban you for too many old/invalid version bytes?[/quote]

A more relevant inquiry would be regarding the time between connection attempts to try those version messages.
[/quote]

That would be a great second question.  But if they don't ban you for trying, then it wouldn't matter how much time you leave between attempts. 
January 31, 2006, 12:28 AM
Ringo
[quote author=iago link=topic=14049.msg143829#msg143829 date=1138667309]
[quote author=Spht link=topic=14049.msg143799#msg143799 date=1138652980]
[quote author=iago link=topic=14049.msg143753#msg143753 date=1138593701]By the way, do they ever ban you for too many old/invalid version bytes?[/quote]

A more relevant inquiry would be regarding the time between connection attempts to try those version messages.
[/quote]

That would be a great second question.  But if they don't ban you for trying, then it wouldn't matter how much time you leave between attempts. 
[/quote]
I think if you try logon up to date version files but have a out of date version byte (or vise verser), battle.net will report invalid game version.
Where as if the hash files are out of date and match the patch of the version byte used, bnet will request the client patchs.
I can only guess, battle.net keeps old versions of the binarys and inclues them into there checkrevision list's, and/unless they keep (for example) around 500 revision forumlas and results on file for each client and each of its patch's.
It would make more sence to create a new list file in an mpq or somthing, rather than re-preforming check revision on *all* binarys every min or 2.
January 31, 2006, 3:29 AM
TheMinistered
Sorry to bump an old thread, but felt like I should?

Allright, I highly doubt blizzard has been modifying code related to the logon for SC/BW too much.  A simple pattern search algorithm that allows for ignoring bytes, which would change from version to version, should turn up the version byte quite easily.  The trick is making a pattern long enough to be unique.

example pattern:  74xx8D55948D4DD4C7459CxxxxxxxxC74594

where xx tells the patern search algorithm to ignore 1 byte.  Examples of instructions that you would want to use would be:

inc eax
dec eax
sub eax, ecx
add ecx, edx
...
...


anything involving memory addresses, etc, should be ignored -- basically run the pattern search algorithm over the binary file and you should be able to locate the offset where it's doing something like so:

mov ecx, 0xC9 ; assuming C9 is version byte

This should provide a somewhat reliable method of obtaining the version byte.

seems like it would be easier to just packetlog sc connecting though...

note: I just read a post by iago, it seems he has discovered it's stored in the resource section and has already figured a reliable way of locating it.  gg no re ;p ?!?!
April 4, 2006, 12:07 PM
warz
[quote]note: I just read a post by iago, it seems he has discovered it's stored in the resource section and has already figured a reliable way of locating it.  gg no re ;p ?!?![/quote]

Sorry, again, about bumping this old thread - but, can anyone confirm this?
October 23, 2006, 5:43 AM
UserLoser
Just look at the call to SnpInitialize or SnpQuery (IIRC those are the names of the Battle.snp exports), I forgot exactly which one, but a structure is passed to one of them from Starcraft.exe and it contains the version byte.  Then you should easily be able to derive the version byte for any .snp game
October 23, 2006, 1:08 PM
warz
Interesting. Both IDA and my debugger don't acknowledge any calls to SnpBind or SnpQuery. There is no SnpInitialize exported.
October 24, 2006, 8:48 PM
UserLoser
Like I said, "if I remember correctly" those were the exports...

So then it is SnpBind and SnpQuery, Starcraft.exe calls them when it loads the SNP before you connect to Battle.net.
October 24, 2006, 10:17 PM
Maddox
you could implement a machine code pattern function to locate a specific function across version changes that lets you know uses the version code.


-- edit: looks like TheMinistered has already suggested this.
October 25, 2006, 5:03 AM
UserLoser
[code]
.text:00472372                 mov     dword ptr [esi], 3Ch
.text:00472378                 mov     al, byte_58E408
.text:0047237D                 test    al, al
.text:0047237F                 pop     edi
.text:00472380                 jz      short loc_472392
.text:00472382                 mov     dword ptr [esi+0Ch], 'SEXP'
.text:00472389                 mov     dword ptr [esi+4], offset aBroodWar ; "Brood War"
.text:00472390                 jmp     short loc_4723A0
.text:00472392 ; ---------------------------------------------------------------------------
.text:00472392
.text:00472392 loc_472392:                             ; CODE XREF: SetVersionInfo+20j
.text:00472392                 mov     dword ptr [esi+0Ch], 'STAR'
.text:00472399                 mov     dword ptr [esi+4], offset aStarcraft_0 ; "Starcraft"
.text:004723A0
.text:004723A0 loc_4723A0:                             ; CODE XREF: SetVersionInfo+30j
.text:004723A0                 push    ebx
.text:004723A1                 lea     eax, [ebp+var_8]
.text:004723A4                 push    eax
.text:004723A5                 lea     ebx, [ebp+var_4]
.text:004723A8                 mov     dword ptr [esi+8], offset aInternalVersio ; "internal version unknown"
.text:004723AF                 mov     dword ptr [esi+10h], 0CFh
.text:004723B6                 mov     dword ptr [esi+18h], 8
.text:004723BD                 mov     dword ptr [esi+28h], 0FFh
[/code]

Most recent Starcraft.exe, enjoy.  .SNP libraries are loaded in Storm 125 IIRC, so go around there and see how to call SnpBind and SnpQuery, etc.

byte_58E408 would be IsExpansion, and the 0xCF @ 004723AF  is the version byte
October 27, 2006, 12:04 AM

Search