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
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.
EWWWW I'd like to introduce you to 2 widly know functions. You will use them often.
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
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)~-~
[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
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?
I use this:
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
It will take the text untill the null.
Hurm Just cuz i like you. I'll give you my Packet DeBuffer Class
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
Simply Put the packet in using .SetData and use the other fucnctions to remove data.
~-~(HDX)~-~
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!):
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
VB errored out saying: "Type mismatch" and indicated the line causing error inside the rFILETIME function:
If strFT(0) > 2147483647 Then strFT(0) = (strFT(0) - 4294967296#)
I assume I messed up in how to deal with the filetime, but I'm not sure. Do I need to do this:
Dim MPQFileTime As FileTime
instead of:
Dim MPQFileTime As String
-- 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?
As you see int eh function, Theres an optional parameter called QWORD. For the MPQFileTime you msut set this to true.
Dim MPQFileTime As String
MPQFileTime = PktDeBuf.rFILETIME(True)
~-~(HDX)~-~
So all filetimes when dealing with bnet are QWords?
And quick question- QWord = how many Dwords? Dwords = 2 Words, right?
No, Not ALL filetimes are QWORDs Thats why I added the 2 ways of removing a FileTime.
And a QWORD = 2 DWORDS
~-~(HDX)~-~
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:
QuoteDMBot 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.
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]