
NTFS의 $LogFile용 파서
기능 $LogFile 레코드와 트랜잭션 항목을 디코딩하고 덤프합니다. NTFS 속성 변경을 디코딩합니다. 선택적으로 $LogFile에서 사용 가능한 모든 데이터런 목록 정보를 해석합니다. 옵션: "Reconstruct data runs". $LogFile 내의 슬랙 공간에서 트랜잭션을 복구합니다. 슬랙에서 발견된 트랜잭션의 누락되거나 손상된 헤더를 재구성하도록 선택합니다. 옵션: "Rebuild header". 선택적으로 LSN 오류 수준 값으로 결과를 미세 조정합니다. 옵션: "LSN error level". csv로 로깅하고 여러 테이블이 있는 sqlite 데이터베이스로 가져옵니다. 선택적으로 mft2csv의 csv 출력을 db로 가져옵니다. 6가지 서로 다른 타임스탬프 형식 중에서 선택합니다. 타임스탬프 정밀도 선택: None, MilliSec 및 NanoSec. 밀리초 단위의 정밀도 구분자를 선택합니다. 나노초 단위의 정밀도 구분자를 선택합니다. 타임스탬프에 대한 지역 조정을 선택합니다. 기본값은 타임스탬프를 UTC 0.0으로 표시하는 것입니다. 출력 구분자를 선택합니다. 옵션: "Set separator". 구성 가능한 UNICODE 또는 ANSI 출력. 옵션 "Unicode". 구성 가능한 MFT 레코드 크기 (1024 또는 4096). 옵션 "MFT record size". 선택적으로 개별 트랜잭션 또는 부분 트랜잭션 (조각)을 디코딩합니다. 단일 또는 다중 트랜잭션 (조각)에서 RCRD를 재구성하는 옵션. 손상된 $LogFile을 구성하는 옵션. 입력으로 carved RCRD를 사용할 때 유용합니다. fixup을 건너뛰는 옵션 (손상된 $LogFile, 일반적으로 메모리에서 carved된 경우). debug.log에 상세한 verbose 출력. 특정 트랜잭션에 대한 ultra verbose 정보를 debug.log에 트리거하기 위한 lsn의 구성 가능한 쉼표로 구분된 목록. 32-bit OS를 위한 구성. resident 데이터 업데이트의 바이너리 데이터 추출을 위한 구성. 출력을 MySql 데이터베이스로 가져오기 위한 자동 생성 sql. 전체 파싱 속도를 높이기 위해 모든 sqlite3 관련 작업을 건너뛰는 옵션. 선택적 명령줄 모드. 배치 스크립팅에 적합한 errorlevel을 지원합니다.
배경 NTFS는 복구 가능한 파일 시스템으로 설계되었습니다. 이는 볼륨 구조를 변경하는 모든 트랜잭션의 로깅을 통해 이루어집니다. 따라서 볼륨의 파일에 대한 모든 변경은 $LogFile에도 기록되어야 하며, 이는 언제든 시스템 장애 시 되돌릴 수 있도록 하기 위함입니다. 따라서 이 파일에 많은 정보가 기록되며, 순환 구조이기 때문에 새로운 트랜잭션이 파일의 오래된 레코드를 덮어씁니다. 따라서 이 파일에서 검색할 수 있는 과거 데이터의 양은 다소 제한적입니다. 다시 말하지만, 이는 볼륨 유형과 $LogFile의 크기에 따라 달라집니다. 자주 사용되는 시스템의 시스템 드라이브에서는 몇 시간 분량의 기록만 얻을 수 있는 반면, 백업 파일이 있는 외부/보조 디스크는 더 많은 과거 정보를 포함할 가능성이 높습니다. 그리고 2MB 파일은 256MB 파일보다 훨씬 적은 기록을 포함합니다. 그렇다면 이 파일은 어떤 크기 범위로 구성할 수 있을까요? 256 KB 이상이면 무엇이든 가능합니다. 크기를 2 GB로 구성하는 방법은 "chkdsk D: /L:2097152"와 같습니다. 큰 크기의 로그 파일이 성능에 미치는 영향은 이 문서의 범위를 벗어납니다. 일반적으로 2048보다 낮게 설정하는 것은 불가능합니다. 그러나 untfs.dll을 패치하면 가능합니다: http://code.google.com/p/mft2csv/wiki/Tiny_NTFS
소개 이 파서는 NTFS의 $LogFile에서 많은 트랜잭션 정보를 디코딩하고 덤프합니다. 여러 csv가 생성될 뿐만 아니라 모든 관련 정보를 포함하는 ntfs.db라는 sqlite 데이터베이스도 생성됩니다. 출력은 매우 상세하고 매우 낮은 수준이므로 이를 이해하려면 상당한 NTFS 지식이 필요합니다. 현재 의미 있는 출력 디코딩으로 처리되는 Redo 트랜잭션 유형은 다음과 같습니다:
InitializeFileRecordSegment CreateAttribute DeleteAttribute UpdateResidentValue UpdateNonResidentValue UpdateMappingPairs SetNewAttributeSizes AddindexEntryRoot DeleteindexEntryRoot AddIndexEntryAllocation DeleteIndexEntryAllocation WriteEndOfIndexBuffer SetIndexEntryVcnRoot SetIndexEntryVcnAllocation UpdateFileNameRoot UpdateFileNameAllocation SetBitsInNonresidentBitMap ClearBitsInNonresidentBitMap OpenNonresidentAttribute OpenAttributeTableDump AttributeNamesDump DirtyPageTableDump TransactionTableDump UpdateRecordDataRoot UpdateRecordDataAllocation CompensationlogRecord
현재 지원되는 속성 목록: $STANDARD_INFORMATION $ATTRIBUTE_LIST $FILE_NAME $OBJECT_ID $SECURITY_DESCRIPTOR $VOLUME_NAME $VOLUME_INFORMATION $DATA $INDEX_ROOT $INDEX_ALLOCATION $REPARSE_POINT $EA_INFORMATION $EA $LOGGED_UTILITY_STREAM
따라서 기본적으로 모든 속성이 지원됩니다.
생성된 다양한 출력에 대한 설명:
LogFile.csv: 파서에서 생성된 기본 csv.
LogFile_DataRuns.csv 데이터런 재구성에 필요한 입력 정보
LogFile_DataRunsResolved.csv 재구성된 데이터런의 최종 출력
LogFile_INDX_I30.csv 덤프되고 디코딩된 모든 인덱스 레코드 (IndexRoot/IndexAllocation)
LogFileJoined.csv LogFile.csv와 동일하지만 $UsnJrnl 또는 mft2csv의 csv에서 파일 이름 정보가 조인됨.
MFTRecords.bin InitializeFileRecordSegment 트랜잭션에서 발견된 MFT 레코드를 기반으로 재생성된 더미 $MFT. 이 파일에 mft2csv를 사용할 수 있습니다 ("broken MFT" 및 "Fixups"를 적절히 구성하는 것을 잊지 마세요).
LogFile_lfUsnJrnl.csv $LogFile 내에서 디코딩된 $UsnJrnl에 대한 레코드
LogFile_UndoWipe_INDX_I30.csv 디렉터리 인덱스 (INDX) 지우기에 대한 모든 undo 작업.
LogFile_AllTransactionHeaders.csv 디코딩된 모든 트랜잭션의 헤더.
LogFile_BitsInNonresidentBitMap.csv 디코딩된 모든 SetBitsInNonresidentBitMap 작업.
LogFile_DirtyPageTable32bit.csv 및 LogFile_DirtyPageTable64bit.csv 32bit 및 64bit OS 모두에 대해 디코딩된 모든 DirtyPageTableDump 작업의 모든 항목.
LogFile_Mft_ObjectId_Entries.csv 디코딩된 $ObjectId 속성.
LogFile_ObjIdO.csv 시스템 파일 $ObjId:$O에서 디코딩된 모든 항목.
LogFile_OpenAttributeTable.csv 디코딩된 모든 OpenAttributeTableDump 작업의 모든 항목.
LogFile_QuotaO.csv 시스템 파일 $Quota:$O에서 디코딩된 모든 항목.
LogFile_QuotaQ.csv 시스템 파일 $Quota:$Q에서 디코딩된 모든 항목.
LogFile_RCRD.csv 디코딩된 모든 RCRD 레코드의 헤더.
LogFile_ReparseR.csv 시스템 파일 $Reparse:$R에서 디코딩된 모든 항목.
LogFile_SecureSDH.csv 시스템 파일 $Secure:$SDH에서 디코딩된 모든 항목.
LogFile_SecureSII.csv 시스템 파일 $Secure:$SII에서 디코딩된 모든 항목.
LogFile_SecurityDescriptors.csv 디코딩된 보안 설명자. 소스는 $SECURITY_DESCRIPTOR 또는 $Secure:$SDS일 수 있습니다.
LogFile_SlackAttributeNamesDump.csv 슬랙 공간에서 발견된 디코딩된 AttributeNamesDump 트랜잭션의 모든 항목.
LogFile_SlackOpenAttributeTable.csv 슬랙 공간에서 발견된 디코딩된 OpenAttributeTableDump 트랜잭션의 모든 항목.
LogFile_TransactionTable.csv 디코딩된 TransactionTableDump 트랜잭션.
LogFile_Filenames.csv MftRef, MftRefSeqNo 및 Lsn이 있는 해석된 모든 파일 이름.
LogFile_TxfData.csv $LOGGED_UTILITY_STREAM의 $DATA:$TXF_DATA에서 디코딩된 데이터.
LogFile_UpdateFileName_I30.csv redo 및 undo 작업 모두에 대한 UpdateFileNameRoot 및 UpdateFileNameAllocation의 모든 디코딩.
LogFile_CompensationlogRecord.csv CompensationlogRecord의 모든 디코딩. nt5.x에는 관련 없음.
Ntfs.db 위 csv와 거의 동일한 테이블을 가진 sqlite 데이터베이스 파일. 데이터베이스는 5개의 테이블을 포함합니다: DataRuns IndexEntries LogFile LogFileTmp (데이터런 재생성 시 사용되는 임시 테이블). UsnJrnl
타임스탬프 기본값은 UTC 0.00으로 표시되며 나노초 정밀도입니다. 기본 형식은 YYYY-MM-DD HH:MM:SS:MSMSMS:NSNSNSNS입니다. 이는 구성할 수 있습니다. 다양한 타임스탬프는 다음을 나타냅니다: CTime은 파일 생성 시간을 의미합니다. ATime은 파일 수정 시간을 의미합니다. MTime은 MFT 항목 수정 시간을 의미합니다. RTime은 파일 마지막 접근 시간을 의미합니다.
데이터런 재구성.
파일 시스템의 많은 작업은 $LogFile에 트랜잭션을 트리거합니다. $DATA 속성, 즉 파일 내용과 관련된 것들은 현재 다음과 같이 식별됩니다:
InitializeFileRecordSegment CreateAttribute UpdateMappingPairs SetNewAttributeSizes
이들은 모두 $LogFile에 서로 다른 정보를 남깁니다. Resident 데이터 수정은 다르게 동작하며, 적어도 최신 Windows 버전에서 비롯된 NTFS 볼륨에서는 그렇게 쉽게 재구성할 수 없습니다.
InitializeFileRecordSegment는 새 파일이 생성될 때입니다. 따라서 $FILE_NAME 속성과 데이터런을 포함한 원래 $DATA 속성 내용을 갖습니다. $LogFile은 순환이므로 오래된 이벤트는 새로운 이벤트로 덮어쓰여지며, $LogFile의 과제는 충분히 오래 전의 정보를 얻는 것입니다. 그러나 InitializeFileRecordSegment가 존재한다면, 그 이후에 작성된 모든 레코드도 사용 가능하므로 모든 것을 재구성할 수 있어야 합니다. 또한 데이터런 목록에 대한 오프셋 정보도 갖게 됩니다. 이는 $DATA 속성의 시작부터 계산된 상대 오프셋입니다. 이는 UpdateMappingPairs가 데이터런 목록의 어디에서 수정을 수행했는지 계산할 때 중요한 정보입니다.
CreateAttribute는 처음 생성되었을 때의 원래 속성입니다 (InitializeFileRecordSegment의 일부로 작성되지 않은 경우). 이것도 마찬가지로 모든 트랜잭션이 사용 가능하므로 데이터런을 재구성할 수 있어야 합니다. 그러나 이것 자체는 파일 이름을 제공하지 않습니다. 여기에서도 데이터런 목록에 대한 오프셋이 사용 가능하며, 이는 UpdateMappingPairs를 해결할 때 매우 유용합니다.
UpdateMappingPairs는 $DATA/데이터런에 대한 수정이 수행될 때 (파일 내용이 변경됨)의 트랜잭션입니다. 이 트랜잭션에서 발견되는 정보는 완전하지 않으며, 기존 데이터런 목록에 추가된 새로운 값만 포함합니다. 또한 데이터런 목록의 어디에 변경 사항이 작성되었는지 알려주는 상대 오프셋을 포함합니다. 이 오프셋은 InitializeFileRecordSegment 및 CreateAttribute에서 발견되는 데이터런에 대한 오프셋과 함께 사용됩니다.
SetNewAttributeSizes는 $DATA 속성에 수행된 크기 값 관련 수정에 대한 정보를 포함하는 트랜잭션입니다. 이는 데이터런 변경만 포함하는 UpdateMappingPairs와 밀접하게 연결되어 있습니다.
위의 4가지 서로 다른 redo 작업을 통해 주어진 참조 번호 (고유 파일)에 대해 파일의 파일 시스템 변경 이력 중 일부를 재구성할 수 있습니다. 순환성 때문에 우리는 이력의 일부, 가장 최근의 것만 갖습니다. 검색할 수 있는 이력의 범위는 대상이 어떤 종류의 볼륨인지에 크게 의존합니다. 시스템 볼륨이라면 일주일의 이력은 아마 기대 이상일 것이며, 이동식 또는 외부 또는 보조 디스크는 훨씬 더 많은 이력을 포함할 것입니다. 따라서 삭제된 파일 ($MFT 레코드가 덮어쓰여진)의 전체 이력을 재구성하고, 복구를 수행할 데이터런 목록을 재생성할 수 있습니다. 다른 경우에는 전체 이력을 재구성할 수 없어 부분적인 데이터런 목록만 재구성할 수 있습니다. 조정된 데이터런이 있는 최종 csv 파일인 LogFile_DatarunsModified.csv는 데이터런을 다르게 표시합니다.
설명: "!"로 시작하는 것은 완전한 데이터런 목록이 재생성되었음을 나타냅니다. "?"로 시작하는 것은 부분 복구를 나타내며, "**"의 개수는 원래 데이터런 목록에서 누락된 바이트 수를 나타냅니다.
데이터런을 기반으로 파일 복구를 단순화하기 위해 ExtractFromDataRuns라는 첨부된 PoC를 사용할 수 있습니다. 이는 상당히 자명합니다. 완전한 데이터런 목록, 실제 크기 및 초기 크기, 출력 파일 이름을 입력하기만 하면 됩니다. 선택적으로 이미지 파일 (디스크 또는 파티션)을 처리하도록 선택할 수 있습니다. 압축/스파스 플래그가 감지되었는지도 체크하세요. 부분적으로 재구성된 데이터런 목록을 제공하면 작동하지 않습니다! 대체 데이터 스트림은 데이터 이름의 존재와 주어진 fileref에 대한 OffsetInMft 값의 차이로 구별할 수 있습니다.
별도의 다운로드 패키지 "SampleTinyNtfsVolume.zip"에는 테스트할 작은 NTFS 볼륨이 있는 파티션 이미지가 있습니다. 볼륨에는 2개의 삭제된 non-resident 파일이 있으며 둘 다 새 파일로 MFT 레코드가 덮어쓰여졌습니다. 시그니처 검색을 기반으로 하는 적절한 복구 소프트웨어는 jpg 파일 (Tulips.jpg)이 연속적이므로 복구할 수 있어야 합니다. 그러나 대부분 파일 이름이나 파일에 대한 다른 정보를 식별하지 못할 것입니다. 두 번째 파일은 단편화되어 (압축됨) MFT 레코드가 덮어쓰여져 데이터런 목록 없이 파일을 해석하는 것이 불가능하므로 표준 도구로는 복구할 수 없을 것입니다. PoC를 사용하면 파일 이름 (suspicious.zip)을 식별하고 완벽한 상태로 추출할 수 있습니다 (걱정하지 마세요, Windows와 함께 제공되는 샘플 이미지 중 하나만 포함되어 있습니다). 샘플 이미지에 대한 세부 정보와 출력 해석 및 파일 복구 방법은 readme.DataRunsResolved.txt 파일을 읽어보세요.
이를 통해 달성한 것은 MFT 레코드가 덮어쓰여진 단편화된 파일을 복구하는 것입니다. 부분/완전한 데이터런 이력을 재구성했으므로 파일 슬랙 데이터가 주어진 파일에 속했는지 여부를 확실하게 (적어도 전체 이력이 재구성된 경우) 결정할 수 있습니다.
제한 사항. 데이터런 재구성은 UNICODE에서 손상됩니다 (ANSI는 괜찮음). Mft2Csv 출력 가져오기는 csv가 UNICODE인 경우 손상됩니다 (ANSI는 괜찮음). IndexRecords (IndexRoot/IndexAllocation)에 대한 부분 업데이트는 원래 인덱스에 대한 지식이 없을 가능성이 높으므로 해석하기가 매우 어렵습니다. 완전한 레코드는 괜찮습니다. 65 MB 파일의 순환성은 얼마나 많은 과거 FS 트랜잭션이 있는지에 대한 내재적이고 절대적인 제한을 제기합니다. 따라서 시스템 드라이브는 $LogFile에 제한된 이력을 가지는 반면, 외부/보조 드라이브는 더 많은 과거 트랜잭션이 저장됩니다. chkdsk로 $LogFile의 크기를 늘릴 수 있습니다 (chkdsk c: /L:262144). resident 파일의 데이터 변경은 $LogFile 내에 저장되지 않으며, 변경이 수행되었다는 정보만 저장됩니다.
참고 $UsnJrnl은 더 인간 친화적인 방식으로 정보를 포함합니다. 예를 들어 각 레코드에는 fileref, 파일 이름, 타임스탬프 및 발생한 일에 대한 설명이 포함됩니다. 또한 $LogFile보다 훨씬 더 많은 과거 정보를 포함하지만 많은 세부 정보는 없습니다. $UsnJrnl이 활성화된 경우 $LogFile의 재활용 수명 동안 기록된 모든 트랜잭션도 $LogFile 내에 존재합니다. 이는 $LogFile을 더 잘 이해하기 위해 $UsnJrnl을 디코딩할 이유가 없음을 의미합니다.
슬랙 공간 이 맥락에서 슬랙 공간은 RCRD 레코드 내에서 마지막 트랜잭션 이후 레코드에 남은 잔여 공간을 의미합니다. 이는 이전에 설명된 적이 없다고 생각하므로 설명하겠습니다. 볼륨 슬랙은 파일 시스템 끝과 파일 시스템이 위치한 파티션 끝 사이의 사용되지 않는 공간입니다. MFT 레코드 슬랙은 종류가 비슷하지만 레코드 끝 시그니처 (0xFFFFFFFF) 이후부터 물리적 레코드 끝 (0x400 또는 0x1000)까지 발견되는 공간을 나타냅니다. 그리고 $LogFile 내의 슬랙 공간은 마지막 트랜잭션 이후부터 RCRD 레코드 끝 (일반적으로 0x1000)까지 발견되는 공간입니다. 슬랙에서 온 이러한 트랜잭션은 실제로 $LogFile이 재활용 (덮어쓰여지기)되기 전부터 있던 것입니다. 슬랙 공간에서 유효한 트랜잭션을 식별하는 알고리즘도 있습니다. 또한 이러한 슬랙 공간의 여러 계층이 존재할 수도 있습니다. 예: 주어진 RCRD 레코드의 마지막 트랜잭션이 오프셋 0x00007D27에서 끝났다고 가정해 봅시다. 이 오프셋부터 0x00007FFF까지 0x2D8 바이트의 슬랙 공간이 있습니다. 그런 다음 0x00007D28에서 시작하는 바이트가 트랜잭션 중간에 있기 때문에 유효한 트랜잭션 헤더가 아닐 수 있습니다. 프로그램은 (구성된 경우) 트랜잭션을 디코딩하기 위해 유효한 값을 가진 의사 헤더를 재구성하려고 시도합니다. 유효한 헤더를 재구성하는 데 실패하면 원래 헤더에서 너무 많은 정보가 손실된 것으로 간주하고 이 바이트를 손실된 것으로 간주하고 슬랙 공간의 나머지 부분에서 유효한 트랜잭션 헤더를 계속 검색합니다. 손실된 바이트는 조사할 수 있도록 debug.log에 기록됩니다. 반면에 유효한 헤더를 재구성할 수 있었다면 이에 대한 정보는 lf_TextInformation 필드에서 찾을 수 있습니다. 오프셋 0x00007D48에서 시작하고 크기가 0xB0인 트랜잭션을 식별했다고 가정해 봅시다. 그런 다음 오프셋 0x00007DF8에서 크기 0xE0으로 바로 뒤따르는 또 다른 좋은 트랜잭션이 식별되었습니다. 그러나 오프셋 0x00007ED8에서는 유효한 트랜잭션 헤더가 없었습니다. 이는 이제 해당 RCRD 레코드 내의 두 번째 슬랙 공간 계층에 있음을 의미합니다. 이제 프로그램이 재검색 후 오프셋 0x00007F18에서 유효한 트랜잭션 헤더를 식별할 수 있었다고 가정해 봅시다. 이 트랜잭션은 csv에서 FromRcrdSlack 필드에 값 2로 표시됩니다. 그러나 트랜잭션 총 크기가 오프셋을 RCRD 레코드 크기 이상으로 밀어내는 경우를 고려하세요. 본질적으로 이것은 부분적으로 복구된 트랜잭션이며, 잘 디코딩될 수 있지만 IncompleteTransaction 필드에 값 1로 발견됩니다. debug.log는 매우 상세하며 디코딩된 출력, 특히 슬랙 공간에서 오는 것을 이해하는 데 도움이 될 것입니다.
32-bit vs 64-bit 구성. 이 설정을 올바르게 설정하는 것이 중요합니다. 이는 어떤 OS가 대상 볼륨을 처리했는지를 의미합니다. 요점은 OpenAttributeTable의 처리가 32-bit OS와 64-bit OS에서 다르다는 것입니다. 물론 (예를 들어 usb 디스크) 볼륨이 여러 다른 OS에 의해 처리된 경우가 있을 수 있으며, 이 경우 이 설정을 100% 정확하게 하는 것이 까다로울 수 있습니다. 버전 2.0.0.8부터 자동 감지 메커니즘이 구현되었습니다. 그러나 여전히 이 구성을 올바르게 설정하는 것이 권장됩니다. TextEinformation 필드에는 구성과 다른 OpenAttributeTableDump 형식이 감지되거나 두 유형이 모두 감지될 때 "Mixed OS detected" 메시지가 출력됩니다. 어쨌든 LogFile_OpenAttributeTable.csv를 살펴보고 출력을 평가하는 것이 유용할 수 있습니다. 이상한 값을 포함하는 열이 있는 항목이 보이면 이 특정 설정이 잘못되었을 수 있습니다. 그렇다면 대부분의 값이 크게 벗어납니다. 예를 들어 대부분의 AttributeType 필드가 UNKNOWN이고, Lsn이 현재 범위 내에 없으며, MftRef가 너무 높고 MftRefSeqNo가 0입니다. AttributeType은 테이블의 초기화되지 않은 항목에 대해 UNKNOWN으로 해석되지만, AllocatedOrNextFree 이후의 모든 값이 0이고 완벽하게 유효하므로 쉽게 발견할 수 있습니다. 이러한 문제는 버전 2.0.0.8에서 구현된 자동 감지로 해결된 것으로 보입니다.resident 속성 업데이트 추출(UpdateResidentValue). UpdateResidentValue 작업은 resident 속성의 내용에 대한 업데이트를 위한 것입니다. "Extract resident updates of min size" 설정을 통해 resident 속성에 대한 바이너리 수정을 추출할 수 있습니다. 입력 필드는 추출할 최소 크기(바이트)를 위한 것입니다. 이 기능의 가장 흥미로운 사용처는 아마도 Nt5.x(XP, 2003)에서 처리되는 볼륨으로, 여기서 $DATA 속성(일반 파일 내용)에 대한 완전한 업데이트가 redo 및 undo 필드에 UpdateResidentValue와 함께 저장됩니다. resident $DATA 내용을 가진 파일은 크기가 더 작은 파일로, 최대 744바이트(MFT 레코드 크기가 1024인 경우)이지만 보통은 그보다 작습니다. 추출된 데이터는 ResidentExtract라는 하위 폴더에 기록됩니다. 출력 파일은 다음과 같은 논리로 이름이 지정됩니다: MFT($MFTRef)$OffsetInMft$AttributeOffset_LSN($Lsn)$Operation.bin. 예를 들어 MFT(1643)_0x0098_0x00B8_LSN(1415242628)redo.bin은 MFT 레코드 번호 1643, MFT 내 대상 속성의 오프셋이 0x98, 대상 속성 내 수정의 오프셋이 0xB8, 트랜잭션의 LSN이 1415242628이며, 이것이 redo 작업을 위한 것임을 의미합니다. 따라서 undo 작업에 대한 추출물은 수정 전 해당 오프셋의 데이터를 포함합니다. 이 기능을 활성화하면 관련 없고 흥미롭지 않은 출력이 발생합니다. 대부분의 오탐은 자동으로 필터링되지만 일부는 피할 수 없습니다. 예를 들어 $INDEX_ROOT, $ATTRIBUTE_LIST 및 $BITMAP의 업데이트가 포함될 수 있습니다. 하지만 OffsetInMft를 관련 InitializeFileRecordSegment에서 발견된 것과 비교하거나 해당되는 경우 $MFT 자체에서 비교하여 수동으로 속성을 추적해 $DATA가 아닌 것을 필터링하는 것이 가능합니다. 버전 2.0.0.13부터 $EA 추출이 추가되었습니다. $EA 속성에 대한 참고 사항을 참조하십시오.
Filenames csv 버전 2.0.0.6부터 식별된 모든 파일 이름을 덤프하는 새로운 기능이 구현되었습니다. 이러한 항목의 출처는 InitializeFileRecordSegment, UpdateNonResidentValue, AddindexEntryRoot, DeleteindexEntryRoot, AddIndexEntryAllocation, DeleteIndexEntryAllocation 및 WriteEndOfIndexBuffer입니다. 이러한 파일 이름이 담긴 csv인 LogFile_FileNames.csv는 따라서 $LogFile 이력 기간 동안의 모든 파일 이름, MftRef 및 MftRefSeqNo의 재구성된 이력을 포함합니다. 따라서 $LogFile이 포괄한 기간 동안 주어진 Mft 레코드가 가졌던 모든 다양한 파일 이름을 볼 수 있습니다. 파일 이름이 변경될 때 MftrefSeqNo는 증가하지 않습니다. MFT 레코드가 삭제됨으로 표시되고 나중에 재사용되면, 새로운 초기화와 함께 MftRefSeqNo가 1 증가합니다.
$TXF_DATA Transactional NTFS(TxF)에서는 $LOGGED_UTILITY_STREAM 속성에 명명된 스트림 $TXF_DATA가 나타날 수 있습니다. 이는 항상 resident이며, 파일당 여러 개가 있을 수 있습니다. 사용은 널리 퍼져 있지 않으며, Microsoft는 실제로 대안 방법을 권장합니다. [quote]Microsoft strongly recommends developers utilize alternative means to achieve your applications needs.[/quote]. 이를 사용하는 소프트웨어 업데이트 메커니즘은 소수에 불과한 것으로 보입니다. 이를 통해 생성된 모든 파일/폴더는 고유한 fileref를 받습니다(MFT 레코드 번호와 혼동하지 마십시오). 이 고유한 fileref는 나중에 파일이 삭제될 때(그리고 $Extend$RmMetadata$Txf 폴더로 이동될 때) 파일 이름이 되는 것입니다. $Tops 파일의 표준 이름 없는 $DATA 속성은 $TxfLogContainer00000000000000000001에서 다음 트랜잭션이 어디로 갈지에 대한 정보를 포함합니다. $Tops의 명명된 $DATA 스트림 $T는 재활용되는(트랜잭션 파일 작업에서 나온) 실제 데이터를 포함합니다. $TXF_DATA 내에는 LsnUserData라는 필드도 있는데, 이는 훨씬 더 많은 트랜잭션 세부 정보가 발견되는 $TxfLogContainer00000000000000000001 내의 오프셋입니다. LsnNtfsMetadata도 동일한 $TxfLogContainer00000000000000000001 파일 내의 오프셋을 포함합니다. 이러한 오프셋은 나중 단계에서 변경될 수 있으며, 그때 $LogFile의 UpdateResidentValue 작업에서 참조됩니다. MftRef_RM_Root 필드는 이 파일과 연관된 트랜잭션을 담당하는 리소스 관리자의 루트에 대한 파일 레코드 번호입니다(기본값은 5이며 루트 디렉터리입니다). UpdateResidentValue를 통한 $TXF_DATA 업데이트의 경우, TextInformation 필드에 "Partial update"라는 텍스트가 추가됩니다. 이러한 이유로 LsnUserData에 0x0000000000007E--와 같은 값이 존재할 수도 있습니다. 이는 크기 31바이트의 UpdateResidentValue가 완전한 구조의 처음 3개 멤버가 누락되었고 LsnUserData에서도 1바이트가 누락되었음을 의미하기 때문입니다. 누락된 바이트는 "low byte"이므로, 누락된 알 수 없는 바이트(실제로는 기존 바이트)를 나타내기 위해 대체로 각각 2개의 문자/니블인 "-"가 사용됩니다. UpdateResidentValue가 32바이트였다면 전체 LsnUserData가 제공되었으므로 대체 문자/니블이 필요하지 않았을 것입니다.
debug.log 이 로그에는 오류 메시지와 상세 정보가 기록됩니다. 출력에서 이상한 값이나 주석이 발견되면 debug.log에서 해당 lsn을 검색하십시오. 보통 전체 트랜잭션이 덤프되며, 이는 이해에 도움이 될 수 있습니다. 트랜잭션 조사를 돕기 위해 입력 필드에 lsn의 쉼표로 구분된 목록을 채우는 것이 유용할 수 있습니다. 그러면 이러한 lsn에 대한 상세 정보가 출력됩니다.
$EA $EA 속성은 이름-값 쌍의 집합이며 OS/2와의 호환성을 위해 존재하는 것으로 여겨집니다. 사용되는 경우는 드물지만 일부 악성코드가 이를 사용했습니다. 속성당 여러 쌍이 있을 수 있지만, 전체의 최대 크기는 65535바이트입니다. 파일당 $EA 속성은 1개만 있을 수 있습니다. 더 큰 내용은 EaTools PoC에 표시된 것처럼 여러 파일에 걸쳐 분산될 수 있습니다: https://github.com/jschicht/EaTools 기존 $EA 속성은 직접 수정할 수 없습니다. 모든 쌍의 크기가 0xFFFF바이트 미만인 한 언제든지 추가 이름/값 쌍을 추가할 수 있습니다. 이 속성의 이상한 동작은 새로운 쌍이 있을 때마다 전체 $EA의 모든 내용이 $LogFile에 기록된다는 것입니다. 이는 resident 및 nonresident $EA 내용 모두에 해당합니다. 즉, $EA에 세 번째 이름/값 쌍이 추가되면 3개 쌍 모두가 UpdateResidentValue 또는 UpdateNonResidentValue를 통해 $LogFile에 기록됩니다.
Todo ntfs.db에 존재하는 데이터에 대한 더 많은 분석을 구현합니다. 현재 출력을 이해하려면 어느 정도 수준의 NTFS 지식이 필요합니다. non-resident $EA 내용을 덤프합니다.
Command line use 매개변수를 제공하지 않으면 기본적으로 GUI가 실행됩니다. 유효한 스위치는 다음과 같습니다:
Switches: /LogFileFile: 추출된 입력 $LogFile. /LogFileFragmentFile:을 사용하지 않는 한 필수입니다. /LogFileFragmentFile: 선택적으로 $LogFile 조각을 입력합니다. 최소 1개의 트랜잭션이 있는 손상된 조각이면 됩니다. /MftCsvFile: 최신 Mft2Csv의 출력 csv. 선택 사항입니다. /OutputPath: 모든 파서 출력의 출력 경로. 기본값은 프로그램 디렉터리입니다. /TimeZone: 시간대에 대한 문자열 값. 유효한 값은 아래 참고 사항을 참조하십시오. /OutputFormat: csv의 출력 형식. 유효한 값은 l2t, BodyFile, all입니다. /BrokenMft: 잘못된 형식의 MFT를 처리하기 위한 부울 값. 기본값은 0입니다. 0 또는 1일 수 있습니다. /SkipFixups: fixup을 건너뛰기 위한 부울 값. 주로 메모리 덤프와 함께 사용됩니다. 기본값은 0입니다. 0 또는 1일 수 있습니다. /Separator: csv에서 사용할 구분자. 기본값은 | /Unicode: 유니코드 문자열을 디코딩하기 위한 부울 값. 기본값은 0입니다. 0 또는 1일 수 있습니다. /TSFormat: 타임스탬프 형식을 지정하기 위한 1 - 6의 정수. 의미를 보려면 gui를 시작하십시오. 기본값은 6입니다. /TSPrecision: 타임스탬프에서 사용할 정밀도. 유효한 값은 None, MilliSec 및 NanoSec입니다. 기본값은 NanoSec입니다. /TSPrecisionSeparator: 정밀도 구분에 넣을 구분자. 기본값은 "."입니다. 의미를 보려면 gui를 시작하십시오. /TSPrecisionSeparator2: 타임스탬프 정밀도에서 MilliSec과 NanoSec 사이에 넣을 구분자. 기본값은 비어 있음/없음입니다. 의미를 보려면 gui를 시작하십시오. /TSErrorVal: 타임스탬프 디코드에서 오류와 함께 넣을 사용자 지정 오류 값. 기본값은 '0000-00-00 00:00:00'이며, MySql과 호환되고 NTFS에 대해 유효하지 않은 타임스탬프 값을 나타냅니다. /ReconstructDataruns: datarun의 재구성을 수행해야 하는지 지정하기 위한 부울 값. 기본값은 0입니다. 0 또는 1일 수 있습니다. /MftRecordSize: MFT 레코드의 크기. 유효한 값은 1024 및 4096입니다. 기본값은 1024입니다. /RebuildHeadersSlack: slack에서 복구된 손상된 트랜잭션으로부터 헤더를 재구성하려고 시도할지 지정하기 위한 부울 값. 기본값은 0입니다. 0 또는 1일 수 있습니다. /SectorsPerCluster: 클러스터당 섹터 수. 기본값은 8입니다. 1,2,4,8,16,32,64 및 128일 수 있습니다. /LsnErrorLevel: 이전 lsn을 기준으로 slack에서 유효/무효 트랜잭션을 식별하기 위한 임계값으로서 0과 1(100%) 사이의 값. 기본값은 0.1(10%)입니다. /SourceIs32bit: 볼륨이 32비트 시스템에서 온 것인지 지정하기 위한 부울 값. 기본값은 0(x64)입니다. 0 또는 1일 수 있습니다. /ExtractDataUpdates: resident 데이터 내용의 추출을 수행해야 하는지 지정하기 위한 부울 값. 기본값은 0입니다. 0 또는 1일 수 있습니다. /ExtractDataUpdatesSize: 추출할 대상의 최소 크기(바이트)를 설정하기 위한 값. ExtractDataUpdates 설정과 함께만 사용됩니다. 기본값은 최소 2(바이트)입니다. /VerboseLsnList: 상세 모드를 트리거할 lsn의 쉼표로 구분된 목록. 상세 로깅 정보는 debug.log에서 찾을 수 있습니다. /SkipSqlite3: 파서가 모든 sqlite3 작업을 생략해야 하는지 지정하기 위한 부울 값. 생성된 ntfs.db(datarun 재구성, mft csv 가져오기)가 사용되지 않으면 이를 안전하게 무시/생략할 수 있습니다. 기본값은 0입니다. 0 또는 1일 수 있습니다. /VerifyFragment: 전체 파서가 아닌 조각에 대해서만 간단한 검증을 활성화하기 위한 부울 값. 0 또는 1일 수 있습니다. /OutFragmentName:에서 달리 지정하지 않는 한 기본적으로 수정된 조각을 OutFragment.bin에 기록합니다. /OutFragmentName: /VerifyFragment:가 1로 설정된 경우 수정된 조각을 기록할 출력 파일 이름. 생략하면 기본 파일 이름은 OutFragment.bin입니다. /SkipFixups: fixup을 건너뛰기 위한 부울 값. 재구성된 조각과 함께 사용됩니다. 예제를 참조하십시오. 기본값은 0입니다. 0 또는 1일 수 있습니다. /BrokenLogFile: $LogFile을 손상된 것으로 취급하기 위한 부울 값. 재구성된 RCRD와 함께 사용되며 여러 검증 검사를 우회합니다. 기본값은 0입니다. 0 또는 1일 수 있습니다.
사용 가능한 TimeZone은 다음과 같습니다: -12.00 -11.00 -10.00 -9.30 -9.00 -8.00 -7.00 -6.00 -5.00 -4.30 -4.00 -3.30 -3.00 -2.00 -1.00 0.00 1.00 2.00 3.00 3.30 4.00 4.30 5.00 5.30 5.45 6.00 6.30 7.00 8.00 8.45 9.00 9.30 10.00 10.30 11.00 11.30 12.00 12.45 13.00 14.00
Error levels 현재 종료(오류) 코드는 명령줄 모드에서 구현되어 있어 배치 스크립팅에 더 적합합니다.
따라서 %ERRORLEVEL% == 1이면 아무것도 디코딩되지 않았음을 의미하고, %ERRORLEVEL% == 2이면 SectorsPerCluster 매개변수가 잘못 설정되었을 가능성이 높습니다.
Examples: LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:2.00 /MftRecordSize:4096 /ExtractDataUpdates:1 /ExtractDataUpdatesSize:8 /SectorsPerCluster:64 /TSFormat:1 /TSPrecision:NanoSec /Unicode:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:-5.00 /MftRecordSize:1024 /SectorsPerCluster:1 /TSFormat:1 /TSPrecision:MilliSec /Unicode:0 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TSFormat:3 /ReconstructDataruns:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:7.00 /MftRecordSize:1024 /TSFormat:2 /TSPrecision:None /SourceIs32bit:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:7.00 /MftRecordSize:1024 /TSFormat:2 /TSPrecision:None /SourceIs32bit:1 /SkipSqlite3:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /OutputPath:E:\LFP-Output LogFileParser.exe /LogFileFile:c:\temp$LogFile /MftCsvFile:c:\temp$MFT LogFileParser.exe /LogFileFragmentFile:c:\temp\fragment.bin /OutputPath:E:\LFP-Output LogFileParser.exe /LogFileFragmentFile:c:\temp\fragment.bin /OutputPath:E:\LFP-Output /VerifyFragment:1 LogFileParser.exe /LogFileFragmentFile:c:\temp\fragment.bin /OutputPath:E:\LFP-Output /VerifyFragment:1 /OutFragmentName:FragmentsRCRDCollection.bin LogFileParser.exe /LogFileFile:E:\LFP-Output\FragmentsRCRDCollection.bin /OutputPath:E:\LFP-Output /SkipFixups:1 /BrokenLogFile:1
마지막 예제는 많은 경우에 잘 작동하는 일반적인 기본값을 사용하는 기본 예제입니다. MySql 가져오기와도 호환됩니다.
References: Windows Internals 6th Edition http://www.opensource.apple.com/source/ntfs/ntfs-80/kext/ntfs_logfile.h https://dl.dropbox.com/s/c0u980a53ipaq7h/CEIC-2012_Anti-Anti_Forensics.pptx?dl=1