Information Security/Digital Forensic

NTFS 메타데이터 파일

hdhwang 2022. 6. 3. 02:10

1. NTFS 메타 데이터 파일

메타 데이터 파일(Meta Data File)이란 NTFS가 볼륨을 관리하기 위해서 사용하는 시스템 파일을 말한다. NTFS는 다른 일반적인 파일시스템들처럼 볼륨을 관리하는 데이터들을 따로 영역을 두고 있는 것이 아니라 파일의 형태로 관리하고 있다. 파일의 형태로 관리하기 때문에 NTFS는 확장성이 좋으며, 정해진 볼륨의 형태가 없다는 점이 특징이다.

1.1. 메타 데이터 파일 종류

메타 데이터 파일들은 일반적인 파일들과 구분 짓기 위해 이름 앞쪽에 ‘$’로 표시한다. 또한 속성 이름들과 구분 짓기 위해서 첫 글자를 제외한 나머지는 전부 소문자로 적는다(, $MFT 메타 데이터 파일은 전부 대문자로 이루어져있다). 메타 데이터 파일들의 내용은 볼륨의 어느 위치에 존재해도 상관없다. 그러나 MFT Entry 위치는 고정되어 있으며, 그 위치는 다음 표에서 설명하는 것과 같다.

Entry Num File Name 설명
0 $MFT MFT을 담고 있는 파일
1 $MFTMirr MFT 파일의 백업본
2 $LogFile 트랜잭션 저널 기록
3 $Volume 볼륨의 레이블, 버전 등 볼륨에 대한 정보
4 $AttrDef 인자 값, 이름, 크기 등 여러 속성
5 . 볼륨의 루트 디렉토리
6 $Bitmap 볼륨의 클러스터 할당 관리 정보 보유
7 $Boot 부트 레코드 영역의 정보
8 $BadClus 배드 클러스터에 대한 정보
9 $Secure 파일들의 보안, 접근 권한에 대한 정보
10 $Upcase 모든 유니코드 문자의 대문자 보유
11 $Extend 추가적인 확장 디렉토리 정보
(Windows는 일반적으로 이 디렉토리 안에 어떠한 정보도 담고 있지 않음)
12~15 사용 안 함 비어 있음
16~23 사용 안 함 비어 있음
상관 없음 $Objld 파일 고유의 ID 정보(Win 2000 이상)
상관 없음 $Quota 사용량 정보(Win 2000 이상)
상관 없음 $Reparse Reparse Point에 대한 정보(Win 2000 이상)
상관 없음 $UsnJrnl 파일이나 디렉토리 변경사항 기록(Win 2000이상)
24~ 일반 파일 일반적인 파일이나 디렉토리

 

MFT Entry 015번까지 총 16개의 MFT Entry는 시스템용으로 예약되어 있으며, 일반 사용자의 파일이 위치할 수 없다. 비어 있는 MFT Entry들은 $MFT 메타 데이터 파일의 내용이 매우 조각화되어 Run List의 크기가 방대해져 MFT Entry 하나로는 정보를 다 담기가 힘들 경우에 이용된다.

1.2. $MFT

NTFS에서 가장 중요한 파일을 꼽으라면 바로 $MFT 파일일 것이다. 이 파일은 MFT를 담고 있는 파일이다.

속성 타입 속성 이름 설명
$STD_INFO 이름 없음 모든 파일에 존재하는 속성
$FILE_NAME $MFT 파일 이름
$DATA 이름 없음 MFT
$BITMAP 이름 없음 MFT Entry의 할당 정보

 

$MFTNon-Resident 속성으로 속성의 내용을 MFT Entry 안에 담아두는 것이 아니라 외부에 별도로 클러스터를 할당받아서 데이터를 담아두게 된다. 그렇기 때문에 $MFT 파일의 $DATA 속성의 Run ListMFT가 저장되어 있는 클러스터와 일치하게 설정할 수 있다.

[그림 1] $MFT 파일과 MFT의 관계

그림을 살펴보면, $MFT 파일의 $DATA 속성의 Run List에 적혀있는 클러스터 주소와 MFT의 할당 클러스터가 일치하는 것을 알 수 있다. 이런 방식으로 NTFSMFT를 관리하고 있으며, $MFT 파일의 $DATA 속성을 조사하면 MFT가 저장되어 있는 클러스터들을 파악 할 수 있다. 이 파일은 $BITMAP 속성을 담고 있는데, 이 파일에서 $BITMAP 속성은 MFT Entry의 할당을 관리하기 위해 사용된다. 어떤 MFT Entry가 할당되어 있으면 그에 해당하는 $BITMAP 속성의 bit1로 설정되고, 비어있다면 0으로 설정된다.

1.2.1. MFT Zone

이론적으로 MFT를 담고 있는 클러스터가 볼륨에 흩어져 있어도 상관없지만, MFT와 같이 매우 중요한 데이터를 담는 클러스터들이 산개할 경우 성능이나 관리 차원에서 좋지 않다. 따라서 Windows에서는 MFT Zone 영역을 설정해두고 있다.

MFT ZoneWindows가 미래에 MFT의 크기가 커질 것을 예상하여 최대한 다른 파일을 담지 않고 비워두는 영역으로 보통 볼륨의 12.5%정도를 할당한다. 만약 MFT Zone으로 비워둔 영역을 제외한 영역을 다 사용해 버렸을 경우 MFT Zone 영역이라도 일반 파일을 담는다.

1.3. $MFT Mirr

MFT Entry의 처음 부분에 담겨 있는 메타 데이터 파일들은 매우 중요하기 때문에 해당 정보가 훼손되면 큰 문제가 발생한다. 때문에 NTFS는 중요한 메타 데이터 파일들을 MFT Entry의 복사본을 $MFT Mirr에 따로 보관하고 있다.

속성 타입 속성 이름 설명
$STD_INFO 이름 없음 모든 파일에 존재하는 속성
$FILE_NAME $MFT 파일 이름
$DATA 이름 없음 중요한 MFT Entry들의 사본 저장

 

