We're winners you and I. We do what it takes to win, regardless of the so called "rules". We've been doing it as long as
we can remember, from the time we first installed mirrors in the room to cheat at UNO, to marking cards with friends and
playing black jack.
I'm certain we all owned one of these things 90's kids)
I know I did.
I chose video game cheating for 2 reasons. First was an excuse to play video games and speak at the same time. Second was the not so obvious link between malware, reverse engineering, hacking, and cheating. It all flows into 1 passion - puttering around and reversing.
Today we'll be discussing:
Cheating at video games is as old as video games themselves. The languages they're written in, the machines they run on, these all change, but the concepts don't. Modify a game save, modify memory, modify some instructions, simulate keystrokes / input.
The first cheats were simple POKE instructions. A POKE (and its counter PEEK) instruction is one that reads (peek) or writes (poke) memory at a certain address.
Sometimes cheating is necessary to beat a game. Remember Contra? Or Gradius? Can't beat those games with 3 lives, but its do-able with the Konami code. Remember the Konami code? Up, up, down, down, left, right, left, right, B, A, start - the screen goes white. I'll never forget this code.
Then there's instances when a developer leaves features inside a game to be found later. Just like sonic 1's debug mode:
There are also game breaking bugs that can be exploited. An example comes to mind - the guy who beat pokemon in 22 minutes. It's quite awesome.
Game Genie and similar devices made their debut in the the 80's as a way to "enhance" games - and enhance they did. the concept of the game genie and similar devices was this - game code is run through the cartridge and instructions are replaced before entering the console with psuedo POKE's.
Here's what some typical game genie code looked like:
Didn't look like much. Looked like magic back in the day. Somehow the cartridge converted this to cheats. So what's in a game genie code anyways? They come in 6 and 8 character codes and are basically an offset and a value for a POKE instruction. C code anyone?
int GameGenieDecode(const char* const characters,Code& code) { if (characters == NULL) return RESULT_ERR_INVALID_PARAM; byte codes[8]; uint length = 6; for (uint i=0; i < length; ++i) { switch (characters[i]) { case 'A': case 'a': codes[i] = 0x0; break; case 'P': case 'p': codes[i] = 0x1; break; case 'Z': case 'z': codes[i] = 0x2; break; case 'L': case 'l': codes[i] = 0x3; break; case 'G': case 'g': codes[i] = 0x4; break; case 'I': case 'i': codes[i] = 0x5; break; case 'T': case 't': codes[i] = 0x6; break; case 'Y': case 'y': codes[i] = 0x7; break; case 'E': case 'e': codes[i] = 0x8; break; case 'O': case 'o': codes[i] = 0x9; break; case 'X': case 'x': codes[i] = 0xA; break; case 'U': case 'u': codes[i] = 0xB; break; case 'K': case 'k': codes[i] = 0xC; break; case 'S': case 's': codes[i] = 0xD; break; case 'V': case 'v': codes[i] = 0xE; break; case 'N': case 'n': codes[i] = 0xF; break; default: return RESULT_ERR_INVALID_PARAM; } if (i == 2 && codes[2] & 0x8U) length = 8; } code.address = 0x8000 | ( ( codes[4] & 0x1U ) << 0x0 | ( codes[4] & 0x2U ) << 0x0 | ( codes[4] & 0x4U ) << 0x0 | ( codes[3] & 0x8U ) << 0x0 | ( codes[2] & 0x1U ) << 0x4 | ( codes[2] & 0x2U ) << 0x4 | ( codes[2] & 0x4U ) << 0x4 | ( codes[1] & 0x8U ) << 0x4 | ( codes[5] & 0x1U ) << 0x8 | ( codes[5] & 0x2U ) << 0x8 | ( codes[5] & 0x4U ) << 0x8 | ( codes[4] & 0x8U ) << 0x8 | ( codes[3] & 0x1U ) << 0xC | ( codes[3] & 0x2U ) << 0xC | ( codes[3] & 0x4U ) << 0xC ); code.value = ( ( codes[0] & 0x1U ) << 0x0 | ( codes[0] & 0x2U ) << 0x0 | ( codes[0] & 0x4U ) << 0x0 | ( codes[1] & 0x1U ) << 0x4 | ( codes[1] & 0x2U ) << 0x4 | ( codes[1] & 0x4U ) << 0x4 | ( codes[0] & 0x8U ) << 0x4 ); if (length == 8) { code.useCompare = true; code.value |= codes[7] & 0x8U; code.compare = ( ( codes[6] & 0x1U ) << 0x0 | ( codes[6] & 0x2U ) << 0x0 | ( codes[6] & 0x4U ) << 0x0 | ( codes[5] & 0x8U ) << 0x0 | ( codes[7] & 0x1U ) << 0x4 | ( codes[7] & 0x2U ) << 0x4 | ( codes[7] & 0x4U ) << 0x4 | ( codes[6] & 0x8U ) << 0x4 ); } else { code.useCompare = false; code.value |= codes[5] & 0x8U; code.compare = 0x00; } return RESULT_OK; }
So much to take in rite?
Game genie wasn't the other contender back in the day (and even now). Pro-action replay sold similar devices for all manner of consoles. The one I remember the most was the GameShark. The 'pro' version allowed us kids to tinker around and make our own codes
Every game shark code, every game genie cheat, (almost) every instance of WriteProcessMemory() with trainers is essentially a POKE instruction. There are other cases however where you're actually modifying instructions / patching them as opposed to modifying the memory.
At this time, game genie is dead, however Datel (owner of action replay) is still at it producing cheating mechanisms for XBOX, PS2, and even the 3DS.
Address Range (Hexadecimal) | Size | Notes (Page size is 256 bytes) | |
---|---|---|---|
$0000–$00FF | 256 bytes | Zero Page — Special Zero Page addressing modes give faster memory read/write access | |
$0100–$01FF | 256 bytes | Stack memory | |
$0200–$07FF | 1536 bytes | RAM | |
$0800–$0FFF | 2048 bytes | Mirror of $0000–$07FF | $0800–$08FF Zero Page $0900–$09FF Stack $0A00–$0FFF RAM |
$1000–$17FF | 2048 bytes | Mirror of $0000–$07FF | $1000–$10FF Zero Page $1100–$11FF Stack $1200–$17FF RAM |
$1800–$1FFF | 2048 bytes | Mirror of $0000–$07FF | $1800–$18FF Zero Page $1900–$19FF Stack $1A00–$1FFF RAM |
$2000–$2007 | 8 bytes | Input/Output registers | |
$2008–$3FFF | 8184 bytes | Mirror of $2000–$2007 (multiple times) | |
$4000–$401F | 32 bytes | Input/Output registers | |
$4020–$5FFF | 8160 bytes | Expansion ROM — Used with Nintendo's MMC5 to expand the capabilities of VRAM. | |
$6000–$7FFF | 8192 bytes | SRAM — Save Ram used to save data between game plays. | |
$8000–$FFFF | 32768 bytes | PRG-ROM | |
$FFFA–$FFFB | 2 bytes | Address of Non Maskable Interrupt (NMI) handler routine | |
$FFFC–$FFFD | 2 bytes | Address of Power on reset handler routine | |
$FFFE–$FFFF | 2 bytes | Address of Break (BRK instruction) handler routine |
Not every instance of cheating is super hard or requires intense understanding of the underlying code. Sometimes all you need is a hex editor. Editing game saves goes all the way back to the days when games allowed saving. The game save file has to contain your present "state" which includes your health, money, items, progress, and anything else necessary to loading from a certain point. Many times this save file isnt even protected from viewing / disassembling.
I will be using the following tools:
Loading the game save into HXD, we see the header that starts with "TES3".
In the case of this save file, our work is cut out for us. The values and fields are clearly explained.
We can see our currently equipped items. Like any and all cheating, we have to guess. Modify values and reload, then hope for the best.
There's really not much else to it. You might want to have the calculator handy for converting hex to decimal, but that's it. It should be worth noting that most games that have save files have had SOMEONE look already and detail their inner workings. Never re-invent the wheel. Check out gamefaqs.com or gamewinners.com for texts on all things save file related.
What the hell is cheat engine? How does it work? What is Tsearch? GameConqueror???
These are programs made to make cheating a little easier. Essentially debuggers catered to the world of cheating.
I will start with Linux to get it out of the way. I will not be giving specifics. Presently on Linux, there is 1 "cheat engine like" tool called GameConqueror. It scans memory, is written in Python and can work on games for Linux. The reason why there aren't more advanced features is that Linux and its games are usually free making such a program unecesessary. Maybe you could use it on the 2 games for Steam on Linux hmm?
Now on to windows. The grandfather of them is Tsearch. Though old and worn looking, Tsearch still works to this day, though only on 32 bit programs. Supports memory dumping, searching, differential value matching, and the like. You can get a lot done with Tsearch, but once you've used its son offspring program Cheat Engine, you'll never go back.
Cheat engine is very powerful in what it allows us to do - full memory manipulation / handling of any application of our choosing.
Here's a quick breakdown of Cheat Engine:
This is our main window. Warm, inviting.
This is our process list. Several options. Cheat Engine allows us to attach to programs live or launch within.
This is our memory viewer / debugger. Our best friend and ally. Supports a live view of memory (like fceux), searching for assembly instructions, dumoping / saving memory, disassembler, tracing, and more. It even supports a kernel mode.
There are many different aspects to cheat engine I could talk for hours on such as the pointer scanner which is used for finding static pointers used when memory is dynamic. For now I will mention its presence:
I will now go over a video of using Cheat Engine against Metro: Last Light. I'm using Cheat Engine to do infinite ammo on some guns.
Now I will go over F.E.A.R VIDEO HERE AND HERE
And lastly for PC games, I will go over either Pinball or Age of empires. I will do this live.
Hack flash apps? Sure why not? After all, gotta be the BAMF in candy crush amirite?
There are many ways to modify flash apps. Some more complicated than others.
In the following video we'll be hacking tetris using Cheat Engine, chrome, and my website.
VIDEO HERE What if we don't wanna do this? What if we're only interested in the score? For that you have to deep dive in the action script. For this, I recommend Sothink SWF decompiler. It has the ability to break down / decompile flash files to their original source.using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading; using System.Runtime.InteropServices; namespace Bot_Me { public partial class Form1 : Form { public Form1() { InitializeComponent(); } [DllImport("User32.dll")] static extern int SetForegroundWindow(IntPtr point); [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; public void DoMouseClick( uint mouseX, uint mouseY) { mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, mouseX, mouseY, 0, 0); } private void bgw_DoWork(object sender, DoWorkEventArgs e) { string processname = cbProcesses.SelectedText; System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessesByName(processname)[0]; if( p != null) { IntPtr h = p.MainWindowHandle; SetForegroundWindow(h); for (int x = 0; x < 100; x++) { SendKeys.Send("w"); DoMouseClick(200,450); Thread.Sleep(2000); SendKeys.Send("s"); DoMouseClick(500, 150); Thread.Sleep(2000); SendKeys.Send("w"); Thread.Sleep(2000); SendKeys.Send("a"); Thread.Sleep(2000); SendKeys.Send("a"); Thread.Sleep(2000); SendKeys.Send("s"); Thread.Sleep(2000); SendKeys.Send("d"); DoMouseClick(100,100); } } } private void DoIt_Click(object sender, EventArgs e) { bgw.RunWorkerAsync(); } private void Form1_Load(object sender, EventArgs e) { foreach (System.Diagnostics.Process kek in System.Diagnostics.Process.GetProcesses()) { cbProcesses.Items.Add(kek.ProcessName); } } } }
Real easy stuff. Get the window handle, send keys will simulate keystrokes to it. We sleep 2 seconds between each. It should simulate movement. This will prevent us from going "afk".
Mouse clicks are different - they're simulated windows events mapped on a 2 dimensional X / Y plane. We feed in the X and the Y values to come to a point to perform the click. You'll need to fine tune this for games (or whatever you want) via getting the screen coordinates for certain points.
How the heck do we (easily) get the screen coordinates? I've got your back. I wrote a small app in .net which does the job. Use windows key + A to get the screen coordinates from where the mouse presently is:
A little code for those interested:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace cursorPOS { public partial class Form1 : Form { [DllImport("user32.dll")] private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk); [DllImport("user32.dll")] private static extern bool UnregisterHotKey(IntPtr hWnd, int id); enum KeyModifier { None = 0, Alt = 1, Control = 2, Shift = 4, WinKey = 8 } [StructLayout(LayoutKind.Sequential)] public struct POINT { public int X; public int Y; public static implicit operator Point(POINT point) { return new Point(point.X, point.Y); } } [DllImport("user32.dll")] public static extern bool GetCursorPos(out POINT lpPoint); public static Point GetCursorPosition() { POINT lpPoint; GetCursorPos(out lpPoint); return lpPoint; } public Form1() { RegisterHotKey(this.Handle, 1234, (int)KeyModifier.WinKey, Keys.A.GetHashCode()); //winkey + a InitializeComponent(); } protected override void WndProc(ref Message m) { base.WndProc(ref m); if (m.Msg == 0x0312) // WM_HKEY message { Point kek = GetCursorPosition(); tbMousePos.Text = "X: " + Convert.ToString(kek.X) + " Y: " + Convert.ToString(kek.Y); } } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { UnregisterHotKey(this.Handle, 1234); } } }
#include <windows.h> #include <tlhelp32.h> int getprivs() { HANDLE Token; TOKEN_PRIVILEGES tp; if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&Token)) { LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (AdjustTokenPrivileges(Token, 0, &tp, sizeof(tp), NULL, NULL)==0){ return 1; //FAIL }else{ return 0; //SUCCESS } } DWORD getPid(char *procName){ HANDLE hsnap; PROCESSENTRY32 pt; hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); pt.dwSize = sizeof(PROCESSENTRY32); do{ if(pt.szExeFile == procName){ DWORD pid = pt.th32ProcessID; CloseHandle(hsnap); return pid; } } while(Process32Next(hsnap, &pt)); CloseHandle(hsnap); return 0; } int main(void) { getprivs(); HANDLE hproc = OpenProcess(PROCESS_ALL_ACCESS, getPid("game.exe")); CONTEXT ct; SuspendThread(hproc); // suspend main thread before grabbing context ct.ContextFlags = (CONTEXT_FULL); GetThreadContext(hproc,&ct); ct.EAX = 10000; ct.EBX = 23456; SetThreadContext(hproc,&ct); ResumeThread(hproc); }
void Trainer::SetLife(float life) { unsigned long pointer = 0xB6F5F0; //CPed address DWORD pCPed; //the var which will hold the player PED struct value. ReadProcessMemory(Trainer::memory.hProc, (LPVOID)pointer, &pCPed, sizeof(pointer), NULL); unsigned long offset = 0x540; //health address LPVOID address = (LPVOID)(pCPed + offset); //the address's combined togher int stat = WriteProcessMemory(Trainer::memory.hProc, address, &life, (DWORD)sizeof(life), NULL); if (stat > 0){ MessageBox(NULL, (LPCSTR)"Health value has been replaced to the new one!", (LPCSTR)"Sucess", MB_ICONINFORMATION | MB_OK); } else { MessageBox(NULL, (LPCSTR)"We couldn't replace the value, his gta_sa.ex open?", (LPCSTR)"Sucess", MB_ICONINFORMATION | MB_OK); } }
By making use of the Read/WriteProcessMemory functions, this code searches for a certain address (0xB6F5F0) at a certain offset (0x540) and modifies it with a larger value (float value named 'life').
That's it, that's all it does. Nothing fancy or special. How do they know which addresses / offsets / values to modify? There's where the fun lies. We use Cheat Engine for this, though Tsearch could also work. The same principles for cheating with Nintendo apply here as well - fuzzy searches for values greater than, less than, equal to, etc to obtain the proper offsets and addresses to modify with our trainer.
Of course cheat engine makes this process much simpler in the form of a cheat address table. The CHT file is essentially an XML file is loaded by cheatengine automatically and modifies the values at certain offsets for us without the need for writing a trainer. So why write a trainer if Cheat Engine does this for us? Portability mostly - most people write trainers for other people - the plebs. Your normal average gamer isn't very bright. It's much simpler for them to load a secondary app with a simple hotkey than to have them launch a fully fledged debugger / cheater engine app with their app. Also some games check for the presence of Cheat Engine and would need to be patched - out of scope for most gamers.
Luckily, we can use the memory locations obtained with cheat engine directly with Read/WriteProcessMemory and it works the same as if CheatEngine were running.
#include <stdio.h> #include <windows.h> #include <tlhelp32.h> typedef int (WINAPI* MsgBoxParam)(HWND, LPCSTR, LPCSTR, UINT); using namespace std; struct PARAMETERS{ DWORD MessageBoxInj; char text[50]; char caption[25]; int buttons; // HWND handle; }; DWORD getPid(char *procName); int getprivs(); DWORD myFunc(PARAMETERS * myparam); DWORD Useless(); DWORD getPid(char *procName){ HANDLE hsnap; PROCESSENTRY32 pt; hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); pt.dwSize = sizeof(PROCESSENTRY32); do{ if(pt.szExeFile == procName){ DWORD pid = pt.th32ProcessID; CloseHandle(hsnap); return pid; } } while(Process32Next(hsnap, &pt)); CloseHandle(hsnap); return 0; } DWORD myFunc(PARAMETERS * myparam){ MsgBoxParam MsgBox = (MsgBoxParam)myparam->MessageBoxInj; int result = MsgBox(0, myparam->text, myparam->caption, myparam->buttons); switch(result){ case IDOK: //your code break; case IDCANCEL: //your code break; } return 0; } DWORD Useless(){ return 0; } int getprivs(){ HANDLE Token; TOKEN_PRIVILEGES tp; if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&Token)) { LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (AdjustTokenPrivileges(Token, 0, &tp, sizeof(tp), NULL, NULL)==0){ return 1; //FAIL }else{ return 0; //SUCCESS } } return 1; } int main() { privileges(); //need SE_DEBUG privs to do this. DWORD pid = getPid("notepad.exe"); if (pid==0) return 1; //error HANDLE p; p = OpenProcess(PROCESS_ALL_ACCESS,false,pid); if (p==NULL) return 1; //error char *mytext = "Hello by DLL Injection!"; char *mycaption = "Injection result"; PARAMETERS data; //let's fill in a PARAMETERS struct data.MessageBoxInj = (DWORD)GetProcAddress(GetModuleHandleA("User32.dll"), "MessageBoxA"); strcpy(data.text, mytext); strcpy(data.caption, mycaption); data.buttons = MB_OKCANCEL | MB_ICONQUESTION; DWORD size_myFunc = (PBYTE)Useless - (PBYTE)myFunc; //this gets myFunc's size //--------now we are ready to inject void * MyFuncAddress = VirtualAllocEx(p, NULL, size_myFunc, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); WriteProcessMemory(p, MyFuncAddress, (void*)myFunc,size_myFunc, NULL); void * DataAddress = VirtualAllocEx(p,NULL,sizeof(PARAMETERS),MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE); WriteProcessMemory(p, DataAddress, &data, sizeof(PARAMETERS), NULL); HANDLE thread = CreateRemoteThread(p, NULL, 0, (LPTHREAD_START_ROUTINE)MyFuncAddress, DataAddress, 0, NULL); if (thread!=0){ //injection completed WaitForSingleObject(thread, INFINITE); //this waits untill thread thread has finished VirtualFree(MyFuncAddress, 0, MEM_RELEASE); //free myFunc memory VirtualFree(DataAddress, 0, MEM_RELEASE); //free data memory CloseHandle(thread); CloseHandle(p); //don't wait for the thread to finish, just close the handle to the process printf("Injection completed!\r\n); }else{ printf("Error!\r\n"); } system("PAUSE"); return EXIT_SUCCESS; }
If you want a tool specific to cheating at games that utilizes dll injection, check out Xenos.
What is a code cave? Its empty space you can cram your code into usually marked Read/Write/Execute. Sometimes it might be necessary write our trainer inline with the program or modify some of the code. We might have new instructions we wish to add to an existing program. Since we can't just tack it to the end (for alignment reasons), we'll have to make use of the code cave.
The minimum size for a code cave is 5 bytes? Any guesses why? That's right, we need 5 bytes to perform a long unconditional jmp that is process memory wide. What if we want to modify a program without taking up space?
We have 2 choices - we can either
The concept is the simple - run your code in the game instead of as a sister program.
I should note that Cheat Engine supports the ability to search for code caves of whatever size you need. Super handy.
// Credits: phrak, Game Deception typedef BOOL ( WINAPI *FindNextFileA_t )( HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData ); typedef HMODULE ( WINAPI *FindFirstFileA_t )( LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData ); FindFirstFileA_t pFindFirstFileA = 0; FindNextFileA_t pFindNextFileA = 0; char *g_pszFileName = "Whatever"; // replace it by your file name DWORD g_dwPbclBase; // = ( DWORD )GetModuleHandle( "pbcl.dll" ); DWORD g_dwPbclSize = 0x84000; // replace it by the correct pbcl.dll size extern "C" void *_ReturnAddress( void ); //======================================================================== HANDLE WINAPI _FindFirstFileA( LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData ) { DWORD dwReturnAddress = PtrToUlong( _ReturnAddress( ) ); int iLoop = 1; HANDLE hReturn = pFindFirstFileA( lpFileName, lpFindFileData ); if( dwReturnAddress >= g_dwPbclBase && dwReturnAddress <= ( g_dwPbclBase+g_dwPbclSize ) ) { while( iLoop && !_strnicmp( lpFindFileData->cFileName, g_pszFileName, strlen( g_pszFileName ) ) ) iLoop = pFindNextFileA( hReturn, lpFindFileData ); if( !iLoop ) hReturn = INVALID_HANDLE_VALUE; } return hReturn; } //======================================================================== BOOL WINAPI _FindNextFileA( HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData ) { DWORD dwReturnAddress = PtrToUlong( _ReturnAddress( ) ); BOOL bReturn = FindNextFileACall( hFindFile, lpFindFileData ); if( dwReturnAddress >= g_dwPbclBase && dwReturnAddress <= ( g_dwPbclBase+g_dwPbclSize ) ) { do { bReturn = FindNextFileACall( hFindFile, lpFindFileData ); } while( !_strnicmp( lpFindFileData->cFileName, g_pszFileName, strlen( g_pszFileName ) ) && bReturn ); if( !bReturn ) memset( lpFindFileData, 0, sizeof( LPWIN32_FIND_DATA ) ); } return bReturn; }
What's going on here? Essentially they're detouring around the FindFirstFile api so that it skips its check for your particular file. Clever huh?
For more info on detours, check out this Microsoft research paper.
As much fun as it is to cheat, there are some members of the fun police that wish to make us abide by the rules. Why anti-cheat and does it work? What I've observed is that it keeps raging 13 year olds off the servers by auto-banning known hax, however any skilled reverse engineer can easily bypass these engines. They do a great job at keeping the masses in check, but the select few who know what they are doing (programmers) will always find a way around the anti-cheat techniques and continue cheating unabaided.
There's several anti-cheating technologies employed today. The most popular are:
Side note, these are only for PC games. Presently I am unaware of any such technologies employed for console games - its not like many trainers exist for the PS4/XBOX360, but if they did, they user would have free reign to do whatever they wanted.
Popular for MMO's including Rift, MapleStory, and Nexon, this korean company poroduces a fairly popular anti-cheat system. While not particularly advanced with its detection, it employs most of what you would expect with such a system - memory scanning, a p2p network, and quick bans.
As you may of guessed, Valve Anti-Cheat belongs to games that are run with Steam. VAC doesn't kick/ban you when it detects a cheat off the bat - instead it waits 2-48 hours before doing so silently. This is because they want to catch as many people as possible whom might be distributing the cheat files.
Because of the popularity of this anti cheat system, there is an ongoing battle between super hacker elite cheaters and the devs of this system - after all valve / steam is HUGE.
FairFight is a different take on your traditional anti-cheat system. They use statistics and logic to determine if someone is cheating.
Did you suddenly go 55 and 1 on a FPS death match but earlier you only did 0 4 and 30? Unless you're Colin or Patrick, its gonna ban you
based off the simple fact that no one usually gets that good over night. There are other indicators that go into this intelligent
determination such as accuracy, movement, times, but all in all its a decent system. Not impossible to get around if you
"cheat conservatively", but where's the fun in that?
One of the earliest anti-cheat detection engines I remember seeing, this product goes back 15 years to 2000 when it was first released. It's also one of the more advanced second to VAC in functionality.
Another MMO anti-cheat system serving up primarily Asian MMO's such as Lineage, Ragnorak, and Phantasy Star Online (PSO), About the same as HackShield in functionality.
How do these systems work? They usually work like an Anti-Virus program in that they have a database of known cheats that they scan for - a blacklist if you will. They scan the contents of memory of games, the OS, etc for known cheat program's signatures. They also inspect open processes for file handles and inspect names for scanning. In the case of VAC, they scan Window Text as well for known bad files.
Do they work? To answer this, ask yourself if anti-viruses work.
I know several of you were waiting for this. How do we get around these checks? An anti cheat detection system is much like and anti-virus, and we all know how GREAT those work right?
In my studies, I have found that most employed methods for defeating the dection is outright disablement of the engine via means of either
Sound familiar? These are about the same things malware writers do, give or take exploits and reflection.
How would you easiest get around something like VAC? Change the cheat files enough to get around the signature check - just like an AV. You can get around the window text check by sending the WM_SETTEXT message to the window of the known cheat program. This can be done via either dll injection or with a shared dll address space like if you were coding a key logger.
What about GameGuard? Sleeping your cheat code will help stave off heuristic detection. Personally the best way to stay above all forms of radar is to keep your cheats secret. The anti-cheat technologies will keep the lower players at bay, but does little for the pros and those who keep their mouths shut.
I would love to go into super duper detail, but this talk is intended to be an intro to the world of cheating, not a full blown deep dive into assembly language modificastion, use of IDA pro, use of debuggers, detours, trampolines, and offset calculation + DMA. That would make this talk like 5 hours.
http://www.unknowncheats.me/ is a forum deticated to this kind of stuff, and has a number of tutorials and techniques for such bypasses. In fact I obtained a number of techniques from there. If you're serious about getting into advanced cheating, start there.