[File Structure] OLE(Object Linking and Embedding) 파일 구조
기초 개념
OLE 파일(CFB, Compound File Binary) 포맷은 일반적으로 복합 문서를 지칭하며 MS의 문서 포맷으로 사용된다.
폴더 역할의 스토리지(Storage)와 파일 역할의 스트림(Stream)으로 구성되어 있으며 512byte의 섹터 단위로 저장되어있다.
CFB(OLE)의 구성 요소
OLE 파일은 헤더 블록(512byte)과 데이터 블록(512byte~)으로 구분할 수 있다.
헤더 블록
OLE 파일 전체의 주요 정보들을 가지고 있다.
Header Signature | 8bytes | 0x0000 | 0xD0 CF 11 E0 A1 B1 1A E1 |
Header CLSID | 16bytes | 0x0008 | 사용되지 않는 클래스 ID 저장(전부 0) |
Minor Version | 2bytes | 0x0018 | 0x003E(Major가 0x0003 혹은 0x0004) |
Major Version | 2bytes | 0x001A | 0x0003(ver3) 혹은 0x0004(ver4) |
Byte Order | 2bytes | 0x001C | 0xFFFE |
Sector Shift | 2bytes | 0x001E | 0x0009(ver3, 512bytes) 혹은 0x000C(ver4, 409) - major version에 따라 변경, 섹터 사이즈 명시 |
Mini Sector Shift | 2bytes | 0x0020 | 0x0006 - mini stream size 64bytes 명시 |
reserved | 6bytes | 0x0022 | 모두 0 |
Number of Directory Sectors | 4bytes | 0x0028 | directory 섹터의 개수 - ver3일 경우 0 |
Number of FAT Sectors | 4bytes | 0x002C | FAT 섹터의 개수 |
First Directory Sector Location | 4bytes | 0x0030 | directory stream 시작 넘버 |
Transaction Signature Number | 4bytes | 0x0034 | |
Mini Stream Cutoff Size | 4bytes | 0x0038 | 0x00001000 |
First Mini FAT Sector Location | 4bytes | 0x003C | mini FAT 시작 위치 |
Number of Mini FAT Sectors | 4bytes | 0x0040 | mini FAT sectors 개수 |
First DIFAT Sector Location | 4bytes | 0x0044 | DIFAT 시작 위치 |
Number of DIFAT Sectors | 4bytes | 0x0048 | DIFAT 섹터 개수 |
DIFAT | 436bytes | 0x004C | ver4에서는 헤더 사이즈(512bytes)가 섹터 사이즈(4096bytes)보다 작기에 남은 부분은 모두 0으로 채움 |
+)위의 예시를 기반으로 directory entry를 찾아가는 법을 설명하겠다.
먼저 first directory sector location를 확인해서 위치를 찾아야한다. 위 예시의 값은 0x01이다.
0x01은 10진수로 1이다. 즉, 1번째 블록에 위치한다는 것을 뜻한다. 512byte 기준이므로 512를 곱해주고 헤더가 -1이므로 512를 더하면 위치 값을 확인할 수 있다.
directory entry 위치 = 512(헤더가 -1 섹터)+512*(first directory sector location의 10진수)
해당 위치로 가면 Root Entry를 확인할 수 있다. 이것이 directory entry의 시작을 알리는 문자열이다.
Directory Entry
directory sector의 그룹으로 각각의 storage object나 stream object가 single directory entry를 표현한다. 128bytes로 고정되어 있으며 directory entry 안의 이름은 unicode UTF-16 code points다.
Directory Entry Name | 64bytes | 0x00 | UTF-16으로 인코딩 된 storage 혹은 stream의 이름 |
Directory Entry Name Length | 2bytes | 0x40 | 길이는 64를 넘지않음. |
Object Type | 1byte | 0x42 | 0x00(Unknown or unallocated), 0x01(Storage Object), 0x02(Stream Object), 0x05(Root Storage Object) |
Color Flag | 1byte | 0x43 | 0x00(red), 0x01(black) |
Left Sibling ID | 4bytes | 0x44 | left sibling stream ID, 없을경우 NOSTREAM (0xFFFFFFFF) |
Right Sibling ID | 4bytes | 0x48 | right sibling stream ID, 없을경우 NOSTREAM (0xFFFFFFFF) |
Child ID | 4bytes | 0x4C | child object의 stream ID |
CLSID | 16bytes | 0x50 | 0으로 채워짐, 0이 아닐 경우는 object class GUID가 시작 어플리케이션 파라미터로 쓰일 경우 |
State Bits | 4bytes | 0x60 | 기본값은 0 |
Creation Time | 8bytes | 0x64 | |
Modified Time | 8bytes | 0x6C | |
Starting Sector Location | 4bytes | 0x74 | 시작 섹터 위치(stream object), 모두 0(storage object) mini stream 시작 섹터(root storage object) |
Stream Size | 8bytes | 0x7C | user-defined data size |