• Welcome to Valhalla Legends Archive.
 

[Solved] [VB] C -> S 0x50 Packet causes disconnection...

Started by Don Cullen, September 10, 2005, 10:03 PM

Previous topic - Next topic

Don Cullen

This is the connection code:

Private Sub cmdConn_Click()
    If cmdConn.Caption = "Connect" Then
        AddC vbWhite, "Connecting to port " & bnetport & " at the " & bnetserver & " server..."
        BNET.Connect bnetserver, bnetport
        cmdConn.Caption = "Disconnect"
    Else
        cmdConn.Caption = "Connect"
        BNETDiscReq = True
        AddC vbWhite, "Disconnected."
        BNET.Close
    End If
End Sub

Private Sub BNET_Connect()
    AddC vbWhite, "Connected!"
    AddC vbWhite, "Initating packetage..."
    P0x01
    P0x50
End Sub


This is the 0x01 packet code:

Public Sub P0x01()
    AddC vbWhite, "Notifying server of emulation..."
    DMBot.BNET.SendData Chr(&H1)    'Send 0x01 packet
    AddC vbWhite, "0x01 protocol packet sent."
    AddC vbWhite, "Server notification done."
End Sub


This is the 0x51 packet code:

Public Sub P0x50()
    AddC vbWhite, "Assembling 0x50 Protocol packet..."
    With PacketBuf
        .InsertDWORD &H0     'This can be left as 0.
        .InsertNonNTString "68XI" & bnetclient 'Intel x86, client abrv
        .InsertDWORD &HCD
                             'Verbyte, changes with product upgrade.
        .InsertDWORD &H0     'This can be left as 0.
        .InsertDWORD &H0     'This can be left as 0.
        .InsertDWORD &H0   'This can be left as 0.
        .InsertDWORD &H0  'This can be left as 0.
        .InsertDWORD &H0  'This can be left as 0.
        .InsertNTString "USA"    'Abbrev. of country
        .InsertNTString "United States"  'Name of country
        .SendPacket DMBot.BNET, &H50         'Send 0x50 packet
    End With
    AddC vbWhite, "0x50 SID_AUTH_INFO packet sent."
End Sub



This is the DataArrival code:

Private Sub bnet_DataArrival(ByVal bytesTotal As Long)
    Static PktBuff As String 'Packet Buffer
    Dim Incoming As String
    Dim PacketLength As Long
    BNET.GetData Incoming, vbString
    PktBuff = PktBuff & Incoming
    AddC vbWhite, "Data recieved."
    AddC vbWhite, "Dumping packet..."
    AddC vbGreen, PktBuff
    AddC vbWhite, "End of packet dump."
End Sub


This is the BNET socket close code:

Private Sub BNET_Close()
    If BNETDiscReq = True Then
        AddC vbRed, "Local Disconnect Confirmation."
    Else
        AddC vbRed, "Server aborted connection!"
    End If
End Sub


And this is what the bot outputs to the textbox:

