해당 기술의 원리는 일반적인 섹터의 마지막 2바이트를 특정 시그니처로 교체해 두고, 원래의 2바이트 값은 Fixup 배열에 저장하여 교체해 둔 시그니처가 다른 값으로 교체되지 않았다면 섹터가 손상되지 않은 것으로 보고 배열에 있는 원래의 값을 다시 섹터 마지막 2바이트에 넣는다.
오직 이 기술은 데이터 구조체에만 사용되며 클러스터 등에는 사용되지 않는다.
17-2. MFT 엔트리
MFT(Master File Table)는 NTFS에서 핵심적인 부분
파일과 디렉토리에 대한 엔트리를 가짐
MFT 엔트리의 크기는 일정하며, 그 크기는 부트 섹터에서 정의하고 일반적 크기는 1024byte
다음 표는 MFT 엔트리 오프셋에 대한 구조이다.
[표 1] MFT 엔트리 오프셋 구조
범위(Byte)
설명
범위(Byte)
설명
0~3
시그니처(FILE)
22~23
플래그
4~5
Fixup 배열 오프셋
24~27
MFT 엔트리 실제 크기
6~7
Fixup 배열 엔트리 개수
28~31
MFT 엔트리 할당 크기
8~15
$LogFile 순서 번호
32~39
기본 레코드 파일 참조
16~17
순서 번호
40~41
다음 속성 ID
18~19
링크 카운트
42~1023
속성과 Fixup 배열 값
20~21
첫 번째 속성 오프셋
시그니처
MFT 엔트리의 시그니처로 'FILE'이란 문자열로 정해져 있음
하지만 chkdsk가 엔트리에 오류를 발견하면 시그니처는 'FILE'이 아닌 'BAAD'로 교체 됨
Fixup 배열 오프셋
해당 오프셋은 MFT 엔트리의 시작으로부터 상대적인 오프셋
$LogFile 순서 번호
해당 번호는 응용 프로그램 참조 모델에서 알아본 저널링에 사용되는 번호
순서 번호
엔트리가 할당되거나 비 할당 될 때 증가하는 값
운영체제에 의해 결정
링크 카운트
하드 링크의 개수를 나타냄
플래그
해당 오프셋 값은 '0x0001'로 설정된다면 해당 엔트리가 사용 중이라는 것을 의미
'0x0002'로 설정된다면 해당 엔트리가 디렉토리에 할당된 엔트리라는 것을 의미
다음 속성 ID 필드까지를 'MFT 엔트리 헤더'라고 한다.
17-3. 속성
MFT 엔트리의 대부분은 속성으로 되어 있으며 그 속성들은 속성 헤더와 속성 내용으로 나뉘게 됨
속성 헤더는 모두 같은 데이터 구조체를 지님
속성 내용은 거주 속성과 비거주 속성으로 나뉘어 조금씩 다른 데이터 구조체를 지님
다음 표는 속성 헤더 오프셋에 대한 구조이다.
[표 2] 속성 헤더 오프셋 구조
범위(Byte)
설명
범위(Byte)
설명
0~3
속성 타입 식별자
4~7
속성 길이
8~8
비거주 플래그
12~13
플래그
9~9
이름 길이
14~15
속성 식별자
10~11
속성 이름 오프셋
비거주 플래그
해당 오프셋 값은 속성 내용이 비거주 속성일 경우 셋팅괴는 값으로 비거주 속성일 경우 '0x01'로 설정
속성 이름 오프셋
속성 헤더의 시작으로부터 상대적인 오프셋 값
플래그
해당 값은 속성의 압축(0x0001), 암호화(0x4000), sparse(0x8000)을 의미하는 값
속성 식별자
MFT에서 속성에 대한 고유 번호
속성 헤더 바로 다음으로는 거주 또는 비거주 속성 데이터 구조체가 위치한다.
다음 표는 거주 속성 오프셋 구조이다.
[표 3] 거주 속성 오프셋 구조
범위(Byte)
설명
0~15
일반 헤더
16~19
내용 크기
20~21
내용 오프셋
다음 표는 비거주 속성 오프셋 구조이다.
[표 4] 비거주 속성 오프셋 구조
범위(Byte)
설명
범위(Byte)
설명
0~15
일반 헤더
36~39
사용 x
16~23
Runlist 시작 VCN
40~47
속성 내용 할당 크기
24~31
Runlist 끝 VCN
48~55
속성 내용 실제 크기
32~33
Runlist 오프셋
56~63
속성 내용 초기화 크기
34~35
압축 블록 크기
VCN
논리적 파일 주소에 대한 다른 이름
해당 값의 시작과 끝은 여러 MFT 엔트리들이 하나의 속성을 설명할 필요가 있을 때 사용
Runlist 오프셋
해당 값은 속성 헤더 시작 오프셋에서의 상대적인 값
MFT 엔트리에 대한 기본적인 분석은 끝났지만 이 정도 분석으로 MFT 엔트리의 분석이 끝나는 것은 아니다.
MFT 엔트리에 할당되는 표준 속성들을 모두 분석해야 MFT 엔트리 분석이 모두 끝이 난다.
STANDARD_INFORMATION 속성
해당 속성은 항상 거주 속성으로 타입 식별자는 16
또 모든 파일과 디렉토리에 존재하며, 파일이나 디렉토리를 위한 기본 메타데이터 파일들을 포함
다음 표는 $STANDARD_INFORMATION 속성의 오프셋 별로 의미하는 것을 분석한 것이다.
[표 5] $STANDARD_INFORMATION 속성 오프셋 구조
범위(Byte)
설명
범위(Byte)
설명
0~7
생성 시간
40~43
버전 번호
8~15
파일 변경 시간
44~47
클래스 ID
16~23
MFT 변경 시간
48~51
소유자 ID (3.0 버전 이상)
24~31
파일 접근 시간
52~55
보안 (3.0 버전 이상)
32~35
플래그
56~63
할당 크기 (3.0 버전 이상)
36~39
버전 번호 중 최대 번호
64~71
업데이트 순서 번호 (USN) (3.0 버전 이상)
4개의 시간 값
해당 시간 값들이 우리가 흔히 속성 창에서 볼 수 있는 시간 값
1601년 1월 1일 UTC부터 100 나노초 단위로 계산되어 저장
플래그
해당 파일에 적용될 수 있는 속성들 중 어떠한 속성을 나타내는 값이 저장되는 오프셋
보안 ID
이 값은 $Sparse 파일의 인덱스 값
보안 ID 값이 아님
플래그 오프셋에 대한 정보는 다음과 같다.
0x0001 : 읽기 전용
0x0002 : 숨김
0x0004 : 시스템
0x0020 : 아카이브
0x0040 : 장치
0x0080 : #일반
0x0100 : 임시
0x0200 : Sparse 파일
0x0400 : 재파싱 지점
0x0800 : 압축
0x1000 : 오프라인
0x2000 : 빠른 검색을 위한 인덱스 외의 내용
0x4000 : 암호화
$FILE_NAME 속성
해당 속성 타입 식별자는 48
파일 이름과 부모 디렉토리 정보 저장을 위해 MFT 엔트리에 위치
디렉토리 인덱스에서 사용
MFT 엔트리에서 사용될 때에는 포함되어 있는 정보가 필수적이지 않지만, 디렉토리 인덱스에서 사용될 때에는 다름
해당 속성은 위에서 설명한 $STANDARD_INFORMATION 속성과 함께 필수적인 속성
항상 거주 속성
또 해당 속성은 일반적으로 $STANDARD_INFORMATION 속성과 $DATA 속성 가운데에 위치하게 되는데 만약 하나의 파일에 여러 MFT 엔트리가 할당 될 경우 다른 비기준 엔트리의 속성을 포함하는 $ATTRIBUTE_LIST 속성이 $STANDARD_INFORMATION 속성과 $FILE_NAME 속성 사이에 위치한다.
다음 표는 $FILE_NAME 속성에 대한 오프셋 구조이다.
[표 6] $FILE_NAME 속성 오프셋 구조
범위(Byte)
설명
범위(Byte)
설명
0~7
부모 디렉토리 파일 참조
48~55
파일 실제 크기
8~15
파일 생성 시간
58~59
플래그
16~23
파일 수정 시간
60~63
재파싱 값
24~31
MFT 수정 시간
64~64
이름 길이
32~39
파일 접근 시간
65~65
네임스페이스
40~47
파일 할당 크기
66~
이름
부모 디렉토리 파일 참조
해당 값의 상위 2바이트는 부모 디렉토리의 순서 번호
하위 6바이트는 부모 디렉토리의 MFT 엔트리 번호
플래그
해당 오프셋 값은 $STANDARD_INFORMATION의 플래그 값과 동일
네임스페이스
이름 필드의 값이 어떤 형식인지 나타내는 값을 가짐
흔히 파일 이름 규칙을 뜻함
이름
이름 오프셋의 길이는 파일명에 따라 달라짐
정확한 길이를 알고자 하면 이름 길이 오프셋을 참고하면 됨
$DATA
해당 속성은 고유한 구조체를 가지고 있지 않음
헤더 이후로는 파일 내용 데이터만 존재
타입 식별자는 128이며 크기는 정해져 있지 않음
하지만 내용이 700Byte 이상이라면 비거주 속성이 되어 클러스터가 할당
$ATTRIBUTE_LIST
해당 속성은 MFT 엔트리에 존재하는데 $STANDARD_INFORMATION 속성과 $FILE_NAME 속성 사이에 위치
타입 식별자는 32
MFT 엔트리에 여러 속성들이 할당되어 엔트리 크기인 1024Byte를 초과할 때 사용
해당 속성 내용으로는 기준 MFT 엔트리에 포함되려 했던 속성들의 엔트리 리스트가 목록화 되어 있음
속성 시작 VCN은 여러 MFT엔트리들이 단일 속성을 ㅓㄹ명해야 할 때 필요하며, 이름 오프셋은 해당 엔트리 시작으로부터 상대적 오프셋 값이다.
다음 표는 $ATTRIBUTE_LIST에 대한 오프셋 구조이다.
[표 7] $ATTRIBUTE_LIST 오프셋 구조
범위(Byte)
설명
범위(Byte)
설명
0~3
속성 타입 식별자
8~15
속성 시작 VCN
4~5
해당 엔트리 길이
16~23
속성이 위치하려 했던 엔트리
6~6
이름 길이
24~24
속성 ID
7~7
이름 오프셋
$OBJECT_ID
해당 속성은 64 타입 식별자를 가짐
이름 대신 파일을 지칭하는 128bit의 오브젝트 식별자를 포함
해당 속성은 간단한 구조로 되어 있음
총 4개의 필드로 구성되어 있으나 보통 첫 번째 필드만 설정되어 있음
다음 표는 $OBJECT_ID 오프셋에 대한 구조이다.
[표 8] $OBJECT_ID 오프셋 구조
범위(Byte)
설명
0~15
오브젝트 ID
16~31
파일이 생성된 볼륨 ID
32~47
파일이 생성될 때 받은 오브젝트 ID
48~63
파일이 생성될 때 받은 도메인 ID
$OBJECT_ID 속성 구조를 보면 오브젝트 ID 필드가 존재하는데 이 필드는 \$Extend\ObjID 인덱스들을 정렬할 때 사용되기도 한다.
$REPARSE_POINT
해당 속성은 식별자 192를 가짐
해당 속성은 재파싱 지점의 파일에 할당 됨
8~9 오프셋 범위와 12~13 오프셋 범위는 바이트 오프셋 16에서 상대적인 오프셋 값을 가짐
다음 표는 $REPARSE_POINT 속성 오프셋에 대한 구조이다.
[표 9] $REPARSE_POINT 속성 오프셋 구조
범위(Byte)
설명
범위(Byte)
설명
0~3
Reparse 타입 플래그
10~11
대상 이름 길이
4~5
Reparse 데이터 크기
12~13
대상의 출력 이름 오프셋
6~7
사용 x
14~15
출력 이름 길이
8~9
대상 이름 오프셋
INDEX_ROOT
해당 속성은 타입 식별자 144를 가짐
항상 거주 속성
해당 속성의 엔트리는 항상 인덱스 트리의 루트
다음 표는 $INDEX_ROOT 속성 헤더 오프셋에 대한 구조이다.
[표 10] $INDEX_ROOT 속성 헤더 오프셋 구조
범위(Byte)
설명
범위(Byte)
설명
0~3
인덱스 속성 타입
12~12
인덱스 레코드 크기(클러스터)
4~7
수집 정렬 규칙
13~15
사용 x
8~11
인덱스 레코드 크기
16~
노드 헤더
인덱스 내의 속성 타입
인덱스에 포함되어 있는 엔트리의 속성 타입을 포함하는 오프셋
엔트리가 속성을 사용하지 않는 경우 0으로 설정
수집 정렬 규칙
$INDEX_ALLOCATION 속성에서 정렬되는 규칙
인덱스 레코드 크기(Byte)
인덱스 레코드의 바이트 크기를 포함하는 오프셋
인덱스 레코드 크기(클러스터)
인덱스 레코드 크기만큼 필요한 클러스터 수
$INDEX_ROOT 속성 헤더는 16바이트의 크기를 가지며, 노드 헤더 또한 16바이트의 크기를 가진다.
$INDEX_ALLOCATION
큰 디렉토리일 경우 인덱스 엔트리가 $INDEX_ROOT 속성에 적합하지 않음
이러한 경우 비 거주 속성인 해당 속성이 사용 됨
해당 속성 내용은 인덱스 레코드로 이루어져 있는데, 인덱스 레코드의 크기는 고정
정렬된 트리의 노드 하나를 포함하고 있음
인덱스 레코드의 크기는 $INDEX_ROOT 속성 헤더의 정의되어 있으며, 보통 4096Byte
해당 속성의 타입 식별자는 160이며 해당 속성의 내용인 인덱스 레코드는 특별한 헤더 데이터 구조체로 시작
헤더 다음으로 노드 헤더와 인덱스 엔트리의 목록이 옴
다음 표는 인덱스 레코드 헤더에 대한 오프셋이다.
[표 11] 인덱스 레코드 헤더 오프셋
범위(Byte)
설명
범위(Byte)
설명
0~3
시그니처(INDX)
8~15
$LogFile 순서 번호(LSN)
4~5
Fixup 배열 오프셋
16~23
전체 인덱스 스트림에서 해당 레코드 VCN
6~7
Fixup 배열 엔트리 수
24~
노드 헤더
시그니처
인덱스 레코드에는 시그니처가 존재
시그니처는 'INDX'
Fixup 배열 오프셋
해당 오프셋의 값은 Fixup 배열의 오프셋 주소
인덱스 레코드 헤더 시작 부분에서 상대적
BITMAP
해당 속성은 인덱스 레코드의 할당 상태를 관리하는 속성
모든 인덱스 레코드가 할당되는 것은 아니며 운영체제 판단에 의해 필요 시 할당
$BITMAP 속성은 MFT 엔트리 할당 추적을 위해 $MFT에 의해 사용
해당 속성은 타입 식별자 176을 가지며 각 바이트를 비트로 변환하여 인덱스 레코드와 맵핑
[그림 3]을 분석해 보면 첫 바이트가 0x01인데 비트로 변환 시 0000 0001이다.
이것은 인덱스 레코드 0이 할당 되었다는 것을 의미한다.
만약 0x02 바이트여서 0000 0010이라면 인덱스 레코드 1이 할당 되었다는 것을 의미한다.
인덱스 노드 헤더 데이터 구조체
$INDEX_ROOT 속성과 $INDEX_ALLOCATION 속성 다음에 위치하게 되는 16Byte의 크기를 가짐
다음 표는 노드 헤더 오프셋에 대한 구조이다.
[표 12] 노드 헤더 오프셋 구조
범위(Byte)
설명
0~3
인덱스 엔트리 목록 시작에서의 오프셋
4~7
인덱스 엔트리 목록 마지막에서의 오프셋
8~11
할당된 인덱스 엔트리 목록 버퍼 마지막에서의 오프셋
12~15
플래그
인덱스 엔트리 목록 시작 오프셋
해당 값은 노드 헤더 시작에서 상대적
인덱스 엔트리 목록의 마지막 오프셋
해당 값은 노드 헤더 마지막에서 상대적
플래그
플래그는 설정되지 않거나 0x01로 설정되는 경우 밖에 없음
0x01로 설정되는 경우 인덱스 엔트리 목록에 있는 엔트리에 의해 지정된 자식 노드가 있다는 것을 의미
17-4. 인덱스 엔트리
표준 인덱스 엔트리
말 그대로 인덱스 엔트리의 표준 레이아웃을 가진 인덱스 엔트리
어떠한 내용도 가질 수 있는 엔트리
다음 표는 인덱스 엔트리 오프셋에 대한 구조이다.
[표 13] 표준 인덱스 엔트리 오프셋 구조
범위(Byte)
설명
범위(Byte)
설명
0~7
????
12~15
플래그
8~9
엔트리 길이
16~
내용
10~11
내용 길이
플래그
0x01 : 자식 노드가 존재
0x02 : 인덱스 엔트리 목록에서 마지막 엔트리
디렉토리 인덱스 엔트리
파일 이름을 사용하는 디렉토리 인덱스는 자신만의 데이터 구조체를 가짐
다음 표는 디렉토리 인덱스 엔트리 오프셋에 대한 구조이다.
[표 14] 디렉토리 인덱스 엔트리 오프셋 구조
범위(Byte)
설명
범위(Byte)
설명
0~7
파일 이름의 MFT 파일 참조
12~15
플래그
8~9
해당 엔트리 길이
16~
내용
10~11
$FILE_NAME 속성 길이
플래그
표준 인덱스 엔트리의 플래그와 동일
표준 인덱스 엔트리와 디렉토리 인덱스 엔트리 마지막 8바이트는 $INDEX_ALLOCATION에 있는 자식 노드의 VCN 값을 가지고 있다.
(18) 메타데이터 파일
$MFT
해당 메타데이터 파일은 앞 내용에서 많이 언급하였으므로 해당 메타데이터 파일의 일반적 구조와 속성은 생략하고, 고유 속성인 $BITMAP 속성만 분석해 볼 것이다.
$BITMAP 속성은 NTFS의 MFT 엔트리 할당 상태를 관리하는 속성
각 비트가 MFT 엔트리의 맵핑되어 MFT 엔트리가 할당되면 해당 MFT 엔트리와 맵핑 관계인 비트가 1로 설정
[그림 4]를 보면 F로 설정된 오프셋과 0으로 설정된 오프셋이 있는데 F로 설정된 오프셋이 할당 상태를 뜻하고 0으로 설정된 오프셋이 비할당 상태를 뜻한다.