为什么这个用于操作PE文件头的代码使用这种奇怪的偏移值?

时间:2012-09-28 11:48:17

标签: c# c++ .net visual-c++

Here's a piece of code for obtaining the time when a .NET assembly was built。注意:

const int c_LinkerTimestampOffset = 8;

以后:

int secondsSince1970 = System.BitConverter.ToInt32(b, i + c_LinkerTimestampOffset);

此代码提取存储在程序集中的IMAGE_FILE_HEADER structure TimeDateStamp成员。结构定义如下:

typedef struct _IMAGE_FILE_HEADER {
    WORD  Machine;
    WORD  NumberOfSections;
    DWORD TimeDateStamp;
    DWORD PointerToSymbolTable;
    DWORD NumberOfSymbols;
    WORD  SizeOfOptionalHeader;
    WORD  Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

WORD是两个字节,应该是两个字节对齐的。当我使用Visual C ++ 10编译以下代码时:

IMAGE_FILE_HEADER header;
char* start = (char*)&header;
char* field = (char*)(&header.TimeDateStamp);
int diff = field - start;

diff等于4,正如我个人所期望的那样。

这是C#代码中的错误吗?为什么使用8的偏移值?

3 个答案:

答案 0 :(得分:3)

用于跳过其他签名,因为i包含NT标头的偏移量,而不是文件图像标头(请参阅formal PE structure):

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature; //<- we need to skip this
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

因此实际总和为sizeof(WORD /* FileHeader.Machine */) + sizeof(WORD /* FileHeader.NumberOfSections */) + sizeof(DWORD /* Signature */)

底线,不是一个错误,只是一些魔法可以跳过一些结构嵌套/内联。

答案 1 :(得分:0)

  

DWORD是一个i​​nt无符号值,4个字节。

C#代码不正确,它读取8个字节。我认为它应该是4。

int secondsSince1970 = System.BitConverter.ToInt32(b, i + c_LinkerTimestampOffset);

几天前我写过一个PE读者。我将它用于“图像文件标题”:

public class IMAGE_FILE_HEADER 
{
     public UInt16 Machine;
     public UInt16 NumberOfSections;
     public UInt32 TimeDateStamp;
     public UInt32 PointerToSymbolTable;
     public UInt32 NumberOfSymbols;
     public UInt16 SizeOfOptionalHeader;
     public UInt16 Characteristics;
}

答案 2 :(得分:-1)

你最有可能获得一个8字节的差异,因为你是在64位系统/目标平台上,如果你在32位上就可能是你所期望的那样。

在32位系统上,DWORD定义为uint(32位/ 4字节),在64位系统上定义为ulong(64位/ 8字节)。

WORD基本上代​​表架构的地址大小。当它被创造时,WORD是16位而DWORD是双字,32位(4字节)。

人们希望在x86系统上DWORD为64位/ 8字节,但MS希望保留传统支持,以便保留旧的定义:http://msdn.microsoft.com/en-us/library/aa383751(VS.85).aspx