我曾尝试在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
}
答案 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);