본문 바로가기

[Forensic] NTFS Analysis

@myeongsang2025. 9. 27. 03:36
반응형

이번엔 NTFS 구조에 대해 설명하겠습니다.

 

1. NTFS(New Technology File System)

Microsoft Windows 의 파일 시스템 입니다. MS-DOS부터 쓰인 FAT의 확장성, 보안, 및 제한 사항을 극복하기 위해서 1993년 Windows NT 3.1과 함께 발표되었습니다. FAT에 비해 여러가지 개선 되었습니다.

 

NTFS Version First OS Release data
1.0 Windows NT 3.1 1993
1.1 Windows NT 3.5 1994
1.2 Windows NT4.0 1996
3.0(5.0) Windows 2000 2000
3.1(5.1) Windows XP 2001

다음은 NTFS Cluster Size 입니다.

Volume Size Windows NT 3.51 Windows NT 4.0 Windows 7, Windows Server 2008 R2, Windows Server 2008, Windows Vista, Windows Server 2003, Windows XP, Windows 2000
7 MB ~ 512 MB 512 bytes 4KB 4KB
512 MB ~ 1 GB 1KB 4KB 4KB
1GB ~ 2GB 2KB 4KB 4KB
2GB ~ 2TB 4KB 4KB 4KB
2TB ~ 16TB Not Supported Not Supported 4KB
16TB ~ 32TB Not Supported Not Supported 8KB
32TB ~ 64TB Not Supported Not Supported 16KB
64TB ~ 128TB Not Supported Not Supported 32KB
128TB ~ 256TB Not Supported Not Supported 64KB
256TB ~ Not Supported Not Supported Not Supported

 

NTFS 파일 시스템도 전반적인 구조는 FAT32와 크게 다르지는 않습니다. MFT(Master File Table)이라는 별도의 구조를 두어서 MFT에 모든 파일의 메타데이터를 저장합니다. 그리고 VBR은 볼륨의 맨끝에 Backup VBR 을 별도로 복구가 가능하도혹 했습니다.

NTFS 구조

1.1 VBR

NTFS의 VBR은 아래와 같은 구조를 가지는데 오프셋 차이만 있고 FAT32의 전반적인 구조와 유사성을 지닙니다.

NTFS VBR구조

Name Offset Size Description
Jump Command 0x0 ~ 0x2 0x3 Boot Code로 점프
BPB(Bios parameter Block) 0x3 ~ 0x53 0x51 볼륨의 전반적인 설정을 포함
Boot Code 0x54 ~ 0x1FD 0x1AA 볼륨 부트코드
Signature 0x1FE ~ 0x1FF 0x2 고정값

 

1.1.1 BPB(Bios Parameter Block)

NTFS - BPB

NTFS VBR의 BPB 영역 구조를 살펴보겠습니다.

Name Offset Description
OEM ID 0x03 ~ 0x0A NTFS로 고정된 값 입니다.
Bytes Per Sector 0x0B ~ 0x0C 한 섹터 당 할당되는 Byte 크기 입니다.
Sector Per Cluster 0x0D ~ 0x0D 한 클러스터당 할당되는 섹터 수 입니다.
Reserved Sector Count 0x0E ~ 0x0F FAT Area가 나오기 전의 섹터 수 입니다.
Unused 0x10 ~ 0x14 사용되지 않습니다.
Media 0x15 ~ 0x15 대부분 0xF8 : 고정 디스크입니다.
Unused 0x16 ~ 0x27 사용되지 않습니다.
Total Sectors 0x28 ~ 0x2F 볼륨의 총 섹터 수 입니다.
Start Cluster for $MFT 0x30 ~ 0x37 해당 값 기반으로 MFT 영역 찾아갈 수 있습니다.
Start Cluster for $MFTMirr 0x38 ~ 0x3F $MFTMirr 영역에 찾아갈 수 있습니다.
Cluster Per Entry 0x40 ~ 0x40 MFT Entry 크기 입니다.
Unused 0x41 ~ 0x43 사용되지 않습니다.
Cluster Per Index 0x44 ~ 0x44 디렉토리 공간 할당을 위해서 사용하는 인덱스 버퍼 크기 입니다.
Unused 0x45 ~ 0x47 사용되지 안습니다.
Volume Serial Number 0x48 ~ 0x4F 볼륨의 식별하는 8byte로 구성되어있는 시리얼 넘버 입니다.
Unused 0x50 ~ 0x53 사용되지 않습니다.

 

