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
}
让我们来看看这个。
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);