본문 바로가기

Kitri_NCS3기 보안과정/디지털포렌식

170620 NTFS의 구조

FAT와 차이점

변경일지 기능

 파일의 작업중 문제 발생시 롤백의 기능 $log파일이 이 역활을함 .

 암호화 

 EFS(Encrypting FileSystem) ,NTFS 5.0 이후 버전부터 지원 

 디스크 쿼터 기능

 Zip 파일 포맷으로 유명한 LZ77의 변형된 방식 사용. 공간의 효율성이 있지만 성능이 떨어짐

 sparse 파일지원 

 파일의 내용 대부분이 0으로 차있을 경우 해당 파일의 정보만을 담는 파일, 요약본 ? 압축 할때 사용됨 

 데이터 복구기능

 FAT에는 데이터 복구 기능 자체가 없는데 반해 NTFS에는 트랜잭션단위로 작업하다가 문제가 생기면 그 전에 완료된 작업으로 롤백하는 기능이 있다.

 ADS(Alternate Data Stream)

 다중 데이터 스트림 , 하나의 파일에 하나 이상에 데이터를 담을 수 있다는 의미. 




NTFS의 구조 

: 모든데이터가 파일의 형태로 관리된다.

 $MFT 에 모든 데이터에 대한 정보가 관리 되므로 분석하면 모든 데이터를 알아 볼 수있다. 


  

 NTFS

 MBR

MBR에 VBR의 위치

 →

VBR 

VBR에 MFT의 위치

 → 

$MFT 

 

VBR 



 BR/VBR

(Boot Record)

 windows를 부팅시키기 위한 기계어 코드와 NTFS의 여러 설정값들이 있다.

OS가 NTFS를 인식하기 위한 시작점이 됨. 

엄밀히 따지면 NTFS는 부트레코드 영역까지도 파일의 형태로 관리하고 있다고 볼수 있다. 

 MFT

(Maste File Table) 

 볼륨에 존재하는 모든 파일과 디렉토리의 정보를 담고 있는 테이블

MFT도 데이터 영역에 존재하는 파일로 관리됨. -> 볼륨에 어디에 위치 하던 상관없다.

MFT Entry라고 불리는 자료들의 집합으로 이루어져 있다. 

 MFT Entry

  0~15번까지 16개의 MFT Entry는 파일 시스템을 관리하는 중요한 정보드를 담고 있는 시스템 파일용으로 에약되어 있다. 이런 메타데이터 파일은 일반 파일과 구분해서 $MFT , $BadClus 처럼 앞에 $를 붙여 표기한다. 

 데이터 영역

 모든영역이 클러스터로 관리 된다. 4KB로 지정. 



부트레코드 항목 


 

00

01

02 

03 

04 

05 

06 

07 

08 

09 

10 

11 

12 

13 

14 

15 

0x00

 Jump Boot Code

OEM Name 

Byte Per Sector 

Sector per Cluster 

Reserved

Sector Count 

0x10

Unused 

Media 

Unused 

0x20

Unused 

Total Sector

0x30

Start of MFT

 Start of MFTMirr

0x40

MES[각주:1]

Unused 

 IRS[각주:2]

Unused 

 Serial Number

0x50

Unused 

 

 

 

 

 

 

 

 

 

 

 

 




 

Offset

길이(byte) 

설명 

Jump Boot code

0x00

3

Boot Record의 위치 

 OEM Name

0x03 

8

NTFS 

Byte per Sector 

0x0B 

2

섹터당 바이트 수 

Sector per cluster 

0x0D 

1

클러스터 당 섹터 수 

Reserved Sector Count 

0x0E 

2

0 

Media 

0x15 

1

볼륨이 어떤 미디어에 저장되어 있는지 나타냄

(0XF8 - 플로피 디스크를 제외한 모든 장치) 

Total Sector 

0x28 

8

볼륨상에 있는 모든 섹터를 8Byte로 나타낸다. 

 Start of MFT

0x30 

8

MFT의 시작 클러스터의 주소를 나타낸다. (클러스터 값으로 기록) 

 Start of MFTMirr

0x38 

8

MFT 의 복사본인 MFTMirr의 시작주소를 담고있다.( 클러스터 값으로 기록) 

 MFT Entry Size

0x40 

1

MFT Entry의 크기 지정 0xF6 = 2^(-10) = 2^10 = 1024 = 1KB

 Index Record Size

0x44 

1

인덱스 레코드의 크기를 나타냄, Size of MFT Entry와 동일한형식을 취함. 

 Serial Number

0x48 

8

볼륨의 시리얼 번호를 적는다. 고유한 ID 값 

    

 Signature

 0x1FE

