It's different, because it isn't just 0x28FA190 + 0x374
, but it's *(0x28FA190 + 0x374)
.
0x28FA190
is a base address, probably of a structure, and 0x374
is an offset, when you sum these values and dereference the result, you get value of a field that's 0x374
bytes away from the beginning of this structure. This field seems to be a pointer, that's why it's value is also an address, but it could contain any value.
struct A
{
char padding[0x374]; // occupy the first 0x374 bytes, so that myPointer's address is address of this structure + 0x374 (i.e. (DWORD)this + 0x374)
int* myPointer;
};
A a;
int valueOfMyPointer = **(int**)((DWORD)&a + 0x374); // valueOfMyPointer = *a.myPointer;
You need to explicitly cast &a
to DWORD
(aka unsigned long
), because of pointer arithmetic - if you would do &a + 0x374
, the result would actually be (DWORD)&a + 0x374 * sizeof(a)
.
You can also write the entire expression from your screen as following:
uint32_t result = *(DWORD*)(*(DWORD*)((DWORD)GetModuleHandle("ac_client.exe") + 0x374) + 0x14);