Welcome to dEViATED. We provide PC trainers, cheats, mods and game trainers and a gamehacking forum for discussions and help. We have pc cheats, cheat engine tables and mods for various old and new single player games.

These are some of the latest trainers released by us and supported fully.
Assassin's Creed Rogue Trainer
Grand Theft Auto 5 Trainer



Sign in to follow this  
Followers 0

Codeshifting - Intro - Techniques - Solution

7 posts in this topic

Posted

Code Shifting

Author: spookie

Written: Saturday 11th Nov, 2003

--------------------------------

Revised: Thursday 8th July, 2004

--------------------------------

Subject: Code Shifting

----------------------

Author: spookie

---------------

CodeShifting happens simply when a DLL is dynamically loaded with LoadLibrary() by the game,

and inside this DLL is the game code that you need to edit. This is becoming more and

more common these days because of the amount of games coming out based on generic engines.

To name a few, Max Payne 2, Splinter Cell, Tron 2.0 and Counter-Strike: Condition Zero.

Out of these four chart topping games, only two working trainers were released. There was

an additional obstacle with Tron 2.0, being based on the Lithtech engine, as not only is the

game code in a dynamically loaded dll, it drops this dll in the temp files with a random

name before loading.

Now, to get around this problem we've got to find the address at which our game code dll

has been loaded, and with the help of the ToolHelp32 APIs it's not a hard task. First of

all, you need to know what dll your code is inside...

So for example lets say our cheat address is 008C3627 - We need to find a dll in the

currently running target game that's loaded at an address lower than 008C3627, but with an

image size of more than 008C3627. If you have LordPE handy (http://protools.cjb.net/) you

can get a list of loaded dlls and their base address and image size by selecting the game

process in the upper list and the dlls will then be displayed in the lower list. Or, you

could use a small tool, codeloc, I created for this, available at http://spookie.rom.cd/.

codeloc takes 2 parameters, the first is the game window text or the game window class

name, the second is your cheat location. e.g...

--------------------------------------------------------------------------------code---

codeloc "MaxPayne2" 8C3627

...will result as...

<008C3627> is inside module "X_GameObjectsMFC.dll" with base address <008B0000>

-------------------------------------------------------------------------------/code---

Now we know what dll we're working inside, we have to offset our given cheat address by

the current base address. Given the above example, my cheat address was 8C3627, and the dll

that contains it was loaded at 008B0000, so our cheat address offset would be 13627...

Cheat Address - Base Address = Cheat Offset

8C3627 - 8B0000 = 13627

So now we have our new cheat address we have to get the base address of the dll within our

trainer at runtime. To do this we'll use the ToolHelp32 APIs to cycle through all the

loaded "Modules" of the target game until we find ours.

Here is the code to do so in Delphi...

--------------------------------------------------------------------------------code---

uses TlHelp32;

function GetModuleBaseAddress(iProcId: Cardinal; DLLName: String): Cardinal;

var

hSnap: THandle; // Process snapshot handle.

xModule: ModuleEntry32; // Module information structure.

begin

Result:= 0; // If the result of the function is 0, it didn't find the base address.

// i.e.. the dll isn't loaded.

hSnap:= CreateToolHelp32Snapshot(TH32CS_SNAPMODULE, iProcId); // Creates a module

// snapshot of the

// game process.

xModule.dwSize:= SizeOf(xModule); // Needed for Module32First/Next to work.

If Module32First(hSnap, xModule) Then Begin // Gets the first module.

While Module32Next(hSnap, xModule) Do // Loops through the rest of the modules.

If xModule.szModule = DLLName Then // If this is the module we want...

Result:= Cardinal(xModule.modBaseAddr); // Save the base address it in result.

End;

CloseHandle(hSnap); // Free the handle.

end;

-------------------------------------------------------------------------------/code---

...and here is the same thing in C...

--------------------------------------------------------------------------------code---

#include <TlHelp32.h>

DWORD GetModuleBaseAddress(DWORD iProcId, char* DLLName)

{

HANDLE hSnap; // Process snapshot handle.

MODULEENTRY32 xModule; // Module information structure.

hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, iProcId); // Creates a module

// snapshot of the

// game process.

xModule.dwSize = sizeof(MODULEENTRY32); // Needed for Module32First/Next to work.

if (Module32First(hSnap, &xModule)) // Gets the first module.

{

while (Module32Next(hSnap, &xModule)) // Loops through the rest of the modules.

{

if (strcmp(xModule.szModule, DLLName) == 0) // If this is the module we want...

{

CloseHandle(hSnap); // Free the handle.

return (DWORD)xModule.modBaseAddr; // return the base address.

}

}

}

CloseHandle(hSnap); // Free the handle.

return 0; // If the result of the function is 0, it didn't find the base address.

// i.e.. the dll isn't loaded.

}

-------------------------------------------------------------------------------/code---

...and finally in masm...

--------------------------------------------------------------------------------code---

GetModuleBaseAddress proc iProcID:DWORD, DLLName:DWORD

LOCAL hSnap:DWORD

LOCAL xModule:MODULEENTRY32

invoke CreateToolhelp32Snapshot, TH32CS_SNAPMODULE, iProcID

mov hSnap,eax

