모두의 dream

Ext4 File System 본문

분야/Digital Forensics

Ext4 File System

오리꽥이로 2023. 9. 12. 21:36

*공부를 위해 정리한 내용으로 틀린 부분이 있을 수 있습니다. *

미리 쓰는 느낀점: NTFS, FAT만 보고 가볍게 덤볐다간 큰 코 다칠 수 있습니다. 너무 어렵다;;

I. GPT (MBR) 

디스크의 기본 구조인 GPT(MBR)에 대해 서술한다.

컴퓨터(Ext4) 부팅 절차

BIOS → POST → MBR(GPT) → GRUB(Boot Loader) → 메모리(RAM)에 커널 로딩 → 운영체제 실행 및 제어권 이동

GPT (MBR)

실습 파일을 GPT 방식으로 만들어서 GPT 를 설명한다.

 

GPT는 기존 MBR의 한계를 해결하기 위해 만들어졌다.

내 컴퓨터의 펌웨어가 레거시(BIOS, Basic Input/Output System)라면 MBR 파티션을 사용하고, UEFI(Unified Extensible Firmware Interface)라면 GPT 파티션을 사용한다. 

파일시스템의 종류와 상관없이 MBR과 GPT는 디스크의 첫 번째 섹터에 위치하는 데이터로, 운영체제에 대한 정보가 담겨있는 영역이다. 따라서 이 영역이 손상될 경우 운영체제가 정상적으로 부팅되지 않는다.

따라서 GPT(MBR) 영역을 파괴시키거나 암호화 시키는 악성코드가 존재한다.

 

GPT 구조

GPT 구조의 첫 번째 섹터는 호환성을 위해 MBR과 동일하다.

LBA(Logical Block Addressing)는 논리적인 주소로 섹터에 접근하는 방법이다. 섹터 1개를 LBA n 으로 부르게 된다.