1.2  MFT(Master File Table)

MFT 파일은 NTFS 파일, 디렉토리, 메타데이터를 모두 파일 형태로 관리하는 파일입니다. 이러한 데이터는 MFT Entry라는 구조를 통해서 저장이 됩니다. MFT Area는 파일 시스템 파일 수에 따라서 동적 할당을 합니다. MFT Entry의 0~15번은 시스템 메타데이터를 저장하기 위해서미리 예약된 영역 으로 사용 됩니다.

 

$MFT 영역 주소 계산법입니다.

[+] MFT Address = Start Cluster For MFT * Cluster Size(0x1000)
[+] Start Cluster For $MFT(Sector) = Start Cluster For MFT * Sector Per Cluster
[+] Start Cluster For $MFTMirr(Sector) = Start Cluster For MFTMirr * Sector Per Cluster

구한 값을 보면 

$MFT
$MFTMirr

2개의 값들을 보면 $파일이 같은것은 알 수 있을겁니다. MFT 영역에서 MFT Entry에 대해서 구조를 봐보겠습니다.

MFT Entry 0~15번까지는 파일시스템의 Reserved Area로 정해져있다.

Entry Num Entry Name Description
0 $MFT 모든 파일의 MFT Entry정보를 담고있습니다.
1 $MFTMirr $MFT 파일의 일부 백업 데이터를 담고 있습니다.
2 $LogFile Meta Data의 트랜잭션 정보를 담고 있는 파일 입니다. 파일 수정, 생성 등과 같은 이벤트 발생시 기록됩니다.
3 $Volume 볼륨의 버전 정보 식졀자와 같은 정보를 담고 있습니다.
4 $ArrtDef 속성의 식별자, 이름, 크기, 등의 정보를 담고 있습니다.
5 $ 볼륨 루트디렉토리 정보를 담고 있습니다.
6 $BitMap 볼륨의 클러스터 할당 정보를 담고 있습니다.
7 $Boot 부트섹터 정보를 담고 있습니다.
8 $BadClus 배드 섹터를 가지는 클러스터의 정보를 담고 있습니다.
9 $Secure 파일의 보안, 접근 제어와 관련한 정보를 담고 있습니다.
10 $Upcase 모든 유니코드의 대문자를 저장 합니다.
11 $Extend 파일의 추가적인 정보를 저장하는 영역 입니다.
12~15   예약된 영역 입니다.
16~   포맷후 생성되는 파일의 정보를 위해 사용하는 영역 입니다.
- $ObjID 파일 고유 ID정보 담고있습니다
- $Quota 사용량의 정보를 담고 있습니다.
- $Reparse Reparse Point에 대한 정보를 담고 있습니다.
- $UsnJrnl 파일, 디렉토리 변경 정보를 담고 있습니다.

 

다음으로 MFT Entry의 영역을 알아보겠습니다. MFT Entry 구조 입니다.

MFT Entry Structure Layout

Name Offset Description
MFT Entry Header 0x0 ~ 0x2F MFT Entry의 메타 데이터
Fix-up Array 0x30 ~ 0x37 NTFS의 신뢰성을 높이기 위한 구조
Attribute Area 0x38 ~ 달라질 수 있습니다 파일 이름, 변경 시각 등 속성 들이 나열되는 영역
End Marker 이후 MFT Entry 끝을 알리는 데이터

1.2.1 MFT Entry Header

MFT Entry Header는 MFT Entry의 메타데이터 정보를 담고 있는 48바이트 영역입니다. MFT Entry Header의 Layout을 확인해 보겠습니다.

MFT Entry Header