$MFT Mirr는 최소한 처음 4개 이상의 MFT Entry 복사본을 자신의 $DATA 속성에 담고 있다. 단지 메타 데이터 파일의 MFT Entry 내용의 복사본을 가지고 있기 때문에 MFT Entry의 내용만 복구 할 수 있다. 볼륨의 클러스터 크기가 MFT Entry 크기의 4배인 경우(, 클러스터 크기가 4KB), $MFT Mirr 파일은 0~3MFT Entry의 백업본을 저장하고 있다. 만약 클러스터 크기가 4KB보다 크다면 $MFT Mirr 파일은 한 클러스터에 들어갈 만큼의 MFT Entry의 백업본을 저장한다.

1.4. $LogFile

$LogFileMFT Entry 2번에 담겨 있다. 이 파일은 볼륨에서 일어나는 트랜잭션에 대한 정보를 담고 있다. 현재 $LogFile은 완벽히 분석되지 않은 상태이므로 NTFS를 구현할 때 이용할 수 없는 기능이다. 본 문서에서는 이 파일의 상위 수준의 구조와 동작 방식에 대해 알아본다.

1.4.1. $LogFile 파일의 저널링 방식

NTFS는 로깅(Logging)이라는 저널링(journaling) 기법을 이용한다. 저널링이란 만약 1,2,3 순서대로 수행되어야 할 경우 2번이나 3번에서 행위를 시작하는 시점에 특정 문제로 인해 수행이 되지 못하면 정상적으로 수행되지 못한 경우이다. 이때 1,2,3번을 수행하기 전으로 되돌려 상태를 정상화 하는 것이다. 데이터의 안전성이 중요한 데이터 베이스에서 이용된 기법으로 이를 고급 파일 시스템에도 도입하였다.

[그림 2] $LogFile의 $DATA 속성의 구조
 

$LogFile$DATA 속성은 언제나 Non-Resident 형태로 되어 있으며 위 그림과 같은 구조로 이루어져 있다. 앞쪽의 재시작 구역(Restart Area)이라고 불리는 곳과 나머지 로깅 구역(Logging Area)으로 불리는 2영역으로 나뉜다. 재시작 구역은 마지막으로 정보가 수정되었던 영역을 가리키고 있는 영역으로 NTFS가 마지막으로 수행했던 일이 무엇인지를 조사하기 위해 모든 로그를 처음부터 조사하지 않도록 해준다. 로깅 구역에는 일어난 트랜잭션의 기록을 저장하고 있게 된다. 로깅 구역이 끝까지 다 차버리면 다시 처음으로 돌아가서 기록을 하게 된다.

$DATA 속성의 크기는 볼륨의 약 1~2%로 고정되며, 더 이상 증가하지 않는다. MFT Entry Header에는 LSN 항목이 있는데 로깅 구역에서 자신의 MFT Entry에 관련된 트랜잭션 정보를 담는 위치 값을 가진다.

1.5. $Volume

$Volume 파일은 볼륨에 대한 정보를 담고 있는 메타 데이터 파일이다. 이 파일의 MFT Entry 주소는 3번이며, 다른 파일은 가지고 있지 않은 특별한 속성을 가지고 있다. 첫 번째는 $Volume_NAME이라는 속성으로 볼륨의 이름을 담고 있다. 이 속성이 담고 있는 볼륨의 UTF-16으로 인코딩 되어 있다. 두 번째는 $VOLUME_INFORMATION이라는 속성으로 NTFS의 버전 정보를 담고 있는 속성이다. 2가지 속성은 메타 데이터 파일에만 존재하며 $DATA는 아무런 정보를 담고 있지 않다.

1.5.1. $VOLUME_NAME 속성

· 속성 Type ID : 96
· 크기 : 최소 2Byte ~ 최대 256Byte
· 언제나 Resident 형식

이 속성이 담을 수 있는 최대 Byte 수는 256Byte이다. 그런데 유니코드는 2Byte 형식의 문자열이므로 볼륨 이름이 가질 수 있는 최대 길이는 128문자이다.

위치(Offset) 크기(Byte) 설명
  ~ 속성 헤더
0 ~ 가변적 볼륨 이름

 

1.5.2. $VOLUME_NAME 속성

· 속성 Type ID : 112
· 크기 : 최소 12Byte ~ 최대 12Byte
· 언제나 Resident 형식
위치(Offset) 크기(Byte) 설명
  ~ 속성 헤더
0~7 8 사용 안 함
8 1 Major Version
9 1 Minor Version
10~11 2 Flags

 

이 속성은 볼륨의 버전과 정보를 담고 있는 속성이다. 버전은 메이저 버전과 마이너 버전 두 가지가 존재하는데, 볼륨을 포맷하면 운영체제별로 다음과 같은 값들이 저장된다.

운영체제 Major Version Minor Version
Windows NT 1 2
Windows 2000 3 0
Windows XP 3 1
Flag 값 설명
0x0001 Dirty
0x0002 Resize LogFile
0x0004 Upgrade on Mount
0x0008 Mounted on NT4
0x0010 Delete USN underway
0x0020 Repair Object IDs
0x8000 Modified by chksdk

 

위 항목 중에서 살펴볼만한 값은 0x0001을 가지는 Dirty 값이다. 만약 이 값이 1이라면 Windows는 부팅 중에 chkdsk(디스크 검사)를 수행하게 된다.

1.6. $AttrDef

$AttrDefMFT Entry 4번에 존재하며, 볼륨에서 사용되는 모든 속성에 대한 여러 가지 정보(속성에 대한 Type ID, 이름 등)를 담고 있다. 이 파일이 이런 정보를 담고 있도록 따로 속성이 존재하는 것은 아니며, $DATA 속성의 내용을 분석해야 한다.

속성 타입 속성 이름 설명
$STD_INFO 이름 없음 모든 파일에 존재하는 속성
$FILE_NAME $AttrDef 파일 이름
$SECURITY_DESCRIPTOR 이름 없음 보안 관련 정보
$DATA 이름 없음 AttrDef Entry 보유

 

이 파일의 $DATA 속성은 아래 표에서 설명하고 있는 AttrDef Entry라고 불리는 구조체들을 담고 있다. AttrDef Entry는 속성의 종류만큼 존재한다.

위치(Offset) 크기(Byte) 설명
0~127 128 속성 이름
128~131 4 속성 Type ID
132~135 4 Display Rule
136~139 4 Collation Rule
140~143 4 Flags
144~151 8 속성의 최소 크기
152~159 8 속성의 최대 크기

 

