HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Map Keys

08-31-2008, 12:17 AM#1
Strilanc
There's a value required for hosting maps that I've been trying to compute for some time now. Currently I can only get it by hosting the map with wc3, and grabbing the value with a packet sniffer.

I want to be able to compute this thing, so I put some work into it. I've found that it seems to be a non-standard crc32 of war3map.j. It definitely only depends on data inside the mpq files, because I repackaged the whole archive with no compression or encryption and it did not change. Changing a single character in war3map.j changes only one byte of the output.

What I'm looking for are suggestions. What non-standard crc32 has blizzard used before? Things like that.
08-31-2008, 05:40 AM#2
Strilanc
It's looking less and less complicated. Changing any 1 bit in the input seems to change only 1 bit in the output. Changing 2 bits seems to change 2 bits (the same as changing both 1 bits for those changes). The changes even increase linearly with the bit number.

But I still can't seem to get it quite right. It returns the right value for the map I'm testing on, but not others. The linear increase also seems to break halfway through.

What I have so far:

Code:
    Public Function loopcheck(ByVal s As IO.Stream, Optional ByVal length As Integer = -1) As UInteger
        If length = -1 Then length = CInt(s.Length)
        Dim mask As UInteger = CUInt(1) << 21
        Dim b As New BitBuffer
        Dim val As UInteger = 606559388
        For repeat As Integer = 0 To length - 1
            b.queueByte(CByte(s.ReadByte()))
            While b.numBits > 0
                If b.takeBit() Then val = val Xor mask
                mask <<= 1
                If mask = 0 Then mask = CUInt(1)
            End While
        Next repeat
        Return val
    End Function
08-31-2008, 06:06 AM#3
Strilanc
It starts at bit 21, moves up 1 bit every bit, and back 3 bits every 32 bits.

Still not working for other maps.
08-31-2008, 06:16 AM#4
Strilanc
Stupid Error Fixed. Now it works for all the versions of my test map, but still not all maps. The function has a lot of room for improvement, but since it's not working yet...

Code:
Public Function loopcheck(ByVal s As IO.Stream, Optional ByVal length As Integer = -1) As UInteger
        If length = -1 Then length = CInt(s.Length)
        Dim mask As UInteger = CUInt(1) << 21
        Dim b As New BitBuffer
        Dim val As UInteger = 890969739
        For repeat As Integer = 1 To length
            b.queueByte(CByte(s.ReadByte()))
            While b.numBits > 0
                If b.takeBit() Then val = val Xor mask
                mask <<= 1
                If mask = 0 Then mask = CUInt(1)
            End While
            If repeat Mod 4 = 0 Then
                mask >>= 1
                If mask = 0 Then mask = CUInt(&H80000000L)
                mask >>= 1
                If mask = 0 Then mask = CUInt(&H80000000L)
                mask >>= 1
                If mask = 0 Then mask = CUInt(&H80000000L)
            End If
        Next repeat
        Return val
    End Function
08-31-2008, 12:13 PM#5
Strilanc
It also uses war3map.doo, war3map.w3e, war3map.wpm. Tried every file now, doesn't use any others present in the test maps.

STILL not working on other maps.
08-31-2008, 05:33 PM#6
PitzerMike
This sounds like it only takes "meaningful" files into consideration and excludes editor-only files.
It probably works in your test map becaue the map doesn't contain all optional files. This leads me to the following lists:

Files that definitely matter:

war3map.j
war3map.w3e
war3map.wpm
war3map.doo

Editor-only files that shouldn't matter:

war3map.wtg
war3map.wct
war3map.w3r
war3map.w3c
war3map.w3s
war3mapUnits.doo (not 100% sure about this one)
war3map.w3i (this is not editor-only but every map has it and if your test map doesn't need it for the computation to succeed I guess it shouldn't matter)
war3map.shd (same as w3i)

Files that might not exist in your map but which might matter:

war3map.wts (externalized strings)
war3map.imp (imported files list)
war3map.w3u (custom units)
war3map.w3t (items)
war3map.w3a (abilities)
war3map.w3b (dests)
war3map.w3d (doods)
war3map.w3q (upgrades)
war3mapMisc.txt (gameplay constants)
war3mapSkin.txt (game interface)
war3mapExtra.txt (external object data source)

