| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
- CodeEngn
- crackme
- ABI
- Dos Stub
- __cdecl
- Programmers
- Calling Convention
- 리버싱
- 코드엔진
- __vectorcall
- x32
- 크랙미
- RVA
- pe format
- 파이썬
- stack frame
- 프로그래머스
- Python
- __fastcall
- 실행파일
- 32bit
- __stdcall
- rev
- 함수 호출 규약
- Reversing
- Rich Header
- 리치헤더
- x64
- image section header
- Image dos header
- Today
- Total
kj0on
[Definition] Rich Header 본문
1. DOS Stub

IMAGE_DOS_HEADER의 e_lfanew 필드는 PE 시그니처 "PE\0\0"가 시작되는 오프셋을 가리키므로 윈도우로더는 DOS Stub 전체를 건너뛰고 곧바로 IMAGE_NT_HEADERS를 읽는다.

DOS Stub 영역은 크게 “This program cannot be run in DOS mode.” 문구를 띄우고 프로그램을 종료하는 MS-DOS Stub Program과 컴파일러, 링커 빌드 정보가 숨겨져 있는 Rich Header 두 부분으로 구성된다.
2. Rich Header
Rich Header는 Microsoft IDE에서 개발된 PE 파일에만 존재하는 데이터 구조다. Visual Studio 97 SP3부터 Microsoft 링커가 MS-DOS Program과 IMAGE_FILE_HEADER 사이에 자동으로 넣는 비공식 메타데이터로 제품 식별자, 빌드 번호, 빌드 프로세스 중 사용 횟수를 키로 XOR 암호화해 DanS와 Rich 키워드 구간에 저장한다. 빌드 시 해당 데이터 청크 삽입을 해제하는 방법은 없다. Microsoft는 이러한 기능을 구현했다고 발표하거나 도입 이유를 밝히지 않았고 관련 공식 문서도 공개하지 않았기 때문에 원래 용도를 확실히 알 수 없다.
3. 분석

MS-DOS Program과 IMAGE_FILE_HEADER 사이에서 "Rich"라는 키워드(0x52696368)를 기준으로 해당 영역이 Rich Header임을 파악할 수 있다.

"Rich" 키워드 바로 뒤에는 32bit의 xor Key가 나타난다. DATA는 제품 식별자, 빌드 번호, 사용횟수의 내용을 담고있고 해당 값들은 키값으로 xor된 값이다.

xor Key의 값을 DATA에 XOR 연산하면 간단하게 복호화가 가능하다.