DMBot activated at [9/10/2005 7:45:43 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: op Kyro[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.
Server aborted connection!


I'm using Dark Minion's PacketBuffer class to handle the assemblage of packets. If you'd like to see the code to that as well, please let me know.

As you can see from above, just after I send the 0x50 packet, the server does a hard abort without responding to the packet whatsoever. I can only assume I made a mistake in the 0x50 packet structure, but I'm not sure since the BNET Docs show that the structure is correct:

Quote(DWORD)       Protocol ID (0)
(DWORD)       Platform ID
(DWORD)       Product ID
(DWORD)       Version Byte
(DWORD)       Product language
(DWORD)       Local IP for NAT compatibility*
(DWORD)       Time zone bias*
(DWORD)       Locale ID*
(DWORD)       Language ID*
(STRING)       Country abreviation
(STRING)       Country

Any input, suggestions, and ideas would be appreciated! Thanks in advance for any help given, or if not that, for at least reading this!

Take care!

[Edit: Corrected typos, moved a question to separate topic, modified subject of this topic]
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Hdx

WoW, most of that is useless. And you forgot to post the 1 thing that matters.
        .InsertNonNTString "68XI" & bnetclient 'Intel x86, client abrv
That should actually be 2 lines.
.InsertDWORD &H49583836 'IX86
.InsertDWORD &H53455850 'SEXP

0x52535441  = STAR
Considering everything in your packet is hard coded.. it seems that your 'bnetclient' is a fault. Also Start handeling DWORDs as DWORDs not "NonNTString"s
~-~(HDX)~-~

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Don Cullen

That solution works- the server doesn't disconnect this time.

QuoteAnd you forgot to post the 1 thing that matters.

What do you mean by that? What did I forget to post?

[Edit: Figured out how HdxBmx27 got the hex values, and removed the question regarding it.]

I asked initially how you knew STAR and SEXP was those hex values-- then I decided to see if I could figure out how you knew it. I did some experimenting, and converted each character of SEXP into hex, and got this:

53 45 58 50
S   E   X   P

So now I get how to know what to put in for it.  But how would I make it so that it's not hard coded? I tried doing this:

        .InsertDWORD StrToHex("IX86")
        .InsertDWORD StrToHex(bnetclient)
        .InsertDWORD StrToHex(VerByte)


In this case, bnetclient's value is "SEXP" and VerByte's value is "CD".

Here's the StrToHex function-- I cannot take credit for this function-- R.A.B.B.I.T. coded this function:

Public Function StrToHex(ByVal string1 As String) As String
    Dim strTemp As String, strReturn As String, i As Long
    For i = 1 To Len(string1)
        strTemp = Hex(Asc(Mid(string1, i, 1)))
    If Len(strTemp) = 1 Then strTemp = "0" & strTemp
    strReturn = strReturn & " " & strTemp
    Next i
        StrToHex = strReturn
End Function


You say everything is hard-coded- how so? So far, I've been trying to keep it soft-coded, but I'm always open to constructive criticism-- so if you have more information on that, it'd be appreciated.

Also, what's the best way to handle DataArrivals? IIRC, the packets can be separated by popping all incoming data into buffer, and passing packet along to a parser upon getting FF, and that the two bits next to FF is the length of the packet, although AFAIK, wouldn't it be easier to just wait til next FF, and then parse, instead of check to see if the buffer has reached that length and pass it along to parser?

Also, I'd like to apologize in advance if I seem dense- it's my first time coding a binary bot-- once again, thanks in advance for the advice!!! :-)
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Hdx

Hard-coded = the value dont change. meaning your setting everything to 0 insted of taking the time to find out the correct values. This can be done easily with a few APi calls.
And I was refering to the content of bnetclient vareable.
And reading all the reply, ifbnetclient = "SEXP" when you were trying to ad it in the 1st place, then thats the problem.
as for the code you posted, theres a few problems. InsertDWORD() is passed a numeric value, not a string, Witch StrtoHex() outputs.
So the correct way of doing it would be:
        .InsertDWORD Val("&H" & Replace(StrToHex("IX86"), Space(1), vbNullString))
        .InsertDWORD Val("&H" & Replace(StrToHex(bnetclient), Space(1), vbNullString))
        .InsertDWORD Val("&H" & VerByte)

That would output the correct information. What you do is convert it to hex, remove the spaces, and get the numeric value of the hex string.
~-~(HDX)~-~

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Don Cullen

Public Sub P0x50()
    AddC vbWhite, "Assembling 0x50 Protocol packet..."
    With PacketBuf
        .InsertDWORD &H0  'This can be left as 0.
        .InsertDWORD CLng("&H" & Replace(StrToHex("IX86"), " ", "")) 'IX86
        .InsertDWORD CLng("&H" & Replace(StrToHex(bnetclient), " ", "")) 'SEXP
        .InsertDWORD CLng("&H" & VerByte)
                          'Verbyte, changes with product upgrade.
        .InsertDWORD &H0  'This can be left as 0.
        .InsertDWORD &H0  'This can be left as 0.
        .InsertDWORD &H0  'This can be left as 0.
        .InsertDWORD &H0  'This can be left as 0.
        .InsertDWORD &H0  'This can be left as 0.
        .InsertNTString "USA"    'Abbrev. of country
        .InsertNTString "United States"  'Name of country
        .SendPacket DMBot.BNET, &H50     'Send 0x50 packet
    End With
    AddC vbWhite, "0x50 SID_AUTH_INFO packet sent."
End Sub


Like that? And where can I find the information on those APIs you're referring to, if you're willing to say? If you're not willing to refer me to the API information, what keywords should I use for google to find it myself? I put those at null because I assumed they were not needed- what uses are there for those, if any? Thanks for the such prompt response!
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Hdx

#5
theres a reason I used "Val" insed to "CLng"
also here are some APIs that are used to get most of the information for the packet (Google for there declarations)
GetLocaleInfoA            'Used to get Country abbrv & full name.
GetSystemTime           'Used to get TimeZone Bias
SystemTimeToFileTime 'Used to get TimeZone Bias
GetLocalTime               'Used to get TimeZone Bias
GetUserDefaultLCID      'Locale ID
GetUserDefaultLangID   'Language ID
You can get the local IP by using the .LocalIP property of your winsock.
And the reasons it's good to get the information is cuz it more-accuratly emulates the client. Also the country determnins what channels the bot starts in, and the timezone bias effect a few things that the server sends you.

~-~(HDX)~-~

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Don Cullen

You say there's a reason you used Val instead of CLng-- what's the reason if I may ask?

Also, does any of the following require a specific format:

(DWORD)       Product language
(DWORD)       Local IP for NAT compatibility*
(DWORD)       Time zone bias*
(DWORD)       Locale ID*
(DWORD)       Language ID*

For example, can I just do:

.InsertDWORD BNET.LocalIP 'Where BNET is the winsocket

Or does it need to be in a specific format?

Also what can I do about product language? Or do I leave that one at null since it's optional? The help you've been giving is most excellent and also very useful, thank you!!!
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Hdx

Nvm, Clng works.. I thoguht it caused an error when passed a string. But ti dosent matter.
As for spacific format. the IP has to be in network byte order.
AE each section of the ip address is a char. EXA: 198.0.0.1 = Chr(198) & Chr(0) & chr(0) & chr(1)
The timeZone Bias is in munites not hrs. EXA WST (-8, My time zone) would be -480.
everything else is regular. You can basically pass it directly from the API to the InsertDWORD.
Also, I havent found a way to get the product language. But unless your client is being used in GreatBrittin, it will always be "USeg" (Great Britin is "GBeg")
~-~(HDX)~-~

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Don Cullen

It took me a while to figure it out, but I managed to write a function on my own to convert an ip address to network byte order as you described... The function works pretty good... If there's a way to improve the function, I'm open to suggestions.

'Converts an IP address to network byte order.
Public Function IP2NBO(IpAddress As String)
    Dim Section(3) As String
    Section(0) = Mid(IpAddress, 1, InStr(1, IpAddress, ".") - 1)
    IpAddress = Mid(IpAddress, InStr(1, IpAddress, ".") + 1)
    Section(1) = Mid(IpAddress, 1, InStr(1, IpAddress, ".") - 1)
    IpAddress = Mid(IpAddress, InStr(1, IpAddress, ".") + 1)
    Section(2) = Mid(IpAddress, 1, InStr(1, IpAddress, ".") - 1)
    Section(3) = Mid(IpAddress, InStr(1, IpAddress, ".") + 1)
    IP2NBO = Chr(Section(0)) & Chr(Section(1)) & Chr(Section(2)) & Chr(Section(3))
End Function


I also managed to obtain a function from ALLAPI.NET that'd pull up information such as LOCALE_SENGCOUNTRY- credit goes to them for the function:

Public Function GetInfo(ByVal lInfo As Long) As String
    Dim Buffer As String, Ret As String
    Buffer = String$(256, 0)
    Ret = GetLocaleInfo(LOCALE_USER_DEFAULT, lInfo, Buffer, Len(Buffer))
    If Ret > 0 Then
        GetInfo = Left$(Buffer, Ret - 1)
    Else
        GetInfo = ""
    End If
End Function


And here's the 0x50 code I have figured out so far:

With PacketBuf
    .InsertDWORD &H0  'This can be left as 0.
    .InsertDWORD CLng("&H" & Replace(StrToHex("IX86"), " ", vbNullString)) 'IX86
    .InsertDWORD CLng("&H" & Replace(StrToHex(bnetclient), " ", vbNullString)) 'SEXP
    .InsertDWORD CLng("&H" & VerByte) 'Verbyte, changes with product upgrade.
    .InsertDWORD &H0  'Product Language
    .InsertDWORD CLng("&H" & Replace(StrToHex(IP2NBO(DM.BNET.LocalIP)), " ", vbNullString))  'Local IP for NAT compatibility
    .InsertDWORD &H0  'Time Zone bias
    .InsertDWORD GetUserDefaultLCID()  'Locale ID
    .InsertDWORD GetUserDefaultLangID  'Language ID
    .InsertNTString GetInfo(LOCALE_SABBREVCTRYNAME) 'Abbrev. of country
    .InsertNTString GetInfo(LOCALE_SENGCOUNTRY) 'Name of country
    .SendPacket DMBot.BNET, &H50     'Send 0x50 packet
End With


Took me quite a while to get this far, but I'd have never had gotten this far without your help! Thanks! If you don't mind elaborating a bit more info, it'd be very much appreciated.

I've been struggling at the time zone bias, and I still can't understand how to implement that one. It involves three API's, and in spite of this following information:

QuoteTimezone bias
The difference, in minutes, between UTC and local time. The client calculates this value by subtracting the Local Time from the System Time, having converted both to Filetime structures, and then converting the resultant offset to minutes by diving it by 600,000,000. If you wish to understand the mechanism involved, read Microsoft's documentation on File times.

I still can't figure out how to implement it. I did manage to get the API declarations for those three APIs:

Declare Sub GetSystemTime Lib "kernel32" (lpSystemTime As SYSTEMTIME)
Declare Function SystemTimeToFileTime Lib "kernel32" (lpSystemTime As SYSTEMTIME, lpFileTime As FILETIME) As Long
Declare Sub GetLocalTime Lib "kernel32" (lpSystemTime As SYSTEMTIME)

Private Type SYSTEMTIME
    wYear As Integer
    wMonth As Integer
    wDayOfWeek As Integer
    wDay As Integer
    wHour As Integer
    wMinute As Integer
    wSecond As Integer
    wMilliseconds As Integer
End Type

Private Type FILETIME
    dwLowDateTime As Long
    dwHighDateTime As Long
End Type


But that's as far as I got. I couldn't understand how exactly to perform the described operation...

As for the Product Language, do I just do:

            .InsertDWORD CLng("&H" & Replace(StrToHex("USeg"), " ", vbNullString))  'Product Language

Or does that need to be done another way?

Also, there's a problem with the LocalIP variable-- while it does contain the correct IP-- it contains the computer's IP, not my actual IP. You see, my computer is part of a network, there's two devices connected to my network; my laptop, and my videophone. The router holds the actual public IP, and assigns private IPs to devices that connect to the network. Will this be a problem? If so, is there a way to get around this problem?

[Edit: Cleaned up code]
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Hdx

#9
@ your IP2BO function.. You could jsut use split.. Insted of lots of mid() calls
@ your current 0x50 sub, Looking good. More detailed then most bots out there.
As always jsut ask what you want me to elaborate on and I will.
@ TimeZone. I forgot to mention youll need the API CopyMemory
What you need to do is use GetSystemTime to get the UTC time. Then use SystemTimeToFileTime to convert to a file time, then use copymemory to copy the filetime struct to a long, remember that filetime struct is 2 longs so use 8 for the number of bytes (Long=4, 4*2=8)
Do the same thing for GetLocalTime. Then use the below UnsignedSubtract to subtract Local from system to get the bias.

Below code was writtin by Lordy-poo and I was given permission long time ago when he was drunk :P

Public Function UnsignedSubtract(ByVal number1 As Long, ByVal number2 As Long) As Long
    UnsignedSubtract = DToL(CDbl(number1) - CDbl(number2))
End Function
Public Function DToL(ByVal num As Double) As Long
    While num > &H7FFFFFFF
        num = num - 4294967296#
    Wend
    While num < &H80000000
        num = num + 4294967296#
    Wend
    DToL = CLng(num)
End Function

@ prod Lang, Looks fine to me.
KK sleep time, I'll read this again in the morning.
~-~(HDX)~-~

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Don Cullen

@Split- thanks-- wish I knew that one sooner-- that'll save me alot of time in the future-- thanks!!

@0x50 looking good-- I owe that to you. :-) Still not done-- there's still the time zone bias...

