MFT 분석을 통한 삭제 파일 복구은(는) 무엇을 하나요?
개요
NTFS 마스터 파일 테이블($MFT)은 NTFS 볼륨에 있는 모든 파일과 디렉터리의 중앙 메타데이터 저장소입니다. 각 파일은 최소한 하나의 1024바이트 MFT 레코드로 표현되며, 여기에는 $STANDARD_INFORMATION(타임스탬프, 권한), $FILE_NAME(파일 이름, 상위 디렉터리 참조, 타임스탬프), $DATA(파일 내용 또는 클러스터 실행 포인터) 등의 속성이 포함됩니다. 파일이 삭제되면 해당 MFT 레코드는 비활성(InUse 플래그 해제)으로 표시되지만, 새 파일이 해당 항목을 재할당할 때까지 메타데이터는 유지됩니다. 이러한 지속성 덕분에 MFT 분석은 삭제된 파일 증거 복구, 파일 시스템 타임라인 재구성, 타임스톰핑과 같은 안티포렌식 활동 탐지를 위한 주요 기술로 사용됩니다.
사용 시기
- 삭제된 파일 복구를 위해 MFT 분석이 필요한 보안 사고를 조사할 때
- 이 도메인에 대한 탐지 규칙 또는 위협 헌팅 쿼리를 구축할 때
- SOC 분석가가 이 분석 유형에 대한 구조화된 절차가 필요할 때
- 관련 공격 기술에 대한 보안 모니터링 범위를 검증할 때
사전 요구 사항
- 포렌식 디스크 이미지(E01, raw/dd, VMDK 또는 VHDX 형식)
- MFTECmd(Eric Zimmerman) 또는 analyzeMFT(Python 기반)
- 이미지 마운팅을 위한 FTK Imager, Arsenal Image Mounter 또는 유사 도구
- CSV 분석을 위한 Timeline Explorer 또는 Excel
- 사용자 정의 분석 스크립트를 위한 Python 3.8+
- NTFS 파일 시스템 내부 구조에 대한 이해
MFT 구조 및 레코드 레이아웃
MFT 레코드 헤더
각 MFT 레코드는 시그니처 "FILE"(0x46494C45)로 시작하며 다음 필드를 포함합니다:
| 오프셋 | 크기 | 필드 |
|---|---|---|
| 0x00 | 4바이트 | 시그니처 ("FILE") |
| 0x04 | 2바이트 | 업데이트 시퀀스 오프셋 |
| 0x06 | 2바이트 | 업데이트 시퀀스 크기 |
| 0x08 | 8바이트 | $LogFile 시퀀스 번호 |
| 0x10 | 2바이트 | 시퀀스 번호 |
| 0x12 | 2바이트 | 하드 링크 개수 |
| 0x14 | 2바이트 | 첫 번째 속성 오프셋 |
| 0x16 | 2바이트 | 플래그 (0x01 = 사용 중, 0x02 = 디렉터리) |
| 0x18 | 4바이트 | MFT 레코드 사용 크기 |
| 0x1C | 4바이트 | MFT 레코드 할당 크기 |
| 0x20 | 8바이트 | 기본 파일 레코드 참조 |
| 0x28 | 2바이트 | 다음 속성 ID |
주요 MFT 속성
| 유형 ID | 이름 | 설명 |
|---|---|---|
| 0x10 | $STANDARD_INFORMATION | 타임스탬프, 플래그, 소유자 ID, 보안 ID |
| 0x30 | $FILE_NAME | 파일 이름, 상위 MFT 참조, 타임스탬프 |
| 0x40 | $OBJECT_ID | 파일에 대한 고유 GUID |
| 0x50 | $SECURITY_DESCRIPTOR | ACL 권한 |
| 0x60 | $VOLUME_NAME | 볼륨 레이블(볼륨 메타데이터 파일 전용) |
| 0x80 | $DATA | 파일 내용(700바이트 미만이면 상주) 또는 클러스터 실행 목록 |
| 0x90 | $INDEX_ROOT | 디렉터리용 B-트리 인덱스 루트 |
| 0xA0 | $INDEX_ALLOCATION | 대형 디렉터리용 B-트리 인덱스 항목 |
| 0xB0 | $BITMAP | 인덱스 또는 MFT의 할당 비트맵 |
삭제 파일 복구 기술
기술 1: MFTECmd를 사용한 MFT 레코드 분석
# KAPE 또는 FTK Imager를 사용하여 포렌식 이미지에서 $MFT 추출
# MFTECmd로 $MFT 파싱
MFTECmd.exe -f "C:\Evidence\$MFT" --csv C:\Output --csvf mft_full.csv
# Timeline Explorer에서 삭제된 파일 필터링(InUse = FALSE)
# InUse 열이 False인 항목 찾기
CSV 출력에서 삭제된 파일 식별:
InUse= False는 삭제되었거나 재할당된 레코드를 나타냄ParentPath는 삭제 전 원본 파일 위치를 표시FileSize는 원본 크기를 표시(여전히 복구 가능할 수 있음)$STANDARD_INFORMATION및$FILE_NAME속성의 타임스탬프가 유지됨
기술 2: USN 저널($UsnJrnl:$J) 분석
USN 저널은 NTFS 볼륨의 모든 파일 변경 사항(생성, 삭제, 이름 변경, 데이터 수정 이벤트 포함)을 기록합니다.
# MFTECmd로 USN 저널 파싱
MFTECmd.exe -f "C:\Evidence\$J" --csv C:\Output --csvf usn_journal.csv
# 삭제 증거에 대한 주요 USN 이유 코드:
# USN_REASON_FILE_DELETE = 0x00000200
# USN_REASON_CLOSE = 0x80000000
# USN_REASON_RENAME_OLD_NAME = 0x00001000
# USN_REASON_RENAME_NEW_NAME = 0x00002000
기술 3: $LogFile 트랜잭션 분석
$LogFile은 USN 저널이 순환된 후에도 파일 작업을 드러낼 수 있는 NTFS 트랜잭션 레코드를 저장합니다.
# LogFileParser로 $LogFile 파싱
LogFileParser.exe -l "C:\Evidence\$LogFile" -o C:\Output
# 파일 삭제를 나타내는 REDO 및 UNDO 작업 찾기:
# - DeallocateFileRecordSegment
# - DeleteAttribute
# - UpdateResidentValue (InUse 플래그 지우기)
기술 4: MFT 슬랙 공간 분석
MFT 슬랙 공간은 MFT 레코드의 사용된 부분 끝과 할당된 1024바이트 끝 사이에 존재합니다. 이 영역에는 이전 파일 레코드의 잔재가 포함될 수 있습니다.
import struct
def parse_mft_slack(mft_path: str, output_path: str):
"""삭제된 파일 잔재를 위해 MFT 슬랙 공간을 추출하고 분석합니다."""
with open(mft_path, "rb") as f:
record_size = 1024
record_num = 0
slack_findings = []
while True:
record = f.read(record_size)
if len(record) < record_size:
break
# FILE 시그니처 확인
if record[:4] != b"FILE":
record_num += 1
continue
# 오프셋 0x18에서 사용된 크기 가져오기
used_size = struct.unpack("<I", record[0x18:0x1C])[0]
if used_size < record_size:
slack = record[used_size:]
# 슬랙에 읽을 수 있는 문자열 또는 속성 헤더가 포함되어 있는지 확인
if any(c > 0x20 and c < 0x7F for c in slack[:50]):
slack_findings.append({
"record": record_num,
"used_size": used_size,
"slack_size": record_size - used_size,
"slack_preview": slack[:100].hex()
})
record_num += 1
return slack_findings
보조 증거와의 연관 분석
MFT와 $Recycle.Bin 상호 참조
# RBCmd로 휴지통 파싱
RBCmd.exe -d "C:\Evidence\$Recycle.Bin" --csv C:\Output --csvf recycle_bin.csv
# 연관 분석: $I 파일에는 원본 경로와 삭제 타임스탬프가 포함됨
# $R 파일의 MFT 항목 번호를 원본 MFT 레코드와 일치시킴
MFT와 볼륨 섀도 복사본 상호 참조
# 볼륨 섀도 복사본 나열
vssadmin list shadows
# 각 섀도 복사본 마운트 및 $MFT 추출
# 섀도 복사본 간 MFT 레코드를 비교하여 시간에 따른 파일 변경 추적
포렌식 가치
- 삭제된 파일 메타데이터 복구: 원본 파일 이름, 경로, 크기 및 타임스탬프
- 타임라인 재구성: 파일 생성, 수정, 액세스 및 삭제 이벤트
- 타임스톰핑 탐지: $SI와 $FN 타임스탬프 비교
- 데이터 카빙 안내: MFT 클러스터 실행 정보가 디스크 상의 파일 내용을 가리킴
- 안티포렌식 탐지: 지워지거나 조작된 MFT 레코드 식별
참조
- NTFS MFT 고급 포렌식 분석: https://www.deaddisk.com/posts/ntfs-mft-advanced-forensic-analysis-guide/
- MFT 슬랙 공간의 포렌식 가치: https://www.sygnia.co/blog/the-forensic-value-of-mft-slack-space/
- MFTECmd 문서: https://ericzimmerman.github.io/
- SANS FOR500: Windows 포렌식 분석
예제 출력
$ MFTECmd.exe -f "C:\Evidence\$MFT" --csv /analysis/mft_output
MFTECmd v1.2.2 - MFT 파서
==============================
입력: C:\Evidence\$MFT (크기: 384 MB)
총 MFT 항목 수: 395,264
MFT 항목 파싱 중... 완료 (12.4초)
--- 삭제 파일 복구 요약 ---
총 항목 수: 395,264
활성 파일: 245,832
삭제된 파일: 149,432
복구 가능: 87,234 (상주 데이터 또는 클러스터가 재할당되지 않음)
부분 복구 가능: 31,456 (일부 클러스터 덮어쓰기됨)
복구 불가: 30,742 (모든 클러스터 재할당됨)
--- 최근 삭제된 파일 (사고 기간: 2024-01-15 ~ 2024-01-18) ---
MFT 항목 | 파일 이름 | 경로 | 크기 | 삭제 시간 (UTC) | 복구 가능
----------|-----------------------------------|-------------------------------------|------------|--------------------------|----------
148923 | exfil_tool.exe | C:\ProgramData\Updates\ | 1,258,496 | 2024-01-17 02:45:12 | 예
148924 | exfil_tool.log | C:\ProgramData\Updates\ | 45,312 | 2024-01-17 02:45:14 | 예
149001 | passwords.txt | C:\Users\jsmith\Desktop\ | 2,048 | 2024-01-17 02:50:33 | 예
149150 | scan_results.csv | C:\Users\jsmith\AppData\Local\Temp | 892,416 | 2024-01-17 03:00:01 | 부분
149200 | mimikatz.exe | C:\Windows\Temp\ | 1,250,816 | 2024-01-18 01:15:22 | 예
149201 | sekurlsa.log | C:\Windows\Temp\ | 32,768 | 2024-01-18 01:15:25 | 예
149302 | .bash_history | C:\Users\jsmith\ | 4,096 | 2024-01-18 03:00:00 | 아니오
149400 | ClearEventLogs.ps1 | C:\Windows\Temp\ | 1,536 | 2024-01-18 03:01:12 | 예
--- $STANDARD_INFORMATION vs $FILE_NAME 타임스탬프 분석 (타임스톰핑 탐지) ---
MFT 항목 | 파일 이름 | $SI 생성 시간 | $FN 생성 시간 | 차이 | 판정
----------|---------------------|----------------------|----------------------|-------------|----------
148923 | exfil_tool.exe | 2023-06-15 10:00:00 | 2024-01-15 14:34:02 | -214일 | 타임스톰프 의심
149200 | mimikatz.exe | 2022-01-01 00:00:00 | 2024-01-16 02:30:15 | -745일 | 타임스톰프 의심
복구된 파일 출력 위치: /analysis/mft_output/recovered/
전체 CSV 보고서: /analysis/mft_output/mft_analysis.csv (395,264행)
타임라인 CSV: /analysis/mft_output/mft_timeline.csv