U E D R , A S I H C RSS

김희성/MTFREADER

_mft_reader.h

#include"ntfs.h"
class _MFT_READER
{

#define FILE_LOAD_ERROR 1
#define OUT_OF_MEMORY_ERROR 2

private:
	HANDLE hVolume;
	BOOT_BLOCK boot_block;
	PFILE_RECORD_HEADER MFT;

	U32 BytesPerFileRecord;
	U32 cnt;
	long MFTLength;

	int ErrorCode;

	void LoadMFT();
	long ReadAttribute(FILE* fp, unsigned char* offset, long flag);
	void ReadSector(U64 sector, U32 count, void* buffer);
	__int64 ReadCluster(unsigned char* point,unsigned char* info);

public:
	_MFT_READER
		//(WCHAR* drive)
		(char* drive)
	{
		ErrorCode=0;

		hVolume = CreateFile(drive, GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE, 0,OPEN_EXISTING, 0, 0);
		ReadFile(hVolume, &boot_block, sizeof(boot_block), &cnt, 0);

		if(!GetLastError())
			LoadMFT();
		else
			ErrorCode=FILE_LOAD_ERROR;
	}

//	void ReLoadMFT(char* drive);
	int LastErrorCode();							//최근에 일어난 클래스 내부의 에러를 반환한다.
	void MakeBinaryFile(char* filename);			//MFT를 Binary 그대로 저장한다.
	void MakeTextFile(char* filename, long flag);	//MFT 속성을 text 파일로 저장.

};

_mft_reader_private.cpp

#include"_MFT_READER.h"

void _MFT_READER::LoadMFT()
{
	unsigned __int64 point,i,j,k,temp;
	unsigned __int64 HeaderSize;
	unsigned __int64 offset;

	PFILE_RECORD_HEADER $MFT;
	BytesPerFileRecord = boot_block.ClustersPerFileRecord < 0x80? boot_block.ClustersPerFileRecord* boot_block.SectorsPerCluster* boot_block.BytesPerSector : 1 << (0x100 - boot_block.ClustersPerFileRecord);
	$MFT = PFILE_RECORD_HEADER(new U8[BytesPerFileRecord]);
	if(!$MFT)
	{
		ErrorCode=OUT_OF_MEMORY_ERROR;
		return;
	}

	ReadSector((boot_block.MftStartLcn) * boot_block.SectorsPerCluster,	BytesPerFileRecord / boot_block.BytesPerSector, $MFT);

	for(j=1;j<=*((unsigned short*)((unsigned char*)$MFT+6));j++)
	{
		if(	*((char*)$MFT+j*boot_block.BytesPerSector-2)==
			*((char*)$MFT+*((unsigned short*)((unsigned char*)$MFT+4)))
			&&
			*((char*)$MFT+j*boot_block.BytesPerSector-1)==
			*((char*)$MFT+*((unsigned short*)((unsigned char*)$MFT+4))+1)
			)
		{
		*((char*)$MFT+j*boot_block.BytesPerSector-2)=
			*((char*)$MFT+*((unsigned short*)((unsigned char*)$MFT+4))+2*j);
		*((char*)$MFT+j*boot_block.BytesPerSector-1)=
			*((char*)$MFT+*((unsigned short*)((unsigned char*)$MFT+4))+2*j+1);
		}
	}

	point=*((unsigned short*)((unsigned char*)$MFT+20));//Offset으로 포인터 이동
	while(*((unsigned long*)((unsigned char*)$MFT+point))!=0xFFFFFFFF)
	{
		/*
			*((unsigned char*)MFT+point+9) = Attribute Name Size
			Attribute Header size : Resident=24 / Non-resident=64
		*/
		if(*((unsigned char*)$MFT+point+8))
			HeaderSize=64+*((unsigned char*)$MFT+point+9);
		else
			HeaderSize=24+*((unsigned char*)$MFT+point+9);


		switch(*((unsigned long*)((unsigned char*)$MFT+point)))
		{
		case 0x80://$DATA
			MFT=PFILE_RECORD_HEADER(new U8[*((unsigned __int64*)((unsigned char*)$MFT+point+40))]);
			if(!MFT)
			{
				delete $MFT;
				ErrorCode=OUT_OF_MEMORY_ERROR;
				return;
			}
			i=*(short*)((unsigned char*)$MFT+point+32);
			MFTLength=ReadCluster((unsigned char*)$MFT+point+i,(unsigned char*)MFT);
			break;
		}
		point+=*((unsigned long*)((unsigned char*)$MFT+point+4));
	}
	delete $MFT;
}

void _MFT_READER::ReadSector(U64 sector, U32 count, void* buffer)
{
	ULARGE_INTEGER offset;
	OVERLAPPED overlap = {0};
	U32 n;
	
	offset.QuadPart = sector * boot_block.BytesPerSector;
	overlap.Offset = offset.LowPart; 
	overlap.OffsetHigh = offset.HighPart;
	ReadFile(hVolume, buffer, count * boot_block.BytesPerSector, &n, &overlap);
}


