1

It it possible to access memory through a specific UInt32 variable?

For example, if I had an UInt32 variable, and its value is 12345678,

then is there any method to access the memory location 0x12345678?

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
Alanight
  • 353
  • 2
  • 8
  • 23

3 Answers3

3

The MSDN shows how to do this, note that you will need to compile with the option /unsafe (you find it in the project settings)

        unsafe 
        {
            // Assign the address of number to a pointer:
            int* p = &number;

            // Commenting the following statement will remove the
            // initialization of number.
            *p = 0xffff;

            // Print the value of *p:
            System.Console.WriteLine("Value at the location pointed to by p: {0:X}", *p);

            // Print the address stored in p:
            System.Console.WriteLine("The address stored in p: {0}", p->ToString());
        }
Binkan Salaryman
  • 3,008
  • 1
  • 17
  • 29
  • 1
    That doesn't answer the question. The example shows how to get a pointer to a variable and access the variable, not how to access an address specified by a number. – Guffa Mar 05 '15 at 12:57
  • Cast your address to a pointer of your desired type (in this case, I took int): `var p = (int*)&0x12345678;` Then modify it: `p[0] = 0xCAFEBABE;` – Binkan Salaryman Mar 05 '15 at 13:02
  • I'll say it's `int* p = (int*)0x12345678`; (no `&`) – xanatos Mar 05 '15 at 13:16
2

Other than using pointers, you can

IntPtr ptr = IntPtr.Zero; // here you need some address you can read
// For example IntPtr ptr = (IntPtr)0x12345678
// IntPtr is 32 bits or 64 bits depending on how the program is running

byte b = Marshal.ReadByte(ptr); // Or all the other Read* methods.

Note that Marshal.Read*/Marshal.Write* don't require unsafe mode (but are probably slower) (and are still unsafe in the english meaning of the word, like running with scissors :-) )

Clearly you need an address you can read (for example received by a C interop call)

Note that in general you can't read any one address of the memory, and that the ptr you are using isn't an absolute pointer to the memory (IntPtr.Zero isn't the memory cell 0 of your RAM, because Windows/any modern OS maps the memory to all the processes)

In general from Windows Server 2003 SP1 "raw" access to memory (direct access to memory not mapped to your process) is forbidden to non-drivers: Read physical memory under Windows 8 . Clearly you can still read all the memory that is mapped to your process.

As a rule don't put pointers in Int32/UInt32. While at 32 bits sizeof(Int32) == sizeof(void*), when you go to 64 bits this doesn't work anymore. Use the pointer types (int*, byte*, ...) or IntPtr/UIntPtr (that are guaranteed to be of the length of a pointer). If you need to do pointer math and you aren't using .NET 4.0 in general use the long/ulong (or Int64/UInt64, same thing) (that are 64 bits, so safe both at 32 and 64 bits)

Community
  • 1
  • 1
xanatos
  • 109,618
  • 12
  • 197
  • 280
1

You can cast a number to a pointer. Example:

int address = 0x12345678;

unsafe {
  byte* ptr = (byte*)address;
  Console.WriteLine(*ptr);
}

Note that you can only access the virtual namespace of your own application, not the actual physical memory, and you get an exception if you try to read outside the memory area allocated for your application. Also, remember that data is not guaranteed to stay put in memory, the garbage collector can move any object at any time.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • It's so much wrong to do it... You are creating a strong implication that `sizeof(int) == sizeof(byte*)`, and by giving a response like this you are telling "it's ok to do it" :-( – xanatos Mar 05 '15 at 13:08
  • I use `IntPtr`, where `IntPtr.Size == sizeof(byte*)` by definition of `IntPtr`. – xanatos Mar 05 '15 at 13:35
  • @xanatos: You are converting an integer to an `IntPtr`, so then the implication that `IntPtr.Size == sizeof(int)`. – Guffa Mar 05 '15 at 13:38
  • I'm converting a specific constant to `IntPtr`. There is a not-so-subtle difference. If I wrote `IntPtr ptr = (IntPtr)0x1234567812345678` it would compile correctly and would work correctly at 64 bits (at 32 bits it would overflow on execution) – xanatos Mar 05 '15 at 13:40
  • @xanatos: That means your answer is useless for the OP. He doesn't have a "specific constant", he has a number in a variable. – Guffa Mar 05 '15 at 14:16