我一直在无意中检查.NET DLL,使用ECMA-335作为参考,据我所知,我犯了一个严重错误,因为它似乎是错误的。我的错误来自于PE签名之后没有立即显示PE文件头的事实。
ECMA-335声明:
“ II.25.2.2 PE文件头
PE签名之后紧随其后的是PE File标头,其中包括以下内容:
偏移量字段说明
0 2
机器始终为0x14c。“
现在,当我使用以下代码时,这适用于普通的非托管DLL和EXE。
unsafe static void Stuff(Stream stream, byte[] buf)
{
int read = stream.Read(buf, 0, 1024);
// skip the first 128 bytes
// since that's the header
fixed (byte* ptr = buf)
{
// get the position of the signature?
int PEHeaderStart = *(int*)(ptr + 0x3c);
char PEsig1 = (char)*(ptr + PEHeaderStart); // P
char PEsig2 = (char)*(ptr + PEHeaderStart + 1); // E
char PEsig3 = (char)*(ptr + PEHeaderStart + 2); // \0
char PEsig4 = (char)*(ptr + PEHeaderStart + 3); // \0
ushort machine = *(ushort*)(ptr + PEHeaderStart + 4);
ushort noSections = *(ushort*)(ptr + PEHeaderStart + 6);
uint secondsFrom1970 = *(uint*)(ptr + PEHeaderStart + 8);
DateTime timeOfCreation = new DateTime(1970, 1, 1) + new TimeSpan((long)secondsFrom1970 * 1000 * 10000);
uint pointerToSymbolTable = *(uint*)(ptr + PEHeaderStart + 12);
uint numberOfSymbols = *(uint*)(ptr + PEHeaderStart + 16);
ushort sizeOfOptionalHeader = *(ushort*)(ptr + PEHeaderStart + 20);
ushort characteristics = *(ushort*)(ptr + PEHeaderStart + 22);
// flags from characteristics
bool IMAGE_FILE_RELOCS_STRIPPED = (characteristics & 0x0001) == 1;
bool IMAGE_FILE_EXECUTABLE_IMAGE = (characteristics & 0x002) == 1;
bool IMAGE_FILE_32BIT_MACHINE = (characteristics & 0x0100) == 1;
bool IMAGE_FILE_DLL = (characteristics & 0x2000) == 1;
int optionalHeaderStart = PEHeaderStart + 24;
// PE optional header
ushort magic = *(ushort*)(ptr + optionalHeaderStart);
byte lmajor = *(ptr + optionalHeaderStart + 2);
byte lminor = *(ptr + optionalHeaderStart + 3);
uint codesize = *(uint*)(ptr + optionalHeaderStart + 4);
}
}
机器号是幻数,并且timeOfCreation是有意义的,并且PE可选标头中的幻数是正确的。在0x3c中指定的指针处,签名为'PE \ 0 \ 0',并且PE文件头随后紧随其后。
但是,当我尝试检查.NET托管的DLL时,我可以成功找到签名'PE \ 0 \ 0',但是此后PE文件头并没有立即出现。所以我后来得到的数字是垃圾。当机器编号为34404(0x8664)而不是ECMA-335认为必须为332(0x14C)时,这变得很明显。
我一定做错了事,或者没有读过特定的部分,但我无法弄清目前的情况。
答案 0 :(得分:3)
它们符合PE,但是它们不包含明智的机器说明。尝试在其中之一上运行dumpbin /disasm
。您将看到它尝试将IL代码解释为机器指令,这给您带来胡扯的结果。例如:
Microsoft (R) COFF/PE Dumper Version 14.16.27026.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file hello.exe
File Type: EXECUTABLE IMAGE
00402000: 80 23 00 and byte ptr [ebx],0
00402003: 00 00 add byte ptr [eax],al
00402005: 00 00 add byte ptr [eax],al
00402007: 00 48 00 add byte ptr [eax],cl
0040200A: 00 00 add byte ptr [eax],al
0040200C: 02 00 add al,byte ptr [eax]
0040200E: 05 00 68 20 00 add eax,206800h
00402013: 00 E4 add ah,ah
00402015: 02 00 add al,byte ptr [eax]
00402017: 00 01 add byte ptr [ecx],al
00402019: 00 00 add byte ptr [eax],al
0040201B: 00 01 add byte ptr [ecx],al
0040201D: 00 00 add byte ptr [eax],al
0040201F: 06 push es
00402020: 00 00 add byte ptr [eax],al
00402022: 00 00 add byte ptr [eax],al
00402024: 00 00 add byte ptr [eax],al
00402026: 00 00 add byte ptr [eax],al
00402028: 00 00 add byte ptr [eax],al
0040202A: 00 00 add byte ptr [eax],al
0040202C: 00 00 add byte ptr [eax],al
但是,这很好,因为Windows加载器knows how to load .NET assemblies可以解析托管代码并改为运行。