= _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