 |
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
KryziK Expert Cheater
Reputation: 3
Joined: 16 Aug 2009 Posts: 199
|
Posted: Sun Jan 16, 2011 6:59 pm Post subject: C# Trainer Tutorial (With Example) |
|
|
This code DOES work, but some of it is outdated/poorly written. I'm in the process of updating but it may never make it to the forums depending on how busy I stay. I'm quite new to C#, so I apologize for the inconvenience.
Hello!
I've recently started using C# for making trainers, and I thought I'd show others how to do it.
Before we begin, the memory functions that I am using, excluding:
Memory: ReadPointer(), WritePointer(), PID(), BaseAddressH(), BaseAddressD()
Addr: ToHex(), ToDec(), Make()
ARE NOT MINE. They were found HERE. In other words, I only wrote the funtions listed in bold, along with the code for the buttons. With that out of the way, let's begin!
Start a new WindowsFormsApplication. Name it whatever you'd like. I'm naming mine CET_Trainer, because we will be making a trainer for Cheat Engine's Tutorial-i386.exe (The new one).
Now, under the Solution Explorer, find Form1.cs. Rename it to 'TrainerForm.cs'.
This step is optional. I only changed it because I think Form1.cs is ugly and not very descriptive.
Next, go to your Form Builder, under properties, and change:
Name to 'hForm'
Text to '[Trainer] Cheat Engine Tutorial'
You can pick and Name and Text you want, but I recommend my suggestions so it's easier to follow the tutorial.
Note: You may have to adjust the size of the window a little bit so that the whole title is shown.
Now, create a button on your form, and change:
Name to 'hButton_Step2'
Text to 'Complete Step 2'
Again, you can change these to whatever you prefer.
Double-Click on your Button, and an Event will be created.
This event will be triggered when the button is clicked.
A code window should have opened up, and should look like this:
We will come back to this event later. First, we need to add our Memory Functions.
Add these to the top of the file, under the other using statements:
Code: | using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Globalization; |
These will allow us additional functionality such as getting a ProcessID from it's name.
Now, copy this code, and paste it under the Form Class, as shown:
Code: | class MemoryAPI
{
[Flags]
public enum ProcessAccessType
{
PROCESS_TERMINATE = (0x0001),
PROCESS_CREATE_THREAD = (0x0002),
PROCESS_SET_SESSIONID = (0x0004),
PROCESS_VM_OPERATION = (0x0008),
PROCESS_VM_READ = (0x0010),
PROCESS_VM_WRITE = (0x0020),
PROCESS_DUP_HANDLE = (0x0040),
PROCESS_CREATE_PROCESS = (0x0080),
PROCESS_SET_QUOTA = (0x0100),
PROCESS_SET_INFORMATION = (0x0200),
PROCESS_QUERY_INFORMATION = (0x0400)
}
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);
[DllImport("kernel32.dll")]
public static extern Int32 CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll")]
public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
public static extern Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesWritten);
}
public class Memory
{
public Memory()
{
}
public Process ReadProcess
{
get
{
return m_ReadProcess;
}
set
{
m_ReadProcess = value;
}
}
private Process m_ReadProcess = null;
private IntPtr m_hProcess = IntPtr.Zero;
public void Open()
{
MemoryAPI.ProcessAccessType access = MemoryAPI.ProcessAccessType.PROCESS_VM_READ
| MemoryAPI.ProcessAccessType.PROCESS_VM_WRITE
| MemoryAPI.ProcessAccessType.PROCESS_VM_OPERATION;
m_hProcess = MemoryAPI.OpenProcess((uint)access, 1, (uint)m_ReadProcess.Id);
}
public void CloseHandle()
{
int iRetValue;
iRetValue = MemoryAPI.CloseHandle(m_hProcess);
if (iRetValue == 0)
throw new Exception("CloseHandle Failed");
}
public byte[] Read(IntPtr MemoryAddress, uint bytesToRead, out int bytesRead)
{
byte[] buffer = new byte[bytesToRead];
IntPtr ptrBytesRead;
MemoryAPI.ReadProcessMemory(m_hProcess, MemoryAddress, buffer, bytesToRead, out ptrBytesRead);
bytesRead = ptrBytesRead.ToInt32();
return buffer;
}
public byte[] PointerRead(IntPtr MemoryAddress, uint bytesToRead, int[] Offset, out int bytesRead)
{
int iPointerCount = Offset.Length - 1;
IntPtr ptrBytesRead;
bytesRead = 0;
byte[] buffer = new byte[4]; //DWORD to hold an Address
int tempAddress = 0;
if (iPointerCount == 0)
{
MemoryAPI.ReadProcessMemory(m_hProcess, MemoryAddress, buffer, 4, out ptrBytesRead);
tempAddress = Addr.ToDec(Addr.Make(buffer)) + Offset[0]; //Final Address
buffer = new byte[bytesToRead];
MemoryAPI.ReadProcessMemory(m_hProcess, (IntPtr)tempAddress, buffer, bytesToRead, out ptrBytesRead);
bytesRead = ptrBytesRead.ToInt32();
return buffer;
}
for (int i = 0; i <= iPointerCount; i++)
{
if (i == iPointerCount)
{
MemoryAPI.ReadProcessMemory(m_hProcess, (IntPtr)tempAddress, buffer, 4, out ptrBytesRead);
tempAddress = Addr.ToDec(Addr.Make(buffer)) + Offset[i]; //Final Address
buffer = new byte[bytesToRead];
MemoryAPI.ReadProcessMemory(m_hProcess, (IntPtr)tempAddress, buffer, bytesToRead, out ptrBytesRead);
bytesRead = ptrBytesRead.ToInt32();
return buffer;
}
else if (i == 0)
{
MemoryAPI.ReadProcessMemory(m_hProcess, MemoryAddress, buffer, 4, out ptrBytesRead);
tempAddress = Addr.ToDec(Addr.Make(buffer)) + Offset[1];
}
else
{
MemoryAPI.ReadProcessMemory(m_hProcess, (IntPtr)tempAddress, buffer, 4, out ptrBytesRead);
tempAddress = Addr.ToDec(Addr.Make(buffer)) + Offset[i];
}
}
return buffer;
}
public void Write(IntPtr MemoryAddress, byte[] bytesToWrite, out int bytesWritten)
{
IntPtr ptrBytesWritten;
MemoryAPI.WriteProcessMemory(m_hProcess, MemoryAddress, bytesToWrite, (uint)bytesToWrite.Length, out ptrBytesWritten);
bytesWritten = ptrBytesWritten.ToInt32();
}
public string PointerWrite(IntPtr MemoryAddress, byte[] bytesToWrite, int[] Offset, out int bytesWritten)
{
int iPointerCount = Offset.Length - 1;
IntPtr ptrBytesWritten;
bytesWritten = 0;
byte[] buffer = new byte[4]; //DWORD to hold an Address
int tempAddress = 0;
if (iPointerCount == 0)
{
MemoryAPI.ReadProcessMemory(m_hProcess, MemoryAddress, buffer, 4, out ptrBytesWritten);
tempAddress = Addr.ToDec(Addr.Make(buffer)) + Offset[0]; //Final Address
MemoryAPI.WriteProcessMemory(m_hProcess, (IntPtr)tempAddress, bytesToWrite, (uint)bytesToWrite.Length, out ptrBytesWritten);
bytesWritten = ptrBytesWritten.ToInt32();
return Addr.ToHex(tempAddress);
}
for (int i = 0; i <= iPointerCount; i++)
{
if (i == iPointerCount)
{
MemoryAPI.ReadProcessMemory(m_hProcess, (IntPtr)tempAddress, buffer, 4, out ptrBytesWritten);
tempAddress = Addr.ToDec(Addr.Make(buffer)) + Offset[i]; //Final Address
MemoryAPI.WriteProcessMemory(m_hProcess, (IntPtr)tempAddress, bytesToWrite, (uint)bytesToWrite.Length, out ptrBytesWritten);
bytesWritten = ptrBytesWritten.ToInt32();
return Addr.ToHex(tempAddress);
}
else if (i == 0)
{
MemoryAPI.ReadProcessMemory(m_hProcess, MemoryAddress, buffer, 4, out ptrBytesWritten);
tempAddress = Addr.ToDec(Addr.Make(buffer)) + Offset[i];
}
else
{
MemoryAPI.ReadProcessMemory(m_hProcess, (IntPtr)tempAddress, buffer, 4, out ptrBytesWritten);
tempAddress = Addr.ToDec(Addr.Make(buffer)) + Offset[i];
}
}
return Addr.ToHex(tempAddress);
}
public int PID()
{
return m_ReadProcess.Id;
}
public string BaseAddressH()
{
return Addr.ToHex(m_ReadProcess.MainModule.BaseAddress.ToInt32());
}
public int BaseAddressD()
{
return m_ReadProcess.MainModule.BaseAddress.ToInt32();
}
}
public class Addr
{
public static string Make(byte[] buffer)
{
string sTemp = "";
for (int i = 0; i < buffer.Length; i++)
{
if (Convert.ToInt16(buffer[i]) < 10)
sTemp = "0" + ToHex(buffer[i]) + sTemp;
else
sTemp = ToHex(buffer[i]) + sTemp;
}
return sTemp;
}
public static string ToHex(int Decimal)
{
return Decimal.ToString("X"); //Convert Decimal to Hexadecimal
}
public static int ToDec(string Hex)
{
return int.Parse(Hex, NumberStyles.HexNumber); //Convert Hexadecimal to Decimal
}
} |
Your code should now look like this (when the classes are minimized):
Alright, now that our memory functions are added to our project, it's time to make our button do something!
Add this code in the Form Class:
Code: | Memory oMemory = new Memory(); |
Add this code to the Event we described earlier:
Code: | Process[] aProcesses = Process.GetProcessesByName("Tutorial-i386"); //Find Tutorial-i386.exe
if (aProcesses.Length != 0) //If the process exists
{
oMemory.ReadProcess = aProcesses[0]; //Sets the Process to Read/Write From/To
oMemory.Open(); //Open Process
int iStep2_Address = Addr.ToDec("57C310"); //The static address of the pointer (#1)
int[] iStep2_Offsets = { 0x98, 0x4, 0x288, 0x24, 0x458 }; //Offsets from bottom to top (#2-#6)
int bytesWritten; //Holds how many bytes were written by PointerWrite
int iValue_To_Write = 1000; //Value that we want to write (Step2 requires that you change the value to 1000)
byte[] bValue_To_Write = BitConverter.GetBytes(iValue_To_Write); //Turns 1000 into bytes
string sWritten_Address = oMemory.PointerWrite((IntPtr)iStep2_Address, //PointerWrite starting with our Step2 Address
bValue_To_Write, //The value to write (as bytes)
iStep2_Offsets, //Our offsets
out bytesWritten); //Stores the # of Written Bytes
if (bytesWritten == bValue_To_Write.Length) //If writing was successful
MessageBox.Show("Wrote " + iValue_To_Write.ToString() + " to " + sWritten_Address + "!"); //Notify the user of success
else
MessageBox.Show("There was an error writing " + iValue_To_Write.ToString() + " to " + sWritten_Address + "."); //Notify the user of failure
oMemory.CloseHandle(); //Close Memory Handle
} |
If you found the pointer yourself, you will most likely have a different number of offsets as me, so change them accordingly. Otherwise, mine should work for you.
Unless I'm forgetting anything (which we will find out soon enough), Run your project, open Tutorial-i386.exe, and press Complete Step 2.
Now go to the Tutorial and see if Next is Enabled!
If not, make sure your Address and Offsets are correct. Check to see if the Address that the MessageBox shows is the same as in your Cheat Table ("P->XXXXXXXX")
This is how you determine iStep2_Address and iStep2_Offsets:
Note: These numbers (#1-#6) are referred to in the comments. #1 DOES NOT mean the first offset.
Now wait! What if you want to write somethine like a Float? Here's how:
Simply change:
Code: | byte[] bValue_To_Write = BitConverter.GetBytes(iValue_To_Write); //Turns 1000 into bytes |
To:
Code: | byte[] bValue_To_Write = BitConverter.GetBytes((float)iValue_To_Write); //Turns 1000 into bytes |
Here is a list of types. I can only confirm the usage of (float) and (double) as of now.
That concludes my tutorial! Please let me know if I forgot something, or if something is incorrect.
Also, feel free to ask questions, and I do take requests on trainers and possibly tutorials. It all depends!
Here is the whole project. It has a few more steps done so you can look at them!
Source Code - Steps 1,2,3,4,5,6,8
Last edited by KryziK on Wed Jan 26, 2011 7:58 pm; edited 1 time in total |
|
Back to top |
|
 |
AhMunRa Grandmaster Cheater Supreme
Reputation: 27
Joined: 06 Aug 2010 Posts: 1117
|
Posted: Mon Jan 17, 2011 9:15 am Post subject: |
|
|
Excellent, as a C# user, this will come in very handy. _________________
<Wiccaan> Bah that was supposed to say 'not saying its dead' lol. Fixing >.> |
|
Back to top |
|
 |
KryziK Expert Cheater
Reputation: 3
Joined: 16 Aug 2009 Posts: 199
|
Posted: Mon Jan 17, 2011 10:54 am Post subject: |
|
|
Hopefully I was clear enough for people to be able to form it to their needs. I did not review static addresses without pointers, but those should be easy enough to figure out, as the functions are there. |
|
Back to top |
|
 |
ej52 Cheater
Reputation: 0
Joined: 29 Mar 2011 Posts: 39 Location: Mother City
|
Posted: Wed Mar 30, 2011 3:01 pm Post subject: |
|
|
@darkjohn20 thx for this useful info
I used this code as a base 4 my 1st trainer yesterday and it works great.
Had sum trouble figuring out how 2 dynamically create the byte arrays as
there does not seem 2 be alot of support 4 C# when it comes 2 ASM ...
but with abit of patience and alot of searching i managed 2 code a some
wat limited ASM class that genarates the byte arrays 4 simple instructions
Anyway thx again
Ej52 |
|
Back to top |
|
 |
GH*master Expert Cheater
Reputation: 8
Joined: 10 Jan 2008 Posts: 159
|
Posted: Wed Mar 30, 2011 4:14 pm Post subject: |
|
|
darkjohn20, WinAPI unmanaged code must be written in C++ language in the module "... .dll" as the exported functions for managed code. Your style of programming in C # is a bad ... |
|
Back to top |
|
 |
atom0s Moderator
Reputation: 204
Joined: 25 Jan 2006 Posts: 8579 Location: 127.0.0.1
|
Posted: Thu Mar 31, 2011 7:02 am Post subject: |
|
|
GH*master wrote: | darkjohn20, WinAPI unmanaged code must be written in C++ language in the module "... .dll" as the exported functions for managed code. Your style of programming in C # is a bad ... |
Uh no? You don't have to import API through DLLs. You are just creating another layer of unneeded bullshit rather then just using DllImport, which is built into the language for a reason; using API.
The wrappers he made around the imported API could be written better, but none of this needs to be in a DLL, this isn't bad style its following the language standards. _________________
- Retired. |
|
Back to top |
|
 |
frank_mascarado How do I cheat?
Reputation: 0
Joined: 03 Jun 2007 Posts: 5
|
Posted: Thu Mar 31, 2011 1:15 pm Post subject: |
|
|
even though the pictures do not appear is a good tutorial for beginners:) _________________
3haat eng1ne 6.0 Rev 1725
img96.imageshack.us/img96/6062/asdryz.jpg |
|
Back to top |
|
 |
