내용

1. 파일시스템 소개

1) 파일시스템의 탄생

[ FAT파일 시스템 변화 ]

 

- FAT 12 플로피디스크를 관리하는데 이용하기 위해 구현하게 되었다.

- Tim Paterson  QDOS 운영체제를 개발하면서 FAT 파일시스템으로 선택하면서 PC환경에 쓰이게 된다.

- FAT 경우 매우 단순한 구조를 가지고 있었고, 조금만 수정하면 32MB 이상 관리도   있을 거라 생각 했는데 PC환경에서도 충분한 용량으로 생각 했다.

[Thinks~]

IBM 개인용 컴퓨터 성능이 16bit CPU 충분하다고 생각 하는 바람에 32bit CPU 출시를 빼앗겼고, Microsoft 메모리의 크기를 640KB 충분하다고 생각해서 MS-DOS 사용한 유저들을 고통으로 몰아 넣게 .

- QDOS 나오면서 FAT파일시스템이 소개 되며, IBM Microsoft 넘어가면서 PC-DOS, MS-DOS 바꾸고, x86 PC 운영체제로 탐재되고, IMB x86 PC 엄청난 성공을 거두면서 표준처럼 자리잡고, 다른 PC 메이커들도 호환기존으로 만들어 내면서 MS-DOS 대중적인 OS 되었다. 따라서 자연스레 FAT 파일시스템이 가장 많이 쓰이는 파일시스템으로 자리 잡게 되었다.

 

2) FAT 12

- 80년에 나온 FAT 파일시스템의 최초 버전은 다른 버전과 구분하기 위해 FAT12라고 불리며 플로피디스크 파일저장을 위해 개발되었다.

- 당시 PC HDD 없고 5.25인치 플로피디스크가 대세였던 시절이였고, 최초로 발표된 FAT 12구조가 매우 단순해서, 디렉토리(Directory)라는 개념도 없었다.

- MS-DOS 2.0 나오면서 FAT12 계층형 디렉토리가 지원되고, 최근의 FAT파일시스템의 기본 구조가 갖추게 된다.

 

3) FAT 16

- 개인용 PC HDD 장착하는 경우가 많아지면서 HDD에서 사용할 파일시스템의 필요성이 증가고, FAT 16버전의 경우 비로서 HDD에사용할 만한 파일시스템이 되었다.

- 구조적으로 FAT 12 거의 동일하지만 FAT 16에서는 클러스터를 표현하는 비트수가 12개에서 16개로 늘어나면서 이론적으로 최대 216 65,535개의 클러스터를 표현할  있게 되었다.

- 이렇게 클러스터 크기를 32KB  경우 최대 2GB까지 표현   있었다. 이때는 평생 써도 남을 정도로 충분하다고 판단 했었다.

 

4) VFAT(Virtual FAT)

- Windows 95버전으 나오면서 FAT파일시스템의 성능  기능을 향상 시켰다.

- VFAT 또는 FAST FAT라고 불러야 하지만 사람들은 FAT 파일시스템이라 불렀다.

- 32Bit 보호모드(Protected Mode) 적합하게 코드  작성하여 성능향상을 시켰고, 독점모드(Exclusive Mode) 추가하여 동시에 여러 프로그램을 같은 파일을 접근할 경우에 대비하였다. 하지만 이는 파일시스템 구조라기 보단 OS 파일 시스템 처리 성능이 개선된 것이다.

- VFAT 경우 LFNs(Long File Names) 지원하여 파일명을 최대 255까지 적을  있게 되었다. 이전 버전의 경우 파일명이 최대 8byte 확장명은 최대 3byte 고작 이였고, 파일명과 확장명은 모두 대문자만 가능 했었다. LFNs 경우 이전 버전의 DOS와도 호환성을 가지면서 파일명의 길에 제한으로부터 자유로울  있게 되었다.

- 파일명의 최대 글자수는 늘어났지만 최대 용량은 여전히 2GB정도가 최대였다.

 

5) FAT 32

- 1996 FAT32버전이 출시되었고, VFAT 기반으로 수정하여 클러스터를 표현하는 bit 32개로 늘렸으나 최상위 4bit 예약 영역으로 사용되지 않고,  28bit 이용하여 클러스터를 표현한다.

- 이는 클러스터 크기를 16KB 하면 최대 4TB까지 가능한 용량이다.

- Windows 경우 FAT32 2TB까지 인식   있지만 여러 가지 이유로 최대용량을 32GB 제한하고 있다.

- 만약 Windows에서 32GB 이상되는 저장 장치를 사용하고 싶다면 NTFS 사용해야 한다.

 

