내용

1.FAT 파일시스템으로 포맷하기

1) 파일 시스템 선택

-  저장장치를 포맷을 할땐 어떤 파일시스템을 사용할  결정 해야하고, FAT12, FAT16, FAT32 결정하는 요소  가장 중요한 것은 클러스터의 개수이며, 각각의 파일 시스템들은 그에 맞는 클러스터 개수의 범위가 정해져 있다.

 

[파일시스템의 클러스터 개수 범위]

파일 시스템

클러스터 개수 범위

FAT 12

~ 4084

FAT 16

4085 ~ 65524

FAT 32 

65525 ~

 

- FAT12 경우 클러스터 개수가 4084 넘는 것은 없고, 4085~ 65524사이의 클러스터 개수를 가진 FAT 16파일시스템도 없다.

- 만약  규칙을 어길 경우 Windows 볼륨을 제대로 인식하지 않는다.

 

클러스터개수를 1,2,6,10 혹은 16 모자라거나 많게 FAT 형태를 계산하는 코드들도 있기 때문에 기존 FAT 코드들과 최대한 호환되는 FAT 볼륨을 생성을 위해선 4085 65525 근처보다는 최소 16클러스터 이상 떨어뜨리는 것이 좋다.

 

- FAT 32파일 시스템의 경우 최소 32MB 이상은 되어야 하게 된다. 최소 클러스터 65526 X 512byte = 33,548,800Byte ( 31.9MB)

- FAT 16 경우 4085 X 512 = 2,091,520Byte( 1.9MB)  최소크기가 매우 작다는    있다.

- 32MB 이하는 FAT 16 파일시스템밖에 선택   없을 것이고, 2GB 넘어가면 FAT 32파일시스템 밖에 선택할  없지만, 32MB ~ 2GB 사이라면 FAT16 FAT32 파일시스템 중에서 선택할  있게 된다.

- 다시 한번 볼륨 용량에 따른 클러스터 크기를 알아보자

 

[Windows 2000 기준]

볼륨 크기

FAT16 클러스터 크기

FAT32 클러스터 크기

NTFS 클러스터 크기

16MB ~ 32MB

512Byte

지원  

512Byte

32MB ~ 63MB

1KB

512Byte

512Byte

64MB ~ 128MB

2KB

1KB

512Byte

128MB ~ 256MB

4KB

2KB

512Byte

256MB ~ 512MB

8KB

4KB

512Byte

512MB ~ 1GB

16KB

4KB

1KB

1GB ~ 2GB

32KB

4KB

2KB

2GB ~ 4GB

64KB()

4KB

4KB

4GB ~ 8GB

지원  

4KB

4KB

8GB ~ 16GB

지원  

8KB

4KB

16GB ~ 32GB

지원  

16KB

4KB

32GB ~ 2TB

지원  

인식 가능 ()

4KB

 

2) FAT 영역 크기 구하기

- Microsoft에서 제공하는 공식문서에 따른 계산 법이지만 정확한 계산을 해주진 않는다.

- 때때로 FAT16에서 2섹터, FAT 32에서 8섹터를 잡는 경우가 있으나 FAT 영역의 크기를 작게 잡는 일은 없다.

- 섹터가  개가 낭비된다는 것을 제외하곤 FAT 영역을 약간 크게 잡는다고 문제될 것은 없다.

RootDirSecCnt = ((RootEntCnt * 32) + (BytesPerSec -1)) / BytesPerSec;

TmpVal1 = VolumeSize – (ReservedSecCnt + RootDirSecCt);

TmpVal2 = (256 * SecPerClus) + NumFATs;

if(FATType == FAT32)

    TmpVal2 = TmpVal2 / 2;

FATSize = (TmpVal1 + (TmpVal2 – 1)) / TmpVal2;

 

3) 부트 레코드 생성

- 클러스터 크기와 개수가 결정되었다면 부트 레코드를 생성한다.

- FAT16 FAT32 파일시스템의 부트레코드 형태에 맞게 생성한다.

 

4) 예약된 영역 생성

- 예약된 영역으로 지정된 섹터들을 전부 '0'으로 초기화 시킨다.

- FAT32 경우 예약된 영역에 FSInfo 구조체를 담기 때문에 이를 생성 한다.

 

5) FAT영역 생성

- 크기를 구한 FAT 영역을 모든 클러스터가 비었음을 의미하는 값을 갖도록 전부 '0'으로 초기화 시킨다.

