Video Tutorial How to Hack Any Game Tutorial C++ Trainer #2 - External v2

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,538
78,998
2,312
This is our last beginner external tutorial. I just wanted to go over a few more things before going to our internal tutorial. So in this video we'll be taking our last C++ external trainer code and re-doing int main() and adding some new functionality.

We will go over:
  • precompiled headers
  • Hack loop
  • Getting Key Input
  • Patching bytes
  • nopping instructions
  • continuous write aka freezing
Hacks we will make:
  • health
  • ammo
  • recoil


If you're following along with the tutorial, download the previous source code from How to Hack Any Game Tutorial C++ External Trainer "Part 2"
The Cheat Table and the new code can be downloaded from the attachment in this thread.




Tutorials referenced in this video that you should do first:
  1. START HERE Beginners Guide to Learning Game Hacking - Guided Hacking
  2. Cheat Engine How To Hack Any Game [1/10 Difficulty] [Part 1/2] - Guided Hacking
  3. How to Hack Any Game Tutorial C++ External Trainer "Part 2" - Guided Hacking
  4. Reverse Engineering Tutorial - Assault Cube Recoil - Guided Hacking
MSDN pages referenced in the video:
GetExitCodeProcess function
GetAsyncKeyState function

Here's some sample code:

C++:
int main()
{
    HANDLE hProcess = 0;

    uintptr_t moduleBase = 0, localPlayerPtr = 0, healthAddr = 0;
    bool bHealth = false, bAmmo = false, bRecoil = false;

    const int newValue = 1337;

    //Get ProcId of the target process
    DWORD procId = GetProcId(L"ac_client.exe");

    if (procId)
    {
        //Get Handle to Process
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, procId);

        //Getmodulebaseaddress
        moduleBase = GetModuleBaseAddress(procId, L"ac_client.exe");

        //Resolve address
        localPlayerPtr = moduleBase + 0x10f4f4;

        //Resolve base address of the pointer chain
        healthAddr = FindDMAAddy(hProcess, localPlayerPtr, { 0xF8 });
    }
    else
    {
        std::cout << "Process not found, press enter to exit\n";
        getchar();
        return 0;
    }

    DWORD dwExit = 0;
    while (GetExitCodeProcess(hProcess, &dwExit) && dwExit == STILL_ACTIVE)
    {
        //Health continuous write
        if (GetAsyncKeyState(VK_NUMPAD1) & 1)
        {
            bHealth = !bHealth;
        }

        //unlimited ammo patch
        if (GetAsyncKeyState(VK_NUMPAD2) & 1)
        {
            bAmmo = !bAmmo;

            if (bAmmo)
            {
                //FF 06 = inc [esi]
                mem::PatchEx((BYTE*)(moduleBase + 0x637e9), (BYTE*)"\xFF\x06", 2, hProcess);
            }

            else
            {
                //FF 0E = dec [esi]
                mem::PatchEx((BYTE*)(moduleBase + 0x637e9), (BYTE*)"\xFF\x0E", 2, hProcess);
            }
        }

        //no recoil NOP
        if (GetAsyncKeyState(VK_NUMPAD3) & 1)
        {
            bRecoil = !bRecoil;

            if (bRecoil)
            {
                mem::NopEx((BYTE*)(moduleBase + 0x63786), 10, hProcess);
            }

            else
            {
                //50 8D 4C 24 1C 51 8B CE FF D2; the original stack setup and call
                mem::PatchEx((BYTE*)(moduleBase + 0x63786), (BYTE*)"\x50\x8D\x4C\x24\x1C\x51\x8B\xCE\xFF\xD2", 10, hProcess);
            }
        }

        if (GetAsyncKeyState(VK_INSERT) & 1)
        {
            return 0;
        }

        //Continuous write
        if (bHealth)
        {
            mem::PatchEx((BYTE*)healthAddr, (BYTE*)&newValue, sizeof(newValue), hProcess);
        }

        Sleep(10);
    }

    std::cout << "Process not found, press enter to exit\n";
    getchar();
    return 0;
}
 

Attachments

Last edited:

Celmos

Trump Tier Donator
Nobleman
Sep 1, 2016
86
1,203
0
Great work as always(y). I´m excited for when these tutorials go a little bit more advanced.
 
  • Like
Reactions: Neku

SUWEDO

Full Member
Nov 23, 2018
9
54
0
Hey, i've got a problem here,

C++:
  if (bAmmo)


            {
                //FF 06 = inc [esi]
                mem::PatchEx((BYTE*)(moduleBase + 0x637e9), (BYTE*)"\xFF\x06", 2, hProcess);
            }
I can't seem to find how you found the address (0x637E9), i've searched on Cheat Engine and found only 0x4637E9 but not the one you wrote, so I decided to run the code with the one I found but it crashes, with yours it works.
Could you help me with that please ?

EDIT: I've found, my bad 0x4637E9 is ac_client.exe module base + 0x637E9 so I just had to do 0x4637E9 - ac_client.exe module base to get 0x637E9, Sorry, I hope this will help to others who didn't understand tho.
 
