Forensic/파일-구조

디렉터리 엔트리 분석 - LFN, SFN

Ron Weasley 2022. 8. 17. 18:38

디렉터리 엔트리는 Windows의 FAT(File Allocation Table) 파일 시스템에서 파일의 이름, 확장자, 위치, 크기, 시간 정보들을 표현하기 위한 구조체입니다. 하나의 파일 및 디렉터리는 각각의 메타정보를 표현하기 위해 하나의 디렉터리 엔트리를 가집니다.
 
FAT 파일 시스템에서 FAT 영역에 이어 오는 루트 디렉터리(Root Directory)영역을 살펴 보면 최상위 디렉터리에 존재하는 파일들의 디렉터리 엔트리를 확인할 수 있습니다. (FAT32는 루트 디렉터리가 파일 시스템 어느 곳에나 올 수 있습니다.)

FAT16 Structure

디렉터리 엔트리는 32바이트의 고정된 형태로 해당 파일의 메타정보를 표현하는데 구조를 한번 보겠습니다.

위에 보시는 구조를 가지는 파일을 SFN(Short File Name)이라합니다.
SFN File은 "파일명이 8바이트 이하인 파일"을 이야기 합니다.
 
만약 8바이트를 초과하면 SFN File이 아니라 LFN File을 사용합니다.
LFN File은 "Long File Name의 약자로 파일명이 8바이트를 초과한 파일"을 이야기합니다.
 
예시를 하나 보면서 같이 따라 가보도록 합시다! 저는 가상 디스크를 하나 만들어 줬습니다.
FAT16으로 포맷을 했으며 파일명이 SFN.txt 인 텍스트 파일을 하나 추가했습니다.

SFN.txt 파일에 SFN Test라는 텍스트를 입력하고 저장했습니다.

Hxd 에디터를 열어서 Root Directory를 찾아 가보겠습니다.
 

1. SFN(Short File Name) Structure - 32bytes

위 사진에 나오는 파일 구조는 SFN File의 구조로 32바이트 입니다.
 
실제 파일의 Hex값을 확인을 해보면 다음과 같습니다.

이제는 구조에 따라 하나씩 비교 해보겠습니다.

1-1 SFN(Short File Name) Structure - Name

Name

디렉터리 엔트리는 기본적으로 Name을 표현할 수 있는 필드가 0x00 ~ 0x07로 8바이트입니다.
그 중 첫번째 바이트는 파일이 파일 시스템상에 존재할 경우 파일이름을 표현하기 위해 사용되지만 파일이 삭제되었을 경우에는 0xE5의 값으로 해당 파일이 삭제되었다는 것을 나타냅니다.
 

1-2 SFN(Short File Name) Structure - Extension

Extension

0x08 ~ 0x0A는 확장자를 나타내는 Extension 필드입니다.
확장자가 지금 txt이기 때문에 0x545854로 나타나져 있는데, 만약 확장자가 없다면 공백인 0x202020이 됩니다.
참고로 모든 확장자는 대문자로 표시됩니다.
 

1-3 SFN(Short File Name) Structure - Attribute

Attribute

0x0B는 파일의 속성을 나타내는 Attribute 필드입니다.
해당 오프셋에 들어가는 값은 다음과 같습니다.

Attribute Offset

예제로 SFN.txt 파일을 숨김 파일로 지정하고 봤습니다.

txt파일은 일반 파일이기 때문에 0x20 값과 숨김 파일 0x02값을 더한 0x22가 되어있음을 확인할 수 있었고, 그 밑에 RECYCLEBIN은 휴지통이기 때문에 0x02(숨김 파일) + 0x04(시스템 파일) + 0x10(디렉터리 파일) 로 0x16의 값을 가집니다.

1-4 SFN(Short File Name) Structure - Reserved Area

Reserved Area

0x0C ~ 0x0D는 예약된 영역을 나타내는 필드입니다.
 

1-5 SFN(Short File Name) Structure - Time Stamp Data

타임스탬프를 나타내는 필드 5개는 한번에 설명을 드리기 위해서 가져왔습니다.
Create Time은 0x0E ~ 0x0F 영역이며 생성 시간을 나타냅니다. (0x639C)
Create Data는 0x10 ~ 0x11 영역이며 생성 날짜를 나타냅니다. (0x5511)
Last Accessed Data는 0x12 ~ 0x13 영역이며 마지막 접근 날짜를 나타냅니다. (0x5511)
Last Written Time은 0x16 ~ 0x17 영역이며 마지막 수정 시간을 나타냅니다. (0x63B3)
Last Written Data는 0x18 ~ 0x19 영역이며 마지막 수정 날짜를 나타냅니다. (0x5511)
 
