[Asm] Codecaving tutorial
Codecaving tutorial
Codecaving is, basically, to put a jump before a target offset that needs to be patched to an empty or unimportant zone in memory, put your modified code there, and then jump back under the target address.
What's the point of doing this?
Codecaving allows you to get the effects of modifying an offset that could be blacklisted by poor anti-cheat software (ex: Warden in Warcraft 3), since you never modify it directly.
You could therefore take the offsets of some hack and make them almost "undetectable" (considering you keep that hack private or simply for yourself).
Pseudo example:
Before the code cave and patching:
- 1 Address 1 and its content
2 Target
3 Address 3 and its content
4 Unimportant stuff
5 Unimportant stuff
6 Unimportant stuff
(Unimportant stuff is mostly 00's and INT3's)
After the Code cave and patching:
- 1 JUMP to address 4
2 Target
3 Address 3 and its content
4 Address 1's content
5 Patched target
6 JUMP back to address 3
As you can see, the target code is still being patched, but not at Address 5 instead of Address 2.
Let's do a codecave now!
Things you will need:
- An offset to patch
- A real-time debugger (OllyDBG)
For this example, we are going to use some stupid offset I found while offset-hunting in Warcraft 3:
6F39B991 BA 08000000 MOV EDX,8
to
6F39B991 BA 00000000 MOV EDX,0
Effect: Removes ground textures (ground becomes all black).
Let's analyze the bunch of code over that address. Open up Warcraft 3 and get in a custom game. Then start OllyDBG and attach war3.exe, then right click -> go to -> 6F39B991 or CTRL+G -> 6F39B991 (you may need to do this twice to get to the address).
We must first find some empty memory zone in which we will input our code.
By scrolling down to the end of Game.dll, I found out this neat little place:
6F85BE24 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE26 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE28 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE2A 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE2C 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE2E 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE30 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE32 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE34 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE36 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE38 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE3A 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE3C 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE3E 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE40 0000 ADD BYTE PTR DS:[EAX],AL
6F85BE42 0000 ADD BYTE PTR DS:[EAX],AL
etc.
Then let'a go back to our target address, 6F39B991, and analyse what's around it.
6F39B974 8D4C24 24 LEA ECX,DWORD PTR SS:[ESP+24]
6F39B978 E8 E3A8C7FF CALL Game.6F016260
=> 6F39B97D E8 1E50C7FF CALL Game.6F0109A0
6F39B982 39AE 30030000 CMP DWORD PTR DS],EBP
6F39B988 74 07 JE SHORT Game.6F39B991
6F39B98A 8BCE MOV ECX,ESI
6F39B98C E8 4FEDFFFF CALL Game.6F39A6E0
6F39B991 BA 08000000 MOV EDX,8 // Target offset
6F39B996 8D4C24 5C LEA ECX,DWORD PTR SS:[ESP+5C] // Return address
We will use a normal jump to get there.
6F39B97D seems like a good place to start our jump since it is 5 bytes long. Take that address's info down in notepad or w/e.
6F39B97D E8 1E50C7FF CALL Game.6F0109A0
PAUSE OllyDBG and change this line:
6F39B97D E8 1E50C7FF CALL Game.6F0109A0
to
6F39B97D E9 A2044C00 JMP Game.6F85BE24
To do this, Select then right click the address -> Assemble or simply press spacebar then type: jmp 6F85BE24 and press enter (don't fill with NOP's)
Now press enter on that address to go the empty zone.
On 6F85BE24, we will place the info of the address we took down in note. It was
CALL Game.6F0109A0
Like we did just a minute ago, we will right click -> assemble.
Type call 6F0109A0 and press enter.
Now that we have added this line, we need to also add everything else that was between it and our target address:
6F39B982 39AE 30030000 CMP DWORD PTR DS:[ESI+330],EBP
6F39B988 74 07 JE SHORT Game.6F39B991
6F39B98A 8BCE MOV ECX,ESI
6F39B98C E8 4FEDFFFF CALL Game.6F39A6E0
6F39B991 BA 08000000 MOV EDX,8 // target address
So, just like we did before, click on the line below the one we modified and assemble this:
Then, on the next line, assemble this twice:
The reason we are putting 2 NOP's here instead of JE SHORT 6F39B991 is because 6F39B991 is way out of range for the short jump.
Then, on the next line:
Then, on the next line:
Now let's modify MOV EDX,8 to MOV EDX,0 to get the black floor effect in-game.
Assemble at 6F85BE38:
Alright, we are almost done! What we need to do now is jump back to 6F39B996, the address that was just below our target.
Assemble this on the next line:
Your memory should now look like this:
Your jump:
Your code cave:
Alright, now we need to jump to the memory zone we just made.
Assemble this at:
You are now ready to press on PLAY in OllyDBG. Your floor should be black.
© Tyrano
[Thank you] and Need an Suggestion
First i want to say thanks for your great post thats so interesting and motivating me so i want to try it to my game.
After got the address from What Code Access to the this pointer, i have this assembly (below) and call it Original Code.
Code:
005B4806 E8 66222200 CALL 007D6A71 //Entry Code Cave
005B480B 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+1C]
005B480F 8BD3 MOV EDX,EBX
005B4811 C1E2 05 SHL EDX,5
005B4814 2BD3 SUB EDX,EBX
005B4816 8D0C50 LEA ECX,DWORD PTR DS:[EAX+EDX*2]
005B4819 0FBE47 4B MOVSX EAX,BYTE PTR DS:[EDI+4B]
005B481D 8B56 04 MOV EDX,DWORD PTR DS:[ESI+4]
005B4820 8BF0 MOV ESI,EAX
005B4822 0FAF748A 1C IMUL ESI,DWORD PTR DS:[EDX+ECX*4+1C]
005B4827 8B4424 20 MOV EAX,DWORD PTR SS:[ESP+20]
005B482B 29B0 D4020000 SUB DWORD PTR DS:[EAX+2D4],ESI // Target offset
005B4831 E9 BB010000 JMP 005B49F1 // Return address
And try to make JMP so the code will jump to my code cave like this, lets call it Code after Injection :
Code after Injection :
Code:
005B4806 E8 66222200 JMP 00947B8C //Entry Code Cave
005B480B 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+1C]
005B480F 8BD3 MOV EDX,EBX
005B4811 C1E2 05 SHL EDX,5
005B4814 2BD3 SUB EDX,EBX
005B4816 8D0C50 LEA ECX,DWORD PTR DS:[EAX+EDX*2]
005B4819 0FBE47 4B MOVSX EAX,BYTE PTR DS:[EDI+4B]
005B481D 8B56 04 MOV EDX,DWORD PTR DS:[ESI+4]
005B4820 8BF0 MOV ESI,EAX
005B4822 0FAF748A 1C IMUL ESI,DWORD PTR DS:[EDX+ECX*4+1C]
005B4827 8B4424 20 MOV EAX,DWORD PTR SS:[ESP+20]
005B482B 29B0 D4020000 SUB DWORD PTR DS:[EAX+2D4],ESI
005B4831 E9 BB010000 JMP 005B49F1
And my Code Cave is more like this, lets call it Code Cave :
Code Cave :
Code:
00947B8C E8 E0EEE8FF CALL GodsWar.007D6A71
00947B91 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+1C]
00947B95 8BD3 MOV EDX,EBX
00947B97 C1E2 05 SHL EDX,5
00947B9A 2BD3 SUB EDX,EBX
00947B9C 8D0C50 LEA ECX,DWORD PTR DS:[EAX+EDX*2]
00947B9F 0FBE47 4B MOVSX EAX,BYTE PTR DS:[EDI+4B]
00947BA3 8B56 04 MOV EDX,DWORD PTR DS:[ESI+4]
00947BA6 8BF0 MOV ESI,EAX
00947BA8 0FAF748A 1C IMUL ESI,DWORD PTR DS:[EDX+ECX*4+1C]
00947BAD 8B4424 20 MOV EAX,DWORD PTR SS:[ESP+20]
00947BB1 83A8 D4020000 00 SUB DWORD PTR DS:[EAX+2D4],0
00947BB8 ^E9 34CEC6FF JMP GodsWar.005B49F1
00947BBD ^E9 44CCC6FF JMP GodsWar.00947B8C
I have try this and the game crashed and disconecting. I need a suggestion or an opinion, just want to learn assembly and disassembly by practicing, im so noob.
Thanks in advance for your help.
Warm Regards,
Donny