네이티브 어셈블리가 관리 코드 응용 프로그램 ( C # ) 에서 x64 또는 x86으로 준수되는지 확인하고 싶습니다 .
OS 로더 가이 정보를 알아야하기 때문에 PE 헤더의 어딘가에 있어야한다고 생각하지만 찾을 수 없었습니다. 물론 관리되는 코드에서 수행하는 것을 선호하지만 필요한 경우 기본 C ++을 사용할 수 있습니다.
답변
DUMPBIN 도 사용할 수 있습니다 . /headers
또는 /all
플래그와 나열된 첫 번째 파일 헤더를 사용하십시오 .
dumpbin /headers cv210.dll
64 비트
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file cv210.dll
PE signature found
File Type: DLL
FILE HEADER VALUES
8664 machine (x64)
6 number of sections
4BBAB813 time date stamp Tue Apr 06 12:26:59 2010
0 file pointer to symbol table
0 number of symbols
F0 size of optional header
2022 characteristics
Executable
Application can handle large (>2GB) addresses
DLL
32 비트
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file acrdlg.dll
PE signature found
File Type: DLL
FILE HEADER VALUES
14C machine (x86)
5 number of sections
467AFDD2 time date stamp Fri Jun 22 06:38:10 2007
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
2306 characteristics
Executable
Line numbers stripped
32 bit word machine
Debug information stripped
DLL
‘찾기’는 삶을 조금 더 쉽게 만들 수 있습니다.
dumpbin /headers cv210.dll |find "machine"
8664 machine (x64)
답변
CorFlags 를 사용하면이 작업을 쉽게 수행 할 수 있습니다. Visual Studio 명령 프롬프트를 열고 “corflags [귀하의 어셈블리]”를 입력하십시오. 다음과 같은 것을 얻을 수 있습니다 :
c : \ Program Files (x86) \ Microsoft Visual Studio 9.0 \ VC> corflags “C : \ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ System.Data.dll”
Microsoft (R) .NET Framework CorFlags 변환 도구. 버전 3.5.21022.8 저작권 (c) Microsoft Corporation. 판권 소유.
버전 : v2.0.50727 CLR 헤더 : 2.5 PE : PE32 CorFlags : 24 ILONLY : 0 32BIT : 0 서명 : 1
PE와 32BIT를 구체적으로보고 있습니다.
-
모든 CPU :
PE : PE32 32
비트 : 0 -
x86 :
PE : PE32 32
비트 : 1 -
x64 :
PE : PE32 +
32BIT : 0
답변
이 트릭 은 작동하며 메모장 만 필요합니다.
메모장과 같은 텍스트 편집기를 사용하여 dll 파일을 열고 문자열이 처음 나타나는 것을 찾으십시오 PE
. 다음 문자는 dll이 32 비트인지 64 비트인지를 정의합니다.
32 비트 :
PE L
64 비트 :
PE d†
답변
Magic
의 필드 IMAGE_OPTIONAL_HEADER
당신에게 PE의 구조를 말할 것이다 (하지만이 윈도우 실행 이미지 (DLL / EXE 파일)의 헤더에 대한 옵션 아무 것도 없다).
다음은 파일에서 아키텍처를 가져 오는 예입니다.
public static ushort GetImageArchitecture(string filepath) {
using (var stream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
using (var reader = new System.IO.BinaryReader(stream)) {
//check the MZ signature to ensure it's a valid Portable Executable image
if (reader.ReadUInt16() != 23117)
throw new BadImageFormatException("Not a valid Portable Executable image", filepath);
// seek to, and read, e_lfanew then advance the stream to there (start of NT header)
stream.Seek(0x3A, System.IO.SeekOrigin.Current);
stream.Seek(reader.ReadUInt32(), System.IO.SeekOrigin.Begin);
// Ensure the NT header is valid by checking the "PE\0\0" signature
if (reader.ReadUInt32() != 17744)
throw new BadImageFormatException("Not a valid Portable Executable image", filepath);
// seek past the file header, then read the magic number from the optional header
stream.Seek(20, System.IO.SeekOrigin.Current);
return reader.ReadUInt16();
}
}
현재 두 가지 아키텍처 상수는 다음과 같습니다.
0x10b - PE32
0x20b - PE32+
건배
업데이트이
답변을 게시 한 지 오래되었습니다.하지만 여전히 몇 번의 공감대를 얻었으므로 업데이트 할 가치가 있다고 생각했습니다. Portable Executable
이미지 의 아키텍처를 얻는 방법을 작성했으며 이미지가로 컴파일되었는지 확인합니다 AnyCPU
. 불행히도 대답은 C ++에 있지만에서 구조를 조회하는 데 몇 분이 걸리더라도 C #으로 포팅하기가 너무 어렵지 않아야합니다 WinNT.h
. 사람들이 관심이 있다면 C #으로 포트를 작성하지만 실제로 사람들이 원하지 않는 한 그것에 대해 많은 시간을 소비하지 않을 것입니다.
#include <Windows.h>
#define MKPTR(p1,p2) ((DWORD_PTR)(p1) + (DWORD_PTR)(p2))
typedef enum _pe_architecture {
PE_ARCHITECTURE_UNKNOWN = 0x0000,
PE_ARCHITECTURE_ANYCPU = 0x0001,
PE_ARCHITECTURE_X86 = 0x010B,
PE_ARCHITECTURE_x64 = 0x020B
} PE_ARCHITECTURE;
LPVOID GetOffsetFromRva(IMAGE_DOS_HEADER *pDos, IMAGE_NT_HEADERS *pNt, DWORD rva) {
IMAGE_SECTION_HEADER *pSecHd = IMAGE_FIRST_SECTION(pNt);
for(unsigned long i = 0; i < pNt->FileHeader.NumberOfSections; ++i, ++pSecHd) {
// Lookup which section contains this RVA so we can translate the VA to a file offset
if (rva >= pSecHd->VirtualAddress && rva < (pSecHd->VirtualAddress + pSecHd->Misc.VirtualSize)) {
DWORD delta = pSecHd->VirtualAddress - pSecHd->PointerToRawData;
return (LPVOID)MKPTR(pDos, rva - delta);
}
}
return NULL;
}
PE_ARCHITECTURE GetImageArchitecture(void *pImageBase) {
// Parse and validate the DOS header
IMAGE_DOS_HEADER *pDosHd = (IMAGE_DOS_HEADER*)pImageBase;
if (IsBadReadPtr(pDosHd, sizeof(pDosHd->e_magic)) || pDosHd->e_magic != IMAGE_DOS_SIGNATURE)
return PE_ARCHITECTURE_UNKNOWN;
// Parse and validate the NT header
IMAGE_NT_HEADERS *pNtHd = (IMAGE_NT_HEADERS*)MKPTR(pDosHd, pDosHd->e_lfanew);
if (IsBadReadPtr(pNtHd, sizeof(pNtHd->Signature)) || pNtHd->Signature != IMAGE_NT_SIGNATURE)
return PE_ARCHITECTURE_UNKNOWN;
// First, naive, check based on the 'Magic' number in the Optional Header.
PE_ARCHITECTURE architecture = (PE_ARCHITECTURE)pNtHd->OptionalHeader.Magic;
// If the architecture is x86, there is still a possibility that the image is 'AnyCPU'
if (architecture == PE_ARCHITECTURE_X86) {
IMAGE_DATA_DIRECTORY comDirectory = pNtHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
if (comDirectory.Size) {
IMAGE_COR20_HEADER *pClrHd = (IMAGE_COR20_HEADER*)GetOffsetFromRva(pDosHd, pNtHd, comDirectory.VirtualAddress);
// Check to see if the CLR header contains the 32BITONLY flag, if not then the image is actually AnyCpu
if ((pClrHd->Flags & COMIMAGE_FLAGS_32BITREQUIRED) == 0)
architecture = PE_ARCHITECTURE_ANYCPU;
}
}
return architecture;
}
이 기능은 메모리 내 PE 이미지에 대한 포인터를 허용합니다 (따라서 독을 선택하는 방법; 메모리 매핑 또는 전체 내용을 메모리로 읽는 방법 등).
답변
관리되지 않는 DLL 파일의 경우 먼저 16 비트 DLL 파일인지 확인해야합니다 (권장하지 않음). 그런 다음 IMAGE\_FILE_HEADER.Machine
필드를 확인하십시오 .
다른 누군가 가 이미이 문제를 해결하는 데 시간 이 걸렸으므로 여기서 반복 할 것입니다.
32 비트 및 64 비트 PE 파일을 구별하려면 IMAGE_FILE_HEADER.Machine 필드를 확인해야합니다. 아래 Microsoft PE 및 COFF 사양에 따라이 필드에 가능한 모든 값을 나열했습니다.
http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/ pecoff_v8.docIMAGE_FILE_MACHINE_UNKNOWN 0x0이 필드의 내용은 모든 머신 유형에 적용 가능한 것으로 가정합니다
IMAGE_FILE_MACHINE_AM33 0x1d3 마쓰시타 AM33
IMAGE_FILE_MACHINE_AMD64 0x8664 x64
IMAGE_FILE_MACHINE_ARM 0x1c0 ARM 리틀 엔디안
IMAGE_FILE_MACHINE_EBC 0xebc EFI 바이트 코드
IMAGE_FILE_MACHINE_I386 0x14c Intel 386 이상의 프로세서 및 호환 가능한 프로세서
IMAGE_FILE_MACHINE_IA64 0x200 Intel Itanium 프로세서 제품군
IMAGE_FILE_MACHINE_M32R 0x9041 미쓰비시 M32R 리틀 엔디안
IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16
FPU가있는 IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS
FPU 포함 IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16
IMAGE_FILE_MACHINE_POWERPC 0x1f0 Power PC 리틀 엔디안
부동 소수점을 지원하는 IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 Power PC
IMAGE_FILE_MACHINE_R4000 0x166 MIPS 리틀 엔디안
IMAGE_FILE_MACHINE_SH3 0x1a2 히타치 SH3
IMAGE_FILE_MACHINE_SH3DSP 0x1a3 Hitachi SH3 DSP
IMAGE_FILE_MACHINE_SH4 0x1a6 히타치 SH4
IMAGE_FILE_MACHINE_SH5 0x1a8 히타치 SH5
IMAGE_FILE_MACHINE_THUMB 0x1c2 Thumb
IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 MIPS 리틀 엔디안 WCE v2
예, IMAGE_FILE_MACHINE_AMD64 | IMAGE_FILE_MACHINE_IA64는 64 비트이고 IMAGE_FILE_MACHINE_I386은 32 비트입니다.
답변
솔루션에 대한 C # 샘플 구현을 여기 에서 찾을 수 있습니다.IMAGE_FILE_HEADER
답변
64 비트 바이너리는 PE32 + 형식으로 저장됩니다. http://www.masm32.com/board/index.php?action=dlattach;topic=6687.0;id=3486을 읽어보십시오 .