(참고: https://velog.io/@markyang92/partition)

MBR 영역 구분 (GRUB Boot Loader, Partition table entry, signature)

MBR은 GRUB Boot Loader, Partition table entry, signature로 구성되어 있다.

 

Partition table entry는 위 사진처럼 16bytes 씩 4개로 구성되어 있다.

 

Partition table은 부팅이 가능한 파티션의 정보가 있는 곳이다. (멀티 부팅을 하게 되면 총 4개의 파티션 까지 가능)

 

Partition table entry의 데이터 구조는 다음과 같다.

Partition table entry

Partition table entry 에서 유심히 본 곳은 부트 식별자(Boot indicator) 와 파티션 타입, 파티션의 시작위치를 가리키는 LBA 주소값과 파티션 전체의 섹터 개수였다.

 

Partition table entry

offset (bytes) 내용 해석
0x04 (1 bytes) Partition Type 0xEE, GPT 파티션
0x08 (4 bytes) LBA 주소값 0x01(리틀엔디안) → 1번 섹터(주소: 1 * 512 = 0x200)
0x0C (4 bytes) 섹터 개수 0x4FFFFFF → 83,886,079개

GPT Header

GPT Header 구조

GPT에 대한 설정 정보를 저장하고 있으며 92bytes로 구성되어 있다.

Header 에서 유심히 본 곳은 Backup LBA, Starting LBA for partition, Ending LBA for partitions 이었다.

위 3개의 정보 (8bytes 씩)

Backup LBA: 0x4FFFFFF → 83,886,079 섹터

83,886,079 섹터

위 섹터에 가보면 GPT Header 가 백업 되어있다.

offset 내용 해석
0x20 (8 bytes) Backup LBA 0x4FFFFFF  → 83,886,079 섹터
0x28 (8 bytes) Starting LBA for partition 0x800 → 2,048 섹터
0x30 (8 bytes) Ending LBA for partitions 0x4FFFFDE → 83,886,046 섹터

 

Starting LBA for partion, 2,048 섹터에 가보면 첫 번째 파티션을 확인할 수 있다.

정확히 뭔지는 모르겠지만 윈도우처럼 리눅스에 기본적으로 존재하는 파티션이 아닐까 예상해본다. 

2,048 섹터

GPT Partition Entry

 

총 2개의 파티션이 확인되며 FTK Imager로 확인해보면 동일하다.

현재 실습파일의 파티션 개수

GPT Partition entry의 구조는 다음과 같다.

Partition Entry 구조

offset bytes 내용
0 (0x00) 16 bytes 파티션 타입을 표현하는 고유한 정보
16 (0x10) 16 bytes 파티션마다 할당하는 고유한 값
32 (0x20) 8 bytes 파티션 시작 주소
40 (0x28) 8 bytes 파티션 끝 주소
48 (0x30) 8 bytes 파티션 속성 (플래그)
56 (0x38) 72 bytes 파티션 이름

아래 사진으로 자세히 분석해보겠다.

Partition Entry 2번째 파티션

Partition Entry 2번째 파티션의 정보는 다음과 같다.

First LBA 0x1000 → 4,096 섹터
Last LBA 0x4FFE7FF → 83,879,935 섹터

II. Ext4 파일시스템

Extended File System, 리눅스에서 사용하기 위해 개발된 Ext 파일시스템의 4번째 후속 버전이다

III. Ext4 파일시스템 구조

Ext4의 구조

Ext4 파일시스템은 블록이라는 단위로 구성되어 있으며 블록의 크기는 일반적으로 4096 bytes 이다. (1KB, 2KB, 4KB 중 선택하여 사용 가능하다.)

블록 그룹 (Block Group)

크게는 블록 그룹(Block Group), 세부적으로 여러개의 블록(Block)들이 존재한다.

한 블록의 크기는 일반적으로 1KB, 2KB, 4KB, 8KB로 설정될 수 있고, 흔히 사용되는 크기는 4KB(4096 Bytes)이다.

Ext4의 구조

슈퍼블록 (Super Block): 슈퍼블록은 파일 시스템에 대한 전반적인 정보를 저장한다. 따라서 여러개의 블록 그룹에 모두 동일한 값으로 저장되어 있다.(총 블록 수, 사용 가능한 블록 수, 사용 중인 블록 수 등)

그룹 디스크립터 (Group Descriptors): 그룹 디스크립터는 각각의 블록 그룹에 대한 정보를 가지고 있다.

GDT 예약 블록 (Reserved GDT Block): 파일시스템 확장을 위해 예약되어 있는 영역.

블록 비트맵 (Block Bitmap): 비트맵은 해당 블록 그룹 내에서 사용 가능한(할당 된) 데이터 블럭을 추적.
아이노드 비트맵 (Inode Bitmap): 아이노드 비트맵은 해당 그룹 내에서 사용 가능한(할당 된) 아이노드를 추적.
아이노드 테이블 (Inode Table): 아이노드 테이블은 개별 파일/디렉터리에 대한 메타데이터(소유자 정보, 접근 권한 등)와 데이터가 저장된 실제 위치 정보 등을 포함하는 아이노드들을 저장하고 있다.
데이터 블럭 (Data Blocks): 실제 파일 데이터가 저장되는 곳이다.

Block Group 0

파일시스템에 존재하는 Block Group에 대한 정보들이 저장되어 있다.

정보들은 0번  Block Group 의 Super block 과 Group descriptors에 저장되며 각 그룹들은 이 데이터만 사용하지만 손상될 경우를 대비하여 각 그룹에 사본 또한 저장되어 있다.

 

Block Group 0의 첫 1024 bytes(Group 0 padding)는 여러 이유로 사용되지 않는다.

Block Group 0 첫 1024 bytes

슈퍼블록 (Super Block)

Super block의 크기는 1,024 Bytes이며 파일 시스템에 대한 전반적인 정보를 저장하고 있다.

Block Group 0의 슈퍼블록

Super block 의 Magic Number(시그니처) 값은 Super block 시작 지점에서 0x38 앞으로 가면 있는 "0xEF53" 이다.

슈퍼블록 Magic Number

Super block 의 중요한 몇가지 필드를 확인해보자.

offset 내용 해석
0x00 ~ 0x03 s_inodes_count
(총 inode 개수)
0x280000 → 2,621,440
0x04 ~ 0x07 s_blocks_count_lo
(총 Block 개수)
0x009FFD00 → 10,484,992
0x0C ~ 0x0F s_free_blocks_count_lo
(사용 가능한 Block 개수)
0x073C553 → 7,587,155
0x10 ~ 0x13 s_free_inodes_count
(사용 가능한 inode 개수)
0x24D826 → 2,414,630
0x14 ~ 0x17 s_first_data_block
(첫 번째 Data Block)
0x00000000 → 0
0x18 ~ 0x1B s_log_block_size
(기본 블록 크기)
계산방법: 2 ^ (10 + s_log_block_size))
2 ( 2 ^ (10 + 2))  4096 Bytes
0x20 ~ 0x23 s_blocks_per_group
(그룹 별 Blocks)
0x8000 → 32,768
0x28 ~ 0x2B s_inodes_per_group
(그룹 별 Inodes)
0x2000 → 8,192
0x38 ~ 0x39 s_magic
(Magic Nuber (Signature))
0xEF53
0x58 ~ 0x59 s_inode_size
(각 inode의 크기)
0x100 → 256 bytes
0x60 ~ 0x63 s_feature_incompat 0x2C2 0010 1100 0010
설정되어 있는 값:
INCOMPAT_FILETYPE, INCOMPAT_EXTENTS, INCOMPAT_64BIT, INCOMPAT_FLEX_BG
0x68 ~ 0x77 s_uuid[16]
(128 bits 볼륨 UUID)
F3 04 36 D8 B3 E6 47 09 AD F6 BC 
40 3A 9D 4C C8
0xD0 ~ 0xDF s_journal_uuid[16]
(저널 superblock UUID)
00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00
0x108 ~0x10B s_mkfs_time
(파일시스템 생성시간)
0x65BC8551 → 1,706,853,713
0x160 ~ 0x163 s_flags
(Flags)
0x00000001 → 1
0x170 ~ 0x173 s_raid_stripe_width
(RAID 현재 디스크 논리 번호,
RAID stripe width )
0x00000000 → 0
0x274 ~ 0x3FB s_reserved[98]
(padding to the end of the block)
-
0x3FC ~ 0x3FF s_checksum
(superblock checksum)
33 5A BD E8

