[TUT] How to code your own ZoomHack in your games ! (pictures + detailed)

04/26/2012 18:34 Spl3en#1
Hello,

[Only registered and activated users can see links. Click Here To Register...]

Introduction
I'm going to introduce to you some tools to code your own Zoom Hack.

I will use "League Of Legends" for this example, but you can reproduce those steps with any other games. That should work similarly.

We will need :
> CheatEngine (free : [Only registered and activated users can see links. Click Here To Register...])
> League Of Legends in game client
> A langage which is able to use win32 API. (C, C++ or C# are the most common languages for that, there is some extensions for the other langages as lua, python, perl, etc., look for it on google)


Zoom Value
First of all, open a custom game with a smurf account, so you can do everything without disturb anything.
Go in the settings window, and change settings to set your client in windowed mode with the minimal resolution. We are going to switch very often between the LoLClient and CheatEngine, so it will be more comfortable.
[Only registered and activated users can see links. Click Here To Register...]


Alright, we are ready to work.
Let's open CheatEngine, and open the League Of Legends.exe process.
[Only registered and activated users can see links. Click Here To Register...]

The first step will be to find the zoom value.
Let's talk this value; We know some facts about it :
(1)- We don't know its exact value.
(2)- When we zoom out, its value increase
(3)- When we zoom in, its value decrease
(4)- Even when we move the camera, its value doesn't change

CheatEngine is a very powerful tool that will find for you any value in the memory of a process.
All you have to do is to find a way to tell to CheatEngine how the variable you are looking for is modified.
If you don't understand this, don't worry, you will understand with the following example :

First of all, go to your LoLClient, and zoom in, the most as you can.
Go back to scan all the variables with the setting "Unknown initial value" (1).
[Only registered and activated users can see links. Click Here To Register...]

Then, go back to your client, and zoom out just a little.
Now, go back to CheatEngine, and do a "Next Scan" with the setting "Increased value" (2).

[Only registered and activated users can see links. Click Here To Register...]

As you can see, there is +1,000,000 results, and we still don't know what is the value of our zoom.
Repeat this process (zoom out, scan decreased value) 5 or 6 times so we filter more values.

Now we get something like that :
[Only registered and activated users can see links. Click Here To Register...]

Still 5,000+ results. This is not good yet. Now, reverse the process :
Zoom in a bit, and scan "Decreased value" (3). Repeat that 5 or 6 times again.

[Only registered and activated users can see links. Click Here To Register...]

Now as you can see, when you zoom in / zoom out, you can see the values increasing or decreasing correctly, but there is still a lot of results (147 here, but it may differs everytime you launch a game)

Notice that if you try to move the camera position, some of those values will be modified; We don't want to work with those values, they are related with the zoom, but they are not the zoom value.
To filter them, move your camera position, but *dont touch the zoom*, and do a next scan with the setting "Unchanged Value" (4).

[Only registered and activated users can see links. Click Here To Register...]
Only 14 results, with 2 differents values!
Let's try to change the value of the variable at the address 00B475A0, from 1148846080 to 1168846080.

[Only registered and activated users can see links. Click Here To Register...]
Victory ! We got the address and the current value of our zoom.
But if you try to zoom in / zoom out in the client, you will see that it doesn't work.
Why ? Because we only modified the *current zoom* value, but not the variable which defines what is the *maximum zoom* value allowed.

Max Zoom Value
Somewhere in the code, there is a variable defining the maximum value of the zoom.
All we have to do for finding it, is to zoom out the most possible to find the value of the max zoom.

[Only registered and activated users can see links. Click Here To Register...]
Now we know that "1158455296" is the value of the max zoom, let's do a new scan of this value with the setting "Exact Value".

[Only registered and activated users can see links. Click Here To Register...]

We find our zoom address at 00B475A0, but also a new one at 00B38C48 !
This is our Max Zoom address. You can modify it to something like 1168455296, go back to your client, and enjoy the unlocked zoom.


Coding
Even if we got the address of the maxzoom, this address may change everytime you launch the game, and probably when a new patch is released.
We don't want to launch CheatEngine everytime we want to hack the zoom, so we are going to code something for that.

How to do that ?
In the memory, some bytes around the max zoom value *never change* everytime you play a game. We will call those bytes the "pattern".

Basically, all we have to do is to parse the memory of League Of Legends.exe, find the pattern, so we got the address of our max zoom.

First of all, we have to get a correct pattern.
Right click on the address of the current value (00B475A0), and chose "Browse this memory region".

[Only registered and activated users can see links. Click Here To Register...]

It will opens a new window of the dump of the current memory at this address.

Keep a look at this window, and, in the client, try to zoom in / zoom out : The values in the dump will be colored in red when they change:

[Only registered and activated users can see links. Click Here To Register...]

It seems that only 3 bytes are modified, all the other are always the same when we play.
Let's keep a track of those bytes : select them, and copy them in notepad.

[Only registered and activated users can see links. Click Here To Register...]

Do the same thing for the max value address (00B38C48).

[Only registered and activated users can see links. Click Here To Register...]

We got that :
Code:
Zoom Value (00B475A0) : 00 40 CE 44 34 4B A3 00 18 9C A7 00 04 9C A7 00 00 00 00 00 24 4B A3 00 5C 9C A7 00 20 9C A7 00
Max Value  (00B38C48) : 00 A0 0C 45 25 24 59 46 00 00 70 41 00 00 FA 43 01 00 00 00 00 00 60 42 00 00 34 43 00 00 80 3E
We got everything we need. Now we need to code something.

We need to :
- Open the League Of Legends.exe process
- Write our new max zoom value at the right address

There is a lot of manners to do it.
I will chose the simpliest one :

1- Get the handle of the window
2- Get the pid of the process
3- Open that process
4- Get the address of max zoom with the pattern
5- Modify the memory at this address

Code:
int pid;
HWND window = FindWindowA(NULL, "League of Legends (TM) Client")); // 1
GetWindowThreadProcessId(window, &pid); // 2
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); // 3
The difficultiest part is 4 and 5.
We need a pattern finding function.

