Using pointers and multiple offsets to obtain an address

My question may sound somewhat confusing and that may be because I'm over complicating this subject, but to start I need to give you some background. I've started learning about reading and writing process memory in C++ and I used this to modify a number(the amount of arrows I have) in the game, 'Thief'.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <Windows.h>
using namespace std;

int main(){
	HWND hwnd =FindWindowA(NULL, "Thief");
	if(hwnd==NULL){
		cout<<"Unable to find window"<<endl;
		exit(-1);
	}else{
		DWORD procID;
		GetWindowThreadProcessId(hwnd, &procID);
		HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
		if(procID==NULL){
			cout<<"Unable to obtain process ID"<<endl;
			exit(-1);
		}else{
			cout<<"Writing to memory..."<<endl;
			//int offset0 = 388; 
			//int offset1 = 0;
			//int offset2 = 38C;
			//int offset3 = 70;
			//int offset4 = 1AC;
                        int arrows = 50;
			while(1==1){
				Sleep(1000);
				WriteProcessMemory(handle, (LPVOID)0x1418C2AC, &arrows, sizeof(arrows), NULL);
			}
		}
	}
	return 0;
}


This code is functional in that it does what I want but only to an extent. All it does is write to the specific address that i found using Cheat Engine(the address that holds the amount of arrows) and its in an infinite loop that just resets the amount of arrows back to 50 every second. So it pretty much gives me unlimited arrows.

My problem is that I quickly learned once you quit the game or even just load the last save, the address for the specific amount of arrows changes so the code becomes useless unless I find the specific address again using Cheat Engine.

So I did the research and found out that there is a base address I need to find that is static. That way I can constantly keep track of the number of arrows even if the game closes and reopens. The base address points me to the new address that the number of arrows are stored in. I went through the point scanner process in Cheat Engine and found what I believe is the base address.

My struggle at the moment is taking the information cheat engine has given me and actually implementing it into my code. I want to be able to use the base address and offsets to find the new address but I'm not sure exactly how I'd go about doing that. Ive read a lot about just ReadingProcessMemory and figuring it out that way but I'm still pretty new to the subject and I'd appreciate if someone can point me in the right direction.

My formal question is this: Is it possible for me to replace the, "0x1418C2AC" in my code with a variable containing the new address. The variable would obtain this address using the base address I have and the offsets. So each time i open the program, It will find the address of the arrows using the static base address and its offsets.

Dont know how to attach a photo to this but this is pretty much what my cheat engine pointer says:

ThiefGame.exe"+0202D0D8 --> 02F87200
Offset 0: 388 .... 02F87200+388-->17B4C360
Offset 1: 0 .... 17B4C360+0-->00CAB0C0
Offset 2: 38C .... 00CAB0C0+38C-->16883200
Offset 3: 70 .... 16883200+70-->1418C100
Offset 4: 1AC .... 1418C100+1AC-->1418C2AC


Base address: 02F87200 (I think this is the base address but I'm not sure what the '0202D0D8' means thats right before it.

Final target address: 1418C2AC(this is the address i want the variable to contain in my program that i can put after '(LPVOID)' )

Final thoughts: Ive used hex calculators online and they dont get what Cheat Engine is getting by adding those values together. For example it adds 0 and 17B4C360 together in Offset 1 and that produces 00CAB0C0. Shouldn't this just be equal to 17B4C360 since its adding 0 to it?

Sorry if my questions are confusing. If you need more information to answer this please ask. Ive been doing hours of research on multi leveled pointers and their offsets and im just confused on how i can implement this in my program so that it finds the right address when it starts up.

Last thing to add just in case it matters, I tried adding the offsets to the base address in my code earlier and it was giving me errors saying the hexadecimals weren't an 'int'. I obviously know its not an int but how can i add these hexadecimals together to get the new address? Also some of the offsets have letters in them and some dont... do the ones without letters in them mean they are strictly decimals or are they all hexadecimals?

Thanks for taking the time to read all this, I've seriously been very confused and i had to just make an account on this website to ask my question.

Any feedback is appreciated :)
Last edited on
1. Read 4 bytes using ReadProcessMemory() at address 0x0202D0D8. In the example you posted this gives back the bytes 00 72 F8 02, which can be interpreted as a pointer with value 0x02F87200.
2. Add 0x388 to 0x02F87200, giving 0x02F87588. Again read 4 bytes, giving 0x17B4C360.
3. Read 4 bytes at 0x17B4C360, giving 0x00CAB0C0.
4. Add 0x38C to 0x00CAB0C0, and read 4 bytes at 0x00CAB44C, giving 0x16883200
5. Add 0x70 to 0x16883200, and read 4 bytes at 0x16883270, giving 0x1418C100.
6. Add 0x1AC to 0x1418C100, giving 0x1418C100.

Here's a quick example. I haven't ensured correctness, this is just to give a general idea:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
typedef std::uint32_t pointer32;

pointer32 read_remote_pointer(HANDLE process, pointer32 address){
    char buffer[sizeof(pointer32)];
    SIZE_T bytes_read;
    if (!ReadProcessMemory(process, (const void *)address, buffer, sizeof(buffer), &bytes_read) || bytes_read != sizeof(buffer))
        return 0;
    return *(pointer32 *)buffer;
}

void find_address(HANDLE process){
    static const int offsets[] = {0x388, 0, 0x38C, 0x70, 0x1AC};
    const pointer32 base = 0x0202D0D8;
    pointer32 p = base;
    for (auto offsets : offsets){
        p = read_remote_pointer(process, p);
        if (!p)
            return 0;
        p += offset;
    }
    return p;
}
Topic archived. No new replies allowed.