|
|
#include "ulib.hxx"
#include "drive.hxx"
#include "ifssys.hxx"
#include "ntfssa.hxx"
#include "frs.hxx"
#include "attrib.hxx"
#include "mftfile.hxx"
#include "bitfrs.hxx"
#include "ntfsbit.hxx"
#include "upfile.hxx"
#include "upcase.hxx"
#include "rfatsa.hxx"
#include "rcache.hxx"
#include "hmem.hxx"
#include "recordpg.hxx"
#include "crack.hxx"
#include "diskedit.h"
extern "C" { #include <stdio.h>
}
extern PLOG_IO_DP_DRIVE Drive;
TCHAR Path[MAX_PATH];
VOID CrackNtfsPath( IN HWND WindowHandle ) { DSTRING path; NTFS_SA ntfssa; MESSAGE msg; NTFS_MFT_FILE mft; NTFS_BITMAP_FILE bitmap_file; NTFS_ATTRIBUTE bitmap_attribute; NTFS_BITMAP volume_bitmap; NTFS_UPCASE_FILE upcase_file; NTFS_ATTRIBUTE upcase_attribute; NTFS_UPCASE_TABLE upcase_table; NTFS_FILE_RECORD_SEGMENT file_record; BOOLEAN error; BOOLEAN system_file; ULONG file_number; TCHAR buf[100];
if (!path.Initialize(Path)) { wsprintf(buf, TEXT("Out of memory")); MessageBox(WindowHandle, buf, TEXT("DiskEdit"), MB_OK|MB_ICONEXCLAMATION); return; }
if (!Drive || !ntfssa.Initialize(Drive, &msg) || !ntfssa.Read() || !mft.Initialize(Drive, ntfssa.QueryMftStartingLcn(), ntfssa.QueryClusterFactor(), ntfssa.QueryFrsSize(), ntfssa.QueryVolumeSectors(), NULL, NULL) || !mft.Read() || !bitmap_file.Initialize(mft.GetMasterFileTable()) || !bitmap_file.Read() || !bitmap_file.QueryAttribute(&bitmap_attribute, &error, $DATA) || !volume_bitmap.Initialize(ntfssa.QueryVolumeSectors() / (ULONG) ntfssa.QueryClusterFactor(), FALSE, NULL, 0) || !volume_bitmap.Read(&bitmap_attribute) || !upcase_file.Initialize(mft.GetMasterFileTable()) || !upcase_file.Read() || !upcase_file.QueryAttribute(&upcase_attribute, &error, $DATA) || !upcase_table.Initialize(&upcase_attribute) || !mft.Initialize(Drive, ntfssa.QueryMftStartingLcn(), ntfssa.QueryClusterFactor(), ntfssa.QueryFrsSize(), ntfssa.QueryVolumeSectors(), &volume_bitmap, &upcase_table) || !mft.Read()) {
swprintf(buf, TEXT("Could not init NTFS data structures")); MessageBox(WindowHandle, buf, TEXT("DiskEdit"), MB_OK|MB_ICONEXCLAMATION);
return; } if (!ntfssa.QueryFrsFromPath(&path, mft.GetMasterFileTable(), &volume_bitmap, &file_record, &system_file, &error)) { wsprintf(buf, TEXT("File not found.")); MessageBox(WindowHandle, buf, TEXT("DiskEdit"), MB_OK|MB_ICONINFORMATION);
return; }
file_number = file_record.QueryFileNumber().GetLowPart();
wsprintf(buf, TEXT("The given path points to file record 0x%X"), file_number);
MessageBox(WindowHandle, buf, TEXT("Path Image"), MB_OK); }
BOOLEAN BacktrackFrs( IN VCN FileNumber, IN OUT PNTFS_MASTER_FILE_TABLE Mft, OUT PWCHAR PathBuffer, IN ULONG BufferLength, OUT PULONG PathLength ) /*++
Routine Description:
This function finds a path from the root to a given FRS.
Arguments:
FileNumber -- Supplies the file number of the target FRS. Mft -- Supplies the volume's Master File Table. PathBuffer -- Receives a path to the FRS. BufferLength -- Supplies the length (in characters) of the client's buffer. PathLength -- Receives the length (in characters) of the path.
Return Value:
TRUE upon successful completion. The returned path may not be NULL-terminated.
--*/ { NTFS_FILE_RECORD_SEGMENT CurrentFrs; NTFS_ATTRIBUTE FileNameAttribute; VCN ParentFileNumber; PCFILE_NAME FileName; ULONG i; BOOLEAN Error;
if( FileNumber == ROOT_FILE_NAME_INDEX_NUMBER ) {
// This is the root; return a NULL path.
//
*PathLength = 0; return TRUE; }
// Initialize the FRS and extract a name (any name will do).
//
if( !CurrentFrs.Initialize( FileNumber, Mft ) || !CurrentFrs.Read() || !CurrentFrs.QueryAttribute( &FileNameAttribute, &Error, $FILE_NAME ) || !FileNameAttribute.IsResident() ) {
return FALSE; }
FileName = (PCFILE_NAME)FileNameAttribute.GetResidentValue();
ParentFileNumber.Set( FileName->ParentDirectory.LowPart, (LONG)FileName->ParentDirectory.HighPart );
// Now recurse into this file's parent.
//
if( !BacktrackFrs( ParentFileNumber, Mft, PathBuffer, BufferLength, PathLength ) ) {
return FALSE; }
// Add this file's name to the path.
//
if( *PathLength + FileName->FileNameLength + 1 > BufferLength ) {
// Buffer is too small.
//
return FALSE; }
PathBuffer[*PathLength] = '\\';
for( i = 0; i < FileName->FileNameLength; i++ ) {
PathBuffer[*PathLength+1+i] = FileName->FileName[i]; }
*PathLength += 1 + FileName->FileNameLength;
return TRUE;
}
BOOLEAN BacktrackFrsFromScratch( IN HWND WindowHandle, IN VCN FileNumber ) /*++
Routine Description:
This function finds a path from the root to a given FRS; it sets up the MFT and its helper objects as needed.
Arguments:
WindowHandle -- Supplies a handle to the parent window. FileNumber -- Supplies the file number of the target FRS.
Return Value:
TRUE upon successful completion. The returned path may not be NULL-terminated.
--*/ { WCHAR WPath[MAX_PATH];
NTFS_SA ntfssa; MESSAGE msg; NTFS_MFT_FILE mft; NTFS_BITMAP_FILE bitmap_file; NTFS_ATTRIBUTE bitmap_attribute; NTFS_BITMAP volume_bitmap; NTFS_UPCASE_FILE upcase_file; NTFS_ATTRIBUTE upcase_attribute; NTFS_UPCASE_TABLE upcase_table; BOOLEAN error; ULONG BufferLength, PathLength, i;
BufferLength = sizeof(WPath);
if (!Drive || !ntfssa.Initialize(Drive, &msg) || !ntfssa.Read() || !mft.Initialize(Drive, ntfssa.QueryMftStartingLcn(), ntfssa.QueryClusterFactor(), ntfssa.QueryFrsSize(), ntfssa.QueryVolumeSectors(), NULL, NULL) || !mft.Read() || !bitmap_file.Initialize(mft.GetMasterFileTable()) || !bitmap_file.Read() || !bitmap_file.QueryAttribute(&bitmap_attribute, &error, $DATA) || !volume_bitmap.Initialize(Drive->QuerySectors()/ (ULONG) ntfssa.QueryClusterFactor(), FALSE, NULL, 0) || !volume_bitmap.Read(&bitmap_attribute) || !upcase_file.Initialize(mft.GetMasterFileTable()) || !upcase_file.Read() || !upcase_file.QueryAttribute(&upcase_attribute, &error, $DATA) || !upcase_table.Initialize(&upcase_attribute) || !mft.Initialize(Drive, ntfssa.QueryMftStartingLcn(), ntfssa.QueryClusterFactor(), ntfssa.QueryFrsSize(), ntfssa.QueryVolumeSectors(), &volume_bitmap, &upcase_table) || !mft.Read() || !bitmap_file.Initialize(mft.GetMasterFileTable()) || !bitmap_file.Read() || !bitmap_file.QueryAttribute(&bitmap_attribute, &error, $DATA) || !volume_bitmap.Initialize(Drive->QuerySectors()/ (ULONG) ntfssa.QueryClusterFactor(), FALSE, NULL, 0) || !volume_bitmap.Read(&bitmap_attribute) || !upcase_file.Initialize(mft.GetMasterFileTable()) || !upcase_file.Read() || !upcase_file.QueryAttribute(&upcase_attribute, &error, $DATA) || !upcase_table.Initialize(&upcase_attribute) || !BacktrackFrs( FileNumber, mft.GetMasterFileTable(), WPath, BufferLength, &PathLength ) ) {
return FALSE; }
MessageBox(WindowHandle, WPath, TEXT("Path Image"), MB_OK);
return TRUE; }
VOID CrackFatPath( IN HWND WindowHandle ) { DSTRING path; REAL_FAT_SA fatsa; MESSAGE msg; ULONG cluster_number; TCHAR buf[100];
if (!path.Initialize(Path) || !Drive || !fatsa.Initialize(Drive, &msg) || !fatsa.FAT_SA::Read()) {
return; }
cluster_number = fatsa.QueryFileStartingCluster(&path);
wsprintf(buf, TEXT("The given path points to cluster 0x%X"), cluster_number);
MessageBox(WindowHandle, buf, TEXT("Path Image"), MB_OK); }
VOID CrackLsn( IN HWND WindowHandle ) { extern LSN Lsn; TCHAR buf[100]; LONGLONG FileOffset;
(void)GetLogPageSize(Drive);
LfsTruncateLsnToLogPage(Drive, Lsn, &FileOffset);
wsprintf(buf, TEXT("page at %x, offset %x, seq %x"), (ULONG)FileOffset, LfsLsnToPageOffset(Drive, Lsn) , LfsLsnToSeqNumber(Drive, Lsn)); MessageBox(WindowHandle, buf, TEXT("LSN"), MB_OK); }
//
// CrackNextLsn -- given an LSN in the Lsn variable, find the
// LSN following that one in the log file. This involves
// reading the log record for the given lsn to find it's
// size, and figuring the page and offset of the following
// lsn from that.
//
BOOLEAN CrackNextLsn( IN HWND WindowHandle ) { extern LSN Lsn; TCHAR buf[100]; NTFS_SA ntfssa; NTFS_MFT_FILE mft; ULONG PageOffset; LONGLONG FileOffset; MESSAGE msg; BOOLEAN error; NTFS_FILE_RECORD_SEGMENT frs; NTFS_ATTRIBUTE attrib;
LFS_RECORD_HEADER RecordHeader; ULONG bytes_read; ULONG RecordLength; ULONG PageSize; ULONGLONG NextLsn; ULONG SeqNumber;
if (0 == (PageSize = GetLogPageSize(Drive))) { return FALSE; }
if (!Drive) return FALSE; if (!ntfssa.Initialize(Drive, &msg)) return FALSE; if (!ntfssa.Read()) return FALSE; if (!mft.Initialize(Drive, ntfssa.QueryMftStartingLcn(), ntfssa.QueryClusterFactor(), ntfssa.QueryFrsSize(), ntfssa.QueryVolumeSectors(), NULL, NULL)) return FALSE; if (!mft.Read()) return FALSE; if (!frs.Initialize((VCN)LOG_FILE_NUMBER, &mft)) return FALSE; if (!frs.Read()) return FALSE; if (!frs.QueryAttribute(&attrib, &error, $DATA, NULL)) { return FALSE; }
LfsTruncateLsnToLogPage(Drive, Lsn, &FileOffset); PageOffset = LfsLsnToPageOffset(Drive, Lsn); SeqNumber = (ULONG)LfsLsnToSeqNumber(Drive, Lsn);
if (!attrib.Read((PVOID)&RecordHeader, ULONG(PageOffset | FileOffset), LFS_RECORD_HEADER_SIZE, &bytes_read)) return FALSE;
if (bytes_read != LFS_RECORD_HEADER_SIZE) { return FALSE; }
RecordLength = LFS_RECORD_HEADER_SIZE + RecordHeader.ClientDataLength;
if (PageOffset + RecordLength < PageSize && PageSize - (PageOffset + RecordLength) >= LFS_RECORD_HEADER_SIZE) {
//
// the current record ends on this page, and the next record begins
// immediately after
//
PageOffset += RecordLength;
} else if (PageSize - (PageOffset+RecordLength) < LFS_RECORD_HEADER_SIZE) {
//
// The next record header will not fit on this page... it
// will begin on the next page immediately following the page
// header
//
FileOffset += PageSize; PageOffset = LFS_PACKED_RECORD_PAGE_HEADER_SIZE;
} else { //
// the next log record starts on a following page
//
ULONG left; ULONG page_capacity;
left = PageSize - (PageOffset + RecordLength); page_capacity = PageSize - LFS_PACKED_RECORD_PAGE_HEADER_SIZE; PageOffset += (left / page_capacity + 1) * PageSize; FileOffset = left % page_capacity + LFS_PACKED_RECORD_PAGE_HEADER_SIZE; }
// create lsn from FileOffset + PageOffset
NextLsn = LfsFileOffsetToLsn(Drive, FileOffset | PageOffset, SeqNumber);
wsprintf(buf, TEXT("Next LSN %x:%x, at %x + %x"), ((PLSN)&NextLsn)->HighPart, ((PLSN)&NextLsn)->LowPart, (ULONG)FileOffset, (ULONG)PageOffset); MessageBox(WindowHandle, buf, TEXT("LSN"), MB_OK);
return TRUE; }
struct { ULONG Code; PTCHAR Name; } TypeCodeNameTab[] = { { $UNUSED, TEXT("$UNUSED") }, { $STANDARD_INFORMATION, TEXT("$STANDARD_INFORMATION") }, { $ATTRIBUTE_LIST, TEXT("$ATTRIBUTE_LIST") }, { $FILE_NAME, TEXT("$FILE_NAME") }, { $OBJECT_ID, TEXT("$OBJECT_ID") }, { $SECURITY_DESCRIPTOR, TEXT("$SECURITY_DESCRIPTOR") }, { $VOLUME_NAME, TEXT("$VOLUME_NAME") }, { $VOLUME_INFORMATION, TEXT("$VOLUME_INFORMATION") }, { $DATA, TEXT("$DATA") }, { $INDEX_ROOT, TEXT("$INDEX_ROOT") }, { $INDEX_ALLOCATION, TEXT("$INDEX_ALLOCATION") }, { $BITMAP, TEXT("$BITMAP") }, { $SYMBOLIC_LINK, TEXT("$SYMBOLIC_LINK") }, { $EA_INFORMATION, TEXT("$EA_INFORMATION") }, { $EA_DATA, TEXT("$EA_DATA") }, { $END, TEXT("$END") } };
PTCHAR GetNtfsAttributeTypeCodeName( IN ULONG Code ) { for (INT i = 0; $END != TypeCodeNameTab[i].Code; ++i) { if (Code == TypeCodeNameTab[i].Code) { return TypeCodeNameTab[i].Name; } } return NULL; }
|