• Welcome to Valhalla Legends Archive.
 
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - Strilanc

#1
Battle.net Bot Development / Verify wc3 cd key
October 21, 2009, 10:26 AM
I'm looking for source code to verify that a wc3 cd key will be accepted by the installer, in order to catch typos when people enter a key into my hosting bot.

Anyone have a link?
#2
Battle.net Bot Development / Warcraft 3 Object IDs
September 01, 2009, 10:51 AM
When communicating in multiplayer, or saving to a replay, the objects (units, destructibles, items, etc) in a wc3 game are referred to by an id number. Duh. It seems to be allocated and freed, pretty simple. You can see it in any of the order or selection actions.

The mystery is that the id is always followed by a second value, which I'll just call id2 (since it seems to be unique per object). All objects created at game init have id = id2. id2 seems to increase with time and with the number of ids. Late in the game a typical id2 for new units is in the hundred thousands whereas the id stays relatively stable due to units dying and such. id2 also seems to increase as more ids are allocated. But, most confusing of all, it doesn't strictly increase. It goes up and down over the short term.

So, the question is: what is this value? What information is the primary id not specifying that this weird secondary one specifies? Why does it increase over the long term? Is it just there to screw with my mind?
#3
I adapted some vb6 code posted by Ringo to load and run warden modules. I moved as much of the logic to managed code as I could, but the dynamic loading and running of modules is still in the DLL.

It works great, except when I try to use it under windows Vista. DEP catches it (for good reason!). I'm looking for pointers on how to 'properly' dynamically load and run executable code.
#4
When hosting wc3 games, there is a required value that I don't know how to compute yet.

Here is what I know about it:
- It depends only on files within the mpq (repackaging the mpq with no compression, etc, has no effect on it)
- It varies only slightly if the difference between the two mpqs is small. If you save a map twice in a row it seems to change very little
- It is not a standard crc32 of any of the individual files
- I believe it includes a crc of the war3map.j file, because the files changes only a little every save [it includes a save time]

What do I do now? Does blizzard have some standard non-standard crc32 they use? [They do use the standard one in other places]

I currently use a packet sniffer to retrieve the value when a game is hosted, but that means I can only run it on valid maps, which makes it difficult to see which files are being read.
#5
I've been looking into the packets sent during the game, and seeing what kind of things I can get away with if I inject custom ones.

For example, there is a packet to fire triggers with a chat event. The packet is needed because other private chat couldn't trigger events for all players. An obvious side-effect of such a packet is that any map with a chat event with substring "" allows people to listen to private chat.

But I don't want to listen in on private chat. I want to fire any trigger with a chat event at will (when I'm host). For example, this is useful if a host bot wants to set the game mode in DOTA.

Here is an example packet:
Code:

F7 0C 1B 00 FA 00 DB 08 02 10 00 60 26 03 00 00 26 03 00 00 2D 74 65 73 74 31 00

F7 - Game packet header
0C - Packet ID
1B 00 - Total size (27)
FA 00 - Tick time (250 milliseconds)
DB 08 - CRC of following data
02 - Player index (not equivalent to player 2, partially based on join order)
10 00 - Size of following chunk (16)
60 - Unknown constant (probably means chat trigger event)
26 03 00 00 - Event handle address
26 03 00 00 - Event handle address again
2D 74 65 73 74 31 00 - Chat string ("-test1")


This will usually fire the event at 26 03 00 00. But if the player index doesn't match the event's player's index or the player index is the local player's index then it won't fire. I want to get around this (specifically the local player thing). Any suggestions?

As a side note, sending the 'chat' packet (not this one) will cause the player to speak even if it's the local player. The potential abuse of that is... wow. Send instructions to the other team, seemingly in private chat from their own team member.
#6
I need help. When a player joins a warcraft 3 game, three 4-byte values about the map are transmitted to that player: size, crc32, and some other value. I need to compute that value, but I have no idea how to start.

I want to find the function computing it (in assembly, obviously), but I don't know how to do that. How should I start?
#7
I've almost finished writing a bot which can host games in wc3. The last obstacle comes at the very end: when players finish loading and enter the map. The bots responsibilities end there, and so I want it to exit graciously.

The problem is all the strategies I've tried for disconnecting end up killing the game (players are sent straight to the score screen). My fear is that I will need to send something different for every map.

Does anyone have any experience with this?


    Public Function startCountdown() As Boolean
        broadcastPacket(GID.START_COUNTDOWN, array(Of Byte)())
        For i As Integer = 5 To 1 Step -1
             say("Game starting in " + i.ToString(), Color.Red)
             Threading.Thread.Sleep(1000)
        Next i
        say("Starting Game", Color.Red)
        broadcastPacket(GID.START_LOADING, array(Of Byte)())
        players(0).ready = True
    End Function

    Public Function receive_GID_PLAYER_READY(ByVal data() As Byte) As Boolean
        'this player is ready
        ready = True
        say(name + " is ready", Color.Blue)
        If send_GID_OTHER_PLAYER_READY() = False Then Return False

        'look for unready players
        Dim b As Boolean = True
        For Each p As BnetGamePlayer In players
            If p.ready = False Then b = False : Exit For
        Next p

        'launch when all ready
        If b Then
            say("All ready", Color.Blue)
            Return launchLoadedGame()
        End If

        Return True
    End Function

    Public Function launchLoadedGame() As Boolean
        say("Launching", Color.Blue)

        'send some game data to look good
        If broadcastPacket(GID.GAME_PACKET, array(Of Byte)(&HFA, &H0)) = False Then Return False

        'inform the players that you are leaving
        If send_GID_PLAYER_LEFT(players(0)) = False Then Return False

        'tell them the new host is the second player
        If send_GID_SET_HOST(players(1)) = False Then Return False

        'disconnect
        For Each p As BnetGamePlayer In copyOfPlayers()
             If Not p.socket Is Nothing Then p.socket.disconnect()
        Next p
    End Function
