4-3.3) MFT Entry의 주요 속성1($SI,$FILE,$DATA)
Last updated
Last updated
아래 실습은 NTFS 가상디스크를 만들어서 분석하였습니다.
실습을 직접 따라 해보고 싶으신 경우 NTFS 분석 처음부터 따라오시는 것을 추천 드립니다. > 4-3) NTFS 기초 분석
MFT Entry 안에 있는 속성 Attribute 에 대해서 알아봅시다. 먼저 속성의 종류를 한번 살펴 봅시다.
이 속성 중에서도 제일 만만한 해보이는 3가지만 살펴보도록 합시다. $STANDARD_INFORMATION, $FILE_NAME, $DATA 나머지는 따로 개별로 속성에 대해서 친해지기, 놀아보기를 해봅시다.
모든 파일과 디렉토리에 존재하는 속성으로 이 속성은 파일 생성시간과 날짜, 파일의 소유자와 보안, 할당량에 관한 정보를 담고 있습니다.
먼저 Attribute의 헤더의 경우 2가지가 있습니다. 헤더의 종류를 결정하는 값은 Non-Resident Flag로 우선 우리가 분석할 대상은 0 으로 Resident Attribute Header 정보를 가지게 됩니다. 한번 살펴보도록 하겠습니다.
Activate Disk Editor에서 분석해주고 있지만 우리도 실제로 계산을 해보도록 합시다. - Attribute Type ID : 10 00 00 00 (리틀엔디안) -> 00 00 00 10(16진수) => 16(10진수) > 10 : $STANDARD_INFORMATION 을 나타내는 값 - Length of Attribute : 60 00 00 00 -> 00 00 00 60 (16진수) => 96 bytes (헤더 포함 속성 길이) - Non Resident Flag : 00 (Resident Attribute Header) - Length of Name : 00 (이름의 길이 - 속성 이름 없음) - Offset to Name : 18 00 -> 00 18 => 24 (이름이 없어서 실제로 사용 안됨) - Flag : 00 00 -> 0000 0000 (2진수) 아무런 옵션이 없는 상태 > 밑에서 Flag의 역할과 동일한 File Attribute에서 확인 가능 - Attribute ID : 00 00 - Size of Content = 48 00 00 00 -> 00 00 00 48 => 72 bytes (헤더 속성 내용 길이) - Offset of Content : 18 00 -> 00 18 => 24 (속성 내용 시작 Offset) - Indexing Flag : 00 (인덱스 플래그 설정 안됨 - 검색에서 사용 안 된다는 뜻) - Padding : 00 (자리 맞추기 용 빈 공간) 정리하면 속성 Type ID로 $STANDARD_INFORMATION 인 걸 알 수 있고 Resident Attribute 이며, 속성 이름은 따로 없다. 속성의 내용은 24번째 속성 헤더 기준 오프셋부터 시작되며, 실제 내용은 72 bytes, 헤더부터 전체는 96bytes 이다.
$STANDARD_INFORMATION의 데이터 내용을 살펴봅시다.
중요한 것들을 분석하여 봅시다. 우선 아래 시간 값이 모두 동일합니다. - Create Time (파일/디렉토리 생성 시간) - File Alter Time (파일/디렉토리 수정 시간) - MFT Modified Time (MFT Entry 마지막수정된 시간) - File access Time (파일에 마지막으로 접근된 시간) AF C6 1F 80 05 B0 DA 01 -> 01 DA B0 05 80 1F C6 AF (16진수) 64bit NTFS 시간 값 계산의 경우 1601년 1월 1일 자정(UTC)을 기준으로 100나노초(0.1 마이크로초) 단위로 측정하고 있다. 즉, 01 DA B0 05 80 1F C6 AF 을 10진수 변환 후 1601년 1월 1일 00:00:00부터 0.0000001초(100 나노초)가 지날 때 마다 1씩 증가하는 것이다. 01 DA B0 05 80 1F C6 AF -> 133,612,676,631,742,127 로 1601년 1월 1일 + ( 133,612,676,631,742,127 X 100나노초)가 지난 상태인 것이다. python 으로 계산을 해보면 2024-05-27 07:14:23 인 것을 알 수 있습니다.
File Attributes 값을 분석해봅시다. File Attributes : 06 00 00 00 -> 00 00 00 06 => 2진수 변환 00000000 00000000 00000000 00000110 -> 결론적으로 1, 2 비트가 1로설정 Hidden 숨김이며, 시스템 파일에 해당합니다. <비트 옵션, 우측부터 n번째 비트> *속성 헤더의 Flag 도 동일한 방법 사용 비트 0 (READONLY) 읽기 전용: 0 비트 1 (HIDDEN) 숨김: 1 비트 2 (SYSTEM) 시스템 : 1 비트 3 (VOLUME_LABEL) 볼륨레이블: 0 비트 4 (DIRECTORY) 폴더: 0 비트 5 (ARCHIVE) 아카이브: 0 / 파일이 백업 또는 아카이브 작업의 대상 (주로 백업SW용) 비트 6 (DEVICE) 미사용: 0 비트 7 (NORMAL) 일반: 0 비트 8 (TEMPORARY) 임시: 0 비트 9 (SPARSE_FILE) Sparse : 0 / 실제 데이터가 저장된 영역만 디스크 공간을 차지 비트 10 (REPARSE_POINT) : 0 / 파일이나 디렉터리에 추가적인 메타데이터를 첨부 비트 11 (COMPRESSED) 압축: 0 비트 12 (OFFLINE): 0 / 로컬 디스크에 없어서, 외부/원격 저장소에서 가져와야 함 비트 13 (NOT_CONTENT_INDEXED) : 0 / 파일의 내용이 인덱싱 안됨 비트 14 (ENCRYPTED) 암호화 0 비트 15-31: 0 (미사용 비트)
아래 것들은 모두 00 으로 사용하지 않는 파일이네요! - Maximum number of Versions - versions number - Class ID : 일반적인 파일 시스템 운영에서는 사용되지 않습니다. 특정 상황에서 사용. - Owner ID : 보안 식별자(SID)로, 파일 소유자의 SID를 저장합니다. 보안에서는 사용.
Quota Charged 할당된 디스크 공간에 대한 쿼터(옵션) 의 경우 모두 00 아직은 사용하고 있지 않거나 초기화 상태 입니다. 추가 설명을 하자면 NTFS 파일 시스템에서 할당된 디스크 공간에 대한 쿼터(Quota)는 각 사용자별로 디스크 사용량을 제한하고 관리하는 데 중요한 역할을 합니다. 이를 통해 시스템 관리자는 특정 사용자나 그룹이 디스크 공간을 과도하게 사용하는 것을 방지할 수 있습니다 일단 우리는 어떤 파일이지 아직은 잘 모르고, 초기화 되어 있는 상태구나.. 하고 넘어가도록 합시다.
USN Journal ID 해당 파일의 마지막 Update Sequence Number를 담고 있으며 이 항목의 값은 $UsnJrnl 파일을 조사할 때 사용됩니다. 만약 이 항목이 0이면 USN 저널링 기능은 비활성화 된 것입니다. -> 일단 우리가 분석 할 첫번째 MFT Entry 는 0으로 비활성화 되어 있는것 같습니다. 그런데.. 저널링이 뭘까..? 이 부분은 추후에 $LOGFILE 과 함께 따로 상세분석을 해보도록 합시다. (파일 흔적 추적용이라고 생각하면 됩니다. 포렌식에서는 매우 중요한 부분이겠지요!)
정말 길었지만 드디어 우리는 우리가 분석하고 있는 MFT 엔트리의 파일명을 확인할 수 있습니다. 우선 분석 후에 정리해 봅시다.
$ FILE_NAME 속성은 파일이나 디렉토리의 이름을 담는 속성이며 빠른 파일 검색을 위해 사용되는 인덱스에도 존재합니다.
위에서 $STANDARD_INFORMATION 헤더와 분석한 것과 동일하게 할 수 있지만 이번엔 바로 Activate Disk Editor 를 이용하여 헤더 부분을 살펴봅시다.
Attribute Type ID가 30(16진수), Length 가 104 bytes 인 것 말고는 다른게 없습니다.
$FILE_NAME 속성에 대해서 알아봅시다.
위 내용을 다시 한번 살펴보도록 합시다. - Parent Directory File record number : 05 00 00 00 00 00 (리틀엔디안) -> 05 => 5 (10진수) - Parent Directory sequence number : 05 00 -> Directory File record number + Directory sequence number 의 경우 MFT Header에서도 나왔던 File Reference Address라고도 하며, MFT Entry 위치를 나타내는 것입니다. 즉, 이 파일의 상위 디렉토리가 5번 MFT Entry에 있다고 하네요! MFT Entry 분석 후 한번 무엇이 있는지 5번 MFT Entry에 무엇이 있는지 살펴봅시다.
시간정보를 살펴봅시다.
- Creation Time - Modified Time - MFT Modified Time - Access Time 모두 AF C6 1F 80 05 B0 DA 01 -> 01 DA B0 05 80 1F C6 AF => 133612676631742127 2024-05-27 07:14:23.174213+00:00 * 아래 소스 실습 시 주의사항 : time_in_100ns = 변환한 숫자만 들어가야 함 ( , 쉼표 들어가면 안됨)
파일 크기 관련 - 파일 할당 크기 : 00 04 00 00 00 00 00 00 -> 00 ~ 40 00 (16진수) => 16,384 Bytes - 파일 실제 크기 : 00 04 00 00 00 00 00 00 -> 00 ~ 40 00 (16진수) => 16,384 Bytes
$FILE_NAME
속성은 파일의 이름과 메타 데이터 정보를 포함하고 있지만, 파일의 실제 데이터 크기를 나타내지는 않습니다. (실제는 다음 속성인 $DATA 크기가 정확)
다른 것을 분석해보면 $FILE_NAME 속성에서는 이 값이 크지 않는 것을 알 수 있습니다. 다만 $MFT의 경우 다양한 곳에 메타데이터(속성 등..)가 있기 때문에 비교적 큰 용량이 표시됩니다. 모든 속성의 크기를 파악해야하기 때문에 굳이 여기서는 확인해보지 않도록 하겠습니다. 추후에 따로 분석해봅시다.
이름 길이 관련 - 이름 길이 : 04 -> 파일 명 길이 (1글자당 2YTES로 총 8바이트 사용 / U16 인코딩) - 이름 형식( Name Space): 03 00 - POSIX (Unix 규칙, 대소문자 구분) / 01 - Win32 (대소문자 구분 안함) 02 - DOS (짧은 이름 사용 "FILENA~1.TXT" 같은) / 03 - WIN32 & DOS (대소문자 구분 안함)
파일이름 이름 : 24 00 4D 00 46 00 54 00 (UTF-16 인코딩) -> $MFT
즉, 우리가 분석하던 가장 처음 MFT Entry 는 $MFT 파일이 였습니다. 그렇다면 이제 $MFT 의 데이터 영역을 살펴보도록 합시다. 예상해보면 FAT32에서는 해당 파일의 시작 클러스터 번호를 가리켰습니다. 우리가 지금 보고 있는 이 클러스터 번호를 가리키고 있지 않을까요?
$DATA 속성은 해당 파일이 위치하는 클러스터를 가리킵니다. 어떻게 가리키고 있는지 살펴봅시다.
먼저 $DATA의 속성 헤더를 살펴봅시다. 기존과 다르게 속성 헤더 값 중에 Non-resident 값이 1인 것을 확인할 수 있습니다. 이렇게 되면 속성의 헤더 구조가 약간 다르게 변경 됩니다.
변경된 헤더 구조를 살펴봅시다.
위에서 살펴본 Resident Attribute Header와 비교해서 16 Bytes까진 동일하고 추가된 것이 있는 것을 알 수 있습니다.
먼저 기본 헤더를 살펴봅시다. - Attribute Type ID : 80 00 00 00 (리틀엔디안) -> 00 00 00 80 (16진수) =>128 (10진수) - Length of Attribute : 48 00 00 00 -> 00 00 00 48 (16진수) => 72 (10진수) - Non-Resident Flag : 01 (Non-Resident 타입 속성) - Length of Name : 00 속성 이름 길이 - Name offset : 40 (이름이 없어서 의미 없는 값) - Flag : 00 00 (속성 없음 - readonly, hidden 등 해당사항 없음) - Attribute ID = 06 00 -> 00 06 => 6 * 타입 아이디가 80(16진수) 속성 크기가 72 bytes 이네요!
우선 크기 관련 먼저 살펴봅시다. - Allocated Size of Attribute content (속성 데이터가 할당되어 있는 클러스터의 총 크기 Byte 단위) - Actual Size of Attribute Content (실제 데이터 용량 bytes) - Initialized Size of attribute content (파일이 부분적으로 쓰여진 경우, 초기화된 크기는 파일의 일부가 실제 데이터로 채워졌음을 나타냄. 보통은 실제 사이즈와 동일) > 모두 00 00 04 00 00 00 00 00 -> 00 00 00 00 00 04 00 00 (16진수) => 262,144(10진수) bytes 동일한 크기 262,144 Bytes를 갖고 있습니다.
RunList에 대해서 이해 해봅시다. 우선 Offset runlist로 가보도록 합시다. $DATA 헤더 첫부분에서 64번째 오프셋 위치로 이동해봅시다. 사실상 속성의 내용 시작 부분인 것을 확인할 수 있습니다.
해당값은실습하는 환경마다 다를 수 있으나 계산 하는 방법은 동일하니 잘 실습해보도록 합시다. 21 40 55 21 값을 나타내고 있습니다.
앞의 1byte 21은 2진수로 0010 0001 이며 4bit로 연속으로 확보된 클러스터 수의 오프셋 크기와 시작 클러스터 위치의 오프셋 크기를 나타냅니다.
- 클러스터 수 오프셋 1 bytes : 40 (16진수) -> 64 클러스터 - 클러스터 시작위치 2 bytes : 55 21 (리틀엔디안) -> 21 55 (16진수) => 8,533 클러스터 시작위치 ※ 파일의 마지막 클러스터 = 시작 클러스터 + 전체 클러스터 수 - 1 (시작 클러스터 포함하여 -1) 8,533 + 64 - 1 = 8,596 클러스터 총 8,533 ~ 8,596 클러스터(64개)를 사용하고 있습니다. 예를 들어 클러스터 수가 256개, 시작 위치가 50번 섹터 라면 12 00 01 32 가 된다. - 클러스터 수 오프셋 2 bytes : 00 01 (리틀엔디안) -> 10 00 => 256 클러스터 수 - 클러스터 시작위치 1 bytes : 32 (16진수) => 50 클러스터 시작 위치 50 + 256 - 1 = 305 클러스터 *50 ~ 305 클러스터 사용 나타내는 runlist
그런데 만약 8,596번 다음 클러스터인 8,597번을 이미 쓰고 있다면?? 이어서 사용할 수 없는 것이죠.. 이미 계산한 걸 사용해보도록 합시다.
50~305번 클러스터를 추가로 사용한다면 어떻게 될까요? > 21 40 55 21 12 00 01 32 00 로 클러스터 런이 이어서 생성되게 됩니다. 클러스터런에 00이 있으면 런리스트의 종료 마커입니다.
파일이 주기적으로 계속 커지게 되면 어떻게 될까? 하나의 파일이 계속 커져 런리스트가 계속 이어지면 다음에 있는 속성값의 위치가 뒤로 밀리게 됩니다. 이렇게 계속 밀리다보면 MFT Entry 의 크기인 2섹터를 넘어가게 되면 어떻게 될까?? 그렇게 된다면 MFT Entry 추가로 할당 하게 되고 $Attribute_List 속성을 추가하여 추가 할당된 MFT Entry를 연결하게 됩니다.
$Attribute_List 속성을 또 분석해야 하나!!?? 또 헤더와 Attribute_List 내용 분석을 해야하나?? 다행히(?) 이번 친해지기에서는 Attribute_List는 분석하지 않고 추후에 MFT Entry 를 다시 상세 분석 할 때 살펴보도록 합시다.
정리 해보자 $MFT 파일의 MFT Entry를 분석해보았다.
$STANDARD_INFORMATION 에서 시간 정보 $FILE_NAME 에서 파일명 , 부모 디렉토리의 File Reference Address $DATA 영역에서 실제 데이터 위치와 파일크기를 확인할 수 있었다. - 파일명 : $MFT - 파일크기 : 16,384 Bytes - 생성시간/수정시간/접근시간 : 2024-05-27 07:14:23.174213+00:00 - 할당된 클러스터 번호 : 8,533 ~ 8,596 (총 64 클러스터) - 시작 물리 섹터 : 파티션 시작 위치 + (클러스터 번호 X 클러스터 당 섹터 수) 128 + (8,533 X 8 ) = 68,392 섹터 (우리가-보고있는 섹터) - 부모 폴더(부모 디렉토리의 File Reference Address) : 5번 MFT Entry
FKT Imager에서도 한번 살펴봅시다... Root 폴더에서 $MFT 를 찾을 수 있고 우리가 MFT Entry 에서 분석한 내용이 모두 표시되고 있습니다. 그런데.. $MFT가 있는 디렉토리가 루트네?
그렇다! 5번 MFT Entry 를 루트 디렉토리의 MFT Entry 입니다. 이렇게 NTFS에서는 고정된 MFT Entry 가 있습니다. 우리는 맨 처음 MFT Entry 를 분석했는데 이게 $MFT 파일의 MFT Entry 였네요! 그만큼 MFT의 복사본도 있을 정도면 중요하지 않을까? 분석 해봐서 알겠지만, $ 사실MFT만 있어도 파일시스템에 무슨 파일이 있고 경로가 어떻게 되는지 파일구조를 모두 파악가능 합니다. 물론 모두 중요하지만 포렌식 분석 시 주요 메타데이터 파일명 정도는 익숙해져 봅시다. (추후에 상세 분석에서 다뤄보면 좋겠네요!)
마지막으로 처음 보는 부분을 살펴봅시다. - First VCN : 00 00 00 00 00 00 00 00 (Run List 시작 VCN) - Last VCN : 3F 00 00 00 00 00 00 00 -> 00 00 00 00 00 00 00 3F (1진수) => 63 (Run List 마지막 VCN) >> 이 뜻은 0 ~ 63 총 64개의 클러스터로 구성되어 있다는 의미 입니다. ※ 즉, Non-Resident의 경우 속성의 내용이 커서 다른 클러스터에 추가로 할당되어 있습니다. 따라서 다른 클러스터에 할당된 정보를 표시하는 것입니다. - Offset runlist : 40 00 -> 00 40 (16진수) => 64 (10진수)로 runlist 가 $DATA 헤더기준으로 64 offset에 위치하고 있습니다. - Compress Unit Size : 00 00 (압축 안함) ※ 클러스터 단위로 압축한 값으로 단위에서 이 저장됩니다. 16클러스터를 압축한 경우 = 16으로 4가 저장