2

부트 레코드의 손상 상태 확인. 0xAA55 일 경우 정상  




$BadClus : 볼륨의 에러 관리

$Boot : br 영역 

orphan - 부모 파일과 연결이 끊어진 파일들을 모아놓음.


$Extend > $Usnjrnl = 파일의 변경상태 저장




MFT (Master File Table)

: 볼륨에 존재하는 모든 파일과 디렉토리에 대한 정보를 담고 있는 테이블. MFT의 크기는 가변적이다. 파일이 늘어남에 따라 MFT Entry가 증가하는 만큼 MFT도 증가한다.


MFT Entry 

: 하나의 MFT Entry는 하나의 파일 또는 디렉토리에 대한 정보를 담고 있다. 1KB의 크기 


- 0~15 까지의 16개의 MFT Entry는 메타데이터 파일로 예약되어 있다.

- 메타 데이터파일은 일반파일과 구분짓기 위해 앞에 $를 붙이고 첫글자만 대문자로 쓰고 나머지는 소문자로 쓴다.($MFT는 예외)

- Start Cluster of MFT를 따라가면 있다.=MFT의 시작 위치(클러스터 단위)



MFT Entry의 처음에는 자신의 상태를 담고 있는 42byte 크기의 구조체가 온다. 

42byte 이후에 파일이나 디렉토리의 속성들로 채워진다. 



 

00

01

02 

03 

04 

05 

06 

07 

08 

09 

10 

11 

12 

13 

14 

15 

0x00

 Signature

Offset Fix up Array 

Cnt Fixup Values 

LSN 

0x10

Sequence Value 

Hard Link Cnt 

OFA

Flags 

Used Size of Entry 

Alloc Size of Entry 

0x20

File Reference to Base MFT Entry 

Next Attr ID 

 

 

 

 

 




Name

Offset

길이(byte) 

설명 

 Signature

0x00

4

일반적으로 'FILE' 이라 표기되며 MFT Entry에 문제가 있을 경우 'BAAD'로 표기된다. 

Offset of Fixup Array 

0x04

2

MFT Entry 내에 Fixup 배경ㄹ이 어디에 저장되어있는지 나타냄. (=48)  

 Count of Fixup Values

0x06

2

 Fixup 배열에 저장되어있는 항목의 개수 (=3)

LSN

($LogFile Sequence Number) 

0x08

8

$LogFile에 기록되어 있는 해당 데이터의 수행과 관련된 마지막 트랜잭션의 위치 

Secuence Value 

0x10

2

MFT Entry가 할당되고 해제 될 때마다 값이 증가 

Hard Link Count 

0x12

2

얼마나 많은 디렉토리가 이 파일을 담고있는지 나타냄.

 Offset to First Attribute

0x14

2

각각의 MFT Entry의 첫번재 속성의 오프셋. (=56)

Flags 

0x16

2

해당 MFT Entry의 상태나 속성정보를 담고 있다.

(0x1 - MFT Entry 사용중 / 0x2 - 해당MFT Entry는 디렉토리 / 0x4 or 8 - 분석안됨) 

Used Size of Entry

0x18

4

MFT Entry 에서 실제로 얼마만큼의 Byte를 사용하는지 나타냄, 8배수로 저장 

Allocated Size of MFT Entry 

0x1C

4

MFT Entry의 크기가 몇 Byte나 되는지 나타냄. (=1024) 

 File Reference to BASE MFT Entry

0x20

8

non-Base MFT Entry일 경우 자신의 base MFT Entry의 위치를 나타냄 아니면 0

Next Attribute ID

0x38

2

MFT Entry에 담기는 속성들은 자신만의 ID 를 별도로 가지고 있는데 이 ID는 동일한 MFT Entry내에서만 고유한 ID 값이며 낮은 숫자부터 증가하여 할당된다. 미래에 생성될 속성이 가질 속성 ID의 값을 담고있다. 


Fixup

 : NTFS가 볼륨에 저장하는 데이터가 1개 이상의 섹터를 사용할 경우 각 섹터의 마지막 2Byte의 값을 특정 Signature 값으로 기록하고, 원래의 값은 따로 기억하고 있는것. 해당 섹터의 데이터에 문제가 없는지를 검사할 때 사용한다. 


Offset to Fixup Array = 0x002A

Count of Fixup Values = 4 




속성

 : MFT Entry는 MFT Enrty Header + 속성 으로 이루어져 있다. 파일이나 디렉토리의 정보는 MFT Entry로 관리하고 MFT Entry의 정보는 속성으로 관리한다. 속성에는 파일의 생성시간, 이름, 내용등을 구성하고 있다.