Last edited:

bigdaddy1337

Dank Tier Donator
Jul 19, 2019
30
1,338
0
Nice tutorial! I am also new to game hacking i did this tutorial.
For those who want to make the similar but with a different task i did a knife rapid attack as an exercise for myself.

For the guys who also want to try it here are the steps:
- Find Knife Time Pointer
- Find the area where the pointer is writing
- Nop this section
- Write a thread with a bind which spams left clicks

Code:
If Statement in the cheat loop
C++:
if (GetAsyncKeyState(VK_NUMPAD4) && 1) {
            bRapidKnife = !bRapidKnife;

            if (bRapidKnife) {
                mem::NopEx((BYTE*)(moduleBase + 0x64514), 2, hProcess);
            }
            else {
                mem::PatchEx((BYTE*)(moduleBase + 0x64514), (BYTE*)"\x89\x0A", 2, hProcess);  
            }

        }
Starting the thread function
C++:
std::thread t1(mouseTask);
The thread function, the bind for the rapid attack is "F", activating the hack is NUMPAD4
C++:
#define KeyDown(Key) (GetAsyncKeyState(Key) & 0x8000)
void mouseTask() {
            POINT p;
            for (; KeyDown(VK_NUMPAD5) == NULL; Sleep(5))
            {
                if (KeyDown(0x46))
                {
                    GetCursorPos(&p);
                    mouse_event(MOUSEEVENTF_LEFTDOWN, p.x, p.y, 0, NULL);
                    Sleep(50);
                    mouse_event(MOUSEEVENTF_LEFTUP, p.x, p.y, 0, 0);
                    Sleep(50);
                }
            }
}
i got this for loop of another tutorial

I did keep it simple so to upgrade it you could code a deactivator and starter bind for the thread. At this moment i started it before the cheat loop and it will end by NUMPAD5 and can't started in this session anymore
 

Lukor

ded
Meme Tier VIP
Fleep Tier Donator
Dec 13, 2013
441
3,978
24
So much pasta...
You could say that next time you post everything except the coders prints.

PS: In case you can not find the tutorial you past'd from... Its by Vincent Dominguez on mpqh
 
  • Like
Reactions: bigdaddy1337

sayewivifi

Full Member
Feb 2, 2019
39
228
0
Hey, i've got a problem here,

C++:
  if (bAmmo)


            {
                //FF 06 = inc [esi]
                mem::PatchEx((BYTE*)(moduleBase + 0x637e9), (BYTE*)"\xFF\x06", 2, hProcess);
            }
I can't seem to find how you found the address (0x637E9), i've searched on Cheat Engine and found only 0x4637E9 but not the one you wrote, so I decided to run the code with the one I found but it crashes, with yours it works.
Could you help me with that please ?

EDIT: I've found, my bad 0x4637E9 is ac_client.exe module base + 0x637E9 so I just had to do 0x4637E9 - ac_client.exe module base to get 0x637E9, Sorry, I hope this will help to others who didn't understand tho.
how do you get that 0x637e9 ?
 

sayewivifi

Full Member
Feb 2, 2019
39
228
0
you are taught how to do this in the first 1 minute and 30 seconds of this video, the video you just replied to...



seriously wtf
sorry i mean i saw it is written on the cheat engine ac_client.exe+637e9

but I am not able to understand that part, we have the offset (374,14,0), do I add those offsets with something to get the 637e9? My question is how that 637e9 is derived.

Thanks
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,538
78,998
2,312
sorry i mean i saw it is written on the cheat engine ac_client.exe+637e9

but I am not able to understand that part, we have the offset (374,14,0), do I add those offsets with something to get the 637e9? My question is how that 637e9 is derived.

Thanks
Do the guide, do each video in order. This is how you learn. If you skip the first videos, you won't understand the following ones.

https://guidedhacking.com/threads/start-here-beginners-guide-to-learning-game-hacking.5911/

Maybe this will help too
 

VoidHVH

Full Member
Oct 20, 2019
9
22
0
Hello, I know this is an old thread so sorry if I had to comment here. Delete my comment if it breaks any rules. But I have some questions.

First, why did we have to use Nop? Can't WPM achieve the same result? Am I missing something?

Second, where did \xFF\x06 or \x50\x8d\x4c\x24\x1c\x51\x8b\xce\xff\xd2 come from? And what is inc/dec [esi]? Do I have to learn reversing to understand that? Did I miss anything on the previous vids?

Thanks :)
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,538
78,998
2,312
Hello, I know this is an old thread so sorry if I had to comment here. Delete my comment if it breaks any rules. But I have some questions.

First, why did we have to use Nop? Can't WPM achieve the same result? Am I missing something?

Second, where did \xFF\x06 or \x50\x8d\x4c\x24\x1c\x51\x8b\xce\xff\xd2 come from? And what is inc/dec [esi]? Do I have to learn reversing to understand that? Did I miss anything on the previous vids?

Thanks :)
this is a video tutorial which explains the entire thing, watch it
 
Last edited:
  • Love
Reactions: VoidHVH

nacho