Name Offset Description
Signature 0x00 ~ 0x03 Signature: File
Offset to Fixup Array 0x04 ~ 0x05 Fixup 배열 시작위치 입니다.
Entries in Fixup Array 0x06 ~ 0x07 Fixup 배열 포함 항목 수 입니다.
$LogFile Sequence Number 0x08 ~ 0x0F $LogFile 존재하는 해당 파일 트랜젝션 위치 입니다.
Sequence Number 0x10 ~ 0x11 순서 번호로 MFT Entry 생성 후에 할당/해제 시 1씩 증가 합니다.
Hard Link Count 0x12 ~ 0x13 해당 MFT Entry에 연결된 하드 링크 입니다.
Offset to File Attribute 0x14 ~ 0x15 해당 Entry의 첫번째 파일 속성 위치 입니다.
Flags 0x16 ~ 0x17 0x01 사용중 / 0x02  디렉토리 (MFT Entry 속성)
Real Size of MFT Entry 0x18 ~ 0x1B 사용 중인 크기 입니다.
Allocated Size of MFT Entry 0x1C ~ 0x1F MFT Entry에 할당된 크기 입니다.
File Reference to Base Entry 0x20 ~ 0x27 Entry가 non-base일때 Base Entry 주소 입니다.
Next Arrtibute ID 0x28 ~ 0x29 다음 속성 ID 입니다.
Align to 48 Boundary 0x2A ~ 0x2B xp만 존재합니다.
Number of this MFT Entry 0x2C ~ 0x2F xp에만 존재합니다.

 

1.2.2 Base & Non-base MFT Entry

MFT Entry Header에서 Base Entry or Non-base Entry참조 주소를 담고 있는걸 알 수 있습니다. Base Entry는 파일의 기본 정보를 저장하고(크기, 시간 등등) 가장 중요한 속성들이 저장됩니다. 그리고 Non-base Entry들의 위치를 관리합니다. 반면에 Non-base MFT Entry는 추가 속성 정보를 저장합니다. 그리고 파일의 속성 내용이 클 경우 하나 이상의 MFT Entry를 사용하게 됩니다. Base MFT Entry는 파일의 첫 MFT를 사용하게 됩니다, Non-Base MFT Entry는 Base MFT Entry를 제외한 나머지 부분을 담고 있는 Entry입니다.

[+] 예시

[+] MFT Entry 100(base) 00 00 00 00 00 00 00 00
Stored contents:
	File Name: test.txt
    File Size: 10MB
    ...

[+] MFT Entry 105(Non-base) 64 00 00 00 00 xx xx
Stored contents:
	Additional ACL information
    Compression attribute
    ....
	
[+] MFT Entry 110(Non-base) 64 00 00 00 00 xx xx
Stored contents:
	etc meta data

[+] (맨뒤에 있는 xx xx는 100번 Entry의 Sequence Number을 사용합니다.)
[+] File Reference to Base MFT Entry 자리가 00 00 00 00 00 00 00 00 이면 Base MFT Entry 구조 이고,
[+] 00 00 00 00 00 00 00 00 이 아니라면 Non-Base MFT Entry구조입니다.

 

1.2.3 File Reference Address

File Reference Address는 NTFS에서 파일을 가리키는 정확한 주소입니다.

  • Size : 8byte(64bit)
  • Composition : Sequence Number(16bit) + MFT Entry Address(48bit)

Sequence Number은 MFT Entry가 재사용 될때마다 값이 증가합니다. 파일이 삭제 되거나 그럴때는 증가하지는 않고, 새로운 파일이 해당 Entry를 사용할 때 증가합니다. Sequence Number에서의 목적은 Entry 재사용시 무결성을 보장하기 위해서 있습니다.

 

만약 Entry 100 에 password.txt 를 저장하고(sequence:0x0001), 다른 곳에서 Entry 100을 참조합니다. 그리고 password.txt 삭제되면(sequence: 0x0001유지) 해당 MFT Entry는 재사용을 위해 가용상태가 되며, Entry 100 에 old.txt 저장 합니다. 그럼 Sequence Number가 1 증가 됩니다.

 

MFT Entry Address은 MFT Entry의 물리적 위치를 나타내는 번호를 뜻합니다. MFT에서 몇번째 Entry 인지 나타냅니다.

 

File Reference Address 계산식은(Sequence Number은 MFT Entry Header 0x10~0x11에 위치합니다.)

[+] File Reference Address = Sequence Number + MFT Entry Address

 

1.2.4 Fixup Array