속성의 구성 

 : 속성은 헤더와 내용으로 구성되어 있다. 마지막엔 0xffffffff 라는 End Marker가 붙는다.

 MFT Entry Header

속성 헤더

속성 내용 

속성 헤더  

속성 내용 

속성 헤더  

성 내용  

0xffffffff 


하나의 MFT Entry에 3개의 속성이 있는 모습이다. 속성은 번호가 낮은것부터 순서대로 저장 되어야 한다. 


속성의 타입번호와 종류 

속성값의 표기는 0x10 = 16 , 0x30 = 48 처럼 헥사값으로 표기된다. 


MFT Entry는 1024의 크기를 가지고 있다. 만약 데이터의 크기가 Entry에 들어갈만큼 작지 않다면 Entry를 초과하게 될것이다. 이럴때 속성에는 헤더만 존재하고 속성 내용은 따로 클러스터를 할당받아서 다른곳에 저장하게 되는데 이것을 Resident속성과 non-Resident속성으로 구분해 정의했다.


 Resident 

 non-Resident

데이터의 내용이 MFT Entry안에 포함되는 크기

데이터의 내용이 MFT Entry를 넘어서는 크기


Resident와 non-Resident를 살펴보기 전에 Cluster Runs와 LCN과 VCN이 무엇인지 먼저 알아보자.


Cluster Runs는 non-Resident의 경우처럼 속성의 헤더에서 다른 클러스터에 저장된 데이터의 위치를 알아보기 위해 정의되는 개념이다. 

위치를 알려주기위해 클러스터의 시작 위치와 크기를 정의해 놓았다. 데이터의 위치가 조각조각 나서 분산 되어 있을 경우 

Run data가 많아 지는 단점이 있다. 



Runlist는 처음의 1바이트를 반으로 나누어 각각의 4bit마다 길이와 시작 위치를 정의한다. 


11 30 60의 있는경우 1 1 30 60

21 10 00 01 의 경우 2 1 10 00 01

처음 나오는 바이트는 다음 길이와 시작위치를 나타내는데 사용할 바이트의 갯수이다. 


LCN과 VCN 

 : NTFS에서 사용하는 주소 방식이다. 

 LCN = 볼륨의 첫번째 클러스터 부터 순차적으로 지정되어있는 주소. 볼륨상에서 지정되있는 고유한 주소이다. 

 VCN = 파일의 첫번째 클러스터 부터 순차적으로 지정되어있는 주소. 파일마다 0부터 시작되며 순서대로 증가한다. 


LCN 의 경우 모든 파일을 통틀어 고유한 값이지만 , VCN은 같은 파일 내에서만 고유하다. 


LCN 1355 부터 3의 크기를 가지며 1120부터 4의 크기를 가지는 속성의 내용을 가리키는 구성이 있다고 해보자 

첫번째 Run에서 LCN이 1355, 1356, 1357에 대응되는 VCN은 0,1,2 이며

두번째 Run에서 LCN이 1120,1121,1122,1123 에 대응되는 VCN은 3,4,5,6 이다. 


LCN은 볼륨의 고유값이기 때문에 각 Run마다 값이 연결되는 모습은 보이지 않는다. 그저 그 위치에 저장된 데이터를 가리키는것 뿐이다. 

VCN은 파일단위로 고려되며 0부터 순차적으로 값이 붙는 모습을 보인다. 


LCN은 원래 볼륨상에 존재하는 위치를 나타낸다고 하면 VCN은 파일단위로 부르기 쉽게 다시 이름을 붙이는 것이다. 


이제 Resident와 Non-Resident 속성을 분석해보자


Resident의 구조 


 

00

01

02 

03 

04 

05 

06 

07 

08 

09 

10 

11 

12 

13 

14 

15 

0x00

Attr Type ID

Len of Attr

NRF[각주:3]

LON[각주:4]

Offset to Name 

Flags 

Attr ID 

0x10

Size of Content

OC[각주:5]

IF [각주:6]

Padding

 



Non-Resident의 구조 


 

00

01

02 

03 

04 

05 

06 

07 

08 

09 

10 

11 

12 

13 

14 

15 

0x00

Attr Type ID

Len of Attr

NRF[각주:7]

LON[각주:8]

Offset to Name 

Flags 

Attr ID 

0x10

Starting VCN of Runlist

Ending VCN of Runlist 

 0x20

Offset runlist 

Compress Unit Size 

Padding 

Allocated Size of Attr Content 

0x30 

Actual Size of Attr Content

Initialized Size of Attr Content 