위 표에서 보여준 구조체가 각각의 속성마다 하나씩 존재하고 있다. 위 표에 존재하는 항목 중에는 속성 Type ID’라는 항목이 있다. NTFS의 모든 속성의 Type ID 값은 기본적으로 정해져 있지만, 이 항목을 통해서 특정 속성의 Type ID를 자신이 원하는 값으로 다시 정의할 수 있다. Display Rule 항목에는 언제나 0 값이 저장되어 있다. Collation Rule 항목에도 아래와 같은 값들이 들어갈 수 있지만 아직까지는 언제나 0 값이 들어간다.

Flag 설명
0x00 Binary
0x01 File Name
0x02 Unicode String
0x10 Unsigned Long
0x11 SID
0x12 Security Hash
0x13 Multiple Unsigned Longs

 

Collation Rule에 들어가는 값은 해당 속성이 Index 정보를 담는데 사용되는 경우 Index Node들을 정렬하는 규칙으로 사용된다.

Flag 설명
0x02 Index 담기는 속성
0x40 Resident 형식만 가능
0x80 Non-Resident, Resident 모두 가능

 

Flags 항목의 값들은 해당 속성의 저장 형태와 Index 유무를 담고 있다. 어떤 속성의 Flag 값이 0x80이라면 속성은 언제나 Non-Resident라는 의미가 아니라 ResidentNon-Resident 모두 가능하다는 의미이다.

1.7. 루트 디렉토리(.)

속성 타입 속성 이름 설명
$STD_INFO 이름 없음 모든 파일에 존재하는 속성
$FILE_NAME . 파일 이름
$SECURITY_DESCRIPTOR 이름 없음 보안 관련 정보
$DATA $MountMgrdatabase 볼륨에 대한 Reparse Point가 있을 때만 존재
$INDEX_ROOT $l30 디렉토리 IndexRoot Node 정보
$INDEX_ALLOCATION $l30 디렉토리 IndexNode 보유
$BITMAP $l30 Index Record의 할당 상태 관리

 

이 파일은 최상위 디렉토리인 루트 디렉토리에 대한 정보를 담고 있는 파일이다. 루트 디렉토리는 다른 디렉토리와는 다르게 검색의 시작점이 되는 중요한 디렉토리이므로 메타 데이터 파일에 해당한다. 루트 디렉토리의 MFT Entry는 반드시 5Entry에 위치해야 한다. NTFS에서 루트 디렉토리의 이름은 ‘.’이지만, 만약 볼륨이 이 디렉토리에 대한 Reparse Point를 가지고 있다면 다른 이름으로도 지정될 수 있다. 그것에 대한 정보는 $MountMgrDatabase 속성을 조사하면 알 수 있다. 루트 디렉토리는 그 위치가 최상위라는 것 외에 다른 모든 것이 일반적인 다른 디렉토리와 다를 것이 없다.

1.8. $Bitmap

$Bitmap 파일은 MFT Entry 6번에 담겨 있으며 해당 볼륨의 클러스터를 관리하고 있다. 할당 정보를 담고 있는 속성은 $DATA이며, 일반적으로 NTFS가 할당 정보를 관리하는데 사용하는 속성은 $BITMAP이지만, 클러스터의 할당정보를 담는 속성은 $DATA이다. 그 안에 담긴 내용은 $BITMAP 속성을 분석하는 방법과 동일하다.

속성 타입 속성 이름 설명
$STD_INFO 이름 없음 모든 파일에 존재하는 속성
$FILE_NAME $Bitmap 파일 이름
$DATA 이름 없음 볼륨의 클러스터 할당 상태 정보

 

각각의 클러스터들은 메타 데이터 파일의 $DATA 속성의 하나의 bit와 각각 대응하게 된다. 할당되어 있다면 bit1이 되고, 비어 있다면 0이 된다.

n번째 존재하는 바이트 해당 클러스터
00000001 (n * 8) 번째 클러스터
00000010 (n * 8) +1번째 클러스터
00000100 (n * 8) +2번째 클러스터
00001000 (n * 8) +3번째 클러스터
00010000 (n * 8) +4번째 클러스터
00100000 (n * 8) +5번째 클러스터
01000000 (n * 8) +6번째 클러스터
10000000 (n * 8) +7번째 클러스터

 

1.9. $Boot

$BootMFT Entry 7번에 저장되어 있는 파일로 부트 레코드 영역을 담는다. $Data 속성은 언제나 Non-Resident 형식이며 Start LCN도 언제나 0번 클러스터로 고정되어 있다. 볼륨의 0번 클러스터에 부트 레코드가 담겨 있기 때문에 NTFS는 볼륨의 모든 부분을 클러스터로 관리하고 있음을 알 수 있다.

속성 타입 속성 이름 설명
$STD_INFO 이름 없음 모든 파일에 존재하는 속성
$FILE_NAME $Boot 파일 이름
$SECURITY_DESCRIPTOR 이름 없음 보안 관련 정보
$DATA 이름 없음 부트 레코드 영역 보유

[그림 3] $Boot 파일과 부트 레코드와의 관계

1.10. $BadClus

$BadClus 파일은 MFT Entry 8번에 존재한다. 평소 이 파일의 $DATA 속성은 볼륨과 동일한 크기로 사용 중인 것처럼 설정되어 있지만, Reparse 형태로 되어 있기 때문에 실제 볼륨상의 어떤 클러스터도 내용을 담고 있지 않다. 배드 클러스터가 생길 때마다 NTFS는 해당 클러스터를 이 파일의 Cluster Run에 추가한다. 이 파일에 연결된 클러스터들은 앞으로 절대 접근 하지 않는다.

속성 타입 속성 이름 설명
$STD_INFO 이름 없음 모든 파일에 존재하는 속성
$FILE_NAME $BadClus 파일 이름
$DATA 이름 없음 사용하지 않음
$DATA $Bad 배드 클러스터에 관한 정보

 

1.11. $UpCase

$Upcase 파일은 MFT Entry 10번에 존재한다. 이 파일의 $DATA 속성은 단순하게 유니코드 형식으로 된 문자열을 담고 있을 뿐이다. 파일 이름을 비교할 때 코드 페이지와 독립적으로 비교할 때 사용된다.

속성 타입 속성 이름 설명
$STD_INFO 이름 없음 모든 파일에 존재하는 속성
$FILE_NAME $UpCase 파일 이름
$DATA 이름 없음 각각의 문자열 보유

 