(1) 32비트/64비트 확인하기

현재 Ext4가 32비트, 64비트 중 어떤 것으로 운영되는지 확인해보려면 s_feature_incompat 필드를 확인해보면 된다.

s_feature_incompat 필드의 INCOMPAT_64BIT 플래그(값: 0x80, 7번째 비트)값이 1로 설정되어 있으면 64비트 모드, 설정되어 있지 않으면 32비트 모드로 운영됨을 뜻한다.

 

s_feature_incompat  필드의 플래그 값들은 다음과 같다.

0x1 Compression. Not implemented. (INCOMPAT_COMPRESSION).
0x2 Directory entries record the file type. See ext4_dir_entry_2 below. (INCOMPAT_FILETYPE).
0x4 Filesystem needs journal recovery. (INCOMPAT_RECOVER).
0x8 Filesystem has a separate journal device. (INCOMPAT_JOURNAL_DEV).
0x10 Meta block groups. See the earlier discussion of this feature. (INCOMPAT_META_BG).
0x40 Files in this filesystem use extents. (INCOMPAT_EXTENTS).
0x80 Enable a filesystem size over 2^32 blocks. (INCOMPAT_64BIT).
Multiple mount protection. Prevent multiple hosts from mounting the filesystem concurrently by updating a reserved block
0x100 periodically while mounted and checking this at mount time to determine if the filesystem is in use on another host. (INCOMPAT_MMP).
0x200 Flexible block groups. See the earlier discussion of this feature. (INCOMPAT_FLEX_BG).
0x400 Inodes can be used to store large extended attribute values (INCOMPAT_EA_INODE).
0x1000 Data in directory entry. Allow additional data fields to be stored in each dirent, after struct ext4_dirent. The presence of extra data is indicated by flags in the high bits of ext4_dirent file type flags (above EXT4_FT_MAX). The flag EXT4_DIRENT_LUFID = 0x10 is used to store a 128-bit File Identifier for Lustre. The flag EXT4_DIRENT_IO64 = 0x20 is used to store the high word of 64-bit inode numbers. Feature still in development. (INCOMPAT_DIRDATA).
0x2000 Metadata checksum seed is stored in the superblock. This feature enables the administrator to change the UUID of a metadata_csum filesystem while the filesystem is mounted; without it, the checksum definition requires all metadata blocks to be rewritten. (INCOMPAT_CSUM_SEED).
0x4000 Large directory >2GB or 3-level htree. Prior to this feature, directories could not be larger than 4GiB and could not have an htree more than 2 levels deep. If this feature is enabled, directories can be larger than 4GiB and have a maximum htree depth of 3. (INCOMPAT_LARGEDIR).
0x8000 Data in inode. Small files or directories are stored directly in the inode i_blocks and/or xattr space. (INCOMPAT_INLINE_DATA).
0x10000 Encrypted inodes are present on the filesystem (INCOMPAT_ENCRYPT).

 

리틀엔디안으로 값을 가져온 후

각 자리에 맞게 해석해주면 된다. (INCOMPAT_64BIT 는 7번째 비트를 해석하면 된다.)

INCOMPAT_64BIT  값을 갖고 있는 s_feature_incompat  필드

 

offset 내용 해석
0x60 ~ 0x63 s_feature_incompat 0x2C2 → '0010 1100 0010' 
sparse_super: 1

 

현재 실습 파일의 INCOMPAT_64BIT 값은 1 이므로 64비트 모드로 운영되고 있음을 확인할 수 있다.

(2) Super block 백업본이 저장되는 블록 확인하기

sparse_super 이라는 값이 활성화되면 Super block 백업본이 블록 그룹 0과 1 그리고 3, 5, 7의 거듭제곱 그룹에 저장된다.

활성화 되어있지 않는다면 모든 블록 그룹에 슈퍼블록 백업본이 저장된다.

 

sparse_super 값은  s_feature_ro_compat 필드에 있으며 0x64 ~ 0x67 까지 값을 가지고 있다.

값을 해석하는 방법은 다음과 같다.

 

1. 리틀 엔디안으로 값을 가져온 후 2진수로 변환한다.

2. 변환된 2진수의 각 비트별 자릿수는 아래의 값들을 가지고 있다.