- FAT32 파일시스템이라면 Cluster 0 Entry : 0x0FFFFFF8, Cluster 1 Entry : 0x0FFFFFFF 바꾼다.

- FAT16파일시스템이라면 Cluster 0 Entry : 0xFFF8, Cluster 2 Entry : 0xFFFF 바꾼다.

- 클러스터의 개수가 섹터단위로 정확히 나눠 떨어지는 경우는 거의 없기 때문에 마지막 섹터의 뒷부분은 클러스터가 없는  영역으로  것이고  부분도 전부 '0'으로 초기화시켜야 한다.

 

6)루트 디렉토리 생성

- 루트 디렉토리 영역에 해당하는 섹터를 전부 0으로 초기화 시킨다.

- FAT32 경우 루트 디렉토리에 섹터를 전부 0으로 초기화 시키면서 해당 클러스터의 Entry 값을 0x0FFFFFFF 바꾸어 해당 클러스터는 사용 중이라고 표시한다.

- 루트 디렉토리 생성시 볼륨 레이블을 지정하고 싶을 경우 초기화  Label Directory Entry 집어넣는다.

 

 

2. 파일시스템 알아내기

- 특정 볼륨의 파일 시스템을 알아내기 위해서는 클러스터의 개수를 얻어서 분석하는 방법이 가장 정확한 방법이다. 가장 위의 표를 참고하자.

- 클러스터 개수 등의 정보를 얻기 위해선 부트 레코드를 분석해야 하는데 FAT32 FAT16 부트 레코드 형태가 다르기 때문에  부분을 정확히 읽기 위한 조사 방법을 알아보자

FAT32 경우 부트 레코드의 FATSize 16값은 반드시 0이다.

FAT32 경우 Root Dir Entry Count 항목 값이 반드시 0 이다.

- 단순히 OEM Name 항목이나 File System Type 읽는 것은 매우 위험하다. 단순한 문자열일  속성이 아니다.

 

 

3. 다음 클러스터 번호 알아내어 섹터 찾기

- FAT 테이블을 조사하여 다음 클러스터의 위치 등을 알아야 한다.

- n 클러스터 FAT Entry   번째 FAT 섹터에 위치하는지,  번째 Entry n  클러스터의 Entry인지 알아내는 것이 중요할 것이다.

- 아래 소스에서 ThisFATSecNum  n 번째 FAT Entry 섹터 번호이고, ThisFATEntOffet 섹터 안에서 n번째 Entry 위치 값이다.

U32    FATOffset, tmpFATSecNum, ThisFATSecNum, ThisFATEntOffset;

 

if(FATType == FAT16)

    FATOffset = N * 2;

else if(FATType = FAT32)

    FATOffset = N *4;

 

tmpFATSecNum = FATOffset / BytePerSec;

ThisFATSecNum = VolBeginSec + ReservdSecCnt + tmpFATSecNum;

 

if(FATType == FAT16)

    ThisFATEntOffset = N - (tmpFATSecNum * 256);

else if

    ThisFATEntOffset = N - (tmpFATSecNum * 128);

 

- n번째 FAT Entry 안의 값을 얻어야 한다. FAT Table다음 클러스터 번호를 얻어보자.

- 아래 소스에서 FAT16ClusEntryVal, FAT32ClusEntryVal 값이 n 클러스터와 연결된 다음 클러스터 번호가 된다.

 

U16 FAT16FATSec[256], FAT16ClusEntryVal;

U32 FAT32FATSec[128], FAT32ClusEntryVal;

 

if(FATType == FAT16){

    HDD_read(Drive, ThisFATSecNum, 1, (char*)FAT16FATSec);

    FAT16ClusEntryVal = FAT16FATSec[ThisFATEntOffset];

}else{

    HDD_read(Drive, ThisFATSecNum, 1, (char*)FAT32FATSec);

    FAT32ClusEntryVal = FAT32FATSec[ThisFATEntOffset] & 0x0FFFFFFF;

 

- 최종 섹터 주소로 변환한  해당 섹터를 읽어야 한다.

- 클러스터 번호를 섹터 주소로 변환하는 소스를 알아보자

U32 FirstSecOfThisClus;

if(FATTYPE == FAT16)

    FirstSecOfThisClus = ((FAT16ClusEntryVal - 2) * SecPerClus) + FirstDataSector;

else

    FirstSecOfThisClus = ((FAT32ClusEntryVal - 2) * SecPerClus) + FirstDataSector;

-  소스에서 ClusEntrVal - 2하는 이유는 클러스터의 0번과 1번은 사용하지 데이터 영역의  번째 클러스터가 2번이기 때문이다.

 

 

4. 디렉토리 엔트리 추가

- 새로운 파일이나 하위 디렉토리 생성시  볼륨에 기록하는 작업 외에도 새로운 디렉토리 엔트리를 생성하고, 정보를 나타내야 한다.

[ "File"이라는 폴더에 "Forensic.txt"  추가하는 경우 ]

1) "File" 디렉토리 내에 "Forensic.txt" 파일이 있는지 조사

