Guide GHB2 - Beginners Guide To Reverse Engineering

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,540
78,998
2,312
What is reverse engineering?

Reverse Engineering is taking bits and bytes and figuring out what they represent, how they are used and why. This is done by using the scientific method which is forming hypotheses and testing them. In the case of reverse engineering computer code we are typically talking about reversing functions from their assembly code and created a higher level picture of what the purpose of the code is.

Let's take a look at it from a lower perspective first and then a higher one.

For bytes that represent data, you reverse engineer their data type, size & purpose. Are they integers, floats, a string or maybe a bitfield? Is it a health value or a name? Is it a 2 byte or 4 byte size integer? Is it signed or unsigned?

For bytes that represent code it's more complicated. You are trying to figure out, what instruction it is, what the length of the instruction is and what the arguments are. Additionally it's good to know what architecture is the code running on, what CPU & is it x86, x64, ARM etc? Is it big endian or little endian? Also what platform are we using, is it Windows, Linux, Android etc...? All these are important on the low level side.

But lucky for us, there are tools that figure all this out for us and represent it in an easy to approach way. Your main tool for reverse engineering in terms of game hacking will be Cheat Engine. That's right everything you've been doing in Cheat Engine is reverse engineering, it just doesn't have they 1337 flare to it. Debuggers are used for reversing processes at runtime, disassemblers are used for static analysis, they take the bits and bytes and represent them in a way we can more easily understand.

This guide is rooted in x86 & x64 Windows game hacking but is relevant to all reverse engineering.

TLDR 4 steps to using this guide:
  1. Do the Start Here Guide
  2. Do the advanced reversing video tutorials by Rake (listed below)
  3. Learn more about assembly, registers, calling conventions & the stack
  4. Learn to hook & call game functions (use resources below)
The main tools you will use on your journey are:
  • Cheat Engine
  • ReClass.NET
  • x64dbg
  • Ida Pro
You might even sprinkle in some Ghidra & Binary Ninja


The rest of this guide requires that you have finished steps 1-11 of our main guide.
https://guidedhacking.com/starthere

This guide provides the foundation of knowledge that will move you into more advanced reverse engineering. It covers the most basic & common assembly instructions and usage of debuggers.



Once you've done the guide your next step will be to get more general experience reverse engineering, for that we have several videos that go a bit more in depth.

Game Hacking Reversing Tutorials in the order you should do them

  1. Read this thread below to learn about registers, assembly, calling conventions & the stack
  2. Guide - IDA Pro Beginner Guide
  3. Video Tutorial - How to Find CSGO NetVar Offsets Hacking Tutorial Ida Pro
  4. Video Tutorial - CSGO bDormant - How to find m_bDormant Offset Tutorial
  5. Video Tutorial - ClassInformer Tutorial - Run Time Type Information Tutorial - RTTI
  6. Video Tutorial - Reverse Engineering Tutorial - Assault Cube Recoil
  7. Video Tutorial - Reversing Engineering Fly Hack NoClip Cheat Engine IDA pro C++
  8. Video Tutorial - Reverse Engineering - How To Find the CSGO Entity List
  9. Video Tutorial - How to Find TraceLine & Call Traceline with Inline ASM
Other GH Reverse Engineering Videos

Advanced Reverse Engineering
After doing those videos you are ready to move onto Advanced Reverse Engineering. What do we mean by advanced reverse engineering?

Well with your current knowledge you can:
  • Find variables & pointers
  • Read & Write to addresses externally
  • Read & Write to addresses internally
  • understand basic assembly
  • Reverse Classes
But after making a few trainers, what's next?

ESP & Aimbot, duh!

These 2 features will require you to learn how to hook and call functions. You will need to hook graphic APIs to draw in game, and you will need to call the TraceLine() function to detect if enemies are visible.

But Rake, I barely know assembly!?!?
Honestly you only need to know ~10 instructions to do 50% of game hacking:
mov, lea, cmp, test, push, pop, call, ret, jmp/jne/je, xor, add, sub

Sure, you can read a bunch of books and tutorials and you can even learn how to make executables using FASM/MASM/NASM in pure assembly. But, as long as you understand the basic 10 instructions, you can figure the rest out as you go.