I use this one, feel free to copy it (this is a well known piece of code that you can find everywhere on internet)

Code:
DWORD
find_pattern_process (HANDLE process, DWORD start, DWORD end, unsigned char *pattern, char* mask)
/*
*	Exemple :
*	char *pattern = "\x00\xC0\xB7\x44\x00\xC0";
*	DWORD address = find_pattern_process(process, 0x800000, 0xC00000, (PBYTE) pattern, "xxx??x");
*/
{
    DWORD size = end - start;
    unsigned char *buffer = (unsigned char *) malloc(size + 1);

	if (ReadProcessMemory(process, (PVOID) start, buffer, size, NULL) == FALSE)
	{
		warning("ReadProcessMemory failed.");
		return 0;
	}

	else
	{
		DWORD address = find_pattern(buffer, size, pattern, mask);

		if (address)
			return start + address;
	}

    return 0;
}

int
compare_pattern (const unsigned char *buffer, const unsigned char *pattern, const char *mask)
{
    for (;*mask;++mask, ++buffer, ++pattern)
	{
		if (*mask == 'x' && *buffer != *pattern)
            return 0;
	}

    return (*mask) == 0;
}

DWORD
find_pattern (const unsigned char *buffer, DWORD size, unsigned char *pattern, char *mask)
{
    for (int i = 0; i < size; i ++)
	{
		if (compare_pattern((buffer + i), pattern, mask))
            return i;
	}

    return 0;
}
It works like that :
- You have to create a mask (x = i want to find the same byte, ? = I don't care about this one)
- You create a buffer containing your pattern.

So, for our example, if we want to find the max zoom address:

Code:
DWORD
get_max_zoom_offset (HANDLE process)
{
	char *mask = "????xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
	char *pattern = "\x00\xA0\x0C\x45\x25\x24\x59\x46\x00\x00\x70\x41\x00\x00\xFA\x43\x01\x00\x00\x00\x00\x00\x60\x42\x00\x00\x34\x43\x00\x00\x80\x3E";

	return find_pattern_process(process, 0x800000, 0xC00000, (PBYTE) pattern, mask);
}
The first 4 bytes are the value of the max zoom; we will modify it, so if we want its address even when it is modified, we have to put some "????" in the mask so thoses bytes aren't important for the pattern finding.


Now that we got the address, all we have to do is to write at this address.

I use this function to write an int in a process at a chosen address :

Code:
int
write_memory_as_int (HANDLE process, DWORD address, unsigned int value)
{
	unsigned char buffer[sizeof(int)];
	DWORD bytes_read;

	int32_to_bytes(value, buffer);

	if (!WriteProcessMemory(process, (PVOID) address, buffer, 4, &bytes_read))
	{
		warning("WriteProcessMemory failed.");
		return 0;
	}

	return 1;
}
So all I have to do is :

Code:
int pid;
HWND window = FindWindowA(NULL, "League of Legends (TM) Client")); // 1
GetWindowThreadProcessId(window, &pid); // 2
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); // 3
DWORD max_zoom = get_max_zoom_offset(process); // 4
write_memory_as_int(process, max_zoom, 1168455296)); // 5
Remember, 1168455296 is the new value of our max zoom.

And here is it !
Now everytime you have a League Of Legends.exe opened and in game, if you launch this program, it will find, and patch for you the zoom max value !

Of course, this tutorial is only about League Of Legends, but as I said, the process is similar for the other games.
- Find the current zoom value
- Zoom out
- Find the max zoom value
- Patch it.


Enjoy !
04/28/2012 11:25 BlackPlane#2
Nice and great turorial! Very well written. Easy to understand!
05/06/2012 09:48 Spl3en#3
Thank you for your answer.
Nobody seems to reply, so I wasn't sure if this tutorial was useful here.
06/09/2012 21:41 CcBrown#4
Thats pretty awesome, im wondering aswell why nobody seems to answering here.
I couldnt compiled the code it shows some errors.. but i try it with cheat engine and find some other interesting stuffs. Could you maybe send me a ready version of the source?
08/06/2012 19:49 Spl3en#5
Hi CcBrown
Sorry for the late answer.
Thank you for the feedback, I appreciated it!

You can find a "ready version" of the source on my repository, here :
[Only registered and activated users can see links. Click Here To Register...]

I use GCC for compiling it. (Try [Only registered and activated users can see links. Click Here To Register...] if you don't want to setup anything)

I can zip the entire project, librairies and DLLs :
[Only registered and activated users can see links. Click Here To Register...]

I use these custom parameters for my project :
-fgnu89-inline -std=gnu99

These librairies are linked :
psapi
pthread
wsock32

Everything should compile well with that options.
08/07/2012 01:44 DumbassIsKing#6
Very good tutorial :handsdown:
08/07/2012 16:08 F.Gump#7
Danke, genau das braucht man :rolleyes:

Hoffentlich gibts bald mehr von dir
08/08/2012 16:08 Crystal M0th#8
Nice tutorial, and its working for me. Thanks