@Prod Lang-- cool, thanks. It's put in code now.

@TimeZone-- still struggling. Here's where I am:

' System time structure
Public Type SYSTEMTIME
        wYear As Integer
        wMonth As Integer
        wDayOfWeek As Integer
        wDay As Integer
        wHour As Integer
        wMinute As Integer
        wSecond As Integer
        wMilliseconds As Integer
End Type

Declare Sub GetSystemTime Lib "kernel32" (lpSystemTime As SYSTEMTIME)
Declare Function SystemTimeToFileTime Lib "kernel32" (lpSystemTime As SYSTEMTIME, lpFileTime As FILETIME) As Long
Declare Sub GetLocalTime Lib "kernel32" (lpSystemTime As SYSTEMTIME)
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal numBytes As Long)

DIM SysUTCTime1 as Date, SysUTCTime2 as Long, SysFTime as long

Dim Result As String * 8

Dim t As SYSTEMTIME
GetSystemTime t
SysUTCTime = DateSerial(t.wYear, t.wMonth, t.wDay) + TimeSerial(t.wHour, t.wMinute, t.wSecond) + t.wMilliseconds / 86400000#
FTime = SystemTimeToFileTime(UTCTime, FTime)
CopyMemory ByVal Result, FTime, 8
FTime2 = Result
'Got lost at about this point.


