Using game structs in C#.

Posts 1–12 of 12 · Page 1 of 1
Using game structs in C#.
Structs are a huge part of both external and internal hacks. However, many people new to hacking are confused by what they are, and how to use them. In this tutorial, I will show how to read and use structs in noob-friendly C# (Go on @Horror ;p).

Structs (or structures) are groups of variables of a fixed size. This means a series of them may be read from memory easily. For my example, I will be using the Client_t struct for MW3 1.9.433 (thanks to @Jorndel for posting):

Code:
typedef struct
{
	int Valid;                                       //0x0 (0xAD28F8)
	char _0x0004[0x8];                               //0x4
	char Name[16];                                   //0xC (0xAD2904)
	int Team;                                        //0x1C (0xAD2914)
	char _0x0020[0x4];                               //0x20
	int Rank;                                        //0x24 (0xAD291C)
	char _0x0028[0x10];                              //0x28
	int Perk;                                        //0x38 (0xAD2930)
	char _0x003C[0x8];                               //0x3C
	int Score;                                       //0x44 (0xAD293C)
	char _0x0048[0x458];                             //0x48
	int Attacking;                                   //0x4A0 (0xAD2D98)
	char _0x04A4[0x4];                               //0x4A4
	int Zooming;                                     //0x4A8 (0xAD2DA0)
	char _0x04AC[0xB8];                              //0x4AC
}client_t; //[Addr: 0xAD28F8] [Size: 0x564]
First off, we'll create a C# Class:

Code:
class Client_t
{
	public int valid;
	public string name;
	public int team;
	public int rank;
	public int perk;
	public int score;
	public int attacking;
	public int zooming;
}
Next, we create a function to read the class from game memory. The numbers on the right of the struct come into play here, as each one represents the variables' offset from the start of the struct. This is what I came up with (using Jorndel's trainer class as a base):

Code:
public static Client_t ReadClient(int Address)
{
	int A = Address;
	Client_t ret = new Client_t();
        	
	ret.valid = ReadInteger(A);
	ret.name = ReadString(A + 0xC, 15);
	ret.team = ReadInteger(A + 0x1C);
	ret.rank = ReadInteger(A + 0x24);
	ret.perk = ReadInteger(A + 0x38);
	ret.score = ReadInteger(A + 0x44);
	ret.attacking = ReadInteger(A + 0x4A0);
	ret.zooming = ReadInteger(A + 0x4A8);
        	
	return ret;
}
Here, the base Address is 0xAD28F8, and the Size is 0x564. Since we know there are 18 clients max in MW3, we can create this function:

Code:
Client_t[] clients = new Client_t[18];
int a = 0xAD28F8;
for (int i = 0; i < clients.Length; i++) {
	clients[i] = ReadClient(a);
	a += 0x564;
}
And you're done. Leave any questions down in the comments with a mention, and I'll answer as many as I can. Happy fragging!
@rawr im a tiger
Started by basicly copying and pasting to try and understand it ... I get knocked off right away D:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MW3Kill
{
    class Client_t
    {
        public int valid;
        public string name;
        public int team;
        public int rank;
        public int perk;
        public int score;
        public int attacking;
        public int zooming;
    }
    public static Client_t ReadClient(int Address)
    {
	int A = Address;
	Client_t ret = new Client_t();
        	
	ret.valid = ReadInteger(A);
	ret.name = ReadString(A + 0xC, 15);
	ret.team = ReadInteger(A + 0x1C);
	ret.rank = ReadInteger(A + 0x24);
	ret.perk = ReadInteger(A + 0x38);
	ret.score = ReadInteger(A + 0x44);
	ret.attacking = ReadInteger(A + 0x4A0);
	ret.zooming = ReadInteger(A + 0x4A8);
        	
	return ret;
    }
    Client_t[] clients = new Client_t[18];
    int a = 0xAD28F8;
    for (int i = 0; i < clients.Length; i++) {
	clients[i] = ReadClient(a);
	a += 0x564;
    }
}
Every Client_t is marked as an error ... Error 1 Expected class, delegate, enum, interface, or struct.
While Client_t is my class ...
Quote Originally Posted by Horror View Post
@rawr im a tiger
Started by basicly copying and pasting to try and understand it ... I get knocked off right away D:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MW3Kill
{
    class Client_t
    {
        public int valid;
        public string name;
        public int team;
        public int rank;
        public int perk;
        public int score;
        public int attacking;
        public int zooming;
    }
    public static Client_t ReadClient(int Address)
    {
	int A = Address;
	Client_t ret = new Client_t();
        	
	ret.valid = ReadInteger(A);
	ret.name = ReadString(A + 0xC, 15);
	ret.team = ReadInteger(A + 0x1C);
	ret.rank = ReadInteger(A + 0x24);
	ret.perk = ReadInteger(A + 0x38);
	ret.score = ReadInteger(A + 0x44);
	ret.attacking = ReadInteger(A + 0x4A0);
	ret.zooming = ReadInteger(A + 0x4A8);
        	
	return ret;
    }
    Client_t[] clients = new Client_t[18];
    int a = 0xAD28F8;
    for (int i = 0; i < clients.Length; i++) {
	clients[i] = ReadClient(a);
	a += 0x564;
    }
}
Every Client_t is marked as an error ... Error 1 Expected class, delegate, enum, interface, or struct.
While Client_t is my class ...
Firstly, put the function inside a class And make sure the Client_t[] clients = new Client_t[18]; section is inside a function.
@rawr im a tiger
Im so sorry im so nooby
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace MW3Kill
{
    class Client_t
    {
        public int valid;
        public string name;
        public int team;
        public int rank;
        public int perk;
        public int score;
        public int attacking;
        public int zooming;
        #region Basic Stuff
        [DllImport("kernel32.dll")]
        private static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesWritten);
        [DllImport("kernel32.dll")]
        private static extern Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesWritten);
        IntPtr pHandel;
        public bool Process_Handle(string ProcessName)
        {
            try
            {
                Process[] ProcList = Process.GetProcessesByName(ProcessName);
                if (ProcList.Length == 0)
                    return false;
                else
                {
                    pHandel = ProcList[0].Handle;
                    return true;
                }
            }
            catch (Exception ex)
            { Console.Beep(); Console.WriteLine("Process_Handle - " + ex.Message); return false; }
        }
        private byte[] Read(int Address, int Length)
        {
            byte[] Buffer = new byte[Length];
            IntPtr Zero = IntPtr.Zero;
            ReadProcessMemory(pHandel, (IntPtr)Address, Buffer, (UInt32)Buffer.Length, out Zero);
            return Buffer;
        }
        private void Write(int Address, int Value)
        {
            byte[] Buffer = BitConverter.GetBytes(Value);
            IntPtr Zero = IntPtr.Zero;
            WriteProcessMemory(pHandel, (IntPtr)Address, Buffer, (UInt32)Buffer.Length, out Zero);
        }
        #endregion
        #region Write Functions (Integer & String)
        public void WriteInteger(int Address, int Value)
        {
            Write(Address, Value);
        }
        public void WriteString(int Address, string Text)
        {
            byte[] Buffer = new ASCIIEncoding().GetBytes(Text);
            IntPtr Zero = IntPtr.Zero;
            WriteProcessMemory(pHandel, (IntPtr)Address, Buffer, (UInt32)Buffer.Length, out Zero);
        }
        public void WriteBytes(int Address, byte[] Bytes)
        {
            IntPtr Zero = IntPtr.Zero;
            WriteProcessMemory(pHandel, (IntPtr)Address, Bytes, (uint)Bytes.Length, out Zero);
        }
        public void WriteNOP(int Address)
        {
            byte[] Buffer = new byte[] { 0x90, 0x90, 0x90, 0x90, 0x90 };
            IntPtr Zero = IntPtr.Zero;
            WriteProcessMemory(pHandel, (IntPtr)Address, Buffer, (UInt32)Buffer.Length, out Zero);
        }


        #endregion
        #region Read Functions (Integer & String)
        public int ReadInteger(int Address, int Length = 4)
        {
            return BitConverter.ToInt32(Read(Address, Length), 0);
        }
        public string ReadString(int Address, int Length = 4)
        {
            return new ASCIIEncoding().GetString(Read(Address, Length));
        }
        public byte[] ReadBytes(int Address, int Length)
        {
            return Read(Address, Length);
        }
        #endregion
        public static Client_t ReadClient(int Address)
        {
            int A = Address;
            Client_t ret = new Client_t();

            ret.valid = ReadInteger(A);
            ret.name = ReadString(A + 0xC, 15);
            ret.team = ReadInteger(A + 0x1C);
            ret.rank = ReadInteger(A + 0x24);
            ret.perk = ReadInteger(A + 0x38);
            ret.score = ReadInteger(A + 0x44);
            ret.attacking = ReadInteger(A + 0x4A0);
            ret.zooming = ReadInteger(A + 0x4A8);
            Client_t[] clients = new Client_t[18];
            int a = 0xAD28F8;
            for (int i = 0; i < clients.Length; i++)
            {
                clients[i] = ReadClient(a);
                a += 0x564;
            }
            return ret;
        }
        
    }
    
}
So basicly, i replaced them to get the error of Client_t gone ... New error pops up : Error 1 An object reference is required for the non-static field, method, or property 'MW3Kill.Client_t.ReadInteger(int, int)'. It points at -> ReadString(A + 0xC, 15); And everything with ReadString in it
Quote Originally Posted by Horror View Post
@rawr im a tiger
Im so sorry im so nooby
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace MW3Kill
{
    class Client_t
    {
        public int valid;
        public string name;
        public int team;
        public int rank;
        public int perk;
        public int score;
        public int attacking;
        public int zooming;
        #region Basic Stuff
        [DllImport("kernel32.dll")]
        private static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesWritten);
        [DllImport("kernel32.dll")]
        private static extern Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesWritten);
        IntPtr pHandel;
        public bool Process_Handle(string ProcessName)
        {
            try
            {
                Process[] ProcList = Process.GetProcessesByName(ProcessName);
                if (ProcList.Length == 0)
                    return false;
                else
                {
                    pHandel = ProcList[0].Handle;
                    return true;
                }
            }
            catch (Exception ex)
            { Console.Beep(); Console.WriteLine("Process_Handle - " + ex.Message); return false; }
        }
        private byte[] Read(int Address, int Length)
        {
            byte[] Buffer = new byte[Length];
            IntPtr Zero = IntPtr.Zero;
            ReadProcessMemory(pHandel, (IntPtr)Address, Buffer, (UInt32)Buffer.Length, out Zero);
            return Buffer;
        }
        private void Write(int Address, int Value)
        {
            byte[] Buffer = BitConverter.GetBytes(Value);
            IntPtr Zero = IntPtr.Zero;
            WriteProcessMemory(pHandel, (IntPtr)Address, Buffer, (UInt32)Buffer.Length, out Zero);
        }
        #endregion
        #region Write Functions (Integer & String)
        public void WriteInteger(int Address, int Value)
        {
            Write(Address, Value);
        }
        public void WriteString(int Address, string Text)
        {
            byte[] Buffer = new ASCIIEncoding().GetBytes(Text);
            IntPtr Zero = IntPtr.Zero;
            WriteProcessMemory(pHandel, (IntPtr)Address, Buffer, (UInt32)Buffer.Length, out Zero);
        }
        public void WriteBytes(int Address, byte[] Bytes)
        {
            IntPtr Zero = IntPtr.Zero;
            WriteProcessMemory(pHandel, (IntPtr)Address, Bytes, (uint)Bytes.Length, out Zero);
        }
        public void WriteNOP(int Address)
        {
            byte[] Buffer = new byte[] { 0x90, 0x90, 0x90, 0x90, 0x90 };
            IntPtr Zero = IntPtr.Zero;
            WriteProcessMemory(pHandel, (IntPtr)Address, Buffer, (UInt32)Buffer.Length, out Zero);
        }


        #endregion
        #region Read Functions (Integer & String)
        public int ReadInteger(int Address, int Length = 4)
        {
            return BitConverter.ToInt32(Read(Address, Length), 0);
        }
        public string ReadString(int Address, int Length = 4)
        {
            return new ASCIIEncoding().GetString(Read(Address, Length));
        }
        public byte[] ReadBytes(int Address, int Length)
        {
            return Read(Address, Length);
        }
        #endregion
        public static Client_t ReadClient(int Address)
        {
            int A = Address;
            Client_t ret = new Client_t();

            ret.valid = ReadInteger(A);
            ret.name = ReadString(A + 0xC, 15);
            ret.team = ReadInteger(A + 0x1C);
            ret.rank = ReadInteger(A + 0x24);
            ret.perk = ReadInteger(A + 0x38);
            ret.score = ReadInteger(A + 0x44);
            ret.attacking = ReadInteger(A + 0x4A0);
            ret.zooming = ReadInteger(A + 0x4A8);
            Client_t[] clients = new Client_t[18];
            int a = 0xAD28F8;
            for (int i = 0; i < clients.Length; i++)
            {
                clients[i] = ReadClient(a);
                a += 0x564;
            }
            return ret;
        }
        
    }
    
}
So basicly, i replaced them to get the error of Client_t gone ... New error pops up : Error 1 An object reference is required for the non-static field, method, or property 'MW3Kill.Client_t.ReadInteger(int, int)'. It points at -> ReadString(A + 0xC, 15); And everything with ReadString in it
Make the functions static then?
Quote Originally Posted by rawr im a tiger View Post
Make the functions static then?
I feel so bad Idk how to do that ...
Quote Originally Posted by rawr im a tiger View Post
public string ReadString(int Address, int Length = 4)
{
return new ASCIIEncoding().GetString(Read(Address, Length));
}
replace public by static isaakske...
@everyone, sorry if it's wrong, i'm also n00b xD
First of all, the way you've write the struct its no managed code, i guess (I'm a kinda noob at C# as well), here's how they should look like:
Code:
 [StructLayout(LayoutKind.Explicit)]
        struct ClientT
        {
            [FieldOffset(0x0), MarshalAs(UnmanagedType.Bool)]
            public bool Valid;
            [FieldOffset(0xC), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string Name;
            [FieldOffset(0x1C)]
            public Int32 Team;
            [FieldOffset(0x24)]
            public Int32 Rank;
            [FieldOffset(0x38)]
            public Int32 Perk;
            [FieldOffset(0x44)]
            public Int32 Score;
            [FieldOffset(0x4A0), MarshalAs(UnmanagedType.Bool)]
            public bool Attacking;
            [FieldOffset(0x4A8), MarshalAs(UnmanagedType.Bool)]
            public bool Zooming;
        }
Secondly, this way to read the struct is the really really bad.. I mean, if the struct has, let's say 20 fields to be read... you gonna have to write 20 lines of code when you can "easily" do it on 3:
Code:
private const int MAXPLAYERS = 18;
ClientT[] Client;
unsafe void ReadGame() {
     while (true) { //Call it on another thread OFC...
           fixed (byte* pBuffer = ReadBytes(OFFS_Client, sizeOfClient * MAXPLAYERS)) {
                 for (int i = 0; i < MAXPLAYERS; i++) {
                       Client[i] = *(ClientT*) (pBuffer + sizeOfClient * i);
                 }
           }
     }
}
And the ReadBytes method:
Code:
private byte[] ReadBytes(int Adress, int Size) {
            byte[] read = new byte[Size];
            int bytesRead;
            ReadProcessMemory(MW3Process, (IntPtr) Adress, read, Size, out bytesRead);
            return read;
        }
BTW, this is from and old External Radar that I was making... Now feel free to knock you head on the wall trying to understand... (I did that)

EDIT: Here's the source of the radar with all structs and reading methods on C#. The radar IS REALLY BUGGED, that's why I gave up on it... As I said I'm not good with C# as well

It's just source code.. but here a virus scan anyway
https://www.virustotal.com/file/28c2...is/1344401195/
Radar_mpgh.net.rar17 KB · 39 downloads Clean
Quote Originally Posted by MarkHC View Post

BTW, this is from and old External Radar that I was making... Now feel free to knock you head on the wall trying to understand... (I did that)

EDIT: Here's the source of the radar with all structs and reading methods on C#. The radar IS REALLY BUGGED, that's why I gave up on it... As I said I'm not good with C# as well

It's just source code.. but here a virus scan anyway
https://www.virustotal.com/file/28c2...is/1344401195/
That's how I do it in C++, but this method is much easier for C#. Also, >unmanaged C#, ishygddt.
Approved
Quote Originally Posted by rawr im a tiger View Post
First off, we'll create a C# Class:

Code:
class Client_t
{
public int valid;
public string name;
public int team;
public int rank;
public int perk;
public int score;
public int attacking;
public int zooming;
}
Next, we create a function to read the class from game memory. The numbers on the right of the struct come into play here, as each one represents the variables' offset from the start of the struct. This is what I came up with (using Jorndel's trainer class as a base):

