연재 순서
Creative Commons License

1. OLE 파일 구조 분석 (1) - Header, BBAT, SBAT

2. OLE 파일 구조 분석 (2) - Root Storage

3. OLE 파일 구조 분석 (3) - Stream Object

OLE File Format

OLE란 Object Linking and Embedding 약자로서 객체 연결 및 삽입을 뜻하며 복합 이진 파일 형식(Compound File Binary Format)이라고도 한다.

Microsoft에서 제작한 OLE File Format은 마치 하나의 작은 파일 시스템과 같은 구조를 지니고 있어 상/하위 파일 버전에 대한 뛰어난 호환성을 가지고 있다. 그렇기에 MS Office 외에 다른 워드 프로세서들도 OLE 파일 형식을 사용하고 있다.

OLE 파일 구조

Storage and Stream

OLE 파일 구조는 마치 하나의 작은 파일 시스템과 같은 구조를 가지고 있다. 스트림은 문서 내용을 담고 있는 파일, 스토리지는 파일을 담는 폴더와 같다. 스토리지와 스트림의 내용은 문서 종류(doc, hwp, xls 등)에 따라 다를 수 있다.

파일 종류에 따른 OLE 내부 구조

Header and Data Section

OLE 파일 구조는 크게 헤더 영역과 데이터 영역으로 나뉜다.

OLE 파일 구조 (헤더와 데이터)

헤더 영역에는 File Signature, Sector Count, Sector Size, Start Sector ID 등 OLE 파일을 구성하고 있는 주요 정보들이 저장되어 있고, 데이터 영역에는 앞서 설명한 스트림과 스토리지 그리고 그것들을 구성하고 있는 테이블 정보(BBAT, SBAT)가 저장된다. 데이터 영역 대부분은 스트림이 차지한다

File Sector

OLE 파일은 섹터 단위로 구성된다. 1섹터 크기는 512바이트이다. 예를 들어 만약 파일 크기가 2560바이트일 경우 헤더 영역은 고정 512바이트, 데이터 영역은 파일 크기에서 헤더 크기만큼 뺀 2560-512=2048바이트로 구성된 것이다. 여기서 주의해야할 점은 나중에 데이터 영역에 Sector ID로 접근을 할 때 헤더 크기는 빼고 계산해야 한다는 것이다. 이 부분은 나중에 다시 설명하도록 하겠다.

OLE 파일 구조 (섹터) OLE 파일 구조 (헤더와 데이터 섹터 맵핑)

Header Information

OLE 파일에서 가장 먼저 읽어야 할 것은 헤더이다. 헤더에는 OLE 파일에 대한 다양한 정보를 저장하고 있다. 헤더 영역은 파일 시작 위치부터 1섹터(512바이트) 만큼이다. Hex Viewer 또는 Microsoft에서 제공하는 OffVis를 통해 직접 확인해 볼 수 있다.

OLE 파일 구조 (헤더: Magic ID)

이름 Magic ID
위치 0x00 ~ 0x07
크기 8바이트
일반적인 값 D0 CF 11 E0 A1 B1 1A E1
설명 OLE 파일임을 나타내는 Signature.
정상적인 OLE 파일의 경우 이 값은 반드시 0xE11AB1A1E011CFD0 이어야 한다.

OLE 파일 구조 (헤더: CLSID)

이름 CLSID
위치 0x08 ~ 0x17
크기 16바이트
일반적인 값 0x00 …
설명 OLE CLSID 값

OLE 파일 구조 (헤더: Minor Version)

이름 Minor Version
위치 0x18 ~ 0x19
크기 2바이트
일반적인 값
설명 파일의 Minor Version 값

OLE 파일 구조 (헤더: Major Version)

이름 Major Version
위치 0x1A ~ 0x1B
크기 2바이트
일반적인 값
설명 파일의 Major Version 값

OLE 파일 구조 (헤더: Byte Order)