I got lost and wasn't able to make heads nor tails of it... Looks like the TimeZone is the most difficult part of the 0x50 packet... What am I doing wrong? I wish I could make sense of this... Thanks for your help thus far! Do you think you could assist me further in this TimeZone Bias stuff? If so, thanks in advance once again! If not, thanks anyhow- you were of huge help!
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Kp

Quote from: Kyro on September 11, 2005, 02:30 AMIt took me a while to figure it out, but I managed to write a function on my own to convert an ip address to network byte order as you described... The function works pretty good... If there's a way to improve the function, I'm open to suggestions.

'Converts an IP address to network byte order.
Public Function IP2NBO(IpAddress As String)
    Dim Section(3) As String
    Section(0) = Mid(IpAddress, 1, InStr(1, IpAddress, ".") - 1)
    IpAddress = Mid(IpAddress, InStr(1, IpAddress, ".") + 1)
    Section(1) = Mid(IpAddress, 1, InStr(1, IpAddress, ".") - 1)
    IpAddress = Mid(IpAddress, InStr(1, IpAddress, ".") + 1)
    Section(2) = Mid(IpAddress, 1, InStr(1, IpAddress, ".") - 1)
    Section(3) = Mid(IpAddress, InStr(1, IpAddress, ".") + 1)
    IP2NBO = Chr(Section(0)) & Chr(Section(1)) & Chr(Section(2)) & Chr(Section(3))