0x1 Sparse superblocks. See the earlier discussion of this feature. (RO_COMPAT_SPARSE_SUPER).
0x2 Allow storing files larger than 2GiB (RO_COMPAT_LARGE_FILE).
0x4 Was intended for use with htree directories, but was not needed. Not used in kernel or e2fsprogs (RO_COMPAT_BTREE_DIR).
0x8 This filesystem has files whose space usage is stored in i_blocks in units of filesystem blocks, not 512-byte sectors. Inodes using this feature will be marked with EXT4_INODE_HUGE_FILE. (RO_COMPAT_HUGE_FILE)
0x10 Group descriptors have checksums. In addition to detecting corruption, this is useful for lazy formatting with uninitialized groups (RO_COMPAT_GDT_CSUM).
0x20 Indicates that the old ext3 32,000 subdirectory limit no longer applies. A directory's i_links_count will be set to 1 if it is incremented past 64,999. (RO_COMPAT_DIR_NLINK).
0x40 Indicates that large inodes exist on this filesystem, storing extra fields after EXT2_GOOD_OLD_INODE_SIZE. (RO_COMPAT_EXTRA_ISIZE).
0x80 This filesystem has a snapshot. Not implemented in ext4. (RO_COMPAT_HAS_SNAPSHOT).
0x100 Quota is handled transactionally with the journal (RO_COMPAT_QUOTA).
0x200 This filesystem supports "bigalloc", which means that filesystem block allocation bitmaps are tracked in units of clusters (of blocks) instead of blocks (RO_COMPAT_BIGALLOC).
0x400 This filesystem supports metadata checksumming. (RO_COMPAT_METADATA_CSUM; implies RO_COMPAT_GDT_CSUM, though GDT_CSUM must not be set)
0x800 Filesystem supports replicas. This feature is neither in the kernel nor e2fsprogs. (RO_COMPAT_REPLICA).
0x1000 Read-only filesystem image; the kernel will not mount this image read-write and most tools will refuse to write to the image. (RO_COMPAT_READONLY).
0x2000 Filesystem tracks project quotas. (RO_COMPAT_PROJECT)

 

3. 각 자리에 맞는 값을 해석해주면 되고, sparse_super 값은 첫 번째 플래그인 RO_COMPAT_SPARSE_SUPER(값: 0x1, 0번째 비트)의 값을 확인해주면 된다.

sparse_super 값을 갖고 있는 s_feature_ro_compat 필드

offset 내용 해석
0x64 ~ 0x67 s_feature_ro_compat 0x46B → ''0100 0110 1011"
sparse_super: 1

 

특정 블록 그룹에만 백업이 저장되는 경우: sparse_super 값이 "1"

모든 블록 그룹에 백업이 저장되는 경우: sparse_super 값이 "0"

 

현재 실습 파일의 sparse_super 값은 1 이므로 특정 블록 그룹(0과 1 그리고 3, 5, 7의 거듭제곱 그룹)에 백업이 저장되고 있다는 사실을 알 수 있다. 이 사실을 증명하기 위해 Block Group의 주소를 계산해봤다.

 

현재 블록의 크기(s_log_block_size)는 4096 bytes, 하나의 블록 그룹이 가지고 있는 블록의 개수(s_blocks_per_group)는 32,768개이다.

 

Block Group 1의 시작 주소를 구하기 위해 Block Group 0의 시작 주소 0x200000에 4,096 * 32,768의 결과값 0x8000000를 더해주면 Block Group 1의 시작주소로 이동할 수 있다.

Block Group Offset
0 0x200000
1 0x8200000
2 0x10200000
3 0x18200000
4 0x20200000
5 0x28200000
6 0x30200000
7 0x38200000
8 0x40200000
9 0x48200000
·
·
·
·
·
·

 

Super Block이 0과 1 그리고 3, 5, 7의 거듭제곱 그룹에만 있는지 직접 확인해봤다.

Block Group 0 ~ 9까지 Super Block 유무 조사

확인해본 결과 0과 1 그리고 3, 5, 7의 거듭제곱 그룹에서 Super Block의 Magic Number "0xEF53"을 확인할 수 있었다.

 

Super block 시작점에서 한 블록의 크기 4096 bytes 만큼 이동하면 Group Descriptors 로 이동할 수 있다.

다만 Block Group 0의 경우 첫 1024 bytes가 NULL 값으로 채워져 있었으므로 3072 bytes 만큼 이동하면 Group Descriptors 로 이동할 수 있다. (혹은 NuLL 값의 시작점부터 (0x200000) 4096 bytes 만큼 이동해도 된다.)

그룹 디스크립터 테이블 (Group Descriptors Table)

Group Descriptor

그룹 디스크립터는 블록 비트맵 주소, 아이노트 비트맵 주소와 아이노드 테이블 주소 등과 같은 각 블록 그룹의 주요 정보 위치를 기록하고 있다. 32 bits일 경우 블록 디스크립터는 32 bytes의 길이, 64 bits일 경우 64 bytes의 길이를 갖게 된다.

 

Group descriptor의 구조는 다음과 같다. 

Group Descriptor 구조

나머지 필드의 값들은 이후 과정에 크게 영향이 없어보여서 별도로 표시하지 않았으며, 추후 필요해질 경우 추가할 예정이다. (직접 확인: Ext4 Disk Layout - Block Descriptor)

 

현재 실습파일은 64비트 모드이므로 블록 디스크립터의 길이는 64 bytes이다.

그룹 당 블록의 개수는 32,768개로 super block의 s_blocks_per_group 필드의 값을 통해 알 수 있다.

따라서 현재 Group Descriptors 개수 또한 32,768개이고 전체 크기는 32,768 * 64의 결과인 0x200000 이다.

블록 비트맵 (Block Bitmap)

Block Group 내의 데이터 Block 들의 사용량을 비트 단위로 기록한다.

Block Bitmap의 크기는 한 블록으로 4096 bytes이다.

 

현재 한 Block 의 크기는 4096 bytes, Group Descriptor에서 확인한 Block bitmap offset은 0x406 부터 1씩 증가하고 있다.