이름 Byte Order
위치 0x1C ~ 0x1D
크기 2바이트
일반적인 값 FE FF(Little Endian), FF FE(Big Endian)
설명 값 저장 방식

OLE 파일 구조 (헤더: Sector Shift (BBAT))

이름 Sector Shift (BBAT)
위치 0x1E ~ 0x1F
크기 2바이트
일반적인 값 09 00
설명 1 섹터 크기 (2 승수로 나타내며 9인 경우 2^9 = 512)

OLE 파일 구조 (헤더: Small Sector Shift (SBAT))

이름 Small Sector Shift (SBAT)
위치 0x20 ~ 0x21
크기 2바이트
일반적인 값 06 00
설명 SBAT 섹터 1개 크기 (2 승수로 나타내며 6인 경우 2^6 = 64)

OLE 파일 구조 (헤더: Reserved1)

이름 Reserved1
위치 0x22 ~ 0x23
크기 2바이트
일반적인 값 0x00 …
설명 사용하고 있지 않음

OLE 파일 구조 (헤더: Reserved2)

이름 Reserved2
위치 0x24 ~ 0x27
크기 4바이트
일반적인 값 0x00 …
설명 사용하고 있지 않음

OLE 파일 구조 (헤더: Reserved3)

이름 Reserved3
위치 0x28 ~ 0x2B
크기 4바이트
일반적인 값 0x00 …
설명 사용하고 있지 않음

OLE 파일 구조 (헤더: Number of Big Block Allocation Table Depot)

이름 Number of Big Block Allocation Table Depot
위치 0x2C ~ 0x2F
크기 4바이트
일반적인 값
설명 BBAT Depot 개수를 나타낸다. 이 개수가 109개 이상일 경우엔 Extra BBAT를 참조해야 한다.

OLE 파일 구조 (헤더: Root Storage Sector ID)

이름 Root Storage Sector ID
위치 0x30 ~ 0x33
크기 4바이트
일반적인 값
설명 Root Entry(Root Storage) 시작 섹터 번호. 헤더 다음으로 가장 먼저 읽어야할 부분이다. 이 위치가 0x27인 경우 다음과 같이 계산할 수 있다. 이전에 앞서 설명한대로 헤더 다음 섹터부터 0번이기 때문에 헤더 크기만큼 추가로 더해야한다.
0x27 * 0x200(Sector Size) + 0x200(Header Size) = 0x5000

OLE 파일 구조 (헤더: Reserved4)

이름 Reserved4
위치 0x34 ~ 0x37
크기 4바이트
일반적인 값 0x00 …
설명 사용하고 있지 않음

OLE 파일 구조 (헤더: Max Small Stream Size)

이름 Max Small Stream Size
위치 0x38 ~ 0x3B
크기 4바이트
일반적인 값 00 10 00 00
설명 이 사이즈 미만인 스트림을 읽을 때는 SBAT를 참조해야 한다. 이 사이즈 미만인 스트림은 Small Stream이다.

OLE 파일 구조 (헤더: SBAT Depot Start Sector ID)

이름 SBAT Depot Start Sector ID
위치 0x3C ~ 0x3F
크기 4바이트
일반적인 값
설명 Small Block Allocation Table Depot 시작 섹터 번호이다. 이 위치를 따라가면 SBAT Depot를 만날 수 있다.

OLE 파일 구조 (헤더: SBAT Sector Count)

이름 SBAT Sector Count
위치 0x40 ~ 0x43
크기 4바이트
일반적인 값
설명 Small Block Allocation Table 크기 값이며, 몇 개의 섹터를 차지하는지에 대한 값이다. 1이면 SBAT 크기는 다음과 같이 결정된다.
1 * 512(Sector Size) = 512

OLE 파일 구조 (헤더: Start Block of Extra Big Block Allocation Table)