6) FAT 파일시스템들의 비교

[FAT 파일 시스템 비교]

구분

FAT12

FAT16

FAT32

사용 용도

플로피 디스크용

저용량 하드디스크

고용량 하드디스크

클러스터 표현 비트 

12 bit

16bit

32bit(28bit 사용)

최대 클러스터 개수

4,084

65,524

 228 

최대 볼륨 크기

16MB

2GB

2TB

파일의 최대 크기

볼륨 크기 만큼

볼륨 크기 만큼

4GB

디렉토리당 최대 파일 개수

X

65,535

65,535ro

루트 디렉토리의 파일 개수 제한

제한 있음

제한 있음

제한 없음

[클러스터 개수의 경우 Microsoft에서 발표한 문서에서 표시한 내용이다.]

 

 

7) 클러스터 크기와 슬랙(Slack) 문제

- 클러스터 크기와 볼륨 크기와 어떤 관계가 있는지, 클러스터 크기에 따른 장단점이 무엇인지 파악 해보자.

[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

 

  1. NT, 2000, xp에서 클러스터 크기를 64KB 해서 2~4GB 볼륨을 16으로 포맷 가능하지만 일부 응용프로그램에서는 64KB 클러스터 볼륨을 인식 못하는 경우가 있으니 2GB넘는 볼륨은 FAT16 아닌 다른 파일시스템을 사용하길 권장한다.

  2. Windows 32GB 넘는 볼륨에 FAT32 이용해서 포맷하는 것을 지원하지 않지만 다른 장치가 포맷한 32GB 넘는 FAT32 볼륨은 인식   있다.

 

[클러스터 크기에 따른 장단점]

구분

클러스터 크기가 작을 

클러스터 크기가  

장점

버려지는 용량이 적다

FAT 영역이 작다.

Cluster 처리 부담이 적다.

단점

FAT 영역이 커진다

버려지는 용량(Slack) 많다.

 

- 클러스터 크기에 따른 장단점이 있으나 클러스터 크기가 작은 경우 버려지는 용량이 적다. 반면  경우 버려지는 용량이  경우 버려지는 용량이 크기 때문에 NTFS 파일시스템에선 클러스터 할당 크기를 작게  놓았다.

- 영상 데이터 같이 대용량 파일만 저장하는 경우 굳이 클러스터 크기를 작게  필요는 없을 것이다.

 

 

2. FAT 파일시스템 구조

1) FAT 파일시스템의 구조

 

[FAT 16 파일시스템 구조]

 

[FAT 32 파일시스템 구조]

 

- FAT16 FAT32 구조적인 부분에서 차이점은 FAT16 경우 루트 디렉토리 영역이 따로 존재한다.

- FAT16 경우 루트 디렉토리 영역이 따로 존재하며 하위 디렉토리들과 달리 FAT#2 영역 뒤에 오지만 FAT32 경우 일반 디렉토리 중의 하나로 간주 하기 때문에 데이터 영역 어디서든지 상관 없다.

 

2) 부트 레코드(Boot Recort)

- 볼륨의  번째 섹터이며, 예약된 (Reserved) 영역의  번째 섹터이다.

- Windows 부팅을 시키기 위한 기계어 코드와 FAT 파일시스템의 여러 설정 값들이 있다.

- BIOS Parameter Block(BPB)이라고도 하며, 크기가 1섹터밖에  되는 작은 영역이지만 Windows FAT 파일 시스템을 인식하는데 가장 중요한 역할을 담당한다.

- 만약 볼륨 내용이 완벽히 살아있어도 부트레코드 섹터의 데이터가 지워지면 Windows에서는 해당 볼륨을 인식   없다.

 

3) 예약된(Reserved) 영역

- FAT16 경우 1섹터, FAT32 경우 32섹터를 할당한다.

- FAT16 경우 1섹터 바로 뒤에 FAT영역이 오며  영역은 미래를 위해 예약되어 있는 영역으로 사용하지 않는 영역이다.

- 만약 특별한 정보를 기록 하고 싶은 경우  영역에 기록 하면  것이다.  FAT32 경우 예약된 영역 안에  개의 섹터를 사용하여 저장하고 있으므로 겹치지 않게 유의해야 한다.

 

 

4) FAT #1 영역과 FAT #2 영역

- 클러스터들을 관리하는 테이블이 모여 있는 공간으로 FAT 영역을 통해 어떤 클러스터가 비어 있는지, 어떤 파일에 어떤 클러스터가 연결되어 있는지   있다.

-  영역에 손상이 된다면 상당히 위험하며, 백업본을   이상 만들어 두게 해놓았다.

