Deprecated: The behavior of unparenthesized expressions containing both '.' and '+'/'-' will change in PHP 8: '+'/'-' will take a higher precedence in /home/iano/public_html/tpforums-vb5/forum/includes/class_core.php on line 5842

PHP Warning: Use of undefined constant MYSQL_NUM - assumed 'MYSQL_NUM' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_ASSOC - assumed 'MYSQL_ASSOC' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_BOTH - assumed 'MYSQL_BOTH' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 588

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 612

PHP Warning: Use of undefined constant archive_postsperpage - assumed 'archive_postsperpage' (this will throw an Error in a future version of PHP) in ..../archive/index.php on line 456
WriteProcessMemory function [Archive] - Forums

PDA

View Full Version : WriteProcessMemory function



Sputnicker
02-05-2013, 12:17 PM
Hello fellows,
As many of you, I'm here because i'm trying to make my own bot for Tibia.
I'm stuck on the cavebot. I need to change the goto x,y,z values, but I'm having a bad time understanding the WriteProcessMemory function.
My C# is not that bad, I had some classes on college, where I study mechanical engineering.
I've search on legacy forum, but i'm not yet able to make it work.

Please, can someone spend a few minutes to help me figure out?
Thanks you guys!

Blaster_89
02-05-2013, 12:21 PM
It's declared exactly the same as ReadProcessMemory.
The C# code might look like this:


public bool WriteBytes(long address, byte[] bytes, uint length)
{
IntPtr bytesWritten;
int result = WinAPI.WriteProcessMemory(this.Client.TibiaHandle, new IntPtr(address), bytes, length, out bytesWritten);
return result != 0;
}

TibiaHandle is an IntPtr holding the Tibia process' handle.

Sputnicker
02-05-2013, 12:53 PM
Ok, so the first argument is the UInt32 adrXgo = 0x983EA0; the second argument is the value? (int gotox = 32933), and the third one is the lenght, so its equal 5?
If is that so, I'm having this problem:



UInt32 adrXgo = 0x983EA0; // Endereço para ir para posição X
int gotox = 32933;
WriteBytes(adrXgo, Convert.ToByte(gotox),5);

Error 1 Argument 2: cannot convert from 'byte' to 'byte[]'


What king of value the function is expecting at the second argument?

Blequi
02-05-2013, 01:13 PM
your second argument should be
new byte[]{ /* bytes goes here */}
BitConvert.GetBytes(gotox) instead of Convert.ToByte(gotox)



check tibiaapi memory functions, it's easy-to-use/understand http://code.google.com/p/tibiaapi/source/browse/branches/tibiaapi-current/trunk/tibiaapi/Util/Memory.cs

Sputnicker
02-05-2013, 01:34 PM
Ok, now i can compile and run, but it dont walk yet.


UInt32 adrXgo = 0x583EA0; // Endereço para ir para posição X
UInt32 adrYgo = 0x583E98; // Endereço para ir para posição Y
UInt32 adrZgo = 0x54C004; // Endereço para ir para posição Z
UInt32 adrGo = 0x54C058; // Endereço para ir para posição indicada
int gotox = 32933;
int gotoy = 32074;
int gotoz = 7;
int gogogo = 1;
WriteBytes(adrXgo, new byte[gotox], 5);
WriteBytes(adrYgo, new byte[gotoy], 5);
WriteBytes(adrZgo, new byte[gotoz], 1);
WriteBytes(adrGo, new byte[gogogo], 1);

Blequi
02-05-2013, 01:55 PM
sorry, but I cannot help you without basic C#. google about "how to create arrays c#".
msdn and google's references are great source.

Blaster_89
02-05-2013, 02:13 PM
Ok, now i can compile and run, but it dont walk yet.


UInt32 adrXgo = 0x583EA0; // Endereço para ir para posição X
UInt32 adrYgo = 0x583E98; // Endereço para ir para posição Y
UInt32 adrZgo = 0x54C004; // Endereço para ir para posição Z
UInt32 adrGo = 0x54C058; // Endereço para ir para posição indicada
int gotox = 32933;
int gotoy = 32074;
int gotoz = 7;
int gogogo = 1;
WriteBytes(adrXgo, new byte[gotox], 5);
WriteBytes(adrYgo, new byte[gotoy], 5);
WriteBytes(adrZgo, new byte[gotoz], 1);
WriteBytes(adrGo, new byte[gogogo], 1);


You're initializing empty byte arrays with the sizes specified in gotox/y/z.


WriteBytes(adrXgo, BitConverter.GetBytes(gotox), 2); // x and y positions in Tibia are 2 bytes long, z is 1 byte long