2) 비어있는 공간을 찾기 위해 Name[0] 값이 0 나올 때까지 "File" 디렉토리의 내용 조사

3) 만약 디렉토리 끝까지 조사하였을  비어 있는 엔트리가 없다면 새로운 클러스터를 할당 받아 디렉토리 크기를 늘린다.

4) 새로운 디렉토리 엔트리를 추가하고, Long File Name 필요하면 Long File Name Entry 추가한다.

 

- 디렉토리를 끝까지 조사 했는데 비어 있는 엔트리가 없을 경우 새로 클러스터를 할당 받는데 새로 할당 받지 않고 Name[0xE5] 경우  디렉토리 엔트리를 덮어쓰는 방법도 있다. 그러나 이럴 경우 삭제된 파일의 정보가 사라져 삭제된 파일의 복구가 어려워 진다.

 

FAT 16 파일시스템의 경우 루트 디렉토리가  찼다면 클러스터를 할당하는 방법으로 루트 디렉토리의 크기를 늘릴  없다. FAT 16에서 루트 디렉토리 크기는 고정되어 있다.

 

 

5. 하위 디렉토리 생성

- FAT 파일시스템에서 루트 디렉토리를 제외한 모든 디렉토리들은 자신의 상위 디렉토리를 가지고 있다.

- 특수한 디렉토리 엔트리인 '.' '..' 디렉토리 엔트리를 통해 자신의 상위 디렉토리 위치를 기억한다.

- 루트 디렉토리를 제외한 모든 디렉토리들은 생성 시에 '.' '..' 디렉토리 엔트리를  번째와 두번째 엔트리에 필수적으로 생성해 주어야 하며, '.' 디렉토리 엔트리는 자신, '..' 디렉토리 엔트리는 상위 디렉토리를 가리키는 디렉토리 엔트리이다.

- 첫번째 클러스터 값을 해당 디렉토리 엔트리 First Cluster항목 값에 저장한다는 의미가 가리킨다는 말이다.

 

[디렉토리 계층의 ]

 

- 하위 디렉토리 생성 방법

1) FAT Table 조사하여  클러스터의 번호를 얻는다.

2) 찾은  클러스터 영역을 모두0으로초기화 한다.

3) 초기화된 클러스터에  번째로 자신을 가리키는 '.' 디렉토리 엔트리를 생성한다.

4)  번째 엔트리에 자신의 상위 디렉토리를 가리키는 '..' 디렉토리 엔트리를 생성한다.

5) FAT Table 해당 클러스터 FAT Entry 값을 EOC 바꾸어 준다.

6) 상위 디렉토리에 방금 생성한 디렉토리를 가리키는 디렉토리 엔트리를 추가한다.

 

- 디렉토리를 생성할 경우 디렉토리 엔트리 들은 FileSize 항목 값을 0으로 해야 하며, 따라서 디렉토리의 크기를 조사할 때는 파일처럼 바로 크기를   없고, 디렉토리 크기 조사  경우 FAT Entry 항목의 EOC 값을 이용해야 한다.

 

6. 새로운 파일 생성

- 파일 생성도 하위 디렉토리 생성처럼 비슷하다.

1) FAT Table 조사하여  클러스터의 번호를 얻어낸다.

2) 찾아낸  클러스터 영역에 파일의 내용을 적는다.

3) 클러스터에 파일의 내용을  적었다면  다른  클러스터를 찾기

4) 마지막으로 파일 내용을 적은 클러스터의 FAT Entry 찾아낸  클러스터 번호를 적는다.

5) 파일의 내용을  적을 때까지 1~4 작업 진행

