Valhalla Legends Forums Archive | Battle.net Bot Development | Bot basics (Java)

AuthorMessageTime
mirza911
I am very new to bot making but i am pretty comfortable with java and i want to try to write a simple bot in java just to get the feel for it. I have been using bnetdocs, wireshark, and d2 smells to see the communication between battle.net and my computer. but the basics of a bot are still very hard for me to grasp.

-I need some advice on how to take the data from the bnet and read it.
-I need advice on how to send the proper packet back.
-With a packet there is so much to look at. I don't know which part is the most important to me and what i need to modify and send back.

This is the code i found online and added a couple things to it. I just want to try to send the first packet successfully.

import java.net.InetAddress;

import jpcap.*;
import jpcap.packet.EthernetPacket;
import jpcap.packet.IPPacket;
import jpcap.packet.Packet;
import jpcap.packet.TCPPacket;

class SendTCP
{
    public static void main(String[] args) throws java.io.IOException
    {
        NetworkInterface[] devices = JpcapCaptor.getDeviceList();
        if (args.length < 1)
        {
            System.out
                    .println("Usage: java SentTCP <device index (e.g., 0, 1..)>");
            for (int i = 0; i < devices.length; i++)
                System.out.println(i + ":" + devices[i].name + "("
                        + devices[i].description + ")");
            // System.exit(0);
        }
        int index = Integer.parseInt(args[0]);
        JpcapSender sender = JpcapSender.openDevice(devices[index]);

        TCPPacket p = new TCPPacket(50371, 6112, 1, 1, false, true, true,
                false, false, false, false, false, 16896, 00);
        p.setIPv4Parameter(0, false, false, false, 0, false, false, false, 0,
                1010101, 128, IPPacket.IPPROTO_TCP, InetAddress.getLocalHost(),
                InetAddress.getByName("useast.battle.net"));
        byte[] by = new byte[]
        { (byte) Integer.parseInt("01", 16) };
        p.data = by;

        EthernetPacket ether = new EthernetPacket();
        ether.frametype = EthernetPacket.ETHERTYPE_IP;
        ether.src_mac = new byte[]
        { (byte) 0, (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5 };
        ether.dst_mac = new byte[]
        { (byte) 0, (byte) 6, (byte) 7, (byte) 8, (byte) 9, (byte) 10 };
        p.datalink = ether;

        for (int i = 0; i < 1; i++)
            sender.sendPacket(p);
        sender.close();
        System.out.println("done");
        return;
    }
}

I would be happy with just a logon bot.
Any help will be appreciated.
December 21, 2009, 12:26 AM
HdxBmx27
Why are you using jpcap?
Just use standard java sockets.
http://java.sun.com/j2se/1.4.2/docs/api/java/net/Socket.html
http://java.sun.com/docs/books/tutorial/networking/sockets/
Bnet docs describes the protocol, and what to send.
If you're looking for code handouts, JavaOp is open source, but you can just use it, you don't need to make your own.
December 21, 2009, 12:48 AM
mirza911
i tried getting javaop but all the links on the javaop homepage dont work. with mozilla or IE.

i thought jpcap would be more useful though why should i just use java sockets?

Also the whole bot thing. Will diablo know how to act based on the packets i send or do i need to send packets and still click on things and type things etc etc.?
December 21, 2009, 1:02 AM
HdxBmx27
Are you trying to 'hack' Diablo II?
AE, attach it to it while you're in game?
jpcap is for (i assume) capturing packets that other processes are sending/receiving. I think it's the java equivalent of PCap.
What EXACTLY are you wanting to do?
December 21, 2009, 1:07 AM
mirza911
i want to make a bot.
December 21, 2009, 2:06 AM
HdxBmx27
That does...
December 21, 2009, 2:07 AM
mirza911
well the main goal would be something like a gambling bot or mf bot but right now i want to start small to get the feel for it. something like a log in bot.
December 21, 2009, 2:19 AM
HdxBmx27
Well, it's rather difficult, pretty much impossible for you to write a bot that would do mf runs or anything.
But look at those two links i sent you
and learn the basics of sockets before you try anything else.
December 21, 2009, 2:21 AM
mirza911
do you mean just for me because i am so inexperienced? or for anyone?
Why exactly is it so impossible?
December 21, 2009, 2:24 AM
HdxBmx27
Few reasons, bust mainly because you're way to inexperienced.
To do a gambling or MF bot, you need to not only understand network programming, you also need to know how to read map files from D2. As well as different types of compression formats (namely huffman, for d2 in-game) Not to mention that quite a bit of things in D2 are not publicly documented, you can thank Ringo and a few others for what is known. (Quite a bit, but i think its outdated)

Do you know anything about network connections, or binary protocols?
Also, Java won't be able to actually hook into Diablo II, so you can't even be lazy, and make the game do most the work for you.

Start by making a basic text based server that echos things back and forth.
Then turn it into a basic binary protocol
Then you can start work on a bnet bot using BNLS because it does 90% of the hard stuff for you
Then work on doing things locally
Then work on in-game protocols.
THEN! once you get something in game and talking, you can work on doing specific things like ganbeling and stuff. BUT! Not many people will help you for that specific thing, because it's pretty much cheating, and ya, not a good thing here.

By the way, wtf is this?
[code]{ (byte) Integer.parseInt("01", 16) };[/code], Why not do (byte)1

I mean I *could* hand you the code that would connect you to Bnet and make it easy on you, But why? If you actually give a shit, you'll work and understand whats going on. Its NOT hard if you know the basics. B.net's protocol is really really simple. But if I were to ask you to show me the hex for the DWORD 0x010203 in network byte order, what would you show me?
December 21, 2009, 2:36 AM
mirza911
would the hex not just be 01 02 03 ? since that would be big-endian. And i am not sure that would just be my guess from what i've read up on it from the newcomers sticky.

I really appreciate you posting though and explaining what you have to me.
December 21, 2009, 3:30 AM
HdxBmx27
Yes, network byte order is big-endian, but, it would actually be: 00 01 02 03 As DWORDs are 32-bit integers (when referring to almost any system)
Let me know when you've made a echo server/client.
And I'll help you with understanding binary protocols.
December 21, 2009, 4:26 AM
mirza911
right that makes sense.  but in little endian would that be 03 02 01 00 or 00 03 02 01?
December 21, 2009, 4:41 AM
HdxBmx27
03 02 01 00
Most everything Battle.net related (and once again almost everything else) is little endian
With the exception of IP/Port information in the protocol.

But ya, get crackin on learnin to use sockets.
If you try hard should take you like.. a day. :P
December 21, 2009, 4:44 AM
mirza911
alright i got an echo server working. and its sending back whatever i send it. so thats why i assume its working...  :) . how can i "learn" to use them?
December 21, 2009, 5:09 AM
HdxBmx27
Show me your code.
If you did it correctly, you should know how to:
Create a Socket that is listening for connections
Accept incoming connections
Create a socket that connects to a remote server
Send data through a socket
Receive data through a socket
And hopefully, you've learned how to handle errors and tell when a socket is closed, could not connect, etc..
December 21, 2009, 5:35 AM
mirza911
This is what i got so far

