0

I am currently working on teleport feature for a game trainer. I found the right static addresses containing a float:

picture of addresses with offsets

This address points to my X-coordinate. Now I am now trying to change my X-coordinate (a float) with read/write processmemory . But whatever i do it doesnt work (I have no problems with changing normal ints). I want to replace the value with a float that i choose before.

Can somebody please give me a detailed example how i can do this ?

Thank you in advance

  • Welcome to stackoverflow.com. Please take some time to read [the help pages](http://stackoverflow.com/help), especially the sections named ["What topics can I ask about here?"](http://stackoverflow.com/help/on-topic) and ["What types of questions should I avoid asking?"](http://stackoverflow.com/help/dont-ask). Also please [take the tour](http://stackoverflow.com/tour) and [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask). Lastly please learn how to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve). – Some programmer dude Feb 28 '18 at 12:17
  • In short: We will not give you detailed examples, but we will help you solve the problem you have with your existing code, if you could create a small and simple example highlighting your problem, and show it to us. – Some programmer dude Feb 28 '18 at 12:19
  • If it doesn't work, how are you so certain it's the right address? Note that you can't even count on _a_ right address existing. The actual live value may live exclusively in a register, and you may be seeing a copy of it in memory. Changing the copy doesn't change the original. – MSalters Feb 28 '18 at 12:43
  • @MSalters Ith the right address because it works if i change the value in CE . I just dont know how to do this in c++ ! – J-P. Faßbender Feb 28 '18 at 13:04

3 Answers3

1

1) get process base address - Getting base address of a process hprocess is handle, pass there openprocess returned value (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320(v=vs.85).aspx)

2) add 'teleport' offset to base address

3) write given value to memory of process

HANDLE hProcess = openProcess(processId); //you also need to pass desired mode, use read & write
DWORD dwBaseAddress = getBaseAddress(hProcess): 
DWORD dwPositionAddress = dwBaseAddress + POSITION_OFFSET; 
float newPosition = 123.5;
WriteProcessMemory(hProcess, dwPositionAddress, &newPosition, sizeof(float));

you need to check for errors, this is just pseudocode to give you idea what you need to do, also make sure you run your trainer as admin and have access to game's memory

bestestefan
  • 852
  • 6
  • 20
0

You have to read pointer and add that pointers its relative offsets to get to teleport address.

You can use WriteProcessMemory() to write into process memory directly and ReadProcessMemory() to read from memory .

But in case if you are reading two-three level pointer it will become cumbersome approach to do so.

So i recommend using Game Trainer or memory hacking library to read/write pointer easily.

you could use GTLibc Game Trainer libray for C/C++. GTLibc Game trainer library

or you could use Memory.dll game hacking library for C#. Memory.dll

Stephen Docy
  • 4,738
  • 7
  • 18
  • 31
Haseeb Mir
  • 928
  • 1
  • 13
  • 22
  • Using a library for doing this is not great advice, especially if a 6 line template function can do that. –  Apr 23 '18 at 03:01
  • A library could provide just one method like **ReadPointerOffset** or Offsets with single function you can read multiple pointers with multiple offsets with ease. But if you want to do it manually you have to use **ReadProcessMemory** multiple times and have to do in loop and add address conversion from void* to int* to add offsets also. So library could do that stuff for you. You can do it with or without any external library as i said before no force on that. – Haseeb Mir Apr 24 '18 at 17:26
  • Did you see my answer? A template is the much preferred option, as your not limited by whatever types the library supports. Additionally, it is a **terrible** idea to use a pseudo-function like `readpointeroffset`, as you're only reading 8 bytes at a time every for every pointer. Such libraries would use a `ReadFloat` for every float in a vector3 in a class, rather than reading every member of a class in one rpm call by mapping out the classes you're trying to read and passing that in a template. Libraries like that are simply inefficient and lead to bad practices. –  Apr 26 '18 at 01:56
  • Yes i read your answer and i agree that template is better option but i disagree that **readPointeroffset** is terrible idea , i was giving you an simple example to readPointer it assumes that data is of _INT_ for other type like float or Double there would be another or overloaded method because Float and Double needs extra precision. And you are suggesting to Inject **DLL** its not good idea to inject DLL where you could just manipulate memory and DLL is advanced stuff you could have suggested , **ShellCodeInjection** method that is easy and doesn't require to load external libraries. – Haseeb Mir Apr 26 '18 at 12:37
  • If you're doing a lot of memory reading and writing, yeah injecting a dll is easier, far more than writing assembly with WPM. When speed matters (often), it makes no sense to use multiple RPM calls to different members in the same class, when you could simply read the entire class in one go. _"because Float and Double needs **extra** precision"_ Do you know how memory works? Your argument isn't making any sense. If you think an injectable dll is "Advanced", know that all you need is 3 more lines than what I gave in my answer for an injection-ready dll. (dllmain) –  Apr 27 '18 at 04:20
  • The basic method of altering any process is by **WPM** because it requires only basic knowledge like address and offset,But any injection or Hook method is advanced like **ShellCode APC or DLL** injection because it requires knowledge how DLL loads,how Libraries work, how process IPC works ,how architecture's ISA works and all stuff you need to know for injecting custom code or DLL into target process. And i know how memory works 32-bit Float has 24-bits mantissa,7-bit Exp and 1 sign bit ,For 64-bit Double 52-bits mantissa, 11 bits Exp & 1 sign bit this is precision i was talking about . – Haseeb Mir Apr 27 '18 at 13:51