Files that probably won't matter since they're rarely used:

war3mapMap.blp
war3mapMap.b00
war3mapMap.tga
war3mapPreview.tga
war3mapPath.tga
war3map.mmp
08-31-2008, 08:19 PM#7
Strilanc
I'm stilling running into issues with some variations of my test map; removing one byte from war3map.j breaks it. It seems some of the magic numbers are actually calculated.

But I've got quite a collection of map keys built up, and the patterns get clearer and clearer.
08-31-2008, 11:40 PM#8
Strilanc
This thing is being devious. If I knew how to use a disassembler or something I could probably just find the function. Right now I'm just feeding dozens of values through it and looking for patterns.

The patterns keep breaking my assumptions. I found one that right shifts by 11 where I expected no right shift... still not sure why that is.

It would be *much* easier if 'feeding a value' didn't involve logging into battle.net, and creating a game. Also it would help if it didn't crash if I modify war3map.j [it reads it for something or other, I can modify war3map.doo at will at least].
09-01-2008, 01:14 PM#9
masda70
I think it uses common.j and blizzard.j as well, and maybe any *.j it encounters. As far as I know, adding such modified script file into the map file forces clients to redownload a fresh copy of the map.

Also, have you tried this on LAN? It might be easier to test it that way.
09-02-2008, 05:17 PM#10
Strilanc
Well I figured out why I was having so much trouble.

I started removing files from the mpq so I was dealing with fewer variables. I found I could get the correct value for all the isolated files- except war3map.j. Even the empty war3map.j file gives a non-zero key.

I think it's prepending common.j or something else onto war3map.j before running the check.

Code:
    Public Function loopcheck(ByVal s As IO.Stream, ByVal valwo As Integer, ByVal valbo As Integer, ByVal wordo As Integer, ByVal byteo As Integer, Optional ByVal length As Integer = -1) As UInteger
        If length = -1 Then length = CInt(s.Length)
        Dim val As UInteger = 0
        Dim r As New IO.BinaryReader(s)
        For repeat As Integer = 1 To length - 3 Step 4
            val = ShiftRotateLeft(val, valwo) Xor ShiftRotateLeft(r.ReadUInt32(), wordo)
        Next repeat
        For repeat As Integer = 1 To length Mod 4
            val = ShiftRotateLeft(val, valbo) Xor ShiftRotateLeft(CUInt(r.ReadByte()), byteo)
        Next repeat
        Return val
    End Function
    Public Function loopCheck2(ByVal m As MPQ.Archive) As UInteger
        Dim val As UInteger = 0
        Dim offset As Integer = 3
        Dim ss() As String = {"war3map.j", "war3map.doo", "war3map.wpm", "war3map.w3e"}
        For Each s As String In ss
            If m.hashTable.contains(s) Then
                offset += 3
                val = val Xor loopcheck(New MPQ.FileStream(m, s), 3, 3, offset, offset)
                If s = "war3map.j" Then val = val Xor CUInt(973126876)
            End If
        Next s
        Return val
    End Function
09-02-2008, 11:29 PM#11
Strilanc
I still haven't solve the .j issue, but I started testing other files like pitzermike suggested. war3map.w3u, war3map.w3a, war3map.w3q are definitely included. Haven't tried items, doodads, and destructables yet but the other files all don't matter.
09-03-2008, 05:48 PM#12
masda70
Have you tried playing with custom versions of common.j and blizzard.j?
09-04-2008, 10:20 PM#13
bomber7
Huh, Strange, at first when I hit refresh I saw like 5 of my posts so I thought *crap* and clicked delete on one then they were suddenly all gone.

So the original post was:

Do stop the map from crashing when you modify war3map.j try to remove the (attributes) file inside the map mpq.
09-04-2008, 10:51 PM#14
Strilanc
I was already fixing the attributes file. The game actually reads the script in war3map.j and validates (at least some of) it.

I found out that putting a null character at the start of war3map.j made it not crash, because it stops parsing before it gets to any non-valid data.
09-05-2008, 01:43 AM#15
Strilanc
Custom common.j, blizzard.j, and common.ai all change the value.

But there are other files I need but don't know, because the key still isn't zeroed with all these 0-length files.

It would help if I knew all the files you could override and all the files it "included" by default.