오프셋 문자
~ ~
0x82 A
0x84 B
0x86 C
~ ~

 

1.12. $Objld

$Objld 파일은 MFT Entry가 고정되지 않으며, 어떤 MFT Entry에 존재하든지 상관 없다. 이 파일은 볼륨에 존재하는 모든 Object ID의 정보를 인덱스에 담는다. Object ID 값은 볼륨에 유일하게 존재하는 고유의 128bit ID 값이며, 어떤 파일이 존재하는 위치가 바뀌거나 파일 이름이 변경되어도 Object ID 값은 변하지 않는다. 따라서 자신이 찾는 파일을 추적할 때 유용하게 사용된다.

속성 타입 속성 이름 설명
$STD_INFO 이름 없음 모든 파일에 존재하는 속성
$FILE_NAME $Objld 파일 이름
$INDEX_ROOT $O Object ID에 관한 루트 인덱스
$INDEX_ALLOCATION $O Object ID에 관한 인덱스
$INDEX_ALLOCATION $O Index Record의 할당 정보

 

$Object 메타 데이터 파일은 볼륨에 존재하는 모든 Object ID정보를 인덱스화 시켜 놓고 있기 때문에 빠르게 원하는 파일을 검색할 수 있게 한다. 여기서 사용하는 인덱스 구조도 디렉토리 인덱스와 동일하며 Index Entry가 담는 내용만 다르다.

위치(Offset) 크기(Byte) 설명
0x00 2 0x20 Offset to Data
0x02 2 0x38 Size of Data
0x04 4 0x00 Padding
0x08 2 0x58 Size of Index Entry
0x0A 2 0x10 Size of Index KEy
0x0C 2   Flags
0x0E 2 0x00 Padding
0x10 16   Key GUID Object ID
0x20 8   Data MFT reference
0x28 16   Data GUID Birth Volume ID
0x38 18   Data GUID Birth Object ID
0x48 16   Data GUID Domain ID
마지막 8바이트 8   $INDEX_ALLOCATION에서의 자식 노드 VCN(자식 노드가 있을 경우만)

 

Key 값은 인덱스를 정렬하는 기준이 되는 값으로, 디렉토리 인덱스에서는 파일 이름이 Key 값이 되고, $ObId 인덱스에서는 Object ID 값이 Key 값이 된다. Index Entry를 제외한 Index Node HeaderIndex Record Header의 구조는 디렉토리 인덱스와 동일하다.

Flag 설명
0x01 자식 노드가 존재함
0x02 마지막 Index Entry

 

1.13. $UsnJrnl

$UsnJrnl 파일은 메타 데이터 파일이긴 하지만 MFT Entry 어디에 위치해도 상관 없으며, 파일이나 디렉토리의 정보가 변경되면 그 기록을 담는다. $LogFile처럼 작업에 대한 기록을 남기는 점은 비슷하나 그 목적이 다르다. $LogFile의 경우 오류 복구가 목적이지만 $UsnJrnl 파일은 수행이 끝난 후 어떤 일이 일어났는지 만을 기록하고 있으면서 사용 목적도 어떤 일이 수행되었는지 확인하기 위한 것이다.

속성 타입 속성 이름 설명
$STD_INFO 이름 없음 모든 파일에 존재하는 속성
$FILE_NAME $UsnJrnl 파일 이름
$DATA $J 저널 데이터
$DATA $Max 저널의 기본적인 정보

 

$UsnJrnl 파일은 어떤 일이 수행되었다는 정보만 담고 있으며, 세부적인 내용은 없다. $DATA라는 2개의 속성이 있는데 ‘$J’‘$Max’이다.

1.13.1. $J 속성

저널 데이터를 담고 있는 $DATA 속성으로, 저널은 Journal Entry라 불리는 구조체들로 이루어져 있다. 각각의 Journal Entry는 파일이나 디렉토리의 변경 정보를 담고 있으며, 이 변경 정보는 순서대로 저장된다. 따라서 특정 시간대에 어떤 파일들이 변경되었는지를 조사하기가 수월하다. 이 속성은 크기가 줄지 않고 계속 증가하는데 물론 최대 허용 크기가 존재한다. 만약 이 속성의 내용이 최대 허용 크기를 다 채울 경우 데이터 앞쪽의 클러스터를 할당 해제함과 동시에 Sparse 형태로 변경한다. 그리고 새로운 클러스터를 할당받아 뒤쪽으로 붙인다. 이런 식으로 진행하면 실제 사용하는 클러스터의 개수는 변함이 없지만 이론적인 ‘$J’ 데이터 속성의 크기는 계속 증가하는 형식을 갖는다.

[그림 4] $UsnJrnl 파일의 저널 구조

위 구조는 A라는 파일이 새로 생성되고, B라는 파일이 수정되었다는 내용을 나타낸 것이다. 모든 파일이나 디렉토리가 가진 속성인 $STANDARD_INFORMATION에는 USN이라는 항목이 있고, 이 항목은 저널 데이터에서 자신과 관련된 Journal Entry의 위치 값을 담고 있다. 이 값을 이용하면 저널 데이터 내에서 관련 있는 Journal Entry를 쉽게 찾을 수 있다. USN 이라는 값은 절대 줄지 않고 계속 증가하며, Sparse 영역을 포함한 저널 데이터의 맨 처음부터 계산한 위치 값을 담는다.

$UsnJrnl 파일의 기능은 매우 유용해 보이지만, 이 기능은 기본적으로 비활성화 되어있다. 또한 일반 응용 프로그램들도 이 기능을 활성/비활성화 시킬 수 있다. 때문에 그리 유용히 쓰이지 못할 수도 있는 기능이다.

위치(Offset) 크기(Byte) 설명
0x00 4 해당 Journal Entry의 총 크기
0x04 2 Major Version
0x06 2 Minor Version
0x08 8 Journal Entry와 관련 있는 File Reference Address
0x10 8 부모의 File Reference Address
0x18 8 저널 데이터($J)에서 해당 Journal Entry의 위치(USN)
0x20 8 Time stamp
0x28 4 Reason Flags
0x2B 4 Source Information
0x30 4 Security ID(SID)
0x34 4 File Attributes
0x38 2 파일 이름의 크기
0x3A 2 파일 이름의 오프셋
0x3C 가변적 파일 이름
맨 뒤쪽 가변적 8Byte로 정렬하기 위한 패딩 바이트

 

