모두의 dream

Ext4 파일 데이터 접근 (with Directory Entry) 본문

분야/Digital Forensics

Ext4 파일 데이터 접근 (with Directory Entry)

오리꽥이로 2023. 9. 15. 10:05

I. inode 분석

inode에 대한 자세한 내용은 아래 링크에서 확인할 수 있다.

https://roklcw.tistory.com/65

 

Ext4 File System

*공부를 위해 정리한 내용으로 틀린 부분이 있을 수 있습니다. *I. Ext4 파일시스템Extended File System, 리눅스에서 사용하기 위해 개발된 Ext 파일시스템의 4번째 후속 버전이다II. Ext4 파일시스템 구조

roklcw.tistory.com

 

실습을 위해 /home/user/Downloads 디렉토리에 Flag_of_South_Korea.svg.png, baseball.jpg 라는 파일을 다운로드 받아놨다.


root 디렉토리의 경우 2번 inode를 고정값으로 갖고 있다.

root directory inode

root directory inode

필드들을 해석해보면 다음과 같다.

offset 이름 해석
0x00 ~ 0x01 i_mode
파일의 권한과 소유자를 나타냄.
구조: type(4bit) + setuid/setgid/sticky bit + user 권한 (3bit) + group 권한 (3bit) + other 권한 (3bit)

0x41ED → 0100 000 111 101 101

0100 (0x4000) : S_IFDIR (Directory)
000: NULL
111 101 101: rwxr-xr-x

결과: 디렉토리, drwxr-xr-x

0x02 ~ 0x03 i_uid 0
0x04 ~ 0x07 i_size_lo
(Size in bytes)
0x1000 → 4096 bytes
0x08 ~ 0x0B i_atime
(Access time)
0x66338E41 → 2024-05-02 21:59:45 (UTC+9)
0x0C ~ 0x0F i_ctime
(Inode Change time)
0x65BC87AF → 2024-02-02 15:11:59 (UTC+9)
0x10 ~ 0x13 i_mtime
(Modification time)
0x65BC87AF → 2024-02-02 15:11:59 (UTC+9)
0x14 ~ 0x17 i_dtime
(Deletion Time)
0x00000000 → NULL
0x18 ~ 0x19 i_gid
(Low 16 bits of Group Id)
0x0000 → NULL
0x1A ~ 0x1B i_links_count
(Links count)
0x14 → 20
0x1C ~ 0x1F i_blocks_lo
(Blocks count)
0x08 → 8
0x20 ~ 0x23 i_flags
(File flags)
0x80000 → 1000 0000 0000 0000 0000

0x80000: Inode uses extents (EXT4_EXTENTS_FL).
 0x24 ~ 0x27 OS dependent 1 0x18 → 24
0x28 ~ 0x63
(60bytes)
i_block[EXT4_N_BLOCKS=15]
(Pointers to blocks)
아래 참조
0x64 ~ 0x67 i_generation
(File version (for NFS))
0
0x68 ~ 0x6B i_file_acl_lo
(File ACL)
0
0x6C ~ 0x6F i_size_high / i_dir_acl 0
0x70 ~ 0x73 i_obso_faddr
(Obsoleted fragment address)
0
0x74 ~ 0x7F OS dependent 2 0xE8BA0000000000000000
0x80 ~ 0x81 i_extra_isize 0x20 → 32
0x82 ~ 0x83 i_checksum_hi
(crc32c(uuid+inum+inode) BE)
0x6628 → 26152
0x84 ~ 0x87 i_ctime_extra
( extra Change time      (nsec << 2 | epoch))
0x79D0475C → 2034-10-06 05:28:12 (UTC+9)
0x88 ~ 0x8B i_mtime_extra
(extra Modification time(nsec << 2 | epoch))
0x79D0475C → 2034-10-06 05:28:12 (UTC+9)
0x8C ~ 0x8F i_atime_extra
(extra Access time      (nsec << 2 | epoch))
0xA8050A34 →1923-03-25 07:01:24 (UTC+9)
0x90 ~ 0x93 i_crtime
( File Creation time)
0x65BC8551 → 2024-02-02 15:01:53 (UTC+9)
0x94 ~ 0x97 i_crtime_extra
(extra FileCreationtime (nsec << 2 | epoch))
0x00000000 → NULL
0x98 ~ 0x9B i_version_hi 0
0x9C ~ 0x9F i_projid 0

 

파일에 접근하기 위해 필요한 i_block 정보는 다음과 같다.