- FAT #1영역과 #2영역은 동일한 내용을 담고 있다. FAT #2영역은 일종의 백업본으로 FAT #1 손상이 갔을 경우를 대비해 만들어 져있다.

- FAT 영역은 최소 1 이상 되어야 한다. 보통 2개의 영역을 만든다.

 

5) 루트 디렉토리 영역(FAT 16 존재)

- FAT 16에서는 루트 디렉토리의 위치가 무조건 FAT #2 영역 뒤쪽으로 고정되어 있다.(크기는 가변적일  있다.)

-  방식은 루트 디렉토리가 어디에 있는지를 조사할 필요가 없어서 개발의 편의성이 증가하게 되는 장점이 있지만, 루트 디렉토리의 파일 개수 제한  단점이 있어서 FAT32에서는 구조가 바뀌었다.

- FAT32에서는 루트 디렉토리가 데이터 영역 어디에 와도 상관이 없으며, 단지  위치를 부트 레코드에 기록하고 있을 뿐이다.  방법의 유일한 단점은 부트 레코드가 망가지면 루트 디렉토리를 찾아내기가 매우 힘들다.

- 따라서 대부분의 FAT 코드들이 FAT32 경우라도 FAT #2 영역 바로 뒤에 루트 디렉토리를 위치시킨다. 따라서 부트 레코드가 망가져서 루트 디렉토리의 위치를   없게 되어버린 경우에도 간단히 찾을  있다.

 

 

6) 데이터 영역(파일과 디렉토리)

-  영역에는 파일 또는 디렉토리가 저장되어 있으며, 클러스터(Cluster)라고 불리는 논리적인 단위로 읽기/쓰기가 된다.

 

 

7) 사용하지 않는(Unused) 영역

-  영역은 물리적으로 사용해도 상관없지만, FAT 파일시스템이 볼륨이 구조화시키는 과정에서 잉여분이 조금 남는 영역이다.

- 매우 작은 양이기 때문에 무시할  있을 정도이다.

 

8) 영역별 정리

구분

부트 레코드

예약된 영역

FAT 영역

데이터 영역

크기

1섹터

1~32섹터

파티션의 1~0.5%

파티션의 99% 이상

접근 단위

섹터

섹터

섹터

클러스터

 

 

 

3. 부트레코드

1) 부트레코드 소개

- BIOS Parameter Block(BPB)라고 불리는  영역은 해당 볼륨의 여러 가지 설정 값들을 저장하고 있으며, 해당 볼륨이 부팅될  있도록 부팅에 필요한 실행 코드도 포함하고 있다.

- Boot Record 저장되는 위치는 해당 볼륨의  번째 섹터이며 FAT 파일 시스템을 구성하는 영역   앞에 위치하는 예약된(Reserved) 영역의  번째 섹터이기도 하다.

- HDD 볼륨이 여러  있다면 각각의 볼륨에 부트 레코드도 하나씩 있게 된다.

- 하드디스크에 파티셔닝이 되어 있지 않아 볼륨이 1개인 경우 부트레코드는 MBR(Master Boot Record) 영역에 존재한다.

 

[파티션 없이 단일 볼륨인 하드디스크의 부트 레코드 위치]

 

[파티션이 존재하고 볼륨이 2개인 하드디스크의 부트 레코드 위치]

 

 

2) 부트레코드에서 FAT 16 FAT 32 차이

[FAT16 FAT32 부트 레코드 레이아웃]

 

- 32오프셋 까지는 공통된 항목을 가졌으나 32 이후에는 항목이 달라 서로호환이 않된다.

- FAT16 부트 레코드 구조체와 FAT32 부트 레코드 구조체를 따로 선언해야 되는 것이다.

- 볼륨의 파일시스템을 조사할  0~32 오프셋까지 공통 항목의 내용을 조사하면   있을 것이다.

 

3) FAT 16 부트 레코드

 

[FAT16 부트레코드 영역]

 

- 512Byte 16진수 내용이 FAT16 부트 레코드의 모든 것이다.

- Windows FAT 파티션을 인식하는데 필수적인 사항들이기 때문에  들어가야 한다.

- 색칠이 되어있지 않은 부분은 부팅할  사용하는 부트 코드 영역이다.  파티션을 부팅용으로 사용하지 않을 경우 모두 '0'으로 채워도 상관 없는 영역이다.

 

[FAT16 부트 레코드 항목]

 

- FAT 파일시스템은 리틀 엔디언(Little Endian)으로 설계되어 있기 때문에 출력되는 값들은 실제 저장한 값과 반대로 뒤집혀 있다.

 

 

