【问题标题】:Access memory by UInt32 in C#在 C# 中通过 UInt32 访问内存
【发布时间】:2015-05-06 20:18:23
【问题描述】:

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

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

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

【问题讨论】:

  • 不太确定您想要实现什么,但您谈论的是IntPtr 和非托管代码。 IE。 C++ 和类似语言中的指针。
  • 不适用于 64 位机器
  • 绝对内存还是虚拟地址? :-)
  • 如果您指向受保护的地址,则会出现页面错误。
  • 您可以在 unsafe 块中执行类似 byte *ptr = 0x12345678; byte value = *ptr; 的操作。这就是你想要做的吗?

标签: c# memory


【解决方案1】:

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

【讨论】:

  • 这不能回答问题。该示例显示了如何获取指向变量的指针并访问该变量,而不是如何访问由数字指定的地址。
  • 将地址转换为所需类型的指针(在本例中,我取的是 int):var p = (int*)&0x12345678; 然后修改它:p[0] = 0xCAFEBABE;
  • 我会说它是int* p = (int*)0x12345678; (没有&
【解决方案2】:

除了使用指针,你还可以

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 不是您的内存单元 0 RAM,因为 Windows/任何现代操作系统都将内存映射到所有进程)

一般来说,非驱动程序禁止从 Windows Server 2003 SP1“原始”访问内存(直接访问未映射到您的进程的内存):Read physical memory under Windows 8。显然,您仍然可以读取映射到您的进程的所有内存。

通常不要将指针放入Int32/UInt32。在 32 位 sizeof(Int32) == sizeof(void*) 时,当您转到 64 位时,这将不再起作用。使用指针类型(int*byte*、...)或IntPtr/UIntPtr(保证是指针的长度)。如果您需要进行指针数学运算并且您通常不使用 .NET 4.0,请使用 long/ulong(或 Int64/UInt64,同样的东西)(这是 64 位,所以在32 位和 64 位)

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 这样做大错特错...您正在创建sizeof(int) == sizeof(byte*)的强烈暗示,并且通过给出这样的回应,您是在告诉“可以这样做”:-(
    • 我使用IntPtr,其中IntPtr.Size == sizeof(byte*)定义为IntPtr
    • @xanatos:您正在将整数转换为IntPtr,因此暗示IntPtr.Size == sizeof(int)
    • 我正在将一个特定的常量转换为IntPtr。有一个不那么微妙的区别。如果我写了IntPtr ptr = (IntPtr)0x1234567812345678,它将正确编译并在 64 位时正常工作(在 32 位时它会在执行时溢出)
    • @xanatos:这意味着您的答案对 OP 来说毫无用处。他没有“特定常数”,他在变量中有一个数字。
    猜你喜欢
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    • 2013-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多