6) 마지막으로 사용된 클러스터의 FAT Entry 값에 EOC 적는다.

7) 상위 디렉토리에 새로 생성한 파일의 정보를 담은 디렉토리 엔트리를 추가한다.

 

- 새로 생성한 파일의 정보를 담은 디렉토리 엔트리 생성시 First Cluster 항목에 파일의 내용을 담은  번째 클러스터 번호를 적어주고, 파일의 크기를 File Size 기록 해야 한다.

- 파일을 새로 생성할 경우 동시에 여러 클러스터를 사용하는 경우가 많은데 이럴 경우 비어있는 클러스터를 계속 찾아 파일의 내용을 쓰되, FAT 테이블에 파일의 클러스터 연결고리를  적어줘야 한다.

 

 

7. 파일 또는 디렉토리 삭제

1) 해당 디렉토리 엔트리의 Name[0] 값을 0xE5 바꾼다.

2) 해당 파일이 Long File Name 가지고 있을 경우 모든 Long File Name Entry Order 항목 값을 0xE5 바꾼다.

3) 해당 파일에 연결되어 있던 클러스터들의 FAT Entry 값을 전부 Free Cluster 값으로 바꾸어 준다.

 

8. 주의 사항

1) 디렉토리  파일 개수 제한

- 파일 내의 디렉토리 개수 제한이 없지만 FAT 코드들은 디렉토리 엔트리 개수를 U16(unsigned Short)형으로 제한하는 경우가 많다.

  엔트리의 개수가 65,535 보다 적어야 한다. 그러나  디렉토리를 생성할 경우 파일 생성   마다 생성할 파일의 이름이 존재하는지

모든 Directory Entry  조사해야 하기 때문에 효율적이지 못하다.

 

2) 파일의 최대 크기

- Directory Entry 항목으로 FileSize 항목은 4바이트이며, 최대 4GB(232)까지 하나의 파일로 가질  있다.

 

3) 마지막 클러스터의 크기 FAT Entry 위치

- 볼륨 마지막 FAT Entry위치를 FAT 영역의 마지막 섹터의 가장 뒷부분의 위치한 FAT Entry 단정 짓는 경우가 많은데 문제점이 발생할  있다. 볼륨의 마지막 FAT Entry인지 아닌지는 FAT Entry 번호로 판단을 해야 한다.

FAT16 파일시스템에서 볼륨의  클러스터 개수가 5000 라면

FAT 영역은  20 섹터이며 136번째 FAT Entry 클러스터 5000번과 대응 하는 볼륨의 마지막 FAT Entry 되며  뒤는 의미가 없다.

FAT 16 경우 클러스터 주소 2bit 나타냄

 1섹터당 주소 (512byte / 2bit) = 256개씩 들어감

256 x 19 + 136 = 5000

20번째 섹터의 136bit까지 사용하고 나머지는 376bit 사용  .

 부분을 FAT Entry 단정하면 안됨

 

9. 실습

- USB 같은 곳을 FAT 16으로 포맷을 하자.

 

포맷을   TEST.TXT 라는 파일을 FAT16으로 포맷한 드라이브에 넣어놓도록 하자.

 

Visual Studio 2012 관리자 권한으로 실행한다.

   

관리자권한으로 실행

프로젝트 속성  구성 속성  일반 -> 프로젝트 기본값  문자집합 : 멀티 바이트 문자 집합 사용

   

#include <stdio.h>

#include <windows.h>

#include <stdlib.h>

#pragma pack(1)     //컴파일러에게 구조체 패딩을 넣지 말라고 선언

 

 

#define U8        unsigned char

#define S8        char

#define U16        unsigned short

#define U32        unsigned int

#define U64        unsigned __int64

 

typedef struct _DIR_struct{     //Directory Entry 구조체

    U8            Name[11];

    U8            Attr;

    U8            NTres;

    U8            CrtTimeTenth;

    U16        CrtTime;

    U16        CrtDate;

    U16        LstAccDate;

    U16        FstClusHi;

    U16        WriteTime;

    U16        WriteDate;

    U16        FstClusLow;

    U32        FileSize;

}DirEntry;

 

typedef struct _File_struct{    //파일 구조체 선언

    U32    curCluster;

    U32    FileSize;

    U32    FileRestByte;

    U32    ClusRestByte;

    U8*    ClusBuf;

}FileStruct;

 

 