4) FAT 16 FAT 32 부트 레코드 공통 항목 설명

 

이름

Jmp Boot Code

위치

(Offset)

0~2

크기

(Size)

3 Byte

일반적인 

(Value)

EB 3C 90

설명

부트 코드로 점프하는 명령어. x86 계열 PC 부팅   항목을 읽어서 부트 코드가 있는 영역으로 점프하게 된다. 해당 볼륨을 이용해서 부팅할 일이 없다면 어떤 값이 와도 무방하다.

 

이름

OEM Name

위치

(Offset)

3~10

크기

(Size)

8 Byte

일반적인 

(Value)

ASCII Code

'MSDOS5.0'

설명

 항목은 단지 OEM 회사를 나타내기 위한 문자열일 뿐이다. Windows  항목에 대해서 어떠한 참조도 하지 않는다. Windows 보통 'MSWIN4.1'이라고 적거나 'MSDOS5.0'이라고 적는다.  항목은 어떤 값이 되어도 상관없다.

 

이름

Byte Per Sector

위치

(Offset)

11~12

크기

(Size)

2 Byte

일반적인 

(Value)

512

설명

섹터당 바이트 수를 적는다. 하드 디스크의  섹터가  바이트를 담고 있는지에 대한 항목으로  항목은 필수적으로 다음 값만 적어주어야 한다.

512, 1024, 2048, 4096 (  외에 다른 값은 사용하지 않는다.)

Windows 다른 FAT 인식하는 장치들에서 여러분이 기록한 FAT 하드디스크가  인식되길 바란다면  항목에 512 되어야  것이다.

섹터당 크기가 512Byte 아닌 하드디스크는 거의 없기 때문에 512 적는 것이 좋다.

 

이름

Sector Per Cluster

위치

(Offset)

13

크기

(Size)

1 Byte

일반적인 

(Value)

32

설명

클러스터당 섹터 ,  클러스터가  개의 섹터로 이루어져있는지 기록되는 부분이다.

 값은 반드시 '0'보다  값이어야 하며 2 배수여야 한다.

 

이름

Reserved Sector Count

위치

(Offset)

14~15

크기

(Size)

2 Byte

일반적인 

(Value)

FAT16 '1'

FAT 32 '32'

설명

예약된(Reserved) 영역의 섹터 수를 저장한다. 예약된 영역의 크기는 최소한 1 섹터 이상 되어야 하는데, 그것은 부트 레코드가 예약된 영역의  번째 섹터에 위치하기 때문이다.

따라서  항목의 값이 '0' 되어서는  된다.

FAT16 경우 보통 '1' 값을 가지며, FAT 32 보통 '32'값을 가진다.

예약된 영역에서 부트 레코드나 특별히 다른 정보를 담지 않고 있는 섹터는 전부 '0'으로 초기화 되어있어야 한다.

 

이름

Number of FATs

위치

(Offset)

16

크기

(Size)

1 Byte

일반적인 

(Value)

2

설명

볼륨에 있는 FAT 영역의 수를 담고 있다.  항목은 최소한 '1' 이상의 값을 가지며, '2'라고 적는 것을 추천한다.

주의할 점은  항목에다 '2'라고 적어놓고 실제 FAT영역을 3 만들거나 1 만드는 것은 좋지 않다.

CF Card 같은 저용량 매체에서 data 영역을 조금이라도  확보하기 위해  항목을 '1' 지정하는 개발자도 있다.

Windows  항목의 값이 '1'이더라도 호환성을 보장하지만, 모든 FAT코드가 호환할  있을지는 장담   없다. Number of FATs 값이 무조건 '2' 것이라는 가정하에 코드를 짜는 개발자들도 있을  있다.

 

이름

Root Directory Entry Count

위치

(Offset)

17~18

크기

(Size)

2 Byte

일반적인 

(Value)

FAT16 '512'

FAT 32 '0'

설명

FAT16 경우  항목은 루트 디렉토리에  개의 엔트리(파일과 디렉토리 모두 1개의 엔트리로 친다.) 수용할 것인지 나타낸다.  항목의 값은 Bytes Per Sector 짝수이어야 한다.  Bytes Per Sector 512라면  항목은 512, 1024,2048 같이 들어갈  있다. 최대 호환성을 위해서는 '512' 적는게 좋다.

주의할 점은 FAT32에서는 반드시 '0'이어야 한다.

 

이름

Total Sector 16

위치

(Offset)

19~20

크기

(Size)

2 Byte

일반적인 

(Value)

FAT16 가변적

FAT 32 반드시 '0'