Many people, including myself just learned assembly as we went, if you are debugging an instruction you don't understand, just do a DuckDuckGo search.

Here are the top 3 best references for assembly:

How to learn assembly better?

Practice! First thing you can do is write your own simple C/C++ apps and reverse them.

Or pick any function in any simple game such as the health of ammo decrement function. Put a breakpoint at the top of the function. Step through every line of code, comment every line of code with what you think it does. Just keep stepping over each line and defining them. When you get to the last line, you will have a full understanding. I know this sounds insane, but it's an amazing learning experience. Be patient and you'll do just fine.

Be sure to look at the registers and the stack as you step over each line.

Registers
Most registers are now "general purpose" registers, but they each once had a specific purpose.

EAX = accumulator register for arithmetic such as adding/subtracting etc...
EBX = base register for indexing
ECX = counter register for keeping count of iterations
EDX = data register used in combination with EAX to do arithmetic

EIP = instruction pointer, this points to the current instruction that is executing
ESP = stack pointer
EBP = stack base pointer

ESI = source index register for string operations
EDI = destination index register for string operations

You will often see them used in the same capacity as they were originally intended, but it's not required, and with optimizations, the compiler will use whatever registers are the most efficient.

But what's all this AX, AL, RCX junk?
Those are different registers. EAX, ECX, EDX these are easy to understand 32bit registers. But it's easy to recognize the different sized register representations.

Using the example of RAX:
  • RAX is the 64bit extended version of EAX
  • EAX is the 32bit extended version of AX
  • AX was a 16bit register at the time when registers were 16bit
You can still easily breakdown a 64 bit register value in hexadecimal to it's smaller components.
  • RAX is the total 64 bits
  • EAX is the lower 32 bits
  • AX is the lower 16 bits
  • AH represents the high 8 bits of AX
  • AL represents the low 8 bits of AX
Therefore if your 64 bit register contains: A0B1C2D3E4F5A6B7
  • EAX = E4F5A6B7
  • AX = A6B7
  • AH = A6
  • AL = B7
You can identify this visually very easily by opening the Windows Calculator and setting it to Programmer mode, hexadecimal mode and a QWORD value. Paste in "A0B1C2D3E4F5A6B7", then click QWORD several times to change it's type progressively smaller to see it's truncated values at each stage.



More about registers:
https://www.tutorialspoint.com/assembly_programming/assembly_registers.htm


But Rake the stack is scary!
It sure can be, so let's break it down. Memory in the context of executing code has 4 classifications, the stack, the heap, code & the data segment which I kinda like to call "statically initialized data".

Code - Initialized at runtime and doesn't change. Modules like csgo.exe contain code that are static once loaded. This code exists on disk and can be resolved via relative offsets.

Data Segment - data that is initialized at the beginning of run time but the values these addresses contain can change, but many don't.

Heap - Dynamically created objects/variables are placed here. Using the "new" keyword in C++ allocates things on the heap, for efficiency reasons, these things don't need to exist on disk or in memory at runtime. They are created on demand when needed and deleted when no longer used.

Stack - this is the bit of memory (relatively small) that functions use for local variable storage.

The Stack
The stack is a part of memory that:
  • expands and shrinks as needed
  • is accessed in a "last in, first out" manner
  • represents local storage for functions
  • stores function arguments
  • stores return addresses
  • is used to preserve data in registers for later use
The Stack is actually a collection of stack frames. Each function has it's own stack frame. If function foo() calls bar() which calls snafu() and you're debugging snafu(), then foo and bar's stack frames are preserved in memory, but your current stack frame is currently defined by the ESP and EBP registers.

ESP = Extended Stack Pointer EBP = Extended Base Pointer

When a new function is to be called, the "function prologue" executes which preserves the previous stack frame, and sets up the stack frame for the next function. Depending on the calling convention it can be done by the caller or the callee, meaning before or after the "call" instruction executes.

Before the "function prologue" or "stack setup" occurs, ESP is pointing at the bottom of the current stack frame, when the setup occurs, EBP is made to point at the same location, and then ESP moves to a new position, which now represents the top of the next stack frame. So when a function prologue is completed, ESP points at the top of the current stack, and EBP points at the bottom of the current stack. The stack starts where ESP points and ends where EBP points. As you push and pop things onto the stack, the top of stack which ESP points to, moves. When you push onto the stack, it expands, when you pop, it shrinks.