typedef struct _FAT16_BPB_struct{     //FAT16 부트 레코드 선언

    //공통 영역

    U8            JmpBoot[3];

    U8            OEMName[8];

    U16        BytsPerSec;

    U8            SecPerClus;

    U16        RsvdSecCnt;

    U8            NumFATs;

    U16        RootEntCnt;

    U16        TotSec16;

    U8            Media;

    U16        FATs16;

    U16        SecPerTrk;

    U16        NumHeads;

    U32        HiddSec;

    U32        TotSec32;

    //FAT 16영역

    U8            DirveNumber;

    U8            Reserved1;

    U8            BootSignal;

    U32        VolumeID;

    U8            VolumeLabel[11];

    U8            FileSysType[8];

 

    U8            BootCodeArea[448];

 

    U16        Signature;

}FAT16_BPB;

#pragma pack()

 

typedef struct _VOL_struct{     //볼륨의 전반적인 정보를 담는 구조체

    U32        Drive;

    U32        VolBeginSec;

    U32        FirstDataSec;

    U32        RootDirSec;

    U32        RootEntCnt;

    U32        RootDirSecCnt;

    U32        FATSize;

    U32        FATStartSec;

    U32        TotalClusCnt;

    U32        TotalSec;

    U32        DataSecSize;

    U32        ClusterSize;

    U32        SecPerClus;

}VolStruct;

 

U32 HDD_read (U8 drv, U32 SecAddr, U32 blocks, U8 *buf);

U32 read_file(FileStruct* pFile, U32 read_size, U8* buf);

U32 open_file(char* FileName, char* FileExtender, DirEntry* pDir, FileStruct* pFile);

U32 get_BPB_info(FAT16_BPB* BPB, VolStruct* pVol);

U32 clus_convTo_sec(U32 clusterNum);

U32 get_next_cluster(U32 curCluster);

 

VolStruct gVol;

 

int main(void){

    U8        buf[512];

    U8    *    pRootBuf;

    U32    readBytes;

    FileStruct readFile;

    FILE*        outFile;

 

    gVol.Drive = 0x2; //드라이브 설정

    gVol.VolBeginSec = 0x87; //부트 레코드 섹터

 

    //저장장치로부터 부트 레코드 섹터를 읽어 buf에 담기.

    if(HDD_read(gVol.Drive, gVol.VolBeginSec, 1, buf) == 0){

        printf("Boot Sector Read Failed \n");

        return 1;

    }

 

    //읽은 buf를 처리한 뒤, gVol 변수에 담는다. 파일시스템이 맞지 않으면 에러

    if(get_BPB_info((FAT16_BPB*)buf, &gVol) == 0){

        printf("It is not FAT16 File System \n");

        return 1;

    }

 

    //루트 디렉토리를 읽어 메모리에 할당.

    pRootBuf = (U8*)malloc(gVol.RootDirSecCnt * 512);

 

    //저장장치로부터 루트 디렉토리의 섹터를 읽어 메모리에 올림

    if(HDD_read(gVol.Drive, gVol.RootDirSec, gVol.RootDirSecCnt, pRootBuf)==0){

        printf("Root Dir Read Failed \n");

        return 1;

    }

 

    //루트 디렉토리에서 test.txt파일을 찾아 readFile 구조체에 정보를 담는다

    if(open_file("TEST","TXT",(DirEntry*)pRootBuf, &readFile) != 0){

        printf("File Find Error\n");

        return 1;

    }

    

    //C드라이브에 test.txt파일을 생성할 준비를 한다.

    fopen_s(&outFile,"c:\\test.txt","wb");

    if(outFile == NULL){

        printf("Can't Create File \n");

        return 1;

    }

 

    //저장장치에 있는 test.txt 파일로부터 512Byte를 읽어 더 이상 읽을게 없을 때 까지 C로 복사

    do{

        readBytes = read_file(&readFile, 512, buf);

        fwrite(buf,readBytes,1,outFile);

    }while( readBytes!=0);

 

    fclose(outFile);

 

    return 0;

}

 