설명

 항목은 볼륨상에 있는  섹터 수를 2Byte 나타낸다.

저장장치의  섹터수가 아닌 볼륨의  섹터 수이며 볼륨에 존재하는 모든 영역을 합친 섹터 수를 기록해야 한다.  항목의 값이 '0'   있다. 만약  항목의 값이 '0' 이라면 아래 설명할 Total Sector 32 항목의 값은 절대 '0' 되어서는  된다. FAT 16 경우  섹터수가 '0xFFFF'보다 크다면 Total Sector 32 항목을 이용한다.

FAT32에서는  항목의 값이 반드시 '0'이어야 한다.

 

이름

Media

위치

(Offset)

21

크기

(Size)

1 Byte

일반적인 

(Value)

0xF8

설명

 항목은  볼륨이 어떤 미디어에 저장되어 있는지를 나타낸다. 보통은 고정식 디스크 값인 '0xF8' 쓰인다. CF Card USB Memory 이동식이므로 '0xF8' 아닐 것이라고 생각 하기 쉽다. 실제 Windows CF Card 포맷하면  항목 값을 '0xF8'이라고 적는다.

플로피 외의 저장장치라면  항목에 '0xF8' 적는 것이 좋다.

 

[Media 항목에 들어갈  있는 값들]

용량

저장장치 형태

0xF0

2.88MB

3.5inch, 양면, 36 sector 플로피디스크

0xF0

1.44MB

3.5inch, 양면, 18 sector 플로피디스크

0xF9

720KB

3.5inch, 양면, 9 sector 플로피디스크

0xF9

1.2MB

5.25inch, 양면, 15 sector 플로피디스크

0xFD

360KB

5.25inch, 양면, 9 sector 플로피디스크

0xFF

320KB

5.25inch, 양면, 8 sector 플로피디스크

0xFC

180KB

5.25inch, 단면, 9 sector 플로피디스크

0xFE

160KB

5.25inch, 단면, 8 sector 플로피디스크

0xF8

X

고정식 디스크(플로피를 제외한 모든 장치

 

이름

FAT size 16

위치

(Offset)

22~23

크기

(Size)

2 Byte

일반적인 

(Value)

FAT16 가변적

FAT 32 반드시 '0'

설명

 항목은 FAT 영역의 섹터 수를 저장하는 항목이다. FAT #1영역과 FAT #2영역을 합친 값이 1개의 FAT 영역의 섹터 수를 적어야 한다.  항목은 FAT12 FAT16 사용한다.

FAT32 FAT Size 32라는 항목이 따로 있다. 중요한 점은 FAT32에서는 항목의 값이 반드시 '0'이어야 한다.

 

이름

Sector Per Track

위치

(Offset)

24~25

크기

(Size)

2 Byte

일반적인 

(Value)

63

설명

 항목은 x86 프로세서 계열에서 발생하는 인터럽트(INT) 0x13 위해 존재하는 항목으로 저장장치의 트랙당 섹터 수를 저장한다.

Windows 계열에서는  이상  항목을 참조 하지 않는다.

 

이름

Number Of Heads

위치

(Offset)

26~27

크기

(Size)

2 Byte

일반적인 

(Value)

255

설명

 항목은 x86 프로세서 계열에서 발생하는 인터럽트(INT) 0x13 위해 존재하는 항목으로 저장장치의 헤더 수를 저장한다. Windows 계열에서는  이상  항목을 참조 하지 않는다.

 

 

이름

Hidden Sector

위치

(Offset)

28~31

크기

(Size)

4 Byte

일반적인 

(Value)

32

설명

 항목은 x86 프로세서 계열에서 발생하는 인터럽트(INT) 0x13 위해 존재하는 항목으로 해당 봉륨 앞에 존재하는 (숨겨진) 섹터 수를 저장한다. 파티션되지 않은 볼륨에서는 반드시 '0'이어야 한다. Windows 계열에서는  이상  항목을 참조 하지 않는다.

 

 

이름

Total Sector 32

위치

(Offset)

32~35

크기

(Size)

1 Byte

일반적인 

(Value)

32

설명

 항목은 볼륨상에 있는 섹터 수를 4Byte 나타낸다. 중요한 것은 저장장치의  섹터 수가 아닌 볼륨의  섹터  라는 점이다. 볼륨에 존재하는 모든 영역을 전부 합친 섹터 수를 적어야 한다. FAT16 경우  항목의 값이 '0'   있다.

 항목이 '0'이라면 위에서 설명한 Total Sector 16 항목의 값은 절대 '0' 되어서는  된다. FAT32에서는  항목의 값이 반드시 '0' 아니여야 한다.

FAT32 Total Sector16 항목은 이용하지 않고, Total Sector32 만을 이용해야 한다.

 

여기까지는 동일한 항목이다.

여기서 클러스터의 크기를 알아보도록 하자.

Sector Per Cluster X Bytes Per Sector = 클러스터 크기

 

Sector Per Cluster : 02 (2)

Byte Per Sector : 00 02(Little Endian) => 0200(16진수)=> 512

2 X 512 = 1024 Byte,  1KB 되는 것이다.

 

 

5) FAT 16 부트 레코드 항목 설명

 