long _MFT_READER::ReadAttribute(FILE* fp, unsigned char* point, long flag)
{
	unsigned char* offset=0;
	SYSTEMTIME time;
	int i,sub_mask;

	sub_mask=1;
	for(i=1;i<25;i++)
	{
		if(sub_mask&flag && *(long*)point==0x10*i)
		{
			if(*((unsigned char*)point+8))
			{
				if(*((unsigned __int64*)((unsigned char*)point+40)))
					offset=(new U8[*((unsigned __int64*)((unsigned char*)point+40))]);
				else
					offset=0;
				if(offset)
					ReadCluster(point+(*(short*)((unsigned char*)point+32)),offset);
			}
			else
			{
				offset=point+24+*((unsigned char*)point+9);
			}
			
		}
		sub_mask<<=1;
	}

	if(!offset)
		return *(long*)((unsigned char*)point+4);

	

	if(!((*(long*)point)&0xFFFFFF00))
	{
		switch(*(long*)point)
		{
			case 0x10://Standard Information
				fprintf(fp,"Attribute type : Standard Information\n");

				FileTimeToSystemTime((FILETIME*)offset,&time);
				fprintf(fp,"File 생성 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);

				FileTimeToSystemTime((FILETIME*)(offset+8),&time);
				fprintf(fp,"File 수정 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);

				FileTimeToSystemTime((FILETIME*)(offset+24),&time);
				fprintf(fp,"File 접근 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);

				break;

			case 0x20://Attribute List
				fprintf(fp,"Attribute type : Attribute list\n");
				break;

			case 0x30://File Name
				fprintf(fp,"Attribute type : File Name\n");

				FileTimeToSystemTime((FILETIME*)(offset+8),&time);
				fprintf(fp,"File 생성 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);

				FileTimeToSystemTime((FILETIME*)(offset+16),&time);
				fprintf(fp,"File 이름 수정 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);

				FileTimeToSystemTime((FILETIME*)(offset+32),&time);
				fprintf(fp,"File 접근 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);

				fprintf(fp,"File Name Size : %d\n",*((unsigned char*)offset+64));	
				fprintf(fp,"File NameSpace : ");
				switch(*((unsigned char*)offset+65))
				{
				case 0:
					fprintf(fp,"POSIX\n");
					break;
				case 1:
					fprintf(fp,"Win32\n");
					break;
				case 2:
					fprintf(fp,"DOS\n");
					break;
				case 3:
					fprintf(fp,"Win32 & DOS\n");
					break;
				default:
					fprintf(fp,"Unkown\n");
					break;
				}

				fprintf(fp,"File Name : ");
				fwprintf(fp,L"%s",((unsigned char*)offset+66));
				fprintf(fp,"\n");
				break;

			case 0x40://Volume Version
				break;

			case 0x50://Object ID
				break;

			case 0x60://Security
				break;
		}
	}

	if(*((unsigned char*)point+8))
	{
		delete offset;
	}

	if(*(long*)((unsigned char*)point+4))
		return *(long*)((unsigned char*)point+4);
	else
		return 0;
}

//*
__int64 _MFT_READER::ReadCluster(unsigned char* point,unsigned char* info)
{
		int i=0,j=0,k;
		__int64 offset=0,temp;
		__int64 length=0;
		while(*(point+i))
		{
			length=0;
			for(k=0;k<(*(point+i)&0x0F);k++)
			{
				length<<=8;
				length+=*((point+i)+(*(point+i)&0x0F)-k);
			}

			temp=offset;	//*오프셋값은 이전 값들과 합계로 계산됨.
			offset=0;
			for(;k<(*(point+i)&0x0F)+((*(point+i)&0xF0)>>4);k++)
			{
				offset<<=8;
				offset+=*((point+i)+(*(point+i)&0x0F)+((*(point+i)&0xF0)>>4)-k+(*(point+i)&0x0F));
			}
//*
			if(offset&(0x80<<(8*(((*(point+i)&0xF0)>>4)-1))) && ((*(point+i)&0xF0)>>4)<8)
			{
				offset=offset^(0x80<<(8*(((*(point+i)&0xF0)>>4)-1)));
				offset=-offset;
			}

//*/
			offset+=temp;

			ReadSector(offset * boot_block.SectorsPerCluster,
				length * boot_block.SectorsPerCluster,
				info+j*boot_block.BytesPerSector*boot_block.SectorsPerCluster);

			i+=(*(point+i)&0x0F)+((*(point+i)&0xF0)>>4)+1;
			j+=length;
		}
		return j;
}
//*/

_mft_reader_public.cpp

#include"_MFT_READER.h"

void _MFT_READER::MakeBinaryFile(char* filename)
{
	FILE* fp;
	fp=fopen(filename,"w");
	if(!fp)
	{
		printf("error");
		return;
	}
	fwrite((void*)MFT,BytesPerFileRecord,MFTLength,fp);
	fclose(fp);
}

void _MFT_READER::MakeTextFile(char* filename, long flag)
{
	FILE *fp=fopen(filename,"w");
	long filecounter=0;
	long i,j,k;

	for(i=0;i<MFTLength*boot_block.BytesPerSector*boot_block.SectorsPerCluster/BytesPerFileRecord;i++)
	{
		if(	((unsigned char*)MFT+i*BytesPerFileRecord)[0]!='F'
			||
			((unsigned char*)MFT+i*BytesPerFileRecord)[1]!='I'
			||
			((unsigned char*)MFT+i*BytesPerFileRecord)[2]!='L'
			||
			((unsigned char*)MFT+i*BytesPerFileRecord)[3]!='E'
			)
			continue;

		//하위 엔트리 필터링
//		if(*((int*)((unsigned char*)MFT+i*BytesPerFileRecord+32)))
//			continue;

		filecounter++;

		fprintf(fp,"MFT's Signaturer : %s\n", ((unsigned char*)MFT+i*BytesPerFileRecord));//+0x27);
		fprintf(fp,"Number of this MFT Entry : 0x%02x%02x%02x%02x\n"
			, *((unsigned char*)MFT+i*BytesPerFileRecord+47),*((unsigned char*)MFT+i*BytesPerFileRecord+46),
			*((unsigned char*)MFT+i*BytesPerFileRecord+45),*((unsigned char*)MFT+i*BytesPerFileRecord+44));


		//offset_array
		for(j=1;j<=*((unsigned short*)((unsigned char*)MFT+i*BytesPerFileRecord+6));j++)
		{
			if(	*((char*)MFT+i*BytesPerFileRecord+j*boot_block.BytesPerSector-2)==
				*((char*)MFT+i*BytesPerFileRecord+*((unsigned short*)((unsigned char*)MFT+i*BytesPerFileRecord+4)))
				&&
				*((char*)MFT+i*BytesPerFileRecord+j*boot_block.BytesPerSector-1)==
				*((char*)MFT+i*BytesPerFileRecord+*((unsigned short*)((unsigned char*)MFT+i*BytesPerFileRecord+4))+1)
				)
			{
			*((char*)MFT+i*BytesPerFileRecord+j*boot_block.BytesPerSector-2)=
				*((char*)MFT+i*BytesPerFileRecord+*((unsigned short*)((unsigned char*)MFT+i*BytesPerFileRecord+4))+2*j);
			*((char*)MFT+i*BytesPerFileRecord+j*boot_block.BytesPerSector-1)=
				*((char*)MFT+i*BytesPerFileRecord+*((unsigned short*)((unsigned char*)MFT+i*BytesPerFileRecord+4))+2*j+1);
			}
		}



		j=*((unsigned short*)((unsigned char*)MFT+i*BytesPerFileRecord+20));//Offset to First Attribute Header

		while(!(*((unsigned long*)((unsigned char*)MFT+i*BytesPerFileRecord+j))&0xFFFFFF00))
		{
			j+=ReadAttribute(fp,(unsigned char*)MFT+i*BytesPerFileRecord+j,flag);
		}
		fprintf(fp,"\n");



		//offset_array
		for(j=1;j<=*((unsigned short*)((unsigned char*)MFT+i*BytesPerFileRecord+6));j++)
		{
			if(	*((char*)MFT+i*BytesPerFileRecord+j*boot_block.BytesPerSector-2)==
				*((char*)MFT+i*BytesPerFileRecord+*((unsigned short*)((unsigned char*)MFT+i*BytesPerFileRecord+4))+2*j)
				&&
				*((char*)MFT+i*BytesPerFileRecord+j*boot_block.BytesPerSector-1)==
				*((char*)MFT+i*BytesPerFileRecord+*((unsigned short*)((unsigned char*)MFT+i*BytesPerFileRecord+4))+2*j+1)
				)
			{
			*((char*)MFT+i*BytesPerFileRecord+j*boot_block.BytesPerSector-2)=
				*((char*)MFT+i*BytesPerFileRecord+*((unsigned short*)((unsigned char*)MFT+i*BytesPerFileRecord+4)));
			*((char*)MFT+i*BytesPerFileRecord+j*boot_block.BytesPerSector-1)=
				*((char*)MFT+i*BytesPerFileRecord+*((unsigned short*)((unsigned char*)MFT+i*BytesPerFileRecord+4))+1);
			}
		}

	}
	fprintf(fp,"Bytes of Files : %d\n",i*BytesPerFileRecord);
	fprintf(fp,"A number of Files : %d\n",filecounter);
	fclose(fp);
}


int _MFT_READER::LastErrorCode()
{
	return ErrorCode;
}

최종 수정 날짜 : 5/1

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:28:51
Processing time 0.0117 sec