위 항목 중 존재하는 Major VersionMinor VersionNTFS 버전이 아니라 저널 데이터의 버전 정보이다. 지금 사용 중인 저널 데이터의 버전은 2.0이므로 Major 버전은 2가 되고 Minor 버전은 0이 들어가는게 보통이다. Source Information 항목에는 일반적으로 0값이 들어가지만, 만약 0이 아니면 해당 Journal Entry는 사용자가 아니라 OS에 의한 것이다.

아래 표는 Reason Flags 항목에 들어갈 수 있는 값들을 보여준다.

오프셋 설명
0x00000001 기본 $DATA 속성의 내용이 덮어 쓰여짐
0x00000002 기본 $DATA 속성의 내용이 추가됨
0x00000004 기본 $DATA 속성의 내용이 감소
0x00000010 이름이 있는 $DATA 속성의 내용이 덮어 쓰여짐
0x00000020 이름이 있는 $DATA 속성의 내용이 추가됨
0x00000040 이름이 있는 $DATA 속성의 내용이 감소
0x00000100 파일 또는 디렉토리가 생성됨
0x00000200 파일 또는 디렉토리가 삭제됨
0x00000400 파일의 확장 속성이 변경됨
0x00000800 Security Descriptor가 변경됨
0x00001000 이름이 변경됨(이전 이름 보유)
0x00002000 이름이 변경됨(새로운 이름 보유)
0x00004000 인덱스 상태가 변경됨
0x00008000 파일 또는 디렉토리의 상태가 변경됨
0x00010000 Hard Link가 생성되거나 삭제됨
0x00020000 압축 상태가 변경됨
0x00040000 암호화 상태가 변경됨
0x00080000 Object ID가 변경됨
0x00100000 Reparse Point 값이 변경됨
0x00200000 이름이 있는 $DATA 속성이 생성, 삭제, 변경됨
0x80000000 파일 또는 디렉토리가 닫힘

 

1.13.2. $Max 속성

위치(Offset) 크기(Byte) 설명
0x00 8 저널 데이터의 최대 크기
0x08 8 저널 데이터의 할당 크기
0x10 8 USN ID
0x18 8 존재하는 것 중 가장 작은 USN

 

위 항목들을 이용하여 저널 데이터의 기본적인 정보를 얻을 수 있다.

2. NTFS 메타 데이터 파일 분석

NTFS 파일시스템에서 NTFS 메타 데이터 파일에 대한 정보를 확인하는 것이 이번 2장의 목표이다.

2.1. NTFS 부트 레코드 분석

NTFS 메타 데이터 파일 분석을 위해서는 먼저 부트 레코드 항목의 분석이 필요하다. 부트 레코드 영역은 해당 볼륨의 여러 가지 설정 값들을 저장하고 있으며, 해당 볼륨이 부팅될 수 있도록 부팅에 필요한 실행 코드도 포함하고 있다. 이 영역에 대한 기본적인 내용은 FAT 파일시스템의 그것과 동일하다. 다만 차이점이 있다면 부트 레코드가 담고 있는 항목들이 다르다는 것이다.

[그림 ] NTFS 부트 레코드

 

위 그림은 테스트 이미지의 NTFS 부트 레코드 이며, 각 항목에 대한 설명은 아래 표와 같다.

이름 위치(Offset) 크기(Byte) 설명
Jump Boot Code 0~2 3 EB 52 90 부트 코드 점프 명령어
OEM Name 3~10 8 ‘NTFS ’ OEM 회사 문자열
Byte Per Sector 11~12 2 512 섹터 당 바이트 수
Sector Per Cluster 13 1 8 클러스터 당 섹터 수
Reserved Sector Count 14~15 2 0 NTFS0으로 저장
Media 21 1 0xF8 볼륨 미디어 확인
Total Sector 40~47 8 1,433,599 볼륨 상에 있는 총 섹터 수
Start of MFT 48~55 8 0x04 MFT의 시작 클러스터 주소
Start of MFTMirr 56~63 8 0x015DFF MFTMirr의 시작 클러스터 주소
MFT Entry Size 64 1 0xF6 MFT Entry의 크기 지정
Index Record Size 68 1 0x01 인덱스 레코드의 크기
Serial Number 72~79 8 C3 93 C3 75 FF A5 AA 6C 볼륨 시리얼 번호
Signature 510~511 2 AA 55 시그니처

 

Byte Per SectorSector Per Cluster값을 통해 클러스터 크기를 구할 수 있다.

Sector Per Cluster * Bytes Per Sector = 클러스터 크기
=> 8 * 512 = 4096

클러스터 당 섹터 수가 8이고, 섹터 당 512바이트이므로 클러스터의 크기는 4KB이다. 또한 Start of MFT 값을 통해 MFT의 시작 클러스터 주소를 알 수 있다.

2.2. MFT

2.2.1. MFT

MFT(Master File Table)는 볼륨에 존재하는 모든 파일과 디렉토리에 대한 정보를 담고 있는 테이블이다. 파일과 디렉토리들의 이름이 뭔지, 언제 생성되었는지, 크기가 얼마인지, 어디에 내용이 있는지, 소유자가 누구인지 전부 MFT 안에 담겨 있다. 이처럼 MFTNTFS에서 가장 중요한 구조체이다.

2.2.2. MFT Entry

MFT는 수많은 MFT Entry의 집합니다. 하나의 MFT Entry는 하나의 파일 또는 디렉토리에 대한 정보를 담고 있다. 하나의 MFT Entry2개의 파일 정보가 담길 수는 없다. 만약 어떤 파일이 담을 정보가 많아서 MFT Entry 1개에 정보를 모두 담을 수 없다면 MFT Entry 여러 개에 나눠서 담기도 한다.

MFT Entry는 크기 2부분으로 구성되어 있다. 첫 번째는 MFT Header 부분이다. 이 부분에는 해당 MFT Entry의 정보와 상태를 담고 있게 된다. MFT Entry Header의 크기는 42Byte로 고정되어 있다. 두 번째는 속성(Attribute)을 담는 부분이다. MFT Entry의 목적은 어떤 파일이나 디렉토리의 정보를 담는 것인데, 그 정보가 바로 속성들을 말한다. MFT Entry1KB의 크기 중에서 자신의 Header 크기인 42Byte를 제외한 남은 영역은 전부 속성들을 담기 위해 사용한다.