You should write wrappers for writing different value types to memory.

Sputnicker
02-05-2013, 02:41 PM
Sorry, my fault. I've done this way, and now the value is recorded into the adress.
Now I can write into the adress, but cant change the Go value.
The chat just go to the position when I manually walk, then the variable is changed by tibia.

So far: WriteBytes(adrGo + Base, BitConverter.GetBytes(gogogo), 1);
It is correct?

Blaster_89
02-05-2013, 03:25 PM
You're supposed to write the player's IsWalking to 1.

XtrmJash
02-05-2013, 03:51 PM
You're supposed to write the player's IsWalking to 1.

In case you didn't see he declared:
int gogogo = 1;

Then put:
So far: WriteBytes(adrGo + Base, BitConverter.GetBytes(gogogo), 1);

Doesn't this have to be a 4 byte write though? Don't know why I'm thinking that, so excuse me if I'm being an idiot.

Also @OP You should be able to get the length of your byte array.

BitConverter BConv = new BitConverter();

int WriteX = 123456;
int WriteY = 123456;
int WriteZ = 07;
Byte[] XByte = BConv.GetBytes(WriteX);
Byte[] YByte = BConv.GetBytes(WriteY);
Byte[] ZByte = BConv.GetBytes(WriteZ);

Byte[] GoByte = BConv.GetBytes(1);


Then:

WriteProcessMemory(XGoAdr + Base, XByte, XByte.Length);
WriteProcessMemory(YGoAdr + Base, YByte, YByte.Length);
WriteProcessMemory(ZGoAdr + Base, ZByte, ZByte.Length);
WriteProcessMemory(GoAdr + Base, GoByte, GoByte.Length);

Should work. Not tested, and not even typed into a syntax highlighter. Good luck!

Sputnicker
02-05-2013, 03:52 PM
Oh, I'll try that. What about the adrGo, whats the point of changing this value?

Sputnicker
02-05-2013, 04:10 PM
BitConverter BConv = new BitConverter();


Had error in this line:
Error 1 Cannot declare a variable of static type 'System.BitConverter'
Error 2 Cannot create an instance of the static class 'System.BitConverter'

Solved that this way:


int WriteX = 32933;
int WriteY = 32074;
int WriteZ = 7;
Byte[] XByte = BitConverter.GetBytes(WriteX);
Byte[] YByte = BitConverter.GetBytes(WriteY);
Byte[] ZByte = BitConverter.GetBytes(WriteZ);
Byte[] GoByte = BitConverter.GetBytes(1);
WriteBytes(adrXgo + Base, XByte, Convert.ToUInt32(XByte.Length));
WriteBytes(adrYgo + Base, YByte, Convert.ToUInt32(YByte.Length));
WriteBytes(adrZgo + Base, ZByte, Convert.ToUInt32(ZByte.Length));
WriteBytes(adrGo + Base, GoByte, Convert.ToUInt32(GoByte.Length));


All the variables are changing value, but the char just walk when I manually move with mouse clicks or keys.
It is required to change battlelist status to iswalking or adrGo to 1 is enough?

XtrmJash
02-06-2013, 07:22 AM
Had error in this line:
Error 1 Cannot declare a variable of static type 'System.BitConverter'
Error 2 Cannot create an instance of the static class 'System.BitConverter'

Solved that this way:


int WriteX = 32933;
int WriteY = 32074;
int WriteZ = 7;
Byte[] XByte = BitConverter.GetBytes(WriteX);
Byte[] YByte = BitConverter.GetBytes(WriteY);
Byte[] ZByte = BitConverter.GetBytes(WriteZ);
Byte[] GoByte = BitConverter.GetBytes(1);
WriteBytes(adrXgo + Base, XByte, Convert.ToUInt32(XByte.Length));
WriteBytes(adrYgo + Base, YByte, Convert.ToUInt32(YByte.Length));
WriteBytes(adrZgo + Base, ZByte, Convert.ToUInt32(ZByte.Length));
WriteBytes(adrGo + Base, GoByte, Convert.ToUInt32(GoByte.Length));


All the variables are changing value, but the char just walk when I manually move with mouse clicks or keys.
It is required to change battlelist status to iswalking or adrGo to 1 is enough?

I don't think IsWalking needs setting, since it is a property of creatures and not a function of the client. Not sure why it's not working though, perhaps Jo3bingham or DarkstaR are lurking somewhere?

Sputnicker
02-06-2013, 12:15 PM
I've tryed many ways, but the char just walks when I make manually walk.
I'm still trying to figure it out.

Updating:


UInt32 adrXgo = 0x583EA0; // Endereço para ir para posição X
UInt32 adrYgo = 0x583E98; // Endereço para ir para posição Y
UInt32 adrZgo = 0x54C004; // Endereço para ir para posição Z
UInt32 adrGo = 0x54C058; // Endereço para ir para posição indicada
private void walkto(int WriteX, int WriteY, int WriteZ)
{
Byte[] XByte = BitConverter.GetBytes(WriteX);
Byte[] YByte = BitConverter.GetBytes(WriteY);
Byte[] ZByte = BitConverter.GetBytes(WriteZ);
Byte[] GoByte = BitConverter.GetBytes(1);
Byte[] StopByte = BitConverter.GetBytes(0);
WriteBytes(adrXgo + Base, XByte, Convert.ToUInt32(XByte.Length));
WriteBytes(adrYgo + Base, YByte, Convert.ToUInt32(YByte.Length));
WriteBytes(adrZgo + Base, ZByte, Convert.ToUInt32(ZByte.Length));
WriteBytes(adrGo + Base, GoByte, Convert.ToUInt32(GoByte.Length));
}
unsafe private void timer1_Tick(object sender, EventArgs e)
{
walkto(32933, 32074, 7);
}

Stiju
02-06-2013, 01:14 PM
There's no static address to begin walking.
You must find your character in the battlelist, locate the isWalking variable and set it to true.

Sputnicker
02-06-2013, 01:46 PM
There's no static address to begin walking.
You must find your character in the battlelist, locate the isWalking variable and set it to true.

Thanks brow, just a question: what the adrGo adresses means?

Stiju
02-06-2013, 02:01 PM
I have no idea where you got it from so I can't really say what it is.

Sputnicker
02-06-2013, 02:21 PM
From Black'd site. http://www.blackdtools.com/forum/showthread.php?59833-9-81-Blackd-Tibia-addresses-9-81
adrXgo=&H983EA0
adrYgo=&H983E98
adrZgo=&H94C004
adrGo=&H94C058

XtrmJash
02-06-2013, 02:38 PM
From Black'd site. http://www.blackdtools.com/forum/showthread.php?59833-9-81-Blackd-Tibia-addresses-9-81
adrXgo=&H983EA0
adrYgo=&H983E98
adrZgo=&H94C004
adrGo=&H94C058

Does it work by setting the IsWalking property of your battle list entry? Did you test it yet? Try read AdrGo and see what the value stores under different circumstances, like do a long mapwalk and read while walking, see if it changes to 1, it might be that while you are walking this is a certain value or something.

Sputnicker
02-06-2013, 03:37 PM
I'll read about the battlelist structure. Havent seen it yet.
I'll try to find some tutorial or exemples.
Thanks guys

XtrmJash
02-06-2013, 07:34 PM
I'll read about the battlelist structure. Havent seen it yet.
I'll try to find some tutorial or exemples.
Thanks guys

You might find this (http://code.google.com/p/japi/source/browse/#svn%2Ftrunk%2FJAPI) useful, in addresses is all current addresses, objects contains the Object for BList (it's basically a creature structure, with hppc, name, cid, etc) and ReaderClass contains my method of reading the battle list. If you have any questions just ask :)

Sputnicker
02-07-2013, 12:21 PM
Well, I've tryed to understand, but right now its a little over my skills.
I'll read a lot and take my time, so I wont make stupid questions. ;)

Sputnicker
02-07-2013, 02:00 PM
ManintheCave, I tried with JAPI, but theres a thing.
When I read crit.Walking, it stay aways in 0 value, dont matter if I walk, mapclick or stay.
This variable shouldn't change when walking?

In this function the name is gathered ok, but the walking value is not.

Here is the image: https://www.box.com/s/ejd9wg8bgjzuo63zve6f



public string getMyName()
{
BList[] batt = new BList[BListAdresses.Max];
batt = BlGet(true);
foreach (BList crit in batt)
{
if (crit.Id == Cid())
{
label6.Text = Convert.ToString(crit.Walking);
return crit.Name;
}
}
return "";
}

XtrmJash
02-07-2013, 06:40 PM
ManintheCave, I tried with JAPI, but theres a thing.
When I read crit.Walking, it stay aways in 0 value, dont matter if I walk, mapclick or stay.
This variable shouldn't change when walking?

In this function the name is gathered ok, but the walking value is not.

Here is the image: https://www.box.com/s/ejd9wg8bgjzuo63zve6f



public string getMyName()
{
BList[] batt = new BList[BListAdresses.Max];
batt = BlGet(true);
foreach (BList crit in batt)
{
if (crit.Id == Cid())
{
label6.Text = Convert.ToString(crit.Walking);
return crit.Name;
}
}
return "";
}


That's because getMyName is only actually acquiring the name and CreatureID, then finding which creature shares a CID with your character as in Cid(). You want to be using BlGet, it returns an array of BList objects (each "BList" being 1 creature, probably a poor naming convention), you must then scan this to find your character, something like this:



UInt32 MyOffset;
Objects.Player p = GetPlayerInfo();

foreach (Objects.BList creature in Read.BlGet())
{
if (Cid() == creature.Cid)
{
MyOffset = BList.Adr;
}
}

Then you'll want to write to the address which is:


(UInt32)MyOffset * BListAdresses.Step + Util.Base + BListAddress.Start + BListAdresses.WalkingOffset;

Or something of that nature. It's a bit of a fuss at the minute, I may store each creatures "address" as a UInt32 in future, as it will make this kind of thing a bit easier.

Sputnicker
02-08-2013, 01:00 AM
Thanks ManintheCave... IT IS WORKING! \o/

I'll just improve the code and then I'll release here for future references.

Thank you all that have helped me.
You guys rule!

XtrmJash
02-08-2013, 07:24 AM
Thanks ManintheCave... IT IS WORKING! \o/

I'll just improve the code and then I'll release here for future references.

Thank you all that have helped me.
You guys rule!

No problem, have fun with it! Your next challenge will probably be to develop a working looter or targeting system I guess? :P That's always fun!

Sputnicker
02-08-2013, 02:39 PM
Actually, the next challenge is to understand JAPI sources ;)
I'm having some troubles when I try to call a function in another class.