import java.io.*;
import java.net.*;

public class EchoServer
{
    public static void main(String[] args)
    {
        try
        {
            ServerSocket s = new ServerSocket(6112);
            while (true)
            {
                Socket incoming = s.accept();
                // buffer
                BufferedReader in = new BufferedReader(new InputStreamReader(
                        incoming.getInputStream()));
                // writer
                PrintWriter out = new PrintWriter(new OutputStreamWriter(
                        incoming.getOutputStream()));

                out.println("Started - Type something to send");
                out.println("Enter \"E\" to exit.");
                out.flush();
                while (true)
                {
                    // read it in
                    String str = in.readLine();
                    if (str == null)
                    {
                        break; // client closed connection
                    }
                    else
                    {
                        // print echo back
                        out.println("Echo: " + str);
                        out.flush();
                        if (str.trim().equals("E"))
                            break;
                    }
                }
                incoming.close();
            }
        } catch (Exception e)
        {
            // handle some exceptions not sure how yet
        }
        return;
    }
}

Also i would like to know how to do that thing where u show the code in green text on posts =)
December 21, 2009, 6:35 AM
HdxBmx27
Use the [ code][ /code] (sans spaces) tag.
And a few notes:
Name your variables descriptively, save single char vars for counters, exa: sckServer or the socket, and x for for loop indexs
while(true) works, but you should NEVER have infinite loops.
Buffered readers, and writers are ok, but have you tried reading the input data yourself? because you'd have to do that for a binary protocol. Read the java docs for InputStream/OutputStream, it's simple
Make sure you understand why you used .trim() and .equals()
When dealing with single characters it's better to use constant comparisons: .charAt(0) = 'E'
And you need to learn how/why to handle exceptions, and how to deal with ones you expect (make it user friendly :P)
Also, you don't need to return from a function as the last line :P

