c#指针问题

本文关键字:问题 指针 | 更新日期: 2023-09-27 18:10:27

我尝试在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 

一切似乎都很好,除了shift指令,我不明白为什么它会在这里。

有谁能告诉我原因吗?

这是结构定义(是的,它是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
}

c#指针问题

让我们来看看这个。

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