Statements
I'd like to state that
I'm not a expert, indeed I'm yet a
novice.
This thread is going to be based alot on Zat threads.
Requirements
*
1. C#-knowledge.
*
2. Brain.
Introduction
Now we are going to talk about RPM and WPM (Read Process Memory and Write Process Memory), which are the hearth and soul of "hacks", and what as the name suggests what it does is Read/Write a/into address from a certain process returning a byte array. If there's something you don't understand about this part you should probably learn more about
C# and how the computer store things into memory.
RPM
RPM or Read Process Memory is the method through which we will use to read a address from the process, it's a part of the WinAPI and its syntax is :
Code:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory(
* *IntPtr hProcess,
* *IntPtr lpBaseAddress,
* *[Out] byte[] lpBuffer,
* *int dwSize,
* *out IntPtr lpNumberOfBytesRead);
Breaking down the arguments :
hProcess : A
handle to the process.
lpBaseAddress : The desired
address to read from.
lbBuffer : The buffer the read data is stored in.
dwSize : The size of the buffer (count of bytes to read).
lpNumberOfBytesRead :Holds the number of bytes read after calling this function.
But wait, how do I call it ? Well, it's pretty simple
1. Create a byte-array of 4 bytes dataBuffer and pointer bytesRead.
2. Call your method using your array and pointer (and handle and address ofc)!
3. Error handling: What do you do if you read no data or less than intended?
4. Convert the content of the buffer to your data-type.
Don't get it yet ? Here, take an example :
Code:
int Read(IntPtr handle, int address)
{
//1. Prepare buffer and pointer
byte[] dataBuffer = new byte[4];
IntPtr bytesRead = IntPtr.Zero;
//2. Read
ReadProcessMemory(handle, (IntPtr)address, dataBuffer, dataBuffer.Length, out bytesRead);
//3. Error handling
if(bytesRead == IntPtr.Zero)
{
Console.WriteLine("We didn't read anything!");
return 0;
}
if(bytesRead.ToInt32() < dataBuffer.Length)
{
Console.WriteLine("We read {0} out of {1} bytes!", bytesRead.ToInt32(), dataBuffer.Length.ToString());
return 0;
}
//4. Convert the content of your buffer to int
return BitConverter.ToInt32(dataBuffer);
}
At some point in your future you're going to be needing to convert the byte array into a structure, well for that you are going to need this thread :
http://bi t.l y/1OwS1SQ (Remove the spaces)
WPM
WPM or Write Process Memory is the method through which we will use to write into a address from the process, it's a part of the WinAPI and its syntax is :
Code:
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(
* *IntPtr hProcess,
* *IntPtr lpBaseAddress,
* *byte[] lpBuffer,
* *int dwSize,
* *out IntPtr lpNumberOfBytesWritten);
Well, if you read the RPM section, you know what most of those mean, being :
hProcess being A handle that leads to the process.
lpBaseAddress being The desired address to write to.
lpBuffer being The buffer the things you write is temporarily stored.
dwSize*being*The size of the buffer (count of bytes to write).
lpNumberOfBytesWritten*being**Holds the number of bytes written after calling this method.
But wait, how do I call it ? Well, it's pretty simple
Take the example from the RPM method, but add to it the value desired to write into the address.
Don't get it yet ? Here, take an example :
Code:
bool Write(IntPtr handle, int address, int value)
{
//1. Create buffer and pointer
byte[] dataBuffer = BitConverter.GetBytes(value);
IntPtr bytesWritten = IntPtr.Zero;
//2. Write
WriteProcessMemory(handle, (IntPtr)address, dataBuffer, dataBuffer.Length, out bytesWritten);
//3. Error handling
if(bytesWritten == IntPtr.Zero)
{
Console.WriteLine("We didn't write anything!");
return false;
}
if(bytesWritten.ToInt32() < dataBuffer.Length)
{
Console.WriteLine("We wrote {0} out of {1} bytes!", bytesWritten.ToInt32(), dataBuffer.Length.ToString());
return false;
}
return true;
}
Mouse Emulating
Well, to our Triggerbot to work it'll obviously need to click, for that we're going to use as source
this thread on stackoverflow.
Code:
* [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
* public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
* private const int MOUSEEVENTF_LEFTDOWN = 0x02;
* private const int MOUSEEVENTF_LEFTUP = 0x04;
* private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
* private const int MOUSEEVENTF_RIGHTUP = 0x10;
* //Call it with mouse_event(MOUSEEVENTF_LEFTDOWN, X, Y, 0, 0);
* //and
* //mouse_event(MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
* //or mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
Finals
Now that you know how to do the RPM and to emulate a mouse click all you need to do is stick it up together.
First of all you want to get the newest offsets so that we can read properly our player and enemy.
Getting our client module adress.
The client.dll is a part of CS:GO, apparently it manages the non-engine client-side stuff, like your health, team, and overall your player, and in order to read it we're going to need it's base address, to start off we need to find the CSGO process by doing so :
Code:
Process p = Process.GetProcessesByName("csgo"); // without the .exe
This will return us a
Process Object that references to our beloved CS:GO. Then we want to loop through all the Process Modules linked to our process by doing :
Code:
foreach (ProcessModule processModule in process.Modules)
{
* if (processModule.ModuleName == "client.dll")
* {
* * *return processModule.BaseAddress;
* }
}
this will give us the BaseAddress for the client.dll, which then can be used along the RPM and the LocalPlayer offset to give us the "Player Base".
Code:
CLIENT = client.dll Base Address
RPM(CLIENT + LocalPlayerOffset) = PlayerBase
RPM(PlayerBase + *m_iHealthOffset) = Your health
RPM(PlayerBase + m_iTeamNum) = Your Team
Play arround with it a bit to get used to it, and then we're moving to detect the enemy in the crosshair.
Code:
CROSSHAIR = RPM(PlayerBase + m_iCrosshairIdxOffset);
ENEMYBASE = RPM(CLIENT + EntityListOffset + ((CROSSHAIR - 1)*0x10);
RPM(ENEMYBASE + *m_iHealthOffset) = Enemy Health
RPM(ENEMYBASE + m_iTeamNum) = Enemy Team
Wow cowboy, hold on to your horse a bit, the enemybase is a little strange I know, but I can't explain it 100%, because I personally don't know how to, and would love if any expert answer it on this thread.
Moving on, we now need a main loop, this will be the "core" of the hack, being responsible for most of ours operations. If you're familliar with C# you know how to do it, just make a while(true) loop. Then we're going to add all the above operations inside it so that we keep our informations up-to-date.
Code:
CLIENT = client.dll Base Address
while(true)
{
* RPM(CLIENT + LocalPlayerOffset) = PlayerBase
* RPM(PlayerBase + *m_iHealthOffset) = Your health
* RPM(PlayerBase + m_iTeamNum) = Your Team
* CROSSHAIR = RPM(PlayerBase + m_iCrosshairIdxOffset);
* ENEMYBASE = RPM(CLIENT + EntityListOffset + ((CROSSHAIR - 1)*0x10);
* RPM(ENEMYBASE + *m_iHealthOffset) = Enemy Health
* RPM(ENEMYBASE + m_iTeamNum) = Enemy Team
}
Now for the triggerbot part, all you need to do is check the enemy health, and if it's greater than 0, and the team that the "enemy" is different then ours.
Code:
CLIENT = client.dll Base Address
while(true)
{
* RPM(CLIENT + LocalPlayerOffset) = PlayerBase
* RPM(PlayerBase + *m_iHealthOffset) = Your health
* RPM(PlayerBase + m_iTeamNum) = Your Team
* CROSSHAIR = RPM(PlayerBase + m_iCrosshairIdxOffset);
* ENEMYBASE = RPM(CLIENT + EntityListOffset + ((CROSSHAIR - 1)*0x10);
* RPM(ENEMYBASE + *m_iHealthOffset) = Enemy Health
* RPM(ENEMYBASE + m_iTeamNum) = Enemy Team
* if(EnemyHealth > 0 && EnemyTeam != PlayerTeam)
* {
* * * Thread.Sleep(30); // This is optional, this delays the shot, so that it isn't instant, making it less obvious.
* * * mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
* }
}
You should have a fully functional TriggerBot.
RCS
RCS, or Recoil Control System, as many of you know it controls your recoil while you're shooting, so to start things off we just wanna start the RCS system IF the player is shooting, in this case we are going to use the*
m_iShotsFired offset, to determine if player is shooting. We do that as we did with the others :
Code:
RPM(PlayerBase + m_iShotsFiredOffset);
That will return us the amount of shots fired from the player at the time of the reading, but now comes the Vectors. Vectors here, will be just like a array of 3 floats, being X,Y,Z*respectively. "Why ?" you ask me, well the First Vector we're using is going to store the player's crosshair position, and the Second Vector is going to store the current weapon punch vector, that is, the total amount of "recoil" produced by the weapon, to obtain the first vector we're going to use another .dll from the game : The engine.dll. For reading structures/classes from the game, we're going to need the 2° RPM method, linked at the bottom of the RPM section, so go ahead and get it first, and as for the Vector3 class, in this example we're using the one from the ExternalUtils from ZAT, that can be found HERE*or only the Vector3 class.
Code:
ENGINE = RPM(engine.dll + EnginePointerOffset);
AIM = RPM<Vector3>(ENGINE + m_dwViewAngles);
//AND THE PUNCH VECTOR
PVECTOR = RPM<Vector3>(PlayerBase + m_vecPunch);
Now that we've gathered arround the amout of bullets fired, and the player aim and punch vectors all we need to do is add it to the main loop, aside with some math operations.
Code:
CLIENT = client.dll Base Address
ENGINE = RPM(engine.dll + EnginePointerOffset);
OLDVECTOR // This will store the old punchvector of the player, so that we can base the mouse movement based on the latest recoil amount, not the total.
while(true)
{
* RPM(CLIENT + LocalPlayerOffset) = PlayerBase
* RPM(PlayerBase + *m_iHealthOffset) = Your health
* RPM(PlayerBase + m_iTeamNum) = Your Team
* CROSSHAIR = RPM(PlayerBase + m_iCrosshairIdxOffset);
* ENEMYBASE = RPM(CLIENT + EntityListOffset + ((CROSSHAIR - 1)*0x10);
* RPM(ENEMYBASE + *m_iHealthOffset) = Enemy Health
* RPM(ENEMYBASE + m_iTeamNum) = Enemy Team
RPM(PlayerBase + m_iShotsFiredOffset) = ShotsFired
AIM = RPM<Vector3>(ENGINE + m_dwViewAngles);
PVECTOR = RPM<Vector3>(PlayerBase + m_vecPunch);
* if(EnemyHealth > 0 && EnemyTeam != PlayerTeam)
* {
* * * Thread.Sleep(30); // This is optional, this delays the shot, so that it isn't instant, making it less obvious.
* * * mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
* }
if(ShotsFired > 0)
{
AIM.X += OLDVECTOR.X;
AIM.Y += OLDVECTOR.Y;
toWriteAim; // The aim that will now be the aim of the player
toWriteAim = new Vector3(AIM.X - PVECTOR.X*2, AIM.Y - PVECTOR.Y*2,AIM.Z);
WPM(ENGINE + m_dwViewAnglesOffset,toWriteAim);
OLDVECTOR.X = AIM.X*2;
OLDVECTOR.Y = AIM.Y*2;
}
else
{
//RESET THE OLDVECTOR FOR THE NEXT SHOOTING
OLDVECTOR.X = 0;
OLDVECTOR.Y = 0;
}
}
*Untested code
*Reading through it you should be able to understand the math behind it, but if you still don't reply above your question and I'll answer it.
Now you should have a functional RCS, along with your Triggerbot, have fun and if you have any questions leave it below.
Credits
Zat - For all the RPM/WPM sections.
Mom & Dad - For creating me.
Suggestions are always welcome.