Valhalla Legends Forums Archive | Battle.net Bot Development References | Battle.net Protocol Information

AuthorMessageTime
taylorjonl
I am working on a battlenet bot program that basically will be a proxy that allows me to parse/modify the battlenet packets. I have done a lot of reading here about various subject, including the compression/decompression of server to client packets. I have found some code for a sample battlenet proxy that I have compiled and works.

When looking through the code I am getting a little confused as to how the client and server communicate. I can see that the client and server communicate via TCP and UDP because this proxy is using both protocols.

Can anyone explain to me their understanding of how the client and server communicate?

My guess is this. TCP is used for the battlenet message and maybe the UDP is for the ingame info? Is this correct?
December 17, 2003, 8:55 PM
Null
Battle.net use's the TCP ( Transmission Control ) protocol to communicate with its client's , how ever im aware that the UDP protocol is/can be used for certain things , which i myself do not no and have not looked at
December 17, 2003, 10:07 PM
Yoni
It depends on the game in question.
December 17, 2003, 10:08 PM
taylorjonl
It is Diablo II. This proxy I speak of seems to do this when it gets a packet from the client.

1) Receives data.
2) Sets up a UDP socket. Code posted below.
3) Processes and forwards data to server.

Now this is the code for setting up the UDP socket. It seems to use the same address that the TCP socket uses but a different port. That is how I am reading it but am rusty when it comes to socket programming.

[code]struct sockaddr_in udpname;
memset(&udpname, '\0', sizeof(udpname));
int namelen = sizeof(udpname);
if (getsockname(pConn->sdServerSock,
(struct sockaddr *)&udpname,
&namelen) < 0) {
LogWrite("Error %d getting bound address.", GetErrorCode());
return FALSE;
}

// bind to the same interface we used for our server connection;
// allocate an unused port
udpname.sin_port = 0;
if (bind(sgsdUdpSock, (struct sockaddr *)&udpname, namelen) < 0)
{
return FALSE;
}[/code]

The UDP socket above is used for server to client communiction.

[code]int ProcessUdpData () {
struct sockaddr_in peer;
char buf[1500];

int peerlen = sizeof(peer);
int n = recvfrom(sgsdUdpSock, buf, 1500, 0,
(struct sockaddr *)&peer, &peerlen);

if (n <= 0)
return FALSE;

// forward the packet to the client
if (sendto(sgsdUdpSock, buf, n, 0,
(struct sockaddr *)&sgGameDataAddr,
sizeof(sgGameDataAddr)) <= 0)
{
LogWrite("Error %d forwarding UDP packet.", GetErrorCode());
return FALSE;
}

return TRUE;
}[/code]

I don't fully understand what it is used for but am getting off work now so I can test it out some at home. If you know my answer please post as you will save me some time.
December 17, 2003, 11:00 PM
Skywing
Diablo II doesn't require the usage of UDP. That is more likely to be important for support of games like Starcraft, which actually use (and respond to) the UDP ping that the server sends when connecting.
December 18, 2003, 2:50 AM
taylorjonl
I found this out last night by using a packet sniffer(Ethereal). It showed no UDP activity. So I know that it is pure TCP. Problem is that now I have to figure out what sockets it needs, such as does it have just 1 socket or does it have multiple sockets. I am leaning to it haveing multiple sockets, I explain my reasoning below.

This is the loop it ends up in after it has established a proxy connection.
[code]
for(;;)
{
n = select(hisock+1, &fds, 0, 0, 0);

// check for input from proxied connections
PROXYCONNECTIONPTR pConn = sgpConnHead;
while (pConn && n) {
if (FD_ISSET(pConn->sdClientSock,&fds)) {
ProcessClientData(pConn);
n--;
}

if (FD_ISSET(pConn->sdServerSock,&fds)) {
ProcessServerData(pConn);
n--;
}
pConn = pConn->pNext;
}
}[/code]
I put print statements in the ProcessServerData() and ProcessClientData() functions and they don't seem aligned with when a TCP packet comes in. I think that DII and Battlenet are bypassing the example proxy server.

In an attempt to force it to use the proxy server I nuked my internet last night. I have a Cisco 675 and was attempthing to setup some IP Filters on 10.0.0.63 through 10.0.0.255 to prevent battlenet traffic. I was then going to setup my main IP as one in that range and a secondary IP on maybe 10.0.0.10 and run the proxy off that IP. I did something wrong and now I can't telnet into my router. DOH.

Will be SOL until I can build me a management cable later tonight. Anyone know if I am on the right path or way off base?
December 18, 2003, 3:12 PM
Kp
First, if you pasted it directly, there's something very wrong. Select clears the bits that weren't interesting (how else would you find the interesting ones?), so you'll need to rebuild the set after each call -- or select on a temporary copy of the set, which is reinitialized at the start of each pass.

Second, I really hope this is a Unix proxy. The win32 implementation of select() and FD_SET sucks really bad. If you're on win32, there's almost certainly better performing alternatives (ideally, overlapped I/O).
December 18, 2003, 5:31 PM
taylorjonl
[quote author=Kp link=board=17;threadid=4311;start=0#msg36200 date=1071768677]
First, if you pasted it directly, there's something very wrong. Select clears the bits that weren't interesting (how else would you find the interesting ones?), so you'll need to rebuild the set after each call -- or select on a temporary copy of the set, which is reinitialized at the start of each pass.[/quote]

It does rebuild the set with FD_SET but I just didn't list it for the sake of post size.

[quote author=Kp link=board=17;threadid=4311;start=0#msg36200 date=1071768677]Second, I really hope this is a Unix proxy. The win32 implementation of select() and FD_SET sucks really bad. If you're on win32, there's almost certainly better performing alternatives (ideally, overlapped I/O).
[/quote]

It is actually a Windows/Unix proxy. It is just code I am studying to try to find out how to write my own. Likely I will do more optimization than this one as it is just some code someone has posted to show you how you could write your own.

This is a link to where I downloaded it from.

[Kp edit: fixed his link. Learn to use YaBBC tags.]
December 18, 2003, 7:14 PM
taylorjonl
I have done some more research on the protocols that battlenet uses and have made some progress. It seems that with DII you will have 2 TCP socket connections. One for the chat server and one for the game server.

Now I want to be able to hijack these with a proxy but need to make DII client think that the proxy is a Battlenet server and Battlenet server think the proxy is a DII client. I think the key is in these 2 packets.

C>0x50 & S>0x3e

C>0x50 passes the server the IP of the client and S>0x3e passes the game server IP to the client. They are both stored as a DWORD in network byte order according to bnetdocs. Problem is when I sniff the packet the C>0x50 sends this '6c 65 0a 00' when my client IP is 10.0.0.10. I can't find any way to convert that to an IP address. I tried assigning it to the IN_ADDR struct's S_un.SinAddr member but that doesn't seem to work.

Any ideas how to interpret that DWORD?
December 23, 2003, 7:15 PM
Arta
That looks like a local network address. What's your external address?
December 27, 2003, 11:04 AM
taylorjonl
It was my mistake. Didn't take into account that the first DWORD basically contains

FF ID XX XX

where

ID is packet ID
XX is the size of packet.

Making alot of progress on learning what I need to do and actually have a proxy that at least proxies the BNCS packets. Next is the MCP then D2GS packets.
December 29, 2003, 1:03 AM

Search