i_block

분류 offset 이름
Header 0x06 ~ 0x07 Header의 eh_depth 0 → 따라서 Leaf nodes
Leaf nodes 1 0x00 ~ 0x03 Leaf nodes ee_block 0
0x04 ~ 0x05 Leaf nodes ee_len 1
0x06 ~ 0x07 Leaf nodes ee_start_hi 0x0000
0x08 ~ 0x0B Leaf nodes ee_start_lo 0x2426

 

최종: 블록번호 (ee_start_hi + ee_start_lo) * 한 블록의 크기 4096 bytes (0x1000)

ee_start_hi + ee_start_lo = 0x00002426 

 

(ee_start_hi + ee_start_lo) * 0x1000 = 0x2426000

 

해당 파티션의 첫 번째 블록그룹 시작점에서 0x2426000 만큼 이동하면 root directory 데이터로 이동할 수 있다.

root directory 구조

 

 /home/user/Downloads 디렉토리에 Flag_of_South_Korea.svg.png를 찾는 과정은 journal inode 분석 이후 진행한다.

II. inode를 통해 파일 주소로 접근하기  

/home/user/Downloads 폴더에 Flag_of_South_Korea.svg.png 로 접근해보자.

우선 root directory의 inode를 통해 root directory에 접근하면 다음과 같은 데이터가 보이며, 이 데이터를 Directory Entry 라고 한다.

root directory

Directory Entry 분석

Directory Entry의 구조는 ext4_dir_entry, ext4_dir_entry_2가 존재한다.

어떤걸 사용하는지에 대한 기준은 슈퍼블록의 s_feature_incompat 필드의 0x2 번째 값(INCOMPAT_FILETYPE)을 통해 결정한다.

0이 (설정되지 않음) 있으면 ext4_dir_entry , 1이 (설정됨) 있으면 ext4_dir_entry_2 구조로 해석하면 된다.

 

구조는 다음과 같다.

ext4_dir_entry

Offset Size Name 설명
0x00 ~ 0x03 4 bytes inode 디렉토리 엔트리가 가리키는 inode 번호
0x04 ~ 0x05 2 bytes rec_len 디렉토리 엔트리 길이
0x06 ~ 0x07 2 bytes name_len 파일 이름 길이
0x08 ~  - name[EXT4_NAME_LEN] 파일 이름

ext4_dir_entry_2

Offset Size Name 설명
0x00 ~ 0x03 4 bytes inode 디렉토리 엔트리가 가리키는 inode 번호
0x04 ~ 0x05 2 bytes rec_len 디렉토리 엔트리 길이
0x06 1 bytes name_len 파일 이름 길이
0x07 1 bytes file_type File type code, one of:
0x0 Unknown.
0x1 Regular file.
0x2 Directory.
0x3 Character device file.
0x4 Block device file.
0x5 FIFO.
0x6 Socket.
0x7 Symbolic link.
0x08 ~  - name[EXT4_NAME_LEN] 파일 이름

실습파일에 접근하기

현재 실습파일은 ext4_dir_entry 구조로 되어있으므로 해석해보면 다음과 같다. (슈퍼블록의 s_feature_incompat 확인)

/home/user/Donwoloads 접근하기

각 디렉토리 별 엔트리

접근하고자 하는 파일의 경로는 /home/user/Downloads 폴더에 Flag_of_South_Korea.svg.png 이므로 home directory entry의 구조를 살펴보자.

 

해석해보면 다음과 같다.

Offset Size Name 설명
0x00 ~ 0x03 4 bytes inode 0x80001 (524,289)
0x04 ~ 0x05 2 bytes rec_len 0x0C (12)
0x06 1 bytes name_len 0x04
0x07 1 bytes file_type File type code, one of:
0x2 Directory.
0x08 ~  - name[EXT4_NAME_LEN] home

 

inode table에서 0x80001(524,289) 번째 inode 값을 확인한다. (각 그룹마다 inode table이 있지만 inode 번호는 초기화되지 않고 쭉 이어진다. 따라서 각 그룹의 inode table 값을 이어붙인 후 찾아가거나, 각 그룹별 첫번째, 마지막 inode 값을 확인하며 접근해야 한다. 나는 FTK Imager에서 inode table을 별도로 묶어서 확인하고 추출할 수 있도록 해놔서 그걸 참고했다.) 또한 inode는 1부터 시작하므로 이 점에 유의해야 한다. (1번째 inode라고 해서 냅다 0x100을 곱한 값으로 접근하면 2번째 inode 값이다. 따라서 값에 접근할 때는 1을 뺴줘야 한다.)

 