Code:
public static Client_t ReadClient(int Address)
{
int A = Address;
Client_t ret = new Client_t();

ret.valid = ReadInteger(A);
ret.name = ReadString(A + 0xC, 15);
ret.team = ReadInteger(A + 0x1C);
ret.rank = ReadInteger(A + 0x24);
ret.perk = ReadInteger(A + 0x38);
ret.score = ReadInteger(A + 0x44);
ret.attacking = ReadInteger(A + 0x4A0);
ret.zooming = ReadInteger(A + 0x4A8);

return ret;
}
Here, the base Address is 0xAD28F8, and the Size is 0x564. Since we know there are 18 clients max in MW3, we can create this function:
why not just create the struct as it is with correct size and stuff, rather than making a custom one and reading values to it separately.
Also i'm assuming ReadInteger() uses ReadProcessMemory(), calling RPM so many times is gona make your shizz run slower.
Create the struct as its supposed to be with correct size and stuff and not a custom one. Then before you use the struct for your aimbot or esp or whatever, read the whole client struct in game memory to your allocated 18 client structs, with size of 0x564 * 18.

Also why not just do something like this .. saves the need to input address each time
Code:
public static Client_t ReadClient(int clientnum)
{
	int A = 0xAD28F8 + ( 0x564 * clientnum );
	Client_t ret = new Client_t();
instead of
public static Client_t ReadClient(int Address)
{
int A = Address;
Client_t ret = new Client_t();
I have never coded in C#, but i smell memory leaks ... not sure, why dont you do something like this?
Code:
public static void ReadClient(int clientnum, Client_t* client)
{
	int A = 0xAD28F8 + ( 0x564 * clientnum );
        	
        client->valid = ReadInteger(A);
and so on... because you've already allocated memory for those 18 clients here ... ?
Code:
Client_t[] clients = new Client_t[18];
int a = 0xAD28F8;
for (int i = 0; i < clients.Length; i++) {
	clients[i] = ReadClient(a);
	a += 0x564;
}
and just pass the pointer of client and modify its values in the func ...
but then again ive never coded in C# and not even sure new Client_t(); means as it would in C++.
Quote Originally Posted by intervention61 View Post
why not just create the struct as it is with correct size and stuff, rather than making a custom one and reading values to it separately.
Also i'm assuming ReadInteger() uses ReadProcessMemory(), calling RPM so many times is gona make your shizz run slower.
Create the struct as its supposed to be with correct size and stuff and not a custom one. Then before you use the struct for your aimbot or esp or whatever, read the whole client struct in game memory to your allocated 18 client structs, with size of 0x564 * 18.

Also why not just do something like this .. saves the need to input address each time
Code:
public static Client_t ReadClient(int clientnum)
{
	int A = 0xAD28F8 + ( 0x564 * clientnum );
	Client_t ret = new Client_t();
instead of


I have never coded in C#, but i smell memory leaks ... not sure, why dont you do something like this?
Code:
public static void ReadClient(int clientnum, Client_t* client)
{
	int A = 0xAD28F8 + ( 0x564 * clientnum );
        	
        client->valid = ReadInteger(A);
and so on... because you've already allocated memory for those 18 clients here ... ?
Code:
Client_t[] clients = new Client_t[18];
int a = 0xAD28F8;
for (int i = 0; i < clients.Length; i++) {
	clients[i] = ReadClient(a);
	a += 0x564;
}
and just pass the pointer of client and modify its values in the func ...
but then again ive never coded in C# and not even sure new Client_t(); means as it would in C++.
If I was to do this tut again, I would use just 1 RPM reading a byte array, and then convert it to client_t. But creating a true struct in C# is very difficult, hence the long explanation.
Posts 1–12 of 12 · Page 1 of 1

Post a Reply

Similar Threads

Tags for this Thread

None

Talk with us