ej52 Cheater
Reputation: 0
Joined: 29 Mar 2011 Posts: 39 Location: Mother City
|
Posted: Thu Mar 31, 2011 1:26 pm Post subject: |
|
|
GH*master wrote: | WinAPI unmanaged code must be written in C++ language in the module |
Not true, as Wiccaan said
frank_mascarado wrote: | even though the pictures do not appear is a good tutorial for beginners:) |
All the images show for me ... _________________
Hitler dNt HiDe WaT mOtHa NaTurE pRoViDe ...  |
|
Back to top |
|
 |
KryziK Expert Cheater
Reputation: 3
Joined: 16 Aug 2009 Posts: 199
|
Posted: Thu Mar 31, 2011 2:53 pm Post subject: |
|
|
Here is the most recent version of my C# Memory Stuff. I think it is written quite a bit better. It does make a DLL, however the .cs file can be put straight into a project so that a DLL is not required. |
|
Back to top |
|
 |
GH*master Expert Cheater
Reputation: 8
Joined: 10 Jan 2008 Posts: 159
|
Posted: Fri Apr 01, 2011 7:27 am Post subject: |
|
|
ej52 wrote: | GH*master wrote: | WinAPI unmanaged code must be written in C++ language in the module |
Not true, as Wiccaan said
|
Maybe YOU or others did not understand me.
Maybe others have little experience of programming and code injection in games.
Think about "why Cheat Engine has a "dll injection "?! "
How can this be attributed to the managed and unmanaged code?
What might be useful managed code? What might be useful unmanaged code?
Think about it. The answer to these questions lies in the many features. |
|
Back to top |
|
 |