Full Member
Jan 13, 2020
7
108
0
Hey, I've been going through the beginner tutorial and it's been great. Just thought I'd clarify the bit-wise & as it's something I spent a bit of time learning.
The & operator checks the corresponding bits of two values and if they're both 1, then the corresponding bit in the result is set to 1 - otherwise it's set to 0.
E.g:
C++:
(5 & 3):   1 0 1
        &  0 1 1
        ----------
        =  0 0 1
GetAsyncKeyState returns a SHORT (16bit integer) with the most significant bit 1 if the key is pressed and the least significant bit 1 when it is pressed for the first time (pressed when it was not pressed the last time the function was called).

So by doing (GetAsyncKeyState(KEY_CODE) & 1) we're actually doing:
C++:
(returnVal & 1):   X (14 zeros) Y
                &  0 (14 zeros) 1
                ------------------
                =  0 (14 zeros) Z
Y will be 1 when you press the key for the first time so the result (Z) will be 1 and the if statement will be evaluated. When the key is held down, the Y bit changes back to zero until the key is released and pressed again.

You can also check if the key is down (regardless of whether it's the first time its pressed) by doing (GetAsyncKeyState(KEY_CODE) & 0x8000). As 0x8000 is the MSB of a 16bit int (i.e. this will test the X bit above.

Hopefully this helps some other noob understand :)
 
Last edited:

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,538
78,998
2,312
I find your explanation actually to be more confusing because you used XYZ and not a full binary representation, so I'm gonna clarify your clarification :)

"if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState"
- GetAsyncKeyState function (winuser.h) - Win32 apps


the LSB is only set if it's the first time it's been pressed since the previous calls to GASKS, therefore the LSB being set represents a button that has just been pressed, not held down.

We don't care about any other value besides the LSB in this situation so all other bits will be set to 0 in this example

0000 0000 0000 0000
0000 0000 0000 0001

If you do a bitwise and on these values you get 0, which is false

if the key is down, the LSB will be set:
0000 0000 0000 0001

in our if statement we AND it with:
0000 0000 0000 0001

therefore:

0000 0000 0000 0001
AND
0000 0000 0000 0001

= 1 = true

- O.2 — Bitwise operators | Learn C++

"Logical AND evaluates to true if both the left and right operand evaluate to true. Bitwise AND evaluates to true (1) if both bits in the column are 1. Consider the expression 0b0101 & 0b0110. Lining each of the bits up and applying an AND operation to each column of bits"
 
Last edited:

nacho

Full Member
Jan 13, 2020
7
108
0
0000 0000 0000 0000
0000 0000 0000 0001

If you do a bitwise or on these values you get 0, which is false
What are you saying here what does OR have to do with this? What's the top number and what's the bottom? Also 0 | 1 is 1 not 0. Not trying to be an a-hole it just confused me - is there a typo?

And I do have a different unrelated question:
How does this cast for the source work?: (BYTE*)"\xFF\x06" from mem::PatchEx((BYTE*)(moduleBase + 0x637e9), (BYTE*)"\xFF\x06", 2, hProcess);

I understand that the destination is just a pointer to the first byte to patch in memory. But the second cast isn't casting an address - does this cast create a pointer to the first of the 2 bytes? And if so where are these two bytes in memory? I would have thought we'd need to declare some variable of a type that's 2 bytes in size (like int16 or SHORT) and then assign it the value 0xFF06 and then pass a pointer to that. Like:

C++:
SHORT bytesToPatch = 0xFF06;
mem::PatchEx((BYTE*)(moduleBase + 0x637e9), (BYTE*)&bytesToPatch, 2, hProcess);
 
Last edited:

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,538
78,998
2,312
is there a typo?
Yeah I fixed it thanks


How does this cast for the source work?: (BYTE*)"\xFF\x06" from mem::PatchEx((BYTE*)(moduleBase + 0x637e9), (BYTE*)"\xFF\x06", 2, hProcess);

I understand that the destination is just a pointer to the first byte to patch in memory. But the second cast isn't casting and address - does this cast create a pointer to the first of the 2 bytes? And if so where are these two bytes in memory? I would have thought we'd need to declare some variable of a type that's 2 bytes in size (like int16 or SHORT) and then assign it the value 0xFF06 and then pass a pointer to that. Like:

C++:
SHORT bytesToPatch = 0xFF06;
mem::PatchEx((BYTE*)(moduleBase + 0x637e9), (BYTE*)&bytesToPatch, 2, hProcess);
"\xFF\x06" is a string literal, at compile time all string literals are typically placed in the data section like any other const string, so it would probably be found where all the other strings are for this file.

a string literal, a const char array is accessed via a pointer, so we're just casting a "const char*" to a "BYTE*" to match the argument type of the PatchEx function. when this is compiled "\xFF\x06" is just replaced by a pointer to the string

using a string literal is preferred when you're writing shellcode, as it's obvious exactly what it is when looking at it, and you don't have to think about little endian or little endian confusion and it's 1 less line of code
 
  • Like
Reactions: nacho
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Community Mods League of Legends Accounts