RAKE THAT MAKES NO SENSE! Why is the bottom of the stack a bigger number than the top!?!? And why in the name of god is it expanding down the address range?!

DONT ASK ME JUST WATCH THE DAMN VIDEOS

Excellent article here by Daax
https://revers.engineering/applied-re-the-stack/

All that stack talk makes my brain explode. Let's move onto something nicer.

Calling Conventions
stdcall, cdecl, thiscall etc... maybe you've heard of them? These define how the stack setup occurs, how the arguments are passed to the callee, how the stack unwinds and how the function returns.

The caller = the function that executes the call instruction
The callee = the function which is called by the caller

The functional prologue typically looks like this:
Code:
push ebp
mov  ebp, esp
sub   esp, n
Where n = the number of bytes used by the function for local storage. EBP is pushed onto the stack, preserving the address of the previous stack, then EBP is made to point at ESP. Then ESP is moved, to expand the stack frame to allow enough space for local variables and arguments in the new stack frame.

The Function epilogue looks like:
Code:
mov esp, ebp
pop ebp
ret
EBP is made to point at ESP, then the old EBP is popped off the stack and back into ESP, essentially resetting the stack frame to what it was before the current function was called.

cdecl = caller unwinds the stack

stdcall = the callee unwinds the stack

thiscall = essentially a stdcall, in which the callee cleans the stack the only difference being the this pointer is stored in ECX. thiscall is used for member functions. Virtual Table functions use this calling convention.

fastcall = first 2 arguments are passed in ECX and edx, the rest are pushed on the stack. The stack is cleaned simply by a series of pops and then a ret.

More about calling conventions:

So now at this part of the guide, you've completed:
  • the Start Here Guide
  • the advanced reversing video tutorials by Rake (listed below)
  • Learn more about assembly, registers, calling conventions & the stack
The next step for you is to practice, spend a week practicing everything you've learned. Start reversing entire functions, figure out their calling convention, the number of arguments, their type and the return type. Get a firm understanding of the stack, stare the debugger for hours.

Feel a little lost?
Did you actually do every lesson? Did you really commit enough time? Go back and solidify your skills.

Sitting in the debugger for 4 hours at a time is completely normal part of game hacking.

But don't worry, the next steps are fun, learning:
  • How to call game functions
  • How to hook functions

Calling Game Functions

The next set of videos you need to watch are from @Traxin. For this part of the guide we will direct you to our pre-made guide. You will find Traxin's videos, with additional information including a bunch of good links here:

Guide - Guide on How to Call Game Functions


How to Hook functions

First, refresh your memory on external detouring: Video Tutorial - C++ Detour / Hooking Function Tutorial for Game Hacking

For this part, we don't have a tutorial or video yet. But to achieve internal hooking you typically want to use a trampoline hook, here is one for x86 based on Solaire's code:
C++:
bool Hook(char* src, char* dst, const intptr_t len)
{
    if (len < 5) return false;

    DWORD  curProtection;
    VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection);

    intptr_t  relativeAddress = (intptr_t)(dst - (intptr_t)src) - 5;

    *src = (char)'\xE9'; //truncation of constant values // "\xE9"
    *(intptr_t *)((intptr_t)src + 1) = relativeAddress;

    VirtualProtect(src, len, curProtection, &curProtection);
    return true;
}