[그림 6] MFT Entry 구조
 

2.3. $MFT 분석

NTFS 부트 레코드 항목의 Start of MFT (클러스터 4)으로 이동하면 $MFT가 위치한다.

[그림 7] $MFT의 MFT Entry Header

 

2.3.1. MFT Entry Header

모든 MFT EntryMFT Entry Header로 시작하게 된다. $MFTMFT Entry Header 항목은 다음 표와 같다.

이름 위치(Offset) 크기(Byte) 설명
Signature 0~3 4 ‘FILE’ 단순 문자열
Offset of Fixup Array 4~5 2 48 Fixup 배열 위치
Count of Fixup Values 6~7 2 3 Fixup 배열의 항목 수
$LogFile Sequence Number(LSN) 8~15 8 0x100A08 $LogFile에 기록되어 있는 해당 데이터의 수행과 관련된 마지막 트랜잭션의 위치
Sequence Value 16~17 2 1 MFT Entry 할당/해제 시 1씩 증가
Hard Link Count 18~19 2 1 Hard Link
Offset to First Attribute 20~21 2 56 첫 번째 속성의 위치
Flags 22~23 2 0x1 Flag
Used Size of MFT Entry 24~27 4 408 MFT Entry 사용 Byte
Allocated Size of MFT Entry 28~31 4 1024 MFT Entry 크기(Byte)
File Reference to Base MFT Entry 32~39 8 0 non-base MFT Entry일 경우 자신의 base MFT Entry 위치
Next Attribute ID 40~41 2 0x04 미래에 생성될 속성이 가질 ID

 

2.3.2. Fixup 배열

MFT Entry Headr 항목 중 Fixup에 관련된 항목이 2개 있다. Offset of Fixup Array라는 항목과 Count of Fixup Values라는 항목이다. Fixup이란 NTFS가 볼륨에 저장하는 데이터가 1개 이상의 섹터를 사용할 경우 각 섹터의 마지막 2Byte의 값을 특정 Signature 값으로 기록하고, 원래의 값은 따로 기억하고 있는 것을 말한다. 이런 Fixup 값은 해당 섹터의 데이터에 문제가 없는지를 검사할 때 사용한다.

[그림 8] Fixup 배열
 

2.3.3. 속성(Attributes)

속성은 MFT Entry Header, Fixup 배열 이후 마지막 표시자(End Marker)가 올 때까지 연속적으로 온다. 각 속성은 크게 속성 헤더와 속성 내용으로 나누어진다.

2.3.3.1 $STANDARD_INFORMATION

[그림 9] $STANDARD_INFORMATION 속성

Fixup 배열 이후에 $STANDARD_INFORMATION 속성이 존재한다.

이름 위치(Offset) 크기(Byte) 설명
Attribute Type Identifier 0~3 4 0x10 해당 속성의 고유 Type ID
Length Of Attribute 4~7 4 96 속성의 길이
Non-Resident Flag 8 1 0 Resident
Length Of Name 9 1 0 속성 이름의 길이
Offset to Name 10~11 2 0x18 속성 이름이 저장되어 있는 위치
Flags 12~13 2 0 속성의 여러 상태
Attribute Identifier 14~15 2 0 속성이 가지는 고유 값
Size of Content 16~19 4 72 속성 내용의 크기
Offset to Content 20~21 2 0x18 속성 내용이 시작되는 위치
Indexed Flag 22 1 0 검색에 사용되지 않는 속성
Padding 23 1 0 의미 없음

 

$STANDARD_INFORMATION 속성은 파일 생성 시간과 날짜, 파일의 소유자와 보안, 할당량에 관한 정보도 담고 있다. 이 속성의 Type ID16이며, 이 속성의 Type ID보다 더 작은 Type ID 값을 가진 속성은 존재하지 않으므로 언제나 MFT Entry의 맨 앞쪽에 이 속성이 위치한다. , non-base MFT Entry의 경우에는 이 속성이 존재하지 않으므로 이 경우는 제외한다. 또한 이 속성은 그 크기가 변하지 않고 언제나 고정되어 있으므로 항상 Resident 형태로 담겨 있다. 다음 표는 샘플 이미지에서의 속성 내용 항목들이다.

이름 위치(Offset) 크기(Byte) 설명
Creation Time 0~7 8 0x01cf60ae061a5a00 파일 생성 시간
Modified Time 8~15 8 0x01cf60ae061a5a00 파일 수정 시간
MFT Modified Time 16~23 8 0x01cf60ae061a5a00 MFT 최종 수정 시간
Accessed Time 24~31 8 0x01cf60ae061a5a00 최종 파일 내용 접근 시간
Flags 32~35 4 0x06 숨김, 시스템 파일
Maximum number of version 36~39 4 0 파일에 허용되는 최대 버전
Version Number 40~43 4 0 파일의 버전
Class ID 44~47 4 0 Class ID
Owner ID 48~51 4 0 파일 소유자 ID
Security ID 52~55 4 0x100 Security ID
Quota Charged 56~63 8 0 제한 량에서 파일 차지 정도
USN 64~71 8 0 Update Sequence Number

 

2.3.3.2 $FILE_NAME

[그림 10] $FILE_NAME 속성
 

$FILE_NAME 속성은 파일이나 디렉토리의 이름을 담는 속성이다. 이 속성에 이름이 저장될 때는 UTF-16으로 인코딩되어 저장된다. 이 속성의 Type ID48번이다.

이름 위치(Offset) 크기(Byte) 설명
Attribute Type Identifier 0~3 4 0x30 해당 속성의 고유 Type ID
Length Of Attribute 4~7 4 68 속성의 길이
Non-Resident Flag 8 1 0 Resident
Length Of Name 9 1 0 속성 이름의 길이
Offset to Name 10~11 2 0x18 속성 이름이 저장되어 있는 위치
Flags 12~13 2 0 속성의 여러 상태
Attribute Identifier 14~15 2 0x02 속성이 가지는 고유 값
Size of Content 16~19 4 74 속성 내용의 크기
Offset to Content 20~21 2 0x18 속성 내용이 시작되는 위치
Indexed Flag 22 1 1 검색에 사용되는 속성
Padding 23 1 0 의미 없음

 

