Exif format 이란?
: Exchangable Image File의 약자로 기본적으로 JPEG file format과 동일하다.
★ "사진의 정보" & "썸네일 사진"을 담는다.
예를 들면 쉽게 이해가 된다.
[카메라 정보]
제조 업체 : Apple
카메라 모델 : iPhone 6s
[이미지 정보]
사진 크기 : 2192 * 2921
너비 : 2192픽셀
높이 : 2921픽셀
수평 해상도 : 72 DPI
수직 해상도 : 72 DPI
등의 정보들이 담겨있는데, 이 정보들이 바로 JPEG포맷에 삽입된 Exif format이다.
< JPEG 파일 구조 >
JPEG라면 파일의 시작은 항상 SOI(Start of Image) Marker인 "FF D8"이다. 다음으로 APP0(JFIF)과 APP1(Exif) marker, 이후로 다른 여러 Marker들이 위치한다. 여기서 우리는 APP1(Exif format)을 구체적으로 다룬다.
EXIF Data Structure 를 자세히 알아보자.
APP1 Marker ("FF E1") |
|
APP1 Data |
APP1 데이터 크기 |
Exif Header |
|
TIFF Header |
|
IFD0 (main image) { 디렉토리 엔트리0 디렉토리 엔트리1 디렉토리 엔트리2 . . . 마지막 4bytes는 IFD1의 offset } |
|
IFD0의 Data 영역. |
|
Exif SubIFD { 디렉토리 엔트리0 디렉토리 엔트리1 디렉토리 엔트리2 . . . 끝. } |
|
SubIFD의 Data 영역 |
|
IFD1 (Thumbnail Image) { 디렉토리 엔트리0 디렉토리 엔트리1 디렉토리 엔트리2 . . . 끝. } |
|
IFD1의 Data 영역 |
|
Thumbnail Image |
Exif format에서는 '이미지 정보'와 '섬네일'을 담는다고 앞서 말했다. IFD0에서 이미지 정보를, IFD1에서 섬네일을 다루며 IFD 링크가 끝난다.
IFD0/IFD1에서는 '셔터 스피드', 'focal length' 등과 같은 어떠한 카메라 정보도 담지 않기 때문에 IFD0에는 항상 Exif SubIFD의 Offset을 담는 Special Tag : Exif Offset(0x8769)가 포함되고, Exif SubIFD에서 digicam의 정보를 다룬다.
여기서,
IFD0 (main image),
Exif SubIFD,
IFD1 (thumbnail image)
에서 각각 다룰 수 있는 Marker들이 다르다는 것을 짐작할 수 있다.
각 디렉터리가 다루는 Marker들은 글의 마지막 부분에 첨부하였다.
이제 JEPG 샘플을 통해 Exif format 요소를 하나씩 살펴보자.
● APP1 Marker
JFIF format(APP0 Marker "FF E0")과 구분되도록 Exif format은 APP1 Marker "FF E1"을 사용한다.
● APP1 데이터 크기
APP1 Marker 다음에는 APP1 크기를 나타내는 2bytes가 있다. (0x1214 = 4628 bytes)
● Exif Header
다음으로 Exif Header이다. ( 0x45 0x78 0x69 0x66 0x00 0x00 고정 문자열 "Exif " )
● TIFF Header
Exif 헤더 다음에는 TIFF 헤더가 위치한다. TIFF 헤더는 3가지 요소를 가진다.
1. 첫번째로 byte aling 표기방식을 구분하는 2bytes.
0x49 0x49 (문자열 "I I") |
intel (리틀엔디언) |
0x4D 0x4D (문자열 "M M") |
motorola (빅엔디언) |
2. 두번째로 Tag Mark 2btyes
"0x002A"로 고정인데, byte align에 맞게 표기된다.
3. 세번째로 첫번째 IFD의 Offset 4bytes
byte align 헤더의 시작을 0으로보고 Offset을 측정한다. 대부분 TIFF 헤더 이후 바로 IFD0가 위치하므로 0x00000008로 고정이라 보면 된다.
● IFD (Image File Directory)
Exif Header에는 IFD0(main image)와 IFD1(thumbnail image)가 존재한다. IFD의 구조를 먼저 살펴보자.
엔트리 개수 |
n개 (2bytes) |
|||
Entry 0 |
Tag (2bytes) |
Format (2bytes) |
컴포넌트 개수 (4bytes) |
data / offset (4bytes) |
Entry 1 |
Tag (2bytes) |
Format (2bytes) |
컴포넌트 개수 (4bytes) |
data / offset (4bytes) |
Entry 2 |
Tag (2bytes) |
Format (2bytes) |
컴포넌트 개수 (4bytes) |
data / offset (4bytes) |
......... |
|
|
|
|
Entry n-1 |
Tag (2bytes) |
Format (2bytes) |
컴포넌트 개수 (4bytes) |
data / offset (4bytes) |
next IFD Offset |
Offset (4bytes) |
|||
"Data 영역" | data 크기가 4bytes가 넘어 데이터 대신 Offset이 적힌 엔트리의 실질적인 데이터들. 각 offset에 (컴포넌트당 bytets 수)*(컴포넌트 개수)=길이만큼 data가 쓰여있음. |
IFD의 엔트리는 하나당 12bytes를 차지하는데, 여기서 데이터를 담을 수 있는 공간은 4btyes에 불과하다. 데이터 길이가 4bytes이하라면 바로 데이터를 담으면 되지만 4btyes를 초과하는 경우에는 데이터가 담긴 Offset을 저장하고 실제 데이터는 각 IFD 끝에 나오는 "Data 영역"에 저장된다.
● IFD0 (main image)
- IFD0 엔트리 개수 : 0x0B.
- 0x0B 만큼의 Entry List 나열. (엔트리 하나 크기는 12bytes로 고정)
- 다음 IFD Offset 명시.
- "Data 영역"
Entry는 4개의 요소로 구성된다.
Tag |
어떤 정보를 담고 있는지 표시. ex) 카메라 제조업체 |
Format |
01 (unsigned byte) : 컴포넌트당 1btye 02 (ascii string) : 컴포넌트당 1btye 03 (unsigned short) : 컴포넌트당 2bytes 04 (unsigned long) : 컴포넌트당 4bytes 05 (ungisned rational) : 컴포넌트당 8bytes 06 (signed byte) : 컴포넌트당 1byte 07 (undefiend) : 컴포넌트당 1byte 08 (signed short) : 컴포넌트당 2bytes 09 (signed long) : 컴포넌트당 4bytes 10 (signed rational) : 컴포넌트당 8bytes 11 (single float) : 컴포넌트당 4bytes 12 (double float) : 컴포넌트당 8bytes 컴포넌트당 몇 bytes를 차지하는가! |
컴포넌트 개수 |
data를 이루는 컴포넌트 개수. |
Data 혹은 Offset |
data가 4bytes 이하라면 바로 적고, 4bytes를 초과한다면 Offset을 명시한다. (데이터는 Entry List 이후인 "Data영역"에 위치.) 데이터 크기 계산 : (컴포넌트당 bytes수) * (컴포넌트 개수) |
Entry List가 끝난 이후의 4bytes는 다음 IFD의 Offset이다.
※ Exif format에는 IFD0(main image)와 IFD1(thumbnail image)만 다루므로 IFD0에만 다음 IFD의 Offset이 담기고, IFD1과 subIFD의 "다음IFD Offset" 값은 00000000이다.
Example)
첫번째 엔트리를 보면 Tag : "01 0F"로 Make(카메라 제조사)를 뜻한다. data가 4bytes가 넘으므로 "Data영역"에 저장되며 해당 Offset을 보면 "Apple"이라고 애플사에서 만든 카메라임을 알 수 있다.
● Exif SubIFD
IFD0과 1에서 다루지 않는 카메라 정보는 따로 SubIFD에서 명시한다.( 각각 다루는 Marker가 다름.) 따라서 SubIFD는 "항상" 존재하며 IFD0의 Marker에서 SubIFD의 Offset을 명시한다.
위 샘플 그림을 보면, IFD0의 Entry에서 0x8769라는 Exif SubIFD Marker가 Offset 0x000000CE에 SubIFD가 있다고 알려준다.
IFD0의 "byte align"이 Offset 계산의 시작점이므로,
{ subIFD 시작지점 = 0xCE(subIFD Offset) + 0x1E(Offset계산 시작지점) = 0xEC } 를 보면 subIFD가 있다! subIFD의 구조도 일반 IFD구조와 동일하다.
● IFD1 (thumbnail image)
IFD0의 "다음 IFD Offset" 4bytes 값이 바로 IFD1(thumbnail image)의 Offset이다.
이또한 IFD0의 byte align 위치를 기준으로한 Offset이므로 0x1E를 더해야 진짜 IFD1의 시작주소다.
{ 0x786 + 0x1E = 0x7A4 }를 보면 IFD1가 위치한다!
IFD구조에 이어서 바로 Thumbnail Image가 따라온다. Start Of Image Marker인 "FF D8"을 보면 섬네일 JPEG를 다루는 구나 알 수 있다.
이후 구조는 JFIF 구조이므로 Exif 구조 분석은 여기서 마무리한다.
----------------------------------------------------------------------------------------------------------------
● 각 디렉터리가 다룰 수 있는 Marker 정리
사진 출처 : https://www.media.mit.edu/pia/Research/deepview/exif.html
1. IFD0 (main image)가 쓰는 Tag들
2. Exif SubIFD가 쓰는 Tag들
3. IFD1 (thumbnail image)가 쓰는 Tag들
'취약점 분석 > 여러가지 구조 형식' 카테고리의 다른 글
JPEG 헤더 구조 (0) | 2018.11.21 |
---|---|
ZIP Archive file format (0) | 2018.09.19 |
GZIP header format (.gz extention) (0) | 2018.01.10 |