char* TrampHook(char* src, char* dst, const intptr_t len)
{
    // Make sure the length is greater than 5
    if (len < 5) return 0;

    // Create the gateway (len + 5 for the overwritten bytes + the jmp)
    void* gateway = VirtualAlloc(0, len + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    //Write the stolen bytes into the gateway
    memcpy(gateway, src, len);

    // Get the gateway to destination addy
    intptr_t  gatewayRelativeAddr = ((intptr_t)src - (intptr_t)gateway) - 5;

    // Add the jmp opcode to the end of the gateway
    *(char*)((intptr_t)gateway + len) = 0xE9; //truncation? 0xe9

    // Add the address to the jmp
    *(intptr_t *)((intptr_t)gateway + len + 1) = gatewayRelativeAddr;

    // Place the hook at the destination
    Hook(src, dst, len);

    return (char*)gateway;
}
Here are a couple good sources with hooking in it:
Source Code - OpenGL SwapBuffers Hook Template Source Code
Source Code - D3D11 Barebones hook PoC
ELTraxo/dx9HookHelp


At this point I've been working on this for 3 days, so the rest of this guide will just be some notes regarding the direction we are going with the next one.

What's next?
So now you're an intermediate reverse engineer, you can call game function and you can hook them. What's next?

Refresh your C++ knowledge - LearnCPP.com
-is there something you didn't quite understand? Make sure you are up to speed.

Make an ESP in Direct3D
-Learn about World To Screen and view matrices

Make an aimbot
-learn more trigonometry

-Learn about PE File Format & Windows Loader
-Learn about Windows memory protections and layout
-Learn operating system mechanics, specifically windows

Additional Resources and Links
The Workshop | RE for Beginners
Discuss - Share Reverse Engineering Videos
Reverse Engineering and Program Understanding | Into the House of Logic
Debug Tutorial Part 2: The Stack
Debug Tutorial Part 3: The Heap
 

Attachments

Last edited:

h4nsbr1x

Full Member
Jul 24, 2020
7
198
0
These videos are useful and fun to watch. I've got some comments on function prologues and epilogues and some other asm stuff (from IDA tutorial 4)

Why are they pushing/popping all this stuff?

When you call a function you can expect some things to be left untouched (e.g. the stack, your wallet, your girlfriend) and other things are going to be used without your consent (e.g. memory south of the stack, Rake's mom). The convention for 32-bit apps is as follows:

EAX, ECX, EDX: assume these get overwritten after the call (EAX in particular is where the return value gets stored)
EBP, ESP, ESI, EDI: EBX: these must be preserved by the function

Argument Passing and Naming Conventions

Why these registers? Fun fact, in 16-bit days (pre-286) you could only dereference pointers in the BP, SP, SI, DI and BX registers (BX is the "general" register that can also be used for pointing to things), and it's expected that people would leave pointers lying around, whereas the others are fair game.

In 64-bit apps the convention is as follows:

RAX, RCX, RDX, R8, R9, R10, R11, XMM0-5, YMM0-5: assume these get overwritten (RAX is the return value, RCX/RDX/R8/R9 are your args)
RBP, RSP, RSI, RDI, RBX, R12, R13, R14, R15: these must be preserved by the function

x64 software conventions

So here's the typical prologue convention:

Code:
; prologue
push rbp ; save rbp (note this is more or less the same in 32 bit too)
mov rbp, rsp ; save rsp
sub rsp, 100 ; create space for local variables
and spl, 0xF0 ; 16-byte align
push rdi ; save if we use it
push rsi ; save if we use it
; ......   the compiler is only going to save registers if it wants to use them
And the epilogue matches up

Code:
pop rsi ; put it back
pop rdi ; tidy your room
mov rsp, rbp ; we did weird stuff to RSP so it's easier to copy from RBP
pop rbp ; put RBP back too


What is the "AND ESP, 0xFFFFFFF0 for"

In the tutorial there's this little line in the prologue that does an AND command on ESP:

Code:
and esp, 0xFFFFFFF0
In x64 it looks like this

Code:
and spl, 0xF0
These both do the same thing, they round the stack pointer down to the nearest 16 (RSP % 16 in C if you like). The reason they do this is because the processor can only read/write on aligned boundaries, whatever that means. In other words, if you want to read 4 bytes from 0x1230 that's fine, you can do that with a single MOV EAX, [0x1230], but if you try to read from 0x1231 it'll throw an exception when you do MOV EAX, [0x1231] (go and try it, I'll wait here). x32 has 8 byte FPU registers, and x64 has 16 byte XMM registers, so if your stack isn't aligned to the nearest 16 bytes there are some functions that will break when you call them and you'll lose hours trying to figure out what's wrong.




Why are ESI/RSI and EDI/RDI special?

Short answer is that it goes back to 8086 days. Long answer is that there are some optimised commands that use these. Here's some examples:

Code:
LODSB ; loads a byte from ESI/RSI into AL and increments it by one (char a = *(rsi++))
STOSB ; stores the byte from AL into ESI/RSI and increments it by one (*(rdi++) = a)
LODSW ; as above, but with words
LODSD
LOSDQ
STOSD
...
MOVSB ; this moves a byte from ESI/RSI to EDI/RDI and increments both by one
REP MOVSB ; this does a MOVSB, then decrements ECX/RCX, and if ECX/RCX isn't zero then it'll loop back on itself
You don't *have* to use these registers as you can dereference any pointer as a register, but the helper functions make these very useful. Here's a memcpy example:

Code:
lea rsi, input
lea rdi, output
mov rcx, input_length
rep movsb
As a result, you'll often find RSI/RDI pointing to strings or structures (or more likely, to the ends of them as they've probably recently been copied).


Other x64 craziness

Make yourself familiar with the x64 calling convention for windows: x64 calling convention

This confuses the shit out of me. In x32 you'd push all your arguments onto the stack in reverse order. In x64, you put your first 4 arguments in RCX,RDX,R8,R9, your other arguments then get pushed *in reverse* onto the stack. You also need to have already created 4 QWORDS of space on the stack because the called function is going to use that space and destroy your local variables otherwise. You also need to unwind the stack yourself (in x86 the stdcall convention does this for you).

So in win32 you'd do this:


Code:
push 0 ; arg 7
push FILE_ATTRIBUTE_NORMAL ; arg 6
push OPEN_EXISTING ; arg 5
push 0 ; arg 4
push 0 ; arg 3
push GENERIC_READ ; arg 2
lea eax, filename
push eax ; arg 1
call CreateFileA ; in MASM you can just do invoke CreateFileA, arg1, arg2 etc and that'll build this for you
Easy, no stack prep, no stack tidy. In x64 you have to do this:

Code:
; we need to create stack space for our first 4 args
; 4 * 0x8 = 0x20
; BUT we push 3 more args
; that's 0x38 which doesn't line up to 16 (0x10) bytes
; so we need to subtract 0x28 from RSP
; then when we push our last 3 args it'll round off to 0x40
; and halloween bill gates and steve ballmer won't eat us
lea rsp, [rsp-0x28] ; uses less bytes than sub rsp, 0x28
lea rcx, filename ; arg 1
mov rdx, GENERIC_READ ; arg 2
mov r8, 0 ; arg 3
mov r9, 0 ; arg 4
push 0 ; arg 7, stack is now 0x30 lower
push FILE_ATTRIBUTE_NORMAL ; arg 6, stack is 0x38 lower
push OPEN_EXISTING ; arg 5, stack is 0x40 lower
call CreateFileA
lea rsp, [rsp+0x40] ; reset stack
Doable, but annoying, and gives super weird bugs if you get something wrong.



Happy assembling kids!
 
Last edited by a moderator:
  • Like
Reactions: Kauv

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,540
78,998
2,312
"Find what writes to" on your Z coordinate, jump. Reverse the functions that modify your Z coordinate, somewhere in there you will find some sort of gravity calculation. You can also do the same thing on your velocity.Z
 

Mystic

Newbie
Full Member
Jan 21, 2017
42
2,393
1
for example ,how can i find the gravitational acceleration(gravity) in a 3D game?it's static,i can't find it with cheat engine.
it would depend on the game. For instance in Call of duty (at least in IW engine), that value is a DVAR and you can find it in cheat engine by using the in-game console to change g_gravity, and then search for the changed value(This is super easy *if* you can change the value using the ingame console). Otherwise, I think you will have to do what Rake suggested.
 

SunBeam

Full Member
Nobleman
Jun 7, 2018
63
1,273
2
I would first check if the game has a console available, by which I could change a CVar (or call it how you want), then search for it with Cheat Engine (when sequentially changing it). That doesn't make it that static anymore. Otherwise, the only means you have to get to it is what rake said: find your XYZ (there's plenty of methods to this) and backtrace from the instructions writing your Z. Yes, it's going to take a bit of analysis, it isn't that simple.

Another thing you can try is to determine where would this float/dword/double value be (which structure). Then find that structure in memory and make use of CE's exceptions breakpoints to break on a large selection. Then inspect each instruction that pops in the debug window ;) Quick way to debug a whole structure on read/write :p

The same applies for player speed and other "statics" used in game physics.
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,540
78,998
2,312
You guys thought I was done with the beginner's guide? Hell no.

I've finally got the time to follow through with my complete course on game hacking.

The idea is, a 3 chapter course. The Start Here Beginner's Guide was just part 1. This reversing guide ^ is part 2.

So the 3 chapter complete course will look something like:

1) Start Here Guide
  • Cheat Engine Basics & Pointers
  • Basic C++
  • GetModuleBaseAddress
  • C++ Multilevel Pointers - FindDMAAddy
  • Basic Windows API Functions
  • Basic external and internal trainers
  • Basic reversing