U32 read_file(FileStruct* pFile, U32 read_size, U8* buf) {

    U32        bkFileRestByte = 0;

    U32        curClusStartSec = 0;

    U32        ThisClusOffset = 0;

    U32        ThisReadBytes = 0;

 

    //파일을 어디까지 읽었는지 저장

    bkFileRestByte = pFile->FileRestByte;

 

    while(1){     //클러스터를 더 읽을 바이트가 남았는지 조사, 더 이상 없으면 다음 클러스터를 읽음

        if(pFile->ClusRestByte ==0){

 

            curClusStartSec = clus_convTo_sec(pFile->curCluster);

 

            if(HDD_read(gVol.Drive, curClusStartSec, gVol.SecPerClus, pFile->ClusBuf) == 0)

                return 0;

            pFile->curCluster = get_next_cluster(pFile->curCluster);

            pFile->ClusRestByte = gVol.ClusterSize;

        }

 

        //클러스터의 어느 부분을 읽어야 하는지 찾아 변수(ThisClusOffset)에 저장

        ThisClusOffset = gVol.ClusterSize - pFile->ClusRestByte;

 

        //파일을 읽을 크기인 read_size 변수의 크기가 남은 파일 크기보다 큰 경우 남은 크기 저장

        read_size = (read_size >= pFile->FileRestByte)? pFile->FileRestByte : read_size;

        ThisReadBytes = (read_size >= pFile->ClusRestByte)? pFile->ClusRestByte : read_size;

 

        //읽은 바이트 수가 0이 아니면 더 남아있기 때문에 계속 일어 내용을 옴겨 담음

        if(ThisReadBytes != 0){

            memcpy(buf, &pFile->ClusBuf[ThisClusOffset], ThisReadBytes);

            pFile->ClusRestByte -= ThisReadBytes;

            pFile->FileRestByte -= ThisReadBytes;

            read_size -= ThisReadBytes;

        }else

        //읽은 바이트 수가 0이면 다 읽었기 때문에 리턴, 실제로 몇 바이트 읽었는지 리턴

            return bkFileRestByte - pFile->FileRestByte;

    }

}

 

U32 open_file(char *FileName, char* FileExtender, DirEntry* pDir, FileStruct* pFile)

{

    U32 i;

    char compFile[11];

 

    //사용자가 넘겨준 파일명과 확장자를 FAT 파일 시스템 형태로 변환

    memset(compFile, 0x20, sizeof(compFile));

    memcpy(&compFile[0], FileName, strlen(FileName));

    memcpy(&compFile[8], FileExtender, strlen(FileExtender));

 

    //찾는 파일이 있는지 계속 조사. Name[0]이 0을 만나면 파일을 못찾고 Entry 검색한 경우.

    //0xE5의 경우 삭제된 Entry므로 건너 뛴다.

    for(i=0; i<=gVol.RootEntCnt ; i++){

        switch( (U8) pDir[i].Name[0]){

        case 0x00 : break;

        case 0xE5 : continue;

        }

 

    //현재 Directory Entry의 Attrivute 값이 0x0F이면 Long File Name Entry이기 때문에 조사

        if(pDir[i].Attr != 0x0F){

            //찾아낸 Directory Entry Name 항목과 사용자가 검색한 파일명 비교

            //일치할 경우 넘어온 파일 포인터에 해당하는 파일 정보를 담기

            if( (memcmp(pDir[i].Name, compFile, sizeof(compFile))) ==0){

                pFile->curCluster = pDir[i].FstClusLow | pDir[i].FstClusHi << 16;

                pFile->FileSize = pDir[i].FileSize;

                pFile->FileRestByte = pFile->FileSize;

                pFile->ClusRestByte = 0;

                pFile->ClusBuf = (U8*)malloc(gVol.ClusterSize);

 

                return 0;

            }

        }

    }

    return 1;

}

 

U32 get_next_cluster(U32 curCluster){

    U16 FATtable[256];

    U32 ThisFATSecNum, ThisFATEntOffset, tmpFATNum;

 

    //curCluster가 몇 번째 FAT 섹터인지 확인. FAT32라면 128로 나눔

    tmpFATNum = curCluster / 256;

    //실제 저장장치 상에서 FAT Table의 위치를 저장

    ThisFATSecNum = gVol.FATStartSec + tmpFATNum;

    //FAT Table의 섹터 내에서 curCluster FAT Entry 위치를 구한다. FAT32면 128을 곱한다.

    ThisFATEntOffset = curCluster - (tmpFATNum * 256);

 

    //FAT Table의 위치를 읽어 해당 FAT Entry 값을 리턴

    HDD_read(gVol.Drive, ThisFATSecNum, 1, (U8*)FATtable);

 

    return FATtable[ThisFATEntOffset];

}

 

