Valhalla Legends Forums Archive | Battle.net Bot Development | [Solved][VB] S -> C 0x50 Parsing

AuthorMessageTime
LockesRabb
[code]        Case &H50
            AddC vbRed, "BNET is requesting authenication information."
            Dim LogonType As String, ServerToken As String, UDPValue As String, IX86verfilename As String, ValueString As String
            LogonType = CLng("&H" & Replace(StrToHex(Mid(PacketData, 4, 4)), " ", vbNullString))
            ServerToken = CLng("&H" & Replace(StrToHex(Mid(PacketData, 8, 4)), " ", vbNullString))
            UDPValue = CLng("&H" & Replace(StrToHex(Mid(PacketData, 12, 4)), " ", vbNullString))
            If LogonType = &H0 Then
                AddC vbWhite, "LogonType = STAR/SEXP/D2DV/D2XP"
            ElseIf LogonType = &H1 Then
                AddC vbWhite, "LogonType = War3Beta"
            ElseIf LogonType = &H2 Then
                AddC vbWhite, "Logon Type = War3"
            Else
                AddC vbRed, "Unrecognized logon type var: " & LogonType
            End If[/code]

As for the product language... Well, I'm thinking since it has to do with the game client, wouldn't that information be stored inside the resource strings? I mean, if you pry open an EXE or DLL with a resource viewer, you'll see resource strings containing the product language. Just an idea.
September 11, 2005, 8:03 PM
HdxBmx27
EWWWW I'd like to introduce you to 2 widly know functions. You will use them often.
[code]Public Function GetDWORD(Data As String) As Long
    Dim lReturn As Long
    Call CopyMemory(lReturn, ByVal Data, 4)
    GetDWORD = lReturn
End Function

Public Function GetWORD(Data As String) As Long
  Dim lReturn As Long
    Call CopyMemory(lReturn, ByVal Data, 2)
    GetWORD = lReturn
