Piki's Play
Chapter 10. FAT 데이터 구조 본문
-> 이번장에서는 FAT를 구성하는 데이터 구조체를 분석해보자. 여기서는 다섯가지 분류모델을 무시하고 개별구조체에 집중해보자.
10.1 부트섹터
- 파일시스템의 첫 섹터에 존재하고, 여러 파일 시스템 범주데이터가 여기에있다. 또한 볼륨레이블은 'Noname'이다.
- FAT12/16과 FAT32는 부트섹터의 구조가 다르다. 그러나 첫 36비트는 동일하다.
-> 첫 번째 값 0~2바이트는 부트코드가 어디에 있는지 알려준다. 이는 해당시스템이 부팅과 관련이 없다면 무의미하다. (Dos와 윈도우의 경우, 부팅과 관련없는 파일시스템도 이 값을 가져야한다. 하지만 리눅스와 같은 다른 운영체제들은 그러지 않다.)
- 매체유형(미디어유형)은 이동식인지 고정매체인지 구분하기 위함이지만, 윈도우는 이를 사용하지 않는다.
- 36바이트 이후는 FAT12/16과 FAT32가 다르다. 이 둘의 공통은 510바이트에 0x55, 511바이트에 0xAA이다. 이것들은 도스파티션 테이블 첫 섹터와 동일한 시그니처이다.
※ FAT12/16의 나머지 데이터 구조체는 다음과 같다.
※ FAT32의 나머지 데이터 구조체는 다음과 같다.
-> 둘의 첫 차이점은 FAT32 섹터가 파일시스템을 더욱 확장하고 유연하게 만드는 데이터를 포함하는 것이다.
- FAT12/16 시스템에서 62-509 바이트 사이의 데이터와 FAT32 시스템에서 90-509바이트 사이에 데이터는 특정 목적을 가지지 않지만 일반적으로 부트코드와 오류메세지를 저장하는데 사용된다. 아래는 윈도우 xp의 첫 섹터 헥스덤프이다.
- 첫 줄은 OEM이름이 'MSDOS5.0'임을 나타내주고 이는 윈도우 2000이나 xp이다. 이는 리틀엔디안 방식(숫자는 반대, 문자는 정순)을 사용한다.
- 바이트 11-12는 각 섹터가 512(0x0200)바이트임을 알려준다. 바이트 13영역은 각 클러스터 크기가 2섹터 즉, 1024바이트임을 알려준다. 14~15바이트는 예약된 영역이 38(0x0026)섹터로 이루어져있음을 알려준다. 즉, FAT영역이 38섹터부터 시작된다는 것을 알 수 있다.
- 바이트 16은 2개의 FAT구조체가 있음을 보여준다.
- 28~31은 이 파일시스템 시작전에 100,800(0x000189c0)섹터가 있음을 알려준다. (이중부팅 시스템이거나, 노트북의 최대절전모드 파티션일 수 있다.)
- 이 이미지는 FAT32이므로 적절한 데이터 구조체를 적용할 필요가 있다. 바이트 36~39를 보면 각 FAT구조체의 크기가 797(0x0000031d)섹터라는 것을 알 수 있다. 우리는 앞서 2개의 FAT 구조체가 있다는 것을 알았다. 따라서 FAT구조체 전체의 크기는 1594섹터가 될 것이다. 바이트 48~49는 FSINFO 정보가 섹터 1에 존재하는 것을 표시한다. 바이트 50~51은 부트섹터의 백업본이 섹터6에 있다는 것을 알려준다.
볼륨일련번호는 67~70바이트에 있고 그 값은 0x41C194603 이다. 볼륨레이블은 71~80에 존재하고 부트섹터이기 때문에 'NONAME'을 갖는다. 이 실제레이블은 다른곳에 저장된다는 것을 나중에 다시 확인하자. 타입레이블은 82~89에 있고 이는 시스템에서 'FAT32'이다.
- 90~509는 파일시스템에서 사용되지 않지만 부팅과 관련이 있으면 사용될 수도 있다. 바이트 510~511은 시그니처 0xAA55를 갖는다.
10.2 FAT FSINFO
-> FAT32 파일시스템에는 FSINFO 구조체가있고, 그 구조체는 운영체제가 새로운 클러스터를 어디에 할당하는지 설명한다. 이 구조체는 부트섹터에 위치하고 레이아웃은 다음과같다. (부트섹터 속 FSINFO)
-> 이중에서 반드시 필요한 것은 없고, 그것들은 운영체제의 필요에 의해 존재한다.
- 이전에 조사했던 파일시스템의 섹터 1(FSINFO) 내용을 확인해보자. 바이트 오프셋은 이 섹터의 시작에서 상대적이다.
-> 0~3, 484~487, 508~511에서 시그니처를 확인할 수 있다. 비할당 클러스터들의 수는 488~491 바이트에 있고, 이 파일시스템에는 101,918개의 비할당 클러스터들이 있다.
Next Free Cluster는 492~495바이트 사이에 있고 이는 클러스터 75(0x0000004b)라는 것을 알 수 있다.
(여기서는 섹터기준이 아닌 클러스터 기준임을 명심하자)
10.3 FAT(FAT영역)
-> FAT는 FAT파일 시스템에서 중요한 역할을 담당하고 있으며 두가지의 목적을 갖는다.
1. 클러스터의 할당상태 판단
2. 파일이나 디렉토리 다음에 할당할 클러스터를 찾는데 사용
- 대체로 한 FAT파일시스템에는 두 개의 FAT가 있고, 그 정확한 번호는 부트섹터에서 주어준다.
첫 FAT는 부트섹터에서 주어준 예약된 영역섹터 이후에 시작된다. 각 FAT크기도 주어주기 때문에 첫 번째 FAT이후에 바로 두 번째 FAT가 시작된다. 두 번째 FAT 테이블은 같은 크기의 엔트리들로 구성되나 헤더나 아래 값들이 없다. 각 엔트리 크기는 파일시스템 버전에 따라 다르다. FAT12는 12비트, FAT16은 16비트, FAT32는 32비트의 FAT엔트리들을 갖는다. 엔트리 주소는 0에서 시작하고 각 엔트리는 같은 주소의 클러스터와 대응된다.
- 만약 클러스터가 할당되지 않으면 그 엔트리는 0이다. 할당되면 0이 아닌 다음 클러스터 주소가 포함된다. 그것이 마지막에 있는 클러스터면 엔트리는 마지막 표시를 하는데 FAT12는 0xff8, FAT16은 0xfff8, FAT32는 0x0ffffff8보다 큰 어떤 값이든 올 수 있다.
만약 엔트리가 FAT12에서 0xff7, FAT16에서 0xfff7, FAT32에서 0x0ffffff7의 값을 갖는다면 그 클러스터는 손상되었다고 표시하고 할당되어서는 안된다.
- 파일시스템에서 시작 클러스터는 2번부터이다, 따라서 FAT구조체에 엔트리 0과 1은 필요하지 않다. 엔트리 0은 보통 매체유형의 복사본을 저장한다. 엔트리1에는 파일시스템의 '불량상태'를 저장한다. -> 이 두 값은 부가적인것이며, 정확하지 않을 수 있다.
- 샘플 이미지의 FAT구조체를 보기 위해 섹터38을 확인해 보자.
(예약된 영역 바로 뒤 FAT영역)
# dcat --f fat fat-4.dd 38 | xxd
[REMOVED]
-> 위는 FAT32 파일시스템의 결과이고 각각의 엔트리는 32바이트의 크기이므로 4바이트의 엔트리 크기를 갖는다고 할 수 있다. 첫 엔트리는 72인데 가지고 있는 값은 73(0x00000049)이다. 이 구조체의 실제 위치는 바이트 288에 위치한다.-> 4바이트당 1엔트리이므로 288/4=72번째 엔트리임을 알아낼 수 있다. 따라서 클러스터 72는 73과 이어지고, 73은 74를 가리킨다. 74는 76을 가리키고 76은 77을 가리킨다. 이 때 77엔트리의 내용을 보면 0x0fffffff 값을 가지는 것을 볼 수 있다. 이는 마지막을 나타내준다.
-TSK도구들을 이용해서 클러스터의 할당상태를 확인할 수 있지만 섹터와 클러스터를 변환해주어야 한다.
이 예제에서 클러스터2는 섹터 1632이고 각 클러스터는 2섹터이다. 앞에서 각 섹터는 512바이트 임을 알려주었다. 클러스터 75를 아래와 같이 한 섹터로 변환할 수 있다.
(Cluster75 - Cluster2) * 2 + Sector 1632 = Sector 1778
(여기서 2는 한 클러스터당 2개의 섹터를 가짐을 의미한다.)
- TSK dstat도구는 할당상태와 섹터의 클러스터 주소를 보여준다. 섹터 1778을 적용한 결과는 다음과 같다.
# dstat -f fat fat-4.dd 1778
Sector : 1778
Not Allocated
Cluster : 75
10.4 디렉토리 엔트리
-> FAT 디렉토리 엔트리들에는 파일이나, 디렉토리의 이름과 메타데이터가 저장되어있다. 이러한 엔트리 중 하나는 모든 파일과 디렉토리에 할당되며, 그것들은 그 파일의 부모 디렉토리에 할당된 클러스터에 위치한다. 그 데이터 구조체에서 이름은 단지 8글자, 확장자는 3글자만 사용된다. 그 이상은 LongFileName엔트리가 필요하다. 이는 다음에 설명하겠다.
-> 첫 번째 바이트가 0xe5, 0x00으로 설정시 비할당을 의미한다. 비할당상태가 아니면 그 바이트는 파일명의 첫글자로 저장한다. (ASCII나 MS의 'Code Pages') -> 이때 파일명이 0xe5이면 0x05로 변경해서 사용할 수 있다. 만약 파일명이 8개 이하면 남은 부분은 0x20(스페이스)로 채워진다.
- 파일 크기 필드가 4바이트이므로 파일의 최대크기는 4GB가 된다. 이때 디렉토리들은 크기가 0이고 그것들에 할당된 클러스터를 판단하기 위해서 FAT구조체가 사용된다. 속성필드에는 아래 표처럼 하나 이상의 비트가 있다.
- '긴 파일 속성'을 갖는 디렉토리 엔트리의 구조체는 위와 모양이 다르다. 긴 파일명 속성은 처음 4개의 속성들의 비트연산 조합이다.
※ 타임스탬프 분석
-> 각 타임스탬프의 날짜는 위 그림의 A처럼 3부분으로 나뉘어진 16비트 값이다. 년-원-일 순으로 나열되어있으며 년도는 1980년도에서 더하면된다. 따라서 년도의 범위는 0~127 즉, 2107년까지이다. 표현은 최종 비트를 16진수로 나타낸다.
-> 날짜와 마찬가지로 16비트를 3부분으로 나눈다. 하위 5비트는 초이며 2초단위로 나타낸다. (44초-> 22)
- 다행히 이들을 자동으로 변환해주는 도구들이 많아서 직접 계산할 필요는 없다.
- 아래와 같이 루트디렉토리내에 있는 가공되지 않은 두 엔트리를 보자 (FAT 루트디렉토리의 시작위치는 부트섹터에서 저장하고 있다.)
-> 바이트 11에 파일속성 값(0x08)을 보여준다. 이는 바이너리로 00001000이다. 이는 볼륨레이블을 나타낸다(위에 파일속성 표를 참고해보자). 두 번째 줄 바이트 22~25에는 그 볼륨의 생성시간과 날짜가 있다. (32바이트-> 4바이트) 이 볼륨레이블의 생성시간은 파일시스템이 생성되었을 때의 날짜를 저장한다.
- 세 번째와 네 번째 줄은 두 번째 디렉토리 엔트리를 위한것이고, 이 파일의 이름이 'RESUME-1.RTF'라는 것을 알 수 있다. 바이트 43에 있는 속성값은 (0x20)-> (00100000)이고 이는 아카이브 속성 비트가 설정되어 있다는 것을 의미한다. 바이트 45(원래 13)은 생성시간을 0.1초로 보여주고 값은 163(0xa3)이다. 바이트 46~47에는 생성시간이 15:39:40인 0x7e34가 저장되어있다. 바이트 48~49는 생성된 날짜를 나타내고 그 값은 0x304a 즉, 2004년 2월 10일 이다.
바이트 52~53과 58~59를 통해 시작클러스터 9(0x00000009)를 알아낼 수 있다. 바이트 60~63은 파일크기가 8689(0x000021f1) 바이트라는 것을 나타낸다. 이 파일의 모든 클러스터를 판단하려면 FAT를 참조해야 한다.
각 클러스터는 2섹터씩 이루어져있고 2섹터는 4바이트이다. 따라서 클러스터9는 (9x4)36바이트에 존재한다. 그래서 클러스터9의 FAT구조체 엔트리는 36~39바이트에 있고 그 값은 (0x0000000a)10이다. 이는 클러스터9 -> 클러스터10으로 연결이 되어있음을 말해준다. 이는 연속적으로 이어져있고 마지막 엔트리 17까지 이어져있다. 즉, 8689바이트 파일을 위해 공간 9216바이트를 이용한 것이다.
- TSK도구로 이 데이터 일부를 볼 수 있는데 섹터 주소로 변환하자
(Cluster9 - Cluster2) * 2 + Sector of Cluster2 = 1646
- TSK fsstat을 이용해 FAT구조체 내용을 덤프하자
#fsstat -f fat fat-4.dd
[REMOVED]
1642 - 1645(4) -> EOF
1646 - 1663(18) -> EOF
1664 - 1681(18) -> EOF
[REMOVED]
- TSK isstat도구는 디렉토리 엔트리의 세부내용을 보여주고 결과는 아래와 같다.
# istat -f fat fat-4.dd 4
Directory Entry : 4
Allocated
File Attributes : File, Archive
Size : 8689
Name : RESUME-1.RTF
Directory Entry Times :
Written : Wed Mar 24 06:26:20 2004
Accessed : Thu Apr 8 00:00:00 2004
Created : Tue Feb 10 15:49:40 2004
Sectors :
1646 1647 1648 1649 1650 1651 1652 1653
1654 1655 1656 1657 1658 1659 1660 1661
1662 1663
-> 'RESUME-1.RTF'파일이 루트디렉토리에 두번째 엔트리고 그 엔트리 주소는 4라는 것을 확인할 수 있다.
10.5 긴 파일명 디렉토리 엔트리
-> 표준 디렉토리 엔트리는 8글자 이름과 3글자 확장자 이름만 지원한다. 더 긴 이름이나 특별한 이름을 사용하는 이름은 Long File Name(LFN)이 필요하다. 한 파일에는 LFN엔트리 외에 일반 엔트리가 있으며(SFN) LFN이 SFN보다 우선한다. 디렉토리 엔트리의 LFN에는 다음과 같은 필드가 있다.
-> 순서번호 필드는 첫 엔트리가 1이고, 파일명을 저장하는데 필요한 엔트리 카운터이다. 파일의 LFN엔트리는 SFN엔트리 전에 목록화되고 그것은 역순이다. 그래서 디렉토리의 첫 번째 엔트리 값은 마지막 LFN엔트리이고 가장 큰 순서번호를 가질 것이다. 사용되지 않은 문자들은 0xff로 채워지고 이름은 NULL문자로 끝난다.
- LFN엔트리 파일 속성은 0x0f이고, SFN을 이용하여 체크섬을 계산하고 그 값은 각 LFN엔트리와 같아야한다. 만약 한 LFN엔트리의 체크섬이 그에 해당하는 SFN에 일치하지 않으면 운영체제는 LFN을 지원하지 않고 디렉토리는 손상되었을 것이다. 체크섬 알고리즘은 각 글자를 반복시키고 각 단계에서 현재 체크섬을 오른쪽으로 한 비트씩 이동시켜 다음 문자의 ASCII를 더하는 것이다.
C = 0;
for (i=0;i<11;i++) {
C = ((C & 0x01) ? 0x80 : 0) + (C>>1);
C = C + shortname[i];
}
※ 두개의 LFN과 테스트 이미지의 루트 디렉토리에 있는 파일의 일반 엔트리를 확인해보자.
-> 첫 두줄이 첫번째 엔트리인데 (11바이트) 속성부분이 0x0f로 설정되어 LFN엔트리임을 알 수 있다. 그 순서번호는 바이트 64에 있고 (0), 0x42이다. -> 여기서 0x40을 제거하면 0x02가 남고 두개의 LFN엔트리가 있는 것을 확인할 수 있다.
체크섬(13)은 바이트 77에서 0xdf를 가지는 것을 알 수 있고 이후 SFN을 찾아서 검증할 수 있다.
- 첫 5개 문자는 바이트 65~74에 있고 이는 'NAME'이다. 두 번째 구역 78~89에는 'rtf'가 있다. 나머지는 0xffff로 설정되어있다. 세 번째 구역 92~95 또한 0xffff로 되어있는 것을 알 수 있다. 따라서 파일 이름이 'Name.rtf'라는 것을 알 수 있다.
- 두 번째 엔트리는 96에서 시작하고 순서번호는 1이다. 얘도 역시 체크섬 '0xdf'를 갖는다. 이 엔트리의 문자열은 'MyLo','ng Fil', 'e'로 되어있다. 이것이 순서번호 1이고 즉, 첫 엔트리 이므로 두개의 엔트리를 결합하면 'My Long File Name.rtf'인 것을 알 수 있다. 이 이름의 짧은 이름 버전은 세 번째 엔트리에서 볼 수 있고, 그 이름은 'MYLONG~1.RTF'이다.
- 체크섬 검증전에 각 문자열이 바이너리로는 어떤 값인지 알아야 한다.
-> 체크섬을 설명하기 위해 모든 것을 2진법으로 설명하자. 첫 단계는 'M'을 변수 check에 할당하는 것이다.
이 과정을 직접 할 필요는 없고 이해만 하면 된다. 최종 0xdf는 앞 LFN엔트리에서 본 체크섬과 일치한다.
※ 이 디렉토리 엔트리를 fls도구로 확인하면 다음 결과를 얻는다.
# fls -f fat fat-2.dd
r/r 3: FAT DISK
r/r 4: RESUME-1.RTF
r/r 7: My Long File Name.rtf
r/r 8: _ile6.txt
-> 결과의 첫 두줄은 볼륨레이블과, 이전 '디렉토리 엔트리'절에서 본 짧은 파일명 디렉토리 엔트리를 나타낸다.
세 번째 줄은 긴 이름과 삭제된 파일 'ile6.txt'의 이름을 표시한다.
-> 별표는 그 부분이 삭제되어 첫 번째 문자가 없어졌다는 뜻이고 비할당된 상태를 보여준다.
▶ 요약
- FAT는 데이터 구조체의 수가 적어 단순하다. 또한 부트섹터와 FAT는 자동화된 방법으로 파일시스템을 분석하는데 필수적이고, 디렉토리 엔트리는 응용프로그램 수준의 기술 없이 삭제된 파일을 복구하는데 중요한 역할을 한다.
p.s 다음시간에 드디어 NTFS를 배워본다. FAT는 약간 기초중에 기초인 느낌?! 더 빡시게 해보자.
'포렌식 > 파일시스템 (파일시스템 포렌식분석)' 카테고리의 다른 글
NTFS의 개념 - 다른 속성 개념, 인덱스, 분석 (0) | 2020.03.03 |
---|---|
Chapter 11. NTFS의 개념 (0) | 2020.02.28 |
FAT 개념과 분석 - 파일 이름 범주 (0) | 2020.02.22 |
FAT 개념과 분석 - 메타데이터 범주 (0) | 2020.02.19 |
FAT 개념과 분석 - 내용범주 (0) | 2020.02.18 |