All about Programming

NtFsControlFile을 사용해서 파일시스템의 비트맵 정보 dump

민토즈 2021. 1. 4. 16:14
300x250

아주 오래 전에 작성했던 코드라 기억이 잘 안나네요.

Windows용 프로그램으로 undocument된 function을 User Level에서 사용합니다. 

 

파일시스템은 기본적인 단위가 cluster 크기로 할당되어 있으며, 한 cluster는 8 sector (4KB), 16 sector, 32 sector 등의 단위로 크기를 설정할 수 있습니다.  한 섹터는 512바이트 입니다.

 

파일 시스템에서 제공되는 1 bit의 크기는 1 cluster가 사용 상태를 보여줍니다. 1은 사용 중인 상태이며, 0은 사용하고 있지 않은 상태입니다. 사용 중인 상태는 파일의 데이터, 파일 레코드, 시스템 메타 데이터 등이 해당 클러스터에 데이터가 저장되어 있음을 나타냅니다. 

 

파티션에서 사용되는 BITMAP을 덤프하는 코드를 작성해보겠습니다. 완전한 코드가 아니며, 전체적인 흐름만 참고하세요.

 

// 볼륨 핸들을 구함

// open volume

HANDLE vHandle;
CHAR Name[] = "\\\\.\\C:";

vHandle = CreateFile(Name, GENERIC_READ, 
                           FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 
                           0, 0);

 

// undocument function인 NtFsControlFile의 address를 가져옴


typedef NTSTATUS (__stdcall *NtFsControlFilexx)( 
                                       HANDLE FileHandle,
                                       HANDLE Event, 
                                       PIO_APC_ROUTINE ApcRoutine, 
                                       PVOID ApcContext, 
                                       PIO_STATUS_BLOCK IoStatusBlock,
                                       ULONG FsControlCode,
                                       PVOID InputBuffer, 
                                       ULONG InputBufferLength,
                                       PVOID OutputBuffer, 
                                       ULONG OutputBufferLength );

#define BITMAPSIZE (4096+2*sizeof(ULONGLONG))

// 
// This is the definition of the buffer that FSCTL_GET_VOLUME_BITMAP
// returns. It consists of a header followed by the actual bitmap data
//
typedef struct {
ULONGLONG StartLcn;
ULONGLONG ClustersToEndOfVol;
BYTE Map[1];
} BITMAP_DESCRIPTOR, *PBITMAP_DESCRIPTOR; 

NtFsControlFilexx NtFsControlFile;
DWORD status;
PBITMAP_DESCRIPTOR bitmap_des;
ULONGLONG cluster;
ULONGLONG Lcn;
BYTE     bitmap[ BITMAPSIZE ];
IO_STATUS_BLOCK io_status;

NtFsControlFile = (NtFsControlFilexx ) GetProcessAddress( GetModuleHandle("ntdll.dll"), ("NtFsControlFile") );

cluster = 0
Lcn = 0;
status = NtFsControlFile(vHandle, NULL, NULL,
                                0, &io_status, FSCTL_GET_VOLUME_BITMAP,
                                &Lcn, sizeof(cluster), bitmap_des, BITMAPSIZE)

// loop for status == STATUS_BUFFER_OVERFLOW or STATUS_PENDING
// 비트맵의 정보는 bitmap_des->Map에 저장되어 있습니다. 
// 모든 bitmap을 읽어올 수 없으므로, Lcn 정보를 갱신해서 bitmap 정보를 읽어 옵니다.

 

300x250