Erchima Gaming Forums

Hack the game and enjoy playing it!


You are not connected. Please login or register


C# Trainer Tutorial (With Example)  

 

#1Almaftuchin

C# Trainer Tutorial (With Example) Empty6th April 2014, 6:31 am

Almaftuchin

Administrator
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.

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).

C# Trainer Tutorial (With Example) Step1by

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.
C# Trainer Tutorial (With Example) Step2
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. 

C# Trainer Tutorial (With Example) Step3e

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.
C# Trainer Tutorial (With Example) Step4b
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:
C# Trainer Tutorial (With Example) Step5ol
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;

C# Trainer Tutorial (With Example) Step6s
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 
   } 
}

C# Trainer Tutorial (With Example) Step7w

Your code should now look like this (when the classes are minimized): 

C# Trainer Tutorial (With Example) Step8

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();

C# Trainer Tutorial (With Example) Step85
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 
}

C# Trainer Tutorial (With Example) Step9x
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:
C# Trainer Tutorial (With Example) Step10d
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

Change 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 Cuup|ErcHimA| on 28th May 2014, 9:58 am; edited 1 time in total

#2hacklol

C# Trainer Tutorial (With Example) Empty6th April 2014, 5:55 pm

hacklol

Newbie
thank u bro

View previous topic View next topic Back to top  Message [Page 1 of 1]

Permissions in this forum:
You cannot reply to topics in this forum