I'm trying to make a w2bn bot, but i dont know much about the login sequence.
I've tryed reading http://bnetdocs.valhallalegends.com/sequence.php, but it didn't help me out much.
Can anyone here post an example login sequence (In a easy-to-read format) here?
So far, my Connection class:
package connection;
import java.net.*;
import java.io.*;
public class Connection implements Runnable {
protected Socket _socket;
protected DataInputStream _in;
protected DataOutputStream _out;
protected String _server;
protected int _port;
protected boolean connected = false;
public Connection(String server, int port) throws Exception {
this._server = _server;
this._port = _port;
connect();
}
public void connect() throws Exception {
_socket = new Socket(_server, _port);
_in = new DataInputStream(_socket.getInputStream());
_out = new DataOutputStream(_socket.getOutputStream());
connected = true;
run();
}
public void run() {
try {
login();
while (connected && _in.readLine() != null) {
String line = _in.readLine();
print(_server + ":" + _port + ">> " + line);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void login() {
if (connected) {
try {
send((byte) 0x1E); // is this what i do?
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public void print(String text) {
System.out.println(text);
}
public void send(byte b) throws IOException {
_out.write(b);
}
public void killSock() {
try {
_socket.close();
_in.close();
_out.close();
connected = false;
} catch(IOException e) {
System.out.println(e);
}
}
}
BnetDocs (http://bnetdocs.valhallalegends.com/content.php) is your best friend, specifically this article (http://bnetdocs.valhallalegends.com/sequence.php).
Quote from: Joex86] link=topic=7385.msg91937#msg91937 date=1158537404]
BnetDocs (http://bnetdocs.valhallalegends.com/content.php) is your best friend, specifically this article (http://bnetdocs.valhallalegends.com/sequence.php).
It confused the shit outta me.
Oh, and please excuse the typo:
this._server = _server;
this._port = _port;
Hmm... This makes bnet not kick me off... As if its waiting for more data...
send((byte) 0x01);
Can someone atleast give me an example of SID_CLIENTID using my send method? I should be able to zoom along after that.
IIRC W2BN doesn't use SID_CLIENTID
Quote from: unTactical on September 17, 2006, 10:34:37 PM
IIRC W2BN doesn't use SID_CLIENTID
That doesn't matter to the battle.net server. :)
You can login to the battle.net server (as of right now, and a long time before now) using the 0x50 system. That saves a lot of handling if you want to do all the legacy clients.
Ok... after a bit of reading, and downloading a packet buffer from javaop1, i made this code, and am partialy confused. If anyone could give me some corrections.
package connection;
import java.net.*;
import java.io.*;
import util.Buffer;
public class Connection implements Runnable {
protected Socket _socket;
protected DataInputStream _in;
protected DataOutputStream _out;
protected String _server;
protected int _port;
protected boolean connected = false;
public Connection(String server, int port) throws Exception {
this._server = server;
this._port = port;
connect();
}
public void connect() throws Exception {
_socket = new Socket(_server, _port);
_in = new DataInputStream(_socket.getInputStream());
_out = new DataOutputStream(_socket.getOutputStream());
connected = true;
run();
}
public void run() {
try {
login();
while (connected && _in.readLine() != null) {
String line = _in.readLine();
print(_server + ":" + _port + ">> " + line);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void login() {
if (connected) {
try {
send((byte)0x01, null); // Send login thingy
Buffer login = new Buffer();
login.addDWord(0);
login.addString("68XI");
login.addString("W2BN");
login.addDWord(0x4F);
login.addDWord(0);
login.addDWord(0);
login.addDWord(0);
login.addDWord(0);
login.addDWord(0);
login.addString("CAN");
login.addDWord(0);
send((byte)0x50, login.getBuffer());
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public void print(String text) {
System.out.println(text);
}
public void send(byte code, byte[] b) throws IOException {
_out.write(code);
if (b != null)
_out.write(b);
}
public void sendText(String text) throws IOException {
_out.write(text.getBytes());
}
public void killSock() {
try {
_socket.close();
_in.close();
_out.close();
connected = false;
} catch(IOException e) {
System.out.println(e);
}
}
}
Feel free to take a look at (and use pieces from) my project CCGBot (http://www.javaop.com/~joe/ccgbot/). The way I implemented multiple protocols was nasty, but it worked. Most of the version checking code (in fact, all if it) is iago's, as well as the XSHA1 implementation. Other than that I think I wrote the rest and released it under the BSD license, and the rest is public domain.
EDIT -
W2BN isn't implemented in CCGBot yet (oops) but it shows other protocols though.
Its alright, i just found out how to get over the first hurdle.
Source code below for others
package connection;
import java.net.*;
import java.io.*;
import util.BNetBuffer;
public class Connection implements Runnable {
protected Socket _socket;
protected InputStream _in;
protected OutputStream _out;
protected String _server;
protected int _port;
protected boolean connected = false;
public Connection(String server, int port) throws Exception {
this._server = server;
this._port = port;
connect();
}
public void connect() throws Exception {
connected = true;
_socket = new Socket(_server, _port);
run();
}
public void run() {
try {
_in = _socket.getInputStream();
_out = _socket.getOutputStream();
login();
print("Logged in.");
int line;
while (true) {
line = _in.read();
print("" + line);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void login() {
if (connected) {
try {
send((byte)0x01); // Send login thingy
BNetBuffer authinfo = new BNetBuffer();
authinfo.setCode((byte) 0x50);
authinfo.add(0x00000000);
authinfo.add(0x49583836);
authinfo.add(getGameCode());
authinfo.add(0x4F);
// These can just be nulled-out
authinfo.add((int) 0x00000000); // product language
authinfo.add((int) 0x00000000); // Local ip
authinfo.add((int) 0x00000000); // Timezone bias
authinfo.add((int) 0x00000000); // Locale Id
authinfo.add((int) 0x00000000); // Language Id
authinfo.addNTString("CAN");
authinfo.addNTString("Canada");
sendNow(authinfo);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public void send(byte b) throws IOException {
_out.write(b);
_out.flush();
}
public int getGameCode() {
return 'W' << 24 |
'2' << 16 |
'B' << 8 |
'N' << 0;
}
public void print(String text) {
System.out.println(text);
}
public void sendNow(util.Buffer data) throws IOException {
_out.write(data.getBuffer());
}
public void killSock() {
try {
_socket.close();
_in.close();
_out.close();
connected = false;
} catch(IOException e) {
System.out.println(e);
}
}
}
A few things (don't take this the wrong way, I think you are doing quite well):
public void connect() throws Exception {
connected = true;
_socket = new Socket(_server, _port);
run();
}
You are setting connected to true, but you don't appear to know why because you only check it once :)
It would be more appropriate to have your while loop check this boolean rather than loop until an Exception occurs.
authinfo.add((int) 0x00000000); // product language
authinfo.add((int) 0x00000000); // Local ip
authinfo.add((int) 0x00000000); // Timezone bias
authinfo.add((int) 0x00000000); // Locale Id
authinfo.add((int) 0x00000000); // Language Id
You don't need to cast an integer to an integer! :) authinfo.add(0); would work for any of those but if you prefer the full hex dword notation thats fine too.
public void sendNow(util.Buffer data) throws IOException {
_out.write(data.getBuffer());
}
Don't forget to flush!
public void killSock() {
try {
_socket.close();
_in.close();
_out.close();
connected = false;
} catch(IOException e) {
System.out.println(e);
}
}
Those 3 close methods are pretty likely to throw an IOException before all of them finish executing (especially since you are closing the streams after they should already be closed since you closed the socket). While probably a minor issue, that could easily cause connected to not be changed. I would change it first or change it outside the try{} block.
Quote from: unTactical on September 18, 2006, 10:03:26 AM
A few things (don't take this the wrong way, I think you are doing quite well):
public void connect() throws Exception {
connected = true;
_socket = new Socket(_server, _port);
run();
}
You are setting connected to true, but you don't appear to know why because you only check it once :)
It would be more appropriate to have your while loop check this boolean rather than loop until an Exception occurs.
The connected boolean is reserved for future use.
Quote from: unTactical on September 18, 2006, 10:03:26 AM
authinfo.add((int) 0x00000000); // product language
authinfo.add((int) 0x00000000); // Local ip
authinfo.add((int) 0x00000000); // Timezone bias
authinfo.add((int) 0x00000000); // Locale Id
authinfo.add((int) 0x00000000); // Language Id
You don't need to cast an integer to an integer! :) authinfo.add(0); would work for any of those but if you prefer the full hex dword notation thats fine too.
I copyed that stuff from javaop1. Blame iago. :)
Quote from: unTactical on September 18, 2006, 10:03:26 AM
public void sendNow(util.Buffer data) throws IOException {
_out.write(data.getBuffer());
}
Don't forget to flush!
public void killSock() {
try {
_socket.close();
_in.close();
_out.close();
connected = false;
} catch(IOException e) {
System.out.println(e);
}
}
Those 3 close methods are pretty likely to throw an IOException before all of them finish executing (especially since you are closing the streams after they should already be closed since you closed the socket). While probably a minor issue, that could easily cause connected to not be changed. I would change it first or change it outside the try{} block.
Hmm... should do flush();... otherwise i get a stinky socket :)
And yah, never realy looked much at killsock(). Thanks for ponting that out
Thnx for the help. Now i just need to identify packets (Yay?) and make them trigger events.
Quote from: chuck on September 18, 2006, 11:09:59 AM
The connected boolean is reserved for future use.
Thats fine, but I still think an infinite loop with the only escape possibility being an exception is bad practice.
Quote from: chuck on September 18, 2006, 11:09:59 AM
Quote from: unTactical on September 18, 2006, 10:03:26 AM
authinfo.add((int) 0x00000000); // product language
authinfo.add((int) 0x00000000); // Local ip
authinfo.add((int) 0x00000000); // Timezone bias
authinfo.add((int) 0x00000000); // Locale Id
authinfo.add((int) 0x00000000); // Language Id
You don't need to cast an integer to an integer! :) authinfo.add(0); would work for any of those but if you prefer the full hex dword notation thats fine too.
I copyed that stuff from javaop1. Blame iago. :)
/me yells at iago
Quote from: chuck on September 18, 2006, 11:09:59 AM
Thnx for the help. Now i just need to identify packets (Yay?) and make them trigger events.
No problem, you'll probably what a constants class for identifying the packets, mine is more up to date than iagos and any that I've seen on VL.
Feel free to use it: http://clanhiim.com/sheriff/src/constants/PacketConstants.class
Quote while (true) {
line = _in.read();
print("" + line);
}
Thats where connected should be used.
Also, you're reading a byte not a line.
Quote public int getGameCode() {
return 'W' << 24 |
'2' << 16 |
'B' << 8 |
'N' << 0;
}
Its more efficient jsut to store the result fo that, insted of figuring it out every time.
private static final PROD_W2BN = 0x5732424E //W2BN
Quote
login();
print("Logged in.");
!! OMG YOU SENT ONE PACKET AND POOF YOU'RE LOGGED IN!!!
Just had to rag on you about your naming.
Quote public void login() {
if (connected) {
try {
send((byte)0x01); // Send login thingy
/*
code
*/
sendNow(authinfo);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
1st, The 'Login thingy' is called the protocol byte. It tells the server what you want to do!
2nd, You have sendNow throw a IOException.. that okay, but then you have login() handle that! So you are sjtu going to go along as if no exception was thrown? Bad boy.
And seriously, don't be lazy, use the correct protocol!
QuoteIts alright, i just found out how to get over the first hurdle.
QuoteI copyed that stuff from javaop1.
Obviously not...
Learn what that 'stuff' is before you continue.
~-~(HDX)~-~
He is doing fine, I doubt you wrote a packet buffer from scratch the first time you created a socket based program ;)
While you are right in all your points above, the efficiency thing is less important than him understanding it, so I made a point to not mention it.
Quote from: unTactical on September 18, 2006, 11:42:50 AM
He is doing fine, I doubt you wrote a packet buffer from scratch the first time you created a socket based program ;)
While you are right in all your points above, the efficiency thing is less important than him understanding it, so I made a point to not mention it.
Not the 1st time, but after like 3 hrs of doing
wsClient.Send(Chr$(0))
/me shudders at those days
I decided to write a crappy buffer yes.
Also I assumed he understood it if he could write such a function. (But now I see he jsut stole it from ron)
I prefer people do things right (AE: following the protocol correctly.)
Also, 'OLS' is harder then 'OOLS' (SID_AUTH* vs non.)
~-~(HDX)~-~
Quote from: unTactical on September 18, 2006, 11:42:50 AM
He is doing fine, I doubt you wrote a packet buffer from scratch the first time you created a socket based program ;)
I did on my first C program, what do I win?
(http://www.ftd.com/pics/products/X657_c.jpg)
Quote from: Blaze on September 18, 2006, 11:51:42 AM
Quote from: unTactical on September 18, 2006, 11:42:50 AM
He is doing fine, I doubt you wrote a packet buffer from scratch the first time you created a socket based program ;)
I did on my first C program, what do I win?
Have a dancing carrot.(http://i21.photobucket.com/albums/b293/LINKDARK51/Nintendo%20Bananas/RedPikminBannana.gif)
Woot, thanks to joes code, look!
Send 0x50
Send 0x25
Login packets sent.
Received ping from Battle.net
0x50 Packet recevied
MPQName: X}???ver-IX86-1.mpq
CDKey accecpted.
Now to join channel and stuff!
Quote from: chuck on September 18, 2006, 01:02:56 PM
Woot, thanks to joes code, look!
Send 0x50
Send 0x25
Login packets sent.
Received ping from Battle.net
0x50 Packet recevied
MPQName: X}???ver-IX86-1.mpq
CDKey accecpted.
Now to join channel and stuff!
You have no effing clue how any of that works do you?
And that is why I hate leechers.
-.-
~-~(HDX)~-~
Quote from: HdxBmx27 on September 18, 2006, 01:45:04 PM
Quote from: chuck on September 18, 2006, 01:02:56 PM
Woot, thanks to joes code, look!
Send 0x50
Send 0x25
Login packets sent.
Received ping from Battle.net
0x50 Packet recevied
MPQName: X}???ver-IX86-1.mpq
CDKey accecpted.
Now to join channel and stuff!
You have no effing clue how any of that works do you?
And that is why I hate leechers.
-.-
~-~(HDX)~-~
I have a pretty good understanding. And it DOES check that battle.net accecpted the cd key.
yay
Send 0x50
Login packets sent.
0x50 Packet recevied
CDKey accecpted.
Account name and password sent.
Joining channel Op FoeBot
Account & password valid.
Entered chat.
* chuck. joined the channel
<chuck.> s
* chuck. left the channel
Screenshot of GUI below
(http://xtarutaru.googlepages.com/aBnetBot.png)
One last question:
How with a jtextpane or jtextarea, do i make differnt color text? All yellow looks kinda yucky.
Quote from: chuck on September 18, 2006, 01:02:56 PM
Woot, thanks to joes code, look!
I'm pretty sure that's a first.
I added plugin support, so its now very similar to javaop.
NO, i DID NOT copy the plugin support. I wrote it from scratch.
There is no hardcoded GUI code, and the bots incredibly fast. Almost all battle.net packets are handled, just need to clean it up a bit. I manged to run it alongside starcraft with no speed loss at all.
:)
Quote from: chuck on September 18, 2006, 06:57:31 PM
the bots incredibly fast
cough, no flood protection, cough
Quote from: unTactical on September 18, 2006, 07:10:12 PM
Quote from: chuck on September 18, 2006, 06:57:31 PM
the bots incredibly fast
cough, no flood protection, cough
i meant in the fact that it loads its plugins
load uber fast. It will have flood protection in a few days. Need to clean up teh code (What a mess i made!)
EDIT: in bold
Does anyone know a way to get a profile correctly? I tryed:
BNetBuffer buf = new BNetBuffer((byte) 0x26);
buf.addDWord(1);
buf.addDWord(4);
buf.addNTString(account);
buf.addNTString("profile\\sex");
buf.addNTString("profile\\age");
buf.addNTString("profile\\location");
buf.addNTString("profile\\description");
sendNow(buf);
Which my packet sniffer shows as:
T 192.168.2.135:49708 -> 63.240.202.129:6112 [AP]
.&P.........FoeBot.profile\sex.profile\age.profile\location.profile\descriptio
n.
And my code to receive the packet look like:
case 0x26:
data.removeDWord(); // Num. accounts
int numKeys = data.removeDWord(); // Num. of keys
data.removeDWord(); // Request ID
String[] keys = new String[numKeys];
for (int z=0; z < numKeys; z++) {
keys[z] = data.removeNTString();
print(keys[z]);
}
Which always prints nothing. The packet bnet sends me back looks like:
T 63.240.202.129:6112 -> 192.168.2.135:49708 [AP]
.&..........FoeB....
I just cannot figure out how to send a String[] through a socket properly. Can anyone help me w/ this? Without flaming me?
NVM, found this document: http://www.valhallalegends.com/docs/ProfileRequest.htm
The code for other people (Sending profile request is the only one i changed for it to work)
public void sendProfileRequest(String account) {
try {
BNetBuffer buf = new BNetBuffer((byte) 0x26);
buf.addDWord(1);
buf.addDWord(4);
buf.addDWord(156); // some random number :)
buf.addNTString(account);
buf.addNTString("profile\\sex");
buf.addNTString("profile\\age");
buf.addNTString("profile\\location");
buf.addNTString("profile\\description");
sendNow(buf);
} catch (IOException ex) {
ex.printStackTrace();
}
}
EDIT:
SS
(http://xtarutaru.googlepages.com/abnetbotss3.png)
Do you understand the difference between your code and the working code?
Shear luck is the only reason you were even getting a response with your code instead of being timebanned :)
Quote from: unTactical on September 21, 2006, 06:54:07 PM
Do you understand the difference between your code and the working code?
Shear luck is the only reason you were even getting a response with your code instead of being timebanned :)
I understand the difference.
I was timebanned over 10 times while trying to get that to work
Incidentally, the following keys all work (insomuch that you don't get banned for requesting them):
profile\sex
profile\age
profile\location
profile\description
system\account created
system\last logon
system\last logoff
system\time logged
Leave it to Ron to come up with sex first in the list of all those. ^_^.
Yeah, who'd think I'd do it in the same order the Blizzard did, and who'd think that they'd do it in the order of the fields in the profile?
Quote from: Joex86] link=topic=7385.msg92764#msg92764 date=1159237614]
Leave it to Ron to come up with sex first in the list of all those. ^_^.
::)
Quote from: iago on September 26, 2006, 12:11:55 PM
Yeah, who'd think I'd do it in the same order the Blizzard did, and who'd think that they'd do it in the order of the fields in the profile?
Likely excuse.
Quote from: Joex86] link=topic=7385.msg92764#msg92764 date=1159237614]
Leave it to Blizzard to come up with sex first in the list of all those. ^_^.
Fixed.