0

Doing it internally instead

Readprocessmemory and writeprocessmemory would be relatively simple, but a better option is to inject a DLL into the target process for speed and simplicity. You can either manually deference by using a *, or do the preferred method and set up classes with the proper sizes so you don't have to deal with offsets in the same way. Check out Reclass.NET for automating this.

class unk3{
public:
    char pad_001[0x10];
    float location;
}

class unk2{
public:
    unk3* m_unk3;
}

class unk1{
public:
    char pad_001[0x78];
    unk2* m_unk2;
}

Then declare an instance at your static offset, and read/write to it like it is your own memory.

unk1* p_unk1 = (unk1*)(uintptr_t*)(OFFSET);
p_unk1->m_unk2->m_unk3->location = 300f;

Using RPM

If you want to go external, you'll need to first open a handle to the process.

void attach(LPCSTR WindowName) {
    HWND hWindow = FindWindowA(NULL, WindowName); 
    if (hWindow)
    {
        GetWindowThreadProcessId(hWindow, &Proc_ID); 
        hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION/*PROCESS_ALL_ACCESS*/, FALSE, Proc_ID); 
        HANDLE hModule = INVALID_HANDLE_VALUE; 
        MODULEENTRY32 ePoint; 
        hModule = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, Proc_ID); 
        ePoint.dwSize = sizeof(MODULEENTRY32); 
        Module32First(hModule, &ePoint);
        base = (DWORD*)ePoint.modBaseAddr; 
        CloseHandle(hModule);
    }
}

Then I'd recommend setting up templates for doing the reading/writing for you.

template <class T>
T read(DWORD_PTR Address){
    T buffer;
    ReadProcessMemory(this->hProcess, (LPCVOID)Address, &buffer, sizeof(buffer), NULL);
    return buffer;
}

Then pretty much the same method for writing. Then execution would be:

DWORD_PTR p_unk1 = mem.read<DWORD_PTR>(OFFSET);
DWORD_PTR p_unk2 = mem.read<DWORD_PTR>(p_unk1 + 0x78);
DWORD_PTR p_unk3 = mem.read<DWORD_PTR>(p_unk2);
float location = mem.read<float>(p_unk3 + 0x10);

Externally efficiency

Rather than just ready sizeof(DWORD_PTR) and reading every element in the class, its better if you do something like this:

class unk3{
public:
    char pad_001[0x10];
    float location;
}

class unk2{
public:
    DWORD_PTR m_unk3;
}

class unk1{
public:
    char pad_001[0x78];
    DWORD_PTR m_unk2;
}

Replace every class* with a DWORD_PTR

Then execute it with

unk1 p_unk1 = mem.read<unk1>(OFFSET);
unk2 p_unk2 = mem.read<unk2>(p_unk1.m_unk2);
unk3 p_unk3 = mem.read<unk3>(p_unk2.m_unk3);
float location = p_unk3.Location;

For those who are wondering, writing that way is done:

mem.write<float>(p_unk2 + offsetof(unk3, location), value);

Wrap up

Internally doing this is significantly better, less hassle. Note on your question, writeprocessmemory just shoves bytes, it doesn't care about type. You're probably passing the address of an integer as the buffer to write, when ints and floats are encoded differently with little endian. Make sure you declare it as a float, or better yet, use a template. Or even better, just write a dll :)