공통 항목 

Name

Offset

길이(byte) 

설명 

 Attribute Type Identifier

0x00

해당 속성이 어떤 속성인지 나타냄 

Length Of Attribute 

0x04

속성의 길이를 나타냄 

Non-Resident Flag 

0x08 

non-Resident 라면 1 아니면 0 

Length of Name 

0x09 

속성의 이름의 길이를 담고 있는 항목 

Offset to Name

0x0A 

속성 이름이 저장되어 있는 위치를 담고 있는 항목 

Flags

0x0C 

속성의 여러 상태를 담고있다. 

(0x0001 - 압축되어있다 / 0x4000 - 암호화 되어있다. / 0x8000 - Sparse속성이다 ) 

Attribute Identifier 

0x0E 

속성이가지는 고유의 값이다 Type ID와 별개로 같은 속성이라도 다름. 


Resident의 항목

Name

Offset

길이(byte) 

설명 

 Size of Content

0x10 

4 

속성의 내용의 크기를 담고 있는 항목 

 Offset to Content

0x14 

2 

속성의 내용이 시작되는 위치를 담고 있는 항목 

indexed Flag 

0x16 

1 

 이 속성이 검색에 사용되는 속성인지 알려주는 항목. 1이면 index정보로 사용

padding  

0x17 

1 

의미 없음  


Non-Resident의 항목

Name

Offset

길이(byte) 

설명 

 Starting VCN of the runlist

0x10

8 

해당 속성이 담고있는 Run list의 시작 VCN 값 

 Ending VCN of the runlist 

0x18

8 

해당 속성이 담고있는 Run list의 마지막 VCN 값 

 Offset to the run list 

0x20

2 

속성내의 Runlist의 위치를 담고있는 값 

 Compression unit size 

0x22

2 

압축의 유무를 나타냄. 예) 압축단위 16 = 2^4 →  4의값이 들어감 

 Padding  

0x24

4 

의미없음 

 Allocated Size of attribute content 

0x28

8 

속성의 데이터가 할당되어 있는 클러스터의 총 크기를 Byte 단위로 담고있다. 

Real Size of attribute content 

0x30

8 

속성 데이터의 실제 크기를 Byte단위로 담고 있다. 

 Initialized Size of attribute content 

 0x38

8 

속성 데이터이 초기화된 크기를 담고 있다. Real size와 동일한 값을 갖는다.  




가상의 vhd 파일을 만들어서 

png 파일을 넣고 그 위치를 찾아가 보았다. 


먼저 mbr에서 vbr의 위치를 찾아갔다 

0x80 = 128섹터를 가리킨다. 



VBR의 MFT의 위치를 가리키는 0x30위치에 0x40000이 있다. 

0x40000 = 262,144

클러스터 단위 이므로 Sector per Cluster 가있는 0x0D 의 위치에 8이 있는걸 확인하고 클러스터 단위로 계산하자 

262144 * 8 +128(NTFS는 MBR이후부터 범위로 계산) = 2097280


NTFS Walker로 MFT Entry를 살펴보았다.

44번째에 png가 위치하고 있으니 MFT의 시작 위치로부터 + 44*2를 해주면 hello.png의 Entry가 나올것이다. 

2를 곱해주느 이유는 한 섹터에 512만큼 할당되어있는데 1섹터는 1024로 설정해놓았기 때문이다. (초기화 값에 따라 상대적인것)


Hello.png Entry = 2097280 + 88 = 2097368


찾아가 보면 속성별로 구조체가 채워져 있는걸 확인 할 수 있다. 


데이터의 위치는 0x80 속성으로 $DATA에 있다. 위에서 확인했듯 속성의 구조체 내에서 0x20에 해당하는 위치에 Runlist의 위치가 있다. 

위치를 따라가면 31 0C E1 FE 03 으로 이루어진 run list 값이 있는데 처음의 바이트를 나누어 각각의 숫자만큼 바이트를 할당받으면, 파일 내용의 위치와 크기를 알 수 있다.


파일의 크기 = 1: 0xC

파일의 위치 = 3 : 0x3FEE1 = 261857 * 8 + 128 = 2094984 섹터에 파일이 데이터가 시작될 것이다. 


hello.png의 데이터의 위치를 찾음.



= 각주 =



  1. MFT Entry Size [본문으로]
  2. Index Record Size [본문으로]
  3. Non-Resident Flag [본문으로]
  4. Length Of Name [본문으로]
  5. Offset to Content [본문으로]
  6. Indexed Flag [본문으로]
  7. Non-Resident Flag [본문으로]
  8. Length Of Name [본문으로]