And where is your client class?
December 21, 2009, 7:16 AM
mirza911
Still am not sure how to use the code tag.

but here is my server

import java.io.*;
import java.net.*;

public class EchoServer
{
    public static void main(String[] args)
    {
        try
        {
            ServerSocket srvrSocket = new ServerSocket(4004);
            while (true)
            {
                Socket incoming = srvrSocket.accept();
                // buffer
                BufferedReader in = new BufferedReader(new InputStreamReader(
                        incoming.getInputStream()));
                // writer
                PrintWriter out = new PrintWriter(new OutputStreamWriter(
                        incoming.getOutputStream()));

                while (true)
                {
                    // read it in
                    String str = in.readLine();
                    if (str == null)
                    {
                        break; // client closed connection
                    }
                    else
                    {
                        // print echo back
                        out.println("Echo: " + str);
                        out.flush();
                        if (str.trim().equals("BYE"))
                            break;
                    }
                }
                incoming.close();
            }
        } catch (Exception e)
        {
            System.out.println("Exception... exiting!");
            System.err.println(e);
            return;
        }
    }
}


and here is my client



import java.net.*;
import java.io.*;

public class EchoClient
{

    public static void main(String[] args)
    {

        String hostname = "localhost";

        if (args.length > 0)
        {
            hostname = args[0];
        }

        PrintWriter out = null;
        BufferedReader networkIn = null;
        try
        {
            Socket clientSocket = new Socket(hostname, 4004);
            networkIn = new BufferedReader(new InputStreamReader(clientSocket
                    .getInputStream()));
            BufferedReader userIn = new BufferedReader(new InputStreamReader(
                    System.in));
            out = new PrintWriter(clientSocket.getOutputStream());
            System.out.println("Connected to echo server");
            System.out.println("Started - Type something to send");
            System.out.println("Enter BYE to exit.");

            while (true)
            {
                String theLine = userIn.readLine();
                if (theLine.equals("BYE"))
                {
                    System.out.println("Exiting");
                    break;
                }
                out.println(theLine);
                out.flush();
                System.out.println(networkIn.readLine());
            }

        } // end try
        catch (IOException e)
        {
            System.out.println("IOException... exiting!");
            System.err.println(e);
            return;
        } finally
        {
            try
            {
                if (networkIn != null)
                    networkIn.close();
                if (out != null)
                    out.close();
            } catch (IOException e)
            {
                System.out.println("IOException... exiting!");
                System.err.println(e);
                return;
            }
        }
    }
}

The variables i know about. i was just kind of rushing through it =P.
what should i use instead of while(true)?
.trim to get rid of whitespaces? and .equals to check if i want to quit or not
Still no sure about the exception more advice on that would be great. how exactly i should handle them.

the return is just for me. sometimes my java programs will stick around if i dont return at the end and i will have to go into the task manager and get rid of them.


I know im still using buffers and pw's but im just taking babysteps. let me know what u think of this now and ill get started on reading the stuff without them. any tips greatly appreciated =)
December 21, 2009, 8:16 AM
HdxBmx27
Have you never used a forum before?
Just type {code}{/code} using []'s instead of {}'s (I hate not being able to not use tags :P)
But a few more note:
You should NOT need to use return, it's something else in your code thats not making it exit properly
Instead of while(true) it should be something like while(running) and set running = true, false if it needs to exit.
Also, you have 'BYE' exiting on the client, w/o sending it to the server, and you have the server terminating the connection on 'BYE' choose one or the other, not both. Just try and define a clear order of events, and responses, it should help establish a mindset of rigor protocols.
You don't really need a Finally case, you should have a generic error handler, and then specific ones for the errors you expect to happen (IO for socket errors, and Exception for generic)

Also, even though it defaults to .toString() when you print exceptions, you should still use it, just good habbits :/

Anyways, I guess you can move along to not using buffered readers/writers.
December 21, 2009, 8:32 AM
mirza911
lol ive used forums but this is just escaping my mind.
With while running would that be the same thing? setting it to false when they type in "BYE". so it would have the same functionality?
With the BYE you want me to send it to the client and then exit?
December 21, 2009, 5:52 PM
HdxBmx27
The infinite loop is prolly why your programs are sticking around after you want them to.
And make two commands, 1 on the server, that closes the connection. So you can handle on the client an unexpected disconnect exception, and 1 on the client that closes the connection so you can handle unexpected closured on the server.
using a var for thw while condition would make the loop exit cleanly when you want to kill the server.
December 21, 2009, 8:30 PM

Search