이름

Drive Number

위치

(Offset)

36

크기

(Size)

1 Byte

일반적인 

(Value)

0x80

설명

 항목은 x86 프로세서 계열에서 발생하는 인터럽트(INT) 0x13 위해 존재하는 항목으로 INT 0x13에서 정의한 드라이브 값을 설정한다.

플로피 디스크는 '0x0',  외의 대부분의 저장장치는 '0x80' 값을 가진다.

Windows계열에서는  이상  항목을 참조하지 않는다.

 항목은 FAT 16에만 해당한다.

 

이름

Reserved1

위치

(Offset)

37

크기

(Size)

1 Byte

일반적인 

(Value)

0

설명

Windows NT 계열에서 사용하려고 만든 항목으로  값은 항상 '0'으로 해야 한다.

 항목은 FAT 16에만 해당 한다.

 

이름

Boot Signature

위치

(Offset)

38

크기

(Size)

1 Byte

일반적인 

(Value)

0x29

설명

확장 부트 서명,  항목의 값은 항상 '0x29'여야 한다.  항목이 의미하는 것은 여기가 끝이 아니라  항목 아래쪽에 3가지 항목이  추가되었다는 것을 말한다.

 항목은 FAT16에만 해당 한다.

 

이름

Volume ID

위치

(Offset)

39~42

크기

(Size)

4 Byte

일반적인 

(Value)

가변적임

설명

볼륨 시리얼 번호, 고유의 임의의 시리얼 번호를 생성해서 기록한다.

 항목은 FAT16에만 해당 한다.

 

이름

Volume Label

위치

(Offset)

43~53

크기

(Size)

11 Byte

일반적인 

(Value)

가변적임

설명

해당 볼륨의 레이블을 적는다. 여기에 적은 문자열은 Windows에서 드라이브 이름으로 쓰이게 된다. 사실 볼륨 레이블을 적는 부분은 2군데가 있는데,   한곳은 여기이고, 다른  곳은 루트 디렉토리에 존재하는 레이블 엔트리이다. 볼륨 레이블이 변경될 경우 2군데 모두 값을 바꿔 주어야 한다. 루트 디렉토리에 레이블 엔트리를 생성하지 않았다면  항목은 "NO NAME "라고 적어야 한다.

 항목은 FAT16에만 해당 한다.

 

이름

File System Type

위치

(Offset)

54~61

크기

(Size)

8 Byte

일반적인 

(Value)

ASCII Code

"FAT16 "

설명

 항목에는 "FAT12 ", "FAT16 ", "FAT "  적절한 문자열을 적어주면 된다. 주의  점은 여러분이 어떤 하드디스크가 FAT16인지 FAT32인지를 조사할   영역에 적힌 값을 이용해서 판단을 내리면  된다는 점이다.  항목은 단순한 문자열이며  외에 어떤 의미도 없기 때문에  영역을 잃고 볼륨을 FAT16이라고 결론을 내리면  된다.

 항목은 FAT16에만 해당 한다.

 

 

6) FAT 32 부트 레코드 항목 설명

 

[FAT32 부트 레코드 항목]

 

 

이름

FAT Size 32

위치

(Offset)

36~39

크기

(Size)

4 Byte

일반적인 

(Value)

가변적임

설명

 항목은 Fat 영역의 섹터 수를 저장하는 항목이다. FAT #1영역과 FAT #2영역을 합친 값이 아닌 1개의 FAT 영역의 섹터 수를 적어야 한다.

 항목은 FAT 32에만 해당한다.

 

이름

Ext Flags

위치

(Offset)

40~41

크기

(Size)

2 Byte

일반적인 

(Value)

0x00

설명

FAT 테이블을 조작하는 것에 대하여 여러 설정 값을 가진다.

 항목은 FAT 32에만 해당한다.

 

[Ext Flags]

 

속성 이름

크기

설명

Active FAT Number

4Bit

활동시킬 Fat 번호, 0부터 시작한다. Flag 값이 '1' 경우에만 의미가 있다.

Reserved

3Bit