inode
inode의 i_block

i_block 값을 분석해보면 다음과 같다.

분류 offset 이름
Header 0x06 ~ 0x07 Header의 eh_depth 0 → 따라서 Leaf nodes
Leaf nodes 1 0x00 ~ 0x03 Leaf nodes ee_block 0
0x04 ~ 0x05 Leaf nodes ee_len 1
0x06 ~ 0x07 Leaf nodes ee_start_hi 0x0000
0x08 ~ 0x0B Leaf nodes ee_start_lo 0x202020

 

최종: 블록번호 (ee_start_hi + ee_start_lo) * 한 블록의 크기 4096 bytes (0x1000)

ee_start_hi + ee_start_lo = 0x0000202020

 

(ee_start_hi + ee_start_lo) * 0x1000 = 0x202020000

 

해당 파티션의 첫 번째 블록그룹 시작점에서 0x488000000 만큼 이동하면 home directory로 이동할 수 있다.

그럼 또 Directory Entry를 확인할 수 있다.

home directory

마지막 디렉토리 record_length 값은 0x0FDC(4,060)으로 자신을 제외한 디렉토리 블록의 남은 공간을 표현하는 값이다.

마지막 디렉토리 엔트리는 남은 데이터 블록 공간을 모두 차지한다. 또한 디렉토리 엔트리가 저장되어 있는 블록은 한 개 이상의 블록을 차지하지 않는다.

Offset Size Name 설명
0x00 ~ 0x03 4 bytes inode 0x80002 (524,290)
0x04 ~ 0x05 2 bytes rec_len 0xFDC (4,060)
0x06 1 bytes name_len 0x04
0x07 1 bytes file_type File type code, one of:
0x2 Directory.
0x08 ~  - name[EXT4_NAME_LEN] user

 

inode table에서 0x80002(524,289) 번째 inode 값을 확인한다.

inode
inode의 i_block

분류 offset 이름
Header 0x06 ~ 0x07 Header의 eh_depth 0 → 따라서 Leaf nodes
Leaf nodes 1 0x00 ~ 0x03 Leaf nodes ee_block 0
0x04 ~ 0x05 Leaf nodes ee_len 1
0x06 ~ 0x07 Leaf nodes ee_start_hi 0x0000
0x08 ~ 0x0B Leaf nodes ee_start_lo 0x202021

 

최종: 블록번호 (ee_start_hi + ee_start_lo) * 한 블록의 크기 4096 bytes (0x1000)

ee_start_hi + ee_start_lo = 0x0000202021

 

(ee_start_hi + ee_start_lo) * 0x1000 = 0x202021000

 

해당 파티션의 첫 번째 블록그룹 시작점에서 0x202021000 만큼 이동하면 user로 이동할 수 있다.

그럼 또 Directory Entry를 확인할 수 있다.

user directory entry

Downloads 폴더로 가본다.

Offset Size Name 설명
0x00 ~ 0x03 4 bytes inode 0x80050 (524,368)
0x04 ~ 0x05 2 bytes rec_len 0x14 (20)
0x06 1 bytes name_len 0x09
0x07 1 bytes file_type File type code, one of:
0x2 Directory.
0x08 ~  - name[EXT4_NAME_LEN] Downloads

 

별개로 마지막 디렉토리의 record_length 값을 확인해보자.

record_length 값이 0xE88로 마지막 디렉토리임을 확인할 수 있다.

 

inode table에서 0x80050(524,368) 번째 inode 값을 확인한다.

inode
inode의 i_block

분류 offset 이름
Header 0x06 ~ 0x07 Header의 eh_depth 0 → 따라서 Leaf nodes
Leaf nodes 1 0x00 ~ 0x03 Leaf nodes ee_block 0
0x04 ~ 0x05 Leaf nodes ee_len 1
0x06 ~ 0x07 Leaf nodes ee_start_hi 0x0000
0x08 ~ 0x0B Leaf nodes ee_start_lo 0x202058

 

최종: 블록번호 (ee_start_hi + ee_start_lo) * 한 블록의 크기 4096 bytes (0x1000)

ee_start_hi + ee_start_lo = 0x202058

 

(ee_start_hi + ee_start_lo) * 0x1000 = 0x202058000

 