End Function[/code]
So Insted of LogonType = CLng("&H" & Replace(StrToHex(Mid(PacketData, 4, 4)), " ", vbNullString)) (Witch I dont think returns the right value, you would use LogonType = GetDWORD(Mid(PacketData, 4, 4))
But that wouldnt return the correct value cuz of your numbering, You need 5,4 not 4,4.

As for the product language.. Your right it's stored in the binary files.
Right-click -> properties -> Version -> Language
You sjut have to figure out how to extract it and convert to the DWORD it's suposto be.
I think you can extract it using "\StringFileInfo\000004B0\Language" and umm ... VerQueryValue
~-~(HDX)~-~
September 11, 2005, 8:14 PM
LockesRabb
[Edit: Fixed tags, and also found out why my code wasn't working-- I forgot to remove the GetDWORD library declaration that I had found on the internet-- it was conflicting with the GetDWORD sub declaration. Code works great now.]

I'll get on figuring out how to pry out the product language out of the resource string.

[Added here to avoid double posting]

OH YES, which reminds me-- I forgot to ask- how exactly do I extract a string from the packet? According to BNETDocs, the packet's form is:

[quote](DWORD) Logon Type
(DWORD) Server Token
(DWORD) UDPValue**
(FILETIME) MPQ filetime
(STRING) IX86ver filename
(STRING) ValueString[/quote]

The IX86verfilename is a string, and so is the ValueString-- how would I go about extracting those? And how do I extract the MPQ filetime? I'm not sure, but I think a filetime is 16 bits, so I'm thinking maybe use three DWORDs to load them into a filename var?
September 11, 2005, 8:27 PM
KkBlazekK
I use this:

[code]
Public Function KillatNull(ByVal Text As String) As String
    Dim i As Integer
    i = InStr(1, Text, Chr(0))
    If i = 0 Then
        KillatNull = Text
        Exit Function
    End If
    KillatNull = Left(Text, i - 1)
End Function
[/code]

It will take the text untill the null.
September 11, 2005, 9:07 PM
HdxBmx27
Hurm Just cuz i like you. I'll give you my Packet DeBuffer Class
[code]
Option Explicit
Private strBuffer As String

Public Sub SetData(Data As String)
    strBuffer = Data
End Sub

Public Function GetData() As String
    GetData = strBuffer
End Function

Public Sub ClearData()
    strBuffer = vbNullString
End Sub

Public Function rFILETIME(Optional QWORD As Boolean = False) As String
    Dim strFT() As String, strTMP As String
    If Not QWORD Then
        strFT = Split(rNTString & Space(1), Space(1))
        If strFT(0) > 2147483647 Then strFT(0) = (strFT(0) - 4294967296#)
        If strFT(1) > 2147483647 Then strFT(1) = (strFT(1) - 4294967296#)
    Else
        ReDim strFT(0 To 1)
        strFT(1) = rDWORD
        strFT(0) = rDWORD
    End If
    rFILETIME = strFT(0) & Space(1) & strFT(1)
End Function

Public Function StripHeader() As Byte
    StripHeader = Asc(Mid(strBuffer, 2, 1))
    strBuffer = Mid(strBuffer, 5)
End Function

Public Function rATString() As String
    On Error Resume Next
    rATString = Left(strBuffer, InStr(strBuffer, Chr(&HA)) - 1)
    strBuffer = Mid(strBuffer, Len(rATString) + 2)
End Function

Public Function rNTString() As String
    On Error Resume Next
    rNTString = Left(strBuffer, InStr(strBuffer, Chr(&H0)) - 1)
    strBuffer = Mid(strBuffer, Len(rNTString) + 2)
End Function

Public Function rDWORD() As Long
    Dim lReturn As Long, strTMP As String
    strTMP = Left(strBuffer, 4)
    Call CopyMemory(lReturn, ByVal strTMP, 4)
    rDWORD = lReturn
    strBuffer = Mid(strBuffer, 5)
End Function

Public Function rWORD() As Long
    Dim lReturn As Long, strTMP As String
    strTMP = Left(strBuffer, 2)
    Call CopyMemory(lReturn, ByVal strTMP, 2)
    rWORD = lReturn
    strBuffer = Mid(strBuffer, 3)
End Function

Public Function rBYTE() As Byte
    rBYTE = Asc(Left(strBuffer, 1))
    strBuffer = Mid(strBuffer, 2)
End Function
Public Function rVOID(Leng As Integer) As String
    If Len(strBuffer) < Leng Then Leng = Len(strBuffer)
    rVOID = Left(strBuffer, Leng)
    strBuffer = Mid(strBuffer, Leng + 1)
End Function[/code]
Simply Put the packet in using .SetData and use the other fucnctions to remove data.
~-~(HDX)~-~
September 11, 2005, 9:41 PM
LockesRabb
Whoa... That class is a beaut... And very efficent too! I like!

I ran into a problem trying to obtain MPQFiletime. This is the code I use for S -> C 0x50, after modifying to reflect usage of the new PacketDebuffer class (thanks a ton!):

[code]        Case &H50
            AddC vbRed, "BNET is requesting authenication information."
           
            Dim LogonType As Long
            Dim ServerToken As Long
            Dim UDPValue As Long
            Dim MPQFileTime As String
            Dim Ix86verfilename As String
            Dim ValueString As String
           
            LogonType = PktDeBuf.rDWORD
            ServerToken = PktDeBuf.rDWORD
            UDPValue = PktDeBuf.rDWORD
            MPQFileTime = PktDeBuf.rFILETIME
            Ix86verfilename = PktDeBuf.rATString
            If LogonType = &H0 Then
                AddC vbWhite, "LogonType = STAR/SEXP/D2DV/D2XP"
            ElseIf LogonType = &H1 Then
                AddC vbWhite, "LogonType = War3Beta"
            ElseIf LogonType = &H2 Then
                AddC vbWhite, "Logon Type = War3"
            Else
                AddC vbRed, "Unrecognized logon type var: " & LogonType
            End If
            AddC vbWhite, "ServerToken = " & ServerToken
            AddC vbWhite, "UDPValue = " & UDPValue
            AddC vbWhite, "MPQFileTime = " & MPQFileTime
            AddC vbWhite, "Ix86verfilename = " & Ix86verfilename
            BNETDiscReq = True
            DMBot.BNET.Close
            DumpPacket (PacketData)
            AddC vbWhite, "Forced Disconnect to avoid ipban since we haven't done S->C 0x50 nor 0x51 yet."
            Call DMBot.BNET_Close
            Exit Sub[/code]

VB errored out saying: "Type mismatch" and indicated the line causing error inside the rFILETIME function:

[code]If strFT(0) > 2147483647 Then strFT(0) = (strFT(0) - 4294967296#)[/code]

I assume I messed up in how to deal with the filetime, but I'm not sure. Do I need to do this:

[code]Dim MPQFileTime As FileTime[/code]

instead of:

[code]Dim MPQFileTime As String[/code]

-- I tried doing that just now, that also resulted in a type mismatch, this time at this line in bnetparser:

MPQFileTime = PktDeBuf.rFILETIME

And checked the rFILETIME function- that one returns a string, so I assume MPQFileTime has to be dimensioned as a string... I'm totally stumped-- any idea what I'm doing wrong?
September 11, 2005, 10:25 PM
HdxBmx27
As you see int eh function, Theres an optional parameter called QWORD. For the MPQFileTime you msut set this to true.
[code]
Dim MPQFileTime As String
MPQFileTime = PktDeBuf.rFILETIME(True)[/code]
~-~(HDX)~-~
September 11, 2005, 10:29 PM
LockesRabb
So all filetimes when dealing with bnet are QWords?

And quick question- QWord = how many Dwords? Dwords = 2 Words, right?
September 11, 2005, 10:34 PM
HdxBmx27
No, Not ALL filetimes are QWORDs Thats why I added the 2 ways of removing a FileTime.
And a QWORD = 2 DWORDS
~-~(HDX)~-~
September 11, 2005, 10:36 PM
LockesRabb
SCORE!!! You know I love you, right? Man, it feels good to see it finally getting this far! And you know what? I wouldn't have gotten this far if it wasn't for you, and the others on vL Bot Dev!

Here's the output:

[quote]DMBot activated at [9/11/2005 3:53:02 PM] .
Loading configuration...
Username: Kyro[DM]
Password: ********
CDKey: **************
Client: Starcraft: Brood War
Client VerByte: CD
BNET Server: useast.battle.net
BNET Port: 6112
BNET Default Channel: Clan DM
Config loaded.
Connecting to port 6112 at the useast.battle.net server...
Connected!
Initating packetage...
Notifying server of emulation...
0x01 protocol packet sent.
Server notification done.
Assembling 0x50 Protocol packet...
0x50 SID_AUTH_INFO packet sent.
BNET: Ping?
Assembling 0x25 SID_PING Packet...
0x25 SID_PING packet sent.
DMBot: Pong!
BNET is requesting authenication information.
LogonType = STAR/SEXP/D2DV/D2XP
ServerToken = 1788771134
UDPValue = 1007814
MPQFileTime = 29690661 1148377344
Ix86verfilename = IX86ver6.mpq
ValueString = A=306413271 B=151642937 C=5623565 4 A=A^S B=B^C C=C-A A=A+B
Dumping packet...

StrToHex Dump:
FF 50 61 00 00 00 00 00 3E 7B 9E 6A C6 60 0F 00 00 D9 72 44 25 0B C5 01 49 58 38 36 76 65 72 36 2E 6D 70 71 00 41 3D 33 30 36 34 31 33 32 37 31 20 42 3D 31 35 31 36 34 32 39 33 37 20 43 3D 35 36 32 33 35 36 35 20 34 20 41 3D 41 5E 53 20 42 3D 42 5E 43 20 43 3D 43 2D 41 20 41 3D 41 2B 42 00
HexToString Dump:
P
End of packet dump.
Forced Disconnect to avoid ipban since we haven't done S->C 0x50 nor 0x51 yet.
Local Disconnect Confirmation.[/quote]

Now isn't that beautiful?

Now to get to work on learning how to assemble the 0x51 packet...

That aside, just letting you know I haven't given up on trying to figure out how to extract product lang from starcraft. But are you sure it's the Language section in version when you right click on file and click properties? Because what I'm seeing is United States (English), not USEg. What I'm dying to know is, how did people know it was supposed to be USeg or GBeg? If it was via packet logging when SC connects, then logic states that if someone used IDL (I think that's the program), and monitored memory while logging in-- one could set up a BP at whatever sent the Prod Lang, and use that as a reference to find out whether the string is stored inside the EXE, or whether Starcraft uses a function to determine the Prod Lang. What do you think?

[Edit: Fixed tags]
September 11, 2005, 11:03 PM

Search