사용되지 않음. 미래를 위해 예약된 공간.

Flag

1Bit

0 : 변경 내용을 모든 FAT 영역에 반영하라.

1 : 변경 내용을 Active FAT Number 적힌 FAT 영역에만 반영하고 다른 영역에는 손대지 마라.

Reserved

8Bit

사용되지 않음. 예약된 공간.

 

 

이름

File System Version

위치

(Offset)

42~43

크기

(Size)

2 Byte

일반적인 

(Value)

0x00

설명

 항목은 FAT32 버전 정보를 나타낸다. 상위 바이트는  버전, 하위 바이트는  버전을 나타낸다. Windows  항목을 조사하여 만약 적혀 있는 버전이 자신이 인식할  있는 버전보다 높다면 파티션 인식 작업을 포기하게 된다. 지금까지 나온 FAT 버전은 전부 0x00으로 설정되어 있고, 아직까지  버전 정보가 올라간 적이 없다. 따라서 0x00으로 설정하는 것이 좋다.

 항목은 FAT 32에만 해당한다.

 

이름

Root Directory Cluster

위치

(Offset)

44~47

크기

(Size)

4 Byte

일반적인 

(Value)

2

설명

 항목은 루트 디렉토리의 클러스터 값을 담고 있다. FAT16 다르게 FAT32 경우 루트 디렉토리가 데이터 영역 어디에 와도 상관 없기 때문에 루트 디렉토리의 시작 위치를 적어  것이다. 보통의 경우  항목의 값은 2 들어가는데 여러분들도  값을 따르는  좋다. 만약 실수로  항목의 값이 엉망이 되어 버렸다면 루트 디렉토리의 위치를   없게 되는데 항상 루트 디렉토리를 클러스터 2 위치시켜 놓는다면 쉽게 루트 디렉토리의 위치를 복구할  있다.

 항목은 FAT 32에만 해당한다.

 

이름

File System Information

위치

(Offset)

48~49

크기

(Size)

2 Byte

일반적인 

(Value)

1

설명

 항목은 FSInfo 구조체가 어디에 저장되어 있는지를 가리킨다. 보통의 경우 볼륨의 1 섹터에 저장된다.

 항목은 FAT 32에만 해당한다.

 

이름

Boot Record Backup Sector

위치

(Offset)

50~51

크기

(Size)

2 Byte

일반적인 

(Value)

6

설명

부트 레코드는 매우 중요하기 때문에 백업을 해두는데  위치를 기록 한다. 사본의 위치는 예약된(Reserved) 영역 어디에 오든 상관없지만, 일반적으로 6 섹터를 이용한다.  항목의 값이 '0'이라면 백업을 하지 않았다는 의미이다.

 항목은 FAT 32에만 해당한다.

 

이름

Reserved

위치

(Offset)

52~63

크기

(Size)

12 Byte

일반적인 

(Value)

0

설명

미래를 위해 예약된 영역이다. 항상 0으로 채워져 있다.

 항목은 FAT 32에만 해당한다.

 

이름

Drive Number

위치

(Offset)

64

크기

(Size)

1 Byte

일반적인 

(Value)

1

설명

 항목은 인터럽트(INT) 0x13 위해 존재하는 항목이다. Windows 계열에서는  이상  항목을 참조하지 않으므로 어떤 값을 써도 무방하다.

 항목은 FAT 32에만 해당한다.

 

이름

Reserved1

위치

(Offset)

65

크기

(Size)

1 Byte

일반적인 

(Value)

0

설명

Windows NT 계열에서 사용하려고 만든 항목이다.  항목은 항상 0으로 해야 한다.

 항목은 FAT 32에만 해당한다.

 

이름

Boot Signature

위치

(Offset)

66

크기

(Size)

1 Byte

일반적인 

(Value)

0x29

설명

확장 부트 서명이다.  항목의 값은 항상 '0x29'여야 한다.  항목이 의미하는 것은 여기가 끝이 아니라  항목 아래쪽에  가지 항목이  추가되었다는 것을 말한다.

 항목은 FAT 32에만 해당한다.

 

이름

Volume ID

위치

(Offset)

67~70

크기

(Size)

4 Byte

일반적인 

(Value)

가변적임

설명

볼륨 시리얼 번호이다. 고유의 임의의 시리얼 번호를 생성해서 기록한다.

 항목은 FAT 32에만 해당한다.

 

이름

Volume Label

위치

(Offset)

71~81

크기

(Size)

11 Byte

일반적인 

(Value)

가변적임

설명