U32 clus_convTo_sec(U32 clusterNum){

    //클러스터번호를 실제 섹터 주소 값으로 변환, 0,1번 클러스터는 사용하지 않고 Cluster 2번부터 사용

    return ((clusterNum -2 ) * gVol.SecPerClus) + gVol.FirstDataSec;

}

 

    //DATA 읽기

U32 HDD_read (U8 drv, U32 SecAddr, U32 blocks, U8* buf){

    U32 ret;

    U32 ldistanceLow, ldistanceHigh, dwpointer, bytestoread, numread;

 

    char cur_drv[100];

    HANDLE g_hDevice;

 

    sprintf_s(cur_drv,sizeof(cur_drv),"\\\\.\\PhysicalDrive%d",(U32)drv);

    g_hDevice=CreateFile(cur_drv, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

    

    if(g_hDevice==INVALID_HANDLE_VALUE)    return 0;

 

    ldistanceLow = SecAddr << 9;

    ldistanceHigh = SecAddr >> (32 - 9);

    dwpointer = SetFilePointer(g_hDevice, ldistanceLow, (long *)&ldistanceHigh, FILE_BEGIN);

    

    if(dwpointer != 0xFFFFFFFF)    {

        bytestoread = blocks * 512;

        ret = ReadFile(g_hDevice, buf, bytestoread, (unsigned long*)&numread, NULL);

        if(ret)    ret = 1;        

        else        ret = 0;        

    }

    

    CloseHandle(g_hDevice);

    return ret;

}

 

U32 get_BPB_info(FAT16_BPB* BPB, VolStruct* pVol){

    //Root Entry Count 항목 조사, 0이면 FAT16이므로 파일시스템 종류 알기 좋다.

    if(BPB->RootEntCnt == 0 || BPB->Signature != 0xAA55){

        return 0;

    }

    //부트 레코드 정보 얻기.

    if(BPB->TotSec16 !=0)    pVol->TotalSec = BPB->TotSec16;

    else                            pVol->TotalSec = BPB->TotSec32;

 

    //get FAT Size

    pVol->FATSize = BPB->FATs16;

 

    //get FAT Start Secotr

    pVol->FATStartSec = pVol->VolBeginSec + BPB->RsvdSecCnt;

 

    //get Root Dir Entry Count

    pVol->RootEntCnt = BPB->RootEntCnt;

    

    //get Root Dir Sector

    pVol->RootDirSec = pVol->VolBeginSec + BPB->RsvdSecCnt + (BPB->NumFATs * BPB->FATs16);

 

    //get Root Dir Sector Count

    pVol->RootDirSecCnt = ((BPB->RootEntCnt * 32) + (BPB->BytsPerSec -1 )) /BPB->BytsPerSec;

 

    //get FAT Start Sector

    pVol->FirstDataSec = pVol->VolBeginSec +BPB->RsvdSecCnt + (BPB->NumFATs * pVol->FATSize) + pVol->RootDirSecCnt;

 

    //get Size of Data Area

    pVol->DataSecSize = pVol->TotalSec - (BPB->RsvdSecCnt + (BPB->NumFATs * pVol->FATSize) + pVol->RootDirSecCnt);

 

    //get Total Cluster Count

    pVol->TotalClusCnt = pVol->DataSecSize / BPB->SecPerClus;

 

    //get Sector per Cluster

    pVol->ClusterSize = BPB->SecPerClus * BPB->BytsPerSec;

 

    //get Sector Per Cluster

    pVol->SecPerClus = BPB->SecPerClus;

 

    return 1;

}

[드라이브 설정]

위에 진하게 주석  부분에서 드라이브 설정을  

gVol.Drive = 0x2  것은 아래 D드라이브를 테스트 하려고  것이다.

   

만약 디스크0번을 분석하려면

gVol.Drive = 0x0 으로 설정 해야한다.

   

   

[부트레코드 섹터위치]

   

gVol.VolBeginSec = 0x87;

아래 스샷은 FTK Imager 확인을 해보았다.

 

[실행 화면]

그냥 컴파일  아무 것도 표시 되지 않으면 정상적으로 진행  것이다.

 

[FAT 16으로 포맷한 USB 있던 TEST.TXT]

 

[컴파일  복사된 C:\\TEST.TXT 파일]

열어보면 같은 내용이 있는걸   있다.

 

+ Recent posts