PWAnnihilus - Sophisticated Botting, Who's with me? (C# + Javascript)

12/26/2011 03:21 novicehacker#1
I've mostly been a lurker on this forum however I figured I'd take another jump out of the shadows and propose that those of us interested in the botting of perfect world pool our efforts and work on something that the entire community can benefit from.

I have put a great deal of thought into an optimal botting solution and I think I've made some serious progress. As one of the greatest fears when running bots is that there may be malicious code inside I believe we can agree that releasing raw source in addition to a compiled binary is a good idea. I also believe that one of the main reasons for the relatively small number of bots is the effort it takes to write them as well as the complicated nature of memory reading, to this end I propose the following
  1. Botting framework that abstracts away the complicated and exposes an easy to use api for bot writers.
  2. Preferably a hosted SQLite database that can be downloaded by clients to update offsets. [if(current db pw version != current version) check for update]
  3. Have bot scripts written in Javascript as it is a popular and easy to use language allowing for rapid development. Using [Only registered and activated users can see links. Click Here To Register...] to handle javascript interpreting in a sandboxed environment we can help to ensure that scripts are safe for the user to run (only allow access to the necessary pw api functions, no local file access, no network access, etc) while simultaneously helping genuine AI writers reach a larger audience and develop faster.

Expanding upon my botting framework idea, the current implementation I've been working on involves a core program that performs the following
  1. Monitors Win32_ProcessStartTrace and Win32_ProcessStopTrace to detect when instances of elementclient.exe are started and stopped
  2. When an instance is detected it will spawn a thread to monitor that process.
  3. The process monitor will loop waiting for a character to log in
  4. When a character logs in will instantiate new instances of the bot scripts
  5. The process monitor then loops; reading process memory, calling the 'loop' function in each bot script, and then sleeping to maintain a desired 'tick' speed. Individual scripts can even specify a slower call speed causing them to only be called every x ticks instead of every tick (each script is also offset by an incremental amount to spread the load across ticks)
I am constantly impressed by the work and intelligence of some of the members of this forum and I would really love to see their work analyzing packets, examining process memory, code injection, etc reach it's full potential. If anyone has any ideas/suggestions or would like to contribute I'm all ears, this project will be infinitely better if powered by the collective ;)
12/26/2011 05:12 NaMeLeS_79#2
I think its a great idea and I would defiantly help if such a project was started

I also think functions other than grinding would be useful to include ie merchanting and mat collection
12/26/2011 06:27 novicehacker#3
Quote:
Originally Posted by NaMeLeS_79 View Post
I think its a great idea and I would defiantly help if such a project was started

I also think functions other than grinding would be useful to include ie merchanting and mat collection
Agreed. I'd love to open up as much of pw to automation as possible. Limiting scripts only by the creativity of the script writers. And there are already functions out there for getting lists of mats and for harvesting them. We just need to get all of those gems into one easy to use structured api instead of scattered around the internet as small code examples.
12/26/2011 10:37 Sᴡoosh#4
While I wont help, since I finance part of my studies through selling of bots, I genuinely wish you luck. What I see as a problem though is what vuduy said a few months ago in my bot thread, namely that PW is a dead game. This is evident every day, as it's sadly always the same people posting here, and always the same leechers.

I think with people like interest07, dumbfck , nameles (he's an awesome private server dev by the way), you are sure to find very good devs on here.

Good luck, finally some competition :D
12/26/2011 20:37 Interest07#5
I personally use a database to store the offsets, which I definitely think is a good idea (just a regular MySQL db). I've written most of my tools and a bot in C# and don't really have much experience with javascript (besides using it for bookmarklets and simple sites). I'm not sure why you'd choose javascript to write a bot in as it seems more aimed at web based stuff, but I'm willing to lend a hand regardless of your choice of language if time permits it.

I was planning to develop something with dumbfck, but I haven't really been around enough to work on that (@dumbfck sorry man).
12/26/2011 21:04 novicehacker#6
Quote:
Originally Posted by Interest07 View Post
I personally use a database to store the offsets, which I definitely think is a good idea (just a regular MySQL db).
I'm actually more familiar with MySQL myself, but SQLite has a smaller file size and the advanced features offered by MySQL that SQLite lacks don't seem needed for our purpose.

Quote:
Originally Posted by Interest07 View Post
I've written most of my tools and a bot in C# and don't really have much experience with javascript (besides using it for bookmarklets and simple sites). I'm not sure why you'd choose javascript to write a bot in as it seems more aimed at web based stuff
Most of the heavy lifting will still be done on the C# side, it's just the high level logic in javascript. I chose javascript because
  • It is an easy to learn/use language (and the syntax is close to c#/java but with dynamic typing)
  • There is already an open source interpreter to use (that sandboxes code even)
  • Javascript is becoming exceedingly popular as a programming/scripting language (node.js for example) so continued advancements in interpreters are fairly likely.

Quote:
Originally Posted by Interest07 View Post
but I'm willing to lend a hand regardless of your choice of language if time permits it.
Glad to hear it, it's actually a lot of your work (and dumbfck's) that inspired me to start this project. I'd really like to see your work get utilized to it's full potential.
12/26/2011 21:47 NaMeLeS_79#7
Yeah, it would be great if you helped Interest, you have a lot of experience and your work that I have seen is pretty awesome
12/26/2011 21:53 ptdk#8
While i have absolutely no idea about programming, sounds like a wellplanned, great idea.

If there is anything i can help with, like testing or idk, lmk(i cant write programs besides the most simple php shet). I honestly cant think of anything i could do so just gonna wish u luck.

GL
12/26/2011 23:02 novicehacker#9
Note this solution ONLY demonstrates the scripting capability, there is no integration with PW or PW functions included. Don't bother downloading unless you want a look at code.

Attached is a copy of a C# solution folder featuring a demo of the Jint engine and my tick based setup. The source code is included (and commented!) and should be ready to be opened in VS. I think after seeing the demo we'll be in agreement that this is the way to go for script development. Included is a demo script file, so just run the solution to see.
12/27/2011 10:19 Interest07#10
Quote:
Originally Posted by novicehacker View Post
Note this solution ONLY demonstrates the scripting capability, there is no integration with PW or PW functions included. Don't bother downloading unless you want a look at code.

Attached is a copy of a C# solution folder featuring a demo of the Jint engine and my tick based setup. The source code is included (and commented!) and should be ready to be opened in VS. I think after seeing the demo we'll be in agreement that this is the way to go for script development. Included is a demo script file, so just run the solution to see.
Definitely interesting concept, I've never done anything like this before so it should make for a good experience. Just did a little reading on javascript and besides the horribly confusing syntax for everything it does have everything you need for decent programming too.

What sane person would ever come up with declaring classes as functions I'll never know, but one can get used to it all I suppose. So how exactly do you link variables and functions from the C# side of things to the JS? I assume you will want to somehow call C# functions from the JS, just not sure what exactly you will have access to and how that's determined.
12/27/2011 12:02 novicehacker#11
Quote:
Originally Posted by Interest07 View Post
Definitely interesting concept, I've never done anything like this before so it should make for a good experience.
I haven't either actually, but if it works out half as well as I've got it in my head I think we'll be okay lol.

Quote:
Originally Posted by Interest07 View Post
Just did a little reading on javascript and besides the horribly confusing syntax for everything it does have everything you need for decent programming too.
It's really not that bad once you get used to it, and the plan is to use it like it's original purpose, as a scripting language. The main goal is to be able to write a script like
Code:
/**
* PWAnnihilusScript
* name Novice's AutoPot
* author novicehacker
*/

var script_settings = {
	"tick_delay" : 5,
	"script_name" : "Novice's AutoPot"
};

var minimum_percent = .20;
var minimum_hp;

function init(){
	minimum_hp = player.hp_max * minium_percent;
	return script_settings;
}

function loop(){
	if(player.hp < minimum_hp && player.has_item(/* item_id */))
		player.use_item(/* item_id */);
}
And have a functioning bot (autopot in this case). We leave the updating of the player variable and the implementation of the player.has_item, player.use_item to our core framework in c# and only worry about the AI logic in the javascript. We also make it easy to use multiple scripts simultaneously; perhaps one script for deciding which items are worth looting, another to handle the autopotting, another to handle combat (skill usage, etc), etc all working in tandem to provide the best experience possible while also opening up script development to a wider range of skill sets (plenty of people are uncomfortable attempting to decipher program memory) and drastically reducing the development time.

Quote:
Originally Posted by Interest07 View Post
So how exactly do you link variables and functions from the C# side of things to the JS? I assume you will want to somehow call C# functions from the JS, just not sure what exactly you will have access to and how that's determined.
If you look at the sample zip i posted it contains a demo implementation that answers most of your questions. I'd also recommend a quick look at [Only registered and activated users can see links. Click Here To Register...], it's basically just an FAQ and it's really short and straight to the point. I'll release an updated scripting demo sometime tomorrow that allows including additional files and has file read/write permission to it's own directory (config files, etc)
12/27/2011 12:38 Interest07#12
Ah yeah, just had some trouble figuring out how to use a function with return value.

So basically you're gonna have a huge list of added functions like:
Code:
            //Setup a parsing engine instance.
            engine = new Jint.JintEngine()
                .SetFunction("print", new Action<object>(Console.WriteLine))
                .SetFunction("testF", new Func<int>(testFunc));
//etc....
Just playing around a bit with how the two languages communicate. Takes some getting used to, but should end up real nice.

edit: oh wait, you can just make like a separate C# class that contains all the necessary functions, so you don't need to set a billion functions up like that.

This is looking good :)

(especially since I have the C# utility classes pretty much lined up for usage, just need the exact specifications and I could easily whip them up for ya)

Quote:
Originally Posted by novicehacker View Post
I haven't either actually, but if it works out half as well as I've got it in my head I think we'll be okay lol.


It's really not that bad once you get used to it, and the plan is to use it like it's original purpose, as a scripting language. The main goal is to be able to write a script like
Code:
/**
* PWAnnihilusScript
* name Novice's AutoPot
* author novicehacker
*/

var script_settings = {
	"tick_delay" : 5,
	"script_name" : "Novice's AutoPot"
};

var minimum_percent = .20;
var minimum_hp;

function init(){
	minimum_hp = player.hp_max * minium_percent;
	return script_settings;
}

function loop(){
	if(player.hp < minimum_hp && player.has_item(/* item_id */))
		player.use_item(/* item_id */);
}
And have a functioning bot (autopot in this case). We leave the updating of the player variable and the implementation of the player.has_item, player.use_item to our core framework in c# and only worry about the AI logic in the javascript.


If you look at the sample zip i posted it contains a demo implementation that answers most of your questions. I'd also recommend a quick look at [Only registered and activated users can see links. Click Here To Register...], it's basically just an FAQ and it's really short and straight to the point. I'll release an updated scripting demo sometime tomorrow that allows including additional files and has file read/write permission to it's own directory (config files, etc)
12/28/2011 03:49 novicehacker#13
Quote:
Originally Posted by Interest07 View Post
So basically you're gonna have a huge list of added functions like:
Code:
            //Setup a parsing engine instance.
            engine = new Jint.JintEngine()
                .SetFunction("print", new Action<object>(Console.WriteLine))
                .SetFunction("testF", new Func<int>(testFunc));
//etc....
We can also use .SetParameter("name", object) to pass objects to javascript (running into a few bugs with it atm though, but I'm working on sorting them out). On a side note we can also subscribe to events with javascript code so that we can just fire events like onmessagerecieved, onlevelup, etc instead of needing the javascript code to keep checking for those actions as well.

Quote:
Originally Posted by Interest07 View Post
(especially since I have the C# utility classes pretty much lined up for usage, just need the exact specifications and I could easily whip them up for ya)
I'm actually open to suggestions on the structure of the pw data in the backend as you're much more familiar with the information available.

I also noticed you were tinkering with getting custom displays inside pw (saw your autopot screen somewhere), how complicated is that? If we could rig up some really basic gui creation functions that people could call that would be pretty epic as well, however I have no experience with that so I'm not sure how feasible it is.
12/28/2011 10:21 Interest07#14
Quote:
Originally Posted by novicehacker View Post
We can also use .SetParameter("name", object) to pass objects to javascript (running into a few bugs with it atm though, but I'm working on sorting them out). On a side note we can also subscribe to events with javascript code so that we can just fire events like onmessagerecieved, onlevelup, etc instead of needing the javascript code to keep checking for those actions as well.

I'm actually open to suggestions on the structure of the pw data in the backend as you're much more familiar with the information available.
What I currently do is this:

I have a PWProcess class that contains all the pw objects and functions, which I call from the GUI layer, so kind of like we will have with the javascript.

The PWProcess contains objects that are structured pretty much like PWI is, as this seemed to be the natural way to go about it. (e.g. a player object that contains functions to move, an itemList object as inventory which contains item objects, etc)

I have one shared Dictionary object (shared by all threads and classes) with all the offsets, read straight from the database, like this:

Code:
        private void loadOffsets()
        {
            if (!loadedOffsets)
            {
                    //Get offsets from database

                    //Open connection
                    OdbcConnection odbcConnection = new OdbcConnection(connectionString);
                    openConnection(odbcConnection);

                    //Read offsets table

                    OdbcCommand selectOffsetsCommand = new OdbcCommand(selectOffsets, odbcConnection);
                    OdbcDataReader offsetsReader = selectOffsetsCommand.ExecuteReader();

                    string name = "";
                    int value = 0;

                    while (offsetsReader.Read())
                    {
                        name = (string)offsetsReader[0];
                        value = (int)offsetsReader[1];
                        offsets[name] = value;
                    }

                    Debug.WriteLine("Read {0} offsets from database.", offsets.Count);
                    loadedOffsets = true;

                    //Close connection
                    odbcConnection.Close();
            }

        }
Then in each class such as player I read the offsets into local variables. This is not necessary of course, and does add a bit of bloat to each class (not that much), but it saves having to access the dictionary each time and ensures easier modification of database offset names (i.e. you don't have to track them down through everywhere in the class the offsets are used).

Then I 'hide' all the memory reading / writing parts by using properties like this:
Code:
        public PWParty party
        {
            get        
            {
                int address = MemFunctions.MemReadInt(processHandle, getPlayerAddress() + off_player_party);
                if (address == 0)
                {
                    return null;
                }
                return new PWParty(processHandle, offsets, address);
            }
        }

        public float expLostOnRevival
        {
            get { return MemFunctions.MemReadFloat(processHandle, getPlayerAddress() + off_player_expLostOnRevival); }
            set { MemFunctions.MemWriteFloat(processHandle, getPlayerAddress() + off_player_expLostOnRevival, value); }
        }
Where, depending on the type of variable, they get a get and/or set property. There's about 20 or so classes like that.


Quote:


I also noticed you were tinkering with getting custom displays inside pw (saw your autopot screen somewhere), how complicated is that? If we could rig up some really basic gui creation functions that people could call that would be pretty epic as well, however I have no experience with that so I'm not sure how feasible it is.
Displaying stuff in itself isn't hard, but you have to do it in C++. Designing the menus and such is a bit of a hassle if you want to maintain the feel of PWI as you're stuck with their image files. The biggest issue is really dragging and dropping items/skills from a PWI menu to your own, as you have to work around some stuff then, and it makes displaying stuff a bit harder with all the z-axis thinking going on.

If all you want to do is some simple text showing and whatever, then it won't be hard at all, as long as you somehow inject a dll (written in C++) into the process. Then again, you'd have to set up some form of communication between the dll and your own C# framework, which I haven't done before, although it shouldn't be that hard.

dumbfck has been doing some very interesting work on an alternative method of ingame GUI creation, which I believe is more promising if you really want something modular. I'm not sure how far along he is exactly, but it was looking to be really sweet.


One thing I noticed, Jint doesn't support threading? That might be an issue if you have a multitude of scripts each being used for a varying amount of PW clients. I was also thinking, if displaying an inagme GUI is somehow not working out, maybe add hotkey support. Allow the user the numpad keys 0-9 as hotkeys to call some specific function in their script if they have it set up in their settings.

Were you planning on having the javascript side of things get a list of all the PW clients, so the user browses through the clients on there, or do you plan on having the javascript executed for each active client?

edit:

What I mean is, do you have something like this in the javascript:
Code:
	var clientArray = test.getPWclients("elementclient");
	for(i = 0; i < clientArray.Length; i++)
	{
		print(clientArray[i].MainWindowTitle);
	}
or do you have something like this in the loop structure, where you pass each individual client to the javascript as parameter:

Code:
            if ((counter + i) % userscripts[i].tick_delay == 0)
            {
                Process[] pwClients = Process.GetProcessesByName(processName);
                for (int j = 0; j < pwClients.Length; j++)
                {
                    userscripts[i].loop(pwClients[j]);
                }
            }
edit: on second thought, that would probably require a separate running script for each individual client, or quite some hassle with the JS global vars (all as arrays for the individual clients)

Obviously, not exactly like this, as you won't be giving the script access to the actual processes, but more an encapsulation of them with whatever functions you need, like I mentioned before. There's quite a difference though, as the user either views all the processes as individuals (like in prophetbot) or as a whole (for example bots in parties, like I do). One way would perhaps be slightly more complex, but as we're assuming the user can code javascript that might not be an issue.

Then again, there are different levels of user, those that create the scripts, and those that merely adjust the settings in the scripts created by others.

Sorry for the wall of text, usually I'll be adding my thoughts over time with the edit button and as the day goes by things ... expand :D
12/29/2011 01:13 novicehacker#15
Quote:
Originally Posted by Interest07 View Post
Were you planning on having the javascript side of things get a list of all the PW clients, so the user browses through the clients on there, or do you plan on having the javascript executed for each active client
Currently I've been planning on having it executed separately for each client. Main reason is that way the user can restrict which processes the bot runs on without hoping the bot writer provides that functionality. It also makes it easy if you want to run different scripts for different characters. At the moment it actually works out to 1 engine instance per script per character, we might be able to optimize that a bit, but so far the performance seems fine running it this way (although I'm away on vacation and my laptop is fairly old, won't be able to do a full test until I'm back home and can use my desktop)

Quote:
Originally Posted by Interest07 View Post
Sorry for the wall of text, usually I'll be adding my thoughts over time with the edit button and as the day goes by things ... expand :D
No worries, I'm glad I'm not the only one excited by this :) and I do appreciate your insights.