MFT Fixup Array Area는 데이터 무결성을 판당하는 영역입니다.(MFT Entry) MFT Entry는 2개의 섹터를 사용합니다. 해당 Fixup Array는 MFT Entry의 데이터 무결성을 가지고 있는지 확인하기 위해서 각 섹터의 마지막 2byte를 특정 Signature로 값을 대체하고 기존 값을 Array에 저장합니다.

위 hex값을 보겠습니다. 빨간 네모박스는 Offset of Fixup Array, 주황색 네모박스는 Number of Entries in Fixup Array이고 초록색은 Signature값 그리고 파란색은 기존 마지막 섹터 2byte를 백업하여 저장한 값입니다.

 

Fixup Array의 크기는 사실상 Signature는 2byte이기 때문에 Number of Entries in Fixup Array값에 따라 결정됩니다. 서로의 합이 Fixup Array크기 이기때문입니다. Offset of Fixup Array: 0x30이고 Fixup Array 크기를 구하면 0x03 * 2= 6byte이니 8byte의 크기가됩니다.

Signature value: 0x02 00
Fixup Array value : 0x42 35 29 30 00 00

그럼 Fixup Array 적용전 적용후를 얘기해 보겠습니다. 

Fixup Array를 적용전에는 해당 Fixup Array에 42 35 29 30값이 저장되지 않고 저장되지 않고 
Signature에 1섹터에 2byte씩저장됩니다.

Fixup Array값을 적용하면 Fixup Array에 값이 42 35 29 30 값이 저장되고 
signature값과 똑같이 0x02 00으로 저장됩니다.

 

1.2.5 Attribute

Attributes Area는 MFT Area에서 가장 크게 차지하고 있습니다. 또한 중요한 영역 입니다. 그리고 모든 디렉토리 및 파일의 모든 내용을 담고 있습니다. 또한 Attribute Entry 는 Attribute Content로 이루어져있고 팡리의 메타데이터 정보와 일부 파일의 데이터 자체를 포함합니다.

 

Resident Attribute: 크기가 작은 파일이 해당되고, MFT Entry속성 헤더 바로 뒤에 속성 내용이 저장됩니다. MFT Entry 내부에 직접 저장되다보니 빠른 접근이 가능합니다.

Non-Resident Attribute: 크기가 큰 파일들이 해당되고, 속성의 내용의 크기가 너무 커서 별도의 클러스터에 저장됩니다. 그리고 MFT Entry에는 위치 정보만 저장됩니다. 이런 Non-Resident Attribute 는 파일시스템의 한도까지 저장 가능합니다.

 

Attributes Area는 여러개의 속성 구조로 관리가 됩니다. 하나의 속성 구조는 속성 헤더, 내용 을 가집니다. 그리고 각각의 Attribute Entry는 Attribute의 파일크기에 따라서 Resident 속성과 Non-Resident 속성 으로 나뉩니다. (하나의 파일을 저장할때 MFT Entry가 생성됩니다. 해당 내의 있는 Attribute Area는 여러개의 Attribute Entry가 생성됩니다.)

 

'File Size' < 700byte Resident Attribute

'File Size' > 700byte Non-Resident Attribute

 

1.2.6 Common Attribute Header

Attribute 의 가장 기본적인 포맷입니다. 구조를 보면

Common Attribute Header는 Resident Attribute Header 와 Non-Resident Attribute Header에 필수 적으로 0x00~0x0F까지 들어가는 구조입니다. 확인해보면

Name Offset Description
Attribute Type ID 0x00 ~ 0x03 속성 타입 식별값입니다.
Length of Attribute 0x04 ~ 0x07 속성 전체길이 입니다.
Non-Resident flag 0x08 ~ 0x08 Non-Resident 인지 확인하는 flag값입니다. (0x00: Resident 속성 0x01: Non-Resident속성)
Length of Name 0x09 ~ 0x09 자신의 이름 길이를 나타내는 부분 입니다.
Offset to Name 0x0A ~ 0x0B 해당 속성 이름이 저장된 곳의 주소를 나타내는 부분입니다.
Flags 0x0C ~ 0x0D 상태 표현하는 부분 입니다.(0x0001: 압축 속성/ 0x4000: 암호화 속성/ 0x8000: Sparse 속성)
Attribute identifier 0x0E ~ 0x0F 속성의 고유한 식별자로 MFT Entry에 같은 속성이 여러개 일 경우 구별하기 위해서 사용하는 부분입니다.

 