Super Block(혹은 Block Group의 시작지점) 에서 부터 0x406 블록 만큼 떨어져 있다는 뜻으로 주소로 계산해보면 다음과 같다.

 

Super Block 시작주소 (혹은 Block Group의 시작지점) : 0x200000

Descriptor 0의 Block Bitmap 주소: 1030(0x406) * 4096 = 0x406000

Descriptor 1의 Block Bitmap 주소: 1030(0x407) * 4096 = 0x407000

 

이동해보면 Block Bitmap을 확인할 수 있다.

각 Descriptor의 Block Bitmap은 정확히 1 Block (4096 bytes) 만큼 차이난다.

Descriptor 0, Descriptor 1의 Block Bitmap

아이노드 비트맵 (inode Bitmap)

inode Table에서 사용중인 항목을 비트 단위로 기록한다.

 

현재 한 Block 의 크기는 4096 bytes, Group Descriptor에서 확인한 inode bitmap offset은 0x416 부터 1씩 증가하고 있다.

Super Block (혹은 Block Group의 시작지점) 에서 부터 0x416 블록 만큼 떨어져 있다는 뜻으로 주소로 계산해보면 다음과 같다.

 

Super Block 시작주소 (혹은 Block Group의 시작지점) : 0x200000

Descriptor 0의 inode Bitmap 주소: 1046(0x416) * 4096 = 0x416000

Descriptor 1의 inode Bitmap 주소: 1047(0x417) * 4096 = 0x417000

 

이동해보면 inode Bitmap을 확인할 수 있다.

각 Descriptor의 inode Bitmap은 정확히 1 Block (4096 bytes) 만큼 차이난다.

Descriptor 0, Descriptor 1의 inode Bitmap

아이노드 테이블 (inode Table)

개별 파일/디렉터리에 대한 메타데이터(소유자 정보, 접근 권한 등)와 데이터가 저장된 실제 위치 정보 등을 포함하는 아이노드들을 저장하고 있다.

 

블록 그룹에 있는 inode의 수는 8,192개이며, 각 inode의 크기는 256 bytes이다.

 

현재 한 Block 의 크기는 4096 bytes, Group Descriptor에서 확인한 inode Table offset은 0x426 부터 시작한다.

Super Block (혹은 Block Group의 시작지점) 에서 부터 0x426 블록 만큼 떨어져 있다는 뜻으로 주소로 계산해보면 다음과 같다.

 

Super Block 시작주소 (혹은 Block Group의 시작지점) : 0x200000

Descriptor 0의 inode Table 주소: 1062(0x426) * 4096 = 0x426000

Descriptor 1의 inode Table 주소: 1574(0x626) * 4096 = 0x626000

 

이동해보면 inode Table을 확인할 수 있다. 

Descriptor 0, Descriptor 1의 inode Table

(1) inode 개념

inode는 특정 파일이나 디렉토리를 가리키는 고유한 번호이다.

소유자 UID, 파일 크기, 액세스 시간, 수정 시간, 삭제 시간 등의 메타데이터가 포함되어 있다.

 

inode의 크기는 기본적으로 256 bytes로 실습파일의 inode 크기는 Super block을 통해 256bytes로 확인할 수 있다.

inode table에 inode는 1번부터 시작되며 오름차순으로 나열되어 있다.

(각 그룹마다 inode table이 있지만 inode 번호는 초기화되지 않고 쭉 이어진다.)

1번 inode

또한 특별한 기능을 위해 예약되어 있는 inode 값이 있다.  (Special inodes)

만약 삭제된 특정 파일을 복구하고자 한다면 2번 root directory, 8번 journal inode를 먼저 확인해보면 된다.

inode Description
0 Doesn't exist; there is no inode 0. (0번은 존재하지 않음.)
1 List of defective blocks. 
2 Root Directory
3 User quota
4 Group quota
5 Boot loader
6 Undelete directory
7 Reserved group descriptor indoe
8 journal inode
9 The exclude inode
10 Replica inode
11 Traditional first non-reserved inode. Usually used for 
lost+found directory

(2) inode 구조

inode의 구조는 다음과 같다.

