I'm trying to read (and eventually write) memory of another process. I have the address (found using cheat engine) and I want to read it's value from my program, but I don't get the expected value. The address is 274A88A1630, but when I convert it to LPCVOID (which is required by ReadProcessMemory) I only get A88A1630 (which doesn't point to the memory I want)
I've tried converting using (LPCVOID) and (void*), both give the same result
int val = 0;
ReadProcessMemory(handle, (void*)0x274A88A1630, &val, sizeof(val), 0);
cout << val <<endl;
That happens because you have compiled your app as an x86 (32 bit/Win32) binary. Pointers (void* in this case) are 32 bits on x86. Pointers on x64 (64 bit/Win64) are 64 bits. 0x274A88A1630 is a 64 bit value, so you will therefore not encounter this problem if you compile your app for x64 (64 bit/Win64).
TLDR; A pointer value over 32 bits gets truncated to 32 bits when compiled for x86.
Related
What is the correct way to use ReadProcessMemory?
I am currently using it like this:
DWORD read_mem(DWORD addr)
{
DWORD buffer = 0x0;
if (!ReadProcessMemory(phandle, LPCVOID(addr), &buffer, sizeof(DWORD), nullptr))
{
return false;
}
return buffer;
}
This causes a warning due to addr being wrongly casted.
warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
Other example code I've seen such as this uses the same approach.
So what is the proper way to use this function without getting a warning?
"cast to pointer from integer of different size" - this means that DWORD and void* are different byte sizes, which can only happen if you are compiling your code for 64-bit, as they are the same byte size in a 32-bit compilation.
From the MSDN documentation, Windows Data Types:
DWORD
A 32-bit unsigned integer. The range is 0 through 4294967295 decimal.
A DWORD is simply not large enough to hold a 64-bit memory address (the other code you mention will similarly only work correctly in 32-bit).
Change Addr (and whatever code you are using to determine the value of Addr) to use DWORD_PTR instead:
DWORD_PTR
An unsigned long type for pointer precision. Use when casting a pointer to a long type to perform pointer arithmetic. (Also commonly used for general 32-bit parameters that have been extended to 64 bits in 64-bit Windows.)
Then Addr will be the correct byte size whether you compile for 32-bit or 64-bit.
I have a buffer(contains audio data) which is void pointer. In 32bit system, it's size is 4 byte and in 64 bit system, it's size is 8 byte. So how can i convert 64bit void pointer into 32bit void pointer without loosing any data ?
As long as the value in your 64-bit pointer plus the size of your buffer is less than 2^32 you can just use the lower 32 bit of your pointer. For example uint32_ptr ptr32 = static_cast<uint32_ptr>(ptr64). It is, however, not a best practice to mess with pointers like this.
In addition, I assume you'll be using these pointers in the same process on the same machine. Any other application will fail!
I have learnt that while printing the address of a variable in c, we use unsigned int (%u in format string).
Its range is from 0 to 65535. Now an integer takes 4 bytes of memory, which means a maximum of 16384 (65536/4) integers can be stored. What will happen if we try to declare an array int a[20000] and get addresses of each of its element?
#include<stdio.h>
int main(void)
{
int a[20000];
for(i=0; i<19999; i++])
printf("%u", &a[i]);
}
In early times of C, a pointer and a int where similar types, and you could safely cast from one to the other and back again. In that early time, pointers and int were both 16 bits long. It is still true on 32 bits systems where int is now 32 bits. But it is false on 64 bits systems, because pointers are 64 bits long and int only 32 bits.
So I do not know where and how you learnt that while printing the address of a variable in c , we use unsigned int(%u), but forget it ASAP because in the general case it is wrong. The only foolproof way to print an adress is %p because system automatically adapt the size to 16, 32 or 64 bits.
And no longer convert pointers to int or opposite side, because it is highly non portable. From that other post, A more portable way (on the C99 standard variant) is to #include <stdint.h> and then cast pointers to intptr_t (and back). This integer type is guaranteed to be the size of a pointer.
And, I almost forgot 65536 = 0x10000 = 216, and 232 = 4294967296. So you were not that far from reality, and it is true that in older 16 bits system you could not have int array[40000] because int were 16 bits long and the array would exhaust all the available memory.
But on 32 bits systems, you can address 4 Gb of memory, so int array[20000] is harmless.
A pointer is a memory address where you can find some data. We can find the size the of a pointer variable using sizeof( ) operator. So its size doesn't depend on what it points at .It however depends on many bytes a memory address takes up on your system, which is 4 for a 32 bit compilers and 8 for 64-bit compiler.
If we have declared a pointer, double j, type of j is double, i.e. “a pointer to double".
%p is the correct format specifier for printing a pointer. %p outputs addresses in the hexadecimal notation.
Sometimes people use %u and %x (unsigned int in hexadecimal form) specifiers to print a pointer variable. It is however an undefined behavior to pass a pointer for a %x or %u argument.
However it works with 32 bit compilers like code blocks .This is because the size of unsigned int and the pointer is same here. (Both 4 bytes)
(It is false to assume that int and pointers have the same width . For both GCC 64 bit and MSVC 64 bit running on x64, sizeof(void *) == 8, while sizeof(unsigned int) == 4. It just so happens that on some architectures pointers and ints are the same size, e.g. the PDP-11/34a, or most 32 bit architectures nowadays. But it is extremely unwise to ever write code that relies on it.
You can do add extra 2 lines as below and verify:
printf("size of unsigned int is %lu\n", sizeof(unsigned int));
printf("size of pointer is %lu\n", sizeof(int *));
On a 64-bit GCC machine with a 64-bit operating system, this should give you 4 and 8 respectively )
On a GCC 64-bit machine-%x casts your pointer to an unsigned integer (32-bit length). The size of pointer is of 8-byte (64 bit) length. Printing with %p prints the whole pointer, in its complete size – 64 bits. But when you are printing with %x, only the lower 32 bits are printed. Hence it is always safe to print a pointer with %p.
Actually unsigned integers are having range of 0 to 65536 on older 16bit compilers like turbo c. Now a days all systems are having 32 or 64 bit architecture on which unsigned integers range is 0 to 4G (giga). So this code should work fine in latest compilers like gcc (under linux) or visual studio (under windows). Try switching to these compilers. They are very good and are widely used now a days. 16bit compilers are obsolete. Avoid using such compilers. If you are using windows then code blocks or dev c++ are some good programming IDEs for learning c.
P.S. avoid using %u for printing addresses. Use %p instead.
I was just wondering how can I know if my laptop is 64 or 32 bit machine. (it is a 64).
So, I thought about printing the following:
int main()
{
printf("%d",sizeof(int));
}
and the result was 4, which seemed weird (since it is a 64 bit machine)
But, when I printed this:
int main()
{
printf("%d",sizeof(int*));
}
the result was 8, which made more sense.
The question is:
Since I'm using a 64 bit machine, shouldn't a primitive type such as int should use 8 bytes
(64 bit) and by that sizeof int should be 8? Why isn't it so?
And why is the int* size is 8?
A bit confused here,
so thanks in advance.
No, the sizeof(int) is implementation defined, and is usually 4 bytes.
On the other hand, in order to address more than 4GB of memory (that 32bit systems can do), you need your pointers to be 8 bytes wide. int* just holds the address to "somewhere in memory", and you can't address more than 4GB of memory with just 32 bits.
Size of a pointer should be 8 byte on any 64-bit C/C++ compiler, but the same is not true for the size of int.
Wikipedia has a good explanation on that:
In many programming environments for C and C-derived languages on
64-bit machines, "int" variables are still 32 bits wide, but long
integers and pointers are 64 bits wide. These are described as having
an LP64 data model. Another alternative is the ILP64 data model in
which all three data types are 64 bits wide, and even SILP64 where
"short" integers are also 64 bits wide.[citation needed] However, in
most cases the modifications required are relatively minor and
straightforward, and many well-written programs can simply be
recompiled for the new environment without changes. Another
alternative is the LLP64 model, which maintains compatibility with
32-bit code by leaving both int and long as 32-bit. "LL" refers to the
"long long integer" type, which is at least 64 bits on all platforms,
including 32-bit environments.
The sizeof(int), sizeof(int*), and "machine size", though often correlated to each other, can each be independently smaller, the same or larger than the others. About the only C requirement is that they be at least 16 bits (or so) - other than that, it compiler dependent for the sizeof(int), sizeof(int*).
(Although maybe a pointer must be at least an int size. Hmmm)
Programmers like to have integer types of 1, 2, 4 and 8 bytes or 8, 16, 32 and 64 bits. There are only two integer types that could be smaller than int: char and short. If int was 64 bits, then you couldn't have all three of the sizes 8, 16 and 32 bits. That's why compilers tend to make int = 32 bits, so you can have char = 8 bit, short = 16 bit, int = 32 bit, long long = 64 bit and long = 32 bit or 64 bit.
Because of size_t was define as
typedef unsigned int size_t;
You should display it with %zu, %u or %lu instead of %d.
printf("%zu\n", sizet);
printf("%u\n", sizet);
printf("%lu\n", sizet);
I need to accurately convert a long representing bits to a double and my soluton shall be portable to different architectures (being able to be standard across compilers as g++ and clang++ woulf be great too).
I'm writing a fast approximation for computing the exp function as suggested in this question answers.
double fast_exp(double val)
{
double result = 0;
unsigned long temp = (unsigned long)(1512775 * val + 1072632447);
/* to convert from long bits to double,
but must check if they have the same size... */
temp = temp << 32;
memcpy(&result, &temp, sizeof(temp));
return result;
}
and I'm using the suggestion found here to convert the long into a double. The issue I'm facing is that whereas I got the following results for int values in [-5, 5] under OS X with clang++ and libc++:
0.00675211846828461
0.0183005779981613
0.0504353642463684
0.132078289985657
0.37483024597168
0.971007823944092
2.7694206237793
7.30961990356445
20.3215942382812
54.8094177246094
147.902587890625
I always get 0 under Ubuntu with clang++ (3.4, same version) and libstd++. The compiler there even tells me (through a warning) that the shifting operation can be problematic since the long has size equal or less that the shifting parameter (indicating that longs and doubles have not the same size probably)
Am I doing something wrong and/or is there a better way to solve the problem being as more compatible as possible?
First off, using "long" isn't portable. Use the fixed length integer types found in stdint.h. This will alleviate the need to check for the same size, since you'll know what size the integer will be.
The reason you are getting a warning is that left shifting 32 bits on the 32 bit intger is undefined behavior. What's bad about shifting a 32-bit variable 32 bits?
Also see this answer: Is it safe to assume sizeof(double) >= sizeof(void*)? It should be safe to assume that a double is 64bits, and then you can use a uint64_t to store the raw hex. No need to check for sizes, and everything is portable.