mov xModule.dwSize, sizeof xModule

invoke Module32First, hSnap, addr xModule

test eax, eax

jnz getdll

mov eax, 0

ret

getdll:

invoke Module32Next, hSnap, addr xModule

test eax, eax

jnz checkdll

mov eax, 0

ret

checkdll:

invoke lstrcmpi, DLLName, addr xModule.szModule

test eax, eax

jnz getdll

mov eax, xModule.modBaseAddr

ret

GetModuleBaseAddress endp

-------------------------------------------------------------------------------/code---

These functions require the ProcessID of the game (GetWindowThreadProcessID()), and the

name of the dll you want the base address of. I've learnt the hard way that you should

use this function before doing any injection, not when the game has first started,

because some games like to reload the game dlls when you change level (Counter-Strike: CZ)

In the end, the lpBaseAddress parameter you will send to WriteProcessMemory will be...

--------------------------------------------------------------------------------code---

GetModuleBaseAddress(GAME_PROCESS_ID, "X_GameObjectsMFC.dll") + 0x13627

-------------------------------------------------------------------------------/code---

Any problems just email me at: [email protected]

- spookie

Share this post


Link to post
Share on other sites

Posted

I hate being the noob that bumps up an over-a-year-old-topic but that's why my post needs approval right? :D

This is a genius method, why is it not famous? What I've been learning is finding pointers to eventually crawl my way to a static address, but that is one hell of a pain in the ass especially when you've got 3-4 level pointers!

Then let's say an update comes out and all your pointers become junk, you gotta go to the beginning and find all your pointers for every hack.

I'm about to put this method to practice, cheat engine's disassembler actually shows you all the modules loaded within a game if you go to:

View ---> Show module names

And then turn off

View ---> show symbols

Your addresses will now indicate the module name+offset

That even allows you to view the base address at which the module was loaded that particular time by

right click ---> go to address

and symply typing out your "ModuleName.dll"

then you symply turn off

view ---> show module names

That's a completely useless practice though, simply there to quench your curiosity. You can do it mathematically too by subtracting the offset from your hack address (duh)

Anyway here it goes, making another trainer using this method, #&#036;%# pointers

Share this post


Link to post
Share on other sites

Posted (edited)

Hmmm interesting. Interesting, interesting, interesting.

Does lpBaseAddress, second parameter of WriteProcessMemory() need to be in hexadecimal?

Edited by satanclaus

Share this post


Link to post
Share on other sites

Posted

Yep. Write it in masm like 0040000h.

1 person likes this

Share this post


Link to post
Share on other sites

Posted (edited)

Thnx emptieness.

I'm writing this in C++, failed to mention that.

My GetModuleBase() function that I wrote:


DWORD GetModuleBase(LPSTR lpModuleName, DWORD procId)

{

   MODULEENTRY32 lpModuleEntry = {0};

   HANDLE hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, procId );

   if(!hSnapShot)

	  return NULL;

   lpModuleEntry.dwSize = sizeof(lpModuleEntry);

   BOOL bModule = Module32First( hSnapShot, &lpModuleEntry );

   while(bModule)

   {

	  if(!strcmp( lpModuleEntry.szModule, lpModuleName ) )

	  {

		 CloseHandle( hSnapShot );

		 return (DWORD)lpModuleEntry.modBaseAddr;

	  }

	  bModule = Module32Next( hSnapShot, &lpModuleEntry );

   }

   CloseHandle( hSnapShot );

   return NULL;

}

Returns the correct base address but in decimal notation (I think unsigned long?)

For example it would return:

9036112

which, when converted to hex, would be:

8E0000

and that would be the correct base address of my module (that particular time the game is launched)

WriteProcessMemory() does not detect a problem with that, and returns true after it's executed

However, the end result is that the value at the memory address that I'm writing to (base+offset) remains unchanged, I checked the assembly code myself after running my trainer.

Bottom line is:

I need to convert the unsigned long value returned by my GetModuleBase() function:

9036112

To hexadecimal notation before I send it to the lpBaseAddress parameter of WriteProcessMemory():

0x8E0000

Anyone have any tips on how to achieve this?

Edited by satanclaus

Share this post


Link to post
Share on other sites

Posted

Your GetModuleBase function returns a dword value. So you need to convert nothing. My function looks similiar to yours and is working perfectly.

Just declare a dword value to store the base address. Then add the offset (dword 0xoffset) to it and you should have the correct address. Don't forget that you have to declare your offsets with a 0x standing before the actual address.


DWORD dwBaseAddress, dwOffset;

DWORD dwRealAddress;

dwBaseAddress = GetModuleBase(szModuleName, ProcID);


dwOffset = 0x400000;


dwRealAddress = dwBaseAddres + dwOffset;

Then call WPM.

Share this post


Link to post
Share on other sites

Posted

Yeah I quickly realized I don't need to convert anything, unfortunately I couldn't edit my post.

Everything I had was all correct from the beginning, WPM just wasn't doing its thing.

It's a bummer that I'm at work right now but I just remembered what I'm missing from my trainer, and that's VirtualProtect( ). I'm quite certain that everything will work out as soon as I get back to my source and call VirtualProtect( ) on my addy.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0