2) Reverse Engineering & Advanced Hacking Guide
  • Learn assembly at an intermediate level
  • Thorough understanding of the stack & calling conventions
  • How to call Game Functions
  • Detours & Hooking
  • Lots of Practice
3) Unknown Title - Chapter 3
  • 3D Game Programming
  • View Matrices & World To Screen
  • GDI, D3D9, D3D11 and OpenGL ESP
  • Trigonometry, CalcAngle & aimbot
  • Learn more about PE File Format, Windows Loader and Operating System Mechanics
  • Basics of Anti-Debug
4) Who knows, maybe 1 more chapter
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,540
78,998
2,312
anyone want to write a little section about flags? I forgot about them

Also notice I'm teaching advanced reverse engineering before coding ESP/aimbot? Doing 2 before 3 eliminates the need for pasting. Someone makes a thread about part 3 but didn't do part 2? reply with part 2 and close thread :brokeback:
 

Sy3kn0m

m0nk3ys
Dank Tier Donator
Sep 7, 2019
9
1,278
0

Your content is 15/10. Every guide of yours that I have followed has literally saved me who knows how many hours of googling.
From a complete beginners prospective when it comes to this I am amazed you have provided so much for free.
Keep up the amazing work! Hopefully one day I'll be able to release some sweets myself.
 