offset 이름 내용
0x00 ~ 0x01 i_mode
File mode. Any of:
0x1 S_IXOTH (Others may execute)
0x2 S_IWOTH (Others may write)
0x4 S_IROTH (Others may read)
0x8 S_IXGRP (Group members may execute)
0x10 S_IWGRP (Group members may write)
0x20 S_IRGRP (Group members may read)
0x40 S_IXUSR (Owner may execute)
0x80 S_IWUSR (Owner may write)
0x100 S_IRUSR (Owner may read)
0x200 S_ISVTX (Sticky bit)
0x400 S_ISGID (Set GID)
0x800 S_ISUID (Set UID)
These are mutually-exclusive file types:
0x1000 S_IFIFO (FIFO)
0x2000 S_IFCHR (Character device)
0x4000 S_IFDIR (Directory)
0x6000 S_IFBLK (Block device)
0x8000 S_IFREG (Regular file)
0xA000 S_IFLNK (Symbolic link)
0xC000 S_IFSOCK (Socket)
0x02 ~ 0x03 i_uid Lower 16-bits of Owner UID.
0x04 ~ 0x07 i_size_lo
(Size in bytes)
Lower 32-bits of size in bytes.
0x08 ~ 0x0B i_atime
(Access time)
Last access time, in seconds since the epoch. However, if the EA_INODE inode flag is set, this inode stores an extended attribute value and this field contains the checksum of the value.
0x0C ~ 0x0F i_ctime
(Inode Change time)
Last inode change time, in seconds since the epoch. However, if the EA_INODE inode flag is set, this inode stores an extended attribute value and this field contains the lower 32 bits of the attribute value's reference count.
0x10 ~ 0x13 i_mtime
(Modification time)
Last data modification time, in seconds since the epoch. However, if the EA_INODE inode flag is set, this inode stores an extended attribute value and this field contains the number of the inode that owns the extended attribute.
0x14 ~ 0x17 i_dtime
(Deletion Time)
Deletion Time, in seconds since the epoch.
0x18 ~ 0x19 i_gid
(Low 16 bits of Group Id)
Lower 16-bits of GID.
0x1A ~ 0x1B i_links_count
(Links count)
Hard link count. Normally, ext4 does not permit an inode to have more than 65,000 hard links. This applies to files as well as directories, which means that there cannot be more than 64,998 subdirectories in a directory (each subdirectory's '..' entry counts as a hard link, as does the '.' entry in the directory itself). With the DIR_NLINK feature enabled, ext4 supports more than 64,998 subdirectories by setting this field to 1 to indicate that the number of hard links is not known.
0x1C ~ 0x1F i_blocks_lo
(Blocks count)
Lower 32-bits of "block" count. If the huge_file feature flag is not set on the filesystem, the file consumes i_blocks_lo 512-byte blocks on disk. If huge_file is set and EXT4_HUGE_FILE_FL is NOT set in inode.i_flags, then the file consumes i_blocks_lo + (i_blocks_hi << 32) 512-byte blocks on disk. If huge_file is set and EXT4_HUGE_FILE_FL IS set in inode.i_flags, then this file consumes (i_blocks_lo + i_blocks_hi << 32) filesystem blocks on disk.
0x20 ~ 0x23 i_flags
(File flags)
Inode flags. Any of:
0x1 This file requires secure deletion (EXT4_SECRM_FL). (not implemented)
0x2 This file should be preserved, should undeletion be desired (EXT4_UNRM_FL). (not implemented)
0x4 File is compressed (EXT4_COMPR_FL). (not really implemented)
0x8 All writes to the file must be synchronous (EXT4_SYNC_FL).
0x10 File is immutable (EXT4_IMMUTABLE_FL).
0x20 File can only be appended (EXT4_APPEND_FL).
0x40 The dump(1) utility should not dump this file (EXT4_NODUMP_FL).
0x80 Do not update access time (EXT4_NOATIME_FL).
0x100 Dirty compressed file (EXT4_DIRTY_FL). (not used)
0x200 File has one or more compressed clusters (EXT4_COMPRBLK_FL). (not used)
0x400 Do not compress file (EXT4_NOCOMPR_FL). (not used)
0x800 Encrypted inode (EXT4_ENCRYPT_FL). This bit value previously was EXT4_ECOMPR_FL (compression error), which was never used.
0x1000 Directory has hashed indexes (EXT4_INDEX_FL).
0x2000 AFS magic directory (EXT4_IMAGIC_FL).
0x4000 File data must always be written through the journal (EXT4_JOURNAL_DATA_FL).
0x8000 File tail should not be merged (EXT4_NOTAIL_FL). (not used by ext4)
0x10000 All directory entry data should be written synchronously (see dirsync) (EXT4_DIRSYNC_FL).
0x20000 Top of directory hierarchy (EXT4_TOPDIR_FL).
0x40000 This is a huge file (EXT4_HUGE_FILE_FL).
0x80000 Inode uses extents (EXT4_EXTENTS_FL).
0x200000 Inode stores a large extended attribute value in its data blocks (EXT4_EA_INODE_FL).
0x400000 This file has blocks allocated past EOF (EXT4_EOFBLOCKS_FL). (deprecated)
0x01000000 Inode is a snapshot (EXT4_SNAPFILE_FL). (not in mainline)
0x04000000 Snapshot is being deleted (EXT4_SNAPFILE_DELETED_FL). (not in mainline)
0x08000000 Snapshot shrink has completed (EXT4_SNAPFILE_SHRUNK_FL). (not in mainline)
0x10000000 Inode has inline data (EXT4_INLINE_DATA_FL).
0x20000000 Create children with the same project ID (EXT4_PROJINHERIT_FL).
0x80000000 Reserved for ext4 library (EXT4_RESERVED_FL).
Aggregate flags:
0x4BDFFF User-visible flags.
0x4B80FF User-modifiable flags. Note that while EXT4_JOURNAL_DATA_FL and EXT4_EXTENTS_FL can be set with setattr, they are not in the kernel's EXT4_FL_USER_MODIFIABLE mask, since it needs to handle the setting of these flags in a special manner and they are masked out of the set of flags that are saved directly to i_flags
 0x24 ~ 0x27 OS dependent 1 Union osd1
Tag: linbux1, hurd1, masix1
0x28 ~ 0x63
(60bytes)
i_block[EXT4_N_BLOCKS=15]
(Pointers to blocks)
Block map or extent tree. See the section "The Contents of inode.i_block".
0x64 ~ 0x67 i_generation
(File version (for NFS))
File version (for NFS).
0x68 ~ 0x6B i_file_acl_lo
(File ACL)
Lower 32-bits of extended attribute block. ACLs are of course one of many possible extended attributes; I think the name of this field is a result of the first use of extended attributes being for ACLs.
0x6C ~ 0x6F i_size_high / i_dir_acl Upper 32-bits of file/directory size. In ext2/3 this field was named i_dir_acl, though it was usually set to zero and never used.
0x70 ~ 0x73 i_obso_faddr
(Obsoleted fragment address)
(Obsolete) fragment address.
0x74 ~ 0x7F OS dependent 2 Union osd2:
Tag: linux2, hurd2, masix2
0x80 ~ 0x81 i_extra_isize Size of this inode - 128. Alternately, the size of the extended inode fields beyond the original ext2 inode, including this field.
0x82 ~ 0x83 i_checksum_hi
(crc32c(uuid+inum+inode) BE)
Upper 16-bits of the inode checksum.
0x84 ~ 0x87 i_ctime_extra
( extra Change time      (nsec << 2 | epoch))
Extra change time bits. This provides sub-second precision. See Inode Timestamps section.
0x88 ~ 0x8B i_mtime_extra
(extra Modification time(nsec << 2 | epoch))
Extra modification time bits. This provides sub-second precision.
0x8C ~ 0x8F i_atime_extra
(extra Access time      (nsec << 2 | epoch))
Extra access time bits. This provides sub-second precision.
0x90 ~ 0x93 i_crtime
( File Creation time)
File creation time, in seconds since the epoch.
0x94 ~ 0x97 i_crtime_extra
(extra FileCreationtime (nsec << 2 | epoch))
Extra file creation time bits. This provides sub-second precision.
0x98 ~ 0x9B i_version_hi Upper 32-bits for version number.
0x9C ~ 0x9F i_projid Project ID.

 

Union osd1, Union osd2 의 자세한 값들은 문서를 확인해 보면 된다.

(3) inode의 i_block 필드

0x28 번째 부터 0x63까지 존재하는 i_block 필드는 60 bytes의 길이를 갖고 있으며 inode가 기술하는 파일의 종류에 따라 다양하게 사용될 수 있다.

일반적으로 파일(혹은 디렉토리) 데이터 블록의 주소를 가리킬때 사용하고, 특수 파일은 특수한 목적에 사용한다.

 

Symbolic Links

"The target of a symbolic link will be stored in this field if the target string is less than 60 bytes long. Otherwise, either extents or block maps will be used to allocate data blocks to store the link target." 라는 문장이 있는데 정확히는 모르겠지만 서술해보면 다음과 같다.

 

i_block이 가리키는 파일이 심볼릭 링크 파일일때 상황을 설명하는 것 같다.

대상 경로 문자열의 길이가 60 bytes 미만일 경우 경로 문자열 자체를 i_block 필드에 저장한다.

대상 경로 문자열의 길이가 60 bytes 이상일 경우에는 별도의 블록을 할당한 후 그 블록에 경로를 저장한다. 이때 사용되는게 ext4의 extents 구조나 block map 구조이다. i_block 필드는 할당한 별도의 블록을 가리키게 된다.

 

Direct(직접)/Indirect(간접) Block Addressing

ext2/3에서 사용된 방식으로 직접 / 간접블록 방식으로 파일에 접근한다.

총 15개의 엔트리가 존재하며, 12개의 직접블록, 3개의 간접블록이 있다.

 

12개의 직접 블록은 파일의 실제 데이터가 저장된 블록을 직접 가리키고 있다.

 

3개의 간접블록은 각각 Single(단일) Indirect Block, Double(이중) Indirect Block, Triple(삼중) Indirect Block으로 직접블록 만으로는 가리킬 수 없는 크기를 갖고 있는 파일을 가리킬 때 사용된다.

 

단점으로는 연속된 파일 (큰 파일)을 관리할 때 비효율적이다.

예시) 1000개의 연속된 블록을 가리키기 위한 간접 블록이 필요하다.

 

