[Digital Forensic] NTFS 파일 시스템 (2)
(7) B-tree
-
NTFS에서는 앞에서 언급했듯이 b-tree를 사용
-
NTFS는 많은 상황에서 인덱스 구조체를 사용
-
NTFS 인덱스는 정렬된 순서로 저장된 속성들의 모음을 일컫음
-
인덱스가 제일 흔하게 사용되는 것이 디렉토리인데, $FILE_NAME 속성을 포함하기 때문
-
NTFS에서 인덱스는 이진 트리, b-tree로 정렬
이진 트리는 자료구조론에서 자주 언급되는 개념 중 하나지만, 여기서 언급은 생략하고 b-tree에 대해서만 설명한다.
b-tree는 이진 트리와 유사한 형태이지만, 노드 별로 자식 노드가 2개 이상이다.
b-tree에는 여러 종류와 규칙이 있지만 여기서는 b-tree에 대해서만 설명할 것이며 노드 삽입, 삭제에 대해서 이야기 해보자.
b-tree는 기본적으로 다음과 같은 구조이다.
가칭으로 각 노드에 알파벳 이름을 붙여 놨다.
이제 위 기본 구조를 이용해 삽입, 삭제를 알아보도록 하겠다.
7-1. 삽입
먼저 위 기본 구조에 90이라는 값을 삽입해보자.
90이라는 값을 삽입하려고 시도할 경우 순서는 다음과 같다.
-
값과 가장 가까운 값이 들어있는 노드를 찾음 (위 기본 구조에서 C 노드가 가장 적합)
-
빈 공간이 있다면 빈 공간에서 삽입하고자 하는 값(90)을 삽입
-
만약 삽입하려 하는 노드에서 원래 있던 값(80)과 삽입하려는 값(90) 중 원래 있던 값이 크다면 삽입하려는 값이 원래 있던 값 앞으로 옴
-
현재 삽입하려는 값이 원래 있던 값보다 크므로 자리 이동 없이 원래 있던 값 뒤에 위치함
위 과정을 거치면 다음과 같다.
이번에는 30이란 값을 삽입해보자.
이번의 경우는 노드가 값으로 꽉 차있을 경우 어떻게 삽입이 되는 지를 알아 보는 것이다.
-
값과 가장 가까운 값이 들어있는 노드를 찾음 (위 구조에서 B 노드가 가장 적합)
-
노드에 빈 공간이 없을 경우 해당 노드를 분열하여 새로운 노드 구성
-
노드를 분열한 후 노드에 들어갈 후보 값(10, 20, 30) 중 제일 큰 값을 새로운 노드로 삽입하고, 남은 두 값(10, 20) 중 큰 값을 부모 노드로 삽입
-
마지막으로 남은 값(10)은 원래 노드에 남겨 둠
-
노드 분열로 인해 다른 노드가 변경되어 값들이 꽉 차 있다면 해당 값들을 비교하여 정렬
이제 [그림 3] 구조에 마지막으로 70이라는 값을 삽입해보자.
이 경우는 부모 노드 분열에 대해 알아보는 것이다.
-
값과 가장 가까운 값이 들어있는 노드를 찾음 (위 구조에서 C 노드가 가장 적합)
-
노드가 꽉 차 있다면 노드를 분열하여 새로운 노드를 구성 (이 과정은 30 값을 삽입할 때 과정과 같음)
-
만약 새로운 노드를 구성하는 도중 부모 노드가 꽉 차 있다면 부모 노드도 분열하여 새로운 노드를 구성
-
노드 분열로 인해 다른 노드가 변경되어 값들이 꽉 차 있다면 해당 값들을 비교하여 정렬
2번 과정에서 노드 분열 도중 80 값이 부모 노드에 삽입되지 못하는 상황이다.
이 때도 노드 분열을 하면 되는데, 위 구조에서 보면 새로운 노드를 하나 구성하고 새로운 노드에 20, 50, 80 값 중 제일 큰 값인 80을 삽입하고 나머지 값인 20, 50 값 중 제일 큰 값을 부모 노드로 삽입한다.
그리고 마지막으로 남은 값은 그대로 남겨둔다.
70값을 삽입한 경우는 다음과 같다.
삽입은 위와 같은 규칙으로 계속 노드를 생성해 나가면 된다.
7-2. 삭제
다음과 같은 구조에 b-tree가 있다고 가정하여 하나씩 살펴보자.
[그림 5] 구조에서 50 값을 삭제하면 다음과 같은 구조가 된다.
이번에는 [그림 6] 구조에서 40 값을 삭제해보자.
-
삭제하려는 값을 삭제 (위 구조의 경우 노드가 비어 버림)
-
노드에 아무런 값도 없다면 부모 노드에서 큰 값이 빈 노드로 내려와 노드를 채우고, 오른쪽 노드에서 작은 값이 부모 노드로 올라감
-
위 구조의 경우 A 노드에서 70 값이 C 노드로 오게 되며, D 노드에서 작은 값인 80이 부모 노드로 가게 됨
이번에는 90 값을 삭제해 보자.
-
삭제하려는 값을 삭제 (위 구조의 경우 노드가 비어 버림)
-
노드에 아무런 값도 없다면 부모 노드에서 큰 값이 빈 노드로 내려와 노드를 채우고, 오른쪽 노드에서 작은 값이 부모 노드로 올라감 (하지만 오른쪽 노드가 없음)
-
오른쪽 노드가 없다면 빈 노드를 삭제하고, 빈 노드가 삭제된 구조에서 오른쪽 노드로 부모 노드 값 중 제일 큰 값이 내려옴
-
D 노드가 삭제되고 삭제된 구조에서 오른쪽 노드인 C 노드로 부모 노드 값 중 제일 큰 80 값이 내려오게 됨
삭제의 경우 노드 생성이 없기 때문에 계속 위와 같은 규칙으로 노드를 삭제해 나가면 된다.
(8) 인덱스 엔트리
NTFS에서 b-tree를 사용한다고 위에서 언급 하였는데, 해당 트리에서는 노드에 값을 저장하기 위해서 '인덱스 엔트리(Index Entry)'라는 데이터 구조체를 사용한다.
-
인덱스 엔트리는 많은 타입들을 가질 수 있으며, 모두 표준 헤더 필드를 사용
-
인덱스 엔트리는 노드의 구성원이며, 비어 있는 인덱스 엔트리는 노드의 마지막을 뜻함
인덱스 엔트리의 구조는 다음 그림과 같이 매우 단순하다.
인덱스 엔트리를 구성원으로 가지고 있는 노드들은 MFT 엔트리 속성 두 개에 따라 저장 방식이 달라진다.
만약 속성이 $INDEX_ROOT 속성이라면 항상 거주 속성을 가져 노드는 한 개만 MFT 엔트리에 저장된다.
만약 노드가 여러 개라면 $INDEX_ALLOCATION 속성이 할당되는 데 이 속성은 비거주 속성이다.
이 속성의 내용은 하나 또는 그 이상의 인덱스 레코드를 포함하는 버퍼(클러스터)인데, 인덱스 레코드는 인덱스 엔트리의 집합이다.
인덱스 레코드의 크기는 4096byte이며, 또 인덱스 레코드는 인덱스 엔트리들의 목록을 포함하고 있다.
인덱스 레코드의 주소는 0으로 시작한다.
[그림 10]을 보면 인덱스 레코드에 할당 되지 않은 영역들이 있는데 이 영역들은 할당이 가능한 상태이다.
인덱스 레코드 할당 상태는 $BITMAP 속성에서 관리하는데, 새로운 노드를 트리에 할당하려고 할 때 $BITMAP 속성은 사용 가능한 인덱스 레코드를 찾게 된다.
인덱스 엔트리에는 자식 노드가 있는지를 판별하게 도와주는 플래그 값이 포함되어 있다.
자식 노드가 있다면 자식 노드의 인덱스 레코드 주소가 부모 인덱스 엔트리에 포함된다.
(9) 메타데이터
-
NTFS에서 파일 시스템을 전반적으로 설명하는 데이터를 포함하는 파일을 메타데이터 파일이라고 함
-
NTFS에서 모든 것이 파일로 할당되므로 메타데이터 파일은 파일 시스템 전체를 데이터 영역으로 보고 어디든지 위치할 수 있음 (부트코드는 예외이며, 정해진 곳에만 위치)
-
메타데이터 파일들의 흥미로운 점을 일반 파일들과 비슷한 구조의 타임 스탬프를 가짐
-
메타데이터 파일이 가지고 있는 타임 스탬프는 파일이 생성될 때 설정되기 때문에 분석 시에 유용하게 사용할 수 있음
9-1. $MFT
-
메타데이터 파일 중에서도 가장 중요한 파일
-
모든 파일과 디렉토리의 엔트리를 가짐
-
MFT의 레이아웃은 $MFT 파일을 분석함으로써 파악 가능
-
MFT의 첫 번째 엔트리이며, 해당 파일의 $DATA 속성의 내용은 MFT에 의해 사용되는 클러스터들을 포함
-
파일 시스템이 시작할 때 되도록 크기가 작은 상태에서 시작되며, 파일들이나 디렉토리가 생성되면 그 크기가 커짐
-
하지만 한 번 생성된 엔트리는 지워지지 않아 크기가 줄어들지 않음
9-2. $MFTMirr
-
해당 파일은 MFT 엔트리들 중 중요한 엔트리들을 복사해 놓은 백업본
-
일반 파일을 찾으려면 부트 섹터와 $MFT를 참조해야 하는데 부트 섹터나 $MFT가 손상되게 되면 일반 파일을 찾을 수 없게 되므로 이럴 때 백업본이 필요함
-
MFT의 두 번째 엔트리이며, 해당 파일의 $DATA 속성은 파일 시스템 중간에 있는 클러스터를 할당 받아, 적어도 아래의 엔트리들을 복사하여 저장
복사하여 저장하는 엔트리들은 다음과 같다.
-
$MFT
-
$MFTMirr
-
$LogFile
-
$Volume
9-3. $Boot
-
파일 시스템의 부트 섹터를 포함하는 파일
-
MFT의 여덟 번째 엔트리
-
해당 파일은 고정된 위치를 갖는 파일로, 이유는 해당 파일의 $DATA 속성 내용이 시스템 부팅에 필요하기 때문
-
$DATA 속성은 항상 파일 시스템 첫 번째 섹터에 위치
-
부트 섹터는 각 클러스터의 크기, 파일 시스템의 섹터 수, MFT 시작 클러스터의 주소 등을 저장
-
$DATA 속성에서 부트 섹터를 위해 할당된 섹터를 제외한 나머지 섹터들은 부트 코드를 위해 할당 됨
$DATA 속성에는 기본적으로 16개의 섹터가 할당되지만, 실제로 부트 섹터를 8개의 섹터에만 할당 된다.
부트 코드는 간단하게 파일 시스템 부팅을 위해 사용되며, 운영체제를 적재하기 위해 사용되는 파일들의 위치를 찾아준다.
부트 섹터도 백업본이 존재하는데, 백업본은 볼륨 마지막 섹터나 중간 섹터에 존재한다.
9-4. $Volume
-
해당 파일은 볼륨 레이블과는 다른 버전 정보를 포함하며, MFT의 네 번째 엔트리
-
해당 파일에는 다른 메타데이터 파일에는 없는 고유 속성 2개가 존재
-
해당 파일에는 $DATA 속성이 존재하지만, 크기는 0
고유 속성 2개는 다음과 같다.
-
$VOLUME_NAME : 볼륨의 유니코드 이름 저장
-
$VOLUME_INFORMATION : NTFS 버전과 오류 상태 저장
9-5. $AttrDef
-
각 속성 타입을 위해 이름과 타입의 식별자 정보를 포함
-
MFT 다섯 번째 엔트리
9-6. $Bitmap
-
해당 파일은 클러스터의 할당 상태를 결정하는 메타데이터 파일
-
MFT 일곱 번째 엔트리
-
해당 파일 $DATA 속성은 파일 시스템 내 모든 클러스터와 매칭되는 1개의 비트를 가지고 있음
-
비트가 1로 설정되면 해당 클러스터는 할당 상태인 것을 의미
-
비트가 0으로 설정되면 해당 클러스터넌 비할당 상태인 것을 의미
9-7. $BadClus
-
해당 파일은 불량 클러스터를 관리하는 메타데이터 파일
-
MFT 아홉 번째 엔트리
-
해당 파일에는 $DATA 속성이 2개 존재
-
하나는 기본적인 $DATA 속성으로 크기가 0
-
나머지 하나는 $Bad라고 불리는데 sparse 파일이며, 클러스터가 손상되었다고 보고 될 시 클러스터 주소가 해당 속성에 포함 됨
-
처음에 $Bad 라고 불리는 이 $DATA 속성에는 아무것도 포함 되어 있지 않음
9-8. $Secure
-
해당 파일은 $SECURITY_DESCRIPTOR 속성에서 사용하는 파일
-
보안 식별자를 저장하는 용도로 사용
-
보안 식별자는 파일이나 디렉토리에 접근 제어 정책을 정의할 때 사용
-
해당 파일은 MFT 엔트리 열 번째에 해당
-
NTFS 버전 3.0 이상에서만 사용
NTFS의 모든 파일이나 디렉토리에 할당 되는 $STANDARD_INFORMATION 속성에는 SID(Security ID)라는 하나의 식별자를 포함하는데, 이 ID가 $Secure 파일에 인덱스로 사용된다. (SID와 윈도우에서 사용자에게 할당하는 SID는 다름)
해당 파일은 $SDH, $SII 인덱스와 이름이 $SDS인 $DATA 속성을 포함한다.
$DATA는 실제 SID(Security ID)를 포함하고, 두 인덱스는 SID를 참조하기 위해 사용된다.
$SII 인덱스는 $STANDARD_INFORMATION 속성에 포함되는 SID(Security ID)로 정렬되는데 $Secure 파일의 SID를 확인할 때 $Secure 파일의 SID의 위치를 확인하기 위해 사용된다.
$SDH 인덱스는 SID(Security ID)의 해쉬에 의해 정렬된다.
만약 해쉬가 없다면 두 인덱스에 의해 SID가 생성된다.
(10) 속성
10-1. STANDARD_INFORMATION
-
모든 파일과 디렉토리에 존재하는 속성
-
포함하는 데이터로는 타임스탬프 세트 및 소유권, 보안, 할당 정책이 있음
-
해당 속성 타입 ID는 16이며 윈도우 별로 고정된 크기를 가짐
-
해당 속성이 가지고 있는 타임스탬프는 총 4개의 시간 값을 가지고 있음
4개의 시간 값은 다음과 같다.
-
생성 시간 : 파일이 생성된 시간
-
수정 시간 : $DATA 또는 $INDEX 속성 내용이 마지막으로 수정된 시간
-
MFT 수정 시간 : 파일 메타데이터가 마지막으로 수정된 시간
-
접근 시간 : 파일의 내용에 마지막으로 접근한 시간
또한 이 속성은 읽기 전용, 시스템, 아카이브 등의 일반적인 속성을 위해 플래그 값을 하나 가진다.
이 플래그 값은 읽기 전용 등의 속성 뿐만 아니라 압축, sparse, 암호화 등의 속성 또한 설명해준다.
하지만 이 플래그는 해당 엔트리가 파일을 위한 것인지, 디렉토리를 위한 것인지에 대한 구분은 해주지 않는다.
NTFS에서의 타임스탬프는 1970년 1월 1일 UTC를 기준으로 현재 시간과의 차이를 100나노로 표현한 64bit 값이다.
10-2. $FILE_NAME
-
모든 파일과 디렉토리는 해당 속성을 필히 가짐
-
해당 속성의 타입 ID는 48이고, 크기는 기본적으로 66byte이지만, 파일 이름의 길이에 따라 유동적
-
해당 속성은 UTF-16 유니코드로 인코딩 된 파일 이름을 포함
-
해당 속성은 부모 엔트리의 주소를 포함하며, 이 정보는 MFT 엔트리 전체의 경로를 파악하는데 유용하게 쓰임
이 속성은 $STANDARD_INFORMATION 속성처럼 타임스탬프 값을 포함하고 있다.
하지만 윈도우는 $FILE_NAME 속성의 타임스탬프 값을 $STANDARD_INFORMATION 속성처럼 자주 업데이트하지 않고 아래와 같은 경우에만 $FILE_NAME 속성의 타임스탬프 값을 업데이트한다.
-
파일 생성
-
파일 이동
-
파일 이름 변경
해당 속성은 $STANDARD_INFORMATION 속성과 같이 읽기 전용, 시스템, 아카이브, 압축, 암호화 등을 구분하기 위한 플래그 값을 포함하고 있다.
10-3. $DATA
-
해당 속성은 데이터의 내용을 저장하기 위해 사용
-
특별히 정의된 값이나 레이아웃을 가지고 있지 않음
-
속성 타입 ID는 128이며, 크기는 내용에 따라 유동적
-
해당 속성은 파일이나 디렉토리의 MFT 엔트리에 기본적으로 할당되기는 하지만, 직접적인 이름은 할당되지 않음
-
이렇게 기본적으로 MFT 엔트리에 할당되는 $DATA 속성은 이름이 존재하지 않아도 되지만, 추가적으로 할당되는 $DATA 속성은 반드시 이름이 있어야 함
이러한 추가 $DATA는 어떤 데이터를 숨길 수도 있으며, 디렉토리의 목록을 확인할 때 보이지 않는다.
대부분의 포렌식 도구들은 ADS(Alternate Data Streams)라고 불리는 추가적인 $DATA 속성들을 보여준다.
$DATA 속성은 비인가된 접근을 막기 위해 암호화하거나, 공간 절약을 위하여 압축할 수 있다.
이러한 선택 사항은 속성 헤더의 플래그를 설정함으로써 사용할 수 있다.
10-4. $ATTRIBUTE_LIST
-
해당 속성은 파일이나 디렉토리의 모든 속성들을 저장하기 위해 MFT 엔트리가 하나 이상일 때 사용되는 속성
-
하나의 파일이나 디렉토리에는 65536개 속성이 올 수가 있지만 MFT 엔트리 하나에 이 속성들을 모두 저장한다는 것은 불가능
-
그렇기 때문에 비기준 MFT 엔트리를 생성한 후 기준 MFT 엔트리에 해당 속성을 할당함
-
해당 속성의 내용은 기준 MFT 엔트리에 저장하지 못한 속성 타입 ID와 저장하지 못한 속성이 포함된 비기준 엔트리의 주소로 이루어짐
(11) 타임스탬프
기본적으로 시간 정보는 파일의 속성 창에서 확인할 수 있고, 시간 값들은 $STANDARD_INFORMATION에 포함되어 있는 값들이다.
NTFS에서 시간 값이 업데이트 되는 조건은 FAT와 유사한데 그 조건은 다음과 같다.
-
파일을 생성하거나 복사하면 생성 시간은 현재 시간으로 업데이트 됨
-
마지막 수정 시간은 $DATA, $INDEX_ROOT, $INDEX_ALLOCATION 속성 값이 수정될 때 업데이트 됨
-
MFT 수정 시간은 어떤 속성이 수정되어도 업데이트 되며, 어떠한 파일을 Open한 것만으로도 업데이트 됨
-
마지막 접근 시간은 메타데이터 또는 내용을 확인했을 때 업데이트 됨
참고로 우리가 파일이나 디렉토리의 속성 정보에서 보는 타임스탬프 값은 $STANDART_INFORMATION 속성의 값이다.
(12) 디렉토리 인덱스
-
NTFS에서는 앞에서 언급한 인덱스를 이용하여 디렉토리 내용을 구성
-
인덱스 엔트리는 노드 값을 포함하며, $INDEX_ROOT, $INDEX_ALLOCATION 속성에 저장 됨
-
$INDEX_ROOT 속성에 저장된 값은 항상 트리 구조에서 루트 노드 값에 해당
-
$INDEX_ALLOCATION 속성에 저장된 인덱스 엔트리들은 트리 구조에서 리프 노드에 해당
그리고 $BITMAP 속성은 인덱스 레코드들의 할당 상태를 관리하는데 사용된다.
NTFS의 디렉토리들은 기본적으로 헤더, $STANDART_INFORMATION, $FILE_NAME 속성을 가진 MFT 엔트리를 가지고 있다.
또 디렉토리 인덱스의 엔트리들은 $FILE_NAME과 파일 참조 주소를 포함하고 있다.
$FILE_NAME 속성은 파일 이름, 비주류 정보, 크기 등의 정보를 포함하는데 윈도우에서는 이 값들 중 비주류 정보와 크기 정보를 업데이트한다.
이러한 이유로 이 정보들은 정확성을 가지고 있다.
NTFS 디렉토리 기본 계층 구조는 다음과 같다.
12-1. 루트 디렉토리
-
파일 시스템 전체 경로에서 어떠한 파일을 찾으려고 할 때 가장 먼저 파악해야 할 것이 루트 디렉토리
-
NTFS에서는 루트 디렉토리가 항상 MFT에서 여섯 번째 엔트리에 위치
-
해당 엔트리는 기본적으로 $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP 속성을 가짐
-
모든 메타데이터 파일이 루트 디렉토리에 위치하며, 메타데이터 파일은 숨김 속성으로 인해 사용자에게는 보이지 않음
12-2. 파일과 디렉토리의 연결
-
NTFS에서는 하드 링크를 이용해 파일이 하나 이상의 이름을 가지도록 함
-
해당 하드 링크 부모 디렉토리 인덱스에 할당되며 원본과 동일한 MFT 엔트리를 가리킴
-
MFT 헤더에는 링크 카운트라는 플래그가 있는데 해당 플래그는 하드 링크가 생성될 때마다 값이 하나씩 증가
-
하드 링크는 사용자가 파일을 삭제하여도 파일이 디스크 상에 남아 있다면 계속 그 파일을 가리키고 있어 파일 복구 가능 여부를 판단하게 도와줌
-
MFT 엔트리에는 하드 링크를 위한 $FILE_NAME 속성이 존재
-
NTFS 3.0 이싱 버전에서는 재파싱 기능을 지원
재파싱 기능은 파일, 디렉토리, 볼륨들을 서로 연결해주는 기능으로, 이 기능은 디렉토리나 파일로 존재한다.
그 내용으로는 어떠한 것들을 연결하고 있는지에 대한 정보이다.
재파싱 기능에는 여러 종류가 있는데 그 종류는 다음과 같다.
-
심볼릭 링크 : 파일과 파일 간의 연결
-
Junction : 디렉토리와 디렉토리 간의 연결
-
마운트 : 디렉토리와 볼륨 간의 연결
재파싱 기능은 파일이나 디렉토리로서 존재한다고 위에서 언급하였는데, 재파싱 기능은 $STANDARD_INFORMATION과 $FILE_NAME, $REPARSE_POINT 속성을 가진다.
$REPARSE_POINT 속성은 연결 대상 파일이나 디렉토리 위치 정보를 포함하는 속성이다.
NTFS는 재파싱 기능의 경로를 기록으로 남기기도 하는데 이 기록은 \$Extend\$Reparse 파일 시스템 메타데이터 파일의 인덱스를 이용한다.
또 루트 디렉토리의 $DATA 속성에 마운트 경로를 기록하기도 하는데 이 속성은 $MountMgrRemoteDatabase라는 이름을 가진 $DATA 속성으로 마운트 대상 볼륨 목록을 포함한다.
(13) 오브젝트 식별자
-
NTFS 3.0 이상 버전에서는 지금까지 설명한 디렉토리/파일 이름, MFT 엔트리 주소를 제외한 다른 주소 지정 방법을 제공
-
운영체제는 각 파일이나 디렉토리에 있는 128bit 고유한 오브젝트 식별자를 할당하여 파일의 이동이나 이름 변경 시에 해당 오브젝트 식별자를 이용하여 파일을 참조
-
오브젝트 식별자가 할당되면 해당 MFT 엔트리에는 $OBJECT_ID 속성이 할당
-
해당 속성에는 원본 도메인과 해당 파일이나 디렉토리가 생성되었던 볼륨 정보를 저장
# Reference
'Digital Forensics > Forensic Theory' 카테고리의 다른 글
[Digital Forensic] NTFS 파일 시스템 (4) (0) | 2020.04.01 |
---|---|
[Digital Forensic] NTFS 파일 시스템 (3) (0) | 2020.04.01 |
[Digital Forensic] NTFS 파일 시스템 (1) (0) | 2020.03.31 |
[Digital Forensic] FAT 파일 시스템 (2) (0) | 2020.03.28 |
[Digital Forensic] FAT 파일 시스템 (1) (0) | 2020.03.28 |