#8
I'm trying to compute the crc32 (I believe that's what it is, 4 bytes, and changes radically when the map is re-saved) for wc3 maps (I'm using icewind v2.05 for my tests).

I implemented the IEEE crc32 but my results aren't matching. According to the sniffed statstring, I should be getting "7E BF CB 09", but I get "7C BB 83 D8". Is there some kind of quirk I need to put in? Am I using the right polynomial?


    ''' <summary>Computes the crc32 value for a stream of data.</summary>
    ''' <param name="s">The stream to read data from.</param>
    ''' <param name="poly">The polynomial to be used, specified in a bit pattern. (Default is CRC-32-IEEE 802.3).</param>
    ''' <returns>crc32 value</returns>
    Public Shared Function crc32(ByVal s As Stream, Optional ByVal poly As UInteger = &H4C11DB7) As UInteger
        Dim r As New BinaryReader(s)

        'Precompute the combined XOR masks for each byte
        Dim xorTable(0 To 255) As UInteger
        For i As Integer = 0 To 255
            Dim regb As Byte = CByte(i)
            For j As Integer = 7 To 0 Step -1
                xorTable(i) = xorTable(i) Xor ((poly << j) * (regb >> 7))
                regb = (regb << 1) Xor CByte((poly >> 24) * (regb >> 7))
            Next j
        Next i

        'Direct Table Algorithm
        Dim reg As UInteger = 0
        For i As Long = 0 To s.Length - 1 - s.Position
            reg = (reg << 8) Xor xorTable(CInt((reg >> 24) Xor r.ReadByte()))
        Next i

        Return reg
    End Function
#9
Using MBNCSUtil I've managed to get all the way to the last logon step in WC3. I need to compute the password proof.

After searching for awhile I managed to find a cached page with an explanation: http://64.233.167.104/search?q=cache:0iTY9kDpd0EJ:www.jbls.org/bnetdocs/content4323.html%3FSection%3Dd%26id%3D18+NLS/SRP+Protocol&hl=en&ct=clnk&cd=1

I implemented this in VB.net:

    Public Function getPasswordProof() As Byte()
        Dim bb As Byte()
        'Compute values
        'strings not null terminated, is that correct?
        bb = packBytes(packString(username.ToUpper()), packString(":"), packString(password.ToUpper()))
        bb = SHA1(bb)
        bb = packBytes(salt, bb)
        bb = SHA1(bb)
        Dim x As BigNum = New BigNum(bb)
        Dim v As BigNum = G.powerMod(x, N)
        bb = SHA1(remoteKey.bytes)
        bb = chopBytes(bb, 4)(0)
        Dim u As BigNum = New BigNum(bb)
        Dim S As BigNum = ((N + remoteKey - v) Mod N).powerMod(privateKey + u * x, N)

        'Separate S into odd and even bytes
        Dim bb1(0 To 15) As Byte, bb2(0 To 15) As Byte
        For i As Integer = 0 To 15
            bb1(i) = S.byteVal(2 * i)
            bb2(i) = S.byteVal(2 * i + 1)
        Next i

        'Hash the odds and the evens
        bb1 = SHA1(bb1)
        bb2 = SHA1(bb2)
        Dim K(0 To 19) As Byte

        'Put evens to evens and odds to odds
        For i As Integer = 0 To 9
            'I assumed 'combine the buffers' meant this, but it could mean a ton of other things
            K(2 * i) = bb1(2 * i)
            K(2 * i + 1) = bb2(2 * i + 1)
        Next i

        'Xor the hashes of G and N together
        bb1 = SHA1(G.bytes)
        bb2 = SHA1(N.bytes)
        For i As Integer = 0 To bb1.Length - 1
            bb1(i) = bb1(i) Xor bb2(i)
        Next i

        'Get the full hash
        bb = SHA1(packString(username.ToUpper()))
        bb = packBytes(bb1, bb, salt, publicKey.bytes, remoteKey.bytes, k)
        bb = SHA1(bb)

        Return bb
    End Function


But I get an "incorrect password" flag when I try to log on.

Is the algorithm on that page correct?
Have I implemented it correctly? (assume the BigNum class works)
Can someone provide the values I should be getting for some given password/key combo?
#10
I've translated the war3 cd key decoder from mbncsutil into vb.net. But I can't seem to get correct results. The compiled library works fine, so I know I've made an error somewhere. I don't have access to a C# interpreter so I can't see what values should be half way through the computation. This is a learning experience for me, so I'd like to figure out what I'm doing wrong. It may be a blind oversight on my part, or some obscure difference between vb and c#.

I did manage to totally rewrite the decodeKeyTable method into something legible, so that's something.

I'm not quite sure what my question is, I just want general help. If someone could tell me the true values of srcData before and after the //mult block for a known cd key, that would be very helpful.