Extent Tree

ext4에서 Direct(직접)/Indirect(간접) Block Addressing 의 단점을 개선하기 위해 나온 파일 접근 방식.

연속된 블록을 가리킬 때 필요한 자원이 감소한다.

 

Extent Tree의 구조는 다음과 같다.

Extent Tree 구조

12 bytes의 Header와 최대 4개의 Extent 엔트리(각 12 bytes, 총 48 bytes) 로 구성되어 있다.

Extent Tree의 Root Node는 inode의 i_block에 저장되며, 이를 통해 추가 메타데이터 블록을 사용하지 않고 4개의 Extent를 기록할 수 있다. (i_block 필드에 있는 extent 와 extent block 은 다르다. extent block이 i_block 필드로 부터 참조가 되는건 맞다.)

 

5개 이상의 extent 가 필요한 대용량 파일은 HTree 방식의 extent tree가 사용된다고 한다.

참고 링크: POSIX 알아보기 #1

 

구조는 다음과 같은데 지금 당장 이해하기엔 어려워 보이므로 파일 복구과정 포스팅, 혹은 별도의 포스팅에서 다뤄보려고 한다.

그림 출처:  https://www.kernel.org/doc/ols/2007/ols2007v2-pages-21-34.pdf

 

Header는 고정이며 상황에 따라 Internal nodes, Leaf nodes 가 사용된다.

