Fuzzy
Initiator

Data inscrierii: 18/Noi/2007 Mesaje: 10
|
|
How to make a trainer |
|
How To Confecționate A Game Trainer Using C/C++
Long way and more harder work from top to bottom...only the strongest mens will survive...
Chapters....
1) Introduction... Programs needed... objective...
2) Api calls we will be using
3) header file of CProcess
4) methods of CProcess
5) An example: Mortal Kombat 4 trainer
6) the end
CHAPTER 1: Introduction... Programs needed... objective...
************************************************** **********
While answering questions on the gamehacking webboard, I noticed a lot
people out there want to develop trainers themselves instead of using
standard kits. Although you can use just about any programming language
for the job, I figure the best option is C/C++. The main advantages of
C/C++ is that its fast enough and that it produces neat, small executables.
You need a C/C++ compiler (duh). What also needs to be included is: a
windows resource editor, text editor and access to Windows API. If you must
know, I use Microsoft Visual C++ for the job.
The objective of this tutorial is to create a small, working trainer
of course, but in school I also learned how to develop reusable code.
Since we all want to release a trainer more than once, I developed a C++
class which just about does it all. The usage of this class looks
something like this (in pseudo-code):
Code: Select all
void timer_or_thread_function ()
{
Find the process
if (process is loaded)
if (key is pressed)
Read/Write memory
}
I won't teach you how the project should be created, how windows messages work,
how C++ classes work or what data types are available... there are plenty of
resources on that available on the net.
Also note that the method of gamehacking presented here is *a* method; not
*the* method
Lets get into some code...
CHAPTER 2: API calls we will be using
***************************************
First, lets list all the Windows APIS we're gonna need to develop the CProcess class.
-----------------------------------------------------------------------------
Code: Select all
HWND FindWindow(
LPCTSTR lpClassName, // pointer to class name
LPCTSTR lpWindowName // pointer to window name
);
details All programs started in windows have a window <duh>
This API call finds the window handle for a running process.
-----------------------------------------------------------------------------
Code: Select all
DWORD GetWindowThreadProcessId(
HWND hWnd, // handle to window
LPDWORD lpdwProcessId // address of variable for process identifier
);
details And you guessed, this one gets the process handle based on
the process ID.
Code: Select all
UINT SetTimer(
HWND hwnd, // handle of window for timer messages
UINT idTimer, // timer identifier
UINT uTimeout, // time-out value
TIMERPROC tmprc // address of timer procedure
);
details This API is used to generate a timer message at a certain interval.
We'll use it to check whether or not keys have been pressed and
if so to read or write values to the game's memory.
-----------------------------------------------------------------------------
Code: Select all
SHORT GetAsyncKeyState(
int vKey // virtual-key code
);
details This API checks to see if a key has been pressed since last call to
the API. We need to call this one over and over again (see SetTimer)
-----------------------------------------------------------------------------
Code: Select all
BOOL WriteProcessMemory(
HANDLE hProcess, // handle of process whose memory is written to
LPVOID lpBaseAddress, // address to start writing to
LPVOID lpBuffer, // address of buffer to write data to
DWORD cbWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten // actual number of bytes written
);
details I'm not religious, but we really have to thank God to have Billy-boy
include this API into Windows. This is the heart of every trainer.
It can write values to memory.
-----------------------------------------------------------------------------
Code: Select all
BOOL ReadProcessMemory(
HANDLE hProcess, // handle of process whose memory is read
LPVOID lpBaseAddress, // address to start reading
LPVOID lpBuffer, // address of buffer to read data to
DWORD cbRead, // number of bytes to read
LPDWORD lpNumberOfBytesWritten // actual number of bytes read
);
details And of course, this is WriteProcessMemory's twin. It can read
values from memory.
-----------------------------------------------------------------------------
Code: Select all
VOID ExitProcess(
UINT uExitCode // exit code for all threads
);
details Windows closes all handles and cleans just about everything, but
its a good programming practise to close it yourself. This one
closes a process.
-----------------------------------------------------------------------------
Ok... take a second look at the all APIs. Notice all the ugly parameter datatypes like HWND,
UINT, LPVOID, HANDLE and HPROCESS. Personally I hate to use these types, so what I'll do is
put all these APIS and variables in the C++ class, so I won't be bothered with them while
programming the trainer.
( Thanx to RECLAIM for the explaination of the APIs )
CHAPTER 3: Header file of CProcess
************************************
The header file of our CProcess class is relatively easy... here it is:
Code: Select all
class CProcess
{
public:
CProcess();
virtual ~CProcess();
bool IsRunning(); // checks if process was found already
bool FindProcess(char *p_WindowTitle); // finds a process
BYTE ReadByte(DWORD p_Address); // reads 1 byte from memory
bool WriteByte(DWORD p_Address, BYTE p_Value); // writes 1 byte to memory
bool IsKeyPressed(int p_iKey); // checks for a key-press
bool IsSpyRunning(char *p_WindowTitle); // checks for trainer spy
private:
HANDLE OpenProcess(char *p_ClassName, char *p_WindowTitle);
HANDLE m_hProcess;
bool m_bGameRunning;
};
CHAPTER 4: Methods of CProcess
********************************
Lets develop each method one by one... here goes.
Constructor/Destructor
Every C++ class has a constructor and a destructor. These methods are used for
initializing resp. deinitializing of local variables. Since we only have 2 local
variables these methods are straightforward:
Code: Select all
CProcess::CProcess()
{
m_hProcess = NULL;
m_bGameRunning = false;
}
CProcess::~CProcess()
{
if (m_bGameRunning)
CloseHandle(m_hProcess);
}
Note the m_hProcess will contain the handle of the process and m_bGameRunning
is a flag to see if we opened the process already.
Private method: OpenProcess
This method will find and open a process.
Code: Select all
HANDLE CProcess::OpenProcess(char *p_ClassName, char *p_WindowTitle)
{
HWND hWindow;
DWORD pid;
hWindow = FindWindow(p_ClassName, p_WindowTitle);
if (hWindow) {
GetWindowThreadProcessId(hWindow, &pid);
return ::OpenProcess(PROCESS_ALL_ACCESS, false, pid);
}
return NULL;
}
Notice that this method is private, which means it can only be used by other members
of the CProcess class. What it does... it looks for the window handle (FindWindow)
based on the window title of the game (the p_Classname parameter should be NULL!).
Then it retrieves the Process ID (GetWindowThreadProcessId), opens the process
(OpenProcess) and returns the handle of that process.
If the game isn't loaded or if the window title isn't correct(!), it will return NULL
indicating failure.
This method is used by FindProcess() and IsTrainerSpyRunning().
Public method: FindProcess
This method will find and open a process and on top of that it'll store everything
in the class' private members.
Code: Select all
bool CProcess::FindProcess(char *p_WindowTitle)
{
if (m_hProcess == NULL) {
m_hProcess = this->OpenProcess(NULL, p_WindowTitle);
if (m_hProcess)
m_bGameRunning = true;
return m_bGameRunning;
}
else
return false;
}
The trainer program will call this method to find and open the process of the game.
This method tries to open the process and store the handle in the class' private
member. It also sets a flag to indicate success or failure.
Public method: WriteByte
This method will write 1 byte to the specified memory addy.
Code: Select all
bool CProcess::WriteByte(DWORD p_Address, BYTE p_Value)
{
DWORD bytes;
if (m_bGameRunning)
return (WriteProcessMemory(m_hProcess, (void*)p_Address,
(void *)&p_Value, 1, &bytes) != 0);
return false;
}
The method returns true if and only if writing the byte to the mem addy was
successful. False indicates the game isn't running (call FindProcess first!)
or writing the value simply failed.
Public method: ReadByte
Code: Select all
BYTE CProcess::ReadByte(DWORD p_Address)
{
DWORD bytes;
BYTE tmpValue;
if (m_bGameRunning) {
if (ReadProcessMemory(m_hProcess, (void*)p_Address,
(void *)&tmpValue, 1, &bytes) == 0)
return 0;
else
return tmpValue;
}
return 0;
}
The method returns the byte value that has been read for the game's memory.
Public method: IsRunning
We need a method to expose the m_bGameRunning variable, so the trainer can tell
whether or not the process was already found and opened successfully.
Code: Select all
bool CProcess::IsRunning()
{
return m_bGameRunning;
}
No further explaination needed, I figure
Public method: IsKeyPressed
This function detects a key press.
bool CProcess::IsKeyPressed(int iKey)
{
return ((GetAsyncKeyState(iKey) & 1) == 1);
}
This might look strange to you. It just so happens GetAsynchKeyState sets the
least significant bit of the returned value to indicate the key has been pressed.
True or False would have worked fine for me, by the way
Public method: IsTrainerSpyRunning
Don't you just hate it when people are trying to rip off your mem addy?
Code: Select all
bool CProcess::IsSpyRunning(char *p_WindowTitle)
{
HANDLE hTmp = this->OpenProcess(NULL, "TRAINER SPY");
if (hTmp) {
CloseHandle(hTmp);
return true;
}
return false;
}
This method tries to open the Trainer Spy process. If it can be opened the
handle of trainer spy (trainer spy will keep on running!) is closed and the method
returns true indicating trainer spy is running and something needs to be done
about it!
Thats it... those are all the methods we need.
CHAPTER 5: An example: Mortal Kombat 4 +3 trainer
************************************************** *
Lets develop a trainer for Mortal Kombat 4.
With GameHack I found these mem addies:
Health player 1 0x00534A9D 1 byte
Health player 2 0x005322ED 1 byte
timer 0x00534AD8 1 byte
Ohw, before we start.. I'm not gonna explain how to use the resource editor
to develop the actual window of the trainer since its different for every
development tool.
Code: Select all
//
// Conține all header files for the VC++ project
//
#include <stdio.h>
#include "stdafx.h"
#include "Process.h"
/* ------------------------------------------ */
/* -- Identification for dialog, controls, -- */
/* -- timers & such -- */
/* ------------------------------------------ */
#define DLG_MAIN 200 // ID for dialog
#define DLG_ICON 30000 // IDs for icons
#define DLG_ICON_S 30000
#define IDC_QUIT 1011 // ID for "quit"-button
#define IDC_INFO 2000 // ID for "info"-button
#define ID_TIMER 1 // ID for timer
#define IDC_STATIC -1 // ID for all labels
#define TIMER_INTERRUPT 500 // timer msg interval in msec
/* ---------------------------------------- */
/* -- The mem addies found with GameHack -- */
/* ---------------------------------------- */
#define HEALTH_PL1_ADDRESS 0x00534A9D
#define HEALTH_PL2_ADDRESS 0x005322ED
#define TIMER_ADDRESS 0x00534AD8
/* ------------------------------------------ */
/* -- Global variables... oh well... -- */
/* ------------------------------------------ */
HINSTANCE TheInstance = 0; // instance handle of this trainer
CProcess gameProcess; // instance of the CProcess class
/* ------------------------------------------------------------- */
//
// Windows passes messages to application windows to indicate "something"
// needs to be done
//
BOOL CALLBACK DialogProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_INITDIALOG:
//
// set the time to generate a timer message (WM_TIMER)
// at a small interval
//
SetTimer(hwnd, ID_TIMER, TIMER_INTERRUPT, NULL);
return TRUE;
case WM_TIMER:
//
// a timer msg was received so call our main function!
//
WriteMem(hwnd);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_INFO:
//
// the info button on the window was pressed
//
MessageBox(hwnd, "<show some info>", "Mortal Kombat 4 +3 trainer", MB_OK);
return TRUE;
case IDC_QUIT:
//
// the quit button on the window was pressed
//
PostQuitMessage(0);
return TRUE;
}
return TRUE;
case WM_DESTROY:
//
// this app is about to be closed so kill the timer
//
KillTimer(hwnd, ID_TIMER);
PostQuitMessage(0);
return TRUE;
case WM_CLOSE:
//
// destroy the window
//
DestroyWindow (hwnd);
return TRUE;
case WM_PAINT:
//
// paint msg so we can show a bmp on the screen (or something else)
//
PaintIt(hwnd);
return TRUE;
}
return FALSE;
}
//
// the main function.. this one was generated by Visual C++ (talk about ugly code!
//
int WINAPI WinMain
(HINSTANCE hInst, HINSTANCE hPrevInst, char * cmdParam, int cmdShow)
{
TheInstance = hInst;
HWND hDialog = 0;
hDialog = CreateDialog (hInst, MAKEINTRESOURCE (DLG_MAIN), 0, (DLGPROC)DialogProc);
if (!hDialog)
{
char buf [100];
wsprintf (buf, "Error x%x", GetLastError ());
MessageBox (0, buf, "CreateDialog", MB_ICONEXCLAMATION | MB_OK);
return 1;
}
HICON hIcon = LoadIcon (TheInstance, MAKEINTRESOURCE (DLG_ICON));
SendMessage (hDialog, WM_SETICON, WPARAM (TRUE), LPARAM (hIcon));
hIcon = LoadIcon (TheInstance, MAKEINTRESOURCE (DLG_ICON_S));
SendMessage (hDialog, WM_SETICON, WPARAM (FALSE), LPARAM (hIcon));
MSG msg;
int status;
while ((status = GetMessage (&msg, 0, 0, 0)) != 0)
{
if (status == -1)
return -1;
if (!IsDialogMessage (hDialog, &msg))
{
TranslateMessage ( &msg );
DispatchMessage ( &msg );
}
}
return msg.wParam;
}
//
// This is our main function that does the job! Remember this function
// is called every time the timer msg is received.
//
void WriteMem(HWND hwnd)
{
//
// find out if we already found the game before
//
bool bOk = gameProcess.IsRunning();
//
// if not then try to find it
//
if (!bOk)
bOk = gameProcess.FindProcess("Mortal Kombat 4");
//
// if and only if game is running -> write mem
//
if (bOk) {
if (gameProcess.IsSpyRunning("TRAINER SPY"))
//
// someone is trying to rip us off! Close this trainer
//
PostQuitMessage(0);
//
// if F10 was pressed, max the timer!
//
if (gameProcess.IsKeyPressed(VK_F10))
if (!gameProcess.WriteByte(TIMER_ADDRESS, 100))
PostQuitMessage(0);
//
// if F11 was pressed, max player 1's health!
//
if (gameProcess.IsKeyPressed(VK_F11))
if (!gameProcess.WriteByte(HEALTH_PL1_ADDRESS, 0xFF))
PostQuitMessage(0);
//
// if F12 was pressed, max player 2's health!
//
if (gameProcess.IsKeyPressed(VK_F12))
if (!gameProcess.WriteByte(HEALTH_PL2_ADDRESS, 0xFF))
PostQuitMessage(0);
}
}
void PaintIt(HWND hwnd)
{
//
// To do (or not to do
// = show a neat pic on your trainer's window
//
}
CHAPTER 6: The End
*********************
You can use the CProcess class or the main program code in any way you want.
If you experience any problems with it, don't hesitate to atingere me.
You can also ask for me to send you the complete MS Visual C++ project. 
_________________
 |
|