각 Time Stamp는 2바이트의 크기를 가지게 되는데, 컴퓨터에서 변환 방법은 2가지로 시간과 날짜로 나뉩니다.
전부다 하는 것은...내용이 길어질 수 있으니 젤 위에 Create Time과 Create Data만 예시로 보겠습니다.
 
시간 변환하는 방법은 16진수로 된 값 0x639C를 2진수로 변환을 해야합니다. 변환을 하면 다음과 같습니다.
0x639C = 0110 0011 1001 1100 입니다.
 
이제 비트로 쪼개줘야 하는데 시간을 나타내는 h는 5비트, 분을 나타내는 m은 6비트, 초를 나타내는 s는 5비트입니다.
쉽게 말하면 hhhhh / mmmmmm / sssss가 됩니다.
 
그럼 변환을 시키면 이렇게 됩니다.
01100 / 011100 / 11100 으로 변환이 되는데 10진수로 바꿔봅시다.
12시 28분 28초로 해석이 가능합니다. 하지만 실제로 속성값을 보면 초가 다릅니다.

초가 다른 이유는 60분을 계산하기 위해서 최소의 비트 값인 6을 사용했습니다. 하지만, 초도 60초를 계산하기 위해 6비트를 사용해야 하는데 남은 5비트로만 초를 계산하기 때문에 2를 곱해주면 됩니다. 홀수는 2를 곱해서 나올 수 없는 값이기 때문에 얼추 28초 * 2는 56초, 57초가 맞습니다.
 
날짜를 변환하는 방법은 16진수로 된 값 0x5511를 2진수로 변환을 해야합니다. 변환을 하면 다음과 같습니다.
0x5511 = 0101 0101 0001 0001
 
날짜는 시간과 달리 연도를 나타내는 y는 7비트, 월을 나타내는 m은 4비트, 일을 나타내는 d는 5비트입니다.
그럼 yyyyyyy / mmmm / ddddd가 되겠죠?
 
변환을 시켜봅시다.
0101010 / 1000 / 10001인데, 42 / 8 / 17 이 됩니다.
근데 뭔가 이상하죠? 지금 2022년인데...왜 42가 나왔을까요?
그 이유는 컴퓨터는 년도에서 +1980을 해줘야 하기 때문입니다. 그래서 계산을 해보면 다음과 같습니다.
2022 / 8 / 17 으로 해석을 정확하게 할 수 있습니다.

 

1-6 SFN(Short File Name) Structure - Starting Cluster

0x14 ~ 0x15와 0x1A ~ 0x1B는 Starting Cluster를 나타내는 필드입니다.
위 값을 확인하면 0x00000005이며 해당 파일 내용은 5번째 클러스터에 있다는 것을 확인할 수 있습니다.
 
지금부터는 살짝 어려우니 따라 해봅시다!
클러스터는 FAT 영역이 끝나고 데이터 영역(Root Directory)부터 시작이 됩니다.

제가 분석하고 있는 디스크에서는 Root Directory 시작 섹터가 512 섹터 였습니다.
Root Directory의 시작 섹터인 512 섹터 + 32섹터 = 544 섹터가 클러스터 2번이면서 Data Area의 시작 주소입니다.

그리고 0번 섹터에서 0x0D를 한번 봅시다.

0x10 = 16입니다. 클러스터 3번은 544 섹터 + 16 섹터인 560섹터입니다.
앞서 SFN.txt는 5번째 클러스터니까 5번 위치에 있습니다. 그럼
560 (클러스터 3번) + 16(클러스터 당 섹터) + 16 = 592 섹터가 되겠죠?

592 섹터가 가보니 제가 txt파일에 적어놓은 텍스트를 확인할 수 있었습니다.
 

1-7 SFN(Short File Name) Structure - File Size

위에서 본 파일 처럼 0x00000008 바이트 인 것을 알 수 있습니다.
 
여기까지 파일 이름이 7바이트 이하인 파일인 SFN.txt의 구조인 SFN File에 대해서 봤습니다. 이제는 LFN도 봐야겠죠? 바로 예제 파일을 만들겠습니다.

하나 만들었습니다.
 
2. LFN(Long File Name) Structure - (32 * n) byte
일단...제가 만든 파일의 hex값을 보겠습니다.

지금까지 배웠던 SFN 구조는 0x401A0 ~ 0x401B0의 오프셋에 자리 잡혀 있습니다.
이를 볼 때, LFN 파일은 다음과 같은 구조를 띄고 있습니다.

파일의 이름이 길어질수록 구조체가 하나씩 더 추가되는 형식입니다.
그래서 제가 만든 LNF File Analysis.txt는 2개의 LFN File과 1개의 SFN File이 구성되어 있습니다.