볼륨 레이블로 해당 파티션의 볼륨 레이블을 적는다. 여기에 적은 글자는 Windows에서 디스크 이름으로 쓰인다. 볼륨 레이블을 적는 부분이 2군데가 있는데   하나는 여기이고, 다른  곳은 루트 디렉토리이다. 볼륨 레이블이 변경될 경우 2군데 모두 값을 바꿔야 한다. 볼륨 레이블이 없는 경우 "NO NAME "이라고 적어준다.

 항목은 FAT 32에만 해당한다.

 

이름

File System Type

위치

(Offset)

82~89

크기

(Size)

8 Byte

일반적인 

(Value)

ASCII Code

"FAT32 "

설명

Windows  항목에 항상 "Fat32 "라고 적는다.  항목은 단순한 문자열이며  외에 어떤 의미도 없기 때문에  영역을 잃고 볼륨을 FAT32이라고 결론을 내리면  된다

 항목은 FAT 32에만 해당한다.

 

- 부트 레코드 항목 중에는 문자열을 저장하는 항목이 있는데 OEM Name, Volume Label, File System Type 항목은 문자열을 저장한다.

-  항목에 문자열을 저장하는  있어서 주의해야  점은  공간을 반드시 Space(0x20) 처리해야 한다.

만약 C언어로 File System Type "FAT16"이라는 문자를 넣을  코드를 보자

 

strcpy(FileSystemType, "FAT16");

이렇게 되면 저장되는 모양은

F

A

T

1

6

NULL

X

X

0x46

0x41

0x54

0x31

0x36

0x0

  없음

  없음

 

하지만  공간에는 Space 들어가야 한다.

아래 형태로 구현을 하기 위해 문자열 제어 함수를 사용하지 말고 직접 특별한 문자열 제어 함수를 구현하던지 배열 값을 넣어야 한다.

F

A

T

1

6

Space

Space

Space

0x46

0x41

0x54

0x31

0x36

0x20

0x20

0x20

 

 

7) 부트 레코드의 끝부분

- 부트 레코드를 구현하는데 있어 FAT16/32 모두 부트 레코드 영역의 Offset 511~512에는 반드시 0xAA55라는 서명이 들어간다.

 

이름

Signature

위치

(Offset)

510~511

크기

(Size)

2 Byte

일반적인 

(Value)

반드시 0xAA55

설명

 항목은 부트 레코드가 손상되었는지 아닌지 확인 하는 용도로 사용하며  항목이 없다면 Windows에서는 부트레코드가 망가졌다고 판단하고 인식을 못하게 된다.

 항목은 FAT 16, FAT32에만 모두 해당한다.

 

많은 FAT문서에는 "Signature 위치는 부트 레코드 가장 끝부분" 이라고 하지만 이것은 섹터가 512Byte 경우에만 유효한 내용이며, Microsoft에서 제공하는 공식 문서에는 섹터의 크기가 512Byte보다  경우라도 Signature Offset 510~511 와야한다.

 

 

4. 부트레코드 실습

 

관리자권한으로 실행

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

 

#include <stdio.h>

#include <windows.h>

#include <stdlib.h>

 

#define U8        unsigned char

#define S8        char

#define U16        unsigned short

#define U32        unsigned int

#define U64        unsigned __int64

 

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

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 get_BPB_info(FAT16_BPB* BPB, VolStruct* PVol);

 

VolStruct gVol;

 

int main(void){

    U8            buf[512];

 

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

    gVol.VolBeginSec = 0x87; //부트 섹터가 있는 곳

 

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

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

        return 1;

    }

 

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

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

        return 1;

    }

 

    printf("[[[[[[[[[Volume Information ]]]]]]]]]\n");

    printf("Total Sector            = %d Sectors : %dMB\n",gVol.TotalSec, ((gVol.TotalSec*512)/1024)/1024);

    printf("FAT Size            = %d Sectors \n",gVol.FATSize);

    printf("Root Dir Sector            = %d      \n", gVol.RootDirSec);

    printf("Root Dir Sector Count        = %d \n", gVol.RootDirSecCnt);

    printf("First Data Sector        = %d \n",gVol.FirstDataSec);

    printf("Data Sector Count        = %d Sectors \n",gVol.DataSecSize);

    printf("Total Cluster            = %d            \n", gVol.TotalClusCnt);

    printf("Size of Cluster            = %d : %dKB        \n",gVol.ClusterSize, gVol.ClusterSize/1024);

 

    return 0;

}

 

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;

 

}

 

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;

}

[드라이브 설정]

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

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

 

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

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

 

 

[부트레코드 섹터위치]

 

gVol.VolBeginSec = 0x87;

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

 

실행화면..

 

 

+ Recent posts