_Necros_

Newbie
Full Member
Oct 6, 2015
38
1,138
0
Damn i hope for the sake of Rake's mental health that people will now stop making threads asking for already answered or dumb questions like "how do i made hack, i copied this not workning"... or "how do i start"
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,540
78,998
2,312
It's a very good book, but it's huge. A book is a tool. If all you do is read it, you learn a few things but you don't learn how to be a reverse engineer. I suggest learning the basics, understand registers, stack & calling convention and then just jump into reversing some easy game functions.

Over the years I've heard the question many times "how to learn reverse engineering?" and what I think people don't understand is, everything you're doing in Cheat Engine is reverse engineering. People dumb down what they're doing to "finding values, finding pointers, finding instructions to NOP" but if you take it to the next level, you can reverse engineer the entire classes which contain the values, see how they are used by the game logic, define the structures which make up the multilevel pointer and discover how the game uses this pointer in it's logic and then to reverse engineer entire functions rather than just knowing you have to NOP one instruction.

Reverse engineering is kinda like when you start looking at the assembly organically instead of as collection of separate abstract pieces. When you become experienced at it, your intuition will carry you and the only way you get that is if you really get alot of practice.

The book is good if you learn well from reading a large textbook like this.

If you have ample experience coding, you just need to learn the registers, stack and calling convention and you can pretty much reverse anything.

After the beginner's guide, where you learn the basic I instruct people to do the next chapter:
https://guidedhacking.com/threads/beginners-guide-to-reverse-engineering-tutorial.13446/

In the videos in this guide ^ I show each step from start to finish, for instance I start with a health variable and end up with an entity list at the end
 
  • Like
Reactions: ReturNull

Deadhead

Trump Tier Donator
Dank Tier Donator
Jul 9, 2019
27
578
0
Dude this thread is amazing. Beginning to dismantling an older game complety, this helps so much!
Only my Ghidra's UI has the tenedency to completly break everytime after ~10min. ^^
 
  • Like
  • Haha
Reactions: Rake and Kleon742
Community Mods League of Legends Accounts