End Function

Consider using instead inet_pton(3), htonl(3), and ntohl(3) for IP addresses (both IPv4 and IPv6).  Use htons(3) and ntohs(3) for port numbers.  inet_pton(3) supercedes inet_aton(3), which can only handle IPv4 addresses.  Note that certain broken implementations of the socket library (such as Microsoft's) fail to provide inet_pton(3) or inet_aton(3).  The recommended workaround for this deficiency is to stop using Microsoft's socket library.  If you are unable to do so, you may be able to get some functionality by using the deprecated inet_addr(3) function instead.  This function is deprecated because you cannot distinguish between an error condition and a valid broadcast address.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Hdx

#12

DIM stSysTime as SYSTEMTIME, ftSysTime as FILETIME, UTCTime as long
Dim Result As long
GetSystemTime stSysTime
Result = SystemTimeToFileTime(stSysTime, ftSysTime)
CopyMemory UTCTime, ByVal ftSysTime, 8
'Got lost at about this point.

That is what I was talking about.
Do the same for LocalTime

@ KP's post. Do as Kp says. Thats the more accurate way of doing it. I'm jsut not well versed i it. (I've done it before, just not much)
So does anyone have a way of determining the Product Language? I'd assume get the system lnguage, and if it's GBeg use that, else use USeg?
~-~(HDX)~-~

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Don Cullen

@HdxBmx27

Public Function GetTimeZoneBias() As Long
    Dim stSysTime As SYSTEMTIME, ftSysTime As FILETIME, SysUTCTime As Long
    Dim stLocalTime As SYSTEMTIME, ftLocalTime As FILETIME, LocalUTCTime As Long
    Dim Result As Long
    GetSystemTime stSysTime
    Result = SystemTimeToFileTime(stSysTime, ftSysTime)
    CopyMemory ByVal SysUTCTime, ftSysTime, 8
    GetLocalTime stSysTime
    Result = SystemTimeToFileTime(stLocalTime, ftLocalTime)
    CopyMemory ByVal LocalUTCTime, ftLocalTime, 8
    GetTimeZoneBias = UnsignedSubtract(LocalUTCTime, SysUTCTime)
End Function


That causes VB to crash. I assume incorrectly coded the CopyMemory lines since I know using memory functions incorrectly will either yield corrupted data or crash vb without an error, woe unto those who didn't save their work before testing. *kicks self* Had to rewrite the function again, just to show you what I had. Heh. In any case, can you tell me what's wrong with that code?

Also, I got curious about those lines:
QuoteDim Result As Long
    Result = SystemTimeToFileTime(stSysTime, ftSysTime)
    Result = SystemTimeToFileTime(stLocalTime, ftLocalTime)

I don't see a reason for having the Result variable, since we do no work with it other than store whatever SystemTimeToFileTime returns. Could it be done like this:

    SystemTimeToFileTime(stSysTime, ftSysTime)
    SystemTimeToFileTime(stLocalTime, ftLocalTime)


@Kp- got a suggestion of a good winsocket class/library that's better than the vb winsock?
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Kp

Quote from: Kyro on September 11, 2005, 02:11 PM@Kp- got a suggestion of a good winsocket class/library that's better than the vb winsock?

No, but then I never suggested that you should use Windows sockets at all.  The address utility functions I mentioned are present in glibc as of several years ago, and probably in the userland libraries for most other systems too.  Windows is the only system I've found that doesn't have it. :)
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!