해당 파티션의 첫 번째 블록그룹 시작점에서 0x202058000 만큼 이동하면 Downloads로 이동할 수 있다.

Flag_of_South_Korea.svg.png

찾고자 하는 Flag_of_South_Korea.svg.png의 Directory Entry를 확인할 수 있다. (빨간색 네모)

Downloads directory

Offset Size Name 설명
0x00 ~ 0x03 4 bytes inode 0x801AA (524,714)
0x04 ~ 0x05 2 bytes rec_len 0xFDC (4,060)
0x06 1 bytes name_len 0x1B
0x07 1 bytes file_type File type code, one of:
0x1 Regular file.
0x08 ~  - name[EXT4_NAME_LEN] Flag_of_South_Korea.svg.png

 

inode table에서 0x 801AA (524,714) 번째 inode 값을 확인한다.

inode

Offset Size Name 설명
0x04 ~ 0x07 4 bytes i_size_lo 0x61C8
0x6C ~ 0x6F 4 bytes i_size_high / i_dir_acl 0x0000

 

inode 분석을 통해 알 수 있는 파일의 크기는 0x61C8이다.

inode의 i_block

분류 offset 이름
Header 0x06 ~ 0x07 Header의 eh_depth 0 → 따라서 Leaf nodes
Leaf nodes 1 0x00 ~ 0x03 Leaf nodes ee_block 0
0x04 ~ 0x05 Leaf nodes ee_len 7
0x06 ~ 0x07 Leaf nodes ee_start_hi 0x0000
0x08 ~ 0x0B Leaf nodes ee_start_lo 0x20BCA7

 

최종: 블록번호 (ee_start_hi + ee_start_lo) * 한 블록의 크기 4096 bytes (0x1000)

ee_start_hi + ee_start_lo = 0x20BCA7

 

(ee_start_hi + ee_start_lo) * 0x1000 = 0x20BCA7000

 

해당 파티션의 첫 번째 블록그룹 시작점에서 0x20BCA7000 만큼 이동하면 최종 목적지인 png 파일이 저장되어 있는 곳으로 이동할 수 있다.

Flag_of_South_Korea.svg.png

baseball.jpg

baseball.jpg의 Downloads 디렉토리 엔트리는 다음과 같다. (연두색 네모)

Downloads directory

baseball.jpg 디렉토리 엔트리를 분석해보면 다음과 같다.

Offset Size Name 설명
0x00 ~ 0x03 4 bytes inode 0x80D92 (527,762)
0x04 ~ 0x05 2 bytes rec_len 0xFB8 (4,024)
0x06 1 bytes name_len 0xC (12)
0x07 1 bytes file_type File type code, one of:
0x1 Regular file.
0x08 ~  - name[EXT4_NAME_LEN] baseball.jpg

 

inode table에서 0x80D92 (527,762) 번째 inode 값을 확인한다.

inode

Offset Size Name 설명
0x04 ~ 0x07 4 bytes i_size_lo 0x2E245
0x6C ~ 0x6F 4 bytes i_size_high / i_dir_acl 0x0000

 

inode 분석을 통해 알 수 있는 파일의 크기는 0x61C8이다.

inode의 i_block

분류 offset 이름
Header 0x06 ~ 0x07 Header의 eh_depth 0 → 따라서 Leaf nodes
Leaf nodes 1 0x00 ~ 0x03 Leaf nodes ee_block 0
0x04 ~ 0x05 Leaf nodes ee_len 0x2F (47)
0x06 ~ 0x07 Leaf nodes ee_start_hi 0x0000
0x08 ~ 0x0B Leaf nodes ee_start_lo 0x20BA7D

 

최종: 블록번호 (ee_start_hi + ee_start_lo) * 한 블록의 크기 4096 bytes (0x1000)

ee_start_hi + ee_start_lo = 0x20BA7D

 

(ee_start_hi + ee_start_lo) * 0x1000 = 0x20BA7D000

 

해당 파티션의 첫 번째 블록그룹 시작점에서 0x20BCA7000 만큼 이동하면 최종 목적지인 jpg 파일이 저장되어 있는 곳으로 이동할 수 있다.

baseball.jpg

'분야 > Digital Forensics' 카테고리의 다른 글

FAT32 삭제된 파일 복구  (0) 2024.03.11
FAT32 File System  (1) 2024.03.04
Ext4 File System  (0) 2023.09.12
윈도우 아티팩트 정리  (1) 2023.09.07
NTFS 삭제된 파일 복원  (1) 2023.08.29