Exemple:
Form1.cs

listBox1.Items.Add(Convert.ToString(ReaderClass.X( ) + ", " + ReaderClass.Y() + ", " + ReaderClass.Z()));

ReaderClass.cs


public int X()
{
return ReadInt32(Addresses.XPos + Util.Base);
}
public int Y()
{
return ReadInt32(Addresses.YPos + Util.Base);
}
public int Z()
{
return ReadInt32(Addresses.ZPos + Util.Base);
}


Error:
An object reference is required for the non-static field, method, or property 'SpotBOT.ReaderClass.X()'
An object reference is required for the non-static field, method, or property 'SpotBOT.ReaderClass.Y()'
An object reference is required for the non-static field, method, or property 'SpotBOT.ReaderClass.Z()'


The problem is solved if I make the function static. Like: static public int X()
Theres any way of doing it without changing the functions?

XtrmJash
02-08-2013, 10:08 PM
Actually, the next challenge is to understand JAPI sources ;)
I'm having some troubles when I try to call a function in another class.

Exemple:
Form1.cs

listBox1.Items.Add(Convert.ToString(ReaderClass.X( ) + ", " + ReaderClass.Y() + ", " + ReaderClass.Z()));

ReaderClass.cs


public int X()
{
return ReadInt32(Addresses.XPos + Util.Base);
}
public int Y()
{
return ReadInt32(Addresses.YPos + Util.Base);
}
public int Z()
{
return ReadInt32(Addresses.ZPos + Util.Base);
}


Error:
An object reference is required for the non-static field, method, or property 'SpotBOT.ReaderClass.X()'
An object reference is required for the non-static field, method, or property 'SpotBOT.ReaderClass.Y()'
An object reference is required for the non-static field, method, or property 'SpotBOT.ReaderClass.Z()'


The problem is solved if I make the function static. Like: static public int X()
Theres any way of doing it without changing the functions?

You get either of two options, make the function static as you said, or you can do what I do (and prefer, might I add, in case you ever want to MC using the same bot to control 2 clients), it would go like this:


ReaderClass read = new ReaderClass();

int xpos = read.X();
int ypos = read.Y();
int zpos = read.Z();

I prefer calling this way, though some would argue it is more complex, I think it's neater and more organised. It's entirely up to you, I don't think either method is correct as at the minute you're using the API internally, though if you were calling the functions using the API as a downloaded resource (just like downloading JAPI.dll and adding a reference) you'd need to declare a new instance of the class (e.g line 1 of above code).

I'll be doing a tutorial tomorrow which you might find extremely useful, on map reading. There is very little information on it other than some introduction to the file structure etc... I found it quite complex, but I have a general plan for how the tutorial will play out. It'll be a video tutorial with source code t'boot, so you can see better exactly what I'm doing and pick it apart.

Regnardgreeb
02-13-2013, 11:05 PM
Actually, it works just fine to use that static address. Not to mention it's a lot less complicated. However, it might be wise to get your hands on the property as well.