복호화된 내용을 보면 "DanS" 키워드를 확인할 수 있으며 이는 Rich Header의 시작을 나타낸다. (해당 복호화 코드는 https://kj0on.tistory.com/26 참고)

"DanS" 이후에는 12바이트 분량의 0x00 패딩이 이어지는 구조를 가진다. Rich Header는 "DanS"로 시작해 `Rich"로 끝나는 구간으로 이 두 키워드를 통해 전체 범위를 파악할 수 있다. 복호화는 "Rich" 키워드부터 역순으로 XOR 연산을 수행하며 "DanS"키워드에 도달할 때까지 진행된다.
REDMOND, Wash., Updated, Feb. 20, 2004 — On Thursday, February 12, Microsoft became aware that portions of the Microsoft Windows 2000 and Windows NT 4.0 source code were illegally made available on the Internet. Subsequent investigation has shown this was not the result of any breach of Microsofts corporate network or internal security, nor is it related to Microsofts Shared Source Initiative or its Government Security Program, which enable our customers and partners, as well as governments, to legally access Microsoft source code. Microsoft reaffirms its support for both the Shared Source Initiative and the Government Security Program.
Microsoft continues to work closely with the U.S. Federal Bureau of Investigation and other law enforcement authorities on this matter. Microsoft source code is both copyrighted and protected as a trade secret. As such, it is illegal to post it, make it available to others, download it or use it. Microsoft will take all appropriate legal actions to protect its intellectual property. These actions include communicating both directly and indirectly with those who possess or seek to possess, post, download or share the illegally disclosed source code.
Specifically, Microsoft is sending letters explaining to individuals who have already downloaded the source code that such actions are in violation of the law. Additionally, Microsoft has instituted the use of alerts on several peer-to-peer clients where such illegal sharing of the source code has taken place. These alerts are designed to inform any user who conducts specific searches on these networks to locate and download the source code that such activity is illegal.
Questions about the ongoing investigation should be referred to the FBI.
Ricch Header 구조와 관련된 자료를 찾아보다 Microsoft 소스코드 유출에 관한 기사를 찾을 수 있었다. 기사의 내용을 요약하자면 "2004년 2월 12일, Microsoft Windows 2000 및 Windows NT 4.0 소스 코드 일부가 인터넷에 불법적으로 유포되었다. Microsoft는 이 문제에 대해 미국 연방수사국(FBI) 및 기타 법 집행 기관과 긴밀히 협력하고 있다. Microsoft 소스 코드는 저작권으로 보호되고 있기 때문에 이를 게시하거나 타인에게 제공하거나 다운로드 또는 사용하는 것은 불법이다." 이 당시 유출된 Windows 2000 소스코드를 통해 Rich Header의 내부 구조가 드러났다. 하지만 현재는 해당 소스코드를 직접 확인할 수는 없다. 게시된 사이트는 내려간 상태다. (https://news.microsoft.com/source/2004/02/12/statement-from-microsoft-regarding-illegal-posting-of-windows-2000-source-code)

As we can see in Figure 2, the data is an array of simple 64-bit PRODITEM structures that consist of two 32-bit fields: dwProdid and dwCount. The dwProdid field is a combination of a product identifier (ProdID) and its corresponding Build number and can be considered as two separate 16-bit values.
Rich Header와 관련된 연구에서 해당 소스코드를 볼 수 있다. 연구에 따르면 위에서 말한 DATA는 dwProdid와 dwCount로 구성된 구조체 배열 이라고 설명한다. dwProdids 멤버는 Build number와 product identifier의 조합이라고 한다. 추가적으로 위 이미지에 있는 코드를 보면 rgproditem[]의 크기는 가변적이라는점, "DanS" 키워드 이후 12byte 0패딩은 하드코딩되어 있다는점을 알 수 있다.

내용을 종합해 보면 Rich Header의 구성은 위와 같이 나타낼 수 있다. rgproditem[]의 개수를 제외한 필드는 고정 크기를 가진다. 그리고 하나의 item은 결과적으로 build number(2byte), product identifier(2byte), dwCount(4byte) 이렇게 3개로 구성된다.

값을 비교하면서 확인해 보면 build number(2byte), product identifier(2byte), dwCount(4byte)의 위치를 파악할 수 있다. 최종적으로 Rich Header의 구성은 위와같다. 각 멤버 사이즈에 맞게 Little Endian으로 값을 10진수로 변환하면 제품 식별자, 빌드 번호, 빌드 프로세스 중 사용 횟수를 알 수 있다.

파이썬출력 결과는 위와 같다. 빌드 번호, 제품 식별자, 빌드 프로세스 중 사용 횟수 값이 나타난다. 제품 식별자(product identifier)의 경우 열거형으로 되어있기 때문에 의미를 직접 파악하기는 힘들다. 값과 제품을 매칭해야한다.

ProdID는 Visual Studio 개발 툴체인의 제품을 나타낸다. 여기에는 링커, C/C++ 컴파일러, MASM, 리소스, imports, implibs 등의 객체가 포함된다고 한다. 해당 제품 식별자 값과 이름은 msobj140-msvcrt.lib에서 확인이 가능하다. 0x9300의 식별자 값이 나타나는데 이는 [이미지11]에서 04번째 출력결과인 30729.147.12에 해당한다. 이 중 식별자 값은 147(0x93)이다. 따라서 첫번째 아이템은 "Implib900(build number:30729) 빌드 중 12회 사용"의 값을 담고 있다.

xor Key는 Microsoft compiler(linker)에 의해 생성된다. 이 값은 IMAGE_DOS_HEADER, MS-DOS Program, 평문 Rich Header의 체크섬이다. 체크섬 게산 알고리즘은 CbBuildProdidBlock 함수에 존재하며 해당 함수는 link.exe에서 찾을 수 있다.
4. Tools
ProdID는 Visual Studio 툴체인의 구성 요소를 구분하는 값으로 [이미지12]와 같이 관련 정보는 msobj140-msvcrt.lib에서 확인할 수 있다. 하지만 이 값들을 일일이 수작업으로 매칭하는 것은 번거롭고 비효율적이기 때문에 이러한 정보를 자동으로 분석하거나 정리해 주는 다양한 도구들이 활용된다.
4-1. richprint

빌드 및 설명은 https://kj0on.tistory.com/27 참고
4-2. pefile
import pefile
filepath = "HelloWorld.exe"
pe = pefile.PE(filepath)
rich_info = pe.parse_rich_header()
for k in rich_info:
print(f"{k} : {rich_info[k]}")

pefile 사용법은 https://pefile.readthedocs.io/en/latest/usage/index.html 참고
4-3. PE-bear

빌드 및 설명은 https://kj0on.tistory.com/28 참고
5. PE 파일의 지문
Rich Header를 분석하면 악성코드의 구성요소 유형과 사용된 빌드 도구를 파악할 뿐 아니라 유사한 샘플을 찾는 데에도 도움을 줄 수 있다. 매일 재배포되는 Crimeware kits의 경우 헤더를 통해 소스코드가 유출되었거나 공개된 가능성을 알려줄 수 있고 단일 공격자인지를 파악하는데에도 도움을 줄 수 있다. 또한 이 악성코드를 감싼 패커의 헤더 역시 고유한 특징을 나타내는 경우가 많으며 유사한 특징을 가지는 샘플을 한 그룹으로 묶을 수 있다. 비정상적인 오프셋이나 헤더 크기, 유효하지 않은 식별자 또는 빌드 버전과의 조합, 프로젝트 크기에 비해 맞지 않는 이미지 크기 등의 불일치는 상황에 따리 쉽게 식별이 가능하며 이러한 이상 정보들을 기반으로 휴리스틱 탐지를 할 수 있다. 리치 헤더가 파일의 일부에만 나타난다면 그다지 유용한 기능이 아닐 것이다. 약 100만개의 악성 데이터 세트를 분석한 결과 PE의 73.20%가 리치 헤더를 포함하고 있는 것으로 나타났다. 하지만 멜웨어 개발자들이 이 기능을 더 잘 인식하고 리치 헤더를 난독화하거나 완전히 제거하려고 시도하면 이 수치는 시간이 지남에 따라 서서히 감소할 것으로 예상된다. Microsoft가 후속 Visual Studio 버전에서 이 기능을 완전히 삭제하기로 결정한다면 더 빠른 변화가 있을 수 있겠지만 최근 출시된 Visual Studio 2019 에서는 링커가 여전히 리치 헤더를 생성한다. 결국 Rich Header는 단순한 구조 이상의 의미를 가지며 악성코드 분석과 추적에 있어 강력한 단서를 제공할 수 있다. 다만 그 존재와 활용 가능성은 향후 도구의 변화나 공격자의 대응 방식에 따라 달라질 수 있으므로 이에 대한 이해와 함께 변화에 유연하게 대응하는 접근이 필요하다.
6. 참고자료
[1] VB2019 paper: Rich Headers: leveraging this mysterious artifact of the PE format, https://www.virusbulletin.com/virusbulletin/2020/01/vb2019-paper-rich-headers-leveraging-mysterious-artifact-pe-format/
[2] PE File Rich Header, https://offwhitesecurity.dev/malware-development/portable-executable-pe/rich-header/
[3] A dive into the PE file format - PE file structure - Part 2: DOS Header, DOS Stub and Rich Header, https://0xrick.github.io/win-internals/pe3/
[4] The devil’s in the Rich header, https://securelist.com/the-devils-in-the-rich-header/84348/
'Reversing > Definition' 카테고리의 다른 글
| [Definition] RVA to RAW (0) | 2025.07.07 |
|---|---|
| [Definition] VA & RVA & RAW (0) | 2025.07.06 |
| [Definition] 64비트 윈도우 실행 파일 구조 (PE+ Format) (0) | 2025.07.04 |
| [Definition] MS-DOS Stub Program (0) | 2025.07.04 |
| [Definition] 32비트 윈도우 실행 파일 구조 (PE Format) (2) | 2025.07.03 |