이름 Start Block of Extra Big Block Allocation Table
위치 0x44 ~ 0x47
크기 4바이트
일반적인 값 FE FF FF FF (BBAT 개수가 109개 이하일 경우)
설명 확장된 BBAT 시작 섹터 번호. Number of Big Block Allocation Table 값이 109개가 넘어서면 여기를 참조해야 한다. 이 값을 따라가면 확장된 BBAT가 나오게 된다.

OLE 파일 구조 (헤더: Number of Extra Big Block Allocation Table)

이름 Number of Extra Big Block Allocation Table
위치 0x48 ~ 0x4B
크기 4바이트
일반적인 값 00 00 00 00 (BBAT 개수가 109개 이하일 경우)
설명 앞서 나온 확장된 BBAT 개수. 예를 들어 만약 BBAT가 120개여서 확장된 경우 이 값은 확장된 크기인 11이다.

OLE 파일 구조 (헤더: BBAT Depot)

이름 BBAT Depot
위치 0x4C ~ 0x01FF
크기 436바이트
일반적인 값
설명 여기서부터 헤더 끝인 0x01FF까지 109개의 BBAT 엔트리들이 저장된다. 4바이트씩 Sector ID를 가지고 있으며, BBAT 개수가 109개 이상일 경우 Start Block of Extra Big Block Allocation Table를 참조해야 한다.

BBAT (Big Block Allocation Table)

OLE 파일은 섹터 단위로 이루어져 있다. 마찬가지로 OLE 파일을 구성하고 있는 데이터들도 전부 섹터 단위로 구성되어 있다. 1섹터 크기는 512바이트이다. 512바이트를 초과하면 한 개 섹터에 데이터를 모두 저장할 수가 없기 때문에 나눠서 저장을 해야한다. 예를 들어 4480바이트 크기 데이터는 9섹터에 각각 512바이트씩 나눠서 저장한다.

BBAT Depot 참조 과정

BBAT Depot 데이터

BBAT는 나눠서 저장한 데이터들을 연결하는 연결고리 저장소이다. 데이터들은 항상 순차적으로 섹터에 저장하지 않기 때문에 반드시 BBAT를 참조하여 직접 연결을 해줘야만 한다. BBAT에는 참조하는 섹터에 연결된 다음 섹터 번호가 저장되어 있다. 데이터를 이루는 섹터는 단일 연결 구조로 구성되어 있다.

Small Block Allocation Table (SBAT)

파일 헤더에 나와있는 Max Small Stream Size보다 크기가 작은 스트림을 읽을 땐 BBAT가 아닌 SBAT를 참조해야 한다. SBAT는 BBAT와 똑같은 메커니즘이다. Small Sector 한 개 크기는 64바이트이다. 만약 256바이트 스트림을 저장할 경우 4개의 Small Sector에 각각 64바이트씩 저장해야 한다. Small Stream (Small Sector)는 Root Storage에 저장되어 있다. 따라서 Small Stream을 읽기 위해서는 Root Storage를 BBAT를 통해 먼저 읽어야 한다.

SBAT Depot 참조 과정

SBAT Depot 데이터

Root Storage (Root Entry)

헤더 다음으로 가장 먼저 읽어야 할 항목이다. 파일 내에 존재하는 모든 스트림과 스토리지를 포함하고 있는 최상위 폴더이고 Small Stream (Small Sector)을 저장하고 있다. BBAT를 참조하여 헤더의 Root Storage Sector ID와 연결된 섹터들을 전부 합친다면 파일 전체적인 구조를 파악할 수 있다.

Root Storage 구조 출력

결론

이번 글에서는 OLE 파일 구조 전체적인 정보에 대해 기술하였다. 다음에는 Root Storage 구조에 대한 자세히 알아보기로 한다.

크리에이티브 커먼즈 라이선스
Creative Commons License
이 저작물은 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 국제 라이선스에 따라 이용할 수 있습니다.
Jin-Hyeong Choe's profile image

Jin-Hyeong Choe

2020-05-04 18:00

Read more posts by this author