Code:
#include "stdafx.h"
DWORD WINAPI maphack();
//patching function variables
DWORD OldAccessRights;
DWORD OffsetA = 0x4989D9;
DWORD OffsetB = 0x42D48A;
DWORD *OffsetC = (DWORD*)0x4989E7;
DWORD OffsetD = 0x497F68;
DWORD *OffsetE = (DWORD*)0x497F78;
DWORD *OffsetF = (DWORD*)0x47FFE2;
//replacement variables
DWORD Var1 =0;
DWORD VisibleUnitArray[20000]={0};
void __declspec(naked) HelperFunction()
{
__asm
{
MOV ECX,Var1
MOV EDX,DWORD PTR DS:[ECX*8+VisibleUnitArray]
MOV EAX,ECX
SHR EAX,1
CMP ECX,1
PUSH ESI
MOV ESI,DWORD PTR DS:[ECX*8+VisibleUnitArray+4]
JBE SHORT JumpB1
PUSH EDI
NOP
JumpC2:
MOV EDI,DWORD PTR DS:[EAX*8+VisibleUnitArray]
CMP EDI,EDX
JNB SHORT JumpB2
MOV DWORD PTR DS:[ECX*8+VisibleUnitArray],EDI
MOV EDI,DWORD PTR DS:[EAX*8+VisibleUnitArray+4]
MOV DWORD PTR DS:[ECX*8+VisibleUnitArray+4],EDI
MOV ECX,EAX
SHR EAX,1
CMP ECX,1
JA SHORT JumpC2
JumpB2:
POP EDI
JumpB1:
MOV DWORD PTR DS:[ECX*8+VisibleUnitArray+4],ESI
MOV DWORD PTR DS:[ECX*8+VisibleUnitArray],EDX
POP ESI
RETN
}
}
void __declspec(naked) ProcessActiveUnits()
{
__asm
{
MOV ECX,Var1
INC ECX
MOV DWORD PTR DS:[ECX*8+VisibleUnitArray+4],ESI
MOVZX EAX,BYTE PTR DS:[ESI+0xD]
CMP EAX,4
MOV Var1,ECX
JA SHORT JumpA1
MOVSX EDX,WORD PTR DS:[ESI+0x16]
JMP SHORT JumpB1
JumpA1:
XOR EDX,EDX
JumpB1:
SHL EAX,0x0D
OR EAX,EDX
XOR EDX,EDX
MOV DL,BYTE PTR DS:[ESI+0xE]
SHL EAX,5
AND EDX,0x10
OR EAX,EDX
MOVZX EDX,WORD PTR DS:[ESI+0x10]
SHL EAX,9
OR EAX,EDX
CMP ECX,1
MOV DWORD PTR DS:[ECX*8+VisibleUnitArray],EAX
JBE SHORT JumpC1
CALL HelperFunction
JumpC1:
RETN
}
}
void __declspec(naked) CheckActiveUnits()
{
__asm
{
pushad
MOV EAX,DWORD PTR DS:[0x6D0EFC]
TEST EAX,EAX
MOV Var1,0
JNZ SHORT JumpA
MOV EDI,DWORD PTR SS:[EBP+8]
CMP EDI,DWORD PTR SS:[EBP+0xC]
JA SHORT JumpB
MOV BL,BYTE PTR DS:[0x57F094]
JumpF:
MOV ESI,DWORD PTR DS:[EDI*4+0x629670]
TEST ESI,ESI
JE SHORT JumpC
JumpE:
TEST BYTE PTR DS:[ESI+0xC],BL
//JE SHORT JumpD
CALL ProcessActiveUnits
//JumpD:
MOV ESI,DWORD PTR DS:[ESI+4]
TEST ESI,ESI
JNZ SHORT JumpE
JumpC:
MOV EAX,DWORD PTR SS:[EBP+0xC]
INC EDI
CMP EDI,EAX
JBE SHORT JumpF
JMP SHORT JumpB
JumpA:
MOV EAX,DWORD PTR SS:[EBP+8]
CMP EAX,DWORD PTR SS:[EBP+0xC]
MOV EDI,EAX
JA SHORT JumpB
MOV BL,BYTE PTR DS:[0x6D0F00]
JumpK:
MOV ESI,DWORD PTR DS:[EDI*4+0x629670]
TEST ESI,ESI
JE SHORT JumpG
JumpJ:
TEST BYTE PTR DS:[ESI+0xC],BL
JNZ SHORT JumpH
MOV EAX,DWORD PTR DS:[0x6D0F04]
TEST EAX,EAX
JE SHORT JumpI
CMP BYTE PTR DS:[ESI+0xA],0x0B
JNZ SHORT JumpI
JumpH:
CALL ProcessActiveUnits
JumpI:
MOV ESI,DWORD PTR DS:[ESI+4]
TEST ESI,ESI
JNZ SHORT JumpJ
JumpG:
MOV EAX,DWORD PTR SS:[EBP+0xC]
INC EDI
CMP EDI,EAX
JBE SHORT JumpK
JumpB:
popad
xor EAX,EAX
jmp OffsetE
}
}
void __declspec(naked) PrintUnitsHelperFunction()
{
__asm
{
PUSH EBP
MOV EBP,ESP
SUB ESP,8
MOV EAX,DWORD PTR DS:[VisibleUnitArray+0xC]
PUSH ESI
MOV ESI,DWORD PTR DS:[VisibleUnitArray+0x8]
PUSH EDI
MOV EDI,Var1
MOV EDX,EDI
MOV ECX,1
SHR EDX,1
CMP EDX,ECX
MOV DWORD PTR SS:[EBP-4],EAX
JB SHORT JumpA4
PUSH EBX
JumpE4:
LEA EBX,DWORD PTR DS:[EBX]
LEA EAX,DWORD PTR DS:[ECX+ECX]
CMP EAX,EDI
JNB SHORT JumpB4
MOV EBX,DWORD PTR DS:[EAX*8+VisibleUnitArray]
CMP EBX,DWORD PTR DS:[EAX*8+VisibleUnitArray+0x8]
JNB SHORT JumpB4
INC EAX
JumpB4:
MOV EBX,DWORD PTR DS:[EAX*8+VisibleUnitArray]
CMP ESI,EBX
JNB SHORT JumpC4
CMP EAX,EDX
MOV DWORD PTR DS:[ECX*8+VisibleUnitArray],EBX
MOV EBX,DWORD PTR DS:[EAX*8+VisibleUnitArray+4]
MOV DWORD PTR DS:[ECX*8+VisibleUnitArray+4],EBX
MOV ECX,EAX
JBE SHORT JumpE4
JumpC4:
POP EBX
JumpA4:
MOV EDX,DWORD PTR SS:[EBP-4]
POP EDI
MOV DWORD PTR DS:[ECX*8+VisibleUnitArray],ESI
MOV DWORD PTR DS:[ECX*8+VisibleUnitArray+4],EDX
POP ESI
MOV ESP,EBP
POP EBP
RETN
}
}
void __declspec(naked) PrintUnits()
{
__asm
{
PUSH ESI
PUSH ESI
MOV ESI,Var1
TEST ESI,ESI
JNZ JumpA3
POP ESI
POP ESI
XOR EAX,EAX
test eax,eax
jmp OffsetC
JumpA3:
PUSH EBX
LEA EBX,DWORD PTR DS:[ESI-1]
PUSH EDI
MOV DWORD PTR DS:[0x6C4A10],EBX
MOV EDI,0x6C2300
NOP
JumpB3:
MOV ECX,DWORD PTR DS:[ESI*8+VisibleUnitArray]
MOV EAX,DWORD PTR DS:[VisibleUnitArray+0xC]
MOV DWORD PTR DS:[VisibleUnitArray+0x8],ECX
MOV EDX,DWORD PTR DS:[ESI*8+VisibleUnitArray+4]
DEC ESI
MOV DWORD PTR DS:[EDI],EAX
MOV DWORD PTR DS:[VisibleUnitArray+0xC],EDX
MOV Var1,ESI
CALL PrintUnitsHelperFunction
ADD EDI,4
TEST ESI,ESI
JNZ SHORT JumpB3
MOV EAX,DWORD PTR DS:[EBX*4+0x6C2300]
POP EDI
POP EBX
POP ESI
POP ESI
test eax,eax
jmp OffsetC
}
}
void CallPatch1(void *pDest,void *pSrc)
{
VirtualProtect(pSrc, 16, PAGE_EXECUTE_READWRITE, &OldAccessRights);
*(BYTE*)((DWORD)pSrc) = 0xE9;
*(DWORD*)((DWORD)pSrc+1) = (DWORD)pDest - (DWORD)pSrc - 5;
*(BYTE*)((DWORD)pSrc+0xC) = 0xEB;
*(BYTE*)((DWORD)pSrc+0xD) = 0xF2;
VirtualProtect(pSrc, 16, OldAccessRights, &OldAccessRights);
VirtualProtect((int*)OffsetB, 2, PAGE_EXECUTE_READWRITE, &OldAccessRights);
*(BYTE*)(OffsetB) = 0x90;
*(BYTE*)(OffsetB+1) = 0x90;
VirtualProtect((int*)OffsetB, 2, OldAccessRights, &OldAccessRights);
VirtualProtect(OffsetF, 4, PAGE_EXECUTE_READWRITE, &OldAccessRights);
*OffsetF = 0x158BC933;
VirtualProtect(OffsetF, 4, OldAccessRights, &OldAccessRights);
}
void CallPatch2(void *pDest,void *pSrc)
{
VirtualProtect(pSrc, 16, PAGE_EXECUTE_READWRITE, &OldAccessRights);
*(BYTE*)((DWORD)pSrc) = 0xE9;
*(DWORD*)((DWORD)pSrc+1) = (DWORD)pDest - (DWORD)pSrc - 5;
*(BYTE*)((DWORD)pSrc+0xE) = 0xEB;
*(BYTE*)((DWORD)pSrc+0xF) = 0xF0;
VirtualProtect(pSrc, 16, OldAccessRights, &OldAccessRights);
}
DWORD WINAPI maphack()
{
CallPatch1(&PrintUnits,(PBYTE)OffsetA);
CallPatch2(&CheckActiveUnits,(PBYTE)OffsetD);
//loop-code for in-game hotkeys
return 0;
}
BOOL APIENTRY DllMain(HANDLE hModule, DWORD CurrentState, LPVOID lpReserved)
{
if (CurrentState == DLL_PROCESS_ATTACH)
{
CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)maphack,NULL,NULL,NULL);
}
else
{
return 1;
};
return 1;
}
Well these tutorials thoroughly covered the art of code caving. I hope they will help people who are just starting out hacking. Please let me know if you have any suggestions or ideas that would make these tutorials better. Also please point out any areas that might be unclear, as I don’t have all day to write tutorials.