Alanight
Alanight

Reputation: 361

Access memory by UInt32 in C#

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?

Upvotes: 1

Views: 1418

Answers (3)

Guffa
Guffa

Reputation: 700372

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.

Upvotes: 1

xanatos
xanatos

Reputation: 111870

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)

Upvotes: 2

Binkan Salaryman
Binkan Salaryman

Reputation: 3048

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());
        }

Upvotes: 3

Related Questions