Header의 eh_depth 값이 1 이상이라면 Internal nodes, 0이라면 Leaf nodes이다.

Header 

총 12 bytes로 구성되어 있다.

offset 이름 내용
0x00 ~ 0x01 eh_magic Magic number, 0xF30A
0x02 ~ 0x03 eh_entries Number of valid entries following the header.
0x04 ~ 0x05 eh_max Maximum number of entries that could follow the header.
0x06 ~0x07 eh_depth Depth of this extent node in the extent tree. 0 = this extent node points to data blocks; otherwise, this extent node points to other extent nodes. The extent tree can be at most 5 levels deep: a logical block number can be at most 2^32, and the smallest n that satisfies 4*(((blocksize - 12)/12)^n) >= 2^32 is 5.
0x08 ~ 0x0B eh_generation Generation of the tree. (Used by Lustre, but not standard ext4).

Internal nodes (Index nodes)

총 12 bytes로 구성되어 있다.

offset 이름 내용
0x00 ~ 0x03 ei_block This index node covers file blocks from 'block' onward.
0x04 ~ 0x07 ei_leaf_lo Lower 32-bits of the block number of the extent node that is the next level lower in the tree. The tree node pointed to can be either another internal node or a leaf node, described below.
0x08 ~ 0x09 ei_leaf_hi Upper 16-bits of the previous field.
0x0A ~ 0x0B ei_unused  

Leaf nodes

총 12 bytes로 구성되어 있다.

offset 이름 내용
0x00 ~ 0x03 ee_block First file block number that this extent covers.
0x04 ~ 0x05 ee_len Number of blocks covered by extent. If the value of this field is <= 32768, the extent is initialized. If the value of the field is > 32768, the extent is uninitialized and the actual extent length is ee_len - 32768. Therefore, the maximum length of a initialized extent is 32768 blocks, and the maximum length of an uninitialized extent is 32767.
0x06 ~ 0x07 ee_start_hi Upper 16-bits of the block number to which this extent points. (상위 16bit)
0x08 ~ 0x0B ee_start_lo Lower 32-bits of the block number to which this extent points. (하위 32 bit)

ext4_extent_tail

Extent Tree 블록의 무결성을 검증하기 위해 사용되는 데이터 구조로 CRC32C 체크섬을 사용하여 데이터를 보호하며, 총 4 bytes의 값을 갖는다. Extent Bock에만 존재하고 inode에 있는 4개의 Extent에는 이미 inode 자체로 체크섬 처리가 되어 있기 때문에 존재하지 않는다.

offset 이름 내용
0x00 ~ 0x03 eb_checksum Checksum of the extent block, crc32c(uuid+inum+igeneration+extentblock)

 

각 접근 방식의 자세한 설명과 비교하는 과정은 쉽지 않아보여서 여유가 생기면 진행해보려고 한다.

(사실 직접 블록의 12개의 의미도 정확히 파악하지 못했기 때문에 작성할 자신이 없다.)

https://roklcw.tistory.com/100

 

Block Mapping & Extent Tree (Ext Filesytem)

모두의 dream Block Mapping & Extent Tree (Ext Filesytem) 본문 분야/Digital Forensics Block Mapping & Extent Tree (Ext Filesytem) 오리꽥이로 2024. 5. 31. 15:03

roklcw.tistory.com

저널 (Journal)

https://roklcw.tistory.com/111

 

Ext4 Journal

모두의 dream Ext4 Journal 본문 카테고리 없음 Ext4 Journal 오리꽥이로 2024. 10. 7. 20:26

roklcw.tistory.com

IV. Ext4 파일 접근 & 삭제된 파일 복구

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

다음 포스팅에서 이 파일에 접근하는 과정에 대해 서술한다.

https://roklcw.tistory.com/66

 

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

모두의 dream Ext4 파일 데이터 접근 (with Directory Entry) 본문 분야/Digital Forensics Ext4 파일 데이터 접근 (with Directory Entry) 오리꽥이로 2023. 9. 15. 10:05

roklcw.tistory.com

 

삭제된 파일을 복구하는 과정은 다음 포스팅에서 서술한다.

https://roklcw.tistory.com/108

 

Ext4 삭제된 파일 복구

모두의 dream Ext4 삭제된 파일 복구 본문 분야/Digital Forensics Ext4 삭제된 파일 복구 오리꽥이로 2024. 9. 30. 11:15

roklcw.tistory.com

 

Reference

https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout

https://www.kernel.org/doc/html/latest/filesystems/ext4/

Ext4 기반 오픈 플랫폼 시스템의 디지털 포렌식 연구 (Digital Forensic Techniques for Ext4 based Open Platform Systems)

https://maj3sty.tistory.com/962

https://digitalforensicmaster.tistory.com/entry/Digital-Forensic-Android-Ext4-File-System-Recovery-Analysis-1