shadi Newbie cheater
Reputation: 0
Joined: 21 Apr 2011 Posts: 11
|
Posted: Thu Apr 21, 2011 10:58 am Post subject: |
|
|
thanks but the photo didnt show |
|
Back to top |
|
 |
atom0s Moderator
Reputation: 204
Joined: 25 Jan 2006 Posts: 8579 Location: 127.0.0.1
|
|
Back to top |
|
 |
Uber How do I cheat?
Reputation: 0
Joined: 15 Dec 2010 Posts: 4 Location: Core
|
|
Back to top |
|
 |
Vulcanraven Newbie cheater
Reputation: 0
Joined: 17 Feb 2008 Posts: 19 Location: Germany
|
|
Back to top |
|
 |
iMockBa How do I cheat?
Reputation: 0
Joined: 01 Sep 2011 Posts: 3
|
Posted: Thu Sep 01, 2011 6:00 am Post subject: |
|
|
Hi.. i want ask how can i read memory by using this script .
i tryed it for writing values & its work perfectly ...but as new on c# i cant find out how to tranceform that script for reading memory .
and other litl question .. in section
int iValue_To_Write = (1000); //Value that we want to write (Step2 requires that you change the value to 1000)
walue to write is inside of script ....& i would like to make that posible to write that value by user inside of TextBox ..... so how can i tranceform String on Int ? if change the cod on
int iValue_To_Write = (TextBox.Text);
i m getting error .
Previously Thanks for any help. |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|