Name 필드를 봤을 때, LFNFIL~1TXT로 되어있는 것을 볼 수 있습니다.
 
현재 분석하고 있는 파일 구조가 LFN - LFN - SFN 구성으로 되어 있기 때문에 다음과 같은 구조를 가집니다.

 

2-1 LFN(Long File Name) Structure - Sequence Number(Status Byte)

0x00 ~ 0x00을 Sequence Number를 나타내는 필드입니다.
 
마지막 LFN 구조에 들어있는 Sequence Number는 해당 LFN 파일 구조의 갯수를 의미합니다.
위 구조에서는 LFN 파일 구조가 2개가 있는 것을 볼 수 있는데 0x40과 XOR 0x02를 해서 0x42라는 값이 저장되어 있습니다.
하지만 밑에 0x40180 오프셋은 01로 되어있는데 마지막에 나오는 0x42만 XOR 연산을 하는 것이지 나머지는 순차적으로 01, 02로 이루어져 있습니다.
 
그리고, LFN 파일 구조에는 13바이트의 파일명이 들어가기 때문에 13바이트를 초과하면 LFN 파일의 개수가 하나씩 늘어납니다.
잠깐 파일명을 엄청 길게 해보겠습니다.

A가 무수히 많은 txt파일을 하나 만들었습니다.

보시면 LFN 파일이 5개이고, 0x40 XOR 0x05를 하기 때문에 0x45로 표시가 됩니다.
그리고 04 - 03 - 02 - 01 순차적으로 이루어져있습니다!
 

2-2 LFN(Long File Name) Structure - FileName #1,2,....

파일명을 나타내는 필드입니다. 위 구조에서 보시다시피 파일명이 1개가 아닙니다..
그래서 보시면 2바이트에 1글자씩 들어있습니다. 
 

2-3 LFN(Long File Name) Structure - Attribute

0x0B ~ 0x0B는 속성값을 나타내는 필드입니다.
항상 이 값은 0x0F를 가지고 있습니다.
 

2-4 LFN(Long File Name) Structure - Reserved Area(Type)

0x0C ~ 0x0C는 예약된 영역을 나타내는 필드입니다.
이 부분은 예약된 영역으로 Type을 나타내기도 하는데 0x00을 주로 띕니다.
 

2-5 LFN(Long File Name) Structure - CheckSum

0x0D ~ 0x0D는 CheckSum을 나타내는 필드입니다.
이 부분은 SFN에 존재하는 파일명에 대응하는 값이 CheckSum으로 채워지게 되는데, 로직을 한번 보겠습니다.
https://ethan-ncs.tistory.com/65
이 블로그에서 가져온 로직입니다!!

이 소스 코드인데, 코드를 이제 실행을 시켜서 파일명을 입력을 하면 CheckSum을 구할 수 있었습니다.

그리고 Seq Num, File Name, Attr Value, Type, CheckSum 중 하나라도 잘못된 값이 들어있다면 인식되지 않습니다.
 

2-6 LFN(Long File Name) Structure - First Cluster Low

0x1A ~ 0x1B는 First Cluster Low를 나타내는 필드입니다.
이 필드는 해당 파일의 내용이나 해당 디렉터리의 하위 데이터 들이 있는 클러스터 번호를 가지고 있ㅅ브니다.
이 파일은 8번 클러스터에 파일 내용이 들어 있음을 의미합니다.
 
아까 위에서 봤듯이 클러스터를 구하는 방법을 봤으니 바로 찾아가겠습니다.
592 섹터가 5번 클러스터였으니까 592 +16 +16 +16 = 640섹터를 찾아가봅시다.

잘 나오네요!!
 
마지막으로 한글 이름의 표현 방식에 대해서 배워 보겠습니다.

위즐리다.txt를 만들어 줬습니다.
FAT 파일시스템 상에서 한글 이름을 가진 파일을 생성하였을 경우 Hex값을 보겠다.

0xC0A7, 0xC1F1, 0xB8AE, 0xB4D9 ... 한글 완성형 코드 값이 설정되어 있는것 같다.
사이트는 다음과 같다. https://kkamagui.tistory.com/234

이렇게 4음절을 초과하지 않는 경우에는 디렉터리 엔트리를 사용해 표현되며 한글 완성형 코드 값으로 기록이 됩니다. 하지만 4음절을 초과하게 되면 유니코드로 표현됩니다.

https://www.utf8-chartable.de/
여기서 변환을 해보면..!
열 : C5F4
심 : C2EC
히 : D788
공 : ACF5
부 : BD80
하 : D558
고 : ACE0
있 : C788
다 : B2E4
 
여기까지 SFN, LFN을 마치도록 하겠습니다!!