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 :)