使用C#中的UInt32访问内存



是否可以通过特定的UInt32变量访问内存?

例如,如果我有一个UInt32变量,它的值是12345678,

那么有什么方法可以访问内存位置0x12345678吗?

MSDN展示了如何做到这一点,请注意,您需要使用选项/unsafe进行编译(您可以在项目设置中找到它)

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

除了使用指针,您还可以

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.

注意,Marshal.Read*/Marshal.Write*不需要不安全模式(但可能更慢)(在单词的英语含义中仍然不安全,就像用剪刀运行:-)

显然,您需要一个可以读取的地址(例如通过C互操作调用接收的地址)

请注意,通常情况下,您无法读取内存的任何一个地址,并且您使用的ptr不是指向内存的绝对指针(IntPtr.Zero不是RAM的内存单元0,因为Windows/任何现代操作系统都会将内存映射到所有进程)

通常,从Windows Server 2003 SP1开始,非驱动程序禁止对内存进行"原始"访问(直接访问未映射到进程的内存):在Windows 8下读取物理内存。显然,您仍然可以读取映射到流程的所有内存。

按照规则不要Int32/UInt32中放置指针。而在32位sizeof(Int32) == sizeof(void*)时,当你转到64位时,这就不再起作用了。使用指针类型(int*byte*…)或IntPtr/UIntPtr(保证为指针长度)。如果你需要做指针数学,而你没有使用。NET 4.0通常使用long/ulong(或Int64/UInt64,相同)(即64位,因此在32位和64位都是安全的)

您可以将数字强制转换为指针。示例:

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

请注意,您只能访问自己的应用程序的虚拟命名空间,而不能访问实际的物理内存,如果您试图在为应用程序分配的内存区域之外进行读取,则会出现异常。此外,请记住,不能保证数据保持在内存中,垃圾收集器可以在任何时间移动任何对象。

最新更新