And I thought I'd seen it all, but I was wrong :) I have to admit I knew it was possible, but I never ever saw an executable change its base address each time it loads. That is, until I loaded up Torchlight.
While it was always on the 'standard' base address in my virtual pc (40000h), on my main pc it kept changing. Could it be a Windows 7 64-Bit thing?
Anyway, this means that all pointers have to be relative to the base address, not fixed. Its not a huge issue, whenever you find a pointer just subtract the base address from it and you have the relative pointer.
But back to the Torchlight and using a code cave. As I mentioned in part #1, I wanted to try something different. Instead of allocating memory for my code detour, I decided to use a code cave instead. Using the handy code cave finder in Cheat Engine, I found that at Torchlight.exe + 2D0h there's a code cave big enough to fit my injected code.
I decided to inject this code (I highlighted points of interest using bold-comment code):
2D0 - push eax // Start of new-health detour
2D1 - call 2f1 // Compare ESI to the Player / Pet Pointer
2D6 - cmp al,00 // Is it an enemy?
2D8 - je 2e5 // Yes, set the new health
2DA - fcom dword ptr [esi+00000394] // No, is the new value higher?
2E0 - fnstsw ax
2E2 - sahf
2E3 - jb 2ed // No, its lower
2E5 - fstp dword ptr [esi+00000394] // Set the new health value
2EB - jmp 2ef
2ED - fstp st(0)
2EF - pop eax
2F0 - ret // Return back to the normal flow (end of new health detour)
2F1 - mov eax,[Torchlight.exe+A2B6A4] // Load base pointer (start of player / pet compare)
2F6 - mov eax,[eax+1c] // Load actual player pointer
2F9 - cmp eax,esi // Compare player pointer to ESI
2FB - je 312 // Is it the player?
2FD - mov eax,[Torchlight.exe+A2B6A4] // Load base pointer
302 - mov eax,[eax+000002d4] // Load pet offset
308 - mov eax,[eax+2c] // Load pet pointer
30B - cmp eax,esi // Compare pet pointer to ESI
30D - je 312 // is it the pet?
30F - mov al,00 // Its an enemy
311 - ret // End of player / pet compare
312 - mov al,01 // Its player or pet
314 - ret // End of player / pet compare
315 - push eax // Start of new mana detour
316 - call 2f1
31B - cmp al,00
31D - je 32a
31F - fcom dword ptr [esi+000003b8]
325 - fnstsw ax
327 - sahf
328 - jb 332
32A - fstp dword ptr [esi+000003b8]
330 - jmp 334
332 - fstp st(0)
334 - pop eax
335 - ret // End of new mana detour
The above code shows 3 functions, the first function is the "new health" detour function. It checks it the health is set for an enemy or player (or pet). If its the player then it will check the new health, if its lower then it wont set the new health, if its higher it will set the new health.
That function is then copied to the "new mana" detour function (the last function).
The middle function is a small helper function (as I needed it for both new health/mana detours), it will compare the esi register with the player/pet pointers and return 1 (player/pet) or 0 (enemy).
I can write this injected code into Torchlight.exe + 2D0h, I can then detour the new health/mana instructions using a call to this injected code. And voila, you cant die, but when you level up you can get more health :)
I do have to say that my first code cave experience was a good one and I'll probably use them more. A nice thing is that almost all the injected code and detour code doesn't change because the code cave doesn't change its address.
In the trainer that I put online I added a few functions. Like change your experience, fame, pet experience, money, stat points and spell point. You can also freeze the enchantment difficulty of items. It'll basically let you enchant with almost no risk (there's still 2% risk).
You can download it here, enjoy.