C#指针问题

时间:2015-08-31 12:10:56

标签: c# pointers

我曾尝试在C#中使用带结构的指针,但是当我向指针添加偏移时会发生一些奇怪的计算:

     p_FILE_HEADER = (IMAGE_FILE_HEADER*)(p_DOS_HEADER +  p_DOS_HEADER->e_lfanew);
  0000018a  mov         eax,dword ptr [ebp-3Ch] 
  0000018d  mov         eax,dword ptr [eax+14h]   
  00000190  mov         edx,dword ptr [ebp-3Ch] 
  00000193  mov         edx,dword ptr [edx+14h] 
  00000196  mov         edx,dword ptr [edx+3Ch] 
  00000199  xor         ecx,ecx 
  0000019b  shl         edx,6   //strange
  0000019e  add         eax,edx 
  000001a0  mov         edx,dword ptr [ebp-3Ch] 
  000001a3  mov         dword ptr [edx+0Ch],eax 

除了转移指令外,一切似乎都没问题,我不明白为什么它会在这里。

谁能告诉我原因?

这是结构定义(是的,它是PE头的一部分)

[StructLayout(LayoutKind.Sequential,Pack=1) ]
public unsafe struct IMAGE_DOS_HEADER
{      // DOS .EXE header


    public ushort e_magic;               //0x0      // Magic number     
    public ushort e_cblp;                //0x2      // Bytes on last page of file
    public ushort e_cp;                  //0x4      // Pages in file    
    public ushort e_crlc;                //0x6      // Relocations
    public ushort e_cparhdr;             //0x8     // Size of header in paragraphs
    public ushort e_minalloc;            //0xA      // Minimum extra paragraphs needed
    public ushort e_maxalloc;            //0xC      // Maximum extra paragraphs needed
    public ushort e_ss;                  //;0xE      // Initial (relative) SS value
    public ushort e_sp;                  //0x10      // Initial SP value
    public ushort e_csum;                //0x12      // Checksum
    public ushort e_ip;                  //0x14      // Initial IP value
    public ushort e_cs;                  //0x16      // Initial (relative) CS value
    public ushort e_lfarlc;              //0x18      // File address of relocation table
    public ushort e_ovno;                //0x1A      // Overlay number

  // [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
    public fixed ushort e_res[4];              //0x1C      // Reserved words
    public ushort e_oemid;               //0x24      // OEM identifier (for e_oeminfo)
    public ushort e_oeminfo;             //0x26      // OEM information; e_oemid specific
  //  [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 10)]
    public fixed ushort e_res2 [10];            //0x28      // Reserved words

    public uint e_lfanew;              //0x3C      // File address of new exe header

}

1 个答案:

答案 0 :(得分:3)

让我们来看看这一秒。

p_FILE_HEADER = (IMAGE_FILE_HEADER*)(p_DOS_HEADER +  p_DOS_HEADER->e_lfanew);

所以你有一些变量p_DOS_HEADER,可能是IMAGE_DOS_HEADER的一个实例。您将PE映像加载到内存中并将此结构放在其上。所以p_DOS_HEADER.e_lfanew告诉你,从文件的开头到字节的距离是新的exe标题'。 p_DOS_HEADER告诉您记忆中的文件'启动。

在C#中,指针算法基于指向类型的大小工作。 int* thing = ...; thing++将导致事物跳过四个字节(int的大小),而不是一个字节。这与大多数其他支持指针的语言支持的约定相同,如C ++或C.

但是,您正在阅读的字段 - e_lfanew以字节为单位存储偏移量。因此,您需要字节算术。

你想要这样的东西:

p_FILE_HEADER = (IMAGE_FILE_HEADER*)( (byte*)p_DOS_HEADER + p_DOS_HEADER->e_lfanew);