1.2.7 Resident Attribute Header

해당 헤더는 Common Attribute Header의 0x00~0x0F 같은 값을 가집니다. 그 밑에 한줄이 추가되었습니다. 해당 Common Attribute Header 다음으로 나오는 영역의 크기는 8 아니면 16byte를 가진다 구조를 보면

Name Offset Description
Length of the Attribute 0x10 ~ 0x13 헤더 뒤에 오는 속성 내용 크기 입니다.
Offset to Attribute Data 0x14 ~ 0x15 속성 내용 시작 위치 입니다.
Indexed Flag 0x16 ~ 0x16 1이라는 값을 가지면 인덱스 된 속성임을 뜻합니다.
Unused 0x17 ~ 0x17 사용되지 않는 부분 입니다.
Attribute Name 0x18 ~ 0x1F 속성 이름이 있는 경우 이고, 없으면 바로 속성 사용하는 부분입니다.

 

1.2.8 Non-Resident Attribute Header

Non-Resident Attribute Header의 경우 Common Attribute Header 다음으로 나오는 영역은 0x30or0x38 크기 입니다. 해당 Common Attribute Header의 Non-Resident Flag값이 0x01이므로 Attribute Size가 0x50으로 이후에 Offset to RunList값이 0x40이며, 해당 0x40~0x4F까지 16byte입니다.

 

저장 구조

0x00~0x0F: Common Header(16Byte)

0x10~0x3F : Extended Header(48byte)

0x40~0x4F: RunList(16byte)



16 + 48 + 16 = 80byte



Name Offset Description
Start VCN of the runlist 0x10~0x17 속성 내용이 담긴 런리스트 시작 값입니다.
End VCN of the runlist 0x18~0x1F 속성 내용이 담긴 런리스트 끝 값입니다.
Offset to runlist 0x20~0x21 속성 내부의 런리스트 시작 위치입니다.
COmpression unit size 0x22~0x23 압축 속성일 경우 압축 단위 입니다.
Unused 0x24~0x27 사용하지 않는 부분 입니다.
Allocated size of attribute content 0x28~0x2F 속성 내용에 할당된 클러스트 크기 입니다.
Real size of attribute content 0x30~0x37 속성 내용의 실제 크기 입니다.
initialized size of attribute content 0x38~0x3F 속성 내용의 초기화된 크기 입니다.
Attribute Name 0x40~0x47 속성 이름이 있는 경우 속성이름 없으면 바로 속성 내용으로 됩니다.

 

1.2.9 Cluster Runs

Cluster Run : 데이터 저장 시에 클러스터가 연속/비연속 적으로 할당된 경우에는 할당된 크러스터 주소와 크기 정보를 포함하는 데이터 입니다.

RunList: Cluster Run의 데이터를 효율적으로 표기하는 방식입니다.

NTFS는 RunList를 참조해서 Cluster Run데이터를 추출하고, 추출된 Cluster Run 데이터로 할당된 클러스터에 접근합니다. Cluster Run 시작 주소는 Attribute 시작주소 + Offset of RunList 입니다.

 

이와 바탕으로 구조를 만들면..

이렇게 Data Run의 첫바이트 기준으로 Data Run Length, Data Run Offset의 길이가 정해집니다.

Logical Cluster Number : 볼륨의 첫 번째 클러스터 부터 순차적 번호 = Data Run Length

Virtual Cluster Number  : 파일의 첫 번째 클러스터 부터 순차적 번호 = Data Run Length

 

첫 바이트가 위의 데이터 처럼 0x33이라 한다면 Data Run Length 길이는 3byte, Data Run Offset 도 3byte입니다.

 

 

반응형

'Field > Digital Forensic' 카테고리의 다른 글

[Forensic] Registry  (0) 2025.10.01
[Forensic] Windows Artifact  (0) 2025.09.29
[Forensic] FAT32 Analysis  (0) 2025.09.19
[Forensic] MBR, VBR  (0) 2025.06.18
[Forensic] 파일 시스템  (1) 2025.06.12
myeongsang
@myeongsang :: myeongsang

myeongsang's security

공감하셨다면 ❤️ 구독도 환영합니다! 🤗

목차