Compound File Binary Format (CFBF)
: 복합 파일, 복합 문서 형식, 여러 파일 및 스트림을 단일 파일에 저장하기 위한 복합문서 파일형식
Compound 파일구조는 FAT와 유사함
파일 → 파일 할당 테이블과 함께 연결된 섹터로 분할됨
디렉토리 → 섹터 ID가 있는 포함된 파일에 대한 정보
구조
512바이트 헤더 레코드와 헤더에 정의된 여러 섹터로 구성
섹터의 길이는 128*2^n (128, 256, 512, 1024 등....)의 크기를 지원
0 sector | 1 sector |
Header | Header 에 정의된대로 섹터가 구성됨 |
* 섹터의 길이 하한선이 128인 이유?
: 디렉토리 섹터에 단일 디렉토리 항목을 맞추기 위해 필요한 최소값.
▷ 섹터의 유형
- FAT : 섹터 인덱스 체인 정보
- Mini FAT: MiniStream 내의 miniSector 체인 정보
- Double Indirect FAT(DIFAT) : FAT 섹터 위치
- Directory Sector : 디렉토리 항목 포함
- Stream Sector : 파일의 데이터 포함
- Range Rock Sector : 큰 파일의 바이트 범위 잠금 영역 포함
<Header>
00 |
01 |
02 |
03 |
04 |
05 |
06 |
07 |
08 |
09 |
10 |
11 |
12 |
13 |
14 |
15 |
File Header Signature |
Header CISID |
||||||||||||||
|
Minor Version |
Major Version |
Byte order Identifier |
Sector Shift |
|||||||||||
Size Mini Sector |
예약영역 |
Directory sectors 개수 |
FAT sectors 개수 |
||||||||||||
SEC ID |
Transaction Signature Number |
Mini Stream Cutoff size |
Mini FAT 위치 |
||||||||||||
Mini FAT 개수 |
first DIFAT Sector Loaction |
DIFAT Sector의 개수 |
FAT #1 위치 |
||||||||||||
FAT #2 위치 | ...... | FAT #N 위치 | 0xFFFFFFFF |
| Offset | 길이(byte) | 설명 |
File Header Signature | 0x00 | 8 | 파일의 종류 시그니쳐 D0 CF 11 E0 A1 B1 1A E1 는 hwp, doc 등의 파일 파일 시그니쳐 종류 : http://forensic-proof.com/archives/300 |
Header CISID | 0x08 | 8 | 예약된 클래스 , 사용하지 않는다. 모두 0으로 기입되어있음 |
Minor Version | 0x18 | 2 | 요약 변경을위한 버젼 번호 major의 값이 0x0003, 0x0004일경우 0x003E |
Major Version | 0x1A | 2 | 변경사항에 관련된 버전정보 0x0003(ver.3) 이나 0x0004(ver.4)로 됨 |
Byte Order Identifier | 0x1C | 2 | 바이트의 순서를 Little-Endian 이냐 Big-Endian이냐 정하는곳 LE: FE FF / BE : FF FE |
Sector Shift | 0x1E | 2 | 섹터의 크기를 정의함 Major의 ver3 = 9 / ver4 = C 를 기재 하는데 2^9 = 512 2^13 = 4096 을 의미함 |
Mini Sector Shift | 0x20 | 2 | Mini Sector의 크기를 정의함. 6으로 정의되야 한다. 2^6 = 64 |
Reserved 영역 | 0x22 | 6 | 0으로 채워준다 |
Directory Sector 개수 | 0x28 | 4 | 디렉토리 섹터의 개수 (Major = 3 이면 0 ) |
FAT Sector 개수 | 0x2C | 4 | FAT 섹터의 개수 |
SEC ID | 0x30 | 4 | 첫 번째 디렉토리 개수 (Root Directory, Directory Entry) |
Transaction Signature Number | 0x34 | 4 | 파일이 특정 API에 의해 저장되면 숫자가 증가됨, 파일이 트랜잭션이 아닌경우 0으로 써주면됨 |
Mini Stream Cutoff size | 0x38 | 4 | 0x00001000 으로 설정되야함 Mini FAT 와 FAT의 분기 기준 ? |
Mini FAT location | 0x3B | 4 | Mini FAT 위치 |
Mini FAT 개수 | 0x40 | 4 | Mini FAT 개수 |
first DIFAT Sector loaction | 0x44 | 4 | 처음 DIFAT Sector의 위치 여기서는 현재위치를 말한다. |
DIFAT Sector 개수 | 0x48 | 4 | DIFAT의 개수 |
FAT#N의 위치 | 0x4B ~ | 4 | FAT의 위치를 말해준다. 하나의 FAT당 4Byte 씩 할당되며 그 이후 나머지는 FF로 채워줌 (major Ver.4의 경우 헤더의 나머지부분은 0으로 채워준다) |
<Root Directory Entry>
00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 |
Directory Entry Name | |||||||||||||||
Directory Entry Name Length | Object Type | Color Flag | Left Sibling ID | Right Sibling ID | Child ID | ||||||||||
CLSID | |||||||||||||||
State Bits | Creation Time | Modified Time | |||||||||||||
Modified Time | Starting Sector Location | Stream Size |
| Offset | 길이(byte) | 설명 | ||||||||||
Directory Entry Name | 0x00 | 64 | 64Byte UNICODE Null 문자로 종료되야한다. '/','\',':','!' 의 문자를 사용할 수 없음 | ||||||||||
Directory Entry Name Length | 0x40 | 2 | Directory Entry Name 문자열의 길이와 일치해야함. 개수에 null도 포함해서 계산 64초과해선 안됨 | ||||||||||
Object Type | 0x42 | 1 | 파일의 유형에 따라 값이 다르다.
| ||||||||||
Color Flag | 0x43 | 1 | 0x00과 0x01 밖에 올 수 없다. root의 경우 0x01
| ||||||||||
Left Sibling ID | 0x44 | 4 | 왼쪽 스트림 아이디를 포함. 없으면 0xFFFFFFFF | ||||||||||
Right Sibling ID | 0x48 | 4 | 오른쪽 스트림 아이디를 포함. 없으면 0xFFFFFFFF | ||||||||||
Child ID | 0x4C | 4 | 하위 스트림 아이디 포함. 없으면 0xFFFFFFFF | ||||||||||
CLSID | 0x50 | 16 | 저장소, 루트 저장소의 경우에 개채 클래스 GUID가 포함됨, 스트림에서는 모두 0 | ||||||||||
State Bits | 0x60 | 4 | 사용자 정의 플래그 | ||||||||||
Creation Time | 0x64 | 8 | 생성 시간, Root에는 0 | ||||||||||
Modified Time | 0x6C | 8 | 수정 시간, UTC 시간으로 저장 | ||||||||||
Starting Sector Location | 0x74 | 4 | Root Storage : 미니스트림의 첫번째 섹터 Mini FAT : 데이터가 존재하는 곳의 첫번째 섹터 | ||||||||||
Stream Size | 0x78 | 8 | >= 4096 → FAT < 4096 → Mini FAT |
실습
Compound 파일에서 데이터를 추출하기
: 데이터를 추출하기위해서는 파일의 정보가명시되어있는 Directory Entry와 FAT 그리고 Data Stream영역을 알아내야 한다.
compound file은 헤더정보를 토대로 파일의 몸통이 생성되기 때문에 헤더값을 살펴보고 분석하자.
<Header>
D0 CF 11 E0 A1 B1 1A E1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3E 00 03 00 FE FF 09 00 06 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 10 00 00 02 00 00 00 02 00 00 00 FE FF FF FF 00 00 00 00 00 00 00 00 |
주의
컴파운드 파일을 분석할때 헤더에서 위치등을 지정하는 경우 지정된 장소는 실제장소와 1의 차이가 난다.
헤더에서 지정할 경우 자신을 제외하기 때문이다. 아래의 그림으로 설명하겠다.
|
0 | 1 | 2 | 3 →Header에서 지정되는 주소값 |
0 |
1 | 2 | 3 | 4 →실제 주소값 |
Header |
|
예를들어 FAT Sector의 주소가 1 이라고 하면 우리가 찾아가야 할 주소는 2인 셈이다.
| Offset | 길이(byte) | 설명 |
File Header Signature | 0x00 | 8 | D0 CF 11 E0 A1 B1 1A E1 hwp, doc, ppt 등의 종류의 파일이다.(파일 시그니쳐 확인) |
Header CISID | 0x08 | 8 | 00 00 00 00 00 00 00 00으로 채워져 있다. |
Minor Version | 0x18 | 2 | 3E 00major가 03 이기 때문에 0x003E |
Major Version | 0x1A | 2 | 03 00 major ver.3 |
Byte Order Identifier | 0x1C | 2 | FE FF Little Endian 방식이다 |
Sector Shift | 0x1E | 2 | 09 00 한 섹터의 크기는 2^9 = 512byte |
Mini Sector Shift | 0x20 | 2 | 06 00 한 mini Sector의 크기는 2^6 = 64byte |
Reserved 영역 | 0x22 | 6 | 예약영역 |
Directory Sector 개수 | 0x28 | 4 | 00 00 00 00 major = 3 이기 때문에 0 |
FAT Sector 개수 | 0x2C | 4 | 01 00 00 00 1개 |
SEC ID | 0x30 | 4 | 01 00 00 00 Root Directory의 위치는 2Sector |
Transaction Signature Number | 0x34 | 4 | 00 00 00 00 |
Mini Stream Cutoff size | 0x38 | 4 | 00 10 00 00 Mini Stream 의 최대사이즈 4096Byte 고정 |
Mini FAT location | 0x3B | 4 | 02 00 00 00 첫번째 Mini FAT의 위치, 3Sector |
Mini FAT 개수 | 0x40 | 4 | 02 00 00 00 Mini FAT의 개수는 2개 |
first DIFAT Sector loaction | 0x44 | 4 | FE FF FF FF 첫번째 DIFAT는 FE FF FF FF = -2 + 1 = -1 (현재 위치) |
DIFAT Sector 개수 | 0x48 | 4 | 00 00 00 00 |
FAT#N의 위치 | 0x4B ~ | 4 | 00 00 00 00 FAT위치는 0 + 1 = 1Sector |
헤더를 분석해서 주요 정보를 나열해 보았다.
섹터의 크기 : 512 byte
mini sector의 크기 : 64byte
mini FAT의 개수 : 2개
FAT의 위치 : 1Sector
Root Directory의 위치 : 2 Sector
첫번째 mini FAT의 위치 : 3 Sector
먼저 FAT의 구조를 보고 파일이 어떻게 배치되어있는지 살펴보았다.
<FAT>
File 1 = 1번째
File 2 = 2, 19번째
File 3 = 3, 20번째
File 4 = 4~34번째(19,20번째 제외)
의 결과가 도출된다
같은색은 하나의 파일이다. 파일의 정체는 알수 없지만 이처럼 구성되 있음을 파악 할 수 있다. 회색영역의 첫 파일은 섹터1의 FAT를 가리킨다.
섹터 2번자리는 Root Directory라고 헤더에서 알아냈다. 그렇다면 0x12 = 18번째 영역에 있는부분 (19sector)에는 Root Directory의 내용이 이어질것이고, 같은 이유로 3번째 자리와 20번째는 mini FAT의 정보가 들어있다는걸 알 수 있다. 그렇다면 그 부분을 제외한 나머지는 파일의 데이터 스트림이 있을것이다.
File 1 = 1번째 = FAT
File 2 = 2, 19번째 = Root Directory
File 3 = 3, 20번째 = Mini FAT
File 4 = 4~34번째(19,20번째 제외) = File
2sector 와 19sector를 가져와서 root directory entry를 완성했다.
우리에게 필요한 시그니쳐는 Starting Sector Location과 Stream Size , 파일별 시작위치, 파일이 FAT인지 miniFAT인지 구분만 하면된다.
Root Entry |
size = 14784(FAT) / 시작 위치 : 3 |
1 |
size = 3332 (mini FAT) / 시작 위치 = 0 |
Catalog |
size = 158(mini FAT) / 시작 위치 = 53 |
2 |
size = 3865(mini FAT) / 시작 위치 = 54 |
3 |
size = 3546(mini FAT) / 시작 위치 = 116 |
4 |
size = 3690(mini FAT) / 시작 위치 = 172 |
Root Entry를 제외한 아래의 다른 파일들은 모두 mini FAT로 되어있다.
mini FAT의 부분을 확인해보자
Entry에서 확인한 시작 위치와 파일의 시작위치를 매칭시켜 파일의 정체를 알아보자.
처음 시작위치가 0인 1번파일이 빨간색 영역의 파일임을 알 수 있다. Catalog의 시작은 53으로 0x35이다 노란색 부분이 catalog임을 알 수 있다.
나머지도 매칭시켜보면
1 |
0x00 ~ 0x34 |
Catalog |
0x35, 0x73, 0xE6 |
2 |
0x37 ~ 0x72 |
3 |
0x75 ~ 0xAB |
4 |
0xAD ~ 0xE5 |
데이터를 추출해보자
Data stream 시작 = offset 2048
1번파일 = 0 ~ (52*64)+2048 = 0 ~ 5376 의 영역이 해당 파일을 구성하는 데이터의 영역이라 한다.
영역만큼 데이터를 긁어야 하는데 주의할점이 있다.
주 의 !
데이터스트림에서 처음 내용은 헤더정보를 나타낸다. offset 0~3은 헤더의 길이. offset 8~11은 파일의 길이이다.
00 |
01 |
02 |
03 |
04 |
05 |
06 |
07 |
08 |
09 |
10 |
11 |
12 |
13 |
14 |
15 |
헤더의 길이 |
|
|
|
|
파일의 길이 |
파일의 내용 |
|||||||||
파일의 내용 |
|||||||||||||||
..... |
<1파일의 header>
헤더의 길이는 0xC = 12 (0~11)
파일의 길이는 0xCF8 = 3320
데이터를 추출하기위해서는 헤더를 제외하고 Offset 12부터 추출한다. 2048 + 12 = 2060
2060 ~ 5376 까지 추출해보겠다.
영역 복붙후 jpg로 저장하면!
1번 파일이 복구 되었다.
2,3,4 파일도 같은 방법으로 복구하면된다.
'Kitri_NCS3기 보안과정 > 디지털포렌식' 카테고리의 다른 글
170619 휘발성/비휘발성 정보 수집 (0) | 2017.06.19 |
---|---|
170619 윈도우 시스템 분석 (0) | 2017.06.19 |
170512 디지털포렌식의 특성 (0) | 2017.05.12 |
170511 타임라인분석 (0) | 2017.05.11 |
170511 FAT32 복구 실습 (0) | 2017.05.11 |