35 프로그램 파일: 머신 형식과 판
패키지 작성기는 담는 PE 파일(.exe, .dll 등)마다 두 가지를 읽는다: 잘못된 아키텍처용 파일을 거부하기 위한 머신 형식, 그리고 Windows Installer 가 판이 있는 파일과 없는 파일을 다르게 다루기 때문에 판 정보 리소스. 배치는 Microsoft PE/COFF 명세와 VS_VERSIONINFO 문서를 따른다. [spec]
35.1 머리 찾기 [spec]#
오프셋 0 "MZ"
오프셋 0x3C u32 e_lfanew: PE 서명의 오프셋
e_lfanew "PE\0\0"
+4 COFF 머리: u16 machine, u16 섹션 수, ..., u16 선택 머리 크기(+16)
+24 선택 머리: u16 magic 0x10B(PE32) 또는 0x20B(PE32+); 데이터 디렉터리는
+96(PE32) 또는 +112(PE32+)에서 그 개수 다음에 시작
그다음 섹션 표: 섹션마다 40바이트(가상 크기 +8, 가상 주소 +12,
원 크기 +16, 원 오프셋 +20)
머신 값: 0x8664 x64, 0xAA64 Arm64, 0x014C x86. MZ 로 시작하지만 올바른 PE\0\0 머리가 없는 파일은 보통 데이터 파일이다.
35.2 판 정보 리소스 [spec]#
- 데이터 디렉터리 2 가 리소스 표다(RVA 와 크기). RVA 는 섹션 표를 거쳐 파일 오프셋으로 바꾼다.
- 리소스 디렉터리는 세 단계다: 형식 -> 이름 -> 언어. 디렉터리마다 16바이트 머리(이름 항목 수와 ID 항목 수가 +12, +14)와 그 뒤 8바이트 항목(u32 이름 또는 ID, u32 오프셋; 오프셋의 최상위 비트는 하위 디렉터리 표시)이 있다.
- 형식 16(
RT_VERSION), 그 첫 이름, 그 첫 언어: 잎은 데이터 항목(u32 RVA, u32 크기)이다. - 데이터는
VS_VERSIONINFO다: u16 길이, u16 값 길이, u16 형식, NUL 까지의 UTF-16 키VS_VERSION_INFO, 4바이트 채움, 그다음 첫 u32 가0xFEEF04BD인VS_FIXEDFILEINFO.dwFileVersionMS(+8)와dwFileVersionLS(+12)가 판HIWORD(MS).LOWORD(MS).HIWORD(LS).LOWORD(LS)를 준다.
35.3 패키지에 드는 것 [observed]#
- 판이 있는 파일:
File.Version= 네 부분 판,File.Language=MsiGetFileVersion이 알려 주는 언어, 곧VarFileInfo\Translation의 첫 언어(예 1033, 1042).MsiFileHash행은 없다. 설치된 파일을 다시 읽으면 같은 판이다. - 판이 없는 파일: 판 없음,
MsiFileHash행 있음(설치·복구·업그레이드·제거가 되는 가장 작은 패키지). - 머신 형식: x64 패키지는 x64 파일을, Arm64 패키지는 Arm64 파일을, x86 패키지는 x86 파일을 받는다. 일부러 하는 예외(64비트 패키지 속 32비트 도우미)는 조용히 받지 말고 선언하게 한다. 구성 요소 자체의 비트 수는 바뀌지 않는다.
35.4 안전하게 읽기#
오프셋과 크기는 쓰기 전에 모두 파일 길이와 대조하고, RVA 는 그 범위 전체를 담은 섹션을 거쳐서만 바꾸며, 기대한 세 디렉터리 단계에서 멈춘다 - 고리나 범위 밖 포인터를 가진 조작된 파일은 흔하다.