$FILE_NAME 속성은 빠른 파일 검색을 위해 사용되는 인덱스에도 존재하는 속성이다. , 동일한 파일이나 디렉토리의 $FILE_NAME 속성이 인덱스에도 존재하고 해당 파일의 MFT Entry에도 존재하게 된다. 다음 표는 샘플 이미지에서의 속성 내용 항목들이다.

이름 위치(Offset) 크기(Byte) 설명
부모 디렉토리의 File Reference Address 0~7 8 0x5000000000005 자신을 담고 있는 디렉토리의 File Reference Address 주소
Creation Time 8~15 8 0x01cf60ae061a5a00 파일 생성 시간
Modified Time 16~23 8 0x01cf60ae061a5a00 파일 수정 시간
MFT Modified Time 24~31 8 0x01cf60ae061a5a00 MFT 최종 수정 시간
Accessed Time 32~39 8 0x01cf60ae061a5a00 최종 파일 내용 접근 시간
파일의 할당 크기 40~47 8 28,672  
파일의 실제 크기 48~55 8 27,648  
Flag 56~59 4 0x06 숨김, 시스템
Reparse Value 60~63 4 0 Reparse Type
이름의 길이 64 1 4  
이름의 형식 65 1 0x03 Win32&DOS
이름 66~ 가변적 0x540046004d00240304 $MFT

 

2.3.3.3 $DATA

$DATA 속성은 파일의 내용을 담고 있는 속성이다. 속성의 Type ID128이다.

[그림 11] $DATA 속성

 

$DATA 속성은 속성 헤더와 데이터로 구성되어 있다. 이 속성의 크기는 제한이 없으며, 만약 데이터의 크기가 700Byte 정도가 넘어가면 Windows는 해당 속성을 Resident에서 Non-Resident 속성으로 전환시킨다.

이름 위치(Offset) 크기(Byte) 설명
Attribute Type Identifier 0~3 4 0x80 해당 속성의 고유 Type ID
Length Of Attribute 4~7 4 72 속성의 길이
Non-Resident Flag 8 1 1 Non-Resident
Length Of Name 9 1 0 속성 이름의 길이
Offset to Name 10~11 2 64 속성 이름이 저장되어 있는 위치
Flags 12~13 2 0 속성의 여러 상태
Attribute Identifier 14~15 2 0x01 속성이 가지는 고유 값
Starting VCN of the runlist 16~23 8 0 Run List 시작 VCN
Ending VCN of the runslist 24~31 8 63 Run List 마지막 VCN
Offset to the run list 32~33 2 64 Run List의 시작 위치
Compression unit size 34~35 2 0 압축 단위 크기
Padding 36~39 4 0 의미 없음
Allocated Size of attribute content 40~47 8 262,144 속성 데이터가 할당 되어있는 클러스터의 총 크기
Real Size of attribute content 48~55 8 262,144 속성 데이터의 실제 크기(Byte)
Initialized Size of attribute content 56~63 8 262,144 속성 데이터의 초기화 된 크기
runlist 64~      

 

$DATA 속성은 Non-Resident 속성으로 Runlist를 통해 실제 데이터를 확인 할 수 있다.

[그림 12] Runlist 정보

[그림 13] Runlist 구조
 

위의 Run List의 구조대로 해석해보면 다음과 같다.

클러스터 런 : 11 40 04

Run 길이(1 bytes) : 64(0x40)

Run 오프셋(1 bytes) : 0x04

2.3.3.4 $BITMAP

$BITMAP 속성은 MFTIndex의 할당 정보를 관리할 때 사용한다. $MFT에 존재하는 $BITMAP 속성은 MFT의 할당 정보를 관리하는 속성이 되고, 디렉토리의 정보를 담고 있는 MFT Entry에 존재하는 $BITMAP 속성은 해당 디렉토리의 Index 할당 정보를 관리한다.

[그림 14] $BITMAP 속성
 

$BITMAP 속성은 속성 헤더와 데이터로 구성되어 있다. 이 속성의 크기는 제한이 없다.

이름 위치(Offset) 크기(Byte) 설명
Attribute Type Identifier 0~3 4 0xB0 해당 속성의 고유 Type ID
Length Of Attribute 4~7 4 72 속성의 길이
Non-Resident Flag 8 1 1 Non-Resident
Length Of Name 9 1 0 속성 이름의 길이
Offset to Name 10~11 2 64 속성 이름이 저장되어 있는 위치
Flags 12~13 2 0 속성의 여러 상태
Attribute Identifier 14~15 2 0x03 속성이 가지는 고유 값
Starting VCN of the runlist 16~23 8 0 Run List 시작 VCN
Ending VCN of the runslist 24~31 8 1 Run List 마지막 VCN
Offset to the run list 32~33 2 64 Run List의 시작 위치
Compression unit size 34~35 2 0 압축 단위 크기
Padding 36~39 4 0 의미 없음
Allocated Size of attribute content 40~47 8 8,192 속성 데이터가 할당 되어있는 클러스터의 총 크기
Real Size of attribute content 48~55 8 4,104 속성 데이터의 실제 크기(Byte)
Initialized Size of attribute content 56~63 8 4,104 속성 데이터의 초기화 된 크기

 

$BITMAP 속성은 Non-Resident 속성으로 Run List를 통해 실제 데이터를 확인 할 수 있다.

2.4. $MFT Mirr 분석

$MFT MirrMFT Entry의 복사본이다. 이 파일은 최소한 처음 4MFT Entry 이상의 복사본을 자신의 $DATA 속성에 담고 있다.

2.4.1. MFT Entry Header

