In this tutorial we will create a zoom hack for the game Banished. By default the game is quite limiting in its’ zoom options, you can zoom in & pan the camera around a bit, but I like to get up real close and see what’s going on down there 🙂
What you learn in this tutorial can be applied to other games as well, useful in some strategy games. So how is zoom hack achieved?
Let’s start by opening up the game and our trusty old pal Cheat Engine. Now in most situations like these there will be a float value with the amount you are zoomed/panned, so let’s start looking for that.
Now what you want to do is go in-game and either zoom in or zoom out, then you go back to Cheat Engine and search for either “Increased value” or “Decreased value”. Which is which? You will find out 🙂
Keep zooming in/out in-game and searching increased/decreased in Cheat Engine. Once in a while don’t zoom in game just move the camera around or other things, then search “Unchanged value”. That will weed out the “bad” values that are unrelated to zoom.
Eventually you will find a value that is 20 when max zoomed in and 130 when max zoomed out.
So what do we do now?
Right-click on it in the cheat table and “Find out what writes to this address” then zoom in in-game to the limit and keep pushing the zoom in button, then do the same thing with zooming out. You will find two instructions that set maximum/minimum value to the zoom when trying to go above/below it.
Digging into the code
Here’s a ASM dump of that
Application-steam-x64.exe+ED970 - F3 0F10 0D 6CED0700 - movss xmm1,[Application-steam-x64.exe+16C6E4] Application-steam-x64.exe+ED978 - 85 DB - test ebx,ebx Application-steam-x64.exe+ED97A - 74 3C - je Application-steam-x64.exe+ED9B8 Application-steam-x64.exe+ED97C - F3 0F10 47 3C - movss xmm0,[rdi+3C] Application-steam-x64.exe+ED981 - 7E 0A - jle Application-steam-x64.exe+ED98D Application-steam-x64.exe+ED983 - F3 0F5C 05 2DED0700 - subss xmm0,[Application-steam-x64.exe+16C6B8] Application-steam-x64.exe+ED98B - EB 08 - jmp Application-steam-x64.exe+ED995 Application-steam-x64.exe+ED98D - F3 0F58 05 23ED0700 - addss xmm0,[Application-steam-x64.exe+16C6B8] Application-steam-x64.exe+ED995 - 0F2F C8 - comiss xmm1,xmm0 Application-steam-x64.exe+ED998 - F3 0F11 47 3C - movss [rdi+3C],xmm0 Application-steam-x64.exe+ED99D - 76 09 - jna Application-steam-x64.exe+ED9A8 Application-steam-x64.exe+ED99F - C7 47 3C 0000A041 - mov [rdi+3C],41A00000 Application-steam-x64.exe+ED9A6 - EB 10 - jmp Application-steam-x64.exe+ED9B8 Application-steam-x64.exe+ED9A8 - 0F2F 05 89ED0700 - comiss xmm0,[Application-steam-x64.exe+16C738] Application-steam-x64.exe+ED9AF - 76 07 - jna Application-steam-x64.exe+ED9B8 Application-steam-x64.exe+ED9B1 - C7 47 3C 00000243 - mov [rdi+3C],43020000 Application-steam-x64.exe+ED9B8 - F3 0F10 57 44 - movss xmm2,[rdi+44]
Let’s dig into it!
movss xmm1,[Application-steam-x64.exe+16C6E4] - 20.0 float (minimum zoom)
Loads the minimum zoom value into xmm1 register
Load current zoom value into xmm0 register
Decrease zoom by 5.0, this is for when we zoom in
Increase zoom by 5.0, this is for when we zoom out
Compare current zoom value to the minimum allowed zoom
Set the new zoom value
JNA (Jump if Not Above)
If the current zoom value is above the minimum allowed zoom value, jump away. Otherwise run the next instruction:
mov [rdi+3C],41A00000 jmp Application-steam-x64.exe+ED9B8
Sets zoom to minimal value (20 float) and then jumps away.
0xA041 is 20 in float value.
Compares current zoom value to the maximum allowed zoom value (130)
If the current zoom value is not above the maximum allowed zoom value, jump away. Otherwise run the next instruction:
Set zoom to maximum value (130 float)
0x0243 is 130 in float value.
This teaches us that zoom factor/value is at 0x3C into some class. This can be a good start for reversing that class (probably a camera class where you can find FOV, camera position etc.) if you are interested in that.
So! Now how do we make it so we can zoom in as close as we want to or as far away as we want? There are many different solutions to this. Let’s look at a couple.
First method for unlimited zoom hack
First of all we could eliminate the two operations that force the zoom value, namely these two
NOP those out (‘Replace with code that does nothing’ in Cheat Engine) and that will do the trick.
Second method for unlimited zoom hack
More interestingly would be to patch one of the jumps to avoid the checks altogether.
76 09 - jna Application-steam-x64.exe+ED9A8 C7 47 3C 0000A041 - mov [rdi+3C],41A00000 EB 10 - jmp Application-steam-x64.exe+ED9B8 0F2F 05 89ED0700 - comiss xmm0,[Application-steam-x64.exe+16C738] 76 07 - jna Application-steam-x64.exe+ED9B8 C7 47 3C 00000243 - mov [rdi+3C],43020000 F3 0F10 57 44 - movss xmm2,[rdi+44]
If we would change the first JNA to a JMP and change it to go all the way down to the movss, then it would avoid the checks 🙂
Current the JNA has the bytes 76 09, 76 is the instruction JNA (short). The instruction JMP (short) is EB, so we start by changing the bytes to EB 09.
Now we have a jump instruction that looks like this
EB 09 - jmp Application-steam-x64.exe+ED9A8
Hmm, that’s no good tho, it will jump to before the next check! So let’s change the distance too.. how can we do that?
The second byte of the instruction is 09. It is the distance in bytes of how far the jump should be! We want our jump to go down to the movss so we need to jump an additional 0x10. Hence we change the 09 to 19!
Now the complete instruction is EB 19 instead of the original 76 09
EB 19 - jmp Application-steam-x64.exe+ED9B8
Now our jump goes all the way down to the movss instruction, skipping the code that would have limited our zoom. Our zoom hack is ready! 🙂
Hacking camera panning
Now, as an added bonus; if we scroll up a little bit in the code we find this area:
FF 15 F3BD0500 - call qword ptr [Application-steam-x64.exe+149730] 84 C0 - test al,al 74 12 - je Application-steam-x64.exe+ED953 F3 0F10 47 44 - movss xmm0,[rdi+44] F3 0F5C 05 BEEC0700 - subss xmm0,[Application-steam-x64.exe+16C60C] F3 0F11 47 44 - movss [rdi+44],xmm0 44 0F2F 5F 44 - comiss xmm11,[rdi+44] 76 04 - jna Application-steam-x64.exe+ED95E 44 89 67 44 - mov [rdi+44],r12d F3 0F10 47 44 - movss xmm0,[rdi+44] 41 0F2F C4 - comiss xmm0,xmm4 76 07 - jna Application-steam-x64.exe+ED970 C7 47 44 0000803F - mov [rdi+44],3F800000 F3 0F10 0D 6CED0700 - movss xmm1,[Application-steam-x64.exe+16C6E4] 85 DB - test ebx,ebx 74 3C - je Application-steam-x64.exe+ED9B8 F3 0F10 47 3C - movss xmm0,[rdi+3C] 7E 0A - jle Application-steam-x64.exe+ED98D F3 0F5C 05 2DED0700 - subss xmm0,[Application-steam-x64.exe+16C6B8]
This is where the game limits the camera panning.
As an exercise I suggest you figure out how that works and how you can patch it to achieve unlimited camera panning too! 😉
Now we can finally see their tiny, pixelated faces up close and personal