If you just want code
If you just want code, as you learn better from it, this piece of software can be found on google code at http://code.google.com/p/tibia-reader/source/browse/trunk/MemoryReader/Form1.cs
Note that it may not work fully, and it will probably contain some bugs. It was written as an example only, and for the purpose of demonstrating how easy it is to extract information from the Tibia client. The information can be used in a variety of ways, the most common of course being to create a cavebot. The best understanding of this will come from the tutorial detailed below, but I have not followed best practice, as I am not a professional programmer, just a hobbyist. There is also a compiled version of the software on the google code page, so if you want to see the results you are welcome to take a look at that.
Getting Started
So, first off, we need to set out some variables to work with. This will allow us to store and call data as we need it.
Here are the two process based ones, which will allow us to obtain information from our computer about which pieces of memory Tibia is using. The first variable will store the base address, and the second will store the process itself (as in task manager, but with more information!)
[code=c#] public static UInt32 Base = 0;
public static Process Tibia = null;[/code]
Now for our memory addresses
[code=c#] UInt32 Pxor = 0x3B3ED0;
UInt32 HpAdr = 0x549000;
UInt32 XpAdr = 0x3B3EE0;
UInt32 MpAdr = 0x3B3F24;
UInt32 CpAdr = 0x580E94;
UInt32 SlAdr = 0x3B3F10;
UInt32 StAdr = 0x3B3F58;
UInt32 MlAdr = 0x3B3ED4;
UInt32 IdAdr = 0x580EA4;[/code]
If the client is updated, the addresses are all we need to update. Here are a few more, which are only used in the battle list
[code=c#] UInt32 BlStart = 0x549008;
UInt32 BlStep = 0xB0;
public int MaxCreatures = 1300;[/code]
These dictate where (in the memory) the battle list starts - BlStart, and how big each entry in the battle list is - BlStep. The third shows how many creatures the Tibia client can store information on at once - MaxCreatures. The tibia client itself will only allow 1300, so we will too.
Using Windows functions, our way
The next step is to import a function from a windows library, which will allow us to access Tibias memory.
[code=c#] [DllImport("kernel32.dll")]
public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
[In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);[/code]
Now we want to use this function (ReadProcessMemory) to read memory addresses, and convert the contents to a format which will be useful to us. So we will start off by creating something to simplify this function (otherwise we would need to enter more information than we should).
?
[code=c#] public static byte[] ReadBytes(IntPtr Handle, Int64 Address, uint BytesToRead)
{
IntPtr ptrBytesRead;
byte[] buffer = new byte[BytesToRead];
ReadProcessMemory(Handle, new IntPtr(Address), buffer, BytesToRead, out ptrBytesRead);
return buffer;
}[/code]
ReadBytes will now read bytes, and return the bytes, so we can do for instance byte[] myvariable = ReadBytes(Handle, Address, BytesToRead);
To use this more to our benefit, we can also convert the bytes into integer values, as shown.
[code=c#] public static int ReadInt32(IntPtr Handle, long Address)
{
return BitConverter.ToInt32(ReadBytes(Handle, Address, 4), 0);
}[/code]
And we can read strings, using an ASCII converter. This also removes all “null characters” from the extracted string, after reading 32 bytes. Because we are reading exactly 32 bytes each time we run this, we will always have 32 bytes of data. We can store a name, like XtrmJosh in fewer than 32 bytes, in fact I believe it would take 8 bytes (don’t take my word for that though, I’m no memory buff!) As a result of this, using ASCII encoder, we would end up with a string like XtrmJosh000000000000000000000000, or something of a similar length, at least. These 0s all represent “\0”, which is a null character in C#. We are replacing those, using temp3 (the variable our read string is stored in) as shown.
[code=c#] public static string ReadString(IntPtr Handle, long Address)
{
string temp3 = ASCIIEncoding.Default.GetString(ReadBytes(Handle, Address, 32));
return temp3.Replace("\0", string.Empty);
}[/code]
Ease of Access to memory
To make it easier to access the memory, we can now write some functions which will read the memory at the addresses we declared earlier. Here are a few I’ve put together, see what addresses you can find, and see how you get on with them.
[code=c#]
public int hp() { return ReadInt32(Tibia.Handle, HpAdr + Base) ^ ReadInt32(Tibia.Handle, (Pxor + Base)); }
public int xp() { return ReadInt32(Tibia.Handle, XpAdr + Base); }
public int mp() { return ReadInt32(Tibia.Handle, MpAdr + Base) ^ ReadInt32(Tibia.Handle, (Pxor + Base)); }
public int cp() { return (ReadInt32(Tibia.Handle, CpAdr + Base) ^ ReadInt32(Tibia.Handle, (Pxor + Base))) / 100; }
public int id() { return ReadInt32(Tibia.Handle, IdAdr + Base); }
public int ml() { return ReadInt32(Tibia.Handle, MlAdr + Base) ^ ReadInt32(Tibia.Handle, (Pxor + Base)); }
public int sl() { return ReadInt32(Tibia.Handle, SlAdr + Base); }
public string st() { int minb = ReadInt32(Tibia.Handle, StAdr + Base); int houa = minb / 60; int mina = minb % 60; return houa.ToString() + ":" + mina.ToString("D2"); }
[/code]
Now, that's our general structure assembled.
We must now just declare our client, for which I've written another function we can call:
[code=c#] private void selectclient()
{
Process[] TibiaProcess = Process.GetProcessesByName("Tibia");
Tibia = TibiaProcess[0];
Base = Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToIn t32());
}[/code]
This will select the first client it finds, if you want, I will add a tutorial for creating a list of clients. This also gets the base address of the client (the starting address, explained further in the battle list tutorial).
Stay tuned for some guide to reading the battle list.
For anyone really newbie, I'll point out that to read memory, after having implemented this code, you just need to do:
[code=c#]
MessageBox.Show("Health: " + Convert.ToString(hp()));
[/code]
Of course change hp() to xp() or whatever you want.
[hr]
Reading the Battle List
Structure
So first off, we need to make a structure. It’s an easy thing to do, just add some code similar to this into your form. Generally speaking, people create a new class for their structures, but for those who don’t know how to do this, you can do it this way for now. If you intend to make some massive advanced program, you will want to learn about using multiple classes and how to pass data between them.
[code=c#] public struct blist
{
public int cid;
public int type;
public string name;
public int z;
public int y;
public int x;
public int iswalking;
public int direction;
public int outfit;
public int outfithead;
public int outfitbody;
public int outfitlegs;
public int outfitfeet;
public int outfitaddon;
public int light;
public int lightcolour;
public int hpbar;
public int walkspeed;
public int unknown;
public int skull;
public int party;
public int war;
public int blocking;
public int visible;
}[/code]
Offsets
Offsets are simple, really, they are exactly what they say. Take the number 1, and consider that the start of a street is house number 1. The house at number 5 would have an offset of 4, because it is 4 houses along from 1! If, however, the first house was 3, house number 5 would have an offset of just 2! I hope this makes sense. The offsets are as follows, though don’t use this code in your form as it is space consuming, and probably confusing. I recommend adding a text file to your project and saving this list there, for future reference.
UInt32 OFFSET_CREATURE_ID = 0;
UInt32 OFFSET_CREATURE_TYPE = 3;
UInt32 OFFSET_CREATURE_NAME = 4;
UInt32 OFFSET_CREATURE_Z = 36;
UInt32 OFFSET_CREATURE_Y = 40;
UInt32 OFFSET_CREATURE_X = 44;
UInt32 OFFSET_CREATURE_IS_WALKING = 80;
UInt32 OFFSET_CREATURE_DIRECTION = 84;
UInt32 OFFSET_CREATURE_OUTFIT = 100;
UInt32 OFFSET_CREATURE_OUTFIT_HEAD = 104;
UInt32 OFFSET_CREATURE_OUTFIT_BODY = 108;
UInt32 OFFSET_CREATURE_OUTFIT_LEGS = 112;
UInt32 OFFSET_CREATURE_OUTFIT_FEET = 116;
UInt32 OFFSET_CREATURE_OUTFIT_ADDON = 120;
UInt32 OFFSET_CREATURE_LIGHT = 124;
UInt32 OFFSET_CREATURE_LIGHT_COLOR = 128;
UInt32 OFFSET_CREATURE_HP_BAR = 140;
UInt32 OFFSET_CREATURE_WALK_SPEED = 144;
UInt32 OFFSET_CREATURE_IS_VISIBLE = 148;
UInt32 OFFSET_CREATURE_SKULL = 152;
UInt32 OFFSET_CREATURE_PARTY = 156;
UInt32 OFFSET_CREATURE_WARICON = 164;
UInt32 OFFSET_CREATURE_ISBLOCKING = 168;
UInt32 OFFSET_CREATURE_WITHINVIEW = 172;
The offsets are pretty self-explanatory, if you need help with one in particular, just ask.
I’m confused, where are we?
So what we’ve done previously is we’ve found a Tibia client, and gotten the base address for it. We’ve then read memory using the address of each element we wanted (e.g the address of our experience, or the address of our health). What we will now do is read the battle list. To do this we basically have to do start address (Base), added onto the battle lists start address (BlStart), then added to the offset of each piece of information (e.g 4 for creature name). Are you still with me?
Finally, the actual “reading”
So here what we will do is read each offset one by one, for the first entry in the battle list. We will then add the step for the creature on to a variable, “current”, so we can track which entry into the battle list we are on. We will then repeat the process until we have read all (up to 1300) entries.
The function looks a little like this:
[code=c#] private void readBlist()
{
// Declare an integer “max”, which will calculate the highest memory address to read.
int max = Convert.ToInt32(BlStep) * MaxCreatures;
// Declare a list of blist (the struct we made earlier) to store the information into.
lst = new blist[1300];
// Declare the current variable, to show where we are each time we start the loop
UInt32 current = BlStart;
// Basically declare I to be 0, and whilst I is under 250, do the contents of the braces and add 1 to i.
for (int i = 0; i < 1300; i++)
{
// If the current creature id is not 0, read the information about the entry. This saves us from reading 1300 entries if we don’t need to, we will always read 1300 creature ids, but we won’t waste time reading all the other shit.
if (ReadInt32(Tibia.Handle, current + Base) != 0)
{
int[] offsets = new int[24] { 0, 3, 4, 36, 40, 44, 80, 84, 100, 104, 108, 112, 116, 120, 124, 128, 140, 144, 148, 152, 156, 164, 168, 172 };
int b = 0;
lst[i].cid = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].type = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].name = ReadString(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].z = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].y = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].x = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].iswalking = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].direction = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].outfit = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].outfithead = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].outfitbody = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].outfitlegs = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].outfitfeet = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].outfitaddon = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].light = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].lightcolour = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].hpbar = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].walkspeed = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].unknown = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].skull = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].party = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].war = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
lst[i].blocking = ReadInt32(Tibia.Handle, current + offsets[b] + Base);
lst[i].visible = ReadInt32(Tibia.Handle, current + offsets[b] + Base); b = b + 1;
}
// Add the step to the variable current, so next time we read the next entry.
current = current + BlStep;
}
}[/code]
Each line is explained where applicable, so please read this carefully to help you understand.
Once this function has been run, we can simple call lst.Name, lst.cid or whatever to get that piece of information about the creature.