[그림 15] $MFT Mirr의 MFT Entry Header

 
이름 위치(Offset) 크기(Byte) 설명
Signature 0~3 4 ‘FILE’ 단순 문자열
Offset of Fixup Array 4~5 2 48 Fixup 배열 위치
Count of Fixup Values 6~7 2 3 Fixup 배열의 항목 수
$LogFile Sequence Number(LSN) 8~15 8 0 $LogFile에 기록되어 있는 해당 데이터의 수행과 관련된 마지막 트랜잭션의 위치
Sequence Value 16~17 2 1 MFT Entry 할당/해제 시 1씩 증가
Hard Link Count 18~19 2 1 Hard Link
Offset to First Attribute 20~21 2 56 첫 번째 속성의 위치
Flags 22~23 2 0x1 Flag
Used Size of MFT Entry 24~27 4 344 MFT Entry 사용 Byte
Allocated Size of MFT Entry 28~31 4 1024 MFT Entry 크기(Byte)
File Reference to Base MFT Entry 32~39 8 0 non-base MFT Entry일 경우 자신의 base MFT Entry 위치
Next Attribute ID 40~41 2 0x03 미래에 생성될 속성이 가질 ID

 

2.4.2. Fixup 배열

 

2.4.3. 속성(Attributes)

속성은 MFT Entry Header, Fixup 배열 이후 마지막 표시자(End Marker)가 올 때까지 연속적으로 온다. 각 속성은 크게 속성 헤더와 속성 내용으로 나누어진다.

2.4.3.1 $STANDARD_INFORMATION

[그림 17] $STANDARD_INFORMATION 속성
 

Fixup 배열 이후에 $STANDARD_INFORMATION 속성이 존재한다.

이름 위치(Offset) 크기(Byte) 설명
Attribute Type Identifier 0~3 4 0x10 해당 속성의 고유 Type ID
Length Of Attribute 4~7 4 96 속성의 길이
Non-Resident Flag 8 1 0 Resident
Length Of Name 9 1 0 속성 이름의 길이
Offset to Name 10~11 2 0x18 속성 이름이 저장되어 있는 위치
Flags 12~13 2 0 속성의 여러 상태
Attribute Identifier 14~15 2 0 속성이 가지는 고유 값
Size of Content 16~19 4 72 속성 내용의 크기
Offset to Content 20~21 2 0x18 속성 내용이 시작되는 위치
Indexed Flag 22 1 0 검색에 사용되지 않는 속성
Padding 23 1 0 의미 없음

 

2.4.3.2 $FILE_NAME

[그림 18] $FILE_NAME 속성
 

$FILE_NAME 속성은 파일이나 디렉토리의 이름을 담는 속성이다. 이 속성에 이름이 저장될 때는 UTF-16으로 인코딩되어 저장된다. 이 속성의 Type ID48번이다.

이름 위치(Offset) 크기(Byte) 설명
Attribute Type Identifier 0~3 4 0x30 해당 속성의 고유 Type ID
Length Of Attribute 4~7 4 112 속성의 길이
Non-Resident Flag 8 1 0 Resident
Length Of Name 9 1 0 속성 이름의 길이
Offset to Name 10~11 2 0x18 속성 이름이 저장되어 있는 위치
Flags 12~13 2 0 속성의 여러 상태
Attribute Identifier 14~15 2 0x02 속성이 가지는 고유 값
Size of Content 16~19 4 82 속성 내용의 크기
Offset to Content 20~21 2 0x18 속성 내용이 시작되는 위치
Indexed Flag 22 1 1 검색에 사용되는 속성
Padding 23 1 0 의미 없음

 

다음 표는 샘플 이미지에서의 속성 내용 항목들이다.

이름 위치(Offset) 크기(Byte) 설명
부모 디렉토리의 File Reference Address 0~7 8 0x5000000000005 자신을 담고 있는 디렉토리의 File Reference Address 주소
Creation Time 8~15 8 0x01cf60ae061a5a00 파일 생성 시간
Modified Time 16~23 8 0x01cf60ae061a5a00 파일 수정 시간
MFT Modified Time 24~31 8 0x01cf60ae061a5a00 MFT 최종 수정 시간
Accessed Time 32~39 8 0x01cf60ae061a5a00 최종 파일 내용 접근 시간
파일의 할당 크기 40~47 8 4,096  
파일의 실제 크기 48~55 8 4,096  
Flag 56~59 4 0x06 숨김, 시스템
Reparse Value 60~63 4 0 Reparse Type
이름의 길이 64 1 8  
이름의 형식 65 1 0x03 Win32&DOS
이름 66~ 가변적 0x540046004d00240304 $MFT Mirr

 

2.4.3.3 $DATA

$DATA 속성은 파일의 내용을 담고 있는 속성이다. 속성의 Type ID128이다.

[그림 19] $DATA 속성
 

$DATA 속성은 속성 헤더와 데이터로 구성되어 있다. 이 속성의 크기는 제한이 없으며, 만약 데이터의 크기가 700Byte 정도가 넘어가면 Windows는 해당 속성을 Resident에서 Non-Resident 속성으로 전환시킨다.

이름 위치(Offset) 크기(Byte) 설명
Attribute Type Identifier 0~3 4 0x80 해당 속성의 고유 Type ID
Length Of Attribute 4~7 4 72 속성의 길이
Non-Resident Flag 8 1 1 Non-Resident
Length Of Name 9 1 0 속성 이름의 길이
Offset to Name 10~11 2 64 속성 이름이 저장되어 있는 위치
Flags 12~13 2 0 속성의 여러 상태
Attribute Identifier 14~15 2 0x01 속성이 가지는 고유 값
Starting VCN of the runlist 16~23 8 0 Run List 시작 VCN
Ending VCN of the runslist 24~31 8 0 Run List 마지막 VCN
Offset to the run list 32~33 2 64 Run List의 위치
Compression unit size 34~35 2 0 압축 단위 크기
Padding 36~39 4 0 의미 없음
Allocated Size of attribute content 40~47 8 4,096 속성 데이터가 할당 되어있는 클러스터의 총 크기
Real Size of attribute content 48~55 8 4,096 속성 데이터의 실제 크기(Byte)
Initialized Size of attribute content 56~63 8 4,096 속성 데이터의 초기화 된 크기

 

$FILE_NAME 속성은 Non-Resident 속성으로 Run List를 통해 실제 데이터를 확인 할 수 있다.

 

Appendix. 참고 문헌

  1. 브라이언 캐리어, 주필환, “파일시스템 포렌식 분석”, 케이앤피IT, 2010.
  2. 정준석, “임베디드 개발자를 위한 파일시스템의 원리와 실습”, 2006.
  3. Security CodeName bitnang, “파일시스템 4_5 NTFS 메타 데이터